Message ID | 20190606142255.29454-5-nsaenzjulienne@suse.de (mailing list archive) |
---|---|
State | Awaiting Upstream, archived |
Headers | show |
Series | cpufreq support for Raspberry Pi | expand |
Quoting Nicolas Saenz Julienne (2019-06-06 07:22:56) > diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c b/drivers/cpufreq/raspberrypi-cpufreq.c > new file mode 100644 > index 000000000000..99b59d5a50aa > --- /dev/null > +++ b/drivers/cpufreq/raspberrypi-cpufreq.c [...] > + > +/* > + * Since the driver depends on clk-raspberrypi, which may return EPROBE_DEFER, > + * all the activity is performed in the probe, which may be defered as well. > + */ > +static struct platform_driver raspberrypi_cpufreq_driver = { > + .driver = { > + .name = "raspberrypi-cpufreq", > + }, > + .probe = raspberrypi_cpufreq_probe, > + .remove = raspberrypi_cpufreq_remove, > +}; > +module_platform_driver(raspberrypi_cpufreq_driver); How does this driver probe? Do you have a node in DT named raspberrypi-cpufreq that matches and probes this? I would think this would follow the drivers/cpufreq/cpufreq-dt-platdev.c design where it's an initcall that probes the board compatible string. Or, if it depends on clk-raspberrypi probing, maybe it could create the platform device in that drivers probe function. > + > +MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de"); > +MODULE_DESCRIPTION("Raspberry Pi cpufreq driver"); > +MODULE_LICENSE("GPL"); > +MODULE_ALIAS("platform:raspberrypi-cpufreq"); I don't think the module alias is needed anymore.
Hi Stephen, Thanks for the review. On Thu, 2019-06-06 at 10:09 -0700, Stephen Boyd wrote: > Quoting Nicolas Saenz Julienne (2019-06-06 07:22:56) > > diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c > > b/drivers/cpufreq/raspberrypi-cpufreq.c > > new file mode 100644 > > index 000000000000..99b59d5a50aa > > --- /dev/null > > +++ b/drivers/cpufreq/raspberrypi-cpufreq.c > [...] > > + > > +/* > > + * Since the driver depends on clk-raspberrypi, which may return > > EPROBE_DEFER, > > + * all the activity is performed in the probe, which may be defered as > > well. > > + */ > > +static struct platform_driver raspberrypi_cpufreq_driver = { > > + .driver = { > > + .name = "raspberrypi-cpufreq", > > + }, > > + .probe = raspberrypi_cpufreq_probe, > > + .remove = raspberrypi_cpufreq_remove, > > +}; > > +module_platform_driver(raspberrypi_cpufreq_driver); > > How does this driver probe? Do you have a node in DT named > raspberrypi-cpufreq that matches and probes this? I would think this > would follow the drivers/cpufreq/cpufreq-dt-platdev.c design where it's > an initcall that probes the board compatible string. > > Or, if it depends on clk-raspberrypi probing, maybe it could create the > platform device in that drivers probe function. Well you just reviewed that patch :) > > + > > +MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de"); > > +MODULE_DESCRIPTION("Raspberry Pi cpufreq driver"); > > +MODULE_LICENSE("GPL"); > > +MODULE_ALIAS("platform:raspberrypi-cpufreq"); > > I don't think the module alias is needed anymore. That's surprising. I remember the driver not being loaded by udev without it. Regards, Nicolas
Quoting Nicolas Saenz Julienne (2019-06-06 10:22:16) > Hi Stephen, > Thanks for the review. > > On Thu, 2019-06-06 at 10:09 -0700, Stephen Boyd wrote: > > Quoting Nicolas Saenz Julienne (2019-06-06 07:22:56) > > > diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c > > > b/drivers/cpufreq/raspberrypi-cpufreq.c > > > new file mode 100644 > > > index 000000000000..99b59d5a50aa > > > --- /dev/null > > > +++ b/drivers/cpufreq/raspberrypi-cpufreq.c > > [...] > > > + > > > +/* > > > + * Since the driver depends on clk-raspberrypi, which may return > > > EPROBE_DEFER, > > > + * all the activity is performed in the probe, which may be defered as > > > well. > > > + */ > > > +static struct platform_driver raspberrypi_cpufreq_driver = { > > > + .driver = { > > > + .name = "raspberrypi-cpufreq", > > > + }, > > > + .probe = raspberrypi_cpufreq_probe, > > > + .remove = raspberrypi_cpufreq_remove, > > > +}; > > > +module_platform_driver(raspberrypi_cpufreq_driver); > > > > How does this driver probe? Do you have a node in DT named > > raspberrypi-cpufreq that matches and probes this? I would think this > > would follow the drivers/cpufreq/cpufreq-dt-platdev.c design where it's > > an initcall that probes the board compatible string. > > > > Or, if it depends on clk-raspberrypi probing, maybe it could create the > > platform device in that drivers probe function. > > Well you just reviewed that patch :) Ok. So what's your plan? > > > > + > > > +MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de"); > > > +MODULE_DESCRIPTION("Raspberry Pi cpufreq driver"); > > > +MODULE_LICENSE("GPL"); > > > +MODULE_ALIAS("platform:raspberrypi-cpufreq"); > > > > I don't think the module alias is needed anymore. > > That's surprising. I remember the driver not being loaded by udev without it. > Maybe I'm wrong. Could be not needed for DT based platform devices with an OF table.
On Thu, 2019-06-06 at 10:36 -0700, Stephen Boyd wrote: > Quoting Nicolas Saenz Julienne (2019-06-06 10:22:16) > > Hi Stephen, > > Thanks for the review. > > > > On Thu, 2019-06-06 at 10:09 -0700, Stephen Boyd wrote: > > > Quoting Nicolas Saenz Julienne (2019-06-06 07:22:56) > > > > diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c > > > > b/drivers/cpufreq/raspberrypi-cpufreq.c > > > > new file mode 100644 > > > > index 000000000000..99b59d5a50aa > > > > --- /dev/null > > > > +++ b/drivers/cpufreq/raspberrypi-cpufreq.c > > > [...] > > > > + > > > > +/* > > > > + * Since the driver depends on clk-raspberrypi, which may return > > > > EPROBE_DEFER, > > > > + * all the activity is performed in the probe, which may be defered as > > > > well. > > > > + */ > > > > +static struct platform_driver raspberrypi_cpufreq_driver = { > > > > + .driver = { > > > > + .name = "raspberrypi-cpufreq", > > > > + }, > > > > + .probe = raspberrypi_cpufreq_probe, > > > > + .remove = raspberrypi_cpufreq_remove, > > > > +}; > > > > +module_platform_driver(raspberrypi_cpufreq_driver); > > > > > > How does this driver probe? Do you have a node in DT named > > > raspberrypi-cpufreq that matches and probes this? I would think this > > > would follow the drivers/cpufreq/cpufreq-dt-platdev.c design where it's > > > an initcall that probes the board compatible string. > > > > > > Or, if it depends on clk-raspberrypi probing, maybe it could create the > > > platform device in that drivers probe function. > > > > Well you just reviewed that patch :) > > Ok. So what's your plan? So as discussed previously with the RPi mantainers, they preferred for the platform device for raspberrypi-clk to be created by the firmware interface driver. IIRC Stefan said it was more flexible and the approach used with RPi's hwmon driver already. Also, it's not really clear whether this driver really fits the device tree as it wouldn't be describing hardware. As far as raspberrypi-cpufreq is concerned the max and min frequencies are configurable in the firmware. So we can't really integrate cpufreq into the device tree as we need to create the opp table dynamically. Hence the dedicated driver. On top of that the CPU might not have a clock during the init process, as both the firmware interface and raspberrypi-clk can be compiled as modules. So I decided the simplest solution was to create the raspberrypi-cpufreq platform device at the end of raspberrypi-clk's probe. Once raspberrypi-cpufreq is loaded it queries the min/max frequencies, populates the CPU's opp table and creates an instance of cpufreq-dt. Which finally can operate, without the need of any dt info, as opp tables are populated and CPUs have a clock. I hope this makes it a little more clear :). > > > > + > > > > +MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de"); > > > > +MODULE_DESCRIPTION("Raspberry Pi cpufreq driver"); > > > > +MODULE_LICENSE("GPL"); > > > > +MODULE_ALIAS("platform:raspberrypi-cpufreq"); > > > > > > I don't think the module alias is needed anymore. > > > > That's surprising. I remember the driver not being loaded by udev without > > it. > > > > Maybe I'm wrong. Could be not needed for DT based platform devices with > an OF table. As explained in the previous paragraph, I'm not using DT. Regards, Nicolas
Quoting Nicolas Saenz Julienne (2019-06-06 11:10:04) > On Thu, 2019-06-06 at 10:36 -0700, Stephen Boyd wrote: > > Quoting Nicolas Saenz Julienne (2019-06-06 10:22:16) > > > Hi Stephen, > > > Thanks for the review. > > > > > > On Thu, 2019-06-06 at 10:09 -0700, Stephen Boyd wrote: > > > > Quoting Nicolas Saenz Julienne (2019-06-06 07:22:56) > > > > > diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c > > > > > b/drivers/cpufreq/raspberrypi-cpufreq.c > > > > > new file mode 100644 > > > > > index 000000000000..99b59d5a50aa > > > > > --- /dev/null > > > > > +++ b/drivers/cpufreq/raspberrypi-cpufreq.c > > > > [...] > > > > > + > > > > > +/* > > > > > + * Since the driver depends on clk-raspberrypi, which may return > > > > > EPROBE_DEFER, > > > > > + * all the activity is performed in the probe, which may be defered as > > > > > well. > > > > > + */ > > > > > +static struct platform_driver raspberrypi_cpufreq_driver = { > > > > > + .driver = { > > > > > + .name = "raspberrypi-cpufreq", > > > > > + }, > > > > > + .probe = raspberrypi_cpufreq_probe, > > > > > + .remove = raspberrypi_cpufreq_remove, > > > > > +}; > > > > > +module_platform_driver(raspberrypi_cpufreq_driver); > > > > > > > > How does this driver probe? Do you have a node in DT named > > > > raspberrypi-cpufreq that matches and probes this? I would think this > > > > would follow the drivers/cpufreq/cpufreq-dt-platdev.c design where it's > > > > an initcall that probes the board compatible string. > > > > > > > > Or, if it depends on clk-raspberrypi probing, maybe it could create the > > > > platform device in that drivers probe function. > > > > > > Well you just reviewed that patch :) > > > > Ok. So what's your plan? > > So as discussed previously with the RPi mantainers, they preferred for the > platform device for raspberrypi-clk to be created by the firmware interface > driver. IIRC Stefan said it was more flexible and the approach used with RPi's > hwmon driver already. Also, it's not really clear whether this driver really > fits the device tree as it wouldn't be describing hardware. > > As far as raspberrypi-cpufreq is concerned the max and min frequencies are > configurable in the firmware. So we can't really integrate cpufreq into the > device tree as we need to create the opp table dynamically. Hence the dedicated > driver. On top of that the CPU might not have a clock during the init process, > as both the firmware interface and raspberrypi-clk can be compiled as modules. > So I decided the simplest solution was to create the raspberrypi-cpufreq > platform device at the end of raspberrypi-clk's probe. > > Once raspberrypi-cpufreq is loaded it queries the min/max frequencies, > populates the CPU's opp table and creates an instance of cpufreq-dt. Which > finally can operate, without the need of any dt info, as opp tables are > populated and CPUs have a clock. > > I hope this makes it a little more clear :). > Yes, thanks. I see that largely follows the commit description so it looks OK to me.
On Thu, 2019-06-06 at 11:23 -0700, Stephen Boyd wrote: > Quoting Nicolas Saenz Julienne (2019-06-06 11:10:04) > > On Thu, 2019-06-06 at 10:36 -0700, Stephen Boyd wrote: > > > Quoting Nicolas Saenz Julienne (2019-06-06 10:22:16) > > > > Hi Stephen, > > > > Thanks for the review. > > > > > > > > On Thu, 2019-06-06 at 10:09 -0700, Stephen Boyd wrote: > > > > > Quoting Nicolas Saenz Julienne (2019-06-06 07:22:56) > > > > > > diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c > > > > > > b/drivers/cpufreq/raspberrypi-cpufreq.c > > > > > > new file mode 100644 > > > > > > index 000000000000..99b59d5a50aa > > > > > > --- /dev/null > > > > > > +++ b/drivers/cpufreq/raspberrypi-cpufreq.c > > > > > [...] > > > > > > + > > > > > > +/* > > > > > > + * Since the driver depends on clk-raspberrypi, which may return > > > > > > EPROBE_DEFER, > > > > > > + * all the activity is performed in the probe, which may be defered > > > > > > as > > > > > > well. > > > > > > + */ > > > > > > +static struct platform_driver raspberrypi_cpufreq_driver = { > > > > > > + .driver = { > > > > > > + .name = "raspberrypi-cpufreq", > > > > > > + }, > > > > > > + .probe = raspberrypi_cpufreq_probe, > > > > > > + .remove = raspberrypi_cpufreq_remove, > > > > > > +}; > > > > > > +module_platform_driver(raspberrypi_cpufreq_driver); > > > > > > > > > > How does this driver probe? Do you have a node in DT named > > > > > raspberrypi-cpufreq that matches and probes this? I would think this > > > > > would follow the drivers/cpufreq/cpufreq-dt-platdev.c design where > > > > > it's > > > > > an initcall that probes the board compatible string. > > > > > > > > > > Or, if it depends on clk-raspberrypi probing, maybe it could create > > > > > the > > > > > platform device in that drivers probe function. > > > > > > > > Well you just reviewed that patch :) > > > > > > Ok. So what's your plan? > > > > So as discussed previously with the RPi mantainers, they preferred for the > > platform device for raspberrypi-clk to be created by the firmware interface > > driver. IIRC Stefan said it was more flexible and the approach used with > > RPi's > > hwmon driver already. Also, it's not really clear whether this driver really > > fits the device tree as it wouldn't be describing hardware. > > > > As far as raspberrypi-cpufreq is concerned the max and min frequencies are > > configurable in the firmware. So we can't really integrate cpufreq into the > > device tree as we need to create the opp table dynamically. Hence the > > dedicated > > driver. On top of that the CPU might not have a clock during the init > > process, > > as both the firmware interface and raspberrypi-clk can be compiled as > > modules. > > So I decided the simplest solution was to create the raspberrypi-cpufreq > > platform device at the end of raspberrypi-clk's probe. > > > > Once raspberrypi-cpufreq is loaded it queries the min/max frequencies, > > populates the CPU's opp table and creates an instance of cpufreq-dt. Which > > finally can operate, without the need of any dt info, as opp tables are > > populated and CPUs have a clock. > > > > I hope this makes it a little more clear :). > > > > Yes, thanks. I see that largely follows the commit description so it > looks OK to me. > Thanks!
On 06-06-19, 11:23, Stephen Boyd wrote: > Yes, thanks. I see that largely follows the commit description so it > looks OK to me. Do you want to provide your Reviewed/Acked-by tag before I apply it ?
Hi Viresh, Am 07.06.19 um 05:09 schrieb Viresh Kumar: > On 06-06-19, 11:23, Stephen Boyd wrote: >> Yes, thanks. I see that largely follows the commit description so it >> looks OK to me. > Do you want to provide your Reviewed/Acked-by tag before I apply it ? Nicolas wanted to send a V3 of this series and as a platform maintainer i need some time for testing this version. Stefan
Hi Nicolas, Am 06.06.19 um 16:22 schrieb Nicolas Saenz Julienne: > Raspberry Pi's firmware offers and interface though which update it's > performance requirements. It allows us to request for specific runtime > frequencies, which the firmware might or might not respect, depending on > the firmware configuration and thermals. > > As the maximum and minimum frequencies are configurable in the firmware > there is no way to know in advance their values. So the Raspberry Pi > cpufreq driver queries them, builds an opp frequency table to then > launch cpufreq-dt. > > Also, as the firmware interface might be configured as a module, making > the cpu clock unavailable during init, this implements a full fledged > driver, as opposed to most drivers registering cpufreq-dt, which only > make use of an init routine. > > Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> > Acked-by: Eric Anholt <eric@anholt.net> > > --- > > Changes since v1: > - Remove compatible checks > - Add module support, now full fledged driver > - Use NULL in clk_get() > > drivers/cpufreq/Kconfig.arm | 8 +++ > drivers/cpufreq/Makefile | 1 + > drivers/cpufreq/raspberrypi-cpufreq.c | 100 ++++++++++++++++++++++++++ > 3 files changed, 109 insertions(+) > create mode 100644 drivers/cpufreq/raspberrypi-cpufreq.c > > diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm > index f8129edc145e..5e9204d443ff 100644 > --- a/drivers/cpufreq/Kconfig.arm > +++ b/drivers/cpufreq/Kconfig.arm > @@ -133,6 +133,14 @@ config ARM_QCOM_CPUFREQ_HW > The driver implements the cpufreq interface for this HW engine. > Say Y if you want to support CPUFreq HW. > > +config ARM_RASPBERRYPI_CPUFREQ > + tristate "Raspberry Pi cpufreq support" > + depends on CLK_RASPBERRYPI || COMPILE_TEST > + help > + This adds the CPUFreq driver for Raspberry Pi > + > + If in doubt, say N. > + > config ARM_S3C_CPUFREQ > bool > help > diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile > index 689b26c6f949..121c1acb66c0 100644 > --- a/drivers/cpufreq/Makefile > +++ b/drivers/cpufreq/Makefile > @@ -64,6 +64,7 @@ obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o > obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o > obj-$(CONFIG_ARM_QCOM_CPUFREQ_HW) += qcom-cpufreq-hw.o > obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO) += qcom-cpufreq-kryo.o > +obj-$(CONFIG_ARM_RASPBERRYPI_CPUFREQ) += raspberrypi-cpufreq.o > obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o > obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o > obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o > diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c b/drivers/cpufreq/raspberrypi-cpufreq.c > new file mode 100644 > index 000000000000..99b59d5a50aa > --- /dev/null > +++ b/drivers/cpufreq/raspberrypi-cpufreq.c > @@ -0,0 +1,100 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Raspberry Pi cpufreq driver > + * > + * Copyright (C) 2019, Nicolas Saenz Julienne <nsaenzjulienne@suse.de> > + */ > + > +#include <linux/clk.h> > +#include <linux/cpu.h> > +#include <linux/cpufreq.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/pm_opp.h> > + > +static struct platform_device *cpufreq_dt; > + > +static int raspberrypi_cpufreq_probe(struct platform_device *pdev) > +{ > + struct device *cpu_dev; > + unsigned long min, max; > + unsigned long rate; > + struct clk *clk; > + int ret; > + > + cpu_dev = get_cpu_device(0); > + if (!cpu_dev) { > + pr_err("Cannot get CPU for cpufreq driver\n"); > + return -ENODEV; > + } > + > + clk = clk_get(cpu_dev, NULL); > + if (IS_ERR(clk)) { > + dev_err(cpu_dev, "Cannot get clock for CPU0\n"); > + return PTR_ERR(clk); > + } > + > + /* > + * The max and min frequencies are configurable in the Raspberry Pi > + * firmware, so we query them at runtime > + */ > + min = clk_round_rate(clk, 0); > + max = clk_round_rate(clk, ULONG_MAX); > + clk_put(clk); > + > + for (rate = min; rate < max; rate += 100000000) { > + ret = dev_pm_opp_add(cpu_dev, rate, 0); > + if (ret) > + goto remove_opp; > + } i played a little bit with my Raspberry Pi Zero W and this series. Looks fine so far. Sorry for this nitpicking, but i expect user questions about the differences between sysfs and vcgencmd measure_clock. scaling_available_frequencies gives 699999 799999 899999 999999 but vcgencmd measure_clock return the rounded up values. I know we shouldn't fake anything, but adding the OPPs rounded up may avoid confusion. Stefan
On Fri, 2019-06-07 at 13:42 +0200, Stefan Wahren wrote: > Hi Nicolas, > > Am 06.06.19 um 16:22 schrieb Nicolas Saenz Julienne: > > Raspberry Pi's firmware offers and interface though which update it's > > performance requirements. It allows us to request for specific runtime > > frequencies, which the firmware might or might not respect, depending on > > the firmware configuration and thermals. > > > > As the maximum and minimum frequencies are configurable in the firmware > > there is no way to know in advance their values. So the Raspberry Pi > > cpufreq driver queries them, builds an opp frequency table to then > > launch cpufreq-dt. > > > > Also, as the firmware interface might be configured as a module, making > > the cpu clock unavailable during init, this implements a full fledged > > driver, as opposed to most drivers registering cpufreq-dt, which only > > make use of an init routine. > > > > Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> > > Acked-by: Eric Anholt <eric@anholt.net> > > > > --- > > > > Changes since v1: > > - Remove compatible checks > > - Add module support, now full fledged driver > > - Use NULL in clk_get() > > > > drivers/cpufreq/Kconfig.arm | 8 +++ > > drivers/cpufreq/Makefile | 1 + > > drivers/cpufreq/raspberrypi-cpufreq.c | 100 ++++++++++++++++++++++++++ > > 3 files changed, 109 insertions(+) > > create mode 100644 drivers/cpufreq/raspberrypi-cpufreq.c > > > > diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm > > index f8129edc145e..5e9204d443ff 100644 > > --- a/drivers/cpufreq/Kconfig.arm > > +++ b/drivers/cpufreq/Kconfig.arm > > @@ -133,6 +133,14 @@ config ARM_QCOM_CPUFREQ_HW > > The driver implements the cpufreq interface for this HW engine. > > Say Y if you want to support CPUFreq HW. > > > > +config ARM_RASPBERRYPI_CPUFREQ > > + tristate "Raspberry Pi cpufreq support" > > + depends on CLK_RASPBERRYPI || COMPILE_TEST > > + help > > + This adds the CPUFreq driver for Raspberry Pi > > + > > + If in doubt, say N. > > + > > config ARM_S3C_CPUFREQ > > bool > > help > > diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile > > index 689b26c6f949..121c1acb66c0 100644 > > --- a/drivers/cpufreq/Makefile > > +++ b/drivers/cpufreq/Makefile > > @@ -64,6 +64,7 @@ obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o > > obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o > > obj-$(CONFIG_ARM_QCOM_CPUFREQ_HW) += qcom-cpufreq-hw.o > > obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO) += qcom-cpufreq-kryo.o > > +obj-$(CONFIG_ARM_RASPBERRYPI_CPUFREQ) += raspberrypi-cpufreq.o > > obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o > > obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o > > obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o > > diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c > > b/drivers/cpufreq/raspberrypi-cpufreq.c > > new file mode 100644 > > index 000000000000..99b59d5a50aa > > --- /dev/null > > +++ b/drivers/cpufreq/raspberrypi-cpufreq.c > > @@ -0,0 +1,100 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Raspberry Pi cpufreq driver > > + * > > + * Copyright (C) 2019, Nicolas Saenz Julienne <nsaenzjulienne@suse.de> > > + */ > > + > > +#include <linux/clk.h> > > +#include <linux/cpu.h> > > +#include <linux/cpufreq.h> > > +#include <linux/module.h> > > +#include <linux/platform_device.h> > > +#include <linux/pm_opp.h> > > + > > +static struct platform_device *cpufreq_dt; > > + > > +static int raspberrypi_cpufreq_probe(struct platform_device *pdev) > > +{ > > + struct device *cpu_dev; > > + unsigned long min, max; > > + unsigned long rate; > > + struct clk *clk; > > + int ret; > > + > > + cpu_dev = get_cpu_device(0); > > + if (!cpu_dev) { > > + pr_err("Cannot get CPU for cpufreq driver\n"); > > + return -ENODEV; > > + } > > + > > + clk = clk_get(cpu_dev, NULL); > > + if (IS_ERR(clk)) { > > + dev_err(cpu_dev, "Cannot get clock for CPU0\n"); > > + return PTR_ERR(clk); > > + } > > + > > + /* > > + * The max and min frequencies are configurable in the Raspberry Pi > > + * firmware, so we query them at runtime > > + */ > > + min = clk_round_rate(clk, 0); > > + max = clk_round_rate(clk, ULONG_MAX); > > + clk_put(clk); > > + > > + for (rate = min; rate < max; rate += 100000000) { > > + ret = dev_pm_opp_add(cpu_dev, rate, 0); > > + if (ret) > > + goto remove_opp; > > + } > > i played a little bit with my Raspberry Pi Zero W and this series. Looks > fine so far. > > Sorry for this nitpicking, but i expect user questions about the > differences between sysfs and vcgencmd measure_clock. > > scaling_available_frequencies gives > > 699999 799999 899999 999999 > > but vcgencmd measure_clock return the rounded up values. > > I know we shouldn't fake anything, but adding the OPPs rounded up may > avoid confusion. > > Stefan Agree, I'll change this in v3.
Quoting Stefan Wahren (2019-06-07 02:13:54) > Hi Viresh, > > Am 07.06.19 um 05:09 schrieb Viresh Kumar: > > On 06-06-19, 11:23, Stephen Boyd wrote: > >> Yes, thanks. I see that largely follows the commit description so it > >> looks OK to me. > > Do you want to provide your Reviewed/Acked-by tag before I apply it ? > > Nicolas wanted to send a V3 of this series and as a platform maintainer > i need some time for testing this version. > You can add my review tag. Reviewed-by: Stephen Boyd <sboyd@kernel.org>
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index f8129edc145e..5e9204d443ff 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -133,6 +133,14 @@ config ARM_QCOM_CPUFREQ_HW The driver implements the cpufreq interface for this HW engine. Say Y if you want to support CPUFreq HW. +config ARM_RASPBERRYPI_CPUFREQ + tristate "Raspberry Pi cpufreq support" + depends on CLK_RASPBERRYPI || COMPILE_TEST + help + This adds the CPUFreq driver for Raspberry Pi + + If in doubt, say N. + config ARM_S3C_CPUFREQ bool help diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 689b26c6f949..121c1acb66c0 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o obj-$(CONFIG_ARM_QCOM_CPUFREQ_HW) += qcom-cpufreq-hw.o obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO) += qcom-cpufreq-kryo.o +obj-$(CONFIG_ARM_RASPBERRYPI_CPUFREQ) += raspberrypi-cpufreq.o obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c b/drivers/cpufreq/raspberrypi-cpufreq.c new file mode 100644 index 000000000000..99b59d5a50aa --- /dev/null +++ b/drivers/cpufreq/raspberrypi-cpufreq.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Raspberry Pi cpufreq driver + * + * Copyright (C) 2019, Nicolas Saenz Julienne <nsaenzjulienne@suse.de> + */ + +#include <linux/clk.h> +#include <linux/cpu.h> +#include <linux/cpufreq.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pm_opp.h> + +static struct platform_device *cpufreq_dt; + +static int raspberrypi_cpufreq_probe(struct platform_device *pdev) +{ + struct device *cpu_dev; + unsigned long min, max; + unsigned long rate; + struct clk *clk; + int ret; + + cpu_dev = get_cpu_device(0); + if (!cpu_dev) { + pr_err("Cannot get CPU for cpufreq driver\n"); + return -ENODEV; + } + + clk = clk_get(cpu_dev, NULL); + if (IS_ERR(clk)) { + dev_err(cpu_dev, "Cannot get clock for CPU0\n"); + return PTR_ERR(clk); + } + + /* + * The max and min frequencies are configurable in the Raspberry Pi + * firmware, so we query them at runtime + */ + min = clk_round_rate(clk, 0); + max = clk_round_rate(clk, ULONG_MAX); + clk_put(clk); + + for (rate = min; rate < max; rate += 100000000) { + ret = dev_pm_opp_add(cpu_dev, rate, 0); + if (ret) + goto remove_opp; + } + + ret = dev_pm_opp_add(cpu_dev, max, 0); + if (ret) + goto remove_opp; + + cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0); + ret = PTR_ERR_OR_ZERO(cpufreq_dt); + if (ret) { + dev_err(cpu_dev, "Failed to create platform device, %d\n", ret); + goto remove_opp; + } + + return 0; + +remove_opp: + dev_pm_opp_remove_all_dynamic(cpu_dev); + + return ret; +} + +static int raspberrypi_cpufreq_remove(struct platform_device *pdev) +{ + struct device *cpu_dev; + + cpu_dev = get_cpu_device(0); + if (cpu_dev) + dev_pm_opp_remove_all_dynamic(cpu_dev); + + platform_device_unregister(cpufreq_dt); + cpufreq_dt = NULL; + + return 0; +} + +/* + * Since the driver depends on clk-raspberrypi, which may return EPROBE_DEFER, + * all the activity is performed in the probe, which may be defered as well. + */ +static struct platform_driver raspberrypi_cpufreq_driver = { + .driver = { + .name = "raspberrypi-cpufreq", + }, + .probe = raspberrypi_cpufreq_probe, + .remove = raspberrypi_cpufreq_remove, +}; +module_platform_driver(raspberrypi_cpufreq_driver); + +MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de"); +MODULE_DESCRIPTION("Raspberry Pi cpufreq driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:raspberrypi-cpufreq");