123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2021 StarFive Technology Co., Ltd.
- */
- #ifndef __VENC_STARFIVE_H__
- #define __VENC_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 VENC_ID_NUM 5
- struct starfive_venc_data {
- struct device *dev;
- struct clk *clk_venc_id[VENC_ID_NUM];
- struct reset_control *rst_venc_id[VENC_ID_NUM];
- };
- static struct starfive_venc_data *sf_venc = NULL;
- const char venc_data_id[VENC_ID_NUM][15] = {
- "vencbrg_main",
- "venc_axi",
- "venc_bclk",
- "venc_cclk",
- "venc_apb",
- };
- void starfive_venc_rst_status(void)
- {
- int i;
- int rst_state;
- for (i = 0; i < VENC_ID_NUM; i++) {
- rst_state = reset_control_status(sf_venc->rst_venc_id[i]);
- dev_dbg(sf_venc->dev, "status_rst %d :%d", i, rst_state);
- }
- return;
- }
- void starfive_venc_clk_status(void)
- {
- int i;
- int clk_state;
- for (i = 0; i < VENC_ID_NUM; i++) {
- clk_state = __clk_is_enabled(sf_venc->clk_venc_id[i]);
- dev_dbg(sf_venc->dev, "status_clk %d :%d", i, clk_state);
- }
- return;
- }
- void starfive_venc_rst_exit(void)
- {
- int i;
- int ret;
- for (i = 1; i < VENC_ID_NUM; i++) {
- /* Assert the reset of "vencbrg_main" could crash*/
- ret = reset_control_assert(sf_venc->rst_venc_id[i]);
- if (ret) {
- dev_err(sf_venc->dev, "VENC reset assert failed:\n");
- dev_err(sf_venc->dev, venc_data_id[i]);
- }
- }
- return;
- }
- void starfive_venc_clk_exit(void)
- {
- int i;
- for (i = 1; i < VENC_ID_NUM; i++) {
- clk_disable_unprepare(sf_venc->clk_venc_id[i]);
- }
-
- return;
- }
- static int starfive_venc_clk_init(void)
- {
- int ret = 0;
- int i;
- for (i = 0; i < VENC_ID_NUM; i++) {
- ret = clk_prepare_enable(sf_venc->clk_venc_id[i]);
- if (ret) {
- dev_err(sf_venc->dev, "VENC enable clock failed:\n");
- dev_err(sf_venc->dev, venc_data_id[i]);
- goto init_clk_failed;
- }
- }
- return 0;
- init_clk_failed:
- for(; i > 1 ; i--) {
- clk_disable_unprepare(sf_venc->clk_venc_id[i-1]);
- }
- return ret;
- }
- static int starfive_venc_get_clk(void)
- {
- int ret = 0;
- int i;
- for ( i = 0; i < VENC_ID_NUM ; i++) {
- sf_venc->clk_venc_id[i] = devm_clk_get(sf_venc->dev, venc_data_id[i]);
- if (IS_ERR(sf_venc->clk_venc_id[i])) {
- dev_err(sf_venc->dev, "VENC get clock failed:\n");
- dev_err(sf_venc->dev, venc_data_id[i]);
- ret = PTR_ERR(sf_venc->clk_venc_id[i]);
- goto get_clk_failed;
- }
- }
- return 0;
- get_clk_failed:
- for( ; i > 0 ; i--) {
- devm_clk_put(sf_venc->dev, sf_venc->clk_venc_id[i-1]);
- }
- return ret;
- }
- static int starfive_venc_reset_init(void)
- {
- int ret = 0;
- int i;
- for (i = 0; i < VENC_ID_NUM ; i++) {
- ret = reset_control_deassert(sf_venc->rst_venc_id[i]);
- if (ret) {
- dev_err(sf_venc->dev, "VENC deassert reset failed:\n");
- dev_err(sf_venc->dev, venc_data_id[i]);
- goto init_reset_failed;
- }
- }
- return 0;
- init_reset_failed:
- for (; i > 1 ; i--) {
- reset_control_assert(sf_venc->rst_venc_id[i-1]);
- }
- return ret;
- }
- static int starfive_venc_get_resets(void)
- {
-
- int ret = 0;
- int i;
- for (i = 0; i < VENC_ID_NUM ; i++) {
- sf_venc->rst_venc_id[i] = devm_reset_control_get_exclusive(sf_venc->dev, venc_data_id[i]);
- if (IS_ERR(sf_venc->rst_venc_id[i])) {
- dev_err(sf_venc->dev, "VENC get reset failed:\n");
- dev_err(sf_venc->dev, venc_data_id[i]);
- ret = PTR_ERR(sf_venc->rst_venc_id[i]);
- goto get_resets_failed;
- }
- }
- return 0;
- get_resets_failed:
- for (; i > 0; i--) {
- reset_control_put(sf_venc->rst_venc_id[i-1]);
- }
- return ret;
- }
- int starfive_venc_data_init(struct device *dev)
- {
- int ret = 0;
- if (sf_venc == NULL){
- sf_venc = devm_kzalloc(dev, sizeof(*sf_venc), GFP_KERNEL);
- if (!sf_venc)
- return -ENOMEM;
- sf_venc->dev = dev;
- ret = starfive_venc_get_clk();
- if (ret) {
- dev_err(sf_venc->dev, "failed to get venc clock\n");
- return ret;
- }
- ret = starfive_venc_get_resets();
- if (ret) {
- dev_err(sf_venc->dev, "failed to get venc resets\n");
- return ret;
- }
- }
- return 0;
- }
- int starfive_venc_clk_enable(struct device *dev)
- {
- int ret = 0;
- ret = starfive_venc_data_init(dev);
- if (ret)
- return ret;
- ret = starfive_venc_clk_init();
- if (ret) {
- dev_err(sf_venc->dev, "failed to enable venc clock\n");
- return ret;
- }
- return 0;
- }
- int starfive_venc_clk_disable(struct device *dev)
- {
- int ret = 0;
- ret = starfive_venc_data_init(dev);
- if (ret)
- return ret;
-
- starfive_venc_clk_exit();
- return 0;
-
- }
- int starfive_venc_rst_deassert(struct device *dev)
- {
- int ret = 0;
- ret = starfive_venc_data_init(dev);
- if (ret)
- return ret;
- ret = starfive_venc_reset_init();
- if (ret) {
- dev_err(sf_venc->dev, "failed to deassert venc resets\n");
- return ret;
- }
- return 0;
- }
- int starfive_venc_rst_assert(struct device *dev)
- {
- int ret = 0;
- ret = starfive_venc_data_init(dev);
- if (ret)
- return ret;
-
- starfive_venc_rst_exit();
- return 0;
-
- }
- int starfive_venc_clk_rst_init(struct platform_device *pdev)
- {
- int ret = 0;
- ret = starfive_venc_data_init(&pdev->dev);
- if (ret)
- return ret;
- ret = starfive_venc_clk_init();
- if (ret) {
- dev_err(sf_venc->dev, "failed to enable venc clock\n");
- return ret;
- }
- starfive_venc_rst_status();
- starfive_venc_rst_exit();
- mdelay(1);
- ret = starfive_venc_reset_init();
- if (ret) {
- dev_err(sf_venc->dev, "failed to set venc reset\n");
- goto init_failed;
- }
- starfive_venc_rst_status();
- dev_info(sf_venc->dev, "success to init VENC clock & reset.");
- return 0;
- init_failed:
- starfive_venc_clk_exit();
- return ret;
- }
- #endif
|