Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 851a205f authored by Odelu Kukatla's avatar Odelu Kukatla Committed by Gerrit - the friendly Code Review server
Browse files

clk: qcom: clk-cpu-osm: Add OSM clock driver support for TRINKET



TRINKET has 4-4 cores configuration, add the necessary changes
to support 4-4 cores configuration.

Change-Id: Iaf74023d6ebd399325170f2216c4df5e22f9fb69
Signed-off-by: default avatarOdelu Kukatla <okukatla@codeaurora.org>
parent 409af4b4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -11,7 +11,8 @@ Properties:
	Value type: <string>
	Definition: must be "qcom,clk-cpu-osm" or "qcom,clk-cpu-osm-sdmshrike"
			or "qcom,clk-cpu-osm-sm6150" or
			"qcom,clk-cpu-osm-sdmmagpie".
			"qcom,clk-cpu-osm-sdmmagpie" or
			"qcom,clk-cpu-osm-trinket".

- reg
	Usage:      required
+83 −35
Original line number Diff line number Diff line
/*
 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/err.h>
#include <asm/smp_plat.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
@@ -41,6 +42,7 @@
#define OSM_INIT_RATE			300000000UL
#define XO_RATE				19200000UL
#define OSM_TABLE_SIZE			40
#define OSM_TABLE_REDUCED_SIZE		12
#define SINGLE_CORE_COUNT		1
#define CORE_COUNT_VAL(val)		((val & GENMASK(18, 16)) >> 16)

@@ -76,6 +78,7 @@ struct clk_osm {
	u32 num_entries;
	u32 cluster_num;
	u32 core_num;
	u32 osm_table_size;
	u64 total_cycle_counter;
	u32 prev_cycle_counter;
	unsigned long rate;
@@ -85,6 +88,7 @@ struct clk_osm {
static bool is_sdmshrike;
static bool is_sm6150;
static bool is_sdmmagpie;
static bool is_trinket;

static inline struct clk_osm *to_clk_osm(struct clk_hw *_hw)
{
@@ -301,6 +305,7 @@ static struct clk_init_data osm_clks_init[] = {

static struct clk_osm l3_clk = {
	.cluster_num = 0,
	.osm_table_size = OSM_TABLE_SIZE,
	.hw.init = &osm_clks_init[0],
};

@@ -312,6 +317,7 @@ static DEFINE_CLK_VOTER(l3_gpu_vote_clk, l3_clk, 0);

static struct clk_osm pwrcl_clk = {
	.cluster_num = 1,
	.osm_table_size = OSM_TABLE_SIZE,
	.hw.init = &osm_clks_init[1],
};

@@ -389,6 +395,7 @@ static struct clk_osm cpu5_pwrcl_clk = {

static struct clk_osm perfcl_clk = {
	.cluster_num = 2,
	.osm_table_size = OSM_TABLE_SIZE,
	.hw.init = &osm_clks_init[2],
};

@@ -442,6 +449,7 @@ static struct clk_osm cpu7_perfcl_clk = {

static struct clk_osm perfpcl_clk = {
	.cluster_num = 3,
	.osm_table_size = OSM_TABLE_SIZE,
	.hw.init = &osm_clks_init[3],
};

@@ -512,7 +520,11 @@ static struct clk_osm *logical_cpu_to_clk(int cpu)
		}

		hwid = of_read_number(cell, of_n_addr_cells(cpu_node));
		if (is_trinket)
			hwid = get_logical_index(hwid);
		else
			hwid = (hwid >> 8) & 0xff;

		of_node_put(cpu_node);
		if (hwid >= ARRAY_SIZE(clk_cpu_map)) {
			pr_err("unsupported CPU number - %d (hw_id - %llu)\n",
@@ -643,11 +655,11 @@ static int osm_cpufreq_cpu_init(struct cpufreq_policy *policy)
	parent = to_clk_osm(p_hw);
	c->vbase = parent->vbase;

	table = kcalloc(OSM_TABLE_SIZE + 1, sizeof(*table), GFP_KERNEL);
	table = kcalloc(parent->osm_table_size + 1, sizeof(*table), GFP_KERNEL);
	if (!table)
		return -ENOMEM;

	for (i = 0; i < OSM_TABLE_SIZE; i++) {
	for (i = 0; i < parent->osm_table_size; i++) {
		u32 data, src, div, lval, core_count;

		data = clk_osm_read_reg(c, FREQ_REG + i * OSM_REG_SIZE);
@@ -876,6 +888,7 @@ static void populate_opp_table(struct platform_device *pdev)
					dev_name(cpu_dev));
	}

	if (!is_trinket)
		populate_l3_opp_table(np, "l3-devs");
}

@@ -920,9 +933,9 @@ static u64 clk_osm_get_cpu_cycle_counter(int cpu)

static int clk_osm_read_lut(struct platform_device *pdev, struct clk_osm *c)
{
	u32 data, src, lval, i, j = OSM_TABLE_SIZE;
	u32 data, src, lval, i, j = c->osm_table_size;

	for (i = 0; i < OSM_TABLE_SIZE; i++) {
	for (i = 0; i < c->osm_table_size; i++) {
		data = clk_osm_read_reg(c, FREQ_REG + i * OSM_REG_SIZE);
		src = ((data & GENMASK(31, 30)) >> 30);
		lval = (data & GENMASK(7, 0));
@@ -942,7 +955,8 @@ static int clk_osm_read_lut(struct platform_device *pdev, struct clk_osm *c)
			 c->osm_table[i].virtual_corner,
			 c->osm_table[i].open_loop_volt);

		if (i > 0 && j == OSM_TABLE_SIZE && c->osm_table[i].frequency ==
		if (i > 0 && j == c->osm_table_size &&
				c->osm_table[i].frequency ==
				c->osm_table[i - 1].frequency)
			j = i;
	}
@@ -965,6 +979,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
{
	struct resource *res;

	if (!is_trinket) {
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
							"osm_l3_base");
		if (!res) {
@@ -974,12 +989,14 @@ static int clk_osm_resources_init(struct platform_device *pdev)
		}

		l3_clk.pbase = (unsigned long)res->start;
	l3_clk.vbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
		l3_clk.vbase = devm_ioremap(&pdev->dev, res->start,
							resource_size(res));

		if (!l3_clk.vbase) {
			dev_err(&pdev->dev, "Unable to map osm_l3_base base\n");
			return -ENOMEM;
		}
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						"osm_pwrcl_base");
@@ -1014,7 +1031,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
		return -ENOMEM;
	}

	if (is_sdmshrike || is_sm6150 || is_sdmmagpie)
	if (is_sdmshrike || is_sm6150 || is_sdmmagpie || is_trinket)
		return 0;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -1056,6 +1073,25 @@ static void clk_cpu_osm_driver_sm6150_fixup(void)
	clk_cpu_map[7] = &cpu7_perfcl_clk;
}

static void clk_cpu_osm_driver_trinket_fixup(void)
{
	pwrcl_clk.osm_table_size = OSM_TABLE_REDUCED_SIZE;
	perfcl_clk.osm_table_size = OSM_TABLE_REDUCED_SIZE;

	osm_qcom_clk_hws[L3_CLUSTER0_VOTE_CLK] = NULL,
	osm_qcom_clk_hws[L3_CLUSTER1_VOTE_CLK] = NULL,
	osm_qcom_clk_hws[L3_CLUSTER2_VOTE_CLK] = NULL,
	osm_qcom_clk_hws[L3_MISC_VOTE_CLK] = NULL,
	osm_qcom_clk_hws[L3_GPU_VOTE_CLK] = NULL,
	osm_qcom_clk_hws[L3_CLK] = NULL,
	osm_qcom_clk_hws[CPU7_PERFPCL_CLK] = NULL,
	osm_qcom_clk_hws[PERFPCL_CLK] = NULL,
	osm_qcom_clk_hws[CPU4_PWRCL_CLK] = NULL,
	osm_qcom_clk_hws[CPU5_PWRCL_CLK] = NULL,
	osm_qcom_clk_hws[CPU7_PERFCL_CLK] = &cpu7_perfcl_clk.hw;
	clk_cpu_map[7] = &cpu7_perfcl_clk;
}

static void clk_cpu_osm_driver_sdmshrike_fixup(void)
{
	osm_qcom_clk_hws[CPU7_PERFPCL_CLK] = NULL;
@@ -1077,6 +1113,9 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
		.get_cpu_cycle_counter = clk_osm_get_cpu_cycle_counter,
	};

	is_trinket = of_device_is_compatible(pdev->dev.of_node,
				"qcom,clk-cpu-osm-trinket");

	is_sdmmagpie = of_device_is_compatible(pdev->dev.of_node,
				"qcom,clk-cpu-osm-sdmmagpie");

@@ -1089,6 +1128,8 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
		clk_cpu_osm_driver_sdmshrike_fixup();
	else if (is_sm6150 || is_sdmmagpie)
		clk_cpu_osm_driver_sm6150_fixup();
	else if (is_trinket)
		clk_cpu_osm_driver_trinket_fixup();

	clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
								GFP_KERNEL);
@@ -1119,12 +1160,14 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
	if (val & BIT(0))
		perfcl_clk.per_core_dcvs = true;

	if (!is_trinket) {
		rc = clk_osm_read_lut(pdev, &l3_clk);
		if (rc) {
			dev_err(&pdev->dev, "Unable to read OSM LUT for L3, rc=%d\n",
				rc);
			return rc;
		}
	}

	rc = clk_osm_read_lut(pdev, &pwrcl_clk);
	if (rc) {
@@ -1140,7 +1183,7 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
		return rc;
	}

	if (!is_sdmshrike && !is_sm6150 && !is_sdmmagpie) {
	if (!is_sdmshrike && !is_sm6150 && !is_sdmmagpie && !is_trinket) {
		rc = clk_osm_read_lut(pdev, &perfpcl_clk);
		if (rc) {
			dev_err(&pdev->dev, "Unable to read OSM LUT for perf plus cluster, rc=%d\n",
@@ -1149,9 +1192,11 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
		}
	}

	if (!is_trinket)
		spin_lock_init(&l3_clk.lock);
	spin_lock_init(&pwrcl_clk.lock);
	spin_lock_init(&perfcl_clk.lock);
	if (!is_trinket)
		spin_lock_init(&perfpcl_clk.lock);

	/* Register OSM l3, pwr and perf clocks with Clock Framework */
@@ -1177,6 +1222,7 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)

	get_online_cpus();

	if (!is_trinket) {
		WARN(clk_prepare_enable(l3_cluster0_vote_clk.hw.clk),
			"clk: Failed to enable cluster0 clock for L3\n");
		WARN(clk_prepare_enable(l3_cluster1_vote_clk.hw.clk),
@@ -1187,6 +1233,7 @@ static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
			"clk: Failed to enable misc clock for L3\n");
		WARN(clk_prepare_enable(l3_gpu_vote_clk.hw.clk),
			"clk: Failed to enable gpu clock for L3\n");
	}

	populate_opp_table(pdev);

@@ -1216,6 +1263,7 @@ static const struct of_device_id match_table[] = {
	{ .compatible = "qcom,clk-cpu-osm" },
	{ .compatible = "qcom,clk-cpu-osm-sm6150" },
	{ .compatible = "qcom,clk-cpu-osm-sdmmagpie" },
	{ .compatible = "qcom,clk-cpu-osm-trinket" },
	{ .compatible = "qcom,clk-cpu-osm-sdmshrike" },
	{}
};