123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2021 StarFive Technology Co., Ltd.
- */
- #ifndef __VDEC_STARFIVE_H__
- #define __VDEC_STARFIVE_H__
- #include <linux/io.h>
- #include <linux/clk.h>
- #include <linux/platform_device.h>
- #include <linux/reset.h>
- #include <linux/reset-controller.h>
- #include <linux/module.h>
- #include <linux/delay.h>
- #include <linux/clk-provider.h>
- #define VDEC_ID_NUM 5
- struct starfive_vdec_data {
- struct device *dev;
- struct clk *clk_vdec_axi;
- struct clk *clk_vdecbrg_main;
- struct clk *clk_vdec_bclk;
- struct clk *clk_vdec_cclk;
- struct clk *clk_vdec_apb;
- struct reset_control *rst_vdecbrg_main;
- struct reset_control *rst_vdec_axi;
- struct reset_control *rst_vdec_bclk;
- struct reset_control *rst_vdec_cclk;
- struct reset_control *rst_vdec_apb;
- struct clk *clk_vdec_id[VDEC_ID_NUM];
- struct reset_control *rst_vdec_id[VDEC_ID_NUM];
- };
- static struct starfive_vdec_data *sf_vdec = NULL;
- const char vdec_data_id[VDEC_ID_NUM][15] = {
- "vdec_axi",
- "vdecbrg_main",
- "vdec_bclk",
- "vdec_cclk",
- "vdec_apb",
- };
- void starfive_vdec_rst_status(void)
- {
- int i;
- int rst_state;
- for (i = 0; i < VDEC_ID_NUM; i++) {
- rst_state = reset_control_status(sf_vdec->rst_vdec_id[i]);
- }
- return;
- }
- void starfive_vdec_clk_status(void)
- {
- int i;
- int clk_state;
- for (i = 0; i < VDEC_ID_NUM; i++) {
- clk_state = __clk_is_enabled(sf_vdec->clk_vdec_id[i]);
- }
- return;
- }
- void starfive_vdec_rst_exit(void)
- {
- int i;
- int ret;
- for (i = 0; i < VDEC_ID_NUM; i++) {
- ret = reset_control_assert(sf_vdec->rst_vdec_id[i]);
- if (ret) {
- dev_err(sf_vdec->dev, "reset assert failed\n");
- }
- }
- return;
- }
- void starfive_vdec_clk_exit(void)
- {
- int i;
- for (i = 0; i < VDEC_ID_NUM; i++) {
- clk_disable_unprepare(sf_vdec->clk_vdec_id[i]);
- }
- return;
- }
- static int starfive_vdec_clk_init(void)
- {
- int ret = 0;
- int i;
- for (i = 0; i < VDEC_ID_NUM; i++) {
- ret = clk_prepare_enable(sf_vdec->clk_vdec_id[i]);
- if (ret) {
- dev_err(sf_vdec->dev, vdec_data_id[i]);
- goto init_clk_failed;
- }
- }
- return 0;
- init_clk_failed:
- for(; i > 0 ; i--) {
- clk_disable_unprepare(sf_vdec->clk_vdec_id[i-1]);
- }
- return ret;
- }
- static int starfive_vdec_get_clk(void)
- {
- int ret = 0;
- int i;
- for ( i = 0; i < VDEC_ID_NUM ; i++) {
- sf_vdec->clk_vdec_id[i] = devm_clk_get(sf_vdec->dev, vdec_data_id[i]);
- if (IS_ERR(sf_vdec->clk_vdec_id[i])) {
- dev_err(sf_vdec->dev, vdec_data_id[i]);
- ret = PTR_ERR(sf_vdec->clk_vdec_id[i]);
- goto get_clk_failed;
- }
- }
- return 0;
- get_clk_failed:
- for( ; i > 0 ; i--) {
- devm_clk_put(sf_vdec->dev, sf_vdec->clk_vdec_id[i-1]);
- }
- return ret;
- }
- static int starfive_vdec_reset_init(void)
- {
- int ret = 0;
- int i;
- for (i = 0; i < VDEC_ID_NUM ; i++) {
- ret = reset_control_deassert(sf_vdec->rst_vdec_id[i]);
- if (ret) {
- dev_err(sf_vdec->dev, vdec_data_id[i]);
- goto init_reset_failed;
- }
- }
- return 0;
- init_reset_failed:
- for (; i > 0 ; i--) {
- reset_control_assert(sf_vdec->rst_vdec_id[i-1]);
- }
- return ret;
- }
- static int starfive_vdec_get_resets(void)
- {
- int ret = 0;
- int i;
- for (i = 0; i < VDEC_ID_NUM ; i++) {
- sf_vdec->rst_vdec_id[i] = devm_reset_control_get_exclusive(sf_vdec->dev, vdec_data_id[i]);
- if (IS_ERR(sf_vdec->rst_vdec_id[i])) {
- dev_err(sf_vdec->dev, vdec_data_id[i]);
- ret = PTR_ERR(sf_vdec->rst_vdec_id[i]);
- goto get_resets_failed;
- }
- }
- return 0;
- get_resets_failed:
- for (; i > 0; i--) {
- reset_control_put(sf_vdec->rst_vdec_id[i-1]);
- }
- return ret;
- }
- int starfive_vdec_data_init(struct device *dev)
- {
- int ret = 0;
- if (sf_vdec == NULL){
- sf_vdec = devm_kzalloc(dev, sizeof(*sf_vdec), GFP_KERNEL);
- if (!sf_vdec)
- return -ENOMEM;
- sf_vdec->dev = dev;
- ret = starfive_vdec_get_clk();
- if (ret) {
- dev_err(sf_vdec->dev, "failed to get vdec clock\n");
- return ret;
- }
- ret = starfive_vdec_get_resets();
- if (ret) {
- dev_err(sf_vdec->dev, "failed to get vdec resets\n");
- return ret;
- }
- }
- return 0;
- }
- int starfive_vdec_clk_enable(struct device *dev)
- {
- int ret = 0;
- ret = starfive_vdec_data_init(dev);
- if (ret)
- return ret;
- ret = starfive_vdec_clk_init();
- if (ret) {
- dev_err(sf_vdec->dev, "failed to enable vdec clock\n");
- return ret;
- }
- return 0;
- }
- int starfive_vdec_clk_disable(struct device *dev)
- {
- int ret = 0;
- ret = starfive_vdec_data_init(dev);
- if (ret)
- return ret;
- starfive_vdec_clk_exit();
- return 0;
-
- }
- int starfive_vdec_rst_deassert(struct device *dev)
- {
- int ret = 0;
- ret = starfive_vdec_data_init(dev);
- if (ret)
- return ret;
- ret = starfive_vdec_reset_init();
- if (ret) {
- dev_err(sf_vdec->dev, "failed to deassert vdec resets\n");
- return ret;
- }
- return 0;
- }
- int starfive_vdec_rst_assert(struct device *dev)
- {
- int ret = 0;
- ret = starfive_vdec_data_init(dev);
- if (ret)
- return ret;
-
- starfive_vdec_rst_exit();
- return 0;
-
- }
- int starfive_vdec_clk_rst_init(struct platform_device *pdev)
- {
- int ret = 0;
- ret = starfive_vdec_data_init(&pdev->dev);
- if (ret)
- return ret;
- ret = starfive_vdec_clk_init();
- if (ret) {
- dev_err(sf_vdec->dev, "failed to enable vdec clock\n");
- return ret;
- }
- starfive_vdec_rst_exit();
- mdelay(1);
- ret = starfive_vdec_reset_init();
- if (ret) {
- dev_err(sf_vdec->dev, "failed to set vdec reset\n");
- goto init_failed;
- }
- printk("starfive vdec clock & reset init success.");
- return 0;
- init_failed:
- starfive_vdec_clk_exit();
- return ret;
- }
- #endif
|