Merge tag 'memory-controller-drv-6.19-2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into soc/drivers
Memory controller drivers for v6.19 1. Tegra drivers: Several cleanups (dev_err_probe(), error messages). 2. Renesas RPC IF: Add system suspend support. * tag 'memory-controller-drv-6.19-2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl: memory: tegra186-emc: Fix missing put_bpmp memory: renesas-rpc-if: Add suspend/resume support memory: tegra30-emc: Add the SoC model prefix to functions memory: tegra20-emc: Add the SoC model prefix to functions memory: tegra186-emc: Add the SoC model prefix to functions memory: tegra124-emc: Add the SoC model prefix to functions memory: tegra124-emc: Simplify and handle deferred probe with dev_err_probe() memory: tegra186-emc: Simplify and handle deferred probe with dev_err_probe() memory: tegra20-emc: Simplify and handle deferred probe with dev_err_probe() memory: tegra30-emc: Simplify and handle deferred probe with dev_err_probe() memory: tegra30-emc: Do not print error on icc_node_create() failure memory: tegra20-emc: Do not print error on icc_node_create() failure memory: tegra186-emc: Do not print error on icc_node_create() failure memory: tegra124-emc: Do not print error on icc_node_create() failure memory: tegra124-emc: Simplify return of emc_init() Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
@@ -67,6 +67,8 @@ struct rpcif_priv {
|
||||
void __iomem *dirmap;
|
||||
struct regmap *regmap;
|
||||
struct reset_control *rstc;
|
||||
struct clk *spi_clk;
|
||||
struct clk *spix2_clk;
|
||||
struct platform_device *vdev;
|
||||
size_t size;
|
||||
const struct rpcif_info *info;
|
||||
@@ -1024,19 +1026,15 @@ static int rpcif_probe(struct platform_device *pdev)
|
||||
* flash write failure. So, enable these clocks during probe() and
|
||||
* disable it in remove().
|
||||
*/
|
||||
if (rpc->info->type == XSPI_RZ_G3E) {
|
||||
struct clk *spi_clk;
|
||||
rpc->spix2_clk = devm_clk_get_optional_enabled(dev, "spix2");
|
||||
if (IS_ERR(rpc->spix2_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(rpc->spix2_clk),
|
||||
"cannot get enabled spix2 clk\n");
|
||||
|
||||
spi_clk = devm_clk_get_enabled(dev, "spix2");
|
||||
if (IS_ERR(spi_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(spi_clk),
|
||||
"cannot get enabled spix2 clk\n");
|
||||
|
||||
spi_clk = devm_clk_get_enabled(dev, "spi");
|
||||
if (IS_ERR(spi_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(spi_clk),
|
||||
"cannot get enabled spi clk\n");
|
||||
}
|
||||
rpc->spi_clk = devm_clk_get_optional_enabled(dev, "spi");
|
||||
if (IS_ERR(rpc->spi_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(rpc->spi_clk),
|
||||
"cannot get enabled spi clk\n");
|
||||
|
||||
vdev = platform_device_alloc(name, pdev->id);
|
||||
if (!vdev)
|
||||
@@ -1063,6 +1061,37 @@ static void rpcif_remove(struct platform_device *pdev)
|
||||
platform_device_unregister(rpc->vdev);
|
||||
}
|
||||
|
||||
static int rpcif_suspend(struct device *dev)
|
||||
{
|
||||
struct rpcif_priv *rpc = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(rpc->spi_clk);
|
||||
clk_disable_unprepare(rpc->spix2_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpcif_resume(struct device *dev)
|
||||
{
|
||||
struct rpcif_priv *rpc = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(rpc->spix2_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable spix2 clock: %pe\n", ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(rpc->spi_clk);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(rpc->spix2_clk);
|
||||
dev_err(dev, "failed to enable spi clock: %pe\n", ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rpcif_impl rpcif_impl = {
|
||||
.hw_init = rpcif_hw_init_impl,
|
||||
.prepare = rpcif_prepare_impl,
|
||||
@@ -1125,12 +1154,15 @@ static const struct of_device_id rpcif_of_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rpcif_of_match);
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(rpcif_pm_ops, rpcif_suspend, rpcif_resume);
|
||||
|
||||
static struct platform_driver rpcif_driver = {
|
||||
.probe = rpcif_probe,
|
||||
.remove = rpcif_remove,
|
||||
.driver = {
|
||||
.name = "rpc-if",
|
||||
.of_match_table = rpcif_of_match,
|
||||
.pm = pm_sleep_ptr(&rpcif_pm_ops),
|
||||
},
|
||||
};
|
||||
module_platform_driver(rpcif_driver);
|
||||
|
||||
@@ -571,8 +571,8 @@ static void emc_seq_wait_clkchange(struct tegra_emc *emc)
|
||||
dev_err(emc->dev, "clock change timed out\n");
|
||||
}
|
||||
|
||||
static struct emc_timing *tegra_emc_find_timing(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
static struct emc_timing *tegra124_emc_find_timing(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
{
|
||||
struct emc_timing *timing = NULL;
|
||||
unsigned int i;
|
||||
@@ -592,10 +592,10 @@ static struct emc_timing *tegra_emc_find_timing(struct tegra_emc *emc,
|
||||
return timing;
|
||||
}
|
||||
|
||||
static int tegra_emc_prepare_timing_change(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
static int tegra124_emc_prepare_timing_change(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
{
|
||||
struct emc_timing *timing = tegra_emc_find_timing(emc, rate);
|
||||
struct emc_timing *timing = tegra124_emc_find_timing(emc, rate);
|
||||
struct emc_timing *last = &emc->last_timing;
|
||||
enum emc_dll_change dll_change;
|
||||
unsigned int pre_wait = 0;
|
||||
@@ -820,10 +820,10 @@ static int tegra_emc_prepare_timing_change(struct tegra_emc *emc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra_emc_complete_timing_change(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
static void tegra124_emc_complete_timing_change(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
{
|
||||
struct emc_timing *timing = tegra_emc_find_timing(emc, rate);
|
||||
struct emc_timing *timing = tegra124_emc_find_timing(emc, rate);
|
||||
struct emc_timing *last = &emc->last_timing;
|
||||
u32 val;
|
||||
|
||||
@@ -896,7 +896,7 @@ static void emc_read_current_timing(struct tegra_emc *emc,
|
||||
timing->emc_mode_reset = 0;
|
||||
}
|
||||
|
||||
static int emc_init(struct tegra_emc *emc)
|
||||
static void emc_init(struct tegra_emc *emc)
|
||||
{
|
||||
emc->dram_type = readl(emc->regs + EMC_FBIO_CFG5);
|
||||
|
||||
@@ -913,8 +913,6 @@ static int emc_init(struct tegra_emc *emc)
|
||||
emc->dram_num = tegra_mc_get_emem_device_count(emc->mc);
|
||||
|
||||
emc_read_current_timing(emc, &emc->last_timing);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_one_timing_from_dt(struct tegra_emc *emc,
|
||||
@@ -988,8 +986,8 @@ static int cmp_timings(const void *_a, const void *_b)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
|
||||
struct device_node *node)
|
||||
static int tegra124_emc_load_timings_from_dt(struct tegra_emc *emc,
|
||||
struct device_node *node)
|
||||
{
|
||||
int child_count = of_get_child_count(node);
|
||||
struct emc_timing *timing;
|
||||
@@ -1017,15 +1015,15 @@ static int tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id tegra_emc_of_match[] = {
|
||||
static const struct of_device_id tegra124_emc_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra124-emc" },
|
||||
{ .compatible = "nvidia,tegra132-emc" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_emc_of_match);
|
||||
MODULE_DEVICE_TABLE(of, tegra124_emc_of_match);
|
||||
|
||||
static struct device_node *
|
||||
tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
|
||||
tegra124_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
|
||||
{
|
||||
struct device_node *np;
|
||||
int err;
|
||||
@@ -1043,7 +1041,7 @@ tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void tegra_emc_rate_requests_init(struct tegra_emc *emc)
|
||||
static void tegra124_emc_rate_requests_init(struct tegra_emc *emc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -1145,7 +1143,7 @@ static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
|
||||
* valid range.
|
||||
*/
|
||||
|
||||
static bool tegra_emc_validate_rate(struct tegra_emc *emc, unsigned long rate)
|
||||
static bool tegra124_emc_validate_rate(struct tegra_emc *emc, unsigned long rate)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -1156,8 +1154,8 @@ static bool tegra_emc_validate_rate(struct tegra_emc *emc, unsigned long rate)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int tegra_emc_debug_available_rates_show(struct seq_file *s,
|
||||
void *data)
|
||||
static int tegra124_emc_debug_available_rates_show(struct seq_file *s,
|
||||
void *data)
|
||||
{
|
||||
struct tegra_emc *emc = s->private;
|
||||
const char *prefix = "";
|
||||
@@ -1173,9 +1171,9 @@ static int tegra_emc_debug_available_rates_show(struct seq_file *s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(tegra_emc_debug_available_rates);
|
||||
DEFINE_SHOW_ATTRIBUTE(tegra124_emc_debug_available_rates);
|
||||
|
||||
static int tegra_emc_debug_min_rate_get(void *data, u64 *rate)
|
||||
static int tegra124_emc_debug_min_rate_get(void *data, u64 *rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
|
||||
@@ -1184,12 +1182,12 @@ static int tegra_emc_debug_min_rate_get(void *data, u64 *rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
static int tegra124_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
int err;
|
||||
|
||||
if (!tegra_emc_validate_rate(emc, rate))
|
||||
if (!tegra124_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
@@ -1201,11 +1199,11 @@ static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(tegra_emc_debug_min_rate_fops,
|
||||
tegra_emc_debug_min_rate_get,
|
||||
tegra_emc_debug_min_rate_set, "%llu\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(tegra124_emc_debug_min_rate_fops,
|
||||
tegra124_emc_debug_min_rate_get,
|
||||
tegra124_emc_debug_min_rate_set, "%llu\n");
|
||||
|
||||
static int tegra_emc_debug_max_rate_get(void *data, u64 *rate)
|
||||
static int tegra124_emc_debug_max_rate_get(void *data, u64 *rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
|
||||
@@ -1214,12 +1212,12 @@ static int tegra_emc_debug_max_rate_get(void *data, u64 *rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
static int tegra124_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
int err;
|
||||
|
||||
if (!tegra_emc_validate_rate(emc, rate))
|
||||
if (!tegra124_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
@@ -1231,9 +1229,9 @@ static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(tegra_emc_debug_max_rate_fops,
|
||||
tegra_emc_debug_max_rate_get,
|
||||
tegra_emc_debug_max_rate_set, "%llu\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(tegra124_emc_debug_max_rate_fops,
|
||||
tegra124_emc_debug_max_rate_get,
|
||||
tegra124_emc_debug_max_rate_set, "%llu\n");
|
||||
|
||||
static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc)
|
||||
{
|
||||
@@ -1268,11 +1266,11 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc)
|
||||
emc->debugfs.root = debugfs_create_dir("emc", NULL);
|
||||
|
||||
debugfs_create_file("available_rates", 0444, emc->debugfs.root, emc,
|
||||
&tegra_emc_debug_available_rates_fops);
|
||||
&tegra124_emc_debug_available_rates_fops);
|
||||
debugfs_create_file("min_rate", 0644, emc->debugfs.root,
|
||||
emc, &tegra_emc_debug_min_rate_fops);
|
||||
emc, &tegra124_emc_debug_min_rate_fops);
|
||||
debugfs_create_file("max_rate", 0644, emc->debugfs.root,
|
||||
emc, &tegra_emc_debug_max_rate_fops);
|
||||
emc, &tegra124_emc_debug_max_rate_fops);
|
||||
}
|
||||
|
||||
static inline struct tegra_emc *
|
||||
@@ -1336,7 +1334,7 @@ static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
||||
static int tegra124_emc_interconnect_init(struct tegra_emc *emc)
|
||||
{
|
||||
const struct tegra_mc_soc *soc = emc->mc->soc;
|
||||
struct icc_node *node;
|
||||
@@ -1352,10 +1350,8 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
||||
|
||||
/* create External Memory Controller node */
|
||||
node = icc_node_create(TEGRA_ICC_EMC);
|
||||
if (IS_ERR(node)) {
|
||||
err = PTR_ERR(node);
|
||||
goto err_msg;
|
||||
}
|
||||
if (IS_ERR(node))
|
||||
return PTR_ERR(node);
|
||||
|
||||
node->name = "External Memory Controller";
|
||||
icc_node_add(node, &emc->provider);
|
||||
@@ -1383,30 +1379,28 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
||||
|
||||
remove_nodes:
|
||||
icc_nodes_remove(&emc->provider);
|
||||
err_msg:
|
||||
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
|
||||
|
||||
return err;
|
||||
return dev_err_probe(emc->dev, err, "failed to initialize ICC\n");
|
||||
}
|
||||
|
||||
static int tegra_emc_opp_table_init(struct tegra_emc *emc)
|
||||
static int tegra124_emc_opp_table_init(struct tegra_emc *emc)
|
||||
{
|
||||
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
||||
int opp_token, err;
|
||||
|
||||
err = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
|
||||
if (err < 0) {
|
||||
dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (err < 0)
|
||||
return dev_err_probe(emc->dev, err, "failed to set OPP supported HW\n");
|
||||
|
||||
opp_token = err;
|
||||
|
||||
err = dev_pm_opp_of_add_table(emc->dev);
|
||||
if (err) {
|
||||
if (err == -ENODEV)
|
||||
dev_err(emc->dev, "OPP table not found, please update your device tree\n");
|
||||
dev_err_probe(emc->dev, err,
|
||||
"OPP table not found, please update your device tree\n");
|
||||
else
|
||||
dev_err(emc->dev, "failed to add OPP table: %d\n", err);
|
||||
dev_err_probe(emc->dev, err, "failed to add OPP table\n");
|
||||
|
||||
goto put_hw_table;
|
||||
}
|
||||
@@ -1417,7 +1411,7 @@ static int tegra_emc_opp_table_init(struct tegra_emc *emc)
|
||||
/* first dummy rate-set initializes voltage state */
|
||||
err = dev_pm_opp_set_rate(emc->dev, clk_get_rate(emc->clk));
|
||||
if (err) {
|
||||
dev_err(emc->dev, "failed to initialize OPP clock: %d\n", err);
|
||||
dev_err_probe(emc->dev, err, "failed to initialize OPP clock\n");
|
||||
goto remove_table;
|
||||
}
|
||||
|
||||
@@ -1431,12 +1425,12 @@ put_hw_table:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void devm_tegra_emc_unset_callback(void *data)
|
||||
static void devm_tegra124_emc_unset_callback(void *data)
|
||||
{
|
||||
tegra124_clk_set_emc_callbacks(NULL, NULL);
|
||||
}
|
||||
|
||||
static int tegra_emc_probe(struct platform_device *pdev)
|
||||
static int tegra124_emc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct tegra_emc *emc;
|
||||
@@ -1460,9 +1454,9 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
|
||||
ram_code = tegra_read_ram_code();
|
||||
|
||||
np = tegra_emc_find_node_by_ram_code(pdev->dev.of_node, ram_code);
|
||||
np = tegra124_emc_find_node_by_ram_code(pdev->dev.of_node, ram_code);
|
||||
if (np) {
|
||||
err = tegra_emc_load_timings_from_dt(emc, np);
|
||||
err = tegra124_emc_load_timings_from_dt(emc, np);
|
||||
of_node_put(np);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -1472,39 +1466,33 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
ram_code);
|
||||
}
|
||||
|
||||
err = emc_init(emc);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "EMC initialization failed: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
emc_init(emc);
|
||||
|
||||
platform_set_drvdata(pdev, emc);
|
||||
|
||||
tegra124_clk_set_emc_callbacks(tegra_emc_prepare_timing_change,
|
||||
tegra_emc_complete_timing_change);
|
||||
tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change,
|
||||
tegra124_emc_complete_timing_change);
|
||||
|
||||
err = devm_add_action_or_reset(&pdev->dev, devm_tegra_emc_unset_callback,
|
||||
err = devm_add_action_or_reset(&pdev->dev, devm_tegra124_emc_unset_callback,
|
||||
NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
emc->clk = devm_clk_get(&pdev->dev, "emc");
|
||||
if (IS_ERR(emc->clk)) {
|
||||
err = PTR_ERR(emc->clk);
|
||||
dev_err(&pdev->dev, "failed to get EMC clock: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (IS_ERR(emc->clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(emc->clk),
|
||||
"failed to get EMC clock\n");
|
||||
|
||||
err = tegra_emc_opp_table_init(emc);
|
||||
err = tegra124_emc_opp_table_init(emc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
tegra_emc_rate_requests_init(emc);
|
||||
tegra124_emc_rate_requests_init(emc);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DEBUG_FS))
|
||||
emc_debugfs_init(&pdev->dev, emc);
|
||||
|
||||
tegra_emc_interconnect_init(emc);
|
||||
tegra124_emc_interconnect_init(emc);
|
||||
|
||||
/*
|
||||
* Don't allow the kernel module to be unloaded. Unloading adds some
|
||||
@@ -1516,16 +1504,16 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct platform_driver tegra_emc_driver = {
|
||||
.probe = tegra_emc_probe,
|
||||
static struct platform_driver tegra124_emc_driver = {
|
||||
.probe = tegra124_emc_probe,
|
||||
.driver = {
|
||||
.name = "tegra-emc",
|
||||
.of_match_table = tegra_emc_of_match,
|
||||
.of_match_table = tegra124_emc_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
.sync_state = icc_sync_state,
|
||||
},
|
||||
};
|
||||
module_platform_driver(tegra_emc_driver);
|
||||
module_platform_driver(tegra124_emc_driver);
|
||||
|
||||
MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
|
||||
MODULE_DESCRIPTION("NVIDIA Tegra124 EMC driver");
|
||||
|
||||
@@ -218,20 +218,20 @@ static int tegra186_emc_get_emc_dvfs_latency(struct tegra186_emc *emc)
|
||||
}
|
||||
|
||||
/*
|
||||
* tegra_emc_icc_set_bw() - Set BW api for EMC provider
|
||||
* tegra186_emc_icc_set_bw() - Set BW api for EMC provider
|
||||
* @src: ICC node for External Memory Controller (EMC)
|
||||
* @dst: ICC node for External Memory (DRAM)
|
||||
*
|
||||
* Do nothing here as info to BPMP-FW is now passed in the BW set function
|
||||
* of the MC driver. BPMP-FW sets the final Freq based on the passed values.
|
||||
*/
|
||||
static int tegra_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst)
|
||||
static int tegra186_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct icc_node *
|
||||
tegra_emc_of_icc_xlate(const struct of_phandle_args *spec, void *data)
|
||||
tegra186_emc_of_icc_xlate(const struct of_phandle_args *spec, void *data)
|
||||
{
|
||||
struct icc_provider *provider = data;
|
||||
struct icc_node *node;
|
||||
@@ -247,7 +247,7 @@ tegra_emc_of_icc_xlate(const struct of_phandle_args *spec, void *data)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
static int tegra_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
static int tegra186_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
{
|
||||
*avg = 0;
|
||||
*peak = 0;
|
||||
@@ -255,7 +255,7 @@ static int tegra_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_interconnect_init(struct tegra186_emc *emc)
|
||||
static int tegra186_emc_interconnect_init(struct tegra186_emc *emc)
|
||||
{
|
||||
struct tegra_mc *mc = dev_get_drvdata(emc->dev->parent);
|
||||
const struct tegra_mc_soc *soc = mc->soc;
|
||||
@@ -263,20 +263,18 @@ static int tegra_emc_interconnect_init(struct tegra186_emc *emc)
|
||||
int err;
|
||||
|
||||
emc->provider.dev = emc->dev;
|
||||
emc->provider.set = tegra_emc_icc_set_bw;
|
||||
emc->provider.set = tegra186_emc_icc_set_bw;
|
||||
emc->provider.data = &emc->provider;
|
||||
emc->provider.aggregate = soc->icc_ops->aggregate;
|
||||
emc->provider.xlate = tegra_emc_of_icc_xlate;
|
||||
emc->provider.get_bw = tegra_emc_icc_get_init_bw;
|
||||
emc->provider.xlate = tegra186_emc_of_icc_xlate;
|
||||
emc->provider.get_bw = tegra186_emc_icc_get_init_bw;
|
||||
|
||||
icc_provider_init(&emc->provider);
|
||||
|
||||
/* create External Memory Controller node */
|
||||
node = icc_node_create(TEGRA_ICC_EMC);
|
||||
if (IS_ERR(node)) {
|
||||
err = PTR_ERR(node);
|
||||
goto err_msg;
|
||||
}
|
||||
if (IS_ERR(node))
|
||||
return PTR_ERR(node);
|
||||
|
||||
node->name = "External Memory Controller";
|
||||
icc_node_add(node, &emc->provider);
|
||||
@@ -304,10 +302,8 @@ static int tegra_emc_interconnect_init(struct tegra186_emc *emc)
|
||||
|
||||
remove_nodes:
|
||||
icc_nodes_remove(&emc->provider);
|
||||
err_msg:
|
||||
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
|
||||
|
||||
return err;
|
||||
return dev_err_probe(emc->dev, err, "failed to initialize ICC\n");
|
||||
}
|
||||
|
||||
static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
@@ -322,12 +318,13 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
|
||||
emc->bpmp = tegra_bpmp_get(&pdev->dev);
|
||||
if (IS_ERR(emc->bpmp))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(emc->bpmp), "failed to get BPMP\n");
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(emc->bpmp),
|
||||
"failed to get BPMP\n");
|
||||
|
||||
emc->clk = devm_clk_get(&pdev->dev, "emc");
|
||||
if (IS_ERR(emc->clk)) {
|
||||
err = PTR_ERR(emc->clk);
|
||||
dev_err(&pdev->dev, "failed to get EMC clock: %d\n", err);
|
||||
err = dev_err_probe(&pdev->dev, PTR_ERR(emc->clk),
|
||||
"failed to get EMC clock\n");
|
||||
goto put_bpmp;
|
||||
}
|
||||
|
||||
@@ -359,7 +356,7 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
* EINVAL instead of passing the request to BPMP-FW later when the BW
|
||||
* request is made by client with 'icc_set_bw()' call.
|
||||
*/
|
||||
err = tegra_emc_interconnect_init(emc);
|
||||
err = tegra186_emc_interconnect_init(emc);
|
||||
if (err) {
|
||||
mc->bpmp = NULL;
|
||||
goto put_bpmp;
|
||||
|
||||
@@ -232,7 +232,7 @@ struct tegra_emc {
|
||||
bool mrr_error;
|
||||
};
|
||||
|
||||
static irqreturn_t tegra_emc_isr(int irq, void *data)
|
||||
static irqreturn_t tegra20_emc_isr(int irq, void *data)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
u32 intmask = EMC_REFRESH_OVERFLOW_INT;
|
||||
@@ -253,8 +253,8 @@ static irqreturn_t tegra_emc_isr(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct emc_timing *tegra_emc_find_timing(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
static struct emc_timing *tegra20_emc_find_timing(struct tegra_emc *emc,
|
||||
unsigned long rate)
|
||||
{
|
||||
struct emc_timing *timing = NULL;
|
||||
unsigned int i;
|
||||
@@ -276,7 +276,7 @@ static struct emc_timing *tegra_emc_find_timing(struct tegra_emc *emc,
|
||||
|
||||
static int emc_prepare_timing_change(struct tegra_emc *emc, unsigned long rate)
|
||||
{
|
||||
struct emc_timing *timing = tegra_emc_find_timing(emc, rate);
|
||||
struct emc_timing *timing = tegra20_emc_find_timing(emc, rate);
|
||||
unsigned int i;
|
||||
|
||||
if (!timing)
|
||||
@@ -321,8 +321,8 @@ static int emc_complete_timing_change(struct tegra_emc *emc, bool flush)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_clk_change_notify(struct notifier_block *nb,
|
||||
unsigned long msg, void *data)
|
||||
static int tegra20_emc_clk_change_notify(struct notifier_block *nb,
|
||||
unsigned long msg, void *data)
|
||||
{
|
||||
struct tegra_emc *emc = container_of(nb, struct tegra_emc, clk_nb);
|
||||
struct clk_notifier_data *cnd = data;
|
||||
@@ -407,8 +407,8 @@ static int cmp_timings(const void *_a, const void *_b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
|
||||
struct device_node *node)
|
||||
static int tegra20_emc_load_timings_from_dt(struct tegra_emc *emc,
|
||||
struct device_node *node)
|
||||
{
|
||||
struct emc_timing *timing;
|
||||
int child_count;
|
||||
@@ -452,7 +452,7 @@ static int tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
|
||||
}
|
||||
|
||||
static struct device_node *
|
||||
tegra_emc_find_node_by_ram_code(struct tegra_emc *emc)
|
||||
tegra20_emc_find_node_by_ram_code(struct tegra_emc *emc)
|
||||
{
|
||||
struct device *dev = emc->dev;
|
||||
struct device_node *np;
|
||||
@@ -710,7 +710,7 @@ static long emc_round_rate(unsigned long rate,
|
||||
return timing->rate;
|
||||
}
|
||||
|
||||
static void tegra_emc_rate_requests_init(struct tegra_emc *emc)
|
||||
static void tegra20_emc_rate_requests_init(struct tegra_emc *emc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -812,7 +812,7 @@ static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
|
||||
* valid range.
|
||||
*/
|
||||
|
||||
static bool tegra_emc_validate_rate(struct tegra_emc *emc, unsigned long rate)
|
||||
static bool tegra20_emc_validate_rate(struct tegra_emc *emc, unsigned long rate)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -823,7 +823,7 @@ static bool tegra_emc_validate_rate(struct tegra_emc *emc, unsigned long rate)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int tegra_emc_debug_available_rates_show(struct seq_file *s, void *data)
|
||||
static int tegra20_emc_debug_available_rates_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct tegra_emc *emc = s->private;
|
||||
const char *prefix = "";
|
||||
@@ -838,9 +838,9 @@ static int tegra_emc_debug_available_rates_show(struct seq_file *s, void *data)
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(tegra_emc_debug_available_rates);
|
||||
DEFINE_SHOW_ATTRIBUTE(tegra20_emc_debug_available_rates);
|
||||
|
||||
static int tegra_emc_debug_min_rate_get(void *data, u64 *rate)
|
||||
static int tegra20_emc_debug_min_rate_get(void *data, u64 *rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
|
||||
@@ -849,12 +849,12 @@ static int tegra_emc_debug_min_rate_get(void *data, u64 *rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
static int tegra20_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
int err;
|
||||
|
||||
if (!tegra_emc_validate_rate(emc, rate))
|
||||
if (!tegra20_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
@@ -866,11 +866,11 @@ static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(tegra_emc_debug_min_rate_fops,
|
||||
tegra_emc_debug_min_rate_get,
|
||||
tegra_emc_debug_min_rate_set, "%llu\n");
|
||||
DEFINE_SIMPLE_ATTRIBUTE(tegra20_emc_debug_min_rate_fops,
|
||||
tegra20_emc_debug_min_rate_get,
|
||||
tegra20_emc_debug_min_rate_set, "%llu\n");
|
||||
|
||||
static int tegra_emc_debug_max_rate_get(void *data, u64 *rate)
|
||||
static int tegra20_emc_debug_max_rate_get(void *data, u64 *rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
|
||||
@@ -879,12 +879,12 @@ static int tegra_emc_debug_max_rate_get(void *data, u64 *rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
static int tegra20_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
int err;
|
||||
|
||||
if (!tegra_emc_validate_rate(emc, rate))
|
||||
if (!tegra20_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
@@ -896,11 +896,11 @@ static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(tegra_emc_debug_max_rate_fops,
|
||||
tegra_emc_debug_max_rate_get,
|
||||
tegra_emc_debug_max_rate_set, "%llu\n");
|
||||
DEFINE_SIMPLE_ATTRIBUTE(tegra20_emc_debug_max_rate_fops,
|
||||
tegra20_emc_debug_max_rate_get,
|
||||
tegra20_emc_debug_max_rate_set, "%llu\n");
|
||||
|
||||
static void tegra_emc_debugfs_init(struct tegra_emc *emc)
|
||||
static void tegra20_emc_debugfs_init(struct tegra_emc *emc)
|
||||
{
|
||||
struct device *dev = emc->dev;
|
||||
unsigned int i;
|
||||
@@ -933,11 +933,11 @@ static void tegra_emc_debugfs_init(struct tegra_emc *emc)
|
||||
emc->debugfs.root = debugfs_create_dir("emc", NULL);
|
||||
|
||||
debugfs_create_file("available_rates", 0444, emc->debugfs.root,
|
||||
emc, &tegra_emc_debug_available_rates_fops);
|
||||
emc, &tegra20_emc_debug_available_rates_fops);
|
||||
debugfs_create_file("min_rate", 0644, emc->debugfs.root,
|
||||
emc, &tegra_emc_debug_min_rate_fops);
|
||||
emc, &tegra20_emc_debug_min_rate_fops);
|
||||
debugfs_create_file("max_rate", 0644, emc->debugfs.root,
|
||||
emc, &tegra_emc_debug_max_rate_fops);
|
||||
emc, &tegra20_emc_debug_max_rate_fops);
|
||||
}
|
||||
|
||||
static inline struct tegra_emc *
|
||||
@@ -1000,7 +1000,7 @@ static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
||||
static int tegra20_emc_interconnect_init(struct tegra_emc *emc)
|
||||
{
|
||||
const struct tegra_mc_soc *soc;
|
||||
struct icc_node *node;
|
||||
@@ -1022,10 +1022,8 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
||||
|
||||
/* create External Memory Controller node */
|
||||
node = icc_node_create(TEGRA_ICC_EMC);
|
||||
if (IS_ERR(node)) {
|
||||
err = PTR_ERR(node);
|
||||
goto err_msg;
|
||||
}
|
||||
if (IS_ERR(node))
|
||||
return PTR_ERR(node);
|
||||
|
||||
node->name = "External Memory Controller";
|
||||
icc_node_add(node, &emc->provider);
|
||||
@@ -1053,57 +1051,52 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
||||
|
||||
remove_nodes:
|
||||
icc_nodes_remove(&emc->provider);
|
||||
err_msg:
|
||||
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
|
||||
|
||||
return err;
|
||||
return dev_err_probe(emc->dev, err, "failed to initialize ICC\n");
|
||||
}
|
||||
|
||||
static void devm_tegra_emc_unset_callback(void *data)
|
||||
static void devm_tegra20_emc_unset_callback(void *data)
|
||||
{
|
||||
tegra20_clk_set_emc_round_callback(NULL, NULL);
|
||||
}
|
||||
|
||||
static void devm_tegra_emc_unreg_clk_notifier(void *data)
|
||||
static void devm_tegra20_emc_unreg_clk_notifier(void *data)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
|
||||
clk_notifier_unregister(emc->clk, &emc->clk_nb);
|
||||
}
|
||||
|
||||
static int tegra_emc_init_clk(struct tegra_emc *emc)
|
||||
static int tegra20_emc_init_clk(struct tegra_emc *emc)
|
||||
{
|
||||
int err;
|
||||
|
||||
tegra20_clk_set_emc_round_callback(emc_round_rate, emc);
|
||||
|
||||
err = devm_add_action_or_reset(emc->dev, devm_tegra_emc_unset_callback,
|
||||
err = devm_add_action_or_reset(emc->dev, devm_tegra20_emc_unset_callback,
|
||||
NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
emc->clk = devm_clk_get(emc->dev, NULL);
|
||||
if (IS_ERR(emc->clk)) {
|
||||
dev_err(emc->dev, "failed to get EMC clock: %pe\n", emc->clk);
|
||||
return PTR_ERR(emc->clk);
|
||||
}
|
||||
if (IS_ERR(emc->clk))
|
||||
return dev_err_probe(emc->dev, PTR_ERR(emc->clk),
|
||||
"failed to get EMC clock\n");
|
||||
|
||||
err = clk_notifier_register(emc->clk, &emc->clk_nb);
|
||||
if (err) {
|
||||
dev_err(emc->dev, "failed to register clk notifier: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
return dev_err_probe(emc->dev, err, "failed to register clk notifier\n");
|
||||
|
||||
err = devm_add_action_or_reset(emc->dev,
|
||||
devm_tegra_emc_unreg_clk_notifier, emc);
|
||||
devm_tegra20_emc_unreg_clk_notifier, emc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
u32 flags)
|
||||
static int tegra20_emc_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
u32 flags)
|
||||
{
|
||||
struct tegra_emc *emc = dev_get_drvdata(dev);
|
||||
struct dev_pm_opp *opp;
|
||||
@@ -1121,8 +1114,8 @@ static int tegra_emc_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
return emc_set_min_rate(emc, rate, EMC_RATE_DEVFREQ);
|
||||
}
|
||||
|
||||
static int tegra_emc_devfreq_get_dev_status(struct device *dev,
|
||||
struct devfreq_dev_status *stat)
|
||||
static int tegra20_emc_devfreq_get_dev_status(struct device *dev,
|
||||
struct devfreq_dev_status *stat)
|
||||
{
|
||||
struct tegra_emc *emc = dev_get_drvdata(dev);
|
||||
|
||||
@@ -1144,13 +1137,13 @@ static int tegra_emc_devfreq_get_dev_status(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct devfreq_dev_profile tegra_emc_devfreq_profile = {
|
||||
static struct devfreq_dev_profile tegra20_emc_devfreq_profile = {
|
||||
.polling_ms = 30,
|
||||
.target = tegra_emc_devfreq_target,
|
||||
.get_dev_status = tegra_emc_devfreq_get_dev_status,
|
||||
.target = tegra20_emc_devfreq_target,
|
||||
.get_dev_status = tegra20_emc_devfreq_get_dev_status,
|
||||
};
|
||||
|
||||
static int tegra_emc_devfreq_init(struct tegra_emc *emc)
|
||||
static int tegra20_emc_devfreq_init(struct tegra_emc *emc)
|
||||
{
|
||||
struct devfreq *devfreq;
|
||||
|
||||
@@ -1172,18 +1165,17 @@ static int tegra_emc_devfreq_init(struct tegra_emc *emc)
|
||||
writel_relaxed(0x00000000, emc->regs + EMC_STAT_LLMC_CONTROL);
|
||||
writel_relaxed(0xffffffff, emc->regs + EMC_STAT_PWR_CLOCK_LIMIT);
|
||||
|
||||
devfreq = devm_devfreq_add_device(emc->dev, &tegra_emc_devfreq_profile,
|
||||
devfreq = devm_devfreq_add_device(emc->dev, &tegra20_emc_devfreq_profile,
|
||||
DEVFREQ_GOV_SIMPLE_ONDEMAND,
|
||||
&emc->ondemand_data);
|
||||
if (IS_ERR(devfreq)) {
|
||||
dev_err(emc->dev, "failed to initialize devfreq: %pe", devfreq);
|
||||
return PTR_ERR(devfreq);
|
||||
}
|
||||
if (IS_ERR(devfreq))
|
||||
return dev_err_probe(emc->dev, PTR_ERR(devfreq),
|
||||
"failed to initialize devfreq\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_probe(struct platform_device *pdev)
|
||||
static int tegra20_emc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_core_opp_params opp_params = {};
|
||||
struct device_node *np;
|
||||
@@ -1199,7 +1191,7 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&emc->rate_lock);
|
||||
emc->clk_nb.notifier_call = tegra_emc_clk_change_notify;
|
||||
emc->clk_nb.notifier_call = tegra20_emc_clk_change_notify;
|
||||
emc->dev = &pdev->dev;
|
||||
|
||||
emc->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
@@ -1210,22 +1202,22 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
np = tegra_emc_find_node_by_ram_code(emc);
|
||||
np = tegra20_emc_find_node_by_ram_code(emc);
|
||||
if (np) {
|
||||
err = tegra_emc_load_timings_from_dt(emc, np);
|
||||
err = tegra20_emc_load_timings_from_dt(emc, np);
|
||||
of_node_put(np);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = devm_request_irq(&pdev->dev, irq, tegra_emc_isr, 0,
|
||||
err = devm_request_irq(&pdev->dev, irq, tegra20_emc_isr, 0,
|
||||
dev_name(&pdev->dev), emc);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tegra_emc_init_clk(emc);
|
||||
err = tegra20_emc_init_clk(emc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1236,10 +1228,10 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
|
||||
platform_set_drvdata(pdev, emc);
|
||||
tegra_emc_rate_requests_init(emc);
|
||||
tegra_emc_debugfs_init(emc);
|
||||
tegra_emc_interconnect_init(emc);
|
||||
tegra_emc_devfreq_init(emc);
|
||||
tegra20_emc_rate_requests_init(emc);
|
||||
tegra20_emc_debugfs_init(emc);
|
||||
tegra20_emc_interconnect_init(emc);
|
||||
tegra20_emc_devfreq_init(emc);
|
||||
|
||||
/*
|
||||
* Don't allow the kernel module to be unloaded. Unloading adds some
|
||||
@@ -1251,22 +1243,22 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id tegra_emc_of_match[] = {
|
||||
static const struct of_device_id tegra20_emc_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra20-emc", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_emc_of_match);
|
||||
MODULE_DEVICE_TABLE(of, tegra20_emc_of_match);
|
||||
|
||||
static struct platform_driver tegra_emc_driver = {
|
||||
.probe = tegra_emc_probe,
|
||||
static struct platform_driver tegra20_emc_driver = {
|
||||
.probe = tegra20_emc_probe,
|
||||
.driver = {
|
||||
.name = "tegra20-emc",
|
||||
.of_match_table = tegra_emc_of_match,
|
||||
.of_match_table = tegra20_emc_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
.sync_state = icc_sync_state,
|
||||
},
|
||||
};
|
||||
module_platform_driver(tegra_emc_driver);
|
||||
module_platform_driver(tegra20_emc_driver);
|
||||
|
||||
MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
|
||||
MODULE_DESCRIPTION("NVIDIA Tegra20 EMC driver");
|
||||
|
||||
@@ -413,7 +413,7 @@ static int emc_seq_update_timing(struct tegra_emc *emc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t tegra_emc_isr(int irq, void *data)
|
||||
static irqreturn_t tegra30_emc_isr(int irq, void *data)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
u32 intmask = EMC_REFRESH_OVERFLOW_INT;
|
||||
@@ -1228,7 +1228,7 @@ static long emc_round_rate(unsigned long rate,
|
||||
return timing->rate;
|
||||
}
|
||||
|
||||
static void tegra_emc_rate_requests_init(struct tegra_emc *emc)
|
||||
static void tegra30_emc_rate_requests_init(struct tegra_emc *emc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -1330,7 +1330,7 @@ static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
|
||||
* valid range.
|
||||
*/
|
||||
|
||||
static bool tegra_emc_validate_rate(struct tegra_emc *emc, unsigned long rate)
|
||||
static bool tegra30_emc_validate_rate(struct tegra_emc *emc, unsigned long rate)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -1341,7 +1341,7 @@ static bool tegra_emc_validate_rate(struct tegra_emc *emc, unsigned long rate)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int tegra_emc_debug_available_rates_show(struct seq_file *s, void *data)
|
||||
static int tegra30_emc_debug_available_rates_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct tegra_emc *emc = s->private;
|
||||
const char *prefix = "";
|
||||
@@ -1356,9 +1356,9 @@ static int tegra_emc_debug_available_rates_show(struct seq_file *s, void *data)
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(tegra_emc_debug_available_rates);
|
||||
DEFINE_SHOW_ATTRIBUTE(tegra30_emc_debug_available_rates);
|
||||
|
||||
static int tegra_emc_debug_min_rate_get(void *data, u64 *rate)
|
||||
static int tegra30_emc_debug_min_rate_get(void *data, u64 *rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
|
||||
@@ -1367,12 +1367,12 @@ static int tegra_emc_debug_min_rate_get(void *data, u64 *rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
static int tegra30_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
int err;
|
||||
|
||||
if (!tegra_emc_validate_rate(emc, rate))
|
||||
if (!tegra30_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
@@ -1384,11 +1384,11 @@ static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(tegra_emc_debug_min_rate_fops,
|
||||
tegra_emc_debug_min_rate_get,
|
||||
tegra_emc_debug_min_rate_set, "%llu\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(tegra30_emc_debug_min_rate_fops,
|
||||
tegra30_emc_debug_min_rate_get,
|
||||
tegra30_emc_debug_min_rate_set, "%llu\n");
|
||||
|
||||
static int tegra_emc_debug_max_rate_get(void *data, u64 *rate)
|
||||
static int tegra30_emc_debug_max_rate_get(void *data, u64 *rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
|
||||
@@ -1397,12 +1397,12 @@ static int tegra_emc_debug_max_rate_get(void *data, u64 *rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
static int tegra30_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
int err;
|
||||
|
||||
if (!tegra_emc_validate_rate(emc, rate))
|
||||
if (!tegra30_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
@@ -1414,11 +1414,11 @@ static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(tegra_emc_debug_max_rate_fops,
|
||||
tegra_emc_debug_max_rate_get,
|
||||
tegra_emc_debug_max_rate_set, "%llu\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(tegra30_emc_debug_max_rate_fops,
|
||||
tegra30_emc_debug_max_rate_get,
|
||||
tegra30_emc_debug_max_rate_set, "%llu\n");
|
||||
|
||||
static void tegra_emc_debugfs_init(struct tegra_emc *emc)
|
||||
static void tegra30_emc_debugfs_init(struct tegra_emc *emc)
|
||||
{
|
||||
struct device *dev = emc->dev;
|
||||
unsigned int i;
|
||||
@@ -1451,11 +1451,11 @@ static void tegra_emc_debugfs_init(struct tegra_emc *emc)
|
||||
emc->debugfs.root = debugfs_create_dir("emc", NULL);
|
||||
|
||||
debugfs_create_file("available_rates", 0444, emc->debugfs.root,
|
||||
emc, &tegra_emc_debug_available_rates_fops);
|
||||
emc, &tegra30_emc_debug_available_rates_fops);
|
||||
debugfs_create_file("min_rate", 0644, emc->debugfs.root,
|
||||
emc, &tegra_emc_debug_min_rate_fops);
|
||||
emc, &tegra30_emc_debug_min_rate_fops);
|
||||
debugfs_create_file("max_rate", 0644, emc->debugfs.root,
|
||||
emc, &tegra_emc_debug_max_rate_fops);
|
||||
emc, &tegra30_emc_debug_max_rate_fops);
|
||||
}
|
||||
|
||||
static inline struct tegra_emc *
|
||||
@@ -1518,7 +1518,7 @@ static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
||||
static int tegra30_emc_interconnect_init(struct tegra_emc *emc)
|
||||
{
|
||||
const struct tegra_mc_soc *soc = emc->mc->soc;
|
||||
struct icc_node *node;
|
||||
@@ -1534,10 +1534,8 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
||||
|
||||
/* create External Memory Controller node */
|
||||
node = icc_node_create(TEGRA_ICC_EMC);
|
||||
if (IS_ERR(node)) {
|
||||
err = PTR_ERR(node);
|
||||
goto err_msg;
|
||||
}
|
||||
if (IS_ERR(node))
|
||||
return PTR_ERR(node);
|
||||
|
||||
node->name = "External Memory Controller";
|
||||
icc_node_add(node, &emc->provider);
|
||||
@@ -1565,56 +1563,51 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
|
||||
|
||||
remove_nodes:
|
||||
icc_nodes_remove(&emc->provider);
|
||||
err_msg:
|
||||
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
|
||||
|
||||
return err;
|
||||
return dev_err_probe(emc->dev, err, "failed to initialize ICC\n");
|
||||
}
|
||||
|
||||
static void devm_tegra_emc_unset_callback(void *data)
|
||||
static void devm_tegra30_emc_unset_callback(void *data)
|
||||
{
|
||||
tegra20_clk_set_emc_round_callback(NULL, NULL);
|
||||
}
|
||||
|
||||
static void devm_tegra_emc_unreg_clk_notifier(void *data)
|
||||
static void devm_tegra30_emc_unreg_clk_notifier(void *data)
|
||||
{
|
||||
struct tegra_emc *emc = data;
|
||||
|
||||
clk_notifier_unregister(emc->clk, &emc->clk_nb);
|
||||
}
|
||||
|
||||
static int tegra_emc_init_clk(struct tegra_emc *emc)
|
||||
static int tegra30_emc_init_clk(struct tegra_emc *emc)
|
||||
{
|
||||
int err;
|
||||
|
||||
tegra20_clk_set_emc_round_callback(emc_round_rate, emc);
|
||||
|
||||
err = devm_add_action_or_reset(emc->dev, devm_tegra_emc_unset_callback,
|
||||
err = devm_add_action_or_reset(emc->dev, devm_tegra30_emc_unset_callback,
|
||||
NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
emc->clk = devm_clk_get(emc->dev, NULL);
|
||||
if (IS_ERR(emc->clk)) {
|
||||
dev_err(emc->dev, "failed to get EMC clock: %pe\n", emc->clk);
|
||||
return PTR_ERR(emc->clk);
|
||||
}
|
||||
if (IS_ERR(emc->clk))
|
||||
return dev_err_probe(emc->dev, PTR_ERR(emc->clk),
|
||||
"failed to get EMC clock\n");
|
||||
|
||||
err = clk_notifier_register(emc->clk, &emc->clk_nb);
|
||||
if (err) {
|
||||
dev_err(emc->dev, "failed to register clk notifier: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
return dev_err_probe(emc->dev, err, "failed to register clk notifier\n");
|
||||
|
||||
err = devm_add_action_or_reset(emc->dev,
|
||||
devm_tegra_emc_unreg_clk_notifier, emc);
|
||||
devm_tegra30_emc_unreg_clk_notifier, emc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_probe(struct platform_device *pdev)
|
||||
static int tegra30_emc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_core_opp_params opp_params = {};
|
||||
struct device_node *np;
|
||||
@@ -1655,14 +1648,12 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
|
||||
emc->irq = err;
|
||||
|
||||
err = devm_request_irq(&pdev->dev, emc->irq, tegra_emc_isr, 0,
|
||||
err = devm_request_irq(&pdev->dev, emc->irq, tegra30_emc_isr, 0,
|
||||
dev_name(&pdev->dev), emc);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to request irq: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
return dev_err_probe(&pdev->dev, err, "failed to request irq\n");
|
||||
|
||||
err = tegra_emc_init_clk(emc);
|
||||
err = tegra30_emc_init_clk(emc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1673,9 +1664,9 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
|
||||
platform_set_drvdata(pdev, emc);
|
||||
tegra_emc_rate_requests_init(emc);
|
||||
tegra_emc_debugfs_init(emc);
|
||||
tegra_emc_interconnect_init(emc);
|
||||
tegra30_emc_rate_requests_init(emc);
|
||||
tegra30_emc_debugfs_init(emc);
|
||||
tegra30_emc_interconnect_init(emc);
|
||||
|
||||
/*
|
||||
* Don't allow the kernel module to be unloaded. Unloading adds some
|
||||
@@ -1687,7 +1678,7 @@ static int tegra_emc_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_suspend(struct device *dev)
|
||||
static int tegra30_emc_suspend(struct device *dev)
|
||||
{
|
||||
struct tegra_emc *emc = dev_get_drvdata(dev);
|
||||
int err;
|
||||
@@ -1708,7 +1699,7 @@ static int tegra_emc_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_emc_resume(struct device *dev)
|
||||
static int tegra30_emc_resume(struct device *dev)
|
||||
{
|
||||
struct tegra_emc *emc = dev_get_drvdata(dev);
|
||||
|
||||
@@ -1720,28 +1711,28 @@ static int tegra_emc_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops tegra_emc_pm_ops = {
|
||||
.suspend = tegra_emc_suspend,
|
||||
.resume = tegra_emc_resume,
|
||||
static const struct dev_pm_ops tegra30_emc_pm_ops = {
|
||||
.suspend = tegra30_emc_suspend,
|
||||
.resume = tegra30_emc_resume,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_emc_of_match[] = {
|
||||
static const struct of_device_id tegra30_emc_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra30-emc", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_emc_of_match);
|
||||
MODULE_DEVICE_TABLE(of, tegra30_emc_of_match);
|
||||
|
||||
static struct platform_driver tegra_emc_driver = {
|
||||
.probe = tegra_emc_probe,
|
||||
static struct platform_driver tegra30_emc_driver = {
|
||||
.probe = tegra30_emc_probe,
|
||||
.driver = {
|
||||
.name = "tegra30-emc",
|
||||
.of_match_table = tegra_emc_of_match,
|
||||
.pm = &tegra_emc_pm_ops,
|
||||
.of_match_table = tegra30_emc_of_match,
|
||||
.pm = &tegra30_emc_pm_ops,
|
||||
.suppress_bind_attrs = true,
|
||||
.sync_state = icc_sync_state,
|
||||
},
|
||||
};
|
||||
module_platform_driver(tegra_emc_driver);
|
||||
module_platform_driver(tegra30_emc_driver);
|
||||
|
||||
MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
|
||||
MODULE_DESCRIPTION("NVIDIA Tegra30 EMC driver");
|
||||
|
||||
Reference in New Issue
Block a user