diff options
Diffstat (limited to 'drivers/cpufreq/imx6q-cpufreq.c')
| -rw-r--r-- | drivers/cpufreq/imx6q-cpufreq.c | 52 | 
1 files changed, 35 insertions, 17 deletions
| diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index b2ff423ad7f8..8cfee0ab804b 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -12,6 +12,7 @@  #include <linux/cpu_cooling.h>  #include <linux/err.h>  #include <linux/module.h> +#include <linux/nvmem-consumer.h>  #include <linux/of.h>  #include <linux/of_address.h>  #include <linux/pm_opp.h> @@ -290,20 +291,32 @@ put_node:  #define OCOTP_CFG3_6ULL_SPEED_792MHZ	0x2  #define OCOTP_CFG3_6ULL_SPEED_900MHZ	0x3 -static void imx6ul_opp_check_speed_grading(struct device *dev) +static int imx6ul_opp_check_speed_grading(struct device *dev)  { -	struct device_node *np; -	void __iomem *base;  	u32 val; +	int ret = 0; -	np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp"); -	if (!np) -		return; +	if (of_find_property(dev->of_node, "nvmem-cells", NULL)) { +		ret = nvmem_cell_read_u32(dev, "speed_grade", &val); +		if (ret) +			return ret; +	} else { +		struct device_node *np; +		void __iomem *base; + +		np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp"); +		if (!np) +			return -ENOENT; + +		base = of_iomap(np, 0); +		of_node_put(np); +		if (!base) { +			dev_err(dev, "failed to map ocotp\n"); +			return -EFAULT; +		} -	base = of_iomap(np, 0); -	if (!base) { -		dev_err(dev, "failed to map ocotp\n"); -		goto put_node; +		val = readl_relaxed(base + OCOTP_CFG3); +		iounmap(base);  	}  	/* @@ -314,7 +327,6 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)  	 * 2b'11: 900000000Hz on i.MX6ULL only;  	 * We need to set the max speed of ARM according to fuse map.  	 */ -	val = readl_relaxed(base + OCOTP_CFG3);  	val >>= OCOTP_CFG3_SPEED_SHIFT;  	val &= 0x3; @@ -334,9 +346,7 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)  				dev_warn(dev, "failed to disable 900MHz OPP\n");  	} -	iounmap(base); -put_node: -	of_node_put(np); +	return ret;  }  static int imx6q_cpufreq_probe(struct platform_device *pdev) @@ -394,10 +404,18 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)  	}  	if (of_machine_is_compatible("fsl,imx6ul") || -	    of_machine_is_compatible("fsl,imx6ull")) -		imx6ul_opp_check_speed_grading(cpu_dev); -	else +	    of_machine_is_compatible("fsl,imx6ull")) { +		ret = imx6ul_opp_check_speed_grading(cpu_dev); +		if (ret == -EPROBE_DEFER) +			return ret; +		if (ret) { +			dev_err(cpu_dev, "failed to read ocotp: %d\n", +				ret); +			return ret; +		} +	} else {  		imx6q_opp_check_speed_grading(cpu_dev); +	}  	/* Because we have added the OPPs here, we must free them */  	free_opp = true; |