From f787d243f0a30461fb2b294bbb1b7da0aa4dfbcb Mon Sep 17 00:00:00 2001 From: Abdul Salam Date: Tue, 14 Mar 2023 23:00:29 +0530 Subject: [PATCH] clk: qcom: Add virtio-clk support Snapshot of virtio-clock driver from msm-5.15 branch at commit 2993484d0d65 ("drivers: virtio: Remove Backward compatibility of VIRTIO_ID's"). Change-Id: Icca58ce048eb93b57ee18394e9a67c663fe9ccfc Signed-off-by: Abdul Salam --- drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 2 + drivers/clk/qcom/virtio_clk.c | 695 +++++++++++++++++++++++++ drivers/clk/qcom/virtio_clk_common.h | 39 ++ drivers/clk/qcom/virtio_clk_direwolf.c | 289 ++++++++++ drivers/clk/qcom/virtio_clk_lemans.c | 154 ++++++ drivers/clk/qcom/virtio_clk_sa8195p.c | 145 ++++++ drivers/clk/qcom/virtio_clk_sm8150.c | 118 +++++ include/linux/virtio_clk.h | 52 ++ 9 files changed, 1503 insertions(+) create mode 100644 drivers/clk/qcom/virtio_clk.c create mode 100644 drivers/clk/qcom/virtio_clk_common.h create mode 100644 drivers/clk/qcom/virtio_clk_direwolf.c create mode 100644 drivers/clk/qcom/virtio_clk_lemans.c create mode 100644 drivers/clk/qcom/virtio_clk_sa8195p.c create mode 100644 drivers/clk/qcom/virtio_clk_sm8150.c create mode 100644 include/linux/virtio_clk.h diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 21c2f871cd94..fcc6d372e619 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -996,3 +996,12 @@ config SM_DEBUGCC_8150 clock measurement functionality. endif + +config VIRTIO_CLK + tristate "Virtio clock driver" + depends on VIRTIO + help + This is the virtual clock driver for virtio. It can be used on + Qualcomm Technologies, Inc automotive virtual machine. + Say Y if you want to use pass through peripheral devices such as UART, + SPI, I2C, USB etc. diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 6b52476525c1..db42a7b02f86 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -139,3 +139,5 @@ obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o obj-$(CONFIG_KRAITCC) += krait-cc.o +obj-$(CONFIG_VIRTIO_CLK) += virtio_clk.o virtio_clk_sm8150.o virtio_clk_direwolf.o \ + virtio_clk_sa8195p.o virtio_clk_lemans.o diff --git a/drivers/clk/qcom/virtio_clk.c b/drivers/clk/qcom/virtio_clk.c new file mode 100644 index 000000000000..63dd32a24ea4 --- /dev/null +++ b/drivers/clk/qcom/virtio_clk.c @@ -0,0 +1,695 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "virtio_clk_common.h" + +struct virtio_clk { + struct virtio_device *vdev; + struct virtqueue *vq; + struct completion rsp_avail; + struct mutex lock; + struct reset_controller_dev rcdev; + const struct clk_virtio_desc *desc; + struct clk_virtio *clks; + size_t num_clks; + size_t num_resets; +}; + +#define to_clk_virtio(_hw) container_of(_hw, struct clk_virtio, hw) + +struct clk_virtio { + int clk_id; + struct clk_hw hw; + struct virtio_clk *vclk; +}; + +struct virtio_cc_map { + char cc_name[20]; + const struct clk_virtio_desc *desc; +}; + +static int virtio_clk_prepare(struct clk_hw *hw) +{ + struct clk_virtio *v = to_clk_virtio(hw); + struct virtio_clk *vclk = v->vclk; + struct virtio_clk_msg *req, *rsp; + struct scatterlist sg[1]; + unsigned int len; + int ret = 0; + + pr_debug("%s\n", clk_hw_get_name(hw)); + + req = kzalloc(sizeof(struct virtio_clk_msg), GFP_KERNEL); + if (!req) + return -ENOMEM; + + strscpy(req->name, clk_hw_get_name(hw), sizeof(req->name)); + req->id = cpu_to_virtio32(vclk->vdev, v->clk_id); + req->type = cpu_to_virtio32(vclk->vdev, VIRTIO_CLK_T_ENABLE); + sg_init_one(sg, req, sizeof(*req)); + + mutex_lock(&vclk->lock); + + ret = virtqueue_add_outbuf(vclk->vq, sg, 1, req, GFP_KERNEL); + if (ret) { + pr_err("%s: fail to add output buffer (%d)\n", + clk_hw_get_name(hw), ret); + goto out; + } + + virtqueue_kick(vclk->vq); + + wait_for_completion(&vclk->rsp_avail); + + rsp = virtqueue_get_buf(vclk->vq, &len); + if (!rsp) { + pr_err("%s: fail to get virtqueue buffer\n", + clk_hw_get_name(hw)); + ret = -EIO; + goto out; + } + + ret = virtio32_to_cpu(vclk->vdev, rsp->result); +out: + mutex_unlock(&vclk->lock); + kfree(req); + + return ret; +} + +static void virtio_clk_unprepare(struct clk_hw *hw) +{ + struct clk_virtio *v = to_clk_virtio(hw); + struct virtio_clk *vclk = v->vclk; + struct virtio_clk_msg *req, *rsp; + struct scatterlist sg[1]; + unsigned int len; + int ret = 0; + + pr_debug("%s\n", clk_hw_get_name(hw)); + + req = kzalloc(sizeof(struct virtio_clk_msg), GFP_KERNEL); + if (!req) + return; + + strscpy(req->name, clk_hw_get_name(hw), sizeof(req->name)); + req->id = cpu_to_virtio32(vclk->vdev, v->clk_id); + req->type = cpu_to_virtio32(vclk->vdev, VIRTIO_CLK_T_DISABLE); + sg_init_one(sg, req, sizeof(*req)); + + mutex_lock(&vclk->lock); + + ret = virtqueue_add_outbuf(vclk->vq, sg, 1, req, GFP_KERNEL); + if (ret) { + pr_err("%s: fail to add output buffer (%d)\n", + clk_hw_get_name(hw), ret); + goto out; + } + + virtqueue_kick(vclk->vq); + + wait_for_completion(&vclk->rsp_avail); + + rsp = virtqueue_get_buf(vclk->vq, &len); + if (!rsp) { + pr_err("%s: fail to get virtqueue buffer\n", + clk_hw_get_name(hw)); + goto out; + } + + if (rsp->result) + pr_err("%s: error response (%d)\n", clk_hw_get_name(hw), + rsp->result); + +out: + mutex_unlock(&vclk->lock); + kfree(req); +} + +static int virtio_clk_set_rate(struct clk_hw *hw, + unsigned long rate, unsigned long parent_rate) +{ + struct clk_virtio *v = to_clk_virtio(hw); + struct virtio_clk *vclk = v->vclk; + struct virtio_clk_msg *req, *rsp; + struct scatterlist sg[1]; + unsigned int len; + int ret = 0; + + pr_debug("%s, rate: %lu, parent_rate: %lu\n", clk_hw_get_name(hw), + rate, parent_rate); + + req = kzalloc(sizeof(struct virtio_clk_msg), GFP_KERNEL); + if (!req) + return -ENOMEM; + + strscpy(req->name, clk_hw_get_name(hw), sizeof(req->name)); + req->id = cpu_to_virtio32(vclk->vdev, v->clk_id); + req->type = cpu_to_virtio32(vclk->vdev, VIRTIO_CLK_T_SET_RATE); + req->data[0] = cpu_to_virtio32(vclk->vdev, rate); + sg_init_one(sg, req, sizeof(*req)); + + mutex_lock(&vclk->lock); + + ret = virtqueue_add_outbuf(vclk->vq, sg, 1, req, GFP_KERNEL); + if (ret) { + pr_err("%s: fail to add output buffer (%d)\n", + clk_hw_get_name(hw), ret); + goto out; + } + + virtqueue_kick(vclk->vq); + + wait_for_completion(&vclk->rsp_avail); + + rsp = virtqueue_get_buf(vclk->vq, &len); + if (!rsp) { + pr_err("%s: fail to get virtqueue buffer\n", + clk_hw_get_name(hw)); + ret = -EIO; + goto out; + } + + ret = virtio32_to_cpu(vclk->vdev, rsp->result); +out: + mutex_unlock(&vclk->lock); + kfree(req); + + return ret; +} + +static long virtio_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct clk_virtio *v = to_clk_virtio(hw); + struct virtio_clk *vclk = v->vclk; + struct virtio_clk_msg *req, *rsp; + struct scatterlist sg[1]; + unsigned int len; + int ret = 0; + + pr_debug("%s, rate: %lu\n", clk_hw_get_name(hw), rate); + + req = kzalloc(sizeof(struct virtio_clk_msg), GFP_KERNEL); + if (!req) + return 0; + + strscpy(req->name, clk_hw_get_name(hw), sizeof(req->name)); + req->id = cpu_to_virtio32(vclk->vdev, v->clk_id); + req->type = cpu_to_virtio32(vclk->vdev, VIRTIO_CLK_T_ROUND_RATE); + req->data[0] = cpu_to_virtio32(vclk->vdev, rate); + sg_init_one(sg, req, sizeof(*req)); + + mutex_lock(&vclk->lock); + + ret = virtqueue_add_outbuf(vclk->vq, sg, 1, req, GFP_KERNEL); + if (ret) { + pr_err("%s: fail to add output buffer (%d)\n", + clk_hw_get_name(hw), ret); + goto out; + } + + virtqueue_kick(vclk->vq); + + wait_for_completion(&vclk->rsp_avail); + + rsp = virtqueue_get_buf(vclk->vq, &len); + if (!rsp) { + pr_err("%s: fail to get virtqueue buffer\n", + clk_hw_get_name(hw)); + ret = 0; + goto out; + } + + if (rsp->result) { + pr_err("%s: error response (%d)\n", clk_hw_get_name(hw), + rsp->result); + ret = 0; + } else + ret = virtio32_to_cpu(vclk->vdev, rsp->data[0]); + +out: + mutex_unlock(&vclk->lock); + kfree(req); + + return ret; +} + +static unsigned long virtio_clk_get_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_virtio *v = to_clk_virtio(hw); + struct virtio_clk *vclk = v->vclk; + struct virtio_clk_msg *req, *rsp; + struct scatterlist sg[1]; + unsigned int len; + int ret = 0; + + req = kzalloc(sizeof(struct virtio_clk_msg), GFP_KERNEL); + if (!req) + return 0; + + strscpy(req->name, clk_hw_get_name(hw), sizeof(req->name)); + req->id = cpu_to_virtio32(vclk->vdev, v->clk_id); + req->type = cpu_to_virtio32(vclk->vdev, VIRTIO_CLK_T_GET_RATE); + sg_init_one(sg, req, sizeof(*req)); + + mutex_lock(&vclk->lock); + + ret = virtqueue_add_outbuf(vclk->vq, sg, 1, req, GFP_KERNEL); + if (ret) { + pr_err("%s: fail to add output buffer (%d)\n", + clk_hw_get_name(hw), ret); + goto out; + } + + virtqueue_kick(vclk->vq); + + wait_for_completion(&vclk->rsp_avail); + + rsp = virtqueue_get_buf(vclk->vq, &len); + if (!rsp) { + pr_err("%s: fail to get virtqueue buffer\n", + clk_hw_get_name(hw)); + ret = 0; + goto out; + } + + if (rsp->result) { + /* + * Some clocks do not support getting rate. + * If getting clock rate is failing, return 0. + */ + pr_debug("%s: error response (%d)\n", clk_hw_get_name(hw), + rsp->result); + ret = 0; + } else + ret = virtio32_to_cpu(vclk->vdev, rsp->data[0]); + +out: + mutex_unlock(&vclk->lock); + kfree(req); + + return ret; +} + +static int virtio_clk_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_virtio *v = to_clk_virtio(hw); + struct virtio_clk *vclk = v->vclk; + struct virtio_clk_msg *req, *rsp; + struct scatterlist sg[1]; + unsigned int len; + int ret = 0; + + pr_debug("%s, parent index: %d\n", clk_hw_get_name(hw), index); + + req = kzalloc(sizeof(struct virtio_clk_msg), GFP_KERNEL); + if (!req) + return 0; + + strscpy(req->name, clk_hw_get_name(hw), sizeof(req->name)); + req->id = cpu_to_virtio32(vclk->vdev, v->clk_id); + req->type = cpu_to_virtio32(vclk->vdev, VIRTIO_CLK_T_SET_PARENT); + req->data[0] = cpu_to_virtio32(vclk->vdev, index); + sg_init_one(sg, req, sizeof(*req)); + + mutex_lock(&vclk->lock); + + ret = virtqueue_add_outbuf(vclk->vq, sg, 1, req, GFP_KERNEL); + if (ret) { + pr_err("%s: fail to add output buffer (%d)\n", + clk_hw_get_name(hw), ret); + goto out; + } + + virtqueue_kick(vclk->vq); + + wait_for_completion(&vclk->rsp_avail); + + rsp = virtqueue_get_buf(vclk->vq, &len); + if (!rsp) { + pr_err("%s: fail to get virtqueue buffer\n", + clk_hw_get_name(hw)); + ret = 0; + goto out; + } + + ret = virtio32_to_cpu(vclk->vdev, rsp->result); + +out: + mutex_unlock(&vclk->lock); + kfree(req); + + return ret; +} + +static u8 virtio_clk_get_parent(struct clk_hw *hw) +{ + return U8_MAX; +} + +static const struct clk_ops clk_virtio_ops = { + .prepare = virtio_clk_prepare, + .unprepare = virtio_clk_unprepare, + .set_rate = virtio_clk_set_rate, + .round_rate = virtio_clk_round_rate, + .recalc_rate = virtio_clk_get_rate, + .set_parent = virtio_clk_set_parent, + .get_parent = virtio_clk_get_parent, +}; + +static int +__virtio_reset(struct reset_controller_dev *rcdev, unsigned long id, + unsigned int action) +{ + struct virtio_clk *vclk = container_of(rcdev, struct virtio_clk, rcdev); + struct virtio_clk_msg *req, *rsp; + struct scatterlist sg[1]; + unsigned int len; + int ret = 0; + + pr_debug("%s, action: %d\n", vclk->desc->reset_names[id], action); + + req = kzalloc(sizeof(struct virtio_clk_msg), GFP_KERNEL); + if (!req) + return -ENOMEM; + + if (vclk->desc && vclk->desc->reset_names[id]) + strscpy(req->name, vclk->desc->reset_names[id], + sizeof(req->name)); + req->id = cpu_to_virtio32(vclk->vdev, id); + req->type = cpu_to_virtio32(vclk->vdev, VIRTIO_CLK_T_RESET); + req->data[0] = cpu_to_virtio32(vclk->vdev, action); + sg_init_one(sg, req, sizeof(*req)); + + mutex_lock(&vclk->lock); + + ret = virtqueue_add_outbuf(vclk->vq, sg, 1, req, GFP_KERNEL); + if (ret) { + pr_err("fail to add output buffer (%d)\n", ret); + goto out; + } + + virtqueue_kick(vclk->vq); + + wait_for_completion(&vclk->rsp_avail); + + rsp = virtqueue_get_buf(vclk->vq, &len); + if (!rsp) { + pr_err("fail to get virtqueue buffer\n"); + ret = -EIO; + goto out; + } + + ret = virtio32_to_cpu(vclk->vdev, rsp->result); + +out: + mutex_unlock(&vclk->lock); + kfree(req); + + return ret; +} + +static int +virtio_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) +{ + return __virtio_reset(rcdev, id, 1); +} + +static int +virtio_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) +{ + return __virtio_reset(rcdev, id, 0); +} + +static int +virtio_reset(struct reset_controller_dev *rcdev, unsigned long id) +{ + rcdev->ops->assert(rcdev, id); + udelay(1); + rcdev->ops->deassert(rcdev, id); + return 0; +} + +static const struct reset_control_ops virtio_reset_ops = { + .reset = virtio_reset, + .assert = virtio_reset_assert, + .deassert = virtio_reset_deassert, +}; + +static void virtclk_isr(struct virtqueue *vq) +{ + struct virtio_clk *vclk = vq->vdev->priv; + + complete(&vclk->rsp_avail); +} + +static int virtclk_init_vqs(struct virtio_clk *vclk) +{ + struct virtqueue *vqs[1]; + vq_callback_t *cbs[] = { virtclk_isr }; + static const char * const names[] = { "clock" }; + int ret; + + ret = virtio_find_vqs(vclk->vdev, 1, vqs, cbs, names, NULL); + if (ret) + return ret; + + vclk->vq = vqs[0]; + + return 0; +} + +static const struct virtio_cc_map clk_virtio_map_table[] = { + { .cc_name = "sm8150-gcc", .desc = &clk_virtio_sm8150_gcc, }, + { .cc_name = "sm8150-scc", .desc = &clk_virtio_sm8150_scc, }, + { .cc_name = "sa8195p-gcc", .desc = &clk_virtio_sa8195p_gcc, }, + { .cc_name = "direwolf-gcc", .desc = &clk_virtio_direwolf_gcc, }, + { .cc_name = "lemans-gcc", .desc = &clk_virtio_lemans_gcc, }, + { } +}; + +static const struct clk_virtio_desc *virtclk_find_desc( + const struct virtio_cc_map *maps, + const char *name) +{ + if (!maps) + return NULL; + + for (; maps->cc_name[0]; maps++) { + if (!strcmp(name, maps->cc_name)) + return maps->desc; + } + + return NULL; +} + +static struct clk_hw * +of_clk_hw_virtio_get(struct of_phandle_args *clkspec, void *data) +{ + struct virtio_clk *vclk = data; + unsigned int idx = clkspec->args[0]; + + if (idx >= vclk->num_clks) { + pr_err("%s: invalid index %u\n", __func__, idx); + return ERR_PTR(-EINVAL); + } + + return &vclk->clks[idx].hw; +} + +static int virtio_clk_probe(struct virtio_device *vdev) +{ + const struct clk_virtio_desc *desc = NULL; + struct virtio_clk *vclk; + struct virtio_clk_config config; + struct clk_virtio *virtio_clks; + char name[40]; + struct clk_init_data init; + static int instance; + unsigned int i; + int ret; + + if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) + return -ENODEV; + + vclk = devm_kzalloc(&vdev->dev, sizeof(*vclk), GFP_KERNEL); + if (!vclk) + return -ENOMEM; + + vdev->priv = vclk; + vclk->vdev = vdev; + mutex_init(&vclk->lock); + init_completion(&vclk->rsp_avail); + + ret = virtclk_init_vqs(vclk); + if (ret) { + dev_err(&vdev->dev, "failed to initialized virtqueue\n"); + return ret; + } + + virtio_device_ready(vdev); + + memset(&config, 0x0, sizeof(config)); + + virtio_cread(vdev, struct virtio_clk_config, num_clks, + &config.num_clks); + virtio_cread_feature(vdev, VIRTIO_CLK_F_RESET, struct virtio_clk_config, + num_resets, &config.num_resets); + + if (virtio_has_feature(vdev, VIRTIO_CLK_F_NAME)) { + virtio_cread_bytes(vdev, + offsetof(struct virtio_clk_config, name), + &config.name, sizeof(config.name)); + desc = virtclk_find_desc(clk_virtio_map_table, config.name); + if (!desc) { + ret = -ENXIO; + goto err_find_desc; + } + } + + dev_dbg(&vdev->dev, "num_clks=%d, num_resets=%d, name=%s\n", + config.num_clks, config.num_resets, config.name); + + if (desc) { + vclk->desc = desc; + vclk->num_clks = desc->num_clks; + if (desc->num_resets > 0) + vclk->num_resets = desc->num_resets; + } else { + vclk->num_clks = config.num_clks; + if (config.num_resets > 0) + vclk->num_resets = config.num_resets; + } + + virtio_clks = devm_kcalloc(&vdev->dev, vclk->num_clks, + sizeof(struct clk_virtio), GFP_KERNEL); + if (!virtio_clks) { + ret = -ENOMEM; + goto err_kcalloc; + } + + vclk->clks = virtio_clks; + + memset(&init, 0x0, sizeof(init)); + init.ops = &clk_virtio_ops; + + if (desc) { + for (i = 0; i < vclk->num_clks; i++) { + if (!desc->clks[i].name) + continue; + + virtio_clks[i].clk_id = i; + virtio_clks[i].vclk = vclk; + init.name = desc->clks[i].name; + init.parent_names = desc->clks[i].parent_names; + init.num_parents = desc->clks[i].num_parents; + virtio_clks[i].hw.init = &init; + ret = devm_clk_hw_register(&vdev->dev, + &virtio_clks[i].hw); + if (ret) { + dev_err(&vdev->dev, "fail to register clock\n"); + goto err_clk_register; + } + } + } else { + init.name = name; + + for (i = 0; i < config.num_clks; i++) { + virtio_clks[i].clk_id = i; + virtio_clks[i].vclk = vclk; + snprintf(name, sizeof(name), "virtio_%d_%d", + instance, i); + virtio_clks[i].hw.init = &init; + ret = devm_clk_hw_register(&vdev->dev, + &virtio_clks[i].hw); + if (ret) { + dev_err(&vdev->dev, "fail to register clock\n"); + goto err_clk_register; + } + } + } + + ret = devm_of_clk_add_hw_provider(vdev->dev.parent, + of_clk_hw_virtio_get, vclk); + if (ret) { + dev_err(&vdev->dev, "failed to add clock provider\n"); + goto err_clk_register; + } + + if (vclk->num_resets > 0) { + vclk->rcdev.of_node = vdev->dev.parent->of_node; + vclk->rcdev.ops = &virtio_reset_ops; + vclk->rcdev.owner = vdev->dev.driver->owner; + vclk->rcdev.nr_resets = vclk->num_resets; + ret = devm_reset_controller_register(&vdev->dev, &vclk->rcdev); + if (ret) + goto err_rst_register; + } + + instance++; + + dev_info(&vdev->dev, "Registered virtio clocks (%s)\n", config.name); + + return 0; + +err_rst_register: +err_clk_register: +err_kcalloc: +err_find_desc: + vdev->config->del_vqs(vdev); + return ret; +} + +static const struct virtio_device_id id_table[] = { + { VIRTIO_ID_CLOCK, VIRTIO_DEV_ANY_ID }, + { 0 }, +}; + +static unsigned int features[] = { + VIRTIO_CLK_F_RESET, + VIRTIO_CLK_F_NAME, +}; + +static struct virtio_driver virtio_clk_driver = { + .feature_table = features, + .feature_table_size = ARRAY_SIZE(features), + .driver.name = KBUILD_MODNAME, + .driver.owner = THIS_MODULE, + .id_table = id_table, + .probe = virtio_clk_probe, +}; + +static int __init virtio_clk_init(void) +{ + return register_virtio_driver(&virtio_clk_driver); +} + +static void __exit virtio_clk_fini(void) +{ + unregister_virtio_driver(&virtio_clk_driver); +} +subsys_initcall_sync(virtio_clk_init); +module_exit(virtio_clk_fini); + +MODULE_DEVICE_TABLE(virtio, id_table); +MODULE_DESCRIPTION("Virtio clock driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/virtio_clk_common.h b/drivers/clk/qcom/virtio_clk_common.h new file mode 100644 index 000000000000..4112fd66c63f --- /dev/null +++ b/drivers/clk/qcom/virtio_clk_common.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __VIRTIO_CLK_COMMON__ +#define __VIRTIO_CLK_COMMON__ + +#include + +/* + * + */ +struct virtio_clk_init_data { + const char *name; + const char * const *parent_names; + u8 num_parents; +}; + +/* + * struct clk_virtio_desc - virtio clock descriptor + * clk_names: the pointer of clock name pointer + * num_clks: number of clocks + * reset_names: the pointer of reset name pointer + * num_resets: number of resets + */ +struct clk_virtio_desc { + const struct virtio_clk_init_data *clks; + size_t num_clks; + const char * const *reset_names; + size_t num_resets; +}; + +extern const struct clk_virtio_desc clk_virtio_sm8150_gcc; +extern const struct clk_virtio_desc clk_virtio_sm8150_scc; +extern const struct clk_virtio_desc clk_virtio_sa8195p_gcc; +extern const struct clk_virtio_desc clk_virtio_direwolf_gcc; +extern const struct clk_virtio_desc clk_virtio_lemans_gcc; +#endif diff --git a/drivers/clk/qcom/virtio_clk_direwolf.c b/drivers/clk/qcom/virtio_clk_direwolf.c new file mode 100644 index 000000000000..a5ab87564d42 --- /dev/null +++ b/drivers/clk/qcom/virtio_clk_direwolf.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include "virtio_clk_common.h" + +static const char * const dirwolf_gcc_parent_names_0[] = { + "pcie_2a_pipe_clk", + "gcc_pcie_mbist_pll_test_se_clk_src", + "bi_tcxo", +}; + +static const char * const dirwolf_gcc_parent_names_1[] = { + "pcie_2b_pipe_clk", + "gcc_pcie_mbist_pll_test_se_clk_src", + "bi_tcxo", +}; + +static const char * const dirwolf_gcc_parent_names_2[] = { + "pcie_3a_pipe_clk", + "gcc_pcie_mbist_pll_test_se_clk_src", + "bi_tcxo", +}; + +static const char * const dirwolf_gcc_parent_names_3[] = { + "pcie_3b_pipe_clk", + "gcc_pcie_mbist_pll_test_se_clk_src", + "bi_tcxo", +}; + +static const char * const dirwolf_gcc_parent_names_4[] = { + "pcie_4_pipe_clk", + "gcc_pcie_mbist_pll_test_se_clk_src", + "bi_tcxo", +}; + +static const char * const dirwolf_gcc_parent_names_usb_prim[] = { + "usb3_phy_wrapper_gcc_usb30_pipe_clk", + "core_bi_pll_test_se", + "bi_tcxo", +}; + +static const char * const dirwolf_gcc_parent_names_usb_sec[] = { + "usb3_uni_phy_sec_gcc_usb30_pipe_clk", + "core_bi_pll_test_se", + "bi_tcxo", +}; + +static const char * const dirwolf_gcc_parent_names_usb_mp0[] = { + "usb3_uni_phy_mp_gcc_usb30_pipe_0_clk", + "core_bi_pll_test_se", + "bi_tcxo", +}; + +static const char * const dirwolf_gcc_parent_names_usb_mp1[] = { + "usb3_uni_phy_mp_gcc_usb30_pipe_1_clk", + "core_bi_pll_test_se", + "bi_tcxo", +}; + +static const struct virtio_clk_init_data direwolf_gcc_virtio_clocks[] = { + [GCC_QUPV3_WRAP0_S0_CLK] = {.name = "gcc_qupv3_wrap0_s0_clk",}, + [GCC_QUPV3_WRAP0_S1_CLK] = {.name = "gcc_qupv3_wrap0_s1_clk",}, + [GCC_QUPV3_WRAP0_S2_CLK] = {.name = "gcc_qupv3_wrap0_s2_clk",}, + [GCC_QUPV3_WRAP0_S3_CLK] = {.name = "gcc_qupv3_wrap0_s3_clk",}, + [GCC_QUPV3_WRAP0_S4_CLK] = {.name = "gcc_qupv3_wrap0_s4_clk",}, + [GCC_QUPV3_WRAP0_S5_CLK] = {.name = "gcc_qupv3_wrap0_s5_clk",}, + [GCC_QUPV3_WRAP0_S6_CLK] = {.name = "gcc_qupv3_wrap0_s6_clk",}, + [GCC_QUPV3_WRAP0_S7_CLK] = {.name = "gcc_qupv3_wrap0_s7_clk",}, + [GCC_QUPV3_WRAP1_S0_CLK] = {.name = "gcc_qupv3_wrap1_s0_clk",}, + [GCC_QUPV3_WRAP1_S1_CLK] = {.name = "gcc_qupv3_wrap1_s1_clk",}, + [GCC_QUPV3_WRAP1_S2_CLK] = {.name = "gcc_qupv3_wrap1_s2_clk",}, + [GCC_QUPV3_WRAP1_S3_CLK] = {.name = "gcc_qupv3_wrap1_s3_clk",}, + [GCC_QUPV3_WRAP1_S4_CLK] = {.name = "gcc_qupv3_wrap1_s4_clk",}, + [GCC_QUPV3_WRAP1_S5_CLK] = {.name = "gcc_qupv3_wrap1_s5_clk",}, + [GCC_QUPV3_WRAP1_S6_CLK] = {.name = "gcc_qupv3_wrap1_s6_clk",}, + [GCC_QUPV3_WRAP1_S7_CLK] = {.name = "gcc_qupv3_wrap1_s7_clk",}, + [GCC_QUPV3_WRAP2_S0_CLK] = {.name = "gcc_qupv3_wrap2_s0_clk",}, + [GCC_QUPV3_WRAP2_S1_CLK] = {.name = "gcc_qupv3_wrap2_s1_clk",}, + [GCC_QUPV3_WRAP2_S2_CLK] = {.name = "gcc_qupv3_wrap2_s2_clk",}, + [GCC_QUPV3_WRAP2_S3_CLK] = {.name = "gcc_qupv3_wrap2_s3_clk",}, + [GCC_QUPV3_WRAP2_S4_CLK] = {.name = "gcc_qupv3_wrap2_s4_clk",}, + [GCC_QUPV3_WRAP2_S5_CLK] = {.name = "gcc_qupv3_wrap2_s5_clk",}, + [GCC_QUPV3_WRAP2_S6_CLK] = {.name = "gcc_qupv3_wrap2_s6_clk",}, + [GCC_QUPV3_WRAP2_S7_CLK] = {.name = "gcc_qupv3_wrap2_s7_clk",}, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_0_m_ahb_clk",}, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_0_s_ahb_clk",}, + [GCC_QUPV3_WRAP_1_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_1_m_ahb_clk",}, + [GCC_QUPV3_WRAP_1_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_1_s_ahb_clk",}, + [GCC_QUPV3_WRAP_2_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_2_m_ahb_clk",}, + [GCC_QUPV3_WRAP_2_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_2_s_ahb_clk",}, + [GCC_USB30_PRIM_MASTER_CLK] = {.name = "gcc_usb30_prim_master_clk",}, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = {.name = "gcc_cfg_noc_usb3_prim_axi_clk",}, + [GCC_AGGRE_USB3_PRIM_AXI_CLK] = {.name = "gcc_aggre_usb3_prim_axi_clk",}, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = {.name = "gcc_usb30_prim_mock_utmi_clk",}, + [GCC_USB30_PRIM_SLEEP_CLK] = {.name = "gcc_usb30_prim_sleep_clk",}, + [GCC_USB3_PRIM_PHY_AUX_CLK] = {.name = "gcc_usb3_prim_phy_aux_clk",}, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = {.name = "gcc_usb3_prim_phy_pipe_clk",}, + [GCC_USB3_PRIM_PHY_PIPE_CLK_SRC] = { + .name = "gcc_usb3_prim_phy_pipe_clk_src", + .parent_names = dirwolf_gcc_parent_names_usb_prim, + .num_parents = ARRAY_SIZE(dirwolf_gcc_parent_names_usb_prim), + }, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = {.name = "gcc_usb3_prim_phy_com_aux_clk",}, + [GCC_USB4_EUD_CLKREF_CLK] = {.name = "gcc_usb4_eud_clkref_en",}, + [GCC_USB30_SEC_MASTER_CLK] = {.name = "gcc_usb30_sec_master_clk",}, + [GCC_CFG_NOC_USB3_SEC_AXI_CLK] = {.name = "gcc_cfg_noc_usb3_sec_axi_clk",}, + [GCC_AGGRE_USB3_SEC_AXI_CLK] = {.name = "gcc_aggre_usb3_sec_axi_clk",}, + [GCC_USB30_SEC_MOCK_UTMI_CLK] = {.name = "gcc_usb30_sec_mock_utmi_clk",}, + [GCC_USB30_SEC_SLEEP_CLK] = {.name = "gcc_usb30_sec_sleep_clk",}, + [GCC_USB3_SEC_PHY_AUX_CLK] = {.name = "gcc_usb3_sec_phy_aux_clk",}, + [GCC_USB3_SEC_PHY_PIPE_CLK] = {.name = "gcc_usb3_sec_phy_pipe_clk",}, + [GCC_USB3_SEC_PHY_PIPE_CLK_SRC] = { + .name = "gcc_usb3_sec_phy_pipe_clk_src", + .parent_names = dirwolf_gcc_parent_names_usb_sec, + .num_parents = ARRAY_SIZE(dirwolf_gcc_parent_names_usb_sec), + }, + [GCC_USB3_SEC_PHY_COM_AUX_CLK] = {.name = "gcc_usb3_sec_phy_com_aux_clk",}, + [GCC_USB4_CLKREF_CLK] = {.name = "gcc_usb4_clkref_en",}, + [GCC_USB30_MP_MASTER_CLK] = {.name = "gcc_usb30_mp_master_clk",}, + [GCC_CFG_NOC_USB3_MP_AXI_CLK] = {.name = "gcc_cfg_noc_usb3_mp_axi_clk",}, + [GCC_AGGRE_USB3_MP_AXI_CLK] = {.name = "gcc_aggre_usb3_mp_axi_clk",}, + [GCC_USB30_MP_MOCK_UTMI_CLK] = {.name = "gcc_usb30_mp_mock_utmi_clk",}, + [GCC_USB30_MP_SLEEP_CLK] = {.name = "gcc_usb30_mp_sleep_clk",}, + [GCC_AGGRE_USB_NOC_AXI_CLK] = {.name = "gcc_aggre_usb_noc_axi_clk",}, + [GCC_AGGRE_USB_NOC_NORTH_AXI_CLK] = {.name = "gcc_aggre_usb_noc_north_axi_clk",}, + [GCC_AGGRE_USB_NOC_SOUTH_AXI_CLK] = {.name = "gcc_aggre_usb_noc_south_axi_clk",}, + [GCC_SYS_NOC_USB_AXI_CLK] = {.name = "gcc_sys_noc_usb_axi_clk",}, + [GCC_USB2_HS0_CLKREF_CLK] = {.name = "gcc_usb2_hs0_clkref_en",}, + [GCC_USB2_HS1_CLKREF_CLK] = {.name = "gcc_usb2_hs1_clkref_en",}, + [GCC_USB2_HS2_CLKREF_CLK] = {.name = "gcc_usb2_hs2_clkref_en",}, + [GCC_USB2_HS3_CLKREF_CLK] = {.name = "gcc_usb2_hs3_clkref_en",}, + [GCC_USB3_MP_PHY_AUX_CLK] = {.name = "gcc_usb3_mp_phy_aux_clk",}, + [GCC_USB3_MP_PHY_PIPE_0_CLK] = {.name = "gcc_usb3_mp_phy_pipe_0_clk",}, + [GCC_USB3_MP_PHY_PIPE_0_CLK_SRC] = { + .name = "gcc_usb3_mp_phy_pipe_0_clk_src", + .parent_names = dirwolf_gcc_parent_names_usb_mp0, + .num_parents = ARRAY_SIZE(dirwolf_gcc_parent_names_usb_mp0), + }, + [GCC_USB3_MP0_CLKREF_CLK] = {.name = "gcc_usb3_mp0_clkref_en",}, + [GCC_USB3_MP_PHY_COM_AUX_CLK] = {.name = "gcc_usb3_mp_phy_com_aux_clk",}, + [GCC_USB3_MP_PHY_PIPE_1_CLK] = {.name = "gcc_usb3_mp_phy_pipe_1_clk",}, + [GCC_USB3_MP_PHY_PIPE_1_CLK_SRC] = { + .name = "gcc_usb3_mp_phy_pipe_1_clk_src", + .parent_names = dirwolf_gcc_parent_names_usb_mp1, + .num_parents = ARRAY_SIZE(dirwolf_gcc_parent_names_usb_mp1), + }, + [GCC_USB3_MP1_CLKREF_CLK] = {.name = "gcc_usb3_mp1_clkref_en",}, + [GCC_SDCC2_AHB_CLK] = {.name = "gcc_sdcc2_ahb_clk",}, + [GCC_SDCC2_APPS_CLK] = {.name = "gcc_sdcc2_apps_clk",}, + [GCC_PCIE_2A_PIPE_CLK] = { .name = "gcc_pcie_2a_pipe_clk",}, + [GCC_PCIE_2A_PIPE_CLK_SRC] = { + .name = "gcc_pcie_2a_pipe_clk_src", + .parent_names = dirwolf_gcc_parent_names_0, + .num_parents = ARRAY_SIZE(dirwolf_gcc_parent_names_0), + }, + [GCC_PCIE_2A_AUX_CLK] = {.name = "gcc_pcie_2a_aux_clk",}, + [GCC_PCIE_2A_CFG_AHB_CLK] = {.name = "gcc_pcie_2a_cfg_ahb_clk",}, + [GCC_PCIE_2A_MSTR_AXI_CLK] = {.name = "gcc_pcie_2a_mstr_axi_clk",}, + [GCC_PCIE_2A_SLV_AXI_CLK] = {.name = "gcc_pcie_2a_slv_axi_clk",}, + [GCC_PCIE_2A2B_CLKREF_CLK] = {.name = "gcc_pcie_2a2b_clkref_en",}, + [GCC_PCIE_2A_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_2a_slv_q2a_axi_clk",}, + [GCC_PCIE2A_PHY_RCHNG_CLK] = {.name = "gcc_pcie2a_phy_rchng_clk",}, + [GCC_PCIE_2A_PIPEDIV2_CLK] = {.name = "gcc_pcie_2a_pipediv2_clk",}, + [GCC_PCIE_2B_PIPE_CLK] = { .name = "gcc_pcie_2b_pipe_clk",}, + [GCC_PCIE_2B_PIPE_CLK_SRC] = { + .name = "gcc_pcie_2b_pipe_clk_src", + .parent_names = dirwolf_gcc_parent_names_1, + .num_parents = ARRAY_SIZE(dirwolf_gcc_parent_names_1), + }, + [GCC_PCIE_2B_AUX_CLK] = {.name = "gcc_pcie_2b_aux_clk",}, + [GCC_PCIE_2B_CFG_AHB_CLK] = {.name = "gcc_pcie_2b_cfg_ahb_clk",}, + [GCC_PCIE_2B_MSTR_AXI_CLK] = {.name = "gcc_pcie_2b_mstr_axi_clk",}, + [GCC_PCIE_2B_SLV_AXI_CLK] = {.name = "gcc_pcie_2b_slv_axi_clk",}, + [GCC_PCIE_2B_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_2b_slv_q2a_axi_clk",}, + [GCC_PCIE2B_PHY_RCHNG_CLK] = {.name = "gcc_pcie2b_phy_rchng_clk",}, + [GCC_PCIE_2B_PIPEDIV2_CLK] = {.name = "gcc_pcie_2b_pipediv2_clk",}, + [GCC_PCIE_3A_PIPE_CLK] = { .name = "gcc_pcie_3a_pipe_clk",}, + [GCC_PCIE_3A_PIPE_CLK_SRC] = { + .name = "gcc_pcie_3a_pipe_clk_src", + .parent_names = dirwolf_gcc_parent_names_2, + .num_parents = ARRAY_SIZE(dirwolf_gcc_parent_names_2), + }, + [GCC_PCIE_3A_AUX_CLK] = {.name = "gcc_pcie_3a_aux_clk",}, + [GCC_PCIE_3A_CFG_AHB_CLK] = {.name = "gcc_pcie_3a_cfg_ahb_clk",}, + [GCC_PCIE_3A_MSTR_AXI_CLK] = {.name = "gcc_pcie_3a_mstr_axi_clk",}, + [GCC_PCIE_3A3B_CLKREF_CLK] = {.name = "gcc_pcie_3a3b_clkref_en",}, + [GCC_PCIE_3A_SLV_AXI_CLK] = {.name = "gcc_pcie_3a_slv_axi_clk",}, + [GCC_PCIE_3A_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_3a_slv_q2a_axi_clk",}, + [GCC_PCIE3A_PHY_RCHNG_CLK] = {.name = "gcc_pcie3a_phy_rchng_clk",}, + [GCC_PCIE_3A_PIPEDIV2_CLK] = {.name = "gcc_pcie_3a_pipediv2_clk",}, + [GCC_PCIE_3B_PIPE_CLK] = { .name = "gcc_pcie_3b_pipe_clk",}, + [GCC_PCIE_3B_PIPE_CLK_SRC] = { + .name = "gcc_pcie_3b_pipe_clk_src", + .parent_names = dirwolf_gcc_parent_names_3, + .num_parents = ARRAY_SIZE(dirwolf_gcc_parent_names_3), + }, + [GCC_PCIE_3B_AUX_CLK] = {.name = "gcc_pcie_3b_aux_clk",}, + [GCC_PCIE_3B_CFG_AHB_CLK] = {.name = "gcc_pcie_3b_cfg_ahb_clk",}, + [GCC_PCIE_3B_MSTR_AXI_CLK] = {.name = "gcc_pcie_3b_mstr_axi_clk",}, + [GCC_PCIE_3B_SLV_AXI_CLK] = {.name = "gcc_pcie_3b_slv_axi_clk",}, + [GCC_PCIE_3B_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_3b_slv_q2a_axi_clk",}, + [GCC_PCIE3B_PHY_RCHNG_CLK] = {.name = "gcc_pcie3b_phy_rchng_clk",}, + [GCC_PCIE_3B_PIPEDIV2_CLK] = {.name = "gcc_pcie_3b_pipediv2_clk",}, + [GCC_PCIE_4_PIPE_CLK] = {.name = "gcc_pcie_4_pipe_clk",}, + [GCC_PCIE_4_PIPE_CLK_SRC] = { + .name = "gcc_pcie_4_pipe_clk_src", + .parent_names = dirwolf_gcc_parent_names_4, + .num_parents = ARRAY_SIZE(dirwolf_gcc_parent_names_4), + }, + [GCC_PCIE_4_AUX_CLK] = {.name = "gcc_pcie_4_aux_clk",}, + [GCC_PCIE_4_CFG_AHB_CLK] = {.name = "gcc_pcie_4_cfg_ahb_clk",}, + [GCC_PCIE_4_MSTR_AXI_CLK] = {.name = "gcc_pcie_4_mstr_axi_clk",}, + [GCC_PCIE_4_SLV_AXI_CLK] = {.name = "gcc_pcie_4_slv_axi_clk",}, + [GCC_PCIE_4_CLKREF_CLK] = {.name = "gcc_pcie_4_clkref_en",}, + [GCC_PCIE_4_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_4_slv_q2a_axi_clk",}, + [GCC_PCIE4_PHY_RCHNG_CLK] = {.name = "gcc_pcie4_phy_rchng_clk",}, + [GCC_DDRSS_PCIE_SF_TBU_CLK] = {.name = "gcc_ddrss_pcie_sf_tbu_clk",}, + [GCC_AGGRE_NOC_PCIE_4_AXI_CLK] = {.name = "gcc_aggre_noc_pcie_4_axi_clk",}, + [GCC_AGGRE_NOC_PCIE_SOUTH_SF_AXI_CLK] = {.name = "gcc_aggre_noc_pcie_south_sf_axi_clk",}, + [GCC_CNOC_PCIE4_QX_CLK] = {.name = "gcc_cnoc_pcie4_qx_clk",}, + [GCC_PCIE_4_PIPEDIV2_CLK] = {.name = "gcc_pcie_4_pipediv2_clk",}, + [GCC_UFS_1_CARD_CLKREF_CLK] = {.name = "gcc_ufs_1_card_clkref_en",}, + [GCC_UFS_CARD_PHY_AUX_CLK] = {.name = "gcc_ufs_card_phy_aux_clk",}, + [GCC_UFS_REF_CLKREF_CLK] = {.name = "gcc_ufs_ref_clkref_en",}, + [GCC_UFS_CARD_AXI_CLK] = {.name = "gcc_ufs_card_axi_clk",}, + [GCC_AGGRE_UFS_CARD_AXI_CLK] = {.name = "gcc_aggre_ufs_card_axi_clk",}, + [GCC_UFS_CARD_AHB_CLK] = {.name = "gcc_ufs_card_ahb_clk",}, + [GCC_UFS_CARD_UNIPRO_CORE_CLK] = {.name = "gcc_ufs_card_unipro_core_clk",}, + [GCC_UFS_CARD_ICE_CORE_CLK] = {.name = "gcc_ufs_card_ice_core_clk",}, + [GCC_UFS_CARD_TX_SYMBOL_0_CLK] = {.name = "gcc_ufs_card_tx_symbol_0_clk",}, + [GCC_UFS_CARD_RX_SYMBOL_0_CLK] = {.name = "gcc_ufs_card_rx_symbol_0_clk",}, + [GCC_UFS_CARD_RX_SYMBOL_1_CLK] = {.name = "gcc_ufs_card_rx_symbol_1_clk",}, + [GCC_EMAC1_AXI_CLK] = {.name = "gcc_emac1_axi_clk",}, + [GCC_EMAC1_SLV_AHB_CLK] = {.name = "gcc_emac1_slv_ahb_clk",}, + [GCC_EMAC1_PTP_CLK] = {.name = "gcc_emac1_ptp_clk",}, + [GCC_EMAC1_RGMII_CLK] = {.name = "gcc_emac1_rgmii_clk",}, +}; + +static const char * const direwolf_gcc_virtio_resets[] = { + [GCC_QUSB2PHY_PRIM_BCR] = "gcc_qusb2phy_prim_bcr", + [GCC_QUSB2PHY_SEC_BCR] = "gcc_qusb2phy_sec_bcr", + [GCC_USB2_PHY_SEC_BCR] = "gcc_usb2_phy_sec_bcr", + [GCC_USB30_PRIM_BCR] = "gcc_usb30_prim_master_clk", + [GCC_USB30_SEC_BCR] = "gcc_usb30_sec_master_clk", + [GCC_USB30_MP_BCR] = "gcc_usb30_mp_master_clk", + [GCC_QUSB2PHY_HS0_MP_BCR] = "gcc_qusb2phy_hs0_mp_bcr", + [GCC_QUSB2PHY_HS1_MP_BCR] = "gcc_qusb2phy_hs1_mp_bcr", + [GCC_QUSB2PHY_HS2_MP_BCR] = "gcc_qusb2phy_hs2_mp_bcr", + [GCC_QUSB2PHY_HS3_MP_BCR] = "gcc_qusb2phy_hs3_mp_bcr", + [GCC_USB4_DP_PHY_PRIM_BCR] = "gcc_usb4_dp_phy_prim_bcr", + [GCC_USB3_PHY_PRIM_BCR] = "gcc_usb3_phy_prim_bcr", + [GCC_USB4_1_DP_PHY_PRIM_BCR] = "gcc_usb4_1_dp_phy_prim_bcr", + [GCC_USB3_PHY_SEC_BCR] = "gcc_usb3_phy_sec_bcr", + [GCC_USB3_UNIPHY_MP0_BCR] = "gcc_usb3_uniphy_mp0_bcr", + [GCC_USB3UNIPHY_PHY_MP0_BCR] = "gcc_usb3uniphy_phy_mp0_bcr", + [GCC_USB3_UNIPHY_MP1_BCR] = "gcc_usb3_uniphy_mp1_bcr", + [GCC_USB3UNIPHY_PHY_MP1_BCR] = "gcc_usb3uniphy_phy_mp1_bcr", + [GCC_PCIE_2A_BCR] = "gcc_pcie_2a_bcr", + [GCC_PCIE_2A_PHY_BCR] = "gcc_pcie_2a_phy_bcr", + [GCC_PCIE_2A_PHY_NOCSR_COM_PHY_BCR] = "gcc_pcie_2a_phy_nocsr_com_phy_bcr", + [GCC_PCIE_2B_BCR] = "gcc_pcie_2b_bcr", + [GCC_PCIE_2B_PHY_BCR] = "gcc_pcie_2b_phy_bcr", + [GCC_PCIE_2B_PHY_NOCSR_COM_PHY_BCR] = "gcc_pcie_2b_phy_nocsr_com_phy_bcr", + [GCC_PCIE_3A_BCR] = "gcc_pcie_3a_bcr", + [GCC_PCIE_3A_PHY_BCR] = "gcc_pcie_3a_phy_bcr", + [GCC_PCIE_3A_PHY_NOCSR_COM_PHY_BCR] = "gcc_pcie_3a_phy_nocsr_com_phy_bcr", + [GCC_PCIE_3B_BCR] = "gcc_pcie_3b_bcr", + [GCC_PCIE_3B_PHY_BCR] = "gcc_pcie_3b_phy_bcr", + [GCC_PCIE_3B_PHY_NOCSR_COM_PHY_BCR] = "gcc_pcie_3b_phy_nocsr_com_phy_bcr", + [GCC_PCIE_4_BCR] = "gcc_pcie_4_bcr", + [GCC_PCIE_4_PHY_BCR] = "gcc_pcie_4_phy_bcr", + [GCC_PCIE_4_PHY_NOCSR_COM_PHY_BCR] = "gcc_pcie_4_phy_nocsr_com_phy_bcr", + [GCC_UFS_CARD_BCR] = "gcc_ufs_card_bcr", +}; + +const struct clk_virtio_desc clk_virtio_direwolf_gcc = { + .clks = direwolf_gcc_virtio_clocks, + .num_clks = ARRAY_SIZE(direwolf_gcc_virtio_clocks), + .reset_names = direwolf_gcc_virtio_resets, + .num_resets = ARRAY_SIZE(direwolf_gcc_virtio_resets), +}; +EXPORT_SYMBOL(clk_virtio_direwolf_gcc); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/virtio_clk_lemans.c b/drivers/clk/qcom/virtio_clk_lemans.c new file mode 100644 index 000000000000..ff552257ce40 --- /dev/null +++ b/drivers/clk/qcom/virtio_clk_lemans.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include "virtio_clk_common.h" + +static const char * const lemans_gcc_parent_names_usb_prim[] = { + "usb3_phy_wrapper_gcc_usb30_pipe_clk", + "core_bi_pll_test_se", + "bi_tcxo", +}; + +static const char * const lemans_gcc_parent_names_usb_sec[] = { + "usb3_uni_phy_sec_gcc_usb30_pipe_clk", + "core_bi_pll_test_se", + "bi_tcxo", +}; + +static const char * const lemans_gcc_parent_names_pcie_0[] = { + "pcie_0_pipe_clk", + "gcc_pcie_mbist_pll_test_se_clk_src", + "bi_tcxo", +}; + +static const char * const lemans_gcc_parent_names_pcie_1[] = { + "pcie_1_pipe_clk", + "gcc_pcie_mbist_pll_test_se_clk_src", + "bi_tcxo", +}; + +static const struct virtio_clk_init_data lemans_gcc_virtio_clocks[] = { + [GCC_QUPV3_WRAP0_S0_CLK] = {.name = "gcc_qupv3_wrap0_s0_clk",}, + [GCC_QUPV3_WRAP0_S1_CLK] = {.name = "gcc_qupv3_wrap0_s1_clk",}, + [GCC_QUPV3_WRAP0_S2_CLK] = {.name = "gcc_qupv3_wrap0_s2_clk",}, + [GCC_QUPV3_WRAP0_S3_CLK] = {.name = "gcc_qupv3_wrap0_s3_clk",}, + [GCC_QUPV3_WRAP0_S4_CLK] = {.name = "gcc_qupv3_wrap0_s4_clk",}, + [GCC_QUPV3_WRAP0_S5_CLK] = {.name = "gcc_qupv3_wrap0_s5_clk",}, + [GCC_QUPV3_WRAP0_S6_CLK] = {.name = "gcc_qupv3_wrap0_s6_clk",}, + [GCC_QUPV3_WRAP1_S0_CLK] = {.name = "gcc_qupv3_wrap1_s0_clk",}, + [GCC_QUPV3_WRAP1_S1_CLK] = {.name = "gcc_qupv3_wrap1_s1_clk",}, + [GCC_QUPV3_WRAP1_S2_CLK] = {.name = "gcc_qupv3_wrap1_s2_clk",}, + [GCC_QUPV3_WRAP1_S3_CLK] = {.name = "gcc_qupv3_wrap1_s3_clk",}, + [GCC_QUPV3_WRAP1_S4_CLK] = {.name = "gcc_qupv3_wrap1_s4_clk",}, + [GCC_QUPV3_WRAP1_S5_CLK] = {.name = "gcc_qupv3_wrap1_s5_clk",}, + [GCC_QUPV3_WRAP1_S6_CLK] = {.name = "gcc_qupv3_wrap1_s6_clk",}, + [GCC_QUPV3_WRAP2_S0_CLK] = {.name = "gcc_qupv3_wrap2_s0_clk",}, + [GCC_QUPV3_WRAP2_S1_CLK] = {.name = "gcc_qupv3_wrap2_s1_clk",}, + [GCC_QUPV3_WRAP2_S2_CLK] = {.name = "gcc_qupv3_wrap2_s2_clk",}, + [GCC_QUPV3_WRAP2_S3_CLK] = {.name = "gcc_qupv3_wrap2_s3_clk",}, + [GCC_QUPV3_WRAP2_S4_CLK] = {.name = "gcc_qupv3_wrap2_s4_clk",}, + [GCC_QUPV3_WRAP2_S5_CLK] = {.name = "gcc_qupv3_wrap2_s5_clk",}, + [GCC_QUPV3_WRAP2_S6_CLK] = {.name = "gcc_qupv3_wrap2_s6_clk",}, + [GCC_QUPV3_WRAP3_S0_CLK] = {.name = "gcc_qupv3_wrap3_s0_clk",}, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_0_m_ahb_clk",}, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_0_s_ahb_clk",}, + [GCC_QUPV3_WRAP_1_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_1_m_ahb_clk",}, + [GCC_QUPV3_WRAP_1_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_1_s_ahb_clk",}, + [GCC_QUPV3_WRAP_2_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_2_m_ahb_clk",}, + [GCC_QUPV3_WRAP_2_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_2_s_ahb_clk",}, + [GCC_QUPV3_WRAP_3_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_3_m_ahb_clk",}, + [GCC_QUPV3_WRAP_3_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_3_s_ahb_clk",}, + [GCC_USB30_PRIM_MASTER_CLK] = {.name = "gcc_usb30_prim_master_clk",}, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = {.name = "gcc_cfg_noc_usb3_prim_axi_clk",}, + [GCC_AGGRE_USB3_PRIM_AXI_CLK] = {.name = "gcc_aggre_usb3_prim_axi_clk",}, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = {.name = "gcc_usb30_prim_mock_utmi_clk",}, + [GCC_USB30_PRIM_SLEEP_CLK] = {.name = "gcc_usb30_prim_sleep_clk",}, + [GCC_USB3_PRIM_PHY_AUX_CLK] = {.name = "gcc_usb3_prim_phy_aux_clk",}, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = {.name = "gcc_usb3_prim_phy_pipe_clk",}, + [GCC_USB3_PRIM_PHY_PIPE_CLK_SRC] = { + .name = "gcc_usb3_prim_phy_pipe_clk_src", + .parent_names = lemans_gcc_parent_names_usb_prim, + .num_parents = ARRAY_SIZE(lemans_gcc_parent_names_usb_prim), + }, + [GCC_USB_CLKREF_EN] = {.name = "gcc_usb_clkref_en",}, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = {.name = "gcc_usb3_prim_phy_com_aux_clk",}, + [GCC_USB30_SEC_MASTER_CLK] = {.name = "gcc_usb30_sec_master_clk",}, + [GCC_CFG_NOC_USB3_SEC_AXI_CLK] = {.name = "gcc_cfg_noc_usb3_sec_axi_clk",}, + [GCC_AGGRE_USB3_SEC_AXI_CLK] = {.name = "gcc_aggre_usb3_sec_axi_clk",}, + [GCC_USB30_SEC_MOCK_UTMI_CLK] = {.name = "gcc_usb30_sec_mock_utmi_clk",}, + [GCC_USB30_SEC_SLEEP_CLK] = {.name = "gcc_usb30_sec_sleep_clk",}, + [GCC_USB3_SEC_PHY_AUX_CLK] = {.name = "gcc_usb3_sec_phy_aux_clk",}, + [GCC_USB3_SEC_PHY_PIPE_CLK] = {.name = "gcc_usb3_sec_phy_pipe_clk",}, + [GCC_USB3_SEC_PHY_PIPE_CLK_SRC] = { + .name = "gcc_usb3_sec_phy_pipe_clk_src", + .parent_names = lemans_gcc_parent_names_usb_sec, + .num_parents = ARRAY_SIZE(lemans_gcc_parent_names_usb_sec), + }, + [GCC_USB3_SEC_PHY_COM_AUX_CLK] = {.name = "gcc_usb3_sec_phy_com_aux_clk",}, + [GCC_USB20_MASTER_CLK] = {.name = "gcc_usb20_master_clk",}, + [GCC_CFG_NOC_USB2_PRIM_AXI_CLK] = {.name = "gcc_cfg_noc_usb2_prim_axi_clk",}, + [GCC_AGGRE_USB2_PRIM_AXI_CLK] = {.name = "gcc_aggre_usb2_prim_axi_clk",}, + [GCC_USB20_MOCK_UTMI_CLK] = {.name = "gcc_usb20_mock_utmi_clk",}, + [GCC_USB20_SLEEP_CLK] = {.name = "gcc_usb20_sleep_clk",}, + [GCC_PCIE_0_PIPE_CLK] = {.name = "gcc_pcie_0_pipe_clk",}, + [GCC_PCIE_0_AUX_CLK] = {.name = "gcc_pcie_0_aux_clk",}, + [GCC_PCIE_0_CFG_AHB_CLK] = {.name = "gcc_pcie_0_cfg_ahb_clk",}, + [GCC_PCIE_0_MSTR_AXI_CLK] = {.name = "gcc_pcie_0_mstr_axi_clk",}, + [GCC_PCIE_0_SLV_AXI_CLK] = {.name = "gcc_pcie_0_slv_axi_clk",}, + [GCC_PCIE_CLKREF_EN] = {.name = "gcc_pcie_clkref_en",}, + [GCC_PCIE_0_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_0_slv_q2a_axi_clk",}, + [GCC_PCIE_0_PHY_RCHNG_CLK] = {.name = "gcc_pcie_0_phy_rchng_clk",}, + [GCC_PCIE_0_PHY_AUX_CLK] = {.name = "gcc_pcie_0_phy_aux_clk",}, + [GCC_PCIE_0_PIPEDIV2_CLK] = {.name = "gcc_pcie_0_pipediv2_clk",}, + [GCC_PCIE_0_PIPE_CLK_SRC] = { + .name = "gcc_pcie_0_pipe_clk_src", + .parent_names = lemans_gcc_parent_names_pcie_0, + .num_parents = ARRAY_SIZE(lemans_gcc_parent_names_pcie_0), + }, + [GCC_PCIE_1_PIPE_CLK] = {.name = "gcc_pcie_1_pipe_clk",}, + [GCC_PCIE_1_AUX_CLK] = {.name = "gcc_pcie_1_aux_clk",}, + [GCC_PCIE_1_CFG_AHB_CLK] = {.name = "gcc_pcie_1_cfg_ahb_clk",}, + [GCC_PCIE_1_MSTR_AXI_CLK] = {.name = "gcc_pcie_1_mstr_axi_clk",}, + [GCC_PCIE_1_SLV_AXI_CLK] = {.name = "gcc_pcie_1_slv_axi_clk",}, + [GCC_PCIE_1_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_1_slv_q2a_axi_clk",}, + [GCC_PCIE_1_PHY_RCHNG_CLK] = {.name = "gcc_pcie_1_phy_rchng_clk",}, + [GCC_PCIE_1_PHY_AUX_CLK] = {.name = "gcc_pcie_1_phy_aux_clk",}, + [GCC_PCIE_1_PIPEDIV2_CLK] = {.name = "gcc_pcie_1_pipediv2_clk",}, + [GCC_PCIE_1_PIPE_CLK_SRC] = { + .name = "gcc_pcie_1_pipe_clk_src", + .parent_names = lemans_gcc_parent_names_pcie_1, + .num_parents = ARRAY_SIZE(lemans_gcc_parent_names_pcie_1), + }, +}; + +static const char * const lemans_gcc_virtio_resets[] = { + [GCC_USB30_PRIM_BCR] = "gcc_usb30_prim_master_clk", + [GCC_USB2_PHY_PRIM_BCR] = "gcc_usb2_phy_prim_bcr", + [GCC_USB3_PHY_PRIM_BCR] = "gcc_usb3_phy_prim_bcr", + [GCC_USB3PHY_PHY_PRIM_BCR] = "gcc_usb3phy_phy_prim_bcr", + [GCC_USB30_SEC_BCR] = "gcc_usb30_sec_master_clk", + [GCC_USB2_PHY_SEC_BCR] = "gcc_usb2_phy_sec_bcr", + [GCC_USB3_PHY_SEC_BCR] = "gcc_usb3_phy_sec_bcr", + [GCC_USB3PHY_PHY_SEC_BCR] = "gcc_usb3phy_phy_sec_bcr", + [GCC_USB3_PHY_TERT_BCR] = "gcc_usb3_tert_bcr", + [GCC_USB20_PRIM_BCR] = "gcc_usb20_master_clk", + [GCC_PCIE_0_BCR] = "gcc_pcie_0_bcr", + [GCC_PCIE_0_PHY_BCR] = "gcc_pcie_0_phy_bcr", + [GCC_PCIE_1_BCR] = "gcc_pcie_1_bcr", + [GCC_PCIE_1_PHY_BCR] = "gcc_pcie_1_phy_bcr", +}; + +const struct clk_virtio_desc clk_virtio_lemans_gcc = { + .clks = lemans_gcc_virtio_clocks, + .num_clks = ARRAY_SIZE(lemans_gcc_virtio_clocks), + .reset_names = lemans_gcc_virtio_resets, + .num_resets = ARRAY_SIZE(lemans_gcc_virtio_resets), +}; +EXPORT_SYMBOL(clk_virtio_lemans_gcc); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/virtio_clk_sa8195p.c b/drivers/clk/qcom/virtio_clk_sa8195p.c new file mode 100644 index 000000000000..bdaf1a9fb3be --- /dev/null +++ b/drivers/clk/qcom/virtio_clk_sa8195p.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.. + */ + +#include +#include +#include +#include "virtio_clk_common.h" + +static const struct virtio_clk_init_data sa8195p_gcc_virtio_clocks[] = { + [GCC_QUPV3_WRAP0_S0_CLK] = {.name = "gcc_qupv3_wrap0_s0_clk",}, + [GCC_QUPV3_WRAP0_S1_CLK] = {.name = "gcc_qupv3_wrap0_s1_clk",}, + [GCC_QUPV3_WRAP0_S2_CLK] = {.name = "gcc_qupv3_wrap0_s2_clk",}, + [GCC_QUPV3_WRAP0_S3_CLK] = {.name = "gcc_qupv3_wrap0_s3_clk",}, + [GCC_QUPV3_WRAP0_S4_CLK] = {.name = "gcc_qupv3_wrap0_s4_clk",}, + [GCC_QUPV3_WRAP0_S5_CLK] = {.name = "gcc_qupv3_wrap0_s5_clk",}, + [GCC_QUPV3_WRAP0_S6_CLK] = {.name = "gcc_qupv3_wrap0_s6_clk",}, + [GCC_QUPV3_WRAP0_S7_CLK] = {.name = "gcc_qupv3_wrap0_s7_clk",}, + [GCC_QUPV3_WRAP1_S0_CLK] = {.name = "gcc_qupv3_wrap1_s0_clk",}, + [GCC_QUPV3_WRAP1_S1_CLK] = {.name = "gcc_qupv3_wrap1_s1_clk",}, + [GCC_QUPV3_WRAP1_S2_CLK] = {.name = "gcc_qupv3_wrap1_s2_clk",}, + [GCC_QUPV3_WRAP1_S3_CLK] = {.name = "gcc_qupv3_wrap1_s3_clk",}, + [GCC_QUPV3_WRAP1_S4_CLK] = {.name = "gcc_qupv3_wrap1_s4_clk",}, + [GCC_QUPV3_WRAP1_S5_CLK] = {.name = "gcc_qupv3_wrap1_s5_clk",}, + [GCC_QUPV3_WRAP2_S0_CLK] = {.name = "gcc_qupv3_wrap2_s0_clk",}, + [GCC_QUPV3_WRAP2_S1_CLK] = {.name = "gcc_qupv3_wrap2_s1_clk",}, + [GCC_QUPV3_WRAP2_S2_CLK] = {.name = "gcc_qupv3_wrap2_s2_clk",}, + [GCC_QUPV3_WRAP2_S3_CLK] = {.name = "gcc_qupv3_wrap2_s3_clk",}, + [GCC_QUPV3_WRAP2_S4_CLK] = {.name = "gcc_qupv3_wrap2_s4_clk",}, + [GCC_QUPV3_WRAP2_S5_CLK] = {.name = "gcc_qupv3_wrap2_s5_clk",}, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_0_m_ahb_clk",}, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_0_s_ahb_clk",}, + [GCC_QUPV3_WRAP_1_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_1_m_ahb_clk",}, + [GCC_QUPV3_WRAP_1_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_1_s_ahb_clk",}, + [GCC_QUPV3_WRAP_2_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_2_m_ahb_clk",}, + [GCC_QUPV3_WRAP_2_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_2_s_ahb_clk",}, + [GCC_USB30_PRIM_MASTER_CLK] = {.name = "gcc_usb30_prim_master_clk",}, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = {.name = "gcc_cfg_noc_usb3_prim_axi_clk",}, + [GCC_AGGRE_USB3_PRIM_AXI_CLK] = {.name = "gcc_aggre_usb3_prim_axi_clk",}, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = {.name = "gcc_usb30_prim_mock_utmi_clk",}, + [GCC_USB30_PRIM_SLEEP_CLK] = {.name = "gcc_usb30_prim_sleep_clk",}, + [GCC_USB3_PRIM_PHY_AUX_CLK] = {.name = "gcc_usb3_prim_phy_aux_clk",}, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = {.name = "gcc_usb3_prim_phy_pipe_clk",}, + [GCC_USB3_PRIM_CLKREF_CLK] = {.name = "gcc_usb3_prim_clkref_en",}, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = {.name = "gcc_usb3_prim_phy_com_aux_clk",}, + [GCC_USB30_SEC_MASTER_CLK] = {.name = "gcc_usb30_sec_master_clk",}, + [GCC_CFG_NOC_USB3_SEC_AXI_CLK] = {.name = "gcc_cfg_noc_usb3_sec_axi_clk",}, + [GCC_AGGRE_USB3_SEC_AXI_CLK] = {.name = "gcc_aggre_usb3_sec_axi_clk",}, + [GCC_USB30_SEC_MOCK_UTMI_CLK] = {.name = "gcc_usb30_sec_mock_utmi_clk",}, + [GCC_USB30_SEC_SLEEP_CLK] = {.name = "gcc_usb30_sec_sleep_clk",}, + [GCC_USB3_SEC_PHY_AUX_CLK] = {.name = "gcc_usb3_sec_phy_aux_clk",}, + [GCC_USB3_SEC_PHY_PIPE_CLK] = {.name = "gcc_usb3_sec_phy_pipe_clk",}, + [GCC_USB3_SEC_CLKREF_CLK] = {.name = "gcc_usb3_sec_clkref_en",}, + [GCC_USB3_SEC_PHY_COM_AUX_CLK] = {.name = "gcc_usb3_sec_phy_com_aux_clk",}, + [GCC_USB30_MP_MASTER_CLK] = {.name = "gcc_usb30_mp_master_clk",}, + [GCC_CFG_NOC_USB3_MP_AXI_CLK] = {.name = "gcc_cfg_noc_usb3_mp_axi_clk",}, + [GCC_AGGRE_USB3_MP_AXI_CLK] = {.name = "gcc_aggre_usb3_mp_axi_clk",}, + [GCC_USB30_MP_MOCK_UTMI_CLK] = {.name = "gcc_usb30_mp_mock_utmi_clk",}, + [GCC_USB30_MP_SLEEP_CLK] = {.name = "gcc_usb30_mp_sleep_clk",}, + [GCC_USB3_MP_PHY_AUX_CLK] = {.name = "gcc_usb3_mp_phy_aux_clk",}, + [GCC_USB3_MP_PHY_PIPE_0_CLK] = {.name = "gcc_usb3_mp_phy_pipe_0_clk",}, + [GCC_USB3_MP_PHY_COM_AUX_CLK] = {.name = "gcc_usb3_mp_phy_com_aux_clk",}, + [GCC_USB3_MP_PHY_PIPE_1_CLK] = {.name = "gcc_usb3_mp_phy_pipe_1_clk",}, + [GCC_PCIE_0_PIPE_CLK] = {.name = "gcc_pcie_0_pipe_clk",}, + [GCC_PCIE_0_AUX_CLK] = {.name = "gcc_pcie_0_aux_clk",}, + [GCC_PCIE_0_CFG_AHB_CLK] = {.name = "gcc_pcie_0_cfg_ahb_clk",}, + [GCC_PCIE_0_MSTR_AXI_CLK] = {.name = "gcc_pcie_0_mstr_axi_clk",}, + [GCC_PCIE_0_SLV_AXI_CLK] = {.name = "gcc_pcie_0_slv_axi_clk",}, + [GCC_PCIE_0_CLKREF_CLK] = {.name = "gcc_pcie_0_clkref_en",}, + [GCC_PCIE_0_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_0_slv_q2a_axi_clk",}, + [GCC_PCIE_1_PIPE_CLK] = {.name = "gcc_pcie_1_pipe_clk",}, + [GCC_PCIE_1_AUX_CLK] = {.name = "gcc_pcie_1_aux_clk",}, + [GCC_PCIE_1_CFG_AHB_CLK] = {.name = "gcc_pcie_1_cfg_ahb_clk",}, + [GCC_PCIE_1_MSTR_AXI_CLK] = {.name = "gcc_pcie_1_mstr_axi_clk",}, + [GCC_PCIE_1_SLV_AXI_CLK] = {.name = "gcc_pcie_1_slv_axi_clk",}, + [GCC_PCIE_1_CLKREF_CLK] = {.name = "gcc_pcie_1_clkref_en",}, + [GCC_PCIE_1_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_1_slv_q2a_axi_clk",}, + [GCC_PCIE_2_PIPE_CLK] = {.name = "gcc_pcie_2_pipe_clk",}, + [GCC_PCIE_2_AUX_CLK] = {.name = "gcc_pcie_2_aux_clk",}, + [GCC_PCIE_2_CFG_AHB_CLK] = {.name = "gcc_pcie_2_cfg_ahb_clk",}, + [GCC_PCIE_2_MSTR_AXI_CLK] = {.name = "gcc_pcie_2_mstr_axi_clk",}, + [GCC_PCIE_2_SLV_AXI_CLK] = {.name = "gcc_pcie_2_slv_axi_clk",}, + [GCC_PCIE_2_CLKREF_CLK] = {.name = "gcc_pcie_2_clkref_en",}, + [GCC_PCIE_2_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_2_slv_q2a_axi_clk",}, + [GCC_PCIE_3_PIPE_CLK] = {.name = "gcc_pcie_3_pipe_clk",}, + [GCC_PCIE_3_AUX_CLK] = {.name = "gcc_pcie_3_aux_clk",}, + [GCC_PCIE_3_CFG_AHB_CLK] = {.name = "gcc_pcie_3_cfg_ahb_clk",}, + [GCC_PCIE_3_MSTR_AXI_CLK] = {.name = "gcc_pcie_3_mstr_axi_clk",}, + [GCC_PCIE_3_SLV_AXI_CLK] = {.name = "gcc_pcie_3_slv_axi_clk",}, + [GCC_PCIE_3_CLKREF_CLK] = {.name = "gcc_pcie_3_clkref_en",}, + [GCC_PCIE_3_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_3_slv_q2a_axi_clk",}, + [GCC_AGGRE_NOC_PCIE_TBU_CLK] = {.name = "gcc_aggre_noc_pcie_tbu_clk",}, + [GCC_PCIE0_PHY_REFGEN_CLK] = {.name = "gcc_pcie0_phy_refgen_clk",}, + [GCC_PCIE1_PHY_REFGEN_CLK] = {.name = "gcc_pcie1_phy_refgen_clk",}, + [GCC_PCIE2_PHY_REFGEN_CLK] = {.name = "gcc_pcie2_phy_refgen_clk",}, + [GCC_PCIE3_PHY_REFGEN_CLK] = {.name = "gcc_pcie3_phy_refgen_clk",}, + [GCC_PCIE_PHY_AUX_CLK] = {.name = "gcc_pcie_phy_aux_clk",}, + [GCC_SDCC2_AHB_CLK] = {.name = "gcc_sdcc2_ahb_clk",}, + [GCC_SDCC2_APPS_CLK] = {.name = "gcc_sdcc2_apps_clk",}, + [GCC_PRNG_AHB_CLK] = {.name = "gcc_prng_ahb_clk",}, + [GCC_UFS_PHY_ICE_CORE_CLK] = {.name = "gcc_ufs_phy_ice_core_clk",}, + [GCC_UFS_CARD_2_AHB_CLK] = {.name = "gcc_ufs_card_2_ahb_clk",}, + [GCC_UFS_CARD_2_ICE_CORE_CLK] = {.name = "gcc_ufs_card_2_ice_core_clk",}, + [GCC_UFS_CARD_2_PHY_AUX_CLK] = {.name = "gcc_ufs_card_2_phy_aux_clk",}, + [GCC_UFS_CARD_2_AXI_CLK] = {.name = "gcc_ufs_card_2_axi_clk",}, + [GCC_AGGRE_UFS_CARD_2_AXI_CLK] = {.name = "gcc_aggre_ufs_card_2_axi_clk",}, + [GCC_UFS_CARD_2_UNIPRO_CORE_CLK] = {.name = "gcc_ufs_card_2_unipro_core_clk",}, + [GCC_UFS_CARD_2_TX_SYMBOL_0_CLK] = {.name = "gcc_ufs_card_2_tx_symbol_0_clk",}, + [GCC_UFS_CARD_2_RX_SYMBOL_0_CLK] = {.name = "gcc_ufs_card_2_rx_symbol_0_clk",}, + [GCC_UFS_CARD_2_RX_SYMBOL_1_CLK] = {.name = "gcc_ufs_card_2_rx_symbol_1_clk",}, +}; + +static const char * const sa8195p_gcc_virtio_resets[] = { + [GCC_QUSB2PHY_PRIM_BCR] = "gcc_qusb2phy_prim_bcr", + [GCC_QUSB2PHY_SEC_BCR] = "gcc_qusb2phy_sec_bcr", + [GCC_QUSB2PHY_MP0_BCR] = "gcc_qusb2phy_mp0_bcr", + [GCC_QUSB2PHY_MP1_BCR] = "gcc_qusb2phy_mp1_bcr", + [GCC_USB30_PRIM_BCR] = "gcc_usb30_prim_master_clk", + [GCC_USB30_SEC_BCR] = "gcc_usb30_sec_master_clk", + [GCC_USB30_MP_BCR] = "gcc_usb30_mp_master_clk", + [GCC_USB3_UNIPHY_MP0_BCR] = "gcc_usb3_uniphy_mp0_bcr", + [GCC_USB3UNIPHY_PHY_MP0_BCR] = "gcc_usb3uniphy_phy_mp0_bcr", + [GCC_USB3_UNIPHY_MP1_BCR] = "gcc_usb3_uniphy_mp1_bcr", + [GCC_USB3UNIPHY_PHY_MP1_BCR] = "gcc_usb3uniphy_phy_mp1_bcr", + [GCC_PCIE_0_BCR] = "gcc_pcie_0_mstr_axi_clk", + [GCC_PCIE_0_PHY_BCR] = "gcc_pcie_0_phy_bcr", + [GCC_PCIE_1_BCR] = "gcc_pcie_1_mstr_axi_clk", + [GCC_PCIE_1_PHY_BCR] = "gcc_pcie_1_phy_bcr", + [GCC_PCIE_2_BCR] = "gcc_pcie_2_mstr_axi_clk", + [GCC_PCIE_2_PHY_BCR] = "gcc_pcie_2_phy_bcr", + [GCC_PCIE_3_BCR] = "gcc_pcie_3_mstr_axi_clk", + [GCC_PCIE_3_PHY_BCR] = "gcc_pcie_3_phy_bcr", + [GCC_UFS_CARD_2_BCR] = "gcc_ufs_card_2_axi_clk", +}; + +const struct clk_virtio_desc clk_virtio_sa8195p_gcc = { + .clks = sa8195p_gcc_virtio_clocks, + .num_clks = ARRAY_SIZE(sa8195p_gcc_virtio_clocks), + .reset_names = sa8195p_gcc_virtio_resets, + .num_resets = ARRAY_SIZE(sa8195p_gcc_virtio_resets), +}; +EXPORT_SYMBOL(clk_virtio_sa8195p_gcc); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/virtio_clk_sm8150.c b/drivers/clk/qcom/virtio_clk_sm8150.c new file mode 100644 index 000000000000..c39d509c01a1 --- /dev/null +++ b/drivers/clk/qcom/virtio_clk_sm8150.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include "virtio_clk_common.h" + +static const struct virtio_clk_init_data sm8150_gcc_virtio_clocks[] = { + [GCC_QUPV3_WRAP0_S0_CLK] = {.name = "gcc_qupv3_wrap0_s0_clk",}, + [GCC_QUPV3_WRAP0_S1_CLK] = {.name = "gcc_qupv3_wrap0_s1_clk",}, + [GCC_QUPV3_WRAP0_S2_CLK] = {.name = "gcc_qupv3_wrap0_s2_clk",}, + [GCC_QUPV3_WRAP0_S3_CLK] = {.name = "gcc_qupv3_wrap0_s3_clk",}, + [GCC_QUPV3_WRAP0_S4_CLK] = {.name = "gcc_qupv3_wrap0_s4_clk",}, + [GCC_QUPV3_WRAP0_S5_CLK] = {.name = "gcc_qupv3_wrap0_s5_clk",}, + [GCC_QUPV3_WRAP0_S6_CLK] = {.name = "gcc_qupv3_wrap0_s6_clk",}, + [GCC_QUPV3_WRAP0_S7_CLK] = {.name = "gcc_qupv3_wrap0_s7_clk",}, + [GCC_QUPV3_WRAP1_S0_CLK] = {.name = "gcc_qupv3_wrap1_s0_clk",}, + [GCC_QUPV3_WRAP1_S1_CLK] = {.name = "gcc_qupv3_wrap1_s1_clk",}, + [GCC_QUPV3_WRAP1_S2_CLK] = {.name = "gcc_qupv3_wrap1_s2_clk",}, + [GCC_QUPV3_WRAP1_S3_CLK] = {.name = "gcc_qupv3_wrap1_s3_clk",}, + [GCC_QUPV3_WRAP1_S4_CLK] = {.name = "gcc_qupv3_wrap1_s4_clk",}, + [GCC_QUPV3_WRAP1_S5_CLK] = {.name = "gcc_qupv3_wrap1_s5_clk",}, + [GCC_QUPV3_WRAP2_S0_CLK] = {.name = "gcc_qupv3_wrap2_s0_clk",}, + [GCC_QUPV3_WRAP2_S1_CLK] = {.name = "gcc_qupv3_wrap2_s1_clk",}, + [GCC_QUPV3_WRAP2_S2_CLK] = {.name = "gcc_qupv3_wrap2_s2_clk",}, + [GCC_QUPV3_WRAP2_S3_CLK] = {.name = "gcc_qupv3_wrap2_s3_clk",}, + [GCC_QUPV3_WRAP2_S4_CLK] = {.name = "gcc_qupv3_wrap2_s4_clk",}, + [GCC_QUPV3_WRAP2_S5_CLK] = {.name = "gcc_qupv3_wrap2_s5_clk",}, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_0_m_ahb_clk",}, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_0_s_ahb_clk",}, + [GCC_QUPV3_WRAP_1_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_1_m_ahb_clk",}, + [GCC_QUPV3_WRAP_1_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_1_s_ahb_clk",}, + [GCC_QUPV3_WRAP_2_M_AHB_CLK] = {.name = "gcc_qupv3_wrap_2_m_ahb_clk",}, + [GCC_QUPV3_WRAP_2_S_AHB_CLK] = {.name = "gcc_qupv3_wrap_2_s_ahb_clk",}, + [GCC_USB30_PRIM_MASTER_CLK] = {.name = "gcc_usb30_prim_master_clk",}, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = {.name = "gcc_cfg_noc_usb3_prim_axi_clk",}, + [GCC_AGGRE_USB3_PRIM_AXI_CLK] = {.name = "gcc_aggre_usb3_prim_axi_clk",}, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = {.name = "gcc_usb30_prim_mock_utmi_clk",}, + [GCC_USB30_PRIM_SLEEP_CLK] = {.name = "gcc_usb30_prim_sleep_clk",}, + [GCC_USB3_SEC_CLKREF_CLK] = {.name = "gcc_usb3_sec_clkref_en",}, + [GCC_USB3_PRIM_PHY_AUX_CLK] = {.name = "gcc_usb3_prim_phy_aux_clk",}, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = {.name = "gcc_usb3_prim_phy_pipe_clk",}, + [GCC_USB3_PRIM_CLKREF_CLK] = {.name = "gcc_usb3_prim_clkref_en",}, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = {.name = "gcc_usb3_prim_phy_com_aux_clk",}, + [GCC_USB30_SEC_MASTER_CLK] = {.name = "gcc_usb30_sec_master_clk",}, + [GCC_CFG_NOC_USB3_SEC_AXI_CLK] = {.name = "gcc_cfg_noc_usb3_sec_axi_clk",}, + [GCC_AGGRE_USB3_SEC_AXI_CLK] = {.name = "gcc_aggre_usb3_sec_axi_clk",}, + [GCC_USB30_SEC_MOCK_UTMI_CLK] = {.name = "gcc_usb30_sec_mock_utmi_clk",}, + [GCC_USB30_SEC_SLEEP_CLK] = {.name = "gcc_usb30_sec_sleep_clk",}, + [GCC_USB3_SEC_PHY_AUX_CLK] = {.name = "gcc_usb3_sec_phy_aux_clk",}, + [GCC_USB3_SEC_PHY_PIPE_CLK] = {.name = "gcc_usb3_sec_phy_pipe_clk",}, + [GCC_USB3_SEC_PHY_COM_AUX_CLK] = {.name = "gcc_usb3_sec_phy_com_aux_clk",}, + [GCC_PCIE_0_PIPE_CLK] = {.name = "gcc_pcie_0_pipe_clk",}, + [GCC_PCIE_0_AUX_CLK] = {.name = "gcc_pcie_0_aux_clk",}, + [GCC_PCIE_0_CFG_AHB_CLK] = {.name = "gcc_pcie_0_cfg_ahb_clk",}, + [GCC_PCIE_0_MSTR_AXI_CLK] = {.name = "gcc_pcie_0_mstr_axi_clk",}, + [GCC_PCIE_0_SLV_AXI_CLK] = {.name = "gcc_pcie_0_slv_axi_clk",}, + [GCC_PCIE_0_CLKREF_CLK] = {.name = "gcc_pcie_0_clkref_en",}, + [GCC_PCIE_0_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_0_slv_q2a_axi_clk",}, + [GCC_PCIE_1_PIPE_CLK] = {.name = "gcc_pcie_1_pipe_clk",}, + [GCC_PCIE_1_AUX_CLK] = {.name = "gcc_pcie_1_aux_clk",}, + [GCC_PCIE_1_CFG_AHB_CLK] = {.name = "gcc_pcie_1_cfg_ahb_clk",}, + [GCC_PCIE_1_MSTR_AXI_CLK] = {.name = "gcc_pcie_1_mstr_axi_clk",}, + [GCC_PCIE_1_SLV_AXI_CLK] = {.name = "gcc_pcie_1_slv_axi_clk",}, + [GCC_PCIE_1_CLKREF_CLK] = {.name = "gcc_pcie_1_clkref_en",}, + [GCC_PCIE_1_SLV_Q2A_AXI_CLK] = {.name = "gcc_pcie_1_slv_q2a_axi_clk",}, + [GCC_AGGRE_NOC_PCIE_TBU_CLK] = {.name = "gcc_aggre_noc_pcie_tbu_clk",}, + [GCC_PCIE0_PHY_REFGEN_CLK] = {.name = "gcc_pcie0_phy_refgen_clk",}, + [GCC_PCIE1_PHY_REFGEN_CLK] = {.name = "gcc_pcie1_phy_refgen_clk",}, + [GCC_PCIE_PHY_AUX_CLK] = {.name = "gcc_pcie_phy_aux_clk",}, + [GCC_SDCC2_AHB_CLK] = {.name = "gcc_sdcc2_ahb_clk",}, + [GCC_SDCC2_APPS_CLK] = {.name = "gcc_sdcc2_apps_clk",}, + [GCC_PRNG_AHB_CLK] = {.name = "gcc_prng_ahb_clk",}, +}; + +static const char * const sm8150_gcc_virtio_resets[] = { + [GCC_QUSB2PHY_PRIM_BCR] = "gcc_qusb2phy_prim_bcr", + [GCC_QUSB2PHY_SEC_BCR] = "gcc_qusb2phy_sec_bcr", + [GCC_USB3_PHY_PRIM_BCR] = "gcc_usb3_phy_prim_bcr", + [GCC_USB3_DP_PHY_PRIM_BCR] = "gcc_usb3_dp_phy_prim_bcr", + [GCC_USB3_PHY_SEC_BCR] = "gcc_usb3_phy_sec_bcr", + [GCC_USB3PHY_PHY_SEC_BCR] = "gcc_usb3phy_phy_sec_bcr", + [GCC_USB30_PRIM_BCR] = "gcc_usb30_prim_master_clk", + [GCC_USB30_SEC_BCR] = "gcc_usb30_sec_master_clk", + [GCC_PCIE_0_BCR] = "gcc_pcie_0_mstr_axi_clk", + [GCC_PCIE_0_PHY_BCR] = "gcc_pcie_0_phy_bcr", + [GCC_PCIE_1_BCR] = "gcc_pcie_1_mstr_axi_clk", + [GCC_PCIE_1_PHY_BCR] = "gcc_pcie_1_phy_bcr", +}; + +const struct clk_virtio_desc clk_virtio_sm8150_gcc = { + .clks = sm8150_gcc_virtio_clocks, + .num_clks = ARRAY_SIZE(sm8150_gcc_virtio_clocks), + .reset_names = sm8150_gcc_virtio_resets, + .num_resets = ARRAY_SIZE(sm8150_gcc_virtio_resets), +}; +EXPORT_SYMBOL(clk_virtio_sm8150_gcc); + +static const struct virtio_clk_init_data sm8150_scc_virtio_clocks[] = { + [SCC_QUPV3_SE0_CLK] = {.name = "scc_qupv3_se0_clk",}, + [SCC_QUPV3_SE1_CLK] = {.name = "scc_qupv3_se1_clk",}, + [SCC_QUPV3_SE2_CLK] = {.name = "scc_qupv3_se2_clk",}, + [SCC_QUPV3_SE3_CLK] = {.name = "scc_qupv3_se3_clk",}, + [SCC_QUPV3_M_HCLK_CLK] = {.name = "scc_qupv3_m_hclk_clk",}, + [SCC_QUPV3_S_HCLK_CLK] = {.name = "scc_qupv3_s_hclk_clk",}, +}; + +const struct clk_virtio_desc clk_virtio_sm8150_scc = { + .clks = sm8150_scc_virtio_clocks, + .num_clks = ARRAY_SIZE(sm8150_scc_virtio_clocks), +}; +EXPORT_SYMBOL(clk_virtio_sm8150_scc); + +MODULE_LICENSE("GPL"); diff --git a/include/linux/virtio_clk.h b/include/linux/virtio_clk.h new file mode 100644 index 000000000000..2d3373130184 --- /dev/null +++ b/include/linux/virtio_clk.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _LINUX_VIRTIO_CLK_H +#define _LINUX_VIRTIO_CLK_H + +#include +#include +#include +#include + +/* Virtio ID of clock */ +#ifdef VIRTIO_ID_CLOCK +#undef VIRTIO_ID_CLOCK +#endif + +/* Virtio ID of clock : 0xC000 */ +#define VIRTIO_ID_CLOCK 49152 + +/* Feature bits */ +#define VIRTIO_CLK_F_RESET 1 /* Support reset */ +#define VIRTIO_CLK_F_NAME 2 /* Support clock name */ + +/* Configuration layout */ +struct virtio_clk_config { + __u32 num_clks; + __u32 num_resets; + __u8 name[20]; +} __packed; + +/* Request/response message format */ +struct virtio_clk_msg { + u8 name[40]; + __virtio32 id; + __virtio32 type; + __virtio32 result; + __virtio32 data[4]; +}; + +/* Request type */ +#define VIRTIO_CLK_T_ENABLE 0 +#define VIRTIO_CLK_T_DISABLE 1 +#define VIRTIO_CLK_T_SET_RATE 2 +#define VIRTIO_CLK_T_GET_RATE 3 +#define VIRTIO_CLK_T_ROUND_RATE 4 +#define VIRTIO_CLK_T_RESET 5 +#define VIRTIO_CLK_T_SET_FLAGS 6 +#define VIRTIO_CLK_T_SET_PARENT 8 + +#endif /* _LINUX_VIRTIO_CLK_H */