linux/drivers/soc/tegra/common.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2014 NVIDIA CORPORATION.  All rights reserved.
   4 */
   5
   6#define dev_fmt(fmt)    "tegra-soc: " fmt
   7
   8#include <linux/clk.h>
   9#include <linux/device.h>
  10#include <linux/export.h>
  11#include <linux/of.h>
  12#include <linux/pm_opp.h>
  13
  14#include <soc/tegra/common.h>
  15#include <soc/tegra/fuse.h>
  16
  17static const struct of_device_id tegra_machine_match[] = {
  18        { .compatible = "nvidia,tegra20", },
  19        { .compatible = "nvidia,tegra30", },
  20        { .compatible = "nvidia,tegra114", },
  21        { .compatible = "nvidia,tegra124", },
  22        { .compatible = "nvidia,tegra132", },
  23        { .compatible = "nvidia,tegra210", },
  24        { }
  25};
  26
  27bool soc_is_tegra(void)
  28{
  29        const struct of_device_id *match;
  30        struct device_node *root;
  31
  32        root = of_find_node_by_path("/");
  33        if (!root)
  34                return false;
  35
  36        match = of_match_node(tegra_machine_match, root);
  37        of_node_put(root);
  38
  39        return match != NULL;
  40}
  41
  42static int tegra_core_dev_init_opp_state(struct device *dev)
  43{
  44        unsigned long rate;
  45        struct clk *clk;
  46        int err;
  47
  48        clk = devm_clk_get(dev, NULL);
  49        if (IS_ERR(clk)) {
  50                dev_err(dev, "failed to get clk: %pe\n", clk);
  51                return PTR_ERR(clk);
  52        }
  53
  54        rate = clk_get_rate(clk);
  55        if (!rate) {
  56                dev_err(dev, "failed to get clk rate\n");
  57                return -EINVAL;
  58        }
  59
  60        /* first dummy rate-setting initializes voltage vote */
  61        err = dev_pm_opp_set_rate(dev, rate);
  62        if (err) {
  63                dev_err(dev, "failed to initialize OPP clock: %d\n", err);
  64                return err;
  65        }
  66
  67        return 0;
  68}
  69
  70/**
  71 * devm_tegra_core_dev_init_opp_table() - initialize OPP table
  72 * @dev: device for which OPP table is initialized
  73 * @params: pointer to the OPP table configuration
  74 *
  75 * This function will initialize OPP table and sync OPP state of a Tegra SoC
  76 * core device.
  77 *
  78 * Return: 0 on success or errorno.
  79 */
  80int devm_tegra_core_dev_init_opp_table(struct device *dev,
  81                                       struct tegra_core_opp_params *params)
  82{
  83        u32 hw_version;
  84        int err;
  85
  86        err = devm_pm_opp_set_clkname(dev, NULL);
  87        if (err) {
  88                dev_err(dev, "failed to set OPP clk: %d\n", err);
  89                return err;
  90        }
  91
  92        /* Tegra114+ doesn't support OPP yet */
  93        if (!of_machine_is_compatible("nvidia,tegra20") &&
  94            !of_machine_is_compatible("nvidia,tegra30"))
  95                return -ENODEV;
  96
  97        if (of_machine_is_compatible("nvidia,tegra20"))
  98                hw_version = BIT(tegra_sku_info.soc_process_id);
  99        else
 100                hw_version = BIT(tegra_sku_info.soc_speedo_id);
 101
 102        err = devm_pm_opp_set_supported_hw(dev, &hw_version, 1);
 103        if (err) {
 104                dev_err(dev, "failed to set OPP supported HW: %d\n", err);
 105                return err;
 106        }
 107
 108        /*
 109         * Older device-trees have an empty OPP table, we will get
 110         * -ENODEV from devm_pm_opp_of_add_table() in this case.
 111         */
 112        err = devm_pm_opp_of_add_table(dev);
 113        if (err) {
 114                if (err == -ENODEV)
 115                        dev_err_once(dev, "OPP table not found, please update device-tree\n");
 116                else
 117                        dev_err(dev, "failed to add OPP table: %d\n", err);
 118
 119                return err;
 120        }
 121
 122        if (params->init_state) {
 123                err = tegra_core_dev_init_opp_state(dev);
 124                if (err)
 125                        return err;
 126        }
 127
 128        return 0;
 129}
 130EXPORT_SYMBOL_GPL(devm_tegra_core_dev_init_opp_table);
 131