[PATCH v12 0/4] Allow USB devices to remain runtime-suspended when sleeping
Hi, this is v12 of an attempt to make it easier for devices to remain in runtime PM when the system goes to sleep, mainly to reduce the time spent resuming devices. For this, we interpret the absence of all PM callback implementations as it being safe to do direct_complete, so their ancestors aren't prevented from remaining runtime-suspended. Additionally, the prepare() callback of USB devices will return 1 if runtime PM is enabled and the current wakeup settings are correct. With these changes, a uvcvideo device (for example) stays in runtime suspend when the system goes to sleep and is left in that state when the system resumes, not delaying it unnecessarily. Thanks, Tomeu Changes in v12: - Include linux/pm_domain.h in vga_switcheroo.c for dev_pm_domain_set() Changes in v11: - Move calls to dev_pm_domain_set() out from >power.lock as that isn't needed for dev->pm_domain. Changes in v10: - Remove superfluous call to pm_runtime_enabled() as suggested by Alan Changes in v9: - Add docs noting the need for the device lock to be held before calling device_is_bound() - Add docs noting the need for the device lock to be held before calling dev_pm_domain_set() - Move to CONFIG_PM_SLEEP as suggested by Rafael and Ulf. - Rename from device_check_pm_callbacks to device_pm_check_callbacks to follow with the naming convention of existing API. - Re-add calling to device_pm_check_callbacks from device registration and when updating the PM domain of a device. Changes in v8: - Add device_is_bound() - Add dev_pm_domain_set() and update code to use it - Move no_pm_callbacks field into CONFIG_PM_SLEEP - Call device_check_pm_callbacks only after a device is bound or unbound Changes in v7: - Reduce indentation by adding a label in device_prepare() Changes in v6: - Add stub for !CONFIG_PM. - Move implementation of device_check_pm_callbacks to power/main.c as it doesn't belong to CONFIG_PM_SLEEP. - Take dev->power.lock before modifying flag. Changes in v5: - Check for all dev_pm_ops instances associated to a device, updating a no_pm_callbacks flag at the times when that could change. Tomeu Vizoso (4): device core: add device_is_bound() PM / Domains: add setter for dev.pm_domain PM / sleep: Go direct_complete if driver has no callbacks USB / PM: Allow USB devices to remain runtime-suspended when sleeping arch/arm/mach-omap2/omap_device.c | 7 --- drivers/acpi/acpi_lpss.c | 5 - drivers/acpi/device_pm.c | 5 +++-- drivers/base/dd.c | 21 +++-- drivers/base/power/clock_ops.c| 5 +++-- drivers/base/power/common.c | 24 drivers/base/power/domain.c | 8 ++-- drivers/base/power/main.c | 35 +++ drivers/base/power/power.h| 3 +++ drivers/gpu/vga/vga_switcheroo.c | 11 ++- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c| 5 +++-- drivers/usb/core/port.c | 6 ++ drivers/usb/core/usb.c| 8 +++- include/linux/device.h| 2 ++ include/linux/pm.h| 1 + include/linux/pm_domain.h | 3 +++ 17 files changed, 132 insertions(+), 22 deletions(-) -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v12 2/4] PM / Domains: add setter for dev.pm_domain
Adds a function that sets the pointer to dev_pm_domain in struct device and that warns if the device has already finished probing. The reason why we want to enforce that is because in the general case that can cause problems and also that we can simplify code quite a bit if we can always assume that. This patch also changes all current code that directly sets the dev.pm_domain pointer. Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com> Reviewed-by: Ulf Hansson <ulf.hans...@linaro.org> --- Changes in v12: - Include linux/pm_domain.h in vga_switcheroo.c for dev_pm_domain_set() Changes in v11: - Move calls to dev_pm_domain_set() out from >power.lock as that isn't needed for dev->pm_domain. Changes in v9: - Add docs noting the need for the device lock to be held before calling dev_pm_domain_set() Changes in v8: - Add dev_pm_domain_set() and update code to use it arch/arm/mach-omap2/omap_device.c | 7 --- drivers/acpi/acpi_lpss.c | 5 - drivers/acpi/device_pm.c | 5 +++-- drivers/base/power/clock_ops.c| 5 +++-- drivers/base/power/common.c | 21 + drivers/base/power/domain.c | 6 -- drivers/gpu/vga/vga_switcheroo.c | 11 ++- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c| 5 +++-- include/linux/pm_domain.h | 3 +++ 10 files changed, 54 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 3750ed14f8c5..0437537751bc 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -168,7 +169,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) r->name = dev_name(>dev); } - pdev->dev.pm_domain = _device_pm_domain; + dev_pm_domain_set(>dev, _device_pm_domain); if (device_active) { omap_device_enable(pdev); @@ -180,7 +181,7 @@ odbfd_exit1: odbfd_exit: /* if data/we are at fault.. load up a fail handler */ if (ret) - pdev->dev.pm_domain = _device_fail_pm_domain; + dev_pm_domain_set(>dev, _device_fail_pm_domain); return ret; } @@ -701,7 +702,7 @@ int omap_device_register(struct platform_device *pdev) { pr_debug("omap_device: %s: registering\n", pdev->name); - pdev->dev.pm_domain = _device_pm_domain; + dev_pm_domain_set(>dev, _device_pm_domain); return platform_device_add(pdev); } diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 047281a6ae11..c570b1d9f094 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -875,13 +876,14 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, switch (action) { case BUS_NOTIFY_BIND_DRIVER: - pdev->dev.pm_domain = _lpss_pm_domain; + dev_pm_domain_set(>dev, _lpss_pm_domain); break; case BUS_NOTIFY_DRIVER_NOT_BOUND: case BUS_NOTIFY_UNBOUND_DRIVER: pdev->dev.pm_domain = NULL; break; case BUS_NOTIFY_ADD_DEVICE: + dev_pm_domain_set(>dev, _lpss_pm_domain); if (pdata->dev_desc->flags & LPSS_LTR) return sysfs_create_group(>dev.kobj, _attr_group); @@ -889,6 +891,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, case BUS_NOTIFY_DEL_DEVICE: if (pdata->dev_desc->flags & LPSS_LTR) sysfs_remove_group(>dev.kobj, _attr_group); + dev_pm_domain_set(>dev, NULL); break; default: break; diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 08a02cdc737c..cd2c3d6d40e0 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "internal.h" @@ -1059,7 +1060,7 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off) struct acpi_device *adev = ACPI_COMPANION(dev); if (adev && dev->pm_domain == _general_pm_domain) { - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); acpi_remove_pm_notifier(adev); if (power_off) { /* @@ -,7 +1112,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) return -EBUSY; acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); - dev->pm_domain = _general_pm_domain; + dev_pm_domain_set(dev, _genera
[PATCH v11 2/4] PM / Domains: add setter for dev.pm_domain
Adds a function that sets the pointer to dev_pm_domain in struct device and that warns if the device has already finished probing. The reason why we want to enforce that is because in the general case that can cause problems and also that we can simplify code quite a bit if we can always assume that. This patch also changes all current code that directly sets the dev.pm_domain pointer. Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com> Reviewed-by: Ulf Hansson <ulf.hans...@linaro.org> --- Changes in v11: - Move calls to dev_pm_domain_set() out from >power.lock as that isn't needed for dev->pm_domain. Changes in v9: - Add docs noting the need for the device lock to be held before calling dev_pm_domain_set() Changes in v8: - Add dev_pm_domain_set() and update code to use it arch/arm/mach-omap2/omap_device.c | 7 --- drivers/acpi/acpi_lpss.c | 5 +++-- drivers/acpi/device_pm.c | 5 +++-- drivers/base/power/clock_ops.c| 5 +++-- drivers/base/power/common.c | 21 + drivers/base/power/domain.c | 6 -- drivers/gpu/vga/vga_switcheroo.c | 10 +- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c| 5 +++-- include/linux/pm_domain.h | 3 +++ 10 files changed, 52 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 4cb8fd9f741f..204101d11632 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -168,7 +169,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) r->name = dev_name(>dev); } - pdev->dev.pm_domain = _device_pm_domain; + dev_pm_domain_set(>dev, _device_pm_domain); if (device_active) { omap_device_enable(pdev); @@ -180,7 +181,7 @@ odbfd_exit1: odbfd_exit: /* if data/we are at fault.. load up a fail handler */ if (ret) - pdev->dev.pm_domain = _device_fail_pm_domain; + dev_pm_domain_set(>dev, _device_fail_pm_domain); return ret; } @@ -701,7 +702,7 @@ int omap_device_register(struct platform_device *pdev) { pr_debug("omap_device: %s: registering\n", pdev->name); - pdev->dev.pm_domain = _device_pm_domain; + dev_pm_domain_set(>dev, _device_pm_domain); return platform_device_add(pdev); } diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index f51bd0d0bc17..cc6e1abc69b3 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -706,7 +707,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, switch (action) { case BUS_NOTIFY_ADD_DEVICE: - pdev->dev.pm_domain = _lpss_pm_domain; + dev_pm_domain_set(>dev, _lpss_pm_domain); if (pdata->dev_desc->flags & LPSS_LTR) return sysfs_create_group(>dev.kobj, _attr_group); @@ -714,7 +715,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, case BUS_NOTIFY_DEL_DEVICE: if (pdata->dev_desc->flags & LPSS_LTR) sysfs_remove_group(>dev.kobj, _attr_group); - pdev->dev.pm_domain = NULL; + dev_pm_domain_set(>dev, NULL); break; default: break; diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 4806b7f856c4..8c5955bf9bbf 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "internal.h" @@ -1076,7 +1077,7 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off) struct acpi_device *adev = ACPI_COMPANION(dev); if (adev && dev->pm_domain == _general_pm_domain) { - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); acpi_remove_pm_notifier(adev); if (power_off) { /* @@ -1128,7 +1129,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) return -EBUSY; acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); - dev->pm_domain = _general_pm_domain; + dev_pm_domain_set(dev, _general_pm_domain); if (power_on) { acpi_dev_pm_full_power(adev); acpi_device_wakeup(adev, ACPI_STATE_S0, false); diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 652b5a367c1f..e80fda6c03a9 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/c
[PATCH v11 0/4] Allow USB devices to remain runtime-suspended when sleeping
Hi, this is v11 of an attempt to make it easier for devices to remain in runtime PM when the system goes to sleep, mainly to reduce the time spent resuming devices. For this, we interpret the absence of all PM callback implementations as it being safe to do direct_complete, so their ancestors aren't prevented from remaining runtime-suspended. Additionally, the prepare() callback of USB devices will return 1 if runtime PM is enabled and the current wakeup settings are correct. With these changes, a uvcvideo device (for example) stays in runtime suspend when the system goes to sleep and is left in that state when the system resumes, not delaying it unnecessarily. Thanks, Tomeu Changes in v11: - Move calls to dev_pm_domain_set() out from >power.lock as that isn't needed for dev->pm_domain. Changes in v10: - Remove superfluous call to pm_runtime_enabled() as suggested by Alan Changes in v9: - Add docs noting the need for the device lock to be held before calling device_is_bound() - Add docs noting the need for the device lock to be held before calling dev_pm_domain_set() - Move to CONFIG_PM_SLEEP as suggested by Rafael and Ulf. - Rename from device_check_pm_callbacks to device_pm_check_callbacks to follow with the naming convention of existing API. - Re-add calling to device_pm_check_callbacks from device registration and when updating the PM domain of a device. Changes in v8: - Add device_is_bound() - Add dev_pm_domain_set() and update code to use it - Move no_pm_callbacks field into CONFIG_PM_SLEEP - Call device_check_pm_callbacks only after a device is bound or unbound Changes in v7: - Reduce indentation by adding a label in device_prepare() Changes in v6: - Add stub for !CONFIG_PM. - Move implementation of device_check_pm_callbacks to power/main.c as it doesn't belong to CONFIG_PM_SLEEP. - Take dev->power.lock before modifying flag. Changes in v5: - Check for all dev_pm_ops instances associated to a device, updating a no_pm_callbacks flag at the times when that could change. Tomeu Vizoso (4): device core: add device_is_bound() PM / Domains: add setter for dev.pm_domain PM / sleep: Go direct_complete if driver has no callbacks USB / PM: Allow USB devices to remain runtime-suspended when sleeping arch/arm/mach-omap2/omap_device.c | 7 --- drivers/acpi/acpi_lpss.c | 5 +++-- drivers/acpi/device_pm.c | 5 +++-- drivers/base/dd.c | 21 +++-- drivers/base/power/clock_ops.c| 5 +++-- drivers/base/power/common.c | 24 drivers/base/power/domain.c | 8 ++-- drivers/base/power/main.c | 35 +++ drivers/base/power/power.h| 3 +++ drivers/gpu/vga/vga_switcheroo.c | 10 +- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c| 5 +++-- drivers/usb/core/port.c | 6 ++ drivers/usb/core/usb.c| 8 +++- include/linux/device.h| 2 ++ include/linux/pm.h| 1 + include/linux/pm_domain.h | 3 +++ 17 files changed, 130 insertions(+), 23 deletions(-) -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v10 2/4] PM / Domains: add setter for dev.pm_domain
On 25 October 2015 at 16:18, Rafael J. Wysocki <r...@rjwysocki.net> wrote: > On Wednesday, October 21, 2015 05:34:12 PM Tomeu Vizoso wrote: >> Adds a function that sets the pointer to dev_pm_domain in struct device >> and that warns if the device has already finished probing. The reason >> why we want to enforce that is because in the general case that can >> cause problems and also that we can simplify code quite a bit if we can >> always assume that. >> >> This patch also changes all current code that directly sets the >> dev.pm_domain pointer. >> >> Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com> >> Reviewed-by: Ulf Hansson <ulf.hans...@linaro.org> >> --- >> >> Changes in v9: >> - Add docs noting the need for the device lock to be held before calling >> dev_pm_domain_set() >> >> Changes in v8: >> - Add dev_pm_domain_set() and update code to use it >> >> arch/arm/mach-omap2/omap_device.c | 7 --- >> drivers/acpi/acpi_lpss.c | 5 +++-- >> drivers/acpi/device_pm.c | 5 +++-- >> drivers/base/power/clock_ops.c| 5 +++-- >> drivers/base/power/common.c | 21 + >> drivers/base/power/domain.c | 4 ++-- >> drivers/gpu/vga/vga_switcheroo.c | 10 +- >> drivers/misc/mei/pci-me.c | 5 +++-- >> drivers/misc/mei/pci-txe.c| 5 +++-- >> include/linux/pm_domain.h | 3 +++ >> 10 files changed, 50 insertions(+), 20 deletions(-) >> >> diff --git a/arch/arm/mach-omap2/omap_device.c >> b/arch/arm/mach-omap2/omap_device.c >> index 4cb8fd9f741f..204101d11632 100644 >> --- a/arch/arm/mach-omap2/omap_device.c >> +++ b/arch/arm/mach-omap2/omap_device.c >> @@ -32,6 +32,7 @@ >> #include >> #include >> #include >> +#include >> #include >> #include >> #include >> @@ -168,7 +169,7 @@ static int omap_device_build_from_dt(struct >> platform_device *pdev) >> r->name = dev_name(>dev); >> } >> >> - pdev->dev.pm_domain = _device_pm_domain; >> + dev_pm_domain_set(>dev, _device_pm_domain); >> >> if (device_active) { >> omap_device_enable(pdev); >> @@ -180,7 +181,7 @@ odbfd_exit1: >> odbfd_exit: >> /* if data/we are at fault.. load up a fail handler */ >> if (ret) >> - pdev->dev.pm_domain = _device_fail_pm_domain; >> + dev_pm_domain_set(>dev, _device_fail_pm_domain); >> >> return ret; >> } >> @@ -701,7 +702,7 @@ int omap_device_register(struct platform_device *pdev) >> { >> pr_debug("omap_device: %s: registering\n", pdev->name); >> >> - pdev->dev.pm_domain = _device_pm_domain; >> + dev_pm_domain_set(>dev, _device_pm_domain); >> return platform_device_add(pdev); >> } >> >> diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c >> index f51bd0d0bc17..cc6e1abc69b3 100644 >> --- a/drivers/acpi/acpi_lpss.c >> +++ b/drivers/acpi/acpi_lpss.c >> @@ -17,6 +17,7 @@ >> #include >> #include >> #include >> +#include >> #include >> #include >> >> @@ -706,7 +707,7 @@ static int acpi_lpss_platform_notify(struct >> notifier_block *nb, >> >> switch (action) { >> case BUS_NOTIFY_ADD_DEVICE: >> - pdev->dev.pm_domain = _lpss_pm_domain; >> + dev_pm_domain_set(>dev, _lpss_pm_domain); >> if (pdata->dev_desc->flags & LPSS_LTR) >> return sysfs_create_group(>dev.kobj, >> _attr_group); >> @@ -714,7 +715,7 @@ static int acpi_lpss_platform_notify(struct >> notifier_block *nb, >> case BUS_NOTIFY_DEL_DEVICE: >> if (pdata->dev_desc->flags & LPSS_LTR) >> sysfs_remove_group(>dev.kobj, _attr_group); >> - pdev->dev.pm_domain = NULL; >> + dev_pm_domain_set(>dev, NULL); >> break; >> default: >> break; >> diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c >> index 4806b7f856c4..8c5955bf9bbf 100644 >> --- a/drivers/acpi/device_pm.c >> +++ b/drivers/acpi/device_pm.c >> @@ -22,6 +22,7 @@ >> #include >> #include >> #include >> +#include >> #include >> >> #include "internal.h" >>
[PATCH v10 0/4] Allow USB devices to remain runtime-suspended when sleeping
Hi, this is v10 of an attempt to make it easier for devices to remain in runtime PM when the system goes to sleep, mainly to reduce the time spent resuming devices. For this, we interpret the absence of all PM callback implementations as it being safe to do direct_complete, so their ancestors aren't prevented from remaining runtime-suspended. Additionally, the prepare() callback of USB devices will return 1 if runtime PM is enabled and the current wakeup settings are correct. With these changes, a uvcvideo device (for example) stays in runtime suspend when the system goes to sleep and is left in that state when the system resumes, not delaying it unnecessarily. Thanks, Tomeu Changes in v10: - Remove superfluous call to pm_runtime_enabled() as suggested by Alan Changes in v9: - Add docs noting the need for the device lock to be held before calling device_is_bound() - Add docs noting the need for the device lock to be held before calling dev_pm_domain_set() - Move to CONFIG_PM_SLEEP as suggested by Rafael and Ulf. - Rename from device_check_pm_callbacks to device_pm_check_callbacks to follow with the naming convention of existing API. - Re-add calling to device_pm_check_callbacks from device registration and when updating the PM domain of a device. Changes in v8: - Add device_is_bound() - Add dev_pm_domain_set() and update code to use it - Move no_pm_callbacks field into CONFIG_PM_SLEEP - Call device_check_pm_callbacks only after a device is bound or unbound Changes in v7: - Reduce indentation by adding a label in device_prepare() Changes in v6: - Add stub for !CONFIG_PM. - Move implementation of device_check_pm_callbacks to power/main.c as it doesn't belong to CONFIG_PM_SLEEP. - Take dev->power.lock before modifying flag. Changes in v5: - Check for all dev_pm_ops instances associated to a device, updating a no_pm_callbacks flag at the times when that could change. Tomeu Vizoso (4): device core: add device_is_bound() PM / Domains: add setter for dev.pm_domain PM / sleep: Go direct_complete if driver has no callbacks USB / PM: Allow USB devices to remain runtime-suspended when sleeping arch/arm/mach-omap2/omap_device.c | 7 --- drivers/acpi/acpi_lpss.c | 5 +++-- drivers/acpi/device_pm.c | 5 +++-- drivers/base/dd.c | 21 +++-- drivers/base/power/clock_ops.c| 5 +++-- drivers/base/power/common.c | 24 drivers/base/power/domain.c | 6 -- drivers/base/power/main.c | 35 +++ drivers/base/power/power.h| 3 +++ drivers/gpu/vga/vga_switcheroo.c | 10 +- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c| 5 +++-- drivers/usb/core/port.c | 6 ++ drivers/usb/core/usb.c| 8 +++- include/linux/device.h| 2 ++ include/linux/pm.h| 1 + include/linux/pm_domain.h | 3 +++ 17 files changed, 128 insertions(+), 23 deletions(-) -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v10 2/4] PM / Domains: add setter for dev.pm_domain
Adds a function that sets the pointer to dev_pm_domain in struct device and that warns if the device has already finished probing. The reason why we want to enforce that is because in the general case that can cause problems and also that we can simplify code quite a bit if we can always assume that. This patch also changes all current code that directly sets the dev.pm_domain pointer. Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com> Reviewed-by: Ulf Hansson <ulf.hans...@linaro.org> --- Changes in v9: - Add docs noting the need for the device lock to be held before calling dev_pm_domain_set() Changes in v8: - Add dev_pm_domain_set() and update code to use it arch/arm/mach-omap2/omap_device.c | 7 --- drivers/acpi/acpi_lpss.c | 5 +++-- drivers/acpi/device_pm.c | 5 +++-- drivers/base/power/clock_ops.c| 5 +++-- drivers/base/power/common.c | 21 + drivers/base/power/domain.c | 4 ++-- drivers/gpu/vga/vga_switcheroo.c | 10 +- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c| 5 +++-- include/linux/pm_domain.h | 3 +++ 10 files changed, 50 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 4cb8fd9f741f..204101d11632 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -168,7 +169,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) r->name = dev_name(>dev); } - pdev->dev.pm_domain = _device_pm_domain; + dev_pm_domain_set(>dev, _device_pm_domain); if (device_active) { omap_device_enable(pdev); @@ -180,7 +181,7 @@ odbfd_exit1: odbfd_exit: /* if data/we are at fault.. load up a fail handler */ if (ret) - pdev->dev.pm_domain = _device_fail_pm_domain; + dev_pm_domain_set(>dev, _device_fail_pm_domain); return ret; } @@ -701,7 +702,7 @@ int omap_device_register(struct platform_device *pdev) { pr_debug("omap_device: %s: registering\n", pdev->name); - pdev->dev.pm_domain = _device_pm_domain; + dev_pm_domain_set(>dev, _device_pm_domain); return platform_device_add(pdev); } diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index f51bd0d0bc17..cc6e1abc69b3 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -706,7 +707,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, switch (action) { case BUS_NOTIFY_ADD_DEVICE: - pdev->dev.pm_domain = _lpss_pm_domain; + dev_pm_domain_set(>dev, _lpss_pm_domain); if (pdata->dev_desc->flags & LPSS_LTR) return sysfs_create_group(>dev.kobj, _attr_group); @@ -714,7 +715,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, case BUS_NOTIFY_DEL_DEVICE: if (pdata->dev_desc->flags & LPSS_LTR) sysfs_remove_group(>dev.kobj, _attr_group); - pdev->dev.pm_domain = NULL; + dev_pm_domain_set(>dev, NULL); break; default: break; diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 4806b7f856c4..8c5955bf9bbf 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "internal.h" @@ -1076,7 +1077,7 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off) struct acpi_device *adev = ACPI_COMPANION(dev); if (adev && dev->pm_domain == _general_pm_domain) { - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); acpi_remove_pm_notifier(adev); if (power_off) { /* @@ -1128,7 +1129,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) return -EBUSY; acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); - dev->pm_domain = _general_pm_domain; + dev_pm_domain_set(dev, _general_pm_domain); if (power_on) { acpi_dev_pm_full_power(adev); acpi_device_wakeup(adev, ACPI_STATE_S0, false); diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 652b5a367c1f..e80fda6c03a9 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #ifdef CONFIG_PM @@ -346,7 +347
[PATCH v9 0/4] Allow USB devices to remain runtime-suspended when sleeping
Hi, this is v9 of an attempt to make it easier for devices to remain in runtime PM when the system goes to sleep, mainly to reduce the time spent resuming devices. For this, we interpret the absence of all PM callback implementations as it being safe to do direct_complete, so their ancestors aren't prevented from remaining runtime-suspended. Additionally, the prepare() callback of USB devices will return 1 if runtime PM is enabled and the current wakeup settings are correct. With these changes, a uvcvideo device (for example) stays in runtime suspend when the system goes to sleep and is left in that state when the system resumes, not delaying it unnecessarily. Thanks, Tomeu Changes in v9: - Add docs noting the need for the device lock to be held before calling device_is_bound() - Add docs noting the need for the device lock to be held before calling dev_pm_domain_set() - Move to CONFIG_PM_SLEEP as suggested by Rafael and Ulf. - Rename from device_check_pm_callbacks to device_pm_check_callbacks to follow with the naming convention of existing API. - Re-add calling to device_pm_check_callbacks from device registration and when updating the PM domain of a device. Changes in v8: - Add device_is_bound() - Add dev_pm_domain_set() and update code to use it - Move no_pm_callbacks field into CONFIG_PM_SLEEP - Call device_check_pm_callbacks only after a device is bound or unbound Changes in v7: - Reduce indentation by adding a label in device_prepare() Changes in v6: - Add stub for !CONFIG_PM. - Move implementation of device_check_pm_callbacks to power/main.c as it doesn't belong to CONFIG_PM_SLEEP. - Take dev->power.lock before modifying flag. Changes in v5: - Check for all dev_pm_ops instances associated to a device, updating a no_pm_callbacks flag at the times when that could change. Tomeu Vizoso (4): device core: add device_is_bound() PM / Domains: add setter for dev.pm_domain PM / sleep: Go direct_complete if driver has no callbacks USB / PM: Allow USB devices to remain runtime-suspended when sleeping arch/arm/mach-omap2/omap_device.c | 7 --- drivers/acpi/acpi_lpss.c | 5 +++-- drivers/acpi/device_pm.c | 5 +++-- drivers/base/dd.c | 21 +++-- drivers/base/power/clock_ops.c| 5 +++-- drivers/base/power/common.c | 24 drivers/base/power/domain.c | 6 -- drivers/base/power/main.c | 35 +++ drivers/base/power/power.h| 3 +++ drivers/gpu/vga/vga_switcheroo.c | 10 +- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c| 5 +++-- drivers/usb/core/port.c | 6 ++ drivers/usb/core/usb.c| 11 ++- include/linux/device.h| 2 ++ include/linux/pm.h| 1 + include/linux/pm_domain.h | 3 +++ 17 files changed, 131 insertions(+), 23 deletions(-) -- 2.4.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v9 2/4] PM / Domains: add setter for dev.pm_domain
Adds a function that sets the pointer to dev_pm_domain in struct device and that warns if the device has already finished probing. The reason why we want to enforce that is because in the general case that can cause problems and also that we can simplify code quite a bit if we can always assume that. This patch also changes all current code that directly sets the dev.pm_domain pointer. Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com> --- Changes in v9: - Add docs noting the need for the device lock to be held before calling dev_pm_domain_set() Changes in v8: - Add dev_pm_domain_set() and update code to use it arch/arm/mach-omap2/omap_device.c | 7 --- drivers/acpi/acpi_lpss.c | 5 +++-- drivers/acpi/device_pm.c | 5 +++-- drivers/base/power/clock_ops.c| 5 +++-- drivers/base/power/common.c | 21 + drivers/base/power/domain.c | 4 ++-- drivers/gpu/vga/vga_switcheroo.c | 10 +- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c| 5 +++-- include/linux/pm_domain.h | 3 +++ 10 files changed, 50 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 4cb8fd9f741f..204101d11632 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -168,7 +169,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) r->name = dev_name(>dev); } - pdev->dev.pm_domain = _device_pm_domain; + dev_pm_domain_set(>dev, _device_pm_domain); if (device_active) { omap_device_enable(pdev); @@ -180,7 +181,7 @@ odbfd_exit1: odbfd_exit: /* if data/we are at fault.. load up a fail handler */ if (ret) - pdev->dev.pm_domain = _device_fail_pm_domain; + dev_pm_domain_set(>dev, _device_fail_pm_domain); return ret; } @@ -701,7 +702,7 @@ int omap_device_register(struct platform_device *pdev) { pr_debug("omap_device: %s: registering\n", pdev->name); - pdev->dev.pm_domain = _device_pm_domain; + dev_pm_domain_set(>dev, _device_pm_domain); return platform_device_add(pdev); } diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index f51bd0d0bc17..cc6e1abc69b3 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -706,7 +707,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, switch (action) { case BUS_NOTIFY_ADD_DEVICE: - pdev->dev.pm_domain = _lpss_pm_domain; + dev_pm_domain_set(>dev, _lpss_pm_domain); if (pdata->dev_desc->flags & LPSS_LTR) return sysfs_create_group(>dev.kobj, _attr_group); @@ -714,7 +715,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, case BUS_NOTIFY_DEL_DEVICE: if (pdata->dev_desc->flags & LPSS_LTR) sysfs_remove_group(>dev.kobj, _attr_group); - pdev->dev.pm_domain = NULL; + dev_pm_domain_set(>dev, NULL); break; default: break; diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 4806b7f856c4..8c5955bf9bbf 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "internal.h" @@ -1076,7 +1077,7 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off) struct acpi_device *adev = ACPI_COMPANION(dev); if (adev && dev->pm_domain == _general_pm_domain) { - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); acpi_remove_pm_notifier(adev); if (power_off) { /* @@ -1128,7 +1129,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) return -EBUSY; acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); - dev->pm_domain = _general_pm_domain; + dev_pm_domain_set(dev, _general_pm_domain); if (power_on) { acpi_dev_pm_full_power(adev); acpi_device_wakeup(adev, ACPI_STATE_S0, false); diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 652b5a367c1f..e80fda6c03a9 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #ifdef CONFIG_PM @@ -346,7 +347,7 @@ static int pm_clk_notify(struct notifier_block *nb,
[PATCH v8 2/4] PM / Domains: add setter for dev.pm_domain
Adds a function that sets the pointer to dev_pm_domain in struct device and that warns if the device has already finished probing. The reason why we want to enforce that is because in the general case that can cause problems and also that we can simplify code quite a bit if we can always assume that. This patch also changes all current code that directly sets the dev.pm_domain pointer. Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com> --- Changes in v8: - Add dev_pm_domain_set() and update code to use it arch/arm/mach-omap2/omap_device.c | 7 --- drivers/acpi/acpi_lpss.c | 5 +++-- drivers/acpi/device_pm.c | 5 +++-- drivers/base/power/clock_ops.c| 5 +++-- drivers/base/power/common.c | 8 drivers/base/power/domain.c | 4 ++-- drivers/gpu/vga/vga_switcheroo.c | 10 +- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c| 5 +++-- include/linux/pm_domain.h | 3 +++ 10 files changed, 37 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 4cb8fd9f741f..204101d11632 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -168,7 +169,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) r->name = dev_name(>dev); } - pdev->dev.pm_domain = _device_pm_domain; + dev_pm_domain_set(>dev, _device_pm_domain); if (device_active) { omap_device_enable(pdev); @@ -180,7 +181,7 @@ odbfd_exit1: odbfd_exit: /* if data/we are at fault.. load up a fail handler */ if (ret) - pdev->dev.pm_domain = _device_fail_pm_domain; + dev_pm_domain_set(>dev, _device_fail_pm_domain); return ret; } @@ -701,7 +702,7 @@ int omap_device_register(struct platform_device *pdev) { pr_debug("omap_device: %s: registering\n", pdev->name); - pdev->dev.pm_domain = _device_pm_domain; + dev_pm_domain_set(>dev, _device_pm_domain); return platform_device_add(pdev); } diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index f51bd0d0bc17..cc6e1abc69b3 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -706,7 +707,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, switch (action) { case BUS_NOTIFY_ADD_DEVICE: - pdev->dev.pm_domain = _lpss_pm_domain; + dev_pm_domain_set(>dev, _lpss_pm_domain); if (pdata->dev_desc->flags & LPSS_LTR) return sysfs_create_group(>dev.kobj, _attr_group); @@ -714,7 +715,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, case BUS_NOTIFY_DEL_DEVICE: if (pdata->dev_desc->flags & LPSS_LTR) sysfs_remove_group(>dev.kobj, _attr_group); - pdev->dev.pm_domain = NULL; + dev_pm_domain_set(>dev, NULL); break; default: break; diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 4806b7f856c4..8c5955bf9bbf 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "internal.h" @@ -1076,7 +1077,7 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off) struct acpi_device *adev = ACPI_COMPANION(dev); if (adev && dev->pm_domain == _general_pm_domain) { - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); acpi_remove_pm_notifier(adev); if (power_off) { /* @@ -1128,7 +1129,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) return -EBUSY; acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); - dev->pm_domain = _general_pm_domain; + dev_pm_domain_set(dev, _general_pm_domain); if (power_on) { acpi_dev_pm_full_power(adev); acpi_device_wakeup(adev, ACPI_STATE_S0, false); diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 652b5a367c1f..e80fda6c03a9 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #ifdef CONFIG_PM @@ -346,7 +347,7 @@ static int pm_clk_notify(struct notifier_block *nb, if (error) break; - dev->pm_domain = c
[PATCH v8 0/4] Allow USB devices to remain runtime-suspended when sleeping
Hi, this is v8 of an attempt to make it easier for devices to remain in runtime PM when the system goes to sleep, mainly to reduce the time spent resuming devices. For this, we interpret the absence of all PM callback implementations as it being safe to do direct_complete, so their ancestors aren't prevented from remaining runtime-suspended. Additionally, the prepare() callback of USB devices will return 1 if runtime PM is enabled and the current wakeup settings are correct. With these changes, a uvcvideo device (for example) stays in runtime suspend when the system goes to sleep and is left in that state when the system resumes, not delaying it unnecessarily. Thanks, Tomeu Changes in v8: - Add device_is_bound() - Add dev_pm_domain_set() and update code to use it - Move no_pm_callbacks field into CONFIG_PM_SLEEP - Call device_check_pm_callbacks only after a device is bound or unbound Changes in v7: - Reduce indentation by adding a label in device_prepare() Changes in v6: - Add stub for !CONFIG_PM. - Move implementation of device_check_pm_callbacks to power/main.c as it doesn't belong to CONFIG_PM_SLEEP. - Take dev->power.lock before modifying flag. Changes in v5: - Check for all dev_pm_ops instances associated to a device, updating a no_pm_callbacks flag at the times when that could change. Tomeu Vizoso (4): device core: add device_is_bound() PM / Domains: add setter for dev.pm_domain PM / sleep: Go direct_complete if driver has no callbacks USB / PM: Allow USB devices to remain runtime-suspended when sleeping arch/arm/mach-omap2/omap_device.c | 7 --- drivers/acpi/acpi_lpss.c | 5 +++-- drivers/acpi/device_pm.c | 5 +++-- drivers/base/dd.c | 12 ++-- drivers/base/power/clock_ops.c| 5 +++-- drivers/base/power/common.c | 8 drivers/base/power/domain.c | 6 -- drivers/base/power/main.c | 33 + drivers/base/power/power.h| 6 ++ drivers/gpu/vga/vga_switcheroo.c | 10 +- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c| 5 +++-- drivers/usb/core/port.c | 6 ++ drivers/usb/core/usb.c| 11 ++- include/linux/device.h| 2 ++ include/linux/pm.h| 1 + include/linux/pm_domain.h | 3 +++ 17 files changed, 107 insertions(+), 23 deletions(-) -- 2.4.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] memory: omap-gpmc: Don't try to save the GPMC context
...if there isn't one already. If for some reason the GPMC device hasn't been probed yet, gpmc_base is going to be NULL. Because there's no context yet to be saved, just turn these functions into no-ops until that device gets probed. Unable to handle kernel NULL pointer dereference at virtual address 0010 pgd = c0204000 [0010] *pgd= Internal error: Oops: 5 [#1] SMP ARM Modules linked in: CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.2.0-rc5-next-20150804-05947-g23f38fe8eda9 #1 Hardware name: Generic OMAP3-GP (Flattened Device Tree) task: c0e623e8 ti: c0e5c000 task.ti: c0e5c000 PC is at omap3_gpmc_save_context+0x8/0xc4 LR is at omap_sram_idle+0x154/0x23c pc : [c087c7ac]lr : [c023262c]psr: 6193 sp : c0e5df40 ip : c0f92a80 fp : c0999eb0 r10: c0e57364 r9 : c0e66f14 r8 : 0003 r7 : r6 : 0003 r5 : r4 : c0f5f174 r3 : c0fa4fe8 r2 : r1 : r0 : fa200280 Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c5387d Table: 80204019 DAC: 0015 Process swapper/0 (pid: 0, stack limit = 0xc0e5c220) Stack: (0xc0e5df40 to 0xc0e5e000) df40: c0e66ef8 c0f5f1a4 0003 c02333a4 c3813822 df60: c0e5a5c8 cfb8a5d0 c07f0c44 0e4f1d7e df80: c3813822 cfb8a5d0 c0e5e4e4 cfb8a5d0 c0e66f14 c0e5a5c8 c0e5e54c dfa0: c0e5e544 c0e57364 c0999eb0 c0277758 00fa c0f5d000 c0d61c18 dfc0: c0d61674 c0df7a48 c0f5d5d4 dfe0: c0e5e4c0 c0df7a44 c0e634f8 80204059 8020807c [c087c7ac] (omap3_gpmc_save_context) from [c023262c] (omap_sram_idle+0x154/0x23c) [c023262c] (omap_sram_idle) from [c02333a4] (omap3_enter_idle_bm+0xec/0x1a8) [c02333a4] (omap3_enter_idle_bm) from [c07f0c44] (cpuidle_enter_state+0xbc/0x284) [c07f0c44] (cpuidle_enter_state) from [c0277758] (cpu_startup_entry+0x174/0x24c) [c0277758] (cpu_startup_entry) from [c0d61c18] (start_kernel+0x358/0x3c0) [c0d61c18] (start_kernel) from [8020807c] (0x8020807c) Code: c0ccace8 c0ccacc0 e59f30b4 e5932000 (e5921010) Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com Suggested-by: Javier Martinez Canillas jav...@dowhile0.org --- drivers/memory/omap-gpmc.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 3a27a84ad3ec..9426276dbe14 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -2245,6 +2245,9 @@ void omap3_gpmc_save_context(void) { int i; + if (!gpmc_base) + return; + gpmc_context.sysconfig = gpmc_read_reg(GPMC_SYSCONFIG); gpmc_context.irqenable = gpmc_read_reg(GPMC_IRQENABLE); gpmc_context.timeout_ctrl = gpmc_read_reg(GPMC_TIMEOUT_CONTROL); @@ -2277,6 +2280,9 @@ void omap3_gpmc_restore_context(void) { int i; + if (!gpmc_base) + return; + gpmc_write_reg(GPMC_SYSCONFIG, gpmc_context.sysconfig); gpmc_write_reg(GPMC_IRQENABLE, gpmc_context.irqenable); gpmc_write_reg(GPMC_TIMEOUT_CONTROL, gpmc_context.timeout_ctrl); -- 2.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
On 02/02/2015 11:41 PM, Mike Turquette wrote: Quoting Tero Kristo (2015-02-02 11:32:01) On 02/01/2015 11:24 PM, Mike Turquette wrote: Quoting Tomeu Vizoso (2015-01-23 03:03:30) Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Tero, Paul Tony, Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and struct dpll_data, namely this snippet from arch/arm/mach-omap2/dpll3xxx.c: parent = __clk_get_parent(hw-clk); if (__clk_get_rate(hw-clk) == __clk_get_rate(dd-clk_bypass)) { WARN(parent != dd-clk_bypass, here0, parent name is %s, bypass name is %s\n, __clk_get_name(parent), __clk_get_name(dd-clk_bypass)); r = _omap3_noncore_dpll_bypass(clk); } else { WARN(parent != dd-clk_ref, here1, parent name is %s, ref name is %s\n, __clk_get_name(parent), __clk_get_name(dd-clk_ref)); r = _omap3_noncore_dpll_lock(clk); } struct dpll_data has members clk_ref and clk_bypass which are struct clk pointers. This was always a bit of a violation of the clk.h contract since drivers are not supposed to deref struct clk pointers. Now that we generate unique pointers for each call to clk_get (clk_ref clk_bypass are populated by of_clk_get in ti_clk_register_dpll) then the pointer comparisons above will never be equal (even if they resolve down to the same struct clk_core). I added the verbose traces to the WARNs above to illustrate the point: the names are always the same but the pointers differ. AFAICT this doesn't break anything, but booting on OMAP3+ results in noisy WARNs. I think the correct fix is to replace clk_bypass and clk_ref pointers with a simple integer parent_index. In fact we already have this index. See how the pointers are populated in ti_clk_register_dpll: The problem is we still need to be able to get runtime parent clock rates (the parent rate may change also), so simple index value is not sufficient. We need a handle of some sort to the bypass/ref clocks. The DPLL code generally requires knowledge of the bypass + reference clock rates to work properly, as it calculates the M/N values based on these. We can maybe introduce something like of_clk_get_parent_rate, as we have analogous stuff for getting parent names and indexes. Without introducing a new helper you could probably just do: clk_ref = clk_get_parent_by_index(dpll_clk, 0); ref_rate = clk_get_rate(clk_ref); clk_bypass = clk_get_parent_by_index(dpll_clk, 1); bypass_rate = clk_get_rate(clk_bypass); Currently the semantics around this call are weird. It seems like it would create a new struct clk pointer but it does not. So don't call clk_put on clk_ref and clk_bypass yet. That might change in the future as we iron out this brave new world that we all live in. Probably best to leave a FIXME in there. Stephen Tomeu, let me know if I got any of that wrong. I think you got it right, just wanted to mention that we can and probably should make the clk_get_parent_* calls in the consumer API to return per-user clk instances but that we need to make sure first that callers call clk_put afterwards. This should also allow us to remove the reference to struct clk from clk_hw, which is at best awkward. Regards, Tomeu Shall I change the DPLL code to check against clk_hw pointers or what is the preferred approach here? The patch at the end does this and fixes the dpll related warnings. Yes, for now that is fine, but feels a bit hacky to me. I don't know honestly, let me sleep on it. Anyways for 3.20 that is perfectly fine but we might want to switch to something like the scheme above. Btw, the rate constraints patch broke boot for me completely, but sounds like you reverted it already. Fixed with Stephen's patch from last week. Thanks for dealing with all the breakage so promptly. It has helped a lot! Regards, Mike -Tero Author: Tero Kristo t-kri...@ti.com Date: Mon Feb 2 17:19:17 2015 +0200 ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks DPLL code uses reference and bypass clock pointers for determining runtime properties for these clocks, like parent clock rates. As clock API now returns per
Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
On 31 January 2015 at 02:31, Stephen Boyd sb...@codeaurora.org wrote: On 01/29, Stephen Boyd wrote: On 01/29/15 05:31, Geert Uytterhoeven wrote: Hi Tomeu, Mike, On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso tomeu.viz...@collabora.com wrote: --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk) return 1; } -static void clk_core_put(struct clk_core *core) +void __clk_put(struct clk *clk) { struct module *owner; - owner = core-owner; + if (!clk || WARN_ON_ONCE(IS_ERR(clk))) + return; clk_prepare_lock(); - kref_put(core-ref, __clk_release); + + hlist_del(clk-child_node); + clk_core_set_rate_nolock(clk-core, clk-core-req_rate); At this point, clk-core-req_rate is still zero, causing cpg_div6_clock_round_rate() to be called with a zero rate parameter, e.g. on r8a7791: Hmm.. I wonder if we should assign core-req_rate to be the same as core-rate during __clk_init()? That would make this call to clk_core_set_rate_nolock() a nop in this case. Here's a patch to do this ---8 From: Stephen Boyd sb...@codeaurora.org Subject: [PATCH] clk: Assign a requested rate by default We need to assign a requested rate here so that we avoid requesting a rate of 0 on clocks when we remove clock consumers. Hi, this looks good to me. Reviewed-by: Tomeu Vizoso tomeu.viz...@collabora.com Thanks, Tomeu Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/clk/clk.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index a29daf9edea4..8416ed1c40be 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user) struct clk_core *orphan; struct hlist_node *tmp2; struct clk_core *clk; + unsigned long rate; if (!clk_user) return -EINVAL; @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user) * then rate is set to zero. */ if (clk-ops-recalc_rate) - clk-rate = clk-ops-recalc_rate(clk-hw, + rate = clk-ops-recalc_rate(clk-hw, clk_core_get_rate_nolock(clk-parent)); else if (clk-parent) - clk-rate = clk-parent-rate; + rate = clk-parent-rate; else - clk-rate = 0; + rate = 0; + clk-rate = clk-req_rate = rate; /* * walk the list of orphan clocks and reparent any that are children of -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project ___ linux-arm-kernel mailing list linux-arm-ker...@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v11 2/4] clk: Make clk API return per-user struct clk instances
On 01/22/2015 07:59 PM, Stephen Boyd wrote: On 01/22, Tomeu Vizoso wrote: On 01/22/2015 02:01 AM, Stephen Boyd wrote: BTW, please try and fixup checkpatch warnings. What were you thinking of specifically? I'm running it with --max-line-length=106 and the other warnings are in clk-test.c that I still have to polish when I get some time. I can see that sometimes we exceed the 80 character limits that are configured by default. We mostly stick to 80 in this file it seems so I'm not sure why 106 is being used. Well, if I run checkpatch.pl with the default, I get the 80 char limit which I think worsens readability. I use 106 as an arbitrary placeholder for a bit more than 80, taken from https://lkml.org/lkml/2009/12/17/229 . I'm reformatting to 80 columns. And we do it here where we could remove the #ifdef. Yeah, I tried to reduce the ifdefing back then and this is the simplest I could come up with. The reason for clk_get() to call __clk_create_clk() directly is that it has more relevant information with which to tag the per-user clk. of_clk_get_by_name() has the name of the node but not the dev_id, which in my testing looked as much less useful when debugging who did what to a clock. Agreed. But didn't we add __of_clk_get_by_name() so that we could pass the dev_id and con_id to it? If we did that then all the relevant information is there and we can call __clk_create_clk() directly instead of relying on the caller to do it. Ah, that sounds much better indeed. Will be sending v13 shortly. Thanks, Tomeu -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com Reviewed-by: Stephen Boyd sb...@codeaurora.org --- v13:* Split some lines to 80 columns * Add dev_id parameter to __of_clk_get_by_name so it can be called by clk_get without losing information v12:* Move __clk_create_clk so it's later next to __clk_free_clk * NULLify a just-free'd pointer * Check the value returned by __clk_create_clk in clk_register v11:* Allow for clk_set_parent to be called with a NULL parent v10:* Add more missing NULL checks * Remove __clk_reparent as it's now unused * Remove clk_core_round_rate as it's now unused * Call nolock variants from __clk_mux_determine_rate v9: * Add missing NULL checks * Remove __clk_prepare and __clk_unprepare as they are unused now v7: * Add stub for __of_clk_get_by_name to fix builds without OF v6: * Guard against NULL pointer v4: * Remove unused function __clk_core_to_clk * Use core more often as the name for struct clk_core* variables * Make sure we don't lose information about the caller in of_clk_get_* v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 111 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 621 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 84 - include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 12 +- 8 files changed, 589 insertions(+), 295 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index 644ff32..adb4e64 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -132,7 +132,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -149,12 +149,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -275,9 +275,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT
[PATCH v13 4/6] clk: Add rate constraints to clocks
Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set minimum rates, or by misc. drivers to set maximum rates to assure a minimum performance level. Changes the signature of the determine_rate callback by adding the parameters min_rate and max_rate. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com Reviewed-by: Stephen Boyd sb...@codeaurora.org --- v13:* Cut one line to the 80-column limit * Make clear in the docs that the ranges are inclusive v12:* Refactor locking so that __clk_put takes the lock only once v11:* Recalculate the rate before putting the reference to clk_core * Don't recalculate the rate when freeing the per-user clock in the initialization error paths * Move __clk_create_clk to be next to __clk_free_clk for more comfortable reading v10:* Refactor __clk_determine_rate to share code with clk_round_rate. * Remove clk_core_round_rate_nolock as it's unused now v9: * s/floor/min and s/ceiling/max * Add a bunch of NULL checks * Propagate our rate range when querying our parent for the rate * Take constraints into account in clk_round_rate * Add __clk_determine_rate() for clk providers to ask their parents for a rate within their range * Make sure that what ops-round_rate returns when changing rates is within the range v7: * Update a few more instances in new code v6: * Take the prepare lock before removing a per-user clk * Init per-user clks list before adding the first clk * Pass the constraints to determine_rate and let clk implementations deal with constraints * Add clk_set_rate_range v5: * Initialize clk.ceiling_constraint to ULONG_MAX * Warn about inconsistent constraints v4: * Copy function docs from header * Move WARN out of critical section * Refresh rate after removing a per-user clk * Rename clk_core.per_user_clks to clk_core.clks * Store requested rate and re-apply it when constraints are updated --- Documentation/clk.txt | 2 + arch/arm/mach-omap2/dpll3xxx.c | 2 + arch/arm/mach-omap2/dpll44xx.c | 2 + arch/mips/alchemy/common/clock.c| 8 ++ drivers/clk/at91/clk-programmable.c | 2 + drivers/clk/bcm/clk-kona.c | 2 + drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 249 +--- drivers/clk/hisilicon/clk-hi3620.c | 2 + drivers/clk/mmp/clk-mix.c | 2 + drivers/clk/qcom/clk-pll.c | 1 + drivers/clk/qcom/clk-rcg.c | 10 +- drivers/clk/qcom/clk-rcg2.c | 6 + drivers/clk/sunxi/clk-factors.c | 2 + drivers/clk/sunxi/clk-sun6i-ar100.c | 2 + include/linux/clk-private.h | 6 + include/linux/clk-provider.h| 15 ++- include/linux/clk.h | 28 include/linux/clk/ti.h | 4 + 19 files changed, 298 insertions(+), 56 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 4ff8462..0e4f90a 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -73,6 +73,8 @@ the operations defined in clk.h: unsigned long *parent_rate); long(*determine_rate)(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index c2da2a0..ac3fb11 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) * in failure. */ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 0e58e5a..acacb90 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -222,6 +222,8 @@ out: * in failure. */ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate
Re: [PATCH v11 2/4] clk: Make clk API return per-user struct clk instances
On 01/22/2015 02:01 AM, Stephen Boyd wrote: On 01/21, Tomeu Vizoso wrote: @@ -2075,10 +2210,12 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) } } -ret = __clk_init(dev, clk); +hw-clk = __clk_create_clk(hw, NULL, NULL); +ret = __clk_init(dev, hw-clk); if (!ret) -return clk; +return hw-clk; +kfree(hw-clk); fail_parent_names_copy: while (--i = 0) kfree(clk-parent_names[i]); Sigh, this patch is so huge I keep finding more things. Sorry. It looks like __clk_create_clk() can return an error pointer, which we then send directly to __clk_init. First off, we shouldn't kfree() that pointer if it's an error pointer. Second, we shouldn't crash in __clk_init() in such a situation so there needs to be some sort of check somewhere. Oops, done. I have reused the fail_parent_names_copy label as the less-bad possibility. Probably the error labels should be named after the target code and not after what the source code does, as per the latest CodingStyle additions. BTW, please try and fixup checkpatch warnings. What were you thinking of specifically? I'm running it with --max-line-length=106 and the other warnings are in clk-test.c that I still have to polish when I get some time. diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index da4bda8..fac3244 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -69,20 +70,22 @@ struct clk *of_clk_get(struct device_node *np, int index) [...] -struct clk *of_clk_get_by_name(struct device_node *np, const char *name) +static struct clk *__of_clk_get_by_name(struct device_node *np, const char *name) It would be nice if this returned an already __clk_create_clk()ed pointer. { struct clk *clk = ERR_PTR(-ENOENT); @@ -119,7 +122,33 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name) [...] +struct clk *of_clk_get_by_name(struct device_node *np, const char *name) +{ +struct clk *clk = __of_clk_get_by_name(np, name); + +if (!IS_ERR(clk)) +clk = __clk_create_clk(__clk_get_hw(clk), np-full_name, name); Because we do it here where we know we're CONFIG_COMMON_CLK=y. + +return clk; +} EXPORT_SYMBOL(of_clk_get_by_name); + +#else /* defined(CONFIG_OF) defined(CONFIG_COMMON_CLK) */ + +static struct clk *__of_clk_get_by_name(struct device_node *np, const char *name) +{ +return ERR_PTR(-ENOENT); +} #endif /* @@ -185,9 +229,13 @@ struct clk *clk_get(struct device *dev, const char *con_id) struct clk *clk; if (dev) { -clk = of_clk_get_by_name(dev-of_node, con_id); -if (!IS_ERR(clk)) +clk = __of_clk_get_by_name(dev-of_node, con_id); +if (!IS_ERR(clk)) { +#if defined(CONFIG_COMMON_CLK) +clk = __clk_create_clk(__clk_get_hw(clk), dev_id, con_id); +#endif And we do it here where we could remove the #ifdef. Yeah, I tried to reduce the ifdefing back then and this is the simplest I could come up with. The reason for clk_get() to call __clk_create_clk() directly is that it has more relevant information with which to tag the per-user clk. of_clk_get_by_name() has the name of the node but not the dev_id, which in my testing looked as much less useful when debugging who did what to a clock. Thanks, Tomeu return clk; +} if (PTR_ERR(clk) == -EPROBE_DEFER) return clk; } -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v11 3/4] clk: Add rate constraints to clocks
On 01/22/2015 02:46 AM, Stephen Boyd wrote: On 01/21, Tomeu Vizoso wrote: Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set minimum rates, or by misc. drivers to set maximum rates to assure a minimum performance level. Changes the signature of the determine_rate callback by adding the parameters min_rate and max_rate. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v11: * Recalculate the rate before putting the reference to clk_core * Don't recalculate the rate when freeing the per-user clock in the initialization error paths * Move __clk_create_clk to be next to __clk_free_clk for more comfortable reading Can we do this in the previous patch where we introduce the function? Ok. @@ -2143,9 +2314,16 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw) else clk-owner = NULL; +INIT_HLIST_HEAD(clk-clks); + +hw-clk = __clk_create_clk(hw, NULL, NULL); + ret = __clk_init(dev, hw-clk); -if (ret) +if (ret) { +__clk_free_clk(hw-clk); +hw-clk = NULL; return ERR_PTR(ret); +} return hw-clk; } @@ -2210,12 +2388,16 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) } } +INIT_HLIST_HEAD(clk-clks); + hw-clk = __clk_create_clk(hw, NULL, NULL); ret = __clk_init(dev, hw-clk); if (!ret) return hw-clk; -kfree(hw-clk); +__clk_free_clk(hw-clk); +hw-clk = NULL; Shouldn't we be assigning to NULL in the previous patch (same comment for __clk_register)? Agreed, though I have gone ahead and removed __clk_register completely because AFAICS it has never been used. fail_parent_names_copy: while (--i = 0) kfree(clk-parent_names[i]); @@ -2420,7 +2602,14 @@ void __clk_put(struct clk *clk) if (!clk || WARN_ON_ONCE(IS_ERR(clk))) return; +clk_prepare_lock(); +hlist_del(clk-child_node); +clk_prepare_unlock(); + +clk_core_set_rate(clk-core, clk-core-req_rate); + clk_core_put(clk-core); + Sad that we take the lock 3 times during __clk_put(). We should be able to do it only once if we have a lockless clk_core_set_rate() function and put the contents of clk_core_put() into this function. Actually we need to do that to be thread safe with clk-core-req_rate changing. We can call the same function in clk_set_rate_range() too so that we don't have to deal with recursive locking there. Sweet, done. kfree(clk); } Thanks, Tomeu -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v12 3/6] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v12:* Move __clk_create_clk so it's later next to __clk_free_clk * NULLify a just-free'd pointer * Check the value returned by __clk_create_clk in clk_register v11:* Allow for clk_set_parent to be called with a NULL parent v10:* Add more missing NULL checks * Remove __clk_reparent as it's now unused * Remove clk_core_round_rate as it's now unused * Call nolock variants from __clk_mux_determine_rate v9: * Add missing NULL checks * Remove __clk_prepare and __clk_unprepare as they are unused now v7: * Add stub for __of_clk_get_by_name to fix builds without OF v6: * Guard against NULL pointer v4: * Remove unused function __clk_core_to_clk * Use core more often as the name for struct clk_core* variables * Make sure we don't lose information about the caller in of_clk_get_* v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 616 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 80 - include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 12 +- 8 files changed, 580 insertions(+), 292 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index 644ff32..4305105 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -132,7 +132,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -149,12 +149,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -275,9 +275,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -292,7 +292,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names
[PATCH v12 4/6] clk: Add rate constraints to clocks
Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set minimum rates, or by misc. drivers to set maximum rates to assure a minimum performance level. Changes the signature of the determine_rate callback by adding the parameters min_rate and max_rate. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v12:* Refactor locking so that __clk_put takes the lock only once v11:* Recalculate the rate before putting the reference to clk_core * Don't recalculate the rate when freeing the per-user clock in the initialization error paths * Move __clk_create_clk to be next to __clk_free_clk for more comfortable reading v10:* Refactor __clk_determine_rate to share code with clk_round_rate. * Remove clk_core_round_rate_nolock as it's unused now v9: * s/floor/min and s/ceiling/max * Add a bunch of NULL checks * Propagate our rate range when querying our parent for the rate * Take constraints into account in clk_round_rate * Add __clk_determine_rate() for clk providers to ask their parents for a rate within their range * Make sure that what ops-round_rate returns when changing rates is within the range v7: * Update a few more instances in new code v6: * Take the prepare lock before removing a per-user clk * Init per-user clks list before adding the first clk * Pass the constraints to determine_rate and let clk implementations deal with constraints * Add clk_set_rate_range v5: * Initialize clk.ceiling_constraint to ULONG_MAX * Warn about inconsistent constraints v4: * Copy function docs from header * Move WARN out of critical section * Refresh rate after removing a per-user clk * Rename clk_core.per_user_clks to clk_core.clks * Store requested rate and re-apply it when constraints are updated --- Documentation/clk.txt | 2 + arch/arm/mach-omap2/dpll3xxx.c | 2 + arch/arm/mach-omap2/dpll44xx.c | 2 + arch/mips/alchemy/common/clock.c| 8 ++ drivers/clk/at91/clk-programmable.c | 2 + drivers/clk/bcm/clk-kona.c | 2 + drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 248 +--- drivers/clk/hisilicon/clk-hi3620.c | 2 + drivers/clk/mmp/clk-mix.c | 2 + drivers/clk/qcom/clk-pll.c | 1 + drivers/clk/qcom/clk-rcg.c | 10 +- drivers/clk/qcom/clk-rcg2.c | 6 + drivers/clk/sunxi/clk-factors.c | 2 + drivers/clk/sunxi/clk-sun6i-ar100.c | 2 + include/linux/clk-private.h | 6 + include/linux/clk-provider.h| 15 ++- include/linux/clk.h | 28 include/linux/clk/ti.h | 4 + 19 files changed, 297 insertions(+), 56 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 4ff8462..0e4f90a 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -73,6 +73,8 @@ the operations defined in clk.h: unsigned long *parent_rate); long(*determine_rate)(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index c2da2a0..ac3fb11 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) * in failure. */ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 0e58e5a..acacb90 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -222,6 +222,8 @@ out: * in failure. */ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/mips/alchemy/common/clock.c b/arch
[PATCH v11 3/4] clk: Add rate constraints to clocks
Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set minimum rates, or by misc. drivers to set maximum rates to assure a minimum performance level. Changes the signature of the determine_rate callback by adding the parameters min_rate and max_rate. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v11:* Recalculate the rate before putting the reference to clk_core * Don't recalculate the rate when freeing the per-user clock in the initialization error paths * Move __clk_create_clk to be next to __clk_free_clk for more comfortable reading v10:* Refactor __clk_determine_rate to share code with clk_round_rate. * Remove clk_core_round_rate_nolock as it's unused now v9: * s/floor/min and s/ceiling/max * Add a bunch of NULL checks * Propagate our rate range when querying our parent for the rate * Take constraints into account in clk_round_rate * Add __clk_determine_rate() for clk providers to ask their parents for a rate within their range * Make sure that what ops-round_rate returns when changing rates is within the range v7: * Update a few more instances in new code v6: * Take the prepare lock before removing a per-user clk * Init per-user clks list before adding the first clk * Pass the constraints to determine_rate and let clk implementations deal with constraints * Add clk_set_rate_range v5: * Initialize clk.ceiling_constraint to ULONG_MAX * Warn about inconsistent constraints v4: * Copy function docs from header * Move WARN out of critical section * Refresh rate after removing a per-user clk * Rename clk_core.per_user_clks to clk_core.clks * Store requested rate and re-apply it when constraints are updated --- Documentation/clk.txt | 2 + arch/arm/mach-omap2/dpll3xxx.c | 2 + arch/arm/mach-omap2/dpll44xx.c | 2 + arch/mips/alchemy/common/clock.c| 8 + drivers/clk/at91/clk-programmable.c | 2 + drivers/clk/bcm/clk-kona.c | 2 + drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 285 drivers/clk/hisilicon/clk-hi3620.c | 2 + drivers/clk/mmp/clk-mix.c | 2 + drivers/clk/qcom/clk-pll.c | 1 + drivers/clk/qcom/clk-rcg.c | 10 +- drivers/clk/qcom/clk-rcg2.c | 6 + drivers/clk/sunxi/clk-factors.c | 2 + drivers/clk/sunxi/clk-sun6i-ar100.c | 2 + include/linux/clk-private.h | 6 + include/linux/clk-provider.h| 15 +- include/linux/clk.h | 28 include/linux/clk/ti.h | 4 + 19 files changed, 325 insertions(+), 65 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 4ff8462..0e4f90a 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -73,6 +73,8 @@ the operations defined in clk.h: unsigned long *parent_rate); long(*determine_rate)(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index c2da2a0..ac3fb11 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) * in failure. */ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 0e58e5a..acacb90 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -222,6 +222,8 @@ out: * in failure. */ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index 48a9dfc..4e65404 100644 --- a/arch/mips
[PATCH v11 2/4] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v11:* Allow for clk_set_parent to be called with a NULL parent v10:* Add more missing NULL checks * Remove __clk_reparent as it's now unused * Remove clk_core_round_rate as it's now unused * Call nolock variants from __clk_mux_determine_rate v9: * Add missing NULL checks * Remove __clk_prepare and __clk_unprepare as they are unused now v7: * Add stub for __of_clk_get_by_name to fix builds without OF v6: * Guard against NULL pointer v4: * Remove unused function __clk_core_to_clk * Use core more often as the name for struct clk_core* variables * Make sure we don't lose information about the caller in of_clk_get_* v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 628 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 80 +++- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 12 +- 8 files changed, 583 insertions(+), 301 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index 644ff32..4305105 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -132,7 +132,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -149,12 +149,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -275,9 +275,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -292,7 +292,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL
Re: [PATCH v9 2/3] clk: Make clk API return per-user struct clk instances
On 19 January 2015 at 21:59, Stephen Boyd sb...@codeaurora.org wrote: On 01/19, Tomeu Vizoso wrote: diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 97f3425..f2a1ff3 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -694,32 +751,32 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_p) { - struct clk *clk = hw-clk, *parent, *best_parent = NULL; + struct clk_core *core = hw-clk-core, *parent, *best_parent = NULL; Can't we just use hw-core here? Yup. int i, num_parents; unsigned long parent_rate, best = 0; @@ -820,15 +877,18 @@ int clk_prepare(struct clk *clk) { int ret; + if (IS_ERR_OR_NULL(clk)) + return PTR_ERR(clk); What's going on here? Should be if (!clk)? Yeah, guess I miscopied it from a function that was expected to be called chained with others. + clk_prepare_lock(); - ret = __clk_prepare(clk); + ret = clk_core_prepare(clk-core); clk_prepare_unlock(); return ret; } EXPORT_SYMBOL_GPL(clk_prepare); @@ -1066,9 +1149,24 @@ long clk_get_accuracy(struct clk *clk) return accuracy; } + +/** + * clk_get_accuracy - return the accuracy of clk + * @clk: the clk whose accuracy is being returned + * + * Simply returns the cached accuracy of the clk, unless + * CLK_GET_ACCURACY_NOCACHE flag is set, which means a recalc_rate will be + * issued. + * If clk is NULL then returns 0. + */ +long clk_get_accuracy(struct clk *clk) +{ + return clk_core_get_accuracy(clk-core); Oops. Missing NULL check. Yup. +} EXPORT_SYMBOL_GPL(clk_get_accuracy); @@ -1130,14 +1220,29 @@ unsigned long clk_get_rate(struct clk *clk) [...] + * + * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag + * is set, which means a recalc_rate will be issued. + * If clk is NULL then returns 0. + */ +unsigned long clk_get_rate(struct clk *clk) +{ + return clk_core_get_rate(clk-core); Oops. Missing NULL check. Agreed. +} EXPORT_SYMBOL_GPL(clk_get_rate); @@ -1629,37 +1741,26 @@ static struct clk *__clk_init_parent(struct clk *clk) [...] -int clk_set_parent(struct clk *clk, struct clk *parent) +void __clk_reparent(struct clk *clk, struct clk *new_parent) +{ + clk_core_reparent(clk-core, new_parent-core); +} Is this used? Looks like we can remove it. Sorry, not sure how I missed this last time. Yes, done. + +static int clk_core_set_parent(struct clk_core *clk, struct clk_core *parent) { int ret = 0; int p_index = 0; @@ -1719,6 +1820,28 @@ out: [...] +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + return clk_core_set_parent(clk-core, parent-core); Oops. Missing NULL check for both inputs. Agreed. +} EXPORT_SYMBOL_GPL(clk_set_parent); /** @@ -1793,18 +1909,31 @@ out: } /** + * clk_get_phase - return the phase shift of a clock signal + * @clk: clock signal source + * + * Returns the phase shift of a clock node in degrees, otherwise returns + * -EERROR. + */ +int clk_get_phase(struct clk *clk) +{ + return clk_core_get_phase(clk-core); Oops. Missing NULL check. Agreed. I have also reworked the changes to __clk_init to maintain the existing behaviour. Thanks, Tomeu -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v9 3/3] clk: Add floor and ceiling constraints to clock rates
On 20 January 2015 at 01:00, Stephen Boyd sb...@codeaurora.org wrote: On 01/19, Tomeu Vizoso wrote: Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set ceiling rates, or by misc. drivers to set floor rates to assure a minimum performance level. Changes the signature of the determine_rate callback by adding the parameters floor_rate and ceiling_rate. Commit text needs the s/floor/min and s/ceiling/max treatment too. diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f2a1ff3..55b3124 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1026,6 +1051,28 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk, else return clk-rate; } +unsigned long __clk_determine_rate(struct clk_hw *hw, +unsigned long rate, +unsigned long min_rate, +unsigned long max_rate) +{ + unsigned long parent_rate = 0; + struct clk_core *core = hw-core; + struct clk_hw *parent_hw; + + if (!core-ops-determine_rate) + return 0; + + if (core-parent) { + parent_rate = core-parent-rate; + parent_hw = core-parent-hw; + } + + return core-ops-determine_rate(core-hw, rate, + min_rate, max_rate, + parent_rate, parent_hw); +} +EXPORT_SYMBOL_GPL(__clk_determine_rate); Maybe I misled you with the API name. I was thinking more along the lines of clk_round_rate() and this new function ending up calling clk_core_round_rate(), but clk_round_rate() would call it with whatever range the clock is constrained to while this new function would allow driver authors to specify the range. It should be easy enough to add min/max to clk_core_round_rate() given that it's a private API in this file. Yeah, I wasn't sure whether it made sense for __clk_determine_rate to have the fallbacks because any caller would need to have checked that the clock implementation supports determine_rate and is aware of the rate constraints. As long as people don't get confused, I'm fine with any of the possibilities. Regards, Tomeu -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v10 2/3] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v10:* Add more missing NULL checks * Remove __clk_reparent as it's now unused * Remove clk_core_round_rate as it's now unused * Call nolock variants from __clk_mux_determine_rate v9: * Add missing NULL checks * Remove __clk_prepare and __clk_unprepare as they are unused now v7: * Add stub for __of_clk_get_by_name to fix builds without OF v6: * Guard against NULL pointer v4: * Remove unused function __clk_core_to_clk * Use core more often as the name for struct clk_core* variables * Make sure we don't lose information about the caller in of_clk_get_* v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 628 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 80 +++- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 12 +- 8 files changed, 583 insertions(+), 301 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index 644ff32..4305105 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -132,7 +132,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -149,12 +149,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -275,9 +275,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -292,7 +292,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), OMAP3430_ST_MPU_CLK_SHIFT
[PATCH v10 3/3] clk: Add rate constraints to clocks
Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set minimum rates, or by misc. drivers to set maximum rates to assure a minimum performance level. Changes the signature of the determine_rate callback by adding the parameters min_rate and max_rate. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v10:* Refactor __clk_determine_rate to share code with clk_round_rate. * Remove clk_core_round_rate_nolock as it's unused now v9: * s/floor/min and s/ceiling/max * Add a bunch of NULL checks * Propagate our rate range when querying our parent for the rate * Take constraints into account in clk_round_rate * Add __clk_determine_rate() for clk providers to ask their parents for a rate within their range * Make sure that what ops-round_rate returns when changing rates is within the range v7: * Update a few more instances in new code v6: * Take the prepare lock before removing a per-user clk * Init per-user clks list before adding the first clk * Pass the constraints to determine_rate and let clk implementations deal with constraints * Add clk_set_rate_range v5: * Initialize clk.ceiling_constraint to ULONG_MAX * Warn about inconsistent constraints v4: * Copy function docs from header * Move WARN out of critical section * Refresh rate after removing a per-user clk * Rename clk_core.per_user_clks to clk_core.clks * Store requested rate and re-apply it when constraints are updated --- Documentation/clk.txt | 2 + arch/arm/mach-omap2/dpll3xxx.c | 2 + arch/arm/mach-omap2/dpll44xx.c | 2 + arch/mips/alchemy/common/clock.c| 8 ++ drivers/clk/at91/clk-programmable.c | 2 + drivers/clk/bcm/clk-kona.c | 2 + drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 237 ++-- drivers/clk/hisilicon/clk-hi3620.c | 2 + drivers/clk/mmp/clk-mix.c | 2 + drivers/clk/qcom/clk-pll.c | 1 + drivers/clk/qcom/clk-rcg.c | 10 +- drivers/clk/qcom/clk-rcg2.c | 6 + drivers/clk/sunxi/clk-factors.c | 2 + drivers/clk/sunxi/clk-sun6i-ar100.c | 2 + include/linux/clk-private.h | 6 + include/linux/clk-provider.h| 15 ++- include/linux/clk.h | 28 + include/linux/clk/ti.h | 4 + 19 files changed, 297 insertions(+), 45 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 4ff8462..0e4f90a 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -73,6 +73,8 @@ the operations defined in clk.h: unsigned long *parent_rate); long(*determine_rate)(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index c2da2a0..ac3fb11 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) * in failure. */ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 0e58e5a..acacb90 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -222,6 +222,8 @@ out: * in failure. */ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index 48a9dfc..4e65404 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -373,6 +373,8 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate, } static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate
Re: [PATCH RESEND v8 1/2] clk: Make clk API return per-user struct clk instances
On 17 January 2015 at 02:02, Stephen Boyd sb...@codeaurora.org wrote: On 01/12, Tomeu Vizoso wrote: Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com Looks mostly good. Missing some NULL checks mostly. Sorry about that, I should have been more careful there. diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f4963b7..7eddfd8 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -114,7 +123,7 @@ static struct hlist_head *orphan_list[] = { +static void clk_summary_show_one(struct seq_file *s, struct clk_core *c, int level) { if (!c) return; @@ -122,14 +131,14 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) [...] -static void clk_summary_show_subtree(struct seq_file *s, struct clk *c, +static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c, int level) { - struct clk *child; + struct clk_core *child; if (!c) return; @@ -172,7 +181,7 @@ static const struct file_operations clk_summary_fops = { .release= single_release, }; -static void clk_dump_one(struct seq_file *s, struct clk *c, int level) +static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level) { if (!c) return; @@ -180,14 +189,14 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level) [...] -static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level) +static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level) { - struct clk *child; + struct clk_core *child; if (!c) return; @@ -418,19 +427,20 @@ static int __init clk_debug_init(void) [...] /* caller must hold prepare_lock */ -static void clk_unprepare_unused_subtree(struct clk *clk) +static void clk_unprepare_unused_subtree(struct clk_core *clk) { - struct clk *child; + struct clk_core *child; if (!clk) return; @@ -453,9 +463,9 @@ static void clk_unprepare_unused_subtree(struct clk *clk) } /* caller must hold prepare_lock */ -static void clk_disable_unused_subtree(struct clk *clk) +static void clk_disable_unused_subtree(struct clk_core *clk) { - struct clk *child; + struct clk_core *child; unsigned long flags; if (!clk) Note: These NULL checks look bogus. No need to fix them here, but a patch to remove them would be nice. Indeed. @@ -532,48 +542,59 @@ late_initcall_sync(clk_disable_unused); [...] + +struct clk *clk_get_parent_by_index(struct clk *clk, u8 index) +{ + struct clk_core *parent; + + parent = clk_core_get_parent_by_index(clk-core, index); I suppose clk could be NULL here (although this is mostly a clk-provider function). At least before we would return NULL in such a case so we should keep the same behavior instead of NULL deref. Agreed. + + return !parent ? NULL : parent-hw-clk; +} EXPORT_SYMBOL_GPL(clk_get_parent_by_index); @@ -593,9 +614,14 @@ unsigned long __clk_get_rate(struct clk *clk) out: return ret; } + +unsigned long __clk_get_rate(struct clk *clk) +{ + return clk_core_get_rate_nolock(clk-core); Oops. clk can be NULL here. We should check for that and return 0. Agreed. +} EXPORT_SYMBOL_GPL(__clk_get_rate); @@ -630,7 +656,12 @@ out: return !!ret; } -bool __clk_is_enabled(struct clk *clk) +bool __clk_is_prepared(struct clk *clk) +{ + return clk_core_is_prepared(clk-core); Oops. clk can be NULL here. Return false if so. Or drop the function entirely? It looks like it may become unused. Are you thinking of anything specific that the alchemy arch can do instead of calling __clk_is_prepared? +} @@ -650,12 +681,17 @@ bool __clk_is_enabled(struct clk *clk) out: return !!ret; } + +bool __clk_is_enabled(struct clk *clk) +{ + return clk_core_is_enabled(clk-core); Oops. clk can be NULL here. Return false if so. Agreed. +} EXPORT_SYMBOL_GPL(__clk_is_enabled); @@ -762,7 +805,12 @@ void __clk_unprepare(struct clk *clk) if (clk-ops-unprepare) clk-ops-unprepare(clk-hw); - __clk_unprepare(clk-parent); + clk_core_unprepare(clk-parent); +} + +void __clk_unprepare(struct clk *clk) +{ + clk_core_unprepare(clk-core); OOps. clk can be NULL here. Bail
Re: [PATCH RESEND v8 2/2] clk: Add floor and ceiling constraints to clock rates
On 17 January 2015 at 02:57, Stephen Boyd sb...@codeaurora.org wrote: On 01/12, Tomeu Vizoso wrote: diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7eddfd8..2793bd7 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1013,8 +1015,8 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk, if (clk-ops-determine_rate) { parent_hw = parent ? parent-hw : NULL; - return clk-ops-determine_rate(clk-hw, rate, parent_rate, - parent_hw); + return clk-ops-determine_rate(clk-hw, rate, 0, ULONG_MAX, + parent_rate, parent_hw); } else if (clk-ops-round_rate) return clk-ops-round_rate(clk-hw, rate, parent_rate); else if (clk-flags CLK_SET_RATE_PARENT) @@ -1453,8 +1458,20 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk, /* find the closest rate and parent clk/rate */ if (clk-ops-determine_rate) { + hlist_for_each_entry(clk_user, clk-clks, child_node) { + floor_rate = max(floor_rate, + clk_user-floor_constraint); + } + + hlist_for_each_entry(clk_user, clk-clks, child_node) { + ceiling_rate = min(ceiling_rate, +clk_user-ceiling_constraint); + } I would think we need to do this in the clk_round_rate() path as well. We can't just pass 0 and ULONG_MAX there or we'll determine one rate here and another rate in round_rate(), violating the contract between set_rate() and round_rate(). Right, I have added a test for this. + parent_hw = parent ? parent-hw : NULL; new_rate = clk-ops-determine_rate(clk-hw, rate, + floor_rate, + ceiling_rate, best_parent_rate, parent_hw); parent = parent_hw ? parent_hw-core : NULL; We should enforce a constraint if the clk is using the round_rate() op too. If the .round_rate() op returns some rate within range it should be ok. Otherwise we can fail the rate change because it's out of range. Ok. We'll also need to introduce some sort of clk_core_determine_rate(core, rate, min, max) so that clock providers can ask parent clocks to find a rate within some range that they can tolerate. If we update __clk_mux_determine_rate() we can see how that would work out. Ok, I'm testing this case as well now. @@ -1660,13 +1657,92 @@ int clk_set_rate(struct clk *clk, unsigned long rate) [...] + */ +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return clk_core_set_rate(clk-core, rate); clk could be NULL. +} EXPORT_SYMBOL_GPL(clk_set_rate); +int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max) +{ + int ret = 0; Check for NULL clk. + +/** + * clk_set_floor_rate - set a minimum clock rate for a clock source + * @clk: clock source + * @rate: desired minimum clock rate in Hz + * + * Returns success (0) or negative errno. + */ +int clk_set_floor_rate(struct clk *clk, unsigned long rate) +{ + return clk_set_rate_range(clk, rate, clk-ceiling_constraint); clk could be NULL. +} +EXPORT_SYMBOL_GPL(clk_set_floor_rate); + +/** + * clk_set_ceiling_rate - set a maximum clock rate for a clock source + * @clk: clock source + * @rate: desired maximum clock rate in Hz + * + * Returns success (0) or negative errno. + */ +int clk_set_ceiling_rate(struct clk *clk, unsigned long rate) +{ + return clk_set_rate_range(clk, clk-floor_constraint, rate); clk could be NULL. +} +EXPORT_SYMBOL_GPL(clk_set_ceiling_rate); + static struct clk_core *clk_core_get_parent(struct clk_core *core) { struct clk_core *parent; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 2e65419..ae5c800 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -175,9 +175,12 @@ struct clk_ops { unsigned long parent_rate); long(*round_rate)(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate); - long(*determine_rate)(struct clk_hw *hw, unsigned long rate, - unsigned long *best_parent_rate, - struct clk_hw **best_parent_hw); + long(*determine_rate)(struct clk_hw *hw, + unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, I wonder if we should call this min_rate
[PATCH v9 2/3] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v9: * Add missing NULL checks * Remove __clk_prepare and __clk_unprepare as they are unused now v7: * Add stub for __of_clk_get_by_name to fix builds without OF v6: * Guard against NULL pointer v4: * Remove unused function __clk_core_to_clk * Use core more often as the name for struct clk_core* variables * Make sure we don't lose information about the caller in of_clk_get_* v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 633 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 80 +++- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 11 +- 8 files changed, 583 insertions(+), 305 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index 644ff32..4305105 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -132,7 +132,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -149,12 +149,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -275,9 +275,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -292,7 +292,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH, 0x0, NULL); @@ -424,7 +424,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = { { .div = 0 }, }; -DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck, 0x0
[PATCH v9 3/3] clk: Add floor and ceiling constraints to clock rates
Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set ceiling rates, or by misc. drivers to set floor rates to assure a minimum performance level. Changes the signature of the determine_rate callback by adding the parameters floor_rate and ceiling_rate. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v9: * s/floor/min and s/ceiling/max * Add a bunch of NULL checks * Propagate our rate range when querying our parent for the rate * Take constraints into account in clk_round_rate * Add __clk_determine_rate() for clk providers to ask their parents for a rate within their range * Make sure that what ops-round_rate returns when changing rates is within the range v7: * Update a few more instances in new code v6: * Take the prepare lock before removing a per-user clk * Init per-user clks list before adding the first clk * Pass the constraints to determine_rate and let clk implementations deal with constraints * Add clk_set_rate_range v5: * Initialize clk.ceiling_constraint to ULONG_MAX * Warn about inconsistent constraints v4: * Copy function docs from header * Move WARN out of critical section * Refresh rate after removing a per-user clk * Rename clk_core.per_user_clks to clk_core.clks * Store requested rate and re-apply it when constraints are updated --- Documentation/clk.txt | 2 + arch/arm/mach-omap2/dpll3xxx.c | 2 + arch/arm/mach-omap2/dpll44xx.c | 2 + arch/mips/alchemy/common/clock.c| 8 ++ drivers/clk/at91/clk-programmable.c | 2 + drivers/clk/bcm/clk-kona.c | 2 + drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 216 ++-- drivers/clk/hisilicon/clk-hi3620.c | 2 + drivers/clk/mmp/clk-mix.c | 2 + drivers/clk/qcom/clk-pll.c | 1 + drivers/clk/qcom/clk-rcg.c | 10 +- drivers/clk/qcom/clk-rcg2.c | 6 + drivers/clk/sunxi/clk-factors.c | 2 + drivers/clk/sunxi/clk-sun6i-ar100.c | 2 + include/linux/clk-private.h | 6 + include/linux/clk-provider.h| 15 ++- include/linux/clk.h | 28 + include/linux/clk/ti.h | 4 + 19 files changed, 281 insertions(+), 40 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 4ff8462..0e4f90a 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -73,6 +73,8 @@ the operations defined in clk.h: unsigned long *parent_rate); long(*determine_rate)(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index c2da2a0..ac3fb11 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) * in failure. */ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 0e58e5a..acacb90 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -222,6 +222,8 @@ out: * in failure. */ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index 48a9dfc..4e65404 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -373,6 +373,8 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate, } static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, + unsigned long min_rate, + unsigned long max_rate, unsigned long
[PATCH RESEND v8 1/2] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v7: * Add stub for __of_clk_get_by_name to fix builds without OF v6: * Guard against NULL pointer v4: * Remove unused function __clk_core_to_clk * Use core more often as the name for struct clk_core* variables * Make sure we don't lose information about the caller in of_clk_get_* v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 644 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 80 +++- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 9 +- 8 files changed, 584 insertions(+), 313 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index 644ff32..4305105 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -132,7 +132,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -149,12 +149,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -275,9 +275,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -292,7 +292,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH, 0x0, NULL); @@ -424,7 +424,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = { { .div = 0 }, }; -DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck_core, 0x0, OMAP_CM_REGADDR(OMAP3430_CAM_MOD
[PATCH RESEND v8 2/2] clk: Add floor and ceiling constraints to clock rates
Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set ceiling rates, or by misc. drivers to set floor rates to assure a minimum performance level. Changes the signature of the determine_rate callback by adding the parameters floor_rate and ceiling_rate. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v7: * Update a few more instances in new code v6: * Take the prepare lock before removing a per-user clk * Init per-user clks list before adding the first clk * Pass the constraints to determine_rate and let clk implementations deal with constraints * Add clk_set_rate_range v5: * Initialize clk.ceiling_constraint to ULONG_MAX * Warn about inconsistent constraints v4: * Copy function docs from header * Move WARN out of critical section * Refresh rate after removing a per-user clk * Rename clk_core.per_user_clks to clk_core.clks * Store requested rate and re-apply it when constraints are updated --- Documentation/clk.txt | 2 + arch/arm/mach-omap2/dpll3xxx.c | 2 + arch/arm/mach-omap2/dpll44xx.c | 2 + arch/mips/alchemy/common/clock.c| 8 ++ drivers/clk/at91/clk-programmable.c | 2 + drivers/clk/bcm/clk-kona.c | 2 + drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 160 +--- drivers/clk/hisilicon/clk-hi3620.c | 2 + drivers/clk/mmp/clk-mix.c | 2 + drivers/clk/qcom/clk-pll.c | 1 + drivers/clk/qcom/clk-rcg.c | 10 ++- drivers/clk/qcom/clk-rcg2.c | 6 ++ drivers/clk/sunxi/clk-factors.c | 2 + drivers/clk/sunxi/clk-sun6i-ar100.c | 2 + include/linux/clk-private.h | 6 ++ include/linux/clk-provider.h| 11 ++- include/linux/clk.h | 28 +++ include/linux/clk/ti.h | 4 + 19 files changed, 224 insertions(+), 37 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 4ff8462..8ebd665 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -73,6 +73,8 @@ the operations defined in clk.h: unsigned long *parent_rate); long(*determine_rate)(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index c2da2a0..b25375c 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) * in failure. */ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 0e58e5a..579fa18 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -222,6 +222,8 @@ out: * in failure. */ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index 48a9dfc..731bedd 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -373,6 +373,8 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate, } static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk, int scale, int maxdiv) @@ -546,6 +548,8 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw, } static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate
[PATCH v7 5/7] clk: Change clk_ops-determine_rate to return a clk_hw as the best parent
This is in preparation for clock providers to not have to deal with struct clk. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com Reviewed-by: Stephen Boyd sb...@codeaurora.org --- v7: * Update a few more instances in new code v4: * Make sure that best_parent_p is populated with the current parent before calling clk_ops.determine_rate() v3: * Rebase on top of linux-next 20141009 * Update Documentation/clk.txt --- Documentation/clk.txt | 2 +- arch/arm/mach-omap2/dpll3xxx.c | 6 +++--- arch/arm/mach-omap2/dpll44xx.c | 6 +++--- arch/mips/alchemy/common/clock.c| 10 +- drivers/clk/at91/clk-programmable.c | 4 ++-- drivers/clk/bcm/clk-kona.c | 4 ++-- drivers/clk/clk-composite.c | 9 + drivers/clk/clk.c | 17 +++-- drivers/clk/hisilicon/clk-hi3620.c | 2 +- drivers/clk/mmp/clk-mix.c | 4 ++-- drivers/clk/qcom/clk-pll.c | 2 +- drivers/clk/qcom/clk-rcg.c | 20 drivers/clk/qcom/clk-rcg2.c | 28 +--- drivers/clk/sunxi/clk-factors.c | 4 ++-- drivers/clk/sunxi/clk-sun6i-ar100.c | 4 ++-- include/linux/clk-provider.h| 4 ++-- include/linux/clk/ti.h | 4 ++-- 17 files changed, 73 insertions(+), 57 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 1fee72f..4ff8462 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -74,7 +74,7 @@ the operations defined in clk.h: long(*determine_rate)(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk); + struct clk_hw **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index 20e120d..c2da2a0 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -474,7 +474,7 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) */ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk) + struct clk_hw **best_parent_clk) { struct clk_hw_omap *clk = to_clk_hw_omap(hw); struct dpll_data *dd; @@ -488,10 +488,10 @@ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, if (__clk_get_rate(dd-clk_bypass) == rate (dd-modes (1 DPLL_LOW_POWER_BYPASS))) { - *best_parent_clk = dd-clk_bypass; + *best_parent_clk = __clk_get_hw(dd-clk_bypass); } else { rate = omap2_dpll_round_rate(hw, rate, best_parent_rate); - *best_parent_clk = dd-clk_ref; + *best_parent_clk = __clk_get_hw(dd-clk_ref); } *best_parent_rate = rate; diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 535822f..0e58e5a 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -223,7 +223,7 @@ out: */ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, - struct clk **best_parent_clk) + struct clk_hw **best_parent_clk) { struct clk_hw_omap *clk = to_clk_hw_omap(hw); struct dpll_data *dd; @@ -237,11 +237,11 @@ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, if (__clk_get_rate(dd-clk_bypass) == rate (dd-modes (1 DPLL_LOW_POWER_BYPASS))) { - *best_parent_clk = dd-clk_bypass; + *best_parent_clk = __clk_get_hw(dd-clk_bypass); } else { rate = omap4_dpll_regm4xen_round_rate(hw, rate, best_parent_rate); - *best_parent_clk = dd-clk_ref; + *best_parent_clk = __clk_get_hw(dd-clk_ref); } *best_parent_rate = rate; diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index 203e440..48a9dfc 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -374,7 +374,7 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate, static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, unsigned long
[PATCH v7 7/7] clk: Add floor and ceiling constraints to clock rates
Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set ceiling rates, or by misc. drivers to set floor rates to assure a minimum performance level. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v7: * Update a few more instances in new code v6: * Take the prepare lock before removing a per-user clk * Init per-user clks list before adding the first clk * Pass the constraints to determine_rate and let clk implementations deal with constraints * Add clk_set_rate_range v5: * Initialize clk.ceiling_constraint to ULONG_MAX * Warn about inconsistent constraints v4: * Copy function docs from header * Move WARN out of critical section * Refresh rate after removing a per-user clk * Rename clk_core.per_user_clks to clk_core.clks * Store requested rate and re-apply it when constraints are updated --- Documentation/clk.txt | 2 + arch/arm/mach-omap2/dpll3xxx.c | 2 + arch/arm/mach-omap2/dpll44xx.c | 2 + arch/mips/alchemy/common/clock.c| 8 ++ drivers/clk/at91/clk-programmable.c | 2 + drivers/clk/bcm/clk-kona.c | 2 + drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 160 +--- drivers/clk/hisilicon/clk-hi3620.c | 2 + drivers/clk/mmp/clk-mix.c | 2 + drivers/clk/qcom/clk-pll.c | 1 + drivers/clk/qcom/clk-rcg.c | 10 ++- drivers/clk/qcom/clk-rcg2.c | 6 ++ drivers/clk/sunxi/clk-factors.c | 2 + drivers/clk/sunxi/clk-sun6i-ar100.c | 2 + include/linux/clk-private.h | 6 ++ include/linux/clk-provider.h| 11 ++- include/linux/clk.h | 28 +++ include/linux/clk/ti.h | 4 + 19 files changed, 224 insertions(+), 37 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 4ff8462..8ebd665 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -73,6 +73,8 @@ the operations defined in clk.h: unsigned long *parent_rate); long(*determine_rate)(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index c2da2a0..b25375c 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) * in failure. */ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 0e58e5a..579fa18 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -222,6 +222,8 @@ out: * in failure. */ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index 48a9dfc..731bedd 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -373,6 +373,8 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate, } static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk, int scale, int maxdiv) @@ -546,6 +548,8 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw, } static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long
[PATCH v7 0/7] Per-user clock constraints
Hello, this seventh version of the series has added just a few fixes for new implementations in linux-next of the determine_rate callback. A rough test module was used to test this: http://cgit.collabora.com/git/user/tomeu/linux.git/commit/?h=per-user-clk-constraints-v7id=3d87d46d98f74b6f53eadf0d28785a3cd85c2178 The first five patches are just cleanups that should be desirable on their own, and that should make easier to review the actual per-user clock patch. The sixth patch actually moves the per-clock data that was stored in struct clk to a new struct clk_core and adds references to it from both struct clk and struct clk_hw. struct clk is now ready to contain information that is specific to a given clk consumer. The seventh patch adds API for setting floor and ceiling constraints and stores that information on the per-user struct clk, which is iterable from struct clk_core. They are based on top of linux-next 20141201. http://cgit.collabora.com/git/user/tomeu/linux.git/log/?h=per-user-clk-constraints-v7 Thanks, Tomeu Tomeu Vizoso (7): clk: Remove unused function __clk_get_prepare_count clk: Don't try to use a struct clk* after it could have been freed clk: Don't expose __clk_get_accuracy clk: change clk_debugfs_add_file to take a struct clk_hw clk: Change clk_ops-determine_rate to return a clk_hw as the best parent clk: Make clk API return per-user struct clk instances clk: Add floor and ceiling constraints to clock rates Documentation/clk.txt | 4 +- arch/arm/mach-omap2/cclock3xxx_data.c | 108 +++-- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- arch/arm/mach-omap2/dpll3xxx.c | 8 +- arch/arm/mach-omap2/dpll44xx.c | 8 +- arch/mips/alchemy/common/clock.c| 18 +- drivers/clk/at91/clk-programmable.c | 6 +- drivers/clk/bcm/clk-kona.c | 6 +- drivers/clk/clk-composite.c | 18 +- drivers/clk/clk.c | 807 +--- drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 80 +++- drivers/clk/hisilicon/clk-hi3620.c | 4 +- drivers/clk/mmp/clk-mix.c | 6 +- drivers/clk/qcom/clk-pll.c | 3 +- drivers/clk/qcom/clk-rcg.c | 30 +- drivers/clk/qcom/clk-rcg2.c | 34 +- drivers/clk/sunxi/clk-factors.c | 6 +- drivers/clk/sunxi/clk-sun6i-ar100.c | 6 +- include/linux/clk-private.h | 41 +- include/linux/clk-provider.h| 26 +- include/linux/clk.h | 28 ++ include/linux/clk/ti.h | 8 +- 24 files changed, 873 insertions(+), 403 deletions(-) -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v7 6/7] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v7: * Add stub for __of_clk_get_by_name to fix builds without OF v6: * Guard against NULL pointer v4: * Remove unused function __clk_core_to_clk * Use core more often as the name for struct clk_core* variables * Make sure we don't lose information about the caller in of_clk_get_* v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 644 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 80 +++- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 9 +- 8 files changed, 584 insertions(+), 313 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index 5c5ebb4..fe722d8 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -131,7 +131,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -148,12 +148,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -274,9 +274,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -291,7 +291,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH, 0x0, NULL); @@ -423,7 +423,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = { { .div = 0 }, }; -DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck_core, 0x0, OMAP_CM_REGADDR(OMAP3430_CAM_MOD
[PATCH v6 6/7] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v6: * Guard against NULL pointer v4: * Remove unused function __clk_core_to_clk * Use core more often as the name for struct clk_core* variables * Make sure we don't lose information about the caller in of_clk_get_* v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 644 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 73 +++- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 9 +- 8 files changed, 577 insertions(+), 313 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index 5c5ebb4..fe722d8 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -131,7 +131,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -148,12 +148,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -274,9 +274,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -291,7 +291,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH, 0x0, NULL); @@ -423,7 +423,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = { { .div = 0 }, }; -DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck_core, 0x0, OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), OMAP3430_CLKSEL_CAM_SHIFT
[PATCH v6 7/7] clk: Add floor and ceiling constraints to clock rates
Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set ceiling rates, or by misc. drivers to set floor rates to assure a minimum performance level. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v6: * Take the prepare lock before removing a per-user clk * Init per-user clks list before adding the first clk * Pass the constraints to determine_rate and let clk implementations deal with constraints * Add clk_set_rate_range v5: * Initialize clk.ceiling_constraint to ULONG_MAX * Warn about inconsistent constraints v4: * Copy function docs from header * Move WARN out of critical section * Refresh rate after removing a per-user clk * Rename clk_core.per_user_clks to clk_core.clks * Store requested rate and re-apply it when constraints are updated --- Documentation/clk.txt | 2 + arch/arm/mach-omap2/dpll3xxx.c | 2 + arch/arm/mach-omap2/dpll44xx.c | 2 + arch/mips/alchemy/common/clock.c| 8 ++ drivers/clk/at91/clk-programmable.c | 2 + drivers/clk/bcm/clk-kona.c | 2 + drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 160 +--- drivers/clk/hisilicon/clk-hi3620.c | 2 + drivers/clk/qcom/clk-pll.c | 1 + drivers/clk/qcom/clk-rcg.c | 4 + drivers/clk/qcom/clk-rcg2.c | 6 ++ drivers/clk/sunxi/clk-factors.c | 2 + drivers/clk/sunxi/clk-sun6i-ar100.c | 2 + include/linux/clk-private.h | 6 ++ include/linux/clk-provider.h| 11 ++- include/linux/clk.h | 28 +++ include/linux/clk/ti.h | 4 + 18 files changed, 218 insertions(+), 35 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 4ff8462..8ebd665 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -73,6 +73,8 @@ the operations defined in clk.h: unsigned long *parent_rate); long(*determine_rate)(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index 20e120d..97084cb 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) * in failure. */ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk **best_parent_clk) { diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 535822f..67d9bd0 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -222,6 +222,8 @@ out: * in failure. */ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk **best_parent_clk) { diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index 48a9dfc..731bedd 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -373,6 +373,8 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate, } static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk, int scale, int maxdiv) @@ -546,6 +548,8 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw, } static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate, + unsigned long floor_rate, + unsigned long ceiling_rate, unsigned long *best_parent_rate, struct clk_hw **best_parent_clk) { @@ -678,6
[PATCH v6 0/7] Per-user clock constraints
Hello, this sixth version of the series has a small fix in the per-user clks commit and the following changes in the clk constraints patch: * Take the prepare lock before removing a per-user clk * Init per-user clks list before adding the first clk * Pass the constraints to determine_rate and let clk implementations deal with constraints * Add clk_set_rate_range A rough test module was used to test this: http://cgit.collabora.com/git/user/tomeu/linux.git/commit/?h=per-user-clk-constraints-v6id=1bada453ab690a1c5be28667d94a4861bc84f8ef The first five patches are just cleanups that should be desirable on their own, and that should make easier to review the actual per-user clock patch. The sixth patch actually moves the per-clock data that was stored in struct clk to a new struct clk_core and adds references to it from both struct clk and struct clk_hw. struct clk is now ready to contain information that is specific to a given clk consumer. The seventh patch adds API for setting floor and ceiling constraints and stores that information on the per-user struct clk, which is iterable from struct clk_core. They are based on top of linux-next 20141128. http://cgit.collabora.com/git/user/tomeu/linux.git/log/?h=per-user-clk-constraints-v6 Thanks, Tomeu Tomeu Vizoso (7): clk: Remove unused function __clk_get_prepare_count clk: Don't try to use a struct clk* after it could have been freed clk: Don't expose __clk_get_accuracy clk: change clk_debugfs_add_file to take a struct clk_hw clk: Change clk_ops-determine_rate to return a clk_hw as the best parent clk: Make clk API return per-user struct clk instances clk: Add floor and ceiling constraints to clock rates Documentation/clk.txt | 4 +- arch/arm/mach-omap2/cclock3xxx_data.c | 108 +++-- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- arch/arm/mach-omap2/dpll3xxx.c | 2 + arch/arm/mach-omap2/dpll44xx.c | 2 + arch/mips/alchemy/common/clock.c| 18 +- drivers/clk/at91/clk-programmable.c | 6 +- drivers/clk/bcm/clk-kona.c | 6 +- drivers/clk/clk-composite.c | 18 +- drivers/clk/clk.c | 807 +--- drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 73 ++- drivers/clk/hisilicon/clk-hi3620.c | 4 +- drivers/clk/qcom/clk-pll.c | 1 + drivers/clk/qcom/clk-rcg.c | 24 +- drivers/clk/qcom/clk-rcg2.c | 34 +- drivers/clk/sunxi/clk-factors.c | 6 +- drivers/clk/sunxi/clk-sun6i-ar100.c | 6 +- include/linux/clk-private.h | 41 +- include/linux/clk-provider.h| 26 +- include/linux/clk.h | 28 ++ include/linux/clk/ti.h | 4 + 23 files changed, 849 insertions(+), 390 deletions(-) -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 6/7] clk: Make clk API return per-user struct clk instances
On 14 November 2014 08:06, Stephen Boyd sb...@codeaurora.org wrote: On 10/30, Tomeu Vizoso wrote: Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com It would be good to have Russell at least ack the clkdev bits. There's still more work to do in the future here, but Reviewed-by: Stephen Boyd sb...@codeaurora.org Thanks, Stephen. Russell, do you think we could have your ack? Regards, Tomeu -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 0/7] Per-user clock constraints
On 31 October 2014 12:33, Peter De Schrijver pdeschrij...@nvidia.com wrote: On Thu, Oct 30, 2014 at 11:48:26AM +0100, Tomeu Vizoso wrote: Hello, this fifth version of the series has just one change, suggested by Stephen: Hi Mike, how is this looking for 3.19? Regards, Tomeu * Initialize clk.ceiling_constraint to ULONG_MAX and warn about new floor constraints being higher than the existing ceiling. The first five patches are just cleanups that should be desirable on their own, and that should make easier to review the actual per-user clock patch. The sixth patch actually moves the per-clock data that was stored in struct clk to a new struct clk_core and adds references to it from both struct clk and struct clk_hw. struct clk is now ready to contain information that is specific to a given clk consumer. The seventh patch adds API for setting floor and ceiling constraints and stores that information on the per-user struct clk, which is iterable from struct clk_core. They are based on top of 3.18-rc1. http://cgit.collabora.com/git/user/tomeu/linux.git/log/?h=per-user-clk-constraints-v5 Acked-By: Peter De Schrijver pdeschrij...@nvidia.com Mike, Do you think this will be merged for 3.19? Thanks, Peter. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 0/7] Per-user clock constraints
Hello, this fifth version of the series has just one change, suggested by Stephen: * Initialize clk.ceiling_constraint to ULONG_MAX and warn about new floor constraints being higher than the existing ceiling. The first five patches are just cleanups that should be desirable on their own, and that should make easier to review the actual per-user clock patch. The sixth patch actually moves the per-clock data that was stored in struct clk to a new struct clk_core and adds references to it from both struct clk and struct clk_hw. struct clk is now ready to contain information that is specific to a given clk consumer. The seventh patch adds API for setting floor and ceiling constraints and stores that information on the per-user struct clk, which is iterable from struct clk_core. They are based on top of 3.18-rc1. http://cgit.collabora.com/git/user/tomeu/linux.git/log/?h=per-user-clk-constraints-v5 Thanks, Tomeu Tomeu Vizoso (7): clk: Remove unused function __clk_get_prepare_count clk: Don't try to use a struct clk* after it could have been freed clk: Don't expose __clk_get_accuracy clk: change clk_debugfs_add_file to take a struct clk_hw clk: Change clk_ops-determine_rate to return a clk_hw as the best parent clk: Make clk API return per-user struct clk instances clk: Add floor and ceiling constraints to clock rates Documentation/clk.txt | 2 +- arch/arm/mach-omap2/cclock3xxx_data.c | 108 +++-- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- arch/mips/alchemy/common/clock.c| 10 +- drivers/clk/at91/clk-programmable.c | 4 +- drivers/clk/bcm/clk-kona.c | 4 +- drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 793 +--- drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 73 ++- drivers/clk/hisilicon/clk-hi3620.c | 2 +- drivers/clk/qcom/clk-rcg.c | 20 +- drivers/clk/qcom/clk-rcg2.c | 28 +- drivers/clk/sunxi/clk-factors.c | 4 +- drivers/clk/sunxi/clk-sun6i-ar100.c | 4 +- include/linux/clk-private.h | 41 +- include/linux/clk-provider.h| 17 +- include/linux/clk.h | 18 + 19 files changed, 773 insertions(+), 385 deletions(-) -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 6/7] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v4: * Remove unused function __clk_core_to_clk * Use core more often as the name for struct clk_core* variables * Make sure we don't lose information about the caller in of_clk_get_* v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 644 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 73 +++- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 9 +- 8 files changed, 577 insertions(+), 313 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index eb8c75e..9b210df 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -131,7 +131,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -148,12 +148,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -271,9 +271,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -288,7 +288,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH, 0x0, NULL); @@ -417,7 +417,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = { { .div = 0 }, }; -DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck_core, 0x0, OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH
[PATCH v4 0/8] Per-user clock constraints
Hello, this fourth version of the series is mainly intended to address many good comments from Stephen Boyd, most notably: * Make sure that best_parent_p is populated with the current parent before calling clk_ops.determine_rate() * Make sure we don't lose information about the caller in of_clk_get_* * Refresh the effective rate after a per-user clk is removed * Store requested rate and re-apply it when constraints are updated The first six patches are just cleanups that should be desirable on their own, and that should make easier to review the actual per-user clock patch. The seventh patch actually moves the per-clock data that was stored in struct clk to a new struct clk_core and adds references to it from both struct clk and struct clk_hw. struct clk is now ready to contain information that is specific to a given clk consumer. The eighth patch adds API for setting floor and ceiling constraints and stores that information on the per-user struct clk, which is iterable from struct clk_core. They are based on top of 3.18-rc1. http://cgit.collabora.com/git/user/tomeu/linux.git/log/?h=per-user-clk-constraints-v4 Thanks, Tomeu Tomeu Vizoso (8): MIPS: Alchemy: Remove direct access to prepare_count field of struct clk clk: Remove unused function __clk_get_prepare_count clk: Don't try to use a struct clk* after it could have been freed clk: Don't expose __clk_get_accuracy clk: change clk_debugfs_add_file to take a struct clk_hw clk: Change clk_ops-determine_rate to return a clk_hw as the best parent clk: Make clk API return per-user struct clk instances clk: Add floor and ceiling constraints to clock rates Documentation/clk.txt | 2 +- arch/arm/mach-omap2/cclock3xxx_data.c | 108 +++-- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- arch/mips/alchemy/common/clock.c| 17 +- drivers/clk/at91/clk-programmable.c | 4 +- drivers/clk/bcm/clk-kona.c | 4 +- drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 788 +--- drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 73 ++- drivers/clk/hisilicon/clk-hi3620.c | 2 +- drivers/clk/qcom/clk-rcg.c | 20 +- drivers/clk/qcom/clk-rcg2.c | 28 +- drivers/clk/sunxi/clk-factors.c | 4 +- drivers/clk/sunxi/clk-sun6i-ar100.c | 4 +- include/linux/clk-private.h | 41 +- include/linux/clk-provider.h| 17 +- include/linux/clk.h | 18 + 19 files changed, 771 insertions(+), 389 deletions(-) -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 7/8] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v4: * Remove unused function __clk_core_to_clk * Use core more often as the name for struct clk_core* variables * Make sure we don't lose information about the caller in of_clk_get_* v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 644 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 73 +++- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 9 +- 8 files changed, 577 insertions(+), 313 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index eb8c75e..9b210df 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -131,7 +131,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -148,12 +148,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -271,9 +271,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -288,7 +288,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH, 0x0, NULL); @@ -417,7 +417,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = { { .div = 0 }, }; -DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck_core, 0x0, OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH
[PATCH v2] CLK: TI: Remove unused includes of linux/clk-private.h
Because they are unused, and there's plans to remove that header in the near future. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v2: * Add rationale to commit message * Include clk-provider.h in each file that uses it, instead of in clk/ti.h --- drivers/clk/ti/clk-44xx.c | 2 +- drivers/clk/ti/clk-54xx.c | 2 +- drivers/clk/ti/clk-7xx.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c index 02517a8..3694615 100644 --- a/drivers/clk/ti/clk-44xx.c +++ b/drivers/clk/ti/clk-44xx.c @@ -12,7 +12,7 @@ #include linux/kernel.h #include linux/list.h -#include linux/clk-private.h +#include linux/clk-provider.h #include linux/clkdev.h #include linux/clk/ti.h diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c index 5e18399..19c4fac 100644 --- a/drivers/clk/ti/clk-54xx.c +++ b/drivers/clk/ti/clk-54xx.c @@ -12,7 +12,7 @@ #include linux/kernel.h #include linux/list.h -#include linux/clk-private.h +#include linux/clk-provider.h #include linux/clkdev.h #include linux/io.h #include linux/clk/ti.h diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index 62ac8f6..853d9ae 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c @@ -12,7 +12,7 @@ #include linux/kernel.h #include linux/list.h -#include linux/clk-private.h +#include linux/clk-provider.h #include linux/clkdev.h #include linux/clk/ti.h -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 7/8] clk: Make clk API return per-user struct clk instances
On 10 October 2014 01:22, Stephen Boyd sb...@codeaurora.org wrote: On 10/09, Tomeu Vizoso wrote: arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 630 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 24 +- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 22 +- 8 files changed, 549 insertions(+), 291 deletions(-) The difstat looks good. diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fb820bf..4db918a 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -695,6 +731,13 @@ struct clk *__clk_lookup(const char *name) return NULL; } +struct clk *__clk_lookup(const char *name) +{ + struct clk_core *clk = clk_core_lookup(name); + + return !clk ? NULL : clk-hw-clk; This just looks weird with clk-hw-clk. I know we're trying to keep the diff small by not renaming clk to core when it's used extensively throughout the code, but for small little additions like this I would prefer we use core for clk_core pointers and clk for clk pointers. Then a patch at the end can rename everything to be consistent. This thing also threw me off because I searched for kfree(core) but couldn't find it so I thought we leaked the clk_core structure. Makes sense, I have tried to reduce confusion in this regard. +} + /* * Helper for finding best parent to provide a given frequency. This can be used * directly as a determine_rate callback (e.g. for a mux), or from a more @@ -2175,24 +2298,24 @@ void clk_unregister(struct clk *clk) * a reference to this clock. */ flags = clk_enable_lock(); - clk-ops = clk_nodrv_ops; + clk-core-ops = clk_nodrv_ops; clk_enable_unlock(flags); - if (!hlist_empty(clk-children)) { - struct clk *child; + if (!hlist_empty(clk-core-children)) { + struct clk_core *child; struct hlist_node *t; /* Reparent all children to the orphan list. */ - hlist_for_each_entry_safe(child, t, clk-children, child_node) - clk_set_parent(child, NULL); + hlist_for_each_entry_safe(child, t, clk-core-children, child_node) + clk_core_set_parent(child, NULL); } - hlist_del_init(clk-child_node); + hlist_del_init(clk-core-child_node); - if (clk-prepare_count) + if (clk-core-prepare_count) pr_warn(%s: unregistering prepared clock: %s\n, - __func__, clk-name); - kref_put(clk-ref, __clk_release); + __func__, clk-core-name); + kref_put(clk-core-ref, __clk_release); clk_prepare_unlock(); It might be worth it to make a core local variable in this function. } @@ -2255,32 +2378,38 @@ void devm_clk_unregister(struct device *dev, struct clk *clk) } EXPORT_SYMBOL_GPL(devm_clk_unregister); +static void clk_core_put(struct clk_core *clk) +{ + struct module *owner; + + if (!clk || WARN_ON_ONCE(IS_ERR(clk))) + return; + + clk_prepare_lock(); + owner = clk-owner; Same here too, we don't need to protect the access to owner so it can move outside the lock. + kref_put(clk-ref, __clk_release); + module_put(owner); + clk_prepare_unlock(); +} + /* * clkdev helpers */ int __clk_get(struct clk *clk) { if (clk) { - if (!try_module_get(clk-owner)) + if (!try_module_get(clk-core-owner)) return 0; - kref_get(clk-ref); + kref_get(clk-core-ref); } return 1; Grow a core pointer? } @@ -2391,6 +2520,31 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) } EXPORT_SYMBOL_GPL(clk_notifier_unregister); +struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id, Curious, why the underscore? To denote it's internal to the CCF implementation. + const char *con_id) +{ + struct clk *clk; + + /* This is to allow this function to be chained to others */ + if (!hw || IS_ERR(hw)) + return (struct clk *) hw; + + clk = kzalloc(sizeof(*clk), GFP_KERNEL); + if (!clk) + return ERR_PTR(-ENOMEM); + + clk-core = hw-core; + clk-dev_id = dev_id; + clk-con_id = con_id; + + return clk; +} diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index da4bda8..4411db6 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -69,6 +70,10 @@ struct clk *of_clk_get(struct device_node *np, int index) clk = of_clk_get_by_clkspec(clkspec); of_node_put(clkspec.np); + + if (!IS_ERR(clk
Re: [PATCH v2 0/8] Per-user clock constraints
On 9 October 2014 03:32, Stephen Boyd sb...@codeaurora.org wrote: On 10/07/2014 08:21 AM, Tomeu Vizoso wrote: Hello, this second version of the series adds several cleanups that were suggested by Stephen Boyd and contains several improvements to the seventh patch (clk: Make clk API return per-user struct clk instances) that were suggested by him during the review of v1. The first six patches are just cleanups that should be desirable on their own, and that should make easier to review the actual per-user clock patch. The seventh patch actually moves the per-clock data that was stored in struct clk to a new struct clk_core and adds references to it from both struct clk and struct clk_hw. struct clk is now ready to contain information that is specific to a given clk consumer. The eighth patch adds API for setting floor and ceiling constraints and stores that information on the per-user struct clk, which is iterable from struct clk_core. As said in the patches, can you please indicate which baseline this is on? Sure, this was based on v3.17. Also available at: http://cgit.collabora.com/git/user/tomeu/linux.git/log/?h=per-user-clk-constraints-v2 Also can you rebase onto clk-next if you send again before that is merged into 3.18-rc1? There are some changes in the debugfs part that will conflict. I'll review the more complicated parts in detail soon. Ack. Thanks, Tomeu -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 0/8] Per-user clock constraints
Hello, this third version of the series is basically just a rebase on top of linux-next 20141009. The first six patches are just cleanups that should be desirable on their own, and that should make easier to review the actual per-user clock patch. The seventh patch actually moves the per-clock data that was stored in struct clk to a new struct clk_core and adds references to it from both struct clk and struct clk_hw. struct clk is now ready to contain information that is specific to a given clk consumer. The eighth patch adds API for setting floor and ceiling constraints and stores that information on the per-user struct clk, which is iterable from struct clk_core. http://cgit.collabora.com/git/user/tomeu/linux.git/log/?h=per-user-clk-constraints-v3 Thanks, Tomeu Tomeu Vizoso (8): MIPS: Alchemy: Remove direct access to prepare_count field of struct clk clk: Remove unused function __clk_get_prepare_count clk: Don't try to use a struct clk* after it could have been freed clk: Don't expose __clk_get_accuracy clk: change clk_debugfs_add_file to take a struct clk_hw clk: Change clk_ops-determine_rate to return a clk_hw as the best parent clk: Make clk API return per-user struct clk instances clk: Add floor and ceiling constraints to clock rates Documentation/clk.txt | 2 +- arch/arm/mach-omap2/cclock3xxx_data.c | 108 +++-- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- arch/mips/alchemy/common/clock.c| 17 +- drivers/clk/at91/clk-programmable.c | 4 +- drivers/clk/bcm/clk-kona.c | 4 +- drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 748 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 24 +- drivers/clk/hisilicon/clk-hi3620.c | 2 +- drivers/clk/qcom/clk-rcg.c | 20 +- drivers/clk/qcom/clk-rcg2.c | 28 +- drivers/clk/sunxi/clk-factors.c | 4 +- drivers/clk/sunxi/clk-sun6i-ar100.c | 4 +- include/linux/clk-private.h | 40 +- include/linux/clk-provider.h| 30 +- include/linux/clk.h | 18 + 19 files changed, 717 insertions(+), 366 deletions(-) -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 7/8] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v3: * Rebase on top of linux-next 20141009 v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 630 drivers/clk/clk.h | 5 + drivers/clk/clkdev.c| 24 +- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 22 +- 8 files changed, 549 insertions(+), 291 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index eb8c75e..9b210df 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -131,7 +131,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -148,12 +148,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -271,9 +271,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -288,7 +288,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH, 0x0, NULL); @@ -417,7 +417,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = { { .div = 0 }, }; -DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck_core, 0x0, OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -459,7 +459,7 @@ static struct clk_hw_omap dpll4_m5x2_ck_hw = { DEFINE_STRUCT_CLK_FLAGS(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names, dpll4_m5x2_ck_ops
[PATCH v2 0/8] Per-user clock constraints
Hello, this second version of the series adds several cleanups that were suggested by Stephen Boyd and contains several improvements to the seventh patch (clk: Make clk API return per-user struct clk instances) that were suggested by him during the review of v1. The first six patches are just cleanups that should be desirable on their own, and that should make easier to review the actual per-user clock patch. The seventh patch actually moves the per-clock data that was stored in struct clk to a new struct clk_core and adds references to it from both struct clk and struct clk_hw. struct clk is now ready to contain information that is specific to a given clk consumer. The eighth patch adds API for setting floor and ceiling constraints and stores that information on the per-user struct clk, which is iterable from struct clk_core. Thanks, Tomeu Tomeu Vizoso (8): MIPS: Alchemy: Remove direct access to prepare_count field of struct clk clk: Remove unused function __clk_get_prepare_count clk: Don't try to use a struct clk* after it could have been freed clk: Don't expose __clk_get_accuracy clk: change clk_debugfs_add_file to take a struct clk_hw clk: Change clk_ops-determine_rate to return a clk_hw as the best parent clk: Make clk API return per-user struct clk instances clk: Add floor and ceiling constraints to clock rates arch/arm/mach-omap2/cclock3xxx_data.c | 108 +++-- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- arch/mips/alchemy/common/clock.c| 7 +- drivers/clk/at91/clk-programmable.c | 4 +- drivers/clk/bcm/clk-kona.c | 4 +- drivers/clk/clk-composite.c | 9 +- drivers/clk/clk.c | 723 +--- drivers/clk/clk.h | 7 + drivers/clk/clkdev.c| 23 +- drivers/clk/hisilicon/clk-hi3620.c | 2 +- drivers/clk/qcom/clk-rcg.c | 20 +- drivers/clk/qcom/clk-rcg2.c | 28 +- drivers/clk/sunxi/clk-factors.c | 4 +- drivers/clk/sunxi/clk-sun6i-ar100.c | 4 +- include/linux/clk-private.h | 40 +- include/linux/clk-provider.h| 30 +- include/linux/clk.h | 18 + 18 files changed, 697 insertions(+), 350 deletions(-) -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 7/8] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- v2: * Remove exported functions that aren't really used outside clk.c * Rename new internal functions to clk_core_ prefix * Remove redundant checks for error pointers in *_get_parent * Change __clk_create_clk to take a struct clk_hw instead * Match the original error behavior in clk_get_sys --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 605 drivers/clk/clk.h | 7 + drivers/clk/clkdev.c| 23 +- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 22 +- 8 files changed, 535 insertions(+), 281 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index eb8c75e..9b210df 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -131,7 +131,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -148,12 +148,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -271,9 +271,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -288,7 +288,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH, 0x0, NULL); @@ -417,7 +417,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = { { .div = 0 }, }; -DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck_core, 0x0, OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -459,7 +459,7 @@ static struct clk_hw_omap dpll4_m5x2_ck_hw = { DEFINE_STRUCT_CLK_FLAGS(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names, dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT); -static struct clk
Re: [PATCH 1/2] clk: Make clk API return per-user struct clk instances
On 4 October 2014 01:15, Stephen Boyd sb...@codeaurora.org wrote: On 10/02, Tomeu Vizoso wrote: + #if defined(CONFIG_OF) defined(CONFIG_COMMON_CLK) These ifdefs look useless. struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec); struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec); void of_clk_lock(void); void of_clk_unlock(void); #endif + +#if defined(CONFIG_COMMON_CLK) So we shouldn't need this one either. Actually, i had to put it back so clkdev.c builds on !CONFIG_COMMON_CLK. Do you have another idea on how to deal with this? Sorry, but I forgot to CC you on v2 (just sent): https://lkml.org/lkml/2014/10/7/430 Thanks, Tomeu -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] clk: Make clk API return per-user struct clk instances
On 4 October 2014 01:15, Stephen Boyd sb...@codeaurora.org wrote: On 10/02, Tomeu Vizoso wrote: Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- We should s/provider/core/ when we're dealing with clk_core structures in the function signature. The providers are hardware drivers and the core structures are for the framework, not the same. Furthermore, the provider drivers should only be dealing with clk_hw structures. The only place that clk_core should be in clk-provider.h is in struct clk_hw because there's no way to get around it. This way, provider drivers should only be including clk-provider.h because they only care about dealing with struct clk_hw. Consumers should only be including linux/clk.h where they only know about struct clk as an opaque pointer. Once we get OMAP to stop using clk-private.h we can kill off that header entirely (I see there are some other bogus users of that header outside of OMAP that we should nuke). Then the framework can include clk-provider.h and clk.h to map between the hw cookie and the consumer cookie. Agreed. This is the end goal. I understand that the provider API is sort of a mess with us allowing drivers to use the underscore and non-underscore functions and the mixture of struct clk and struct ckl_hw throughout. struct clk_hw -- struct clk_core struct clk \- struct clk |- struct clk Agree this is how it should look like at some point, but for now I need a reference to struct clk from struct clk_hw, so providers can keep using the existing API. This reference would be removed once they move to the new clk_hw-based API. providers - struct clk_hw { struct clk_core * ... }; consumers - struct clk; hidden in core framework struct clk { struct clk_core *; ... } struct clk_core { struct clk_hw *; ... } diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 4eeb8de..b216b13 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -37,6 +37,13 @@ static HLIST_HEAD(clk_root_list); static HLIST_HEAD(clk_orphan_list); static LIST_HEAD(clk_notifier_list); +static void clk_provider_put(struct clk_core *clk); Does this need to be forward declared? No, removed. +static long clk_provider_get_accuracy(struct clk_core *clk); +static bool clk_provider_is_prepared(struct clk_core *clk); +static bool clk_provider_is_enabled(struct clk_core *clk); +static long clk_provider_round_rate(struct clk_core *clk, unsigned long rate); @@ -356,7 +363,7 @@ out: * * Caller must hold prepare_lock. */ -static void clk_debug_unregister(struct clk *clk) +static void clk_debug_unregister(struct clk_core *clk) { debugfs_remove_recursive(clk-dentry); } @@ -366,8 +373,8 @@ struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode, We should pass struct clk_hw here instead of struct clk. Let's do it soon before we get any users. Sounds good to me. { struct dentry *d = NULL; - if (clk-dentry) - d = debugfs_create_file(name, mode, clk-dentry, data, fops); + if (clk-core-dentry) + d = debugfs_create_file(name, mode, clk-core-dentry, data, fops); return d; } @@ -545,53 +553,67 @@ late_initcall_sync(clk_disable_unused); const char *__clk_get_name(struct clk *clk) { - return !clk ? NULL : clk-name; + return !clk ? NULL : clk-core-name; } EXPORT_SYMBOL_GPL(__clk_get_name); struct clk_hw *__clk_get_hw(struct clk *clk) { - return !clk ? NULL : clk-hw; + return !clk ? NULL : clk-core-hw; } EXPORT_SYMBOL_GPL(__clk_get_hw); u8 __clk_get_num_parents(struct clk *clk) { - return !clk ? 0 : clk-num_parents; + return !clk ? 0 : clk-core-num_parents; } EXPORT_SYMBOL_GPL(__clk_get_num_parents); struct clk *__clk_get_parent(struct clk *clk) { - return !clk ? NULL : clk-parent; + /* TODO: Create a per-user clk and change callers to call clk_put */ More like replace all callers with a function that returns their parent's hw pointer. Sounds good, but I thought about it and have chosen to just remove the comment. struct clk_hw *clk_provider_get_parent(struct clk_hw *hw) + return
[PATCH] CLK: TI: Remove unused includes of linux/clk-private.h
Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- drivers/clk/ti/clk-44xx.c | 1 - drivers/clk/ti/clk-54xx.c | 1 - drivers/clk/ti/clk-7xx.c | 1 - include/linux/clk/ti.h| 1 + 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c index 02517a8..8ea705e 100644 --- a/drivers/clk/ti/clk-44xx.c +++ b/drivers/clk/ti/clk-44xx.c @@ -12,7 +12,6 @@ #include linux/kernel.h #include linux/list.h -#include linux/clk-private.h #include linux/clkdev.h #include linux/clk/ti.h diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c index 5e18399..e823d0b 100644 --- a/drivers/clk/ti/clk-54xx.c +++ b/drivers/clk/ti/clk-54xx.c @@ -12,7 +12,6 @@ #include linux/kernel.h #include linux/list.h -#include linux/clk-private.h #include linux/clkdev.h #include linux/io.h #include linux/clk/ti.h diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index 62ac8f6..afd61a6 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c @@ -12,7 +12,6 @@ #include linux/kernel.h #include linux/list.h -#include linux/clk-private.h #include linux/clkdev.h #include linux/clk/ti.h diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index e8d8a35..ced953a 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -16,6 +16,7 @@ #define __LINUX_CLK_TI_H__ #include linux/clkdev.h +#include linux/clk-provider.h /** * struct dpll_data - DPLL registers and integration data -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] clk: Make clk API return per-user struct clk instances
Moves clock state to struct clk_core, but takes care to change as little API as possible. struct clk_hw still has a pointer to a struct clk, which is the implementation's per-user clk instance, for backwards compatibility. The struct clk that clk_get_parent() returns isn't owned by the caller, but by the clock implementation, so the former shouldn't call clk_put() on it. Because some boards in mach-omap2 still register clocks statically, their clock registration had to be updated to take into account that the clock information is stored in struct clk_core now. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- arch/arm/mach-omap2/cclock3xxx_data.c | 108 -- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 617 drivers/clk/clk.h | 7 + drivers/clk/clkdev.c| 23 +- include/linux/clk-private.h | 35 +- include/linux/clk-provider.h| 27 +- 8 files changed, 548 insertions(+), 285 deletions(-) diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c index eb8c75e..9b210df 100644 --- a/arch/arm/mach-omap2/cclock3xxx_data.c +++ b/arch/arm/mach-omap2/cclock3xxx_data.c @@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0, OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT, OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL); -DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck, 0x0, +DEFINE_CLK_DIVIDER(sys_ck, osc_sys_ck, osc_sys_ck_core, 0x0, OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT, OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -131,7 +131,7 @@ static struct clk_hw_omap dpll3_ck_hw = { DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops); -DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll3_m2_ck, dpll3_ck, dpll3_ck_core, 0x0, OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH, @@ -148,12 +148,12 @@ static const struct clk_ops core_ck_ops = {}; DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL); DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops); -DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck, 0x0, +DEFINE_CLK_DIVIDER(l3_ick, core_ck, core_ck_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); -DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick, 0x0, +DEFINE_CLK_DIVIDER(l4_ick, l3_ick, l3_ick_core, 0x0, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL), OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -271,9 +271,9 @@ static struct clk_hw_omap dpll1_ck_hw = { DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops); -DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck, 0x0, 2, 1); +DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, dpll1_ck, dpll1_ck_core, 0x0, 2, 1); -DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, dpll1_x2_ck, dpll1_x2_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL), OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT, OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH, @@ -288,7 +288,7 @@ static const char *mpu_ck_parent_names[] = { DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, mpu_clkdm); DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops); -DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck, 0x0, +DEFINE_CLK_DIVIDER(arm_fck, mpu_ck, mpu_ck_core, 0x0, OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH, 0x0, NULL); @@ -417,7 +417,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = { { .div = 0 }, }; -DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck, 0x0, +DEFINE_CLK_DIVIDER(dpll4_m5_ck, dpll4_ck, dpll4_ck_core, 0x0, OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL), OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); @@ -459,7 +459,7 @@ static struct clk_hw_omap dpll4_m5x2_ck_hw = { DEFINE_STRUCT_CLK_FLAGS(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names, dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT); -static struct clk dpll4_m5x2_ck_3630 = { +static struct clk_core dpll4_m5x2_ck_3630_core = { .name = dpll4_m5x2_ck, .hw = dpll4_m5x2_ck_hw.hw, .parent_names = dpll4_m5x2_ck_parent_names, @@ -468,6 +468,10 @@ static struct clk dpll4_m5x2_ck_3630 = { .flags = CLK_SET_RATE_PARENT, }; +static
[PATCH 0/2] Per-user clock constraints
Hello, these patches add the possibility of setting constraints on the frequency of clocks. In contrast to my two previous approaches, this is accomplished with per-user clocks, but without requiring changes to existing drivers. An exception to the latter are a few boards in mach-omap2, which still register their clocks statically and thus had to be changed to initialize struct clk_core. Hopefully the whole of clk-private.h can be removed once those boards have been converted to initialize their clocks with DTS files. The first patch implements per-user clocks properly, and the second adds the constraint API. Thanks, Tomeu Tomeu Vizoso (2): clk: Make clk API return per-user struct clk instances clk: Add floor and ceiling constraints to clock rates arch/arm/mach-omap2/cclock3xxx_data.c | 108 +++-- arch/arm/mach-omap2/clock.h | 11 +- arch/arm/mach-omap2/clock_common_data.c | 5 +- drivers/clk/clk.c | 723 +--- drivers/clk/clk.h | 8 + drivers/clk/clkdev.c| 23 +- include/linux/clk-private.h | 40 +- include/linux/clk-provider.h| 27 +- include/linux/clk.h | 18 + 9 files changed, 656 insertions(+), 307 deletions(-) -- 1.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] clk: Add floor and ceiling constraints to clock rates
Adds a way for clock consumers to set maximum and minimum rates. This can be used for thermal drivers to set ceiling rates, or by misc. drivers to set floor rates to assure a minimum performance level. Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com --- drivers/clk/clk.c | 116 +--- drivers/clk/clk.h | 1 + drivers/clk/clkdev.c| 2 +- include/linux/clk-private.h | 5 ++ include/linux/clk.h | 18 +++ 5 files changed, 114 insertions(+), 28 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index b216b13..b96d470 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1615,30 +1615,10 @@ static void clk_change_rate(struct clk_core *clk) clk_change_rate(clk-new_child); } -/** - * clk_set_rate - specify a new rate for clk - * @clk: the clk whose rate is being changed - * @rate: the new rate for clk - * - * In the simplest case clk_set_rate will only adjust the rate of clk. - * - * Setting the CLK_SET_RATE_PARENT flag allows the rate change operation to - * propagate up to clk's parent; whether or not this happens depends on the - * outcome of clk's .round_rate implementation. If *parent_rate is unchanged - * after calling .round_rate then upstream parent propagation is ignored. If - * *parent_rate comes back with a new rate for clk's parent then we propagate - * up to clk's parent and set its rate. Upward propagation will continue - * until either a clk does not support the CLK_SET_RATE_PARENT flag or - * .round_rate stops requesting changes to clk's parent_rate. - * - * Rate changes are accomplished via tree traversal that also recalculates the - * rates for the clocks and fires off POST_RATE_CHANGE notifiers. - * - * Returns 0 on success, -EERROR otherwise. - */ -int clk_set_rate(struct clk *clk, unsigned long rate) +static int clk_provider_set_rate(struct clk_core *clk, unsigned long rate) { struct clk_core *top, *fail_clk; + struct clk *clk_user; int ret = 0; if (!clk) @@ -1647,18 +1627,27 @@ int clk_set_rate(struct clk *clk, unsigned long rate) /* prevent racing with updates to the clock topology */ clk_prepare_lock(); + hlist_for_each_entry(clk_user, clk-per_user_clks, child_node) { + rate = max(rate, clk_user-floor_constraint); + } + + hlist_for_each_entry(clk_user, clk-per_user_clks, child_node) { + if (clk_user-ceiling_constraint 0) + rate = min(rate, clk_user-ceiling_constraint); + } + /* bail early if nothing to do */ - if (rate == clk_get_rate(clk)) + if (rate == clk_provider_get_rate(clk)) goto out; - if ((clk-core-flags CLK_SET_RATE_GATE) - clk-core-prepare_count) { + if ((clk-flags CLK_SET_RATE_GATE) + clk-prepare_count) { ret = -EBUSY; goto out; } /* calculate new rates and get the topmost changed clock */ - top = clk_calc_new_rates(clk-core, rate); + top = clk_calc_new_rates(clk, rate); if (!top) { ret = -EINVAL; goto out; @@ -1682,8 +1671,69 @@ out: return ret; } + +/** + * clk_set_rate - specify a new rate for clk + * @clk: the clk whose rate is being changed + * @rate: the new rate for clk + * + * In the simplest case clk_set_rate will only adjust the rate of clk. + * + * Setting the CLK_SET_RATE_PARENT flag allows the rate change operation to + * propagate up to clk's parent; whether or not this happens depends on the + * outcome of clk's .round_rate implementation. If *parent_rate is unchanged + * after calling .round_rate then upstream parent propagation is ignored. If + * *parent_rate comes back with a new rate for clk's parent then we propagate + * up to clk's parent and set its rate. Upward propagation will continue + * until either a clk does not support the CLK_SET_RATE_PARENT flag or + * .round_rate stops requesting changes to clk's parent_rate. + * + * Rate changes are accomplished via tree traversal that also recalculates the + * rates for the clocks and fires off POST_RATE_CHANGE notifiers. + * + * Returns 0 on success, -EERROR otherwise. + */ +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return clk_provider_set_rate(clk-core, rate); +} EXPORT_SYMBOL_GPL(clk_set_rate); +int clk_set_floor_rate(struct clk *clk, unsigned long rate) +{ + int ret; + + clk_prepare_lock(); + + clk-floor_constraint = rate; + ret = clk_set_rate(clk, clk_get_rate(clk)); + + clk_prepare_unlock(); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_floor_rate); + +int clk_set_ceiling_rate(struct clk *clk, unsigned long rate) +{ + int ret; + + clk_prepare_lock(); + + WARN(rate 0 rate clk-floor_constraint, +clk %s dev %s con %s: new ceiling %lu lower than existing floor %lu\n