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

Commit e26d16ab authored by Patrick Daly's avatar Patrick Daly
Browse files

msm: clock-9630: Add clock driver device for 9630



Allow expressing hw version differences in devicetree, rather
than relying on socinfo.

Change-Id: I13415305c7c82a20211dcc8815b0366a3dbb0ea8
Signed-off-by: default avatarPatrick Daly <pdaly@codeaurora.org>
parent 2fb18674
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -91,7 +91,6 @@
			regulator-min-microvolt = <1>;
			regulator-max-microvolt = <7>;
			qcom,use-voltage-corner;
			qcom,consumer-supplies = "vdd_dig", "";
		};
		pmd9635_l3_corner_ao: regulator-l3-corner-ao {
			compatible = "qcom,rpm-smd-regulator";
@@ -100,7 +99,6 @@
			regulator-min-microvolt = <1>;
			regulator-max-microvolt = <7>;
			qcom,use-voltage-corner;
			qcom,consumer-supplies = "vdd_dig_ao", "";
		};
		pmd9635_l3_floor_corner: regulator-l3-floor-corner {
			compatible = "qcom,rpm-smd-regulator";
+10 −0
Original line number Diff line number Diff line
@@ -715,6 +715,16 @@
		qcom,slope = <2901 2846 3200 3200 3200>;
	};

	clock_gcc: qcom,gcc@fc400000 {
		compatible = "qcom,gcc-9630";
		reg = <0xfc400000 0x4000>,
			<0xf9011000 0x1C>,
			<0xf9008018 0x28>;
		reg-names = "cc_base", "meas", "apcs_base";
		vdd_dig-supply = <&pmd9635_l3_corner>;
		vdd_dig_ao-supply = <&pmd9635_l3_corner_ao>;
	};

	qcom,clock-a7@f9010008 {
		compatible = "qcom,clock-a7-9630";
		reg = <0xf9010008 0x8>;
+0 −1
Original line number Diff line number Diff line
@@ -51,7 +51,6 @@ void __init mdm9630_add_drivers(void)
	msm_rpm_driver_init();
	rpm_smd_regulator_driver_init();
	msm_spm_device_init();
	msm_clock_init(&mdm9630_clock_init_data);
}

void __init mdm9630_reserve(void)
+101 −47
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/rpm-smd-regulator.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/iopoll.h>
#include <linux/clk/msm-clk.h>
#include <soc/qcom/clock-alpha-pll.h>
@@ -28,14 +30,8 @@
#include <soc/qcom/clock-rpm.h>
#include <soc/qcom/clock-voter.h>

#include <soc/qcom/socinfo.h>

#include "clock.h"

enum {
	GCC_BASE,
	LPASS_BASE,
	APCS_GLB_BASE,
	APCS_GCC_BASE,
	APCS_ACC_BASE,
	N_BASES,
@@ -2197,7 +2193,7 @@ static struct clk_lookup msm_clocks_9630[] = {
	CLK_LOOKUP("", qpic_a_clk.c, ""),
};

static void __init reg_init(void)
static void reg_init(void)
{
	u32 regval;

@@ -2211,7 +2207,7 @@ static void __init reg_init(void)
	writel_relaxed(regval, GCC_REG_BASE(APCS_CLOCK_BRANCH_ENA_VOTE));
}

static void __init mdm9630_clock_post_init(void)
static void mdm9630_clock_post_init(void)
{
	/*
	 * Hold an active set vote for CXO; this is because CXO is expected
@@ -2226,59 +2222,117 @@ static void __init mdm9630_clock_post_init(void)
	clk_prepare_enable(&pnoc_keepalive_a_clk.c);
}

#define GCC_CC_PHYS		0xFC400000
#define GCC_CC_SIZE		SZ_8K
static int mdm9630_clock_pre_init(void)
{
	int rc;
	rc = enable_rpm_scaling();
	if (rc)
		return rc;

	reg_init();
	return 0;
}

#define LPASS_CC_PHYS		0xFE000000
#define LPASS_CC_SIZE		SZ_256K
/* Please note that the order of reg-names is important */
static int get_memory(struct platform_device *pdev)
{
	int i, count;
	const char *str;
	struct resource *res;
	struct device *dev = &pdev->dev;

	count = of_property_count_strings(dev->of_node, "reg-names");
	if (count != N_BASES) {
		dev_err(dev, "missing reg-names property, expected %d strings\n",
				N_BASES);
		return -EINVAL;
	}

#define APCS_GLB_PHYS		0xF9010000
#define APCS_GLB_SIZE		0x38
	for (i = 0; i < count; i++) {
		of_property_read_string_index(dev->of_node, "reg-names", i,
						&str);
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, str);
		if (!res) {
			dev_err(dev, "Unable to retrieve register base.\n");
			return -ENOMEM;
		}

#define APCS_GCC_PHYS		0xF9011000
#define APCS_GCC_SIZE		0x1C
		virt_bases[i] = devm_ioremap(dev, res->start,
							resource_size(res));
		if (!virt_bases[i]) {
			dev_err(dev, "Failed to map in CC registers.\n");
			return -ENOMEM;
		}
	}

#define APCS_ACC_PHYS		0xF9008018
#define APCS_ACC_SIZE		0x28
	return 0;
}

static void __init mdm9630_clock_pre_init(void)
static int get_regulators(struct device *dev)
{
	virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
	if (!virt_bases[GCC_BASE])
		panic("clock-9630: Unable to ioremap GCC memory!");
	struct regulator *r;

	virt_bases[LPASS_BASE] = ioremap(LPASS_CC_PHYS, LPASS_CC_SIZE);
	if (!virt_bases[LPASS_BASE])
		panic("clock-8226: Unable to ioremap LPASS_CC memory!");
	r = vdd_dig.regulator[0] = devm_regulator_get(dev, "vdd_dig");
	if (IS_ERR(r)) {
		if (PTR_ERR(r) != -EPROBE_DEFER)
			dev_err(dev, "Unable to get the vdd_dig regulator!");
		return PTR_ERR(r);
	}

	virt_bases[APCS_GLB_BASE] = ioremap(APCS_GLB_PHYS, APCS_GLB_SIZE);
	if (!virt_bases[APCS_GLB_BASE])
		panic("clock-9630: Unable to ioremap APCS_GLB memory!");
	r = vdd_dig_ao.regulator[0] = devm_regulator_get(dev, "vdd_dig_ao");
	if (IS_ERR(r)) {
		if (PTR_ERR(r) != -EPROBE_DEFER)
			dev_err(dev, "Unable to get the vdd_dig_ao regulator!");
		return PTR_ERR(r);
	}
	return 0;
}

	virt_bases[APCS_GCC_BASE] = ioremap(APCS_GCC_PHYS, APCS_GCC_SIZE);
	if (!virt_bases[APCS_GCC_BASE])
		panic("clock-9630: Unable to ioremap APCS_GCC memory!");
static int gcc_probe(struct platform_device *pdev)
{
	int rc;
	struct device *dev = &pdev->dev;

	virt_bases[APCS_ACC_BASE] = ioremap(APCS_ACC_PHYS, APCS_ACC_SIZE);
	if (!virt_bases[APCS_ACC_BASE])
		panic("clock-9630: Unable to ioremap APCS_PLL memory!");
	rc = get_regulators(dev);
	if (rc)
		return rc;

	vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
	if (IS_ERR(vdd_dig.regulator[0]))
		panic("clock-9630: Unable to get the vdd_dig regulator!");
	rc = get_memory(pdev);
	if (rc)
		return rc;

	vdd_dig_ao.regulator[0] = regulator_get(NULL, "vdd_dig_ao");
	if (IS_ERR(vdd_dig_ao.regulator[0]))
		panic("clock-9630: Unable to get the vdd_dig_ao regulator!");
	rc = mdm9630_clock_pre_init();
	if (rc)
		return rc;

	enable_rpm_scaling();
	rc =  msm_clock_register(msm_clocks_9630, ARRAY_SIZE(msm_clocks_9630));
	if (rc)
		return rc;

	reg_init();
	mdm9630_clock_post_init();
	return 0;
}

struct clock_init_data mdm9630_clock_init_data __initdata = {
	.table = msm_clocks_9630,
	.size = ARRAY_SIZE(msm_clocks_9630),
	.pre_init = mdm9630_clock_pre_init,
	.post_init = mdm9630_clock_post_init,
static struct of_device_id gcc_match_table[] = {
	{ .compatible = "qcom,gcc-9630" },
	{}
};

static struct platform_driver gcc_driver = {
	.probe = gcc_probe,
	.driver = {
		.name = "qcom,gcc-9630",
		.of_match_table = gcc_match_table,
		.owner = THIS_MODULE,
	},
};

static bool initialized;
int __init msm_gcc_9630_init(void)
{
	if (initialized)
		return true;
	initialized  = true;
	return platform_driver_register(&gcc_driver);
}
arch_initcall(msm_gcc_9630_init);
+0 −2
Original line number Diff line number Diff line
@@ -55,8 +55,6 @@ extern struct clock_init_data apq8084_clock_init_data;
extern struct clock_init_data apq8084_rumi_clock_init_data;
extern struct clock_init_data mpq8092_clock_init_data;
extern struct clock_init_data mpq8092_rumi_clock_init_data;
extern struct clock_init_data mdm9630_clock_init_data;
extern struct clock_init_data msmkrypton_clock_init_data;
extern struct clock_init_data msmsamarium_clock_init_data;
extern struct clock_init_data msmsamarium_rumi_clock_init_data;
extern struct clock_init_data fsm9900_clock_init_data;