* Re: [PATCH] ACPI, cpuidle: Fix suspend/resume regression caused by cpuidle cleanup.
From: Rafael J. Wysocki @ 2012-06-19 20:35 UTC (permalink / raw)
To: Deepthi Dharwar
Cc: Dave Hansen, Linux PM mailing list, linux-pm, linux-acpi,
Len Brown, Jean Pihet, Arjan van de Ven, Kevin Hilman,
Arnd Bergmann, Ferenc Wagner, Tomas M., Srivatsa S. Bhat, preeti
In-Reply-To: <4FD87249.6010302@linux.vnet.ibm.com>
On Wednesday, June 13, 2012, Deepthi Dharwar wrote:
>
> From: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
>
> Fix suspend/resume regression caused by cpuidle cleanup.
>
> Commit e978aa7d7d57d04eb5f88a7507c4fb98577def77 ( cpuidle: Move
> dev->last_residency update to driver enter routine; remove dev->last_state)
> was breaking suspend on laptops, as reported in the below link
> - https://lkml.org/lkml/2011/11/11/164
>
> This was fixed in commit 3439a8da16bcad6b0982ece938c9f8299bb53584
> (ACPI / cpuidle: Remove acpi_idle_suspend (to fix suspend regression)
> by removing acpi_idle_suspend flag.
> - https://lkml.org/lkml/2011/11/14/74
>
> But this fix did not work on all systems
> as Suspend/resume regression was reported on Lenovo S10-3
> recently by Dave.
> - https://lkml.org/lkml/2012/5/27/115
> It looked like with commit e978aa7d broke suspend and
> with commit 3439a8da resume was not working with acpi_idle driver.
>
> This patch fixes the regression that caused this issue
> in the first place. acpi_idle_suspend flag is essential on
> some x86 systems to prevent the cpus from going to deeper C-states
> when suspend is triggered ( commit b04e7bdb984 )
> So reverting the commit 3439a8da is essential.
>
> By default, irqs are disabled in cpu_idle arch specific call
> and re-enabled in idle state return path . As the acpi_idle_suspend
> flag was being set during suspend, which prevented the cpus
> going to deeper idle states, it is essential to
> enabling the irqs in its return path too.
>
> To address the suspend issue,
> we were not re-enabling the interrupts while returning from
> acpi_idle_enter_bm() routine if acpi_idle_suspend flag is set.
> and this was causing suspend failure.
>
> In addition to the above fix, a sanity check has also been added
> in x86 arch specific cpu_idle call to ensure that the idle call
> always returns with IRQs enabled.
>
> This patch applies on 3.5-rc2
> ---
>
> Reported-and-Tested-by: Dav Hansen <dave@linux.vnet.ibm.com>
> Tested-by: Preeti Murthy <preeti@linux.vnet.ibm.com>
> Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
> Reviewed-by: Srivatsa S Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Applied to linux-pm/linux-next, will be pushed to Linus later this week.
Thanks,
Rafael
> ---
> arch/x86/kernel/process.c | 6 ++++++
> drivers/acpi/processor_idle.c | 28 ++++++++++++++++++++++++++++
> 2 files changed, 34 insertions(+), 0 deletions(-)
>
> diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
> index 735279e..8ab76ad 100644
> --- a/arch/x86/kernel/process.c
> +++ b/arch/x86/kernel/process.c
> @@ -460,6 +460,12 @@ void cpu_idle(void)
> pm_idle();
>
> rcu_idle_exit();
> +
> + /*
> + * Sanity check to ensure that idle call returns
> + * with IRQs enabled
> + */
> + WARN_ON(irqs_disabled());
> start_critical_timings();
>
> /* In many cases the interrupt that ended idle
> diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
> index f3decb3..c2ffd84 100644
> --- a/drivers/acpi/processor_idle.c
> +++ b/drivers/acpi/processor_idle.c
> @@ -224,6 +224,7 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
> /*
> * Suspend / resume control
> */
> +static int acpi_idle_suspend;
> static u32 saved_bm_rld;
>
> static void acpi_idle_bm_rld_save(void)
> @@ -242,13 +243,21 @@ static void acpi_idle_bm_rld_restore(void)
>
> int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
> {
> + if (acpi_idle_suspend == 1)
> + return 0;
> +
> acpi_idle_bm_rld_save();
> + acpi_idle_suspend = 1;
> return 0;
> }
>
> int acpi_processor_resume(struct acpi_device * device)
> {
> + if (acpi_idle_suspend == 0)
> + return 0;
> +
> acpi_idle_bm_rld_restore();
> + acpi_idle_suspend = 0;
> return 0;
> }
>
> @@ -754,6 +763,12 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
>
> local_irq_disable();
>
> + if (acpi_idle_suspend) {
> + local_irq_enable();
> + cpu_relax();
> + return -EINVAL;
> + }
> +
> lapic_timer_state_broadcast(pr, cx, 1);
> kt1 = ktime_get_real();
> acpi_idle_do_entry(cx);
> @@ -823,6 +838,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
>
> local_irq_disable();
>
> + if (acpi_idle_suspend) {
> + local_irq_enable();
> + cpu_relax();
> + return -EINVAL;
> + }
> +
> if (cx->entry_method != ACPI_CSTATE_FFH) {
> current_thread_info()->status &= ~TS_POLLING;
> /*
> @@ -901,6 +922,13 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
> if (unlikely(!pr))
> return -EINVAL;
>
> + if (acpi_idle_suspend) {
> + if (irqs_disabled())
> + local_irq_enable();
> + cpu_relax();
> + return -EINVAL;
> + }
> +
> if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
> if (drv->safe_state_index >= 0) {
> return drv->states[drv->safe_state_index].enter(dev,
>
> Regards,
> Deepthi
>
>
>
^ permalink raw reply
* Re: [linux-pm] acpi_idle and max_cpus
From: Thomas Renninger @ 2012-06-19 15:30 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: Srivatsa S. Bhat, Deepthi Dharwar, linux-acpi, linux-pm
In-Reply-To: <4FE027AC.8010607@linaro.org>
On Tuesday, June 19, 2012 09:18:04 AM Daniel Lezcano wrote:
> On 06/19/2012 09:03 AM, Srivatsa S. Bhat wrote:
> > On 06/19/2012 12:24 PM, Deepthi Dharwar wrote:
> >
> >> On 06/18/2012 06:24 PM, Daniel Lezcano wrote:
> >>
> >>> On 06/18/2012 02:25 PM, Deepthi Dharwar wrote:
> >>>> Hi Daniel,
> >>>>
> >>>> On 06/18/2012 01:48 AM, Daniel Lezcano wrote:
> >>>>
> >>>>> On 06/15/2012 05:28 PM, Daniel Lezcano wrote:
> >>>>>>
> >>>>>> Hi all,
> >>>>>>
> >>>>>> I have a dual core Intel T9500.
> >>>>>>
> >>>>>> I boot the cpu with the acpi_idle driver and intel_idle enabled in the
> >>>>>> config.
> >>>>>>
> >>>>>> The kernel is booted with maxcpus=1.
> >>>>>>
> >>>>>> After the system has boot, I put cpu1 online via sysfs.
> >>>>>>
> >>>>>> But I don't see any 'cpuidle' directory in the cpu's sysfs entry:
> >>>>>>
> >>>>>> /sys/devices/system/cpu/cpu1/cpuidle (?)
> >>>>>>
> >>>>>> When I look at the code I see the notifier is present for hotplug in
> >>>>>> processor_driver.c and the cpuidle intel init routine should be called
> >>>>>> there.
> >>>>>>
> >>>>
> >>>>
> >>>> Yes, we have a hotplug notifier.
> >>>> Commit 99b72508 by Thomas Renninger fixed this issue.
> >>>>
> >>>> Please let me know which kernel version you are running and what is idle
> >>>> driver registered ?
> >>>
> >>> The kernel version is 3.5.0-rc1
> >>> The registered driver is acpi_idle (with intel_idle if I am not wrong).
> >>>
> >>> Thomas's patch is in this version.
> >>>
> >>> Maybe I am wrong but I think the patch is not correct because:
> >>>
> >>> static int __cpuinit acpi_processor_add(struct acpi_device *device)
> >>> {
> >>>
> >>> ...
> >>>
> >>> #ifdef CONFIG_SMP
> >>> if (pr->id >= setup_max_cpus && pr->id != 0)
> >>> return 0;
> >>> #endif
> >>>
> >>> ...
> >>>
> >>> per_cpu(processors, pr->id) = pr;
> >>>
> >>> ...
> >>> }
> >>>
> >>> With max_cpus=1 we exit before setting up 'pr'.
> >>>
> >>> So the condition in:
> >>>
> >>> static int acpi_cpu_soft_notify(...)
> >>> {
> >>>
> >>> unsigned int cpu = (unsigned long)hcpu;
> >>> struct acpi_processor *pr = per_cpu(processors, cpu);
> >>>
> >>> if (action == CPU_ONLINE && pr) {
> >>>
> >>> ...
> >>> }
> >>>
> >>> Is always false because pr == NULL
> >>>
> >>> I did the change but I don't still see the 'cpuidle' directory
> >>> appearing, I suspect also pr->flags.need_hotplug_init is not correctly
> >>> initialized but I did not investigate more.
> >>>
> >>
> >>
> >> Well looks like variable maxcpus holds the key here.
> >>
> >
> >
> > Whose equivalent is setup_max_cpus inside the kernel, as Daniel mentioned.
> >
> >> When I am booting the system, say with 2 out of 4 available cpus,
> >> set via maxcpus variable with intel_idle or acpi_idle and onlining the
> >> other 2 cpus later via sysfs, I dont see cpufreq or cpuidle dir in the
> >> sysfs path.
> >>
> >> # cd /sys/devices/system/cpu/cpu2
> >> xxx:/sys/devices/system/cpu/cpu2# ls
> >> crash_notes node0 online
> >> xxx:/sys/devices/system/cpu/cpu2# echo 1 > online
> >> xxx:/sys/devices/system/cpu/cpu2# ls
> >> cache crash_notes node0 online thermal_throttle topology
> >>
> >> So looks like its designed that way for now.
> >
> >
> > I don't think so. Looks more like a bug than a design ;-)
> >
> >> So if maxcpus=X, X<Y where Y is no of available cpus.
> >> Enabling the Y-X cpus later after the boot via sysfs is not enabling
> >> cpuidle and cpufreq .
> >>
> >> The question is, do we want to modify this behavior ?
> >>
> >
> >
> > Yes we do, and that's Daniel's pain point as well. I don't think there is
> > any good reason why the cpuidle directory must _not_ be exported for cpus
> > that are onlined later.
>
> Yes and if I refer to the code, it is supposed to do that.
>
> I added Thomas in Cc.
maxcpus=X is supposed to statically set the maximum allowed CPUs of the booted
kernel to X.
It's not supposed to online cores exceeding X later.
This is similar to mem=4G, you won't be able to online memory beyond 4G later
at runtime.
Strange that one can online cores beyond X later at runtime, this sounds like
a bug. But maxcpus=X is a debugging variable mostly anyway.
The patch I sent some time ago was to fix CPU hotplug on systems where
a real CPU got added at runtime (without maxcpus being involved).
Not sure whether such systems got finally sold, afaik they are not.
Thomas
^ permalink raw reply
* RE: [RFC PATCH 0/12] generic thermal layer enhancement
From: R, Durgadoss @ 2012-06-19 11:31 UTC (permalink / raw)
To: Zhang, Rui, linux-pm, linux-acpi@vger.kernel.org
Cc: Amit Kachhap, eduardo, Len, Brown, Matthew Garrett
In-Reply-To: <1339384751.1492.153.camel@rui.sh.intel.com>
Hi All,
> The whole idea is
> 1) make sure we have multiple cooling states for both active cooling and
> passive cooling devices. (patch 1,2,3)
> 2) remove passive specific requirement, aka, tc1/tc2, and
> introduce .get_trend() instead, for both active and passive cooling
> algorithm. (patch 4,5)
> 3) introduce new function thermal_zone_trip_update(), this contains the
> code for the general cooling algorithm. (patch 6)
> 4) rename some thermal structures. Use thermal_instance instead of
> thermal_cooling_device_instance, as this structure is used to
> describe the behavior of a certain cooling device for a certain trip
> point in a certain thermal zone.
> thermal_zone_device has a list of all the thermal instances in this
> thermal zone so that it can update them when the temperature changes.
> thermal_cooling_device has a list of all the thermal instances for
> this cooling device so that it can make decision which cooling state
> should be in when the temperature changes. (patch 7,8,9,10)
> 5) introduce a simple arbitrator. (patch 11)
> When temperature changes, we update a thermal zone in two stages,
> a) thermal_zone_trip_point() is the general cooling algorithm to
> update the thermal instances in the thermal zone device
> b) thermal_zone_do_update() is the arbitrator for the cooling device
> to choose the deepest cooling state required to enter.
> 6) unify the code for both passive and active cooling.
>
> TODO, add locking mechanism. I know this is important but as this patch
> set changes the thermal layer a lot, I just want to make sure I'm in the
> right direction before going on.
>
> BTW, in theory, they should make no change to the behavior of the
> current generic thermal layer users. But I have just done the build
> test.
I talked to Rui about this patch set and my other patch sets.
Rui suggested me to rebase my patches on top of his changes.
So, I hope Rui will be able to clean up these 12 patches and submit them
(in a week's time :-)
I will rebase my patches on top of them.
Also, Rui promised me that he can host a tree for us to easily pick up changes,
Let us see :-)
Thanks,
Durga
^ permalink raw reply
* Re: [linux-pm] acpi_idle and max_cpus
From: Daniel Lezcano @ 2012-06-19 7:18 UTC (permalink / raw)
To: Srivatsa S. Bhat; +Cc: Deepthi Dharwar, linux-acpi, linux-pm, trenn
In-Reply-To: <4FE0243C.4040600@linux.vnet.ibm.com>
On 06/19/2012 09:03 AM, Srivatsa S. Bhat wrote:
> On 06/19/2012 12:24 PM, Deepthi Dharwar wrote:
>
>> On 06/18/2012 06:24 PM, Daniel Lezcano wrote:
>>
>>> On 06/18/2012 02:25 PM, Deepthi Dharwar wrote:
>>>> Hi Daniel,
>>>>
>>>> On 06/18/2012 01:48 AM, Daniel Lezcano wrote:
>>>>
>>>>> On 06/15/2012 05:28 PM, Daniel Lezcano wrote:
>>>>>>
>>>>>> Hi all,
>>>>>>
>>>>>> I have a dual core Intel T9500.
>>>>>>
>>>>>> I boot the cpu with the acpi_idle driver and intel_idle enabled in the
>>>>>> config.
>>>>>>
>>>>>> The kernel is booted with maxcpus=1.
>>>>>>
>>>>>> After the system has boot, I put cpu1 online via sysfs.
>>>>>>
>>>>>> But I don't see any 'cpuidle' directory in the cpu's sysfs entry:
>>>>>>
>>>>>> /sys/devices/system/cpu/cpu1/cpuidle (?)
>>>>>>
>>>>>> When I look at the code I see the notifier is present for hotplug in
>>>>>> processor_driver.c and the cpuidle intel init routine should be called
>>>>>> there.
>>>>>>
>>>>
>>>>
>>>> Yes, we have a hotplug notifier.
>>>> Commit 99b72508 by Thomas Renninger fixed this issue.
>>>>
>>>> Please let me know which kernel version you are running and what is idle
>>>> driver registered ?
>>>
>>> The kernel version is 3.5.0-rc1
>>> The registered driver is acpi_idle (with intel_idle if I am not wrong).
>>>
>>> Thomas's patch is in this version.
>>>
>>> Maybe I am wrong but I think the patch is not correct because:
>>>
>>> static int __cpuinit acpi_processor_add(struct acpi_device *device)
>>> {
>>>
>>> ...
>>>
>>> #ifdef CONFIG_SMP
>>> if (pr->id >= setup_max_cpus && pr->id != 0)
>>> return 0;
>>> #endif
>>>
>>> ...
>>>
>>> per_cpu(processors, pr->id) = pr;
>>>
>>> ...
>>> }
>>>
>>> With max_cpus=1 we exit before setting up 'pr'.
>>>
>>> So the condition in:
>>>
>>> static int acpi_cpu_soft_notify(...)
>>> {
>>>
>>> unsigned int cpu = (unsigned long)hcpu;
>>> struct acpi_processor *pr = per_cpu(processors, cpu);
>>>
>>> if (action == CPU_ONLINE && pr) {
>>>
>>> ...
>>> }
>>>
>>> Is always false because pr == NULL
>>>
>>> I did the change but I don't still see the 'cpuidle' directory
>>> appearing, I suspect also pr->flags.need_hotplug_init is not correctly
>>> initialized but I did not investigate more.
>>>
>>
>>
>> Well looks like variable maxcpus holds the key here.
>>
>
>
> Whose equivalent is setup_max_cpus inside the kernel, as Daniel mentioned.
>
>> When I am booting the system, say with 2 out of 4 available cpus,
>> set via maxcpus variable with intel_idle or acpi_idle and onlining the
>> other 2 cpus later via sysfs, I dont see cpufreq or cpuidle dir in the
>> sysfs path.
>>
>> # cd /sys/devices/system/cpu/cpu2
>> xxx:/sys/devices/system/cpu/cpu2# ls
>> crash_notes node0 online
>> xxx:/sys/devices/system/cpu/cpu2# echo 1 > online
>> xxx:/sys/devices/system/cpu/cpu2# ls
>> cache crash_notes node0 online thermal_throttle topology
>>
>> So looks like its designed that way for now.
>
>
> I don't think so. Looks more like a bug than a design ;-)
>
>> So if maxcpus=X, X<Y where Y is no of available cpus.
>> Enabling the Y-X cpus later after the boot via sysfs is not enabling
>> cpuidle and cpufreq .
>>
>> The question is, do we want to modify this behavior ?
>>
>
>
> Yes we do, and that's Daniel's pain point as well. I don't think there is
> any good reason why the cpuidle directory must _not_ be exported for cpus
> that are onlined later.
Yes and if I refer to the code, it is supposed to do that.
I added Thomas in Cc.
Thanks
-- Daniel
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [linux-pm] acpi_idle and max_cpus
From: Srivatsa S. Bhat @ 2012-06-19 7:03 UTC (permalink / raw)
To: Deepthi Dharwar; +Cc: Daniel Lezcano, linux-acpi, linux-pm
In-Reply-To: <4FE02233.2060809@linux.vnet.ibm.com>
On 06/19/2012 12:24 PM, Deepthi Dharwar wrote:
> On 06/18/2012 06:24 PM, Daniel Lezcano wrote:
>
>> On 06/18/2012 02:25 PM, Deepthi Dharwar wrote:
>>> Hi Daniel,
>>>
>>> On 06/18/2012 01:48 AM, Daniel Lezcano wrote:
>>>
>>>> On 06/15/2012 05:28 PM, Daniel Lezcano wrote:
>>>>>
>>>>> Hi all,
>>>>>
>>>>> I have a dual core Intel T9500.
>>>>>
>>>>> I boot the cpu with the acpi_idle driver and intel_idle enabled in the
>>>>> config.
>>>>>
>>>>> The kernel is booted with maxcpus=1.
>>>>>
>>>>> After the system has boot, I put cpu1 online via sysfs.
>>>>>
>>>>> But I don't see any 'cpuidle' directory in the cpu's sysfs entry:
>>>>>
>>>>> /sys/devices/system/cpu/cpu1/cpuidle (?)
>>>>>
>>>>> When I look at the code I see the notifier is present for hotplug in
>>>>> processor_driver.c and the cpuidle intel init routine should be called
>>>>> there.
>>>>>
>>>
>>>
>>> Yes, we have a hotplug notifier.
>>> Commit 99b72508 by Thomas Renninger fixed this issue.
>>>
>>> Please let me know which kernel version you are running and what is idle
>>> driver registered ?
>>
>> The kernel version is 3.5.0-rc1
>> The registered driver is acpi_idle (with intel_idle if I am not wrong).
>>
>> Thomas's patch is in this version.
>>
>> Maybe I am wrong but I think the patch is not correct because:
>>
>> static int __cpuinit acpi_processor_add(struct acpi_device *device)
>> {
>>
>> ...
>>
>> #ifdef CONFIG_SMP
>> if (pr->id >= setup_max_cpus && pr->id != 0)
>> return 0;
>> #endif
>>
>> ...
>>
>> per_cpu(processors, pr->id) = pr;
>>
>> ...
>> }
>>
>> With max_cpus=1 we exit before setting up 'pr'.
>>
>> So the condition in:
>>
>> static int acpi_cpu_soft_notify(...)
>> {
>>
>> unsigned int cpu = (unsigned long)hcpu;
>> struct acpi_processor *pr = per_cpu(processors, cpu);
>>
>> if (action == CPU_ONLINE && pr) {
>>
>> ...
>> }
>>
>> Is always false because pr == NULL
>>
>> I did the change but I don't still see the 'cpuidle' directory
>> appearing, I suspect also pr->flags.need_hotplug_init is not correctly
>> initialized but I did not investigate more.
>>
>
>
> Well looks like variable maxcpus holds the key here.
>
Whose equivalent is setup_max_cpus inside the kernel, as Daniel mentioned.
> When I am booting the system, say with 2 out of 4 available cpus,
> set via maxcpus variable with intel_idle or acpi_idle and onlining the
> other 2 cpus later via sysfs, I dont see cpufreq or cpuidle dir in the
> sysfs path.
>
> # cd /sys/devices/system/cpu/cpu2
> xxx:/sys/devices/system/cpu/cpu2# ls
> crash_notes node0 online
> xxx:/sys/devices/system/cpu/cpu2# echo 1 > online
> xxx:/sys/devices/system/cpu/cpu2# ls
> cache crash_notes node0 online thermal_throttle topology
>
> So looks like its designed that way for now.
I don't think so. Looks more like a bug than a design ;-)
> So if maxcpus=X, X<Y where Y is no of available cpus.
> Enabling the Y-X cpus later after the boot via sysfs is not enabling
> cpuidle and cpufreq .
>
> The question is, do we want to modify this behavior ?
>
Yes we do, and that's Daniel's pain point as well. I don't think there is
any good reason why the cpuidle directory must _not_ be exported for cpus
that are onlined later.
Regards,
Srivatsa S. Bhat
^ permalink raw reply
* Re: [linux-pm] acpi_idle and max_cpus
From: Deepthi Dharwar @ 2012-06-19 6:54 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: linux-acpi, linux-pm
In-Reply-To: <4FDF24FE.1010108@linaro.org>
On 06/18/2012 06:24 PM, Daniel Lezcano wrote:
> On 06/18/2012 02:25 PM, Deepthi Dharwar wrote:
>> Hi Daniel,
>>
>> On 06/18/2012 01:48 AM, Daniel Lezcano wrote:
>>
>>> On 06/15/2012 05:28 PM, Daniel Lezcano wrote:
>>>>
>>>> Hi all,
>>>>
>>>> I have a dual core Intel T9500.
>>>>
>>>> I boot the cpu with the acpi_idle driver and intel_idle enabled in the
>>>> config.
>>>>
>>>> The kernel is booted with maxcpus=1.
>>>>
>>>> After the system has boot, I put cpu1 online via sysfs.
>>>>
>>>> But I don't see any 'cpuidle' directory in the cpu's sysfs entry:
>>>>
>>>> /sys/devices/system/cpu/cpu1/cpuidle (?)
>>>>
>>>> When I look at the code I see the notifier is present for hotplug in
>>>> processor_driver.c and the cpuidle intel init routine should be called
>>>> there.
>>>>
>>
>>
>> Yes, we have a hotplug notifier.
>> Commit 99b72508 by Thomas Renninger fixed this issue.
>>
>> Please let me know which kernel version you are running and what is idle
>> driver registered ?
>
> The kernel version is 3.5.0-rc1
> The registered driver is acpi_idle (with intel_idle if I am not wrong).
>
> Thomas's patch is in this version.
>
> Maybe I am wrong but I think the patch is not correct because:
>
> static int __cpuinit acpi_processor_add(struct acpi_device *device)
> {
>
> ...
>
> #ifdef CONFIG_SMP
> if (pr->id >= setup_max_cpus && pr->id != 0)
> return 0;
> #endif
>
> ...
>
> per_cpu(processors, pr->id) = pr;
>
> ...
> }
>
> With max_cpus=1 we exit before setting up 'pr'.
>
> So the condition in:
>
> static int acpi_cpu_soft_notify(...)
> {
>
> unsigned int cpu = (unsigned long)hcpu;
> struct acpi_processor *pr = per_cpu(processors, cpu);
>
> if (action == CPU_ONLINE && pr) {
>
> ...
> }
>
> Is always false because pr == NULL
>
> I did the change but I don't still see the 'cpuidle' directory
> appearing, I suspect also pr->flags.need_hotplug_init is not correctly
> initialized but I did not investigate more.
>
Well looks like variable maxcpus holds the key here.
When I am booting the system, say with 2 out of 4 available cpus,
set via maxcpus variable with intel_idle or acpi_idle and onlining the
other 2 cpus later via sysfs, I dont see cpufreq or cpuidle dir in the
sysfs path.
# cd /sys/devices/system/cpu/cpu2
xxx:/sys/devices/system/cpu/cpu2# ls
crash_notes node0 online
xxx:/sys/devices/system/cpu/cpu2# echo 1 > online
xxx:/sys/devices/system/cpu/cpu2# ls
cache crash_notes node0 online thermal_throttle topology
So looks like its designed that way for now.
So if maxcpus=X, X<Y where Y is no of available cpus.
Enabling the Y-X cpus later after the boot via sysfs is not enabling
cpuidle and cpufreq .
The question is, do we want to modify this behavior ?
Cheers,
Deepthi
^ permalink raw reply
* Re: [PATCH 1/2] PM: devfreq: add freq table and available_freqs
From: 함명주 @ 2012-06-19 5:49 UTC (permalink / raw)
To: Xiaoguang Chen, Xiaoguang Chen
Cc: 박경민, linux-kernel@vger.kernel.org,
linux-pm@lists.linux-foundation.org
> OK, I get it.
> Another question, do you guys ever want to add the devfreq governor dynamic change feature?
>
> I mean we can switch governors for one devfreq driver dynamically in devfreq framework. current framework only supports statically compile the governor and can't change it dynamically.
>
> Thanks
> Xiaoguang
Yes, that's on the TODO list.
But, we have done nothing to support it, yet, as you can see in git.infradead.org repository.
Cheers!
MyungJoo
^ permalink raw reply
* RE: RE: Re: [PATCH 1/2] PM: devfreq: add freq table and available_freqs
From: Xiaoguang Chen @ 2012-06-19 5:30 UTC (permalink / raw)
To: myungjoo.ham@samsung.com, Xiaoguang Chen
Cc: linux-kernel@vger.kernel.org, 박경민,
linux-pm@lists.linux-foundation.org, myungjoo.ham@gmail.com
In-Reply-To: <9923093.588271340082284749.JavaMail.weblogic@epml24>
OK, I get it.
Another question, do you guys ever want to add the devfreq governor dynamic change feature?
I mean we can switch governors for one devfreq driver dynamically in devfreq framework. current framework only supports statically compile the governor and can't change it dynamically.
Thanks
Xiaoguang
-----Original Message-----
From: 함명주 [mailto:myungjoo.ham@samsung.com]
Sent: 2012年6月19日 13:05
To: Xiaoguang Chen; Xiaoguang Chen
Cc: linux-kernel@vger.kernel.org; 박경민; linux-pm@lists.linux-foundation.org; myungjoo.ham@gmail.com
Subject: Re: RE: Re: [PATCH 1/2] PM: devfreq: add freq table and available_freqs
> Hi, Myungjoo
>
> the API is optional, but I think one frequency table is better to have.
> if user space want to see what is the supported frequencies for the specific devfreq driver, then where do you think we can see this interface?
> do we have to go to OPP framework to get it ? or we can just add it in
> our devfreq ? for example:
> sys/class/devfreq/xxx-devfreq/available_freqs
> I think it is best for us to see this in the same sysfs path.
>
> Thanks
> Xiaoguang
Hi Xiaoguang,
First of all, both conceptually and practically, devfreq subsystem does not need to hold the list of available frequencies. Devfreq subsystem does not care whether a devfreq device has only two (or even one) frequencies available or several billions frequencies available, which is why OPP is dropped from devfreq subsystem and only helper functions are remaining.
The available frequencies information may be in OPP, clock subsystem, or the device driver itself. The listing of available frequencies should be provided by the one who has the information at first.
Anyway, except for the pure curiosity of users, why do we need to provide the list of available frequencies at the devfreq subsystem? If we are adding it in devfreq subsystem, we are adding an ABI and supporting data structure that are never used by the subsystem, but for printing out via ABI which only satisfies the curiosity of users that may already know what it would list up. There are even cases where the devfreq device driver itself also does not aware of avilable frequencies; when OPP is given outside.
Cheers!
MyungJoo.
>
>
> -----Original Message-----
> From: 함명주 [mailto:myungjoo.ham@samsung.com]
> Sent: 2012年6月14日 12:44
> To: Xiaoguang Chen
> Cc: Xiaoguang Chen; linux-kernel@vger.kernel.org; 박경민;
> linux-pm@lists.linux-foundation.org
> Subject: Re: Re: [PATCH 1/2] PM: devfreq: add freq table and
> available_freqs
>
> > Hi, Myungjoo
> >
> >
> > what's your opinion?
>
> Hello Xiaoguang,
>
> Still, I don't think we need additional API and ABI for a simple frequency table. Why a devfreq device driver would want to register a table in struct devfreq while it can hold one either with its dev-data, private data of devfreq, or even OPP.
>
> 1. Devfreq is not "combined" with OPP. OPP is optional.
>
> 2. I guess filling voltage column with some arbitrary values in OPP table won't hurt anything if the device does not care voltage values. (just a suggestion and speculation) Thus, you can still use OPP in your case as long as the frequency values are discrete and not too many.
>
> 3. Devfreq and its governors recommends the base frequency to devfreq drivers. Frequency table is only needed to be visible to devfreq drivers, not to governors or devfreq itself. The frequency table you've suggested is not need to be visible to devfreq subsystem.
>
>
> I still object to adding a frequency table (which is already supported by OPP by not specifying voltage or specifying arbitrary voltage values). However, even if I don't, we won't need that API (devfreq_set_freq_table), which should've been added in device profile at devfreq_add_device() time.
>
>
> Cheers!
> MyungJoo.
>
> >
> >
> > Thanks
> > Xiaoguang
> >
> >
> > > 2012/6/13 Xiaoguang Chen <chenxg.marvell@gmail.com>
> > >
> > > I think Devfreq should not be combined with OPP, OPP framework
> > > does contain one frequency table, but the frequency is combined with voltage. some platforms may don't want to use this but handling voltage seperately in their clock driver.
> > >
> > >
> > > and some platforms don't use OPP, and they want a frequency list.
> > > then this is necessary. also devfreq should contain a frequency list even without any other frameworks, don't you think so ?
> > >
> > >
> > > Thanks
> > > Xiaoguang
> > >
> > >
> > >
> > > 2012/6/13 MyungJoo Ham <myungjoo.ham@samsung.com>
> > > >
> > > > > Devfreq framework don't have a frequency table, add it for
> > > > > easy use.
> > > > >
> > > > > Signed-off-by: Xiaoguang Chen <chenxg@marvell.com>
> > > >
> > > >
> > > > If you need a predefined data structure to support frequency
> > > > table, you can simply use OPP, which has helper functions
> > > > implemented in devfreq subsystem. Is there any reason not to use
> > > > OPP and to implement another data structure to store a frequency table attached to a device?
> > > >
> > > >
> > > > Cheers!
> > > > MyungJoo.
> > > >
>
>
>
>
>
>
>
^ permalink raw reply
* Re: [PATCH 1/2] PM: devfreq: add freq table and available_freqs
From: 함명주 @ 2012-06-19 5:04 UTC (permalink / raw)
To: Xiaoguang Chen, Xiaoguang Chen
Cc: 박경민, linux-kernel@vger.kernel.org,
linux-pm@lists.linux-foundation.org
> Hi, Myungjoo
>
> the API is optional, but I think one frequency table is better to have.
> if user space want to see what is the supported frequencies for the specific devfreq driver, then where do you think we can see this interface?
> do we have to go to OPP framework to get it ? or we can just add it in our devfreq ? for example: sys/class/devfreq/xxx-devfreq/available_freqs
> I think it is best for us to see this in the same sysfs path.
>
> Thanks
> Xiaoguang
Hi Xiaoguang,
First of all, both conceptually and practically, devfreq subsystem does not need to hold the list of available frequencies. Devfreq subsystem does not care whether a devfreq device has only two (or even one) frequencies available or several billions frequencies available, which is why OPP is dropped from devfreq subsystem and only helper functions are remaining.
The available frequencies information may be in OPP, clock subsystem, or the device driver itself. The listing of available frequencies should be provided by the one who has the information at first.
Anyway, except for the pure curiosity of users, why do we need to provide the list of available frequencies at the devfreq subsystem? If we are adding it in devfreq subsystem, we are adding an ABI and supporting data structure that are never used by the subsystem, but for printing out via ABI which only satisfies the curiosity of users that may already know what it would list up. There are even cases where the devfreq device driver itself also does not aware of avilable frequencies; when OPP is given outside.
Cheers!
MyungJoo.
>
>
> -----Original Message-----
> From: 함명주 [mailto:myungjoo.ham@samsung.com]
> Sent: 2012年6月14日 12:44
> To: Xiaoguang Chen
> Cc: Xiaoguang Chen; linux-kernel@vger.kernel.org; 박경민; linux-pm@lists.linux-foundation.org
> Subject: Re: Re: [PATCH 1/2] PM: devfreq: add freq table and available_freqs
>
> > Hi, Myungjoo
> >
> >
> > what's your opinion?
>
> Hello Xiaoguang,
>
> Still, I don't think we need additional API and ABI for a simple frequency table. Why a devfreq device driver would want to register a table in struct devfreq while it can hold one either with its dev-data, private data of devfreq, or even OPP.
>
> 1. Devfreq is not "combined" with OPP. OPP is optional.
>
> 2. I guess filling voltage column with some arbitrary values in OPP table won't hurt anything if the device does not care voltage values. (just a suggestion and speculation) Thus, you can still use OPP in your case as long as the frequency values are discrete and not too many.
>
> 3. Devfreq and its governors recommends the base frequency to devfreq drivers. Frequency table is only needed to be visible to devfreq drivers, not to governors or devfreq itself. The frequency table you've suggested is not need to be visible to devfreq subsystem.
>
>
> I still object to adding a frequency table (which is already supported by OPP by not specifying voltage or specifying arbitrary voltage values). However, even if I don't, we won't need that API (devfreq_set_freq_table), which should've been added in device profile at devfreq_add_device() time.
>
>
> Cheers!
> MyungJoo.
>
> >
> >
> > Thanks
> > Xiaoguang
> >
> >
> > > 2012/6/13 Xiaoguang Chen <chenxg.marvell@gmail.com>
> > >
> > > I think Devfreq should not be combined with OPP, OPP framework does
> > > contain one frequency table, but the frequency is combined with voltage. some platforms may don't want to use this but handling voltage seperately in their clock driver.
> > >
> > >
> > > and some platforms don't use OPP, and they want a frequency list.
> > > then this is necessary. also devfreq should contain a frequency list even without any other frameworks, don't you think so ?
> > >
> > >
> > > Thanks
> > > Xiaoguang
> > >
> > >
> > >
> > > 2012/6/13 MyungJoo Ham <myungjoo.ham@samsung.com>
> > > >
> > > > > Devfreq framework don't have a frequency table, add it for easy
> > > > > use.
> > > > >
> > > > > Signed-off-by: Xiaoguang Chen <chenxg@marvell.com>
> > > >
> > > >
> > > > If you need a predefined data structure to support frequency
> > > > table, you can simply use OPP, which has helper functions
> > > > implemented in devfreq subsystem. Is there any reason not to use
> > > > OPP and to implement another data structure to store a frequency table attached to a device?
> > > >
> > > >
> > > > Cheers!
> > > > MyungJoo.
> > > >
>
>
>
>
>
>
>
^ permalink raw reply
* Re: cpuidle future and improvements
From: Daniel Lezcano @ 2012-06-18 19:00 UTC (permalink / raw)
To: Colin Cross
Cc: Kevin Hilman, Rob Lee, Lists Linaro-dev, Peter De Schrijver,
Linux Kernel Mailing List, Amit Kucheria, linux-acpi, linux-next,
linux-pm, Linus Torvalds, Andrew Morton
In-Reply-To: <CAMbhsRQRFXcayyWjM1RirgFppVAK23z2+3EbYOCw-qmzuY9_2g@mail.gmail.com>
On 06/18/2012 08:15 PM, Colin Cross wrote:
> On Mon, Jun 18, 2012 at 1:40 AM, Daniel Lezcano
> <daniel.lezcano@linaro.org> wrote:
>> I propose to host a cpuidle-next tree where all these modifications will
>> be and where people can send patches against, preventing last minutes
>> conflicts and perhaps Lenb will agree to pull from this tree. In the
>> meantime, the tree will be part of the linux-next, the patches will be
>> more widely tested and could be fixed earlier.
>
> My coupled cpuidle patches were acked and temporarily in Len's
> next/Linus pull branch, but were later dropped when the first pull
> request to Linus was rejected. I asked Len to either put the coupled
> cpuidle patches into his next branch, or let me host them so people
> could base SoC branches off of them and let Len pull them later, but
> got no response. If you do start a cpuidle for-next branch, can you
> pull my coupled-cpuidle branch:
No problem.
Thanks
-- Daniel
> The following changes since commit 76e10d158efb6d4516018846f60c2ab5501900bc:
>
> Linux 3.4 (2012-05-20 15:29:13 -0700)
>
> are available in the git repository at:
> https://android.googlesource.com/kernel/common.git coupled-cpuidle
>
> Colin Cross (4):
> cpuidle: refactor out cpuidle_enter_state
> cpuidle: fix error handling in __cpuidle_register_device
> cpuidle: add support for states that affect multiple cpus
> cpuidle: coupled: add parallel barrier function
>
> drivers/cpuidle/Kconfig | 3 +
> drivers/cpuidle/Makefile | 1 +
> drivers/cpuidle/coupled.c | 715 +++++++++++++++++++++++++++++++++++++++++++++
> drivers/cpuidle/cpuidle.c | 68 ++++-
> drivers/cpuidle/cpuidle.h | 32 ++
> include/linux/cpuidle.h | 11 +
> 6 files changed, 813 insertions(+), 17 deletions(-)
> create mode 100644 drivers/cpuidle/coupled.c
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* Re: cpuidle future and improvements
From: Colin Cross @ 2012-06-18 18:15 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Kevin Hilman, Rob Lee, Lists Linaro-dev, Peter De Schrijver,
Linux Kernel Mailing List, Amit Kucheria, linux-acpi, linux-next,
linux-pm, Linus Torvalds, Andrew Morton
In-Reply-To: <4FDEE98D.7010802@linaro.org>
On Mon, Jun 18, 2012 at 1:40 AM, Daniel Lezcano
<daniel.lezcano@linaro.org> wrote:
> I propose to host a cpuidle-next tree where all these modifications will
> be and where people can send patches against, preventing last minutes
> conflicts and perhaps Lenb will agree to pull from this tree. In the
> meantime, the tree will be part of the linux-next, the patches will be
> more widely tested and could be fixed earlier.
My coupled cpuidle patches were acked and temporarily in Len's
next/Linus pull branch, but were later dropped when the first pull
request to Linus was rejected. I asked Len to either put the coupled
cpuidle patches into his next branch, or let me host them so people
could base SoC branches off of them and let Len pull them later, but
got no response. If you do start a cpuidle for-next branch, can you
pull my coupled-cpuidle branch:
The following changes since commit 76e10d158efb6d4516018846f60c2ab5501900bc:
Linux 3.4 (2012-05-20 15:29:13 -0700)
are available in the git repository at:
https://android.googlesource.com/kernel/common.git coupled-cpuidle
Colin Cross (4):
cpuidle: refactor out cpuidle_enter_state
cpuidle: fix error handling in __cpuidle_register_device
cpuidle: add support for states that affect multiple cpus
cpuidle: coupled: add parallel barrier function
drivers/cpuidle/Kconfig | 3 +
drivers/cpuidle/Makefile | 1 +
drivers/cpuidle/coupled.c | 715 +++++++++++++++++++++++++++++++++++++++++++++
drivers/cpuidle/cpuidle.c | 68 ++++-
drivers/cpuidle/cpuidle.h | 32 ++
include/linux/cpuidle.h | 11 +
6 files changed, 813 insertions(+), 17 deletions(-)
create mode 100644 drivers/cpuidle/coupled.c
^ permalink raw reply
* Re: [linux-pm] cpuidle future and improvements
From: a0393909 @ 2012-06-18 13:30 UTC (permalink / raw)
To: Daniel Lezcano
Cc: linux-acpi, linux-pm, Lists Linaro-dev, Linux Kernel Mailing List,
Kevin Hilman, Peter De Schrijver, Amit Kucheria, linux-next,
Colin Cross, Andrew Morton, Linus Torvalds, Rob Lee
In-Reply-To: <4FDEE98D.7010802@linaro.org>
Daniel,
On 06/18/2012 02:10 PM, Daniel Lezcano wrote:
>
> Dear all,
>
> A few weeks ago, Peter De Schrijver proposed a patch [1] to allow per
> cpu latencies. We had a discussion about this patchset because it
> reverse the modifications Deepthi did some months ago [2] and we may
> want to provide a different implementation.
>
> The Linaro Connect [3] event bring us the opportunity to meet people
> involved in the power management and the cpuidle area for different SoC.
>
> With the Tegra3 and big.LITTLE architecture, making per cpu latencies
> for cpuidle is vital.
>
> Also, the SoC vendors would like to have the ability to tune their cpu
> latencies through the device tree.
>
> We agreed in the following steps:
>
> 1. factor out / cleanup the cpuidle code as much as possible
> 2. better sharing of code amongst SoC idle drivers by moving common bits
> to core code
> 3. make the cpuidle_state structure contain only data
> 4. add a API to register latencies per cpu
>
> These four steps impacts all the architecture. I began the factor out
> code / cleanup [4] and that has been accepted upstream and I proposed
> some modifications [5] but I had a very few answers.
>
Another thing which we discussed is bringing the CPU cluster/package
notion in the core idle code. Couple idle did bring that idea to some
extent but in can be further extended and absratcted. Atm, most of
the work is done in back-end cpuidle drivers which can be easily
abstracted if the "cluster idle" notion is supported in the core layer.
Per CPU __and__ per operating point(OPP), latency is something which
can be also added to the list. From the discussion I remember, it
matters for few SoCs and can be beneficial.
Regards
Santosh
^ permalink raw reply
* Re: cpuidle future and improvements
From: Daniel Lezcano @ 2012-06-18 13:26 UTC (permalink / raw)
To: Jean Pihet
Cc: Peter De Schrijver, Deepthi Dharwar, linux-acpi@vger.kernel.org,
linux-pm@lists.linux-foundation.org, Lists Linaro-dev,
Linux Kernel Mailing List, Amit Kucheria, lenb@kernel.org,
Andrew Morton, Linus Torvalds, Colin Cross, Rob Lee, rjw@sisk.pl,
Kevin Hilman, linux-next@vger.kernel.org
In-Reply-To: <CAORVsuWLLp1v4uQeKCqtSyZNZ8Mj=xA-1ZOfk+OAkHvHMEcwUg@mail.gmail.com>
On 06/18/2012 03:06 PM, Jean Pihet wrote:
> Hi Daniel,
>
> On Mon, Jun 18, 2012 at 2:55 PM, Daniel Lezcano
> <daniel.lezcano@linaro.org> wrote:
>> On 06/18/2012 02:53 PM, Peter De Schrijver wrote:
>>> On Mon, Jun 18, 2012 at 02:35:42PM +0200, Daniel Lezcano wrote:
>>>> On 06/18/2012 01:54 PM, Deepthi Dharwar wrote:
>>>>> On 06/18/2012 02:10 PM, Daniel Lezcano wrote:
>>>>>
>>>>>>
>>>>>> Dear all,
>>>>>>
>>>>>> A few weeks ago, Peter De Schrijver proposed a patch [1] to allow per
>>>>>> cpu latencies. We had a discussion about this patchset because it
>>>>>> reverse the modifications Deepthi did some months ago [2] and we may
>>>>>> want to provide a different implementation.
>>>>>>
>>>>>> The Linaro Connect [3] event bring us the opportunity to meet people
>>>>>> involved in the power management and the cpuidle area for different SoC.
>>>>>>
>>>>>> With the Tegra3 and big.LITTLE architecture, making per cpu latencies
>>>>>> for cpuidle is vital.
>>>>>>
>>>>>> Also, the SoC vendors would like to have the ability to tune their cpu
>>>>>> latencies through the device tree.
>>>>>>
>>>>>> We agreed in the following steps:
>>>>>>
>>>>>> 1. factor out / cleanup the cpuidle code as much as possible
>>>>>> 2. better sharing of code amongst SoC idle drivers by moving common bits
>>>>>> to core code
>>>>>> 3. make the cpuidle_state structure contain only data
>>>>>> 4. add a API to register latencies per cpu
> That makes sense, especially if you can refactor _and_ add new
> functionality at the same time.
Yes :)
>>>>> On huge systems especially servers, doing a cpuidle registration on a
>>>>> per-cpu basis creates a big overhead.
>>>>> So global registration was introduced in the first place.
>>>>>
>>>>> Why not have it as a configurable option or so ?
>>>>> Architectures having uniform cpuidle state parameters can continue to
>>>>> use global registration, else have an api to register latencies per cpu
>>>>> as proposed. We can definitely work to see the best way to implement it.
>>>>
>>>> Absolutely, this is one reason I think adding a function:
>>>>
>>>> cpuidle_register_latencies(int cpu, struct cpuidle_latencies);
>>>>
>>>> makes sense if it is used only for cpus with different latencies.
>>>> The other architecture will be kept untouched.
> Do you mean by keeping the parameters in the cpuidle_driver struct and
> not calling the new API?
Yes, right.
> That looks great.
>
>>>>
>>>> IMHO, before adding more functionalities to cpuidle, we should cleanup
>>>> and consolidate the code. For example, there is a dependency between
>>>> acpi_idle and intel_idle which can be resolved with the notifiers, or
>>>> there is intel specific code in cpuidle.c and cpuidle.h, cpu_relax is
>>>> also introduced to cpuidle which is related to x86 not the cpuidle core,
>>>> etc ...
>>>>
>>>> Cleanup the code will help to move the different bits from the arch
>>>> specific code to the core code and reduce the impact of the core's
>>>> modifications. That should let a common pattern to emerge and will
>>>> facilitate the modifications in the future (per cpu latencies is one of
>>>> them).
>>>>
>>>> That will be a lot of changes and this is why I proposed to put in place
>>>> a cpuidle-next tree in order to consolidate all the cpuidle
>>>> modifications people is willing to see upstream and provide better testing.
> Nice! The new tree needs to be as close as possible to mainline
> though. Do you have plans for that?
Yes, AFAIU as I ask for the cpuidle-next inclusion in linux-next, I have
to base the tree on top of Linus's tree and it will be pulled every day.
That will allow to detect conflicts and bogus commit early, especially
for the numerous x86 architecture variant and cpuidle combination.
For the moment I have a local commits in my tree and I am waiting for
some feedbacks from the lists about the RFC I sent for some cpuidle core
changes.
I will create a clean new tree cpuidle-next.
> Do not hesitate to ask for help on OMAPs!
Cool thanks, will do :)
-- Daniel
> Regards,
> Jean
>
>>>
>>> Sounds like a good idea. Do you have something like that already?
>>
>> Yes but I need to cleanup the tree before.
>>
>> http://git.linaro.org/gitweb?p=people/dlezcano/linux-next.git;a=summary
>>
>> --
>> <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
>>
>> Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
>> <http://twitter.com/#!/linaroorg> Twitter |
>> <http://www.linaro.org/linaro-blog/> Blog
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at http://www.tux.org/lkml/
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: cpuidle future and improvements
From: Jean Pihet @ 2012-06-18 13:06 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Kevin Hilman, Rob Lee, Lists Linaro-dev, Peter De Schrijver,
Linux Kernel Mailing List, Amit Kucheria,
linux-acpi@vger.kernel.org, linux-next@vger.kernel.org,
Colin Cross, linux-pm@lists.linux-foundation.org, Linus Torvalds,
Andrew Morton
In-Reply-To: <4FDF255E.3080402@linaro.org>
Hi Daniel,
On Mon, Jun 18, 2012 at 2:55 PM, Daniel Lezcano
<daniel.lezcano@linaro.org> wrote:
> On 06/18/2012 02:53 PM, Peter De Schrijver wrote:
>> On Mon, Jun 18, 2012 at 02:35:42PM +0200, Daniel Lezcano wrote:
>>> On 06/18/2012 01:54 PM, Deepthi Dharwar wrote:
>>>> On 06/18/2012 02:10 PM, Daniel Lezcano wrote:
>>>>
>>>>>
>>>>> Dear all,
>>>>>
>>>>> A few weeks ago, Peter De Schrijver proposed a patch [1] to allow per
>>>>> cpu latencies. We had a discussion about this patchset because it
>>>>> reverse the modifications Deepthi did some months ago [2] and we may
>>>>> want to provide a different implementation.
>>>>>
>>>>> The Linaro Connect [3] event bring us the opportunity to meet people
>>>>> involved in the power management and the cpuidle area for different SoC.
>>>>>
>>>>> With the Tegra3 and big.LITTLE architecture, making per cpu latencies
>>>>> for cpuidle is vital.
>>>>>
>>>>> Also, the SoC vendors would like to have the ability to tune their cpu
>>>>> latencies through the device tree.
>>>>>
>>>>> We agreed in the following steps:
>>>>>
>>>>> 1. factor out / cleanup the cpuidle code as much as possible
>>>>> 2. better sharing of code amongst SoC idle drivers by moving common bits
>>>>> to core code
>>>>> 3. make the cpuidle_state structure contain only data
>>>>> 4. add a API to register latencies per cpu
That makes sense, especially if you can refactor _and_ add new
functionality at the same time.
>>>> On huge systems especially servers, doing a cpuidle registration on a
>>>> per-cpu basis creates a big overhead.
>>>> So global registration was introduced in the first place.
>>>>
>>>> Why not have it as a configurable option or so ?
>>>> Architectures having uniform cpuidle state parameters can continue to
>>>> use global registration, else have an api to register latencies per cpu
>>>> as proposed. We can definitely work to see the best way to implement it.
>>>
>>> Absolutely, this is one reason I think adding a function:
>>>
>>> cpuidle_register_latencies(int cpu, struct cpuidle_latencies);
>>>
>>> makes sense if it is used only for cpus with different latencies.
>>> The other architecture will be kept untouched.
Do you mean by keeping the parameters in the cpuidle_driver struct and
not calling the new API? That looks great.
>>>
>>> IMHO, before adding more functionalities to cpuidle, we should cleanup
>>> and consolidate the code. For example, there is a dependency between
>>> acpi_idle and intel_idle which can be resolved with the notifiers, or
>>> there is intel specific code in cpuidle.c and cpuidle.h, cpu_relax is
>>> also introduced to cpuidle which is related to x86 not the cpuidle core,
>>> etc ...
>>>
>>> Cleanup the code will help to move the different bits from the arch
>>> specific code to the core code and reduce the impact of the core's
>>> modifications. That should let a common pattern to emerge and will
>>> facilitate the modifications in the future (per cpu latencies is one of
>>> them).
>>>
>>> That will be a lot of changes and this is why I proposed to put in place
>>> a cpuidle-next tree in order to consolidate all the cpuidle
>>> modifications people is willing to see upstream and provide better testing.
Nice! The new tree needs to be as close as possible to mainline
though. Do you have plans for that?
Do not hesitate to ask for help on OMAPs!
Regards,
Jean
>>
>> Sounds like a good idea. Do you have something like that already?
>
> Yes but I need to cleanup the tree before.
>
> http://git.linaro.org/gitweb?p=people/dlezcano/linux-next.git;a=summary
>
> --
> <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
>
> Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
> <http://twitter.com/#!/linaroorg> Twitter |
> <http://www.linaro.org/linaro-blog/> Blog
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply
* Re: cpuidle future and improvements
From: Daniel Lezcano @ 2012-06-18 12:55 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Deepthi Dharwar, linux-acpi@vger.kernel.org,
linux-pm@lists.linux-foundation.org, Lists Linaro-dev,
Linux Kernel Mailing List, Amit Kucheria, lenb@kernel.org,
Andrew Morton, Linus Torvalds, Colin Cross, Rob Lee, rjw@sisk.pl,
Kevin Hilman, linux-next@vger.kernel.org
In-Reply-To: <20120618125327.GB32111@tbergstrom-lnx.Nvidia.com>
On 06/18/2012 02:53 PM, Peter De Schrijver wrote:
> On Mon, Jun 18, 2012 at 02:35:42PM +0200, Daniel Lezcano wrote:
>> On 06/18/2012 01:54 PM, Deepthi Dharwar wrote:
>>> On 06/18/2012 02:10 PM, Daniel Lezcano wrote:
>>>
>>>>
>>>> Dear all,
>>>>
>>>> A few weeks ago, Peter De Schrijver proposed a patch [1] to allow per
>>>> cpu latencies. We had a discussion about this patchset because it
>>>> reverse the modifications Deepthi did some months ago [2] and we may
>>>> want to provide a different implementation.
>>>>
>>>> The Linaro Connect [3] event bring us the opportunity to meet people
>>>> involved in the power management and the cpuidle area for different SoC.
>>>>
>>>> With the Tegra3 and big.LITTLE architecture, making per cpu latencies
>>>> for cpuidle is vital.
>>>>
>>>> Also, the SoC vendors would like to have the ability to tune their cpu
>>>> latencies through the device tree.
>>>>
>>>> We agreed in the following steps:
>>>>
>>>> 1. factor out / cleanup the cpuidle code as much as possible
>>>> 2. better sharing of code amongst SoC idle drivers by moving common bits
>>>> to core code
>>>> 3. make the cpuidle_state structure contain only data
>>>> 4. add a API to register latencies per cpu
>>>
>>> On huge systems especially servers, doing a cpuidle registration on a
>>> per-cpu basis creates a big overhead.
>>> So global registration was introduced in the first place.
>>>
>>> Why not have it as a configurable option or so ?
>>> Architectures having uniform cpuidle state parameters can continue to
>>> use global registration, else have an api to register latencies per cpu
>>> as proposed. We can definitely work to see the best way to implement it.
>>
>> Absolutely, this is one reason I think adding a function:
>>
>> cpuidle_register_latencies(int cpu, struct cpuidle_latencies);
>>
>> makes sense if it is used only for cpus with different latencies.
>> The other architecture will be kept untouched.
>>
>> IMHO, before adding more functionalities to cpuidle, we should cleanup
>> and consolidate the code. For example, there is a dependency between
>> acpi_idle and intel_idle which can be resolved with the notifiers, or
>> there is intel specific code in cpuidle.c and cpuidle.h, cpu_relax is
>> also introduced to cpuidle which is related to x86 not the cpuidle core,
>> etc ...
>>
>> Cleanup the code will help to move the different bits from the arch
>> specific code to the core code and reduce the impact of the core's
>> modifications. That should let a common pattern to emerge and will
>> facilitate the modifications in the future (per cpu latencies is one of
>> them).
>>
>> That will be a lot of changes and this is why I proposed to put in place
>> a cpuidle-next tree in order to consolidate all the cpuidle
>> modifications people is willing to see upstream and provide better testing.
>
> Sounds like a good idea. Do you have something like that already?
Yes but I need to cleanup the tree before.
http://git.linaro.org/gitweb?p=people/dlezcano/linux-next.git;a=summary
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [linux-pm] acpi_idle and max_cpus
From: Daniel Lezcano @ 2012-06-18 12:54 UTC (permalink / raw)
To: Deepthi Dharwar; +Cc: linux-acpi, linux-pm
In-Reply-To: <4FDF1E3A.6010200@linux.vnet.ibm.com>
On 06/18/2012 02:25 PM, Deepthi Dharwar wrote:
> Hi Daniel,
>
> On 06/18/2012 01:48 AM, Daniel Lezcano wrote:
>
>> On 06/15/2012 05:28 PM, Daniel Lezcano wrote:
>>>
>>> Hi all,
>>>
>>> I have a dual core Intel T9500.
>>>
>>> I boot the cpu with the acpi_idle driver and intel_idle enabled in the
>>> config.
>>>
>>> The kernel is booted with maxcpus=1.
>>>
>>> After the system has boot, I put cpu1 online via sysfs.
>>>
>>> But I don't see any 'cpuidle' directory in the cpu's sysfs entry:
>>>
>>> /sys/devices/system/cpu/cpu1/cpuidle (?)
>>>
>>> When I look at the code I see the notifier is present for hotplug in
>>> processor_driver.c and the cpuidle intel init routine should be called
>>> there.
>>>
>
>
> Yes, we have a hotplug notifier.
> Commit 99b72508 by Thomas Renninger fixed this issue.
>
> Please let me know which kernel version you are running and what is idle
> driver registered ?
The kernel version is 3.5.0-rc1
The registered driver is acpi_idle (with intel_idle if I am not wrong).
Thomas's patch is in this version.
Maybe I am wrong but I think the patch is not correct because:
static int __cpuinit acpi_processor_add(struct acpi_device *device)
{
...
#ifdef CONFIG_SMP
if (pr->id >= setup_max_cpus && pr->id != 0)
return 0;
#endif
...
per_cpu(processors, pr->id) = pr;
...
}
With max_cpus=1 we exit before setting up 'pr'.
So the condition in:
static int acpi_cpu_soft_notify(...)
{
unsigned int cpu = (unsigned long)hcpu;
struct acpi_processor *pr = per_cpu(processors, cpu);
if (action == CPU_ONLINE && pr) {
...
}
Is always false because pr == NULL
I did the change but I don't still see the 'cpuidle' directory
appearing, I suspect also pr->flags.need_hotplug_init is not correctly
initialized but I did not investigate more.
>>> I am wondering is it a bug or an expected behavior ?
>>
>> Any thoughts on that ?
>>
>> Thanks
>> -- Daniel
>>
>>
>
>
> Cheers
> Deepthi
>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: cpuidle future and improvements
From: Peter De Schrijver @ 2012-06-18 12:53 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Deepthi Dharwar, linux-acpi@vger.kernel.org,
linux-pm@lists.linux-foundation.org, Lists Linaro-dev,
Linux Kernel Mailing List, Amit Kucheria, lenb@kernel.org,
Andrew Morton, Linus Torvalds, Colin Cross, Rob Lee, rjw@sisk.pl,
Kevin Hilman, linux-next@vger.kernel.org
In-Reply-To: <4FDF209E.7070803@linaro.org>
On Mon, Jun 18, 2012 at 02:35:42PM +0200, Daniel Lezcano wrote:
> On 06/18/2012 01:54 PM, Deepthi Dharwar wrote:
> > On 06/18/2012 02:10 PM, Daniel Lezcano wrote:
> >
> >>
> >> Dear all,
> >>
> >> A few weeks ago, Peter De Schrijver proposed a patch [1] to allow per
> >> cpu latencies. We had a discussion about this patchset because it
> >> reverse the modifications Deepthi did some months ago [2] and we may
> >> want to provide a different implementation.
> >>
> >> The Linaro Connect [3] event bring us the opportunity to meet people
> >> involved in the power management and the cpuidle area for different SoC.
> >>
> >> With the Tegra3 and big.LITTLE architecture, making per cpu latencies
> >> for cpuidle is vital.
> >>
> >> Also, the SoC vendors would like to have the ability to tune their cpu
> >> latencies through the device tree.
> >>
> >> We agreed in the following steps:
> >>
> >> 1. factor out / cleanup the cpuidle code as much as possible
> >> 2. better sharing of code amongst SoC idle drivers by moving common bits
> >> to core code
> >> 3. make the cpuidle_state structure contain only data
> >> 4. add a API to register latencies per cpu
> >
> > On huge systems especially servers, doing a cpuidle registration on a
> > per-cpu basis creates a big overhead.
> > So global registration was introduced in the first place.
> >
> > Why not have it as a configurable option or so ?
> > Architectures having uniform cpuidle state parameters can continue to
> > use global registration, else have an api to register latencies per cpu
> > as proposed. We can definitely work to see the best way to implement it.
>
> Absolutely, this is one reason I think adding a function:
>
> cpuidle_register_latencies(int cpu, struct cpuidle_latencies);
>
> makes sense if it is used only for cpus with different latencies.
> The other architecture will be kept untouched.
>
> IMHO, before adding more functionalities to cpuidle, we should cleanup
> and consolidate the code. For example, there is a dependency between
> acpi_idle and intel_idle which can be resolved with the notifiers, or
> there is intel specific code in cpuidle.c and cpuidle.h, cpu_relax is
> also introduced to cpuidle which is related to x86 not the cpuidle core,
> etc ...
>
> Cleanup the code will help to move the different bits from the arch
> specific code to the core code and reduce the impact of the core's
> modifications. That should let a common pattern to emerge and will
> facilitate the modifications in the future (per cpu latencies is one of
> them).
>
> That will be a lot of changes and this is why I proposed to put in place
> a cpuidle-next tree in order to consolidate all the cpuidle
> modifications people is willing to see upstream and provide better testing.
Sounds like a good idea. Do you have something like that already?
Thanks,
Peter.
^ permalink raw reply
* Re: cpuidle future and improvements
From: Daniel Lezcano @ 2012-06-18 12:35 UTC (permalink / raw)
To: Deepthi Dharwar
Cc: linux-acpi, linux-pm, Lists Linaro-dev, Linux Kernel Mailing List,
Amit Kucheria, lenb@kernel.org, Andrew Morton, Linus Torvalds,
Colin Cross, Peter De Schrijver, Rob Lee, rjw, Kevin Hilman,
linux-next
In-Reply-To: <4FDF16DB.6080004@linux.vnet.ibm.com>
On 06/18/2012 01:54 PM, Deepthi Dharwar wrote:
> On 06/18/2012 02:10 PM, Daniel Lezcano wrote:
>
>>
>> Dear all,
>>
>> A few weeks ago, Peter De Schrijver proposed a patch [1] to allow per
>> cpu latencies. We had a discussion about this patchset because it
>> reverse the modifications Deepthi did some months ago [2] and we may
>> want to provide a different implementation.
>>
>> The Linaro Connect [3] event bring us the opportunity to meet people
>> involved in the power management and the cpuidle area for different SoC.
>>
>> With the Tegra3 and big.LITTLE architecture, making per cpu latencies
>> for cpuidle is vital.
>>
>> Also, the SoC vendors would like to have the ability to tune their cpu
>> latencies through the device tree.
>>
>> We agreed in the following steps:
>>
>> 1. factor out / cleanup the cpuidle code as much as possible
>> 2. better sharing of code amongst SoC idle drivers by moving common bits
>> to core code
>> 3. make the cpuidle_state structure contain only data
>> 4. add a API to register latencies per cpu
>
> On huge systems especially servers, doing a cpuidle registration on a
> per-cpu basis creates a big overhead.
> So global registration was introduced in the first place.
>
> Why not have it as a configurable option or so ?
> Architectures having uniform cpuidle state parameters can continue to
> use global registration, else have an api to register latencies per cpu
> as proposed. We can definitely work to see the best way to implement it.
Absolutely, this is one reason I think adding a function:
cpuidle_register_latencies(int cpu, struct cpuidle_latencies);
makes sense if it is used only for cpus with different latencies.
The other architecture will be kept untouched.
IMHO, before adding more functionalities to cpuidle, we should cleanup
and consolidate the code. For example, there is a dependency between
acpi_idle and intel_idle which can be resolved with the notifiers, or
there is intel specific code in cpuidle.c and cpuidle.h, cpu_relax is
also introduced to cpuidle which is related to x86 not the cpuidle core,
etc ...
Cleanup the code will help to move the different bits from the arch
specific code to the core code and reduce the impact of the core's
modifications. That should let a common pattern to emerge and will
facilitate the modifications in the future (per cpu latencies is one of
them).
That will be a lot of changes and this is why I proposed to put in place
a cpuidle-next tree in order to consolidate all the cpuidle
modifications people is willing to see upstream and provide better testing.
>> These four steps impacts all the architecture. I began the factor out
>> code / cleanup [4] and that has been accepted upstream and I proposed
>> some modifications [5] but I had a very few answers.
>>
>> The patch review are very slow and done at the last minute at the merge
>> window and that makes code upstreaming very difficult. It is not a
>> reproach, it is just how it is and I would like to propose a solution
>> for that.
>>
>> I propose to host a cpuidle-next tree where all these modifications will
>> be and where people can send patches against, preventing last minutes
>> conflicts and perhaps Lenb will agree to pull from this tree. In the
>> meantime, the tree will be part of the linux-next, the patches will be
>> more widely tested and could be fixed earlier.
>>
>> Thanks
>> -- Daniel
>>
>> [1] http://lwn.net/Articles/491257/
>> [2] http://lwn.net/Articles/464808/
>> [3] http://summit.linaro.org/
>> [4]
>> http://www.mail-archive.com/linux-omap@vger.kernel.org/msg67033.html,
>> http://www.spinics.net/lists/linux-pm/msg27330.html,
>> http://comments.gmane.org/gmane.linux.ports.arm.omap/76311,
>> http://www.digipedia.pl/usenet/thread/18885/11795/
>>
>> [5] https://lkml.org/lkml/2012/6/8/375
>>
>
>
> Cheers,
> Deepthi
>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: acpi_idle and max_cpus
From: Deepthi Dharwar @ 2012-06-18 12:25 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: linux-acpi, linux-pm
In-Reply-To: <4FDE3B96.8030306@linaro.org>
Hi Daniel,
On 06/18/2012 01:48 AM, Daniel Lezcano wrote:
> On 06/15/2012 05:28 PM, Daniel Lezcano wrote:
>>
>> Hi all,
>>
>> I have a dual core Intel T9500.
>>
>> I boot the cpu with the acpi_idle driver and intel_idle enabled in the
>> config.
>>
>> The kernel is booted with maxcpus=1.
>>
>> After the system has boot, I put cpu1 online via sysfs.
>>
>> But I don't see any 'cpuidle' directory in the cpu's sysfs entry:
>>
>> /sys/devices/system/cpu/cpu1/cpuidle (?)
>>
>> When I look at the code I see the notifier is present for hotplug in
>> processor_driver.c and the cpuidle intel init routine should be called
>> there.
>>
Yes, we have a hotplug notifier.
Commit 99b72508 by Thomas Renninger fixed this issue.
Please let me know which kernel version you are running and what is idle
driver registered ?
>> I am wondering is it a bug or an expected behavior ?
>
> Any thoughts on that ?
>
> Thanks
> -- Daniel
>
>
Cheers
Deepthi
^ permalink raw reply
* Re: [RFC PATCH v2 09/11] ARM: DT: Add support to system control module for OMAP4
From: Sergei Shtylyov @ 2012-06-18 12:13 UTC (permalink / raw)
To: Konstantin Baydarov
Cc: b-cousson, kishon, santosh.shilimkar, tony, paul, amit.kucheria,
Eduardo Valentin, balbi, linux-pm, linux-omap, linux-arm-kernel,
amit.kachhap
In-Reply-To: <4FDF11D6.6050205@dev.rtsoft.ru>
Hello.
On 18-06-2012 15:32, Konstantin Baydarov wrote:
> This patch adds device tree entries on OMAP4 based boards
> for System Control Module (SCM).
> TODO:
> The IOMEM windows of ctrl_module_core, bandgap, usbphy overlap, so
> probably only specific registers should be specified in dts for
> bandgap and usb phy entries.
> Signed-off-by: Konstantin Baydarov<kbaidarov@dev.rtsoft.ru>
> Signed-off-by: Eduardo Valentin<eduardo.valentin@ti.com>
> ---
> arch/arm/boot/dts/omap4.dtsi | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> Index: linux-2.6/arch/arm/boot/dts/omap4.dtsi
> ===================================================================
> --- linux-2.6.orig/arch/arm/boot/dts/omap4.dtsi
> +++ linux-2.6/arch/arm/boot/dts/omap4.dtsi
> @@ -272,5 +272,22 @@
> ti,hwmods = "mmc5";
> ti,needs-special-reset;
> };
> +
> + ctrl_module_core: ctrl_module_core@4a002000 {
> + compatible = "ti,omap4-control";
> + #address-cells =<1>;
> + #size-cells =<1>;
> + ranges;
> + ti,hwmods = "ctrl_module_core";
> + reg =<0x4a002000 0x1000>;
> + bandgap@4a002000 {
> + compatible = "ti,omap4-bandgap";
> + reg =<0x4a002000 0x1000>;
> + };
> + usb@4a002000 {
> + compatible = "ti,omap4-usb-phy";
> + reg =<0x4a002000 0x1000>;
Two devices at the same address? Also, shouldn't values in the "reg"
property be relative to the value in the parent's "reg" property? Are they
needed at all here?
WBR, Sergei
^ permalink raw reply
* Re: cpuidle future and improvements
From: Deepthi Dharwar @ 2012-06-18 11:54 UTC (permalink / raw)
To: Daniel Lezcano
Cc: linux-acpi, linux-pm, Lists Linaro-dev, Linux Kernel Mailing List,
Amit Kucheria, lenb@kernel.org, Andrew Morton, Linus Torvalds,
Colin Cross, Peter De Schrijver, Rob Lee, rjw, Kevin Hilman,
linux-next
In-Reply-To: <4FDEE98D.7010802@linaro.org>
On 06/18/2012 02:10 PM, Daniel Lezcano wrote:
>
> Dear all,
>
> A few weeks ago, Peter De Schrijver proposed a patch [1] to allow per
> cpu latencies. We had a discussion about this patchset because it
> reverse the modifications Deepthi did some months ago [2] and we may
> want to provide a different implementation.
>
> The Linaro Connect [3] event bring us the opportunity to meet people
> involved in the power management and the cpuidle area for different SoC.
>
> With the Tegra3 and big.LITTLE architecture, making per cpu latencies
> for cpuidle is vital.
>
> Also, the SoC vendors would like to have the ability to tune their cpu
> latencies through the device tree.
>
> We agreed in the following steps:
>
> 1. factor out / cleanup the cpuidle code as much as possible
> 2. better sharing of code amongst SoC idle drivers by moving common bits
> to core code
> 3. make the cpuidle_state structure contain only data
> 4. add a API to register latencies per cpu
On huge systems especially servers, doing a cpuidle registration on a
per-cpu basis creates a big overhead.
So global registration was introduced in the first place.
Why not have it as a configurable option or so ?
Architectures having uniform cpuidle state parameters can continue to
use global registration, else have an api to register latencies per cpu
as proposed. We can definitely work to see the best way to implement it.
> These four steps impacts all the architecture. I began the factor out
> code / cleanup [4] and that has been accepted upstream and I proposed
> some modifications [5] but I had a very few answers.
>
> The patch review are very slow and done at the last minute at the merge
> window and that makes code upstreaming very difficult. It is not a
> reproach, it is just how it is and I would like to propose a solution
> for that.
>
> I propose to host a cpuidle-next tree where all these modifications will
> be and where people can send patches against, preventing last minutes
> conflicts and perhaps Lenb will agree to pull from this tree. In the
> meantime, the tree will be part of the linux-next, the patches will be
> more widely tested and could be fixed earlier.
>
> Thanks
> -- Daniel
>
> [1] http://lwn.net/Articles/491257/
> [2] http://lwn.net/Articles/464808/
> [3] http://summit.linaro.org/
> [4]
> http://www.mail-archive.com/linux-omap@vger.kernel.org/msg67033.html,
> http://www.spinics.net/lists/linux-pm/msg27330.html,
> http://comments.gmane.org/gmane.linux.ports.arm.omap/76311,
> http://www.digipedia.pl/usenet/thread/18885/11795/
>
> [5] https://lkml.org/lkml/2012/6/8/375
>
Cheers,
Deepthi
^ permalink raw reply
* [RFC PATCH v2 09/11] ARM: DT: Add support to system control module for OMAP4
From: Konstantin Baydarov @ 2012-06-18 11:32 UTC (permalink / raw)
To: b-cousson, kishon, kbaidarov, santosh.shilimkar, tony, paul
Cc: balbi, amit.kucheria, linux-pm, linux-arm-kernel, linux-omap,
amit.kachhap, Eduardo Valentin
In-Reply-To: <1337934361-1606-1-git-send-email-eduardo.valentin@ti.com>
This patch adds device tree entries on OMAP4 based boards
for System Control Module (SCM).
TODO:
The IOMEM windows of ctrl_module_core, bandgap, usbphy overlap, so
probably only specific registers should be specified in dts for
bandgap and usb phy entries.
Signed-off-by: Konstantin Baydarov <kbaidarov@dev.rtsoft.ru>
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
arch/arm/boot/dts/omap4.dtsi | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
Index: linux-2.6/arch/arm/boot/dts/omap4.dtsi
===================================================================
--- linux-2.6.orig/arch/arm/boot/dts/omap4.dtsi
+++ linux-2.6/arch/arm/boot/dts/omap4.dtsi
@@ -272,5 +272,22 @@
ti,hwmods = "mmc5";
ti,needs-special-reset;
};
+
+ ctrl_module_core: ctrl_module_core@4a002000 {
+ compatible = "ti,omap4-control";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ ti,hwmods = "ctrl_module_core";
+ reg = <0x4a002000 0x1000>;
+ bandgap@4a002000 {
+ compatible = "ti,omap4-bandgap";
+ reg = <0x4a002000 0x1000>;
+ };
+ usb@4a002000 {
+ compatible = "ti,omap4-usb-phy";
+ reg = <0x4a002000 0x1000>;
+ };
+ };
};
};
^ permalink raw reply
* [RFC PATCH v2 08/11] omap4: thermal: add basic CPU thermal zone
From: Konstantin Baydarov @ 2012-06-18 11:32 UTC (permalink / raw)
To: b-cousson, kishon, kbaidarov, santosh.shilimkar, tony, paul
Cc: balbi, amit.kucheria, linux-pm, linux-arm-kernel, linux-omap,
amit.kachhap, Eduardo Valentin
In-Reply-To: <1337934361-1606-1-git-send-email-eduardo.valentin@ti.com>
This patch exposes OMAP4 thermal sensor as a thermal zone
named "cpu". Only thermal creation is done here.
TODO:
- Add cooling bindings
- Add extrapolation rules
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
drivers/thermal/Kconfig | 12 ++++++
drivers/thermal/Makefile | 1
drivers/thermal/omap-bandgap.c | 1
drivers/thermal/omap-bandgap.h | 12 ++++++
drivers/thermal/omap4-thermal.c | 72 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 98 insertions(+)
Index: linux-2.6/drivers/thermal/Kconfig
===================================================================
--- linux-2.6.orig/drivers/thermal/Kconfig
+++ linux-2.6/drivers/thermal/Kconfig
@@ -38,3 +38,15 @@ config OMAP_BANDGAP
This includes alert interrupts generation and also the TSHUT
support.
+config OMAP4_THERMAL
+ bool "Texas Instruments OMAP4 thermal support"
+ depends on OMAP_BANDGAP
+ depends on ARCH_OMAP4
+ help
+ If you say yes here you get thermal support for the Texas Instruments
+ OMAP4 SoC family. The current chip supported are:
+ - OMAP4460
+
+ This includes alert interrupts generation and also the TSHUT
+ support.
+
Index: linux-2.6/drivers/thermal/Makefile
===================================================================
--- linux-2.6.orig/drivers/thermal/Makefile
+++ linux-2.6/drivers/thermal/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_THERMAL) += thermal_sys.o
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
obj-$(CONFIG_OMAP_BANDGAP) += omap-thermal.o
omap-thermal-y := omap-bandgap.o
+omap-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal.o
Index: linux-2.6/drivers/thermal/omap-bandgap.c
===================================================================
--- linux-2.6.orig/drivers/thermal/omap-bandgap.c
+++ linux-2.6/drivers/thermal/omap-bandgap.c
@@ -1213,6 +1213,7 @@ static const struct omap_bandgap_data om
.fclock_name = "bandgap_ts_fclk",
.div_ck_name = "div_ts_ck",
.conv_table = omap4460_adc_to_temp,
+ .expose_sensor = omap4_thermal_expose_sensor,
.irq = 126,
.sensors = {
{
Index: linux-2.6/drivers/thermal/omap-bandgap.h
===================================================================
--- linux-2.6.orig/drivers/thermal/omap-bandgap.h
+++ linux-2.6/drivers/thermal/omap-bandgap.h
@@ -61,4 +61,16 @@ int omap_bandgap_write_update_interval(s
int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
int *temperature);
+#ifdef CONFIG_OMAP4_THERMAL
+int omap4_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
+ char *domain);
+#else
+static inline int omap4_thermal_expose_sensor(struct omap_bandgap *bg_ptr,
+ int id, char *domain)
+{
+ return 0;
+}
+
+#endif
+
#endif
Index: linux-2.6/drivers/thermal/omap4-thermal.c
===================================================================
--- /dev/null
+++ linux-2.6/drivers/thermal/omap4-thermal.c
@@ -0,0 +1,72 @@
+/*
+ * SPEAr thermal driver.
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Inc.
+ * Contact:
+ * Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/thermal.h>
+
+#include "omap-bandgap.h"
+
+struct omap4_thermal_data {
+ struct thermal_zone_device *omap4_thermal;
+ struct omap_bandgap *bg_ptr;
+ int sensor_id;
+};
+
+static inline int omap4_thermal_get_temp(struct thermal_zone_device *thermal,
+ unsigned long *temp)
+{
+ struct omap4_thermal_data *data = thermal->devdata;
+ int ret, tmp;
+
+ ret = omap_bandgap_read_temperature(data->bg_ptr, data->sensor_id,
+ &tmp);
+ if (!ret)
+ *temp = tmp;
+
+ return ret;
+}
+
+static struct thermal_zone_device_ops omap4_thermal_ops = {
+ .get_temp = omap4_thermal_get_temp,
+};
+
+int omap4_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
+ char *domain)
+{
+ struct omap4_thermal_data *data;
+
+ data = devm_kzalloc(bg_ptr->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ dev_err(bg_ptr->dev, "kzalloc fail\n");
+ return -ENOMEM;
+ }
+ data->sensor_id = id;
+ data->bg_ptr = bg_ptr;
+ data->omap4_thermal = thermal_zone_device_register(domain, 0,
+ data, &omap4_thermal_ops, 0, 0, 0, 0);
+ if (IS_ERR(data->omap4_thermal)) {
+ dev_err(bg_ptr->dev, "thermal zone device is NULL\n");
+ return PTR_ERR(data->omap4_thermal);
+ }
+
+ return 0;
+}
^ permalink raw reply
* [RFC PATCH v2 07/11] ARM: OMAP4+: thermal: introduce bandgap temperature sensor
From: Konstantin Baydarov @ 2012-06-18 11:32 UTC (permalink / raw)
To: b-cousson, kishon, kbaidarov, santosh.shilimkar, tony, paul
Cc: balbi, amit.kucheria, linux-pm, linux-arm-kernel, linux-omap,
amit.kachhap, Eduardo Valentin, Keerthy
In-Reply-To: <1337934361-1606-1-git-send-email-eduardo.valentin@ti.com>
In the System Control Module, OMAP supplies a voltage reference
and a temperature sensor feature that are gathered in the band
gap voltage and temperature sensor (VBGAPTS) module. The band
gap provides current and voltage reference for its internal
circuits and other analog IP blocks. The analog-to-digital
converter (ADC) produces an output value that is proportional
to the silicon temperature.
This patch provides a platform driver which expose this feature.
It is moduled as a MFD child of the System Control Module core
MFD driver.
This driver provides only APIs to access the device properties,
like temperature, thresholds and update rate.
Changes since previous version:
- Bandgap and usb phy: drivers are now independent from control module driver, they use their own API functions.
- Bandgap and usb phy: Added private spinlocks for bandgap and usb drivers.
- Bandgap: Check the type of bandgap dynamically in bandgap driver probe function by reading
omap core control module revision register CONTROL_GEN_CORE_REVISION.
Signed-off-by: Konstantin Baydarov <kbaidarov@dev.rtsoft.ru>
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
---
Documentation/devicetree/bindings/thermal/omap_bandgap.txt | 27
drivers/thermal/Kconfig | 12
drivers/thermal/Makefile | 4
drivers/thermal/omap-bandgap.c | 1654 +++++++++++++
drivers/thermal/omap-bandgap.h | 64
5 files changed, 1760 insertions(+), 1 deletion(-)
Index: linux-2.6/Documentation/devicetree/bindings/thermal/omap_bandgap.txt
===================================================================
--- /dev/null
+++ linux-2.6/Documentation/devicetree/bindings/thermal/omap_bandgap.txt
@@ -0,0 +1,27 @@
+* Texas Instrument OMAP SCM bandgap bindings
+
+In the System Control Module, OMAP supplies a voltage reference
+and a temperature sensor feature that are gathered in the band
+gap voltage and temperature sensor (VBGAPTS) module. The band
+gap provides current and voltage reference for its internal
+circuits and other analog IP blocks. The analog-to-digital
+converter (ADC) produces an output value that is proportional
+to the silicon temperature.
+
+Required properties:
+- compatible : Should be:
+ - "ti,omap4460-control-bandgap" : for OMAP4460 bandgap
+ - "ti,omap5430-control-bandgap" : for OMAP5430 bandgap
+- interrupts : this entry should indicate which interrupt line
+the talert signal is routed to;
+Specific:
+- ti,tshut-gpio : this entry should be used to inform which GPIO
+line the tshut signal is routed to;
+
+Example:
+
+bandgap {
+ compatible = "ti,omap4460-control-bandgap";
+ interrupts = <0 126 4>; /* talert */
+ ti,tshut-gpio = <86>;
+};
Index: linux-2.6/drivers/thermal/Kconfig
===================================================================
--- linux-2.6.orig/drivers/thermal/Kconfig
+++ linux-2.6/drivers/thermal/Kconfig
@@ -26,3 +26,15 @@ config SPEAR_THERMAL
help
Enable this to plug the SPEAr thermal sensor driver into the Linux
thermal framework
+
+config OMAP_BANDGAP
+ tristate "Texas Instruments OMAP4+ temperature sensor driver"
+ depends on THERMAL
+ help
+ If you say yes here you get support for the Texas Instruments
+ OMAP4460+ on die bandgap temperature sensor support. The register
+ set is part of system control module.
+
+ This includes alert interrupts generation and also the TSHUT
+ support.
+
Index: linux-2.6/drivers/thermal/Makefile
===================================================================
--- linux-2.6.orig/drivers/thermal/Makefile
+++ linux-2.6/drivers/thermal/Makefile
@@ -3,4 +3,6 @@
#
obj-$(CONFIG_THERMAL) += thermal_sys.o
-obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
\ No newline at end of file
+obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
+obj-$(CONFIG_OMAP_BANDGAP) += omap-thermal.o
+omap-thermal-y := omap-bandgap.o
Index: linux-2.6/drivers/thermal/omap-bandgap.c
===================================================================
--- /dev/null
+++ linux-2.6/drivers/thermal/omap-bandgap.c
@@ -0,0 +1,1654 @@
+/*
+ * OMAP4 Bandgap temperature sensor driver
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: J Keerthy <j-keerthy@ti.com>
+ * Author: Moiz Sonasath <m-sonasath@ti.com>
+ * Couple of fixes, DT and MFD adaptation:
+ * Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/reboot.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+
+#include <mach/control.h>
+
+#include "omap-bandgap.h"
+
+/* Offsets from the base of temperature sensor registers */
+
+#define OMAP4460_TEMP_SENSOR_CTRL_OFFSET 0x32C
+#define OMAP4460_BGAP_CTRL_OFFSET 0x378
+#define OMAP4460_BGAP_COUNTER_OFFSET 0x37C
+#define OMAP4460_BGAP_THRESHOLD_OFFSET 0x380
+#define OMAP4460_BGAP_TSHUT_OFFSET 0x384
+#define OMAP4460_BGAP_STATUS_OFFSET 0x388
+#define OMAP4460_FUSE_OPP_BGAP 0x260
+
+#define OMAP5430_TEMP_SENSOR_MPU_OFFSET 0x32C
+#define OMAP5430_BGAP_CTRL_OFFSET 0x380
+#define OMAP5430_BGAP_COUNTER_MPU_OFFSET 0x39C
+#define OMAP5430_BGAP_THRESHOLD_MPU_OFFSET 0x384
+#define OMAP5430_BGAP_TSHUT_MPU_OFFSET 0x390
+#define OMAP5430_BGAP_STATUS_OFFSET 0x3A8
+#define OMAP5430_FUSE_OPP_BGAP_MPU 0x1E4
+
+#define OMAP5430_TEMP_SENSOR_GPU_OFFSET 0x330
+#define OMAP5430_BGAP_COUNTER_GPU_OFFSET 0x3A0
+#define OMAP5430_BGAP_THRESHOLD_GPU_OFFSET 0x388
+#define OMAP5430_BGAP_TSHUT_GPU_OFFSET 0x394
+#define OMAP5430_FUSE_OPP_BGAP_GPU 0x1E0
+
+#define OMAP5430_TEMP_SENSOR_CORE_OFFSET 0x334
+#define OMAP5430_BGAP_COUNTER_CORE_OFFSET 0x3A4
+#define OMAP5430_BGAP_THRESHOLD_CORE_OFFSET 0x38C
+#define OMAP5430_BGAP_TSHUT_CORE_OFFSET 0x398
+#define OMAP5430_FUSE_OPP_BGAP_CORE 0x1E8
+
+#define OMAP4460_TSHUT_HOT 900 /* 122 deg C */
+#define OMAP4460_TSHUT_COLD 895 /* 100 deg C */
+#define OMAP4460_T_HOT 800 /* 73 deg C */
+#define OMAP4460_T_COLD 795 /* 71 deg C */
+#define OMAP4460_MAX_FREQ 1500000
+#define OMAP4460_MIN_FREQ 1000000
+#define OMAP4460_MIN_TEMP -40000
+#define OMAP4460_MAX_TEMP 123000
+#define OMAP4460_HYST_VAL 5000
+#define OMAP4460_ADC_START_VALUE 530
+#define OMAP4460_ADC_END_VALUE 932
+
+#define OMAP5430_MPU_TSHUT_HOT 915
+#define OMAP5430_MPU_TSHUT_COLD 900
+#define OMAP5430_MPU_T_HOT 800
+#define OMAP5430_MPU_T_COLD 795
+#define OMAP5430_MPU_MAX_FREQ 1500000
+#define OMAP5430_MPU_MIN_FREQ 1000000
+#define OMAP5430_MPU_MIN_TEMP -40000
+#define OMAP5430_MPU_MAX_TEMP 125000
+#define OMAP5430_MPU_HYST_VAL 5000
+#define OMAP5430_ADC_START_VALUE 532
+#define OMAP5430_ADC_END_VALUE 934
+
+#define OMAP5430_GPU_TSHUT_HOT 915
+#define OMAP5430_GPU_TSHUT_COLD 900
+#define OMAP5430_GPU_T_HOT 800
+#define OMAP5430_GPU_T_COLD 795
+#define OMAP5430_GPU_MAX_FREQ 1500000
+#define OMAP5430_GPU_MIN_FREQ 1000000
+#define OMAP5430_GPU_MIN_TEMP -40000
+#define OMAP5430_GPU_MAX_TEMP 125000
+#define OMAP5430_GPU_HYST_VAL 5000
+
+#define OMAP5430_CORE_TSHUT_HOT 915
+#define OMAP5430_CORE_TSHUT_COLD 900
+#define OMAP5430_CORE_T_HOT 800
+#define OMAP5430_CORE_T_COLD 795
+#define OMAP5430_CORE_MAX_FREQ 1500000
+#define OMAP5430_CORE_MIN_FREQ 1000000
+#define OMAP5430_CORE_MIN_TEMP -40000
+#define OMAP5430_CORE_MAX_TEMP 125000
+#define OMAP5430_CORE_HYST_VAL 5000
+
+/**
+ * The register offsets and bit fields might change across
+ * OMAP versions hence populating them in this structure.
+ */
+
+struct temp_sensor_registers {
+ u32 temp_sensor_ctrl;
+ u32 bgap_tempsoff_mask;
+ u32 bgap_soc_mask;
+ u32 bgap_eocz_mask;
+ u32 bgap_dtemp_mask;
+
+ u32 bgap_mask_ctrl;
+ u32 mask_hot_mask;
+ u32 mask_cold_mask;
+
+ u32 bgap_mode_ctrl;
+ u32 mode_ctrl_mask;
+
+ u32 bgap_counter;
+ u32 counter_mask;
+
+ u32 bgap_threshold;
+ u32 threshold_thot_mask;
+ u32 threshold_tcold_mask;
+
+ u32 tshut_threshold;
+ u32 tshut_hot_mask;
+ u32 tshut_cold_mask;
+
+ u32 bgap_status;
+ u32 status_clean_stop_mask;
+ u32 status_bgap_alert_mask;
+ u32 status_hot_mask;
+ u32 status_cold_mask;
+
+ u32 bgap_efuse;
+ spinlock_t bg_reg_lock;
+};
+
+/**
+ * The thresholds and limits for temperature sensors.
+ */
+struct temp_sensor_data {
+ u32 tshut_hot;
+ u32 tshut_cold;
+ u32 t_hot;
+ u32 t_cold;
+ u32 min_freq;
+ u32 max_freq;
+ int max_temp;
+ int min_temp;
+ int hyst_val;
+ u32 adc_start_val;
+ u32 adc_end_val;
+ u32 update_int1;
+ u32 update_int2;
+};
+
+/**
+ * struct temp_sensor_regval - temperature sensor register values
+ * @bg_mode_ctrl: temp sensor control register value
+ * @bg_ctrl: bandgap ctrl register value
+ * @bg_counter: bandgap counter value
+ * @bg_threshold: bandgap threshold register value
+ * @tshut_threshold: bandgap tshut register value
+ */
+struct temp_sensor_regval {
+ u32 bg_mode_ctrl;
+ u32 bg_ctrl;
+ u32 bg_counter;
+ u32 bg_threshold;
+ u32 tshut_threshold;
+};
+
+/**
+ * struct omap_temp_sensor - bandgap temperature sensor platform data
+ * @ts_data: pointer to struct with thresholds, limits of temperature sensor
+ * @registers: pointer to the list of register offsets and bitfields
+ * @regval: temperature sensor register values
+ * @domain: the name of the domain where the sensor is located
+ */
+struct omap_temp_sensor {
+ struct temp_sensor_data *ts_data;
+ struct temp_sensor_registers *registers;
+ struct temp_sensor_regval *regval;
+ char *domain;
+};
+
+/**
+ * struct omap_bandgap_data - bandgap platform data structure
+ * @has_talert: indicates if the chip has talert output line
+ * @has_tshut: indicates if the chip has tshut output line
+ * @conv_table: Pointer to adc to temperature conversion table
+ * @fclock_name: clock name of the functional clock
+ * @div_ck_nme: clock name of the clock divisor
+ * @sensor_count: count of temperature sensor device in scm
+ * @sensors: array of sensors present in this bandgap instance
+ * @expose_sensor: callback to export sensor to thermal API
+ */
+struct omap_bandgap_data {
+ bool has_talert;
+ bool has_tshut;
+ int tshut_gpio;
+ const int *conv_table;
+ char *fclock_name;
+ char *div_ck_name;
+ int sensor_count;
+ int (*report_temperature)(struct omap_bandgap *bg_ptr, int id);
+ int (*expose_sensor)(struct omap_bandgap *bg_ptr, int id, char *domain);
+ int irq;
+
+ /* this needs to be at the end */
+ struct omap_temp_sensor sensors[];
+};
+
+/* TODO: provide data structures for 4430 */
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap4460_mpu_temp_sensor_registers = {
+ .temp_sensor_ctrl = OMAP4460_TEMP_SENSOR_CTRL_OFFSET,
+ .bgap_tempsoff_mask = OMAP4460_BGAP_TEMPSOFF_MASK,
+ .bgap_soc_mask = OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK,
+ .bgap_eocz_mask = OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK,
+ .bgap_dtemp_mask = OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+ .bgap_mask_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
+ .mask_hot_mask = OMAP4460_MASK_HOT_MASK,
+ .mask_cold_mask = OMAP4460_MASK_COLD_MASK,
+
+ .bgap_mode_ctrl = OMAP4460_BGAP_CTRL_OFFSET,
+ .mode_ctrl_mask = OMAP4460_SINGLE_MODE_MASK,
+
+ .bgap_counter = OMAP4460_BGAP_COUNTER_OFFSET,
+ .counter_mask = OMAP4460_COUNTER_MASK,
+
+ .bgap_threshold = OMAP4460_BGAP_THRESHOLD_OFFSET,
+ .threshold_thot_mask = OMAP4460_T_HOT_MASK,
+ .threshold_tcold_mask = OMAP4460_T_COLD_MASK,
+
+ .tshut_threshold = OMAP4460_BGAP_TSHUT_OFFSET,
+ .tshut_hot_mask = OMAP4460_TSHUT_HOT_MASK,
+ .tshut_cold_mask = OMAP4460_TSHUT_COLD_MASK,
+
+ .bgap_status = OMAP4460_BGAP_STATUS_OFFSET,
+ .status_clean_stop_mask = OMAP4460_CLEAN_STOP_MASK,
+ .status_bgap_alert_mask = OMAP4460_BGAP_ALERT_MASK,
+ .status_hot_mask = OMAP4460_HOT_FLAG_MASK,
+ .status_cold_mask = OMAP4460_COLD_FLAG_MASK,
+
+ .bgap_efuse = OMAP4460_FUSE_OPP_BGAP,
+};
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap5430_mpu_temp_sensor_registers = {
+ .temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_MPU_OFFSET,
+ .bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+ .bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
+ .bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+ .bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+ .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+ .mask_hot_mask = OMAP5430_MASK_HOT_MPU_MASK,
+ .mask_cold_mask = OMAP5430_MASK_COLD_MPU_MASK,
+
+ .bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_MPU_OFFSET,
+ .mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
+
+ .bgap_counter = OMAP5430_BGAP_COUNTER_MPU_OFFSET,
+ .counter_mask = OMAP5430_COUNTER_MASK,
+
+ .bgap_threshold = OMAP5430_BGAP_THRESHOLD_MPU_OFFSET,
+ .threshold_thot_mask = OMAP5430_T_HOT_MASK,
+ .threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+ .tshut_threshold = OMAP5430_BGAP_TSHUT_MPU_OFFSET,
+ .tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+ .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+ .bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+ .status_clean_stop_mask = 0x0,
+ .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
+ .status_hot_mask = OMAP5430_HOT_MPU_FLAG_MASK,
+ .status_cold_mask = OMAP5430_COLD_MPU_FLAG_MASK,
+
+ .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_MPU,
+};
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap5430_gpu_temp_sensor_registers = {
+ .temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_GPU_OFFSET,
+ .bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+ .bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
+ .bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+ .bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+ .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+ .mask_hot_mask = OMAP5430_MASK_HOT_MM_MASK,
+ .mask_cold_mask = OMAP5430_MASK_COLD_MM_MASK,
+
+ .bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_GPU_OFFSET,
+ .mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
+
+ .bgap_counter = OMAP5430_BGAP_COUNTER_GPU_OFFSET,
+ .counter_mask = OMAP5430_COUNTER_MASK,
+
+ .bgap_threshold = OMAP5430_BGAP_THRESHOLD_GPU_OFFSET,
+ .threshold_thot_mask = OMAP5430_T_HOT_MASK,
+ .threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+ .tshut_threshold = OMAP5430_BGAP_TSHUT_GPU_OFFSET,
+ .tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+ .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+ .bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+ .status_clean_stop_mask = 0x0,
+ .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
+ .status_hot_mask = OMAP5430_HOT_MM_FLAG_MASK,
+ .status_cold_mask = OMAP5430_COLD_MM_FLAG_MASK,
+
+ .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_GPU,
+};
+
+/*
+ * OMAP4460 has one instance of thermal sensor for MPU
+ * need to describe the individual bit fields
+ */
+static struct temp_sensor_registers
+omap5430_core_temp_sensor_registers = {
+ .temp_sensor_ctrl = OMAP5430_TEMP_SENSOR_CORE_OFFSET,
+ .bgap_tempsoff_mask = OMAP5430_BGAP_TEMPSOFF_MASK,
+ .bgap_soc_mask = OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK,
+ .bgap_eocz_mask = OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK,
+ .bgap_dtemp_mask = OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK,
+
+ .bgap_mask_ctrl = OMAP5430_BGAP_CTRL_OFFSET,
+ .mask_hot_mask = OMAP5430_MASK_HOT_CORE_MASK,
+ .mask_cold_mask = OMAP5430_MASK_COLD_CORE_MASK,
+
+ .bgap_mode_ctrl = OMAP5430_BGAP_COUNTER_CORE_OFFSET,
+ .mode_ctrl_mask = OMAP5430_REPEAT_MODE_MASK,
+
+ .bgap_counter = OMAP5430_BGAP_COUNTER_CORE_OFFSET,
+ .counter_mask = OMAP5430_COUNTER_MASK,
+
+ .bgap_threshold = OMAP5430_BGAP_THRESHOLD_CORE_OFFSET,
+ .threshold_thot_mask = OMAP5430_T_HOT_MASK,
+ .threshold_tcold_mask = OMAP5430_T_COLD_MASK,
+
+ .tshut_threshold = OMAP5430_BGAP_TSHUT_CORE_OFFSET,
+ .tshut_hot_mask = OMAP5430_TSHUT_HOT_MASK,
+ .tshut_cold_mask = OMAP5430_TSHUT_COLD_MASK,
+
+ .bgap_status = OMAP5430_BGAP_STATUS_OFFSET,
+ .status_clean_stop_mask = 0x0,
+ .status_bgap_alert_mask = OMAP5430_BGAP_ALERT_MASK,
+ .status_hot_mask = OMAP5430_HOT_CORE_FLAG_MASK,
+ .status_cold_mask = OMAP5430_COLD_CORE_FLAG_MASK,
+
+ .bgap_efuse = OMAP5430_FUSE_OPP_BGAP_CORE,
+};
+
+/* Thresholds and limits for OMAP4460 MPU temperature sensor */
+static struct temp_sensor_data omap4460_mpu_temp_sensor_data = {
+ .tshut_hot = OMAP4460_TSHUT_HOT,
+ .tshut_cold = OMAP4460_TSHUT_COLD,
+ .t_hot = OMAP4460_T_HOT,
+ .t_cold = OMAP4460_T_COLD,
+ .min_freq = OMAP4460_MIN_FREQ,
+ .max_freq = OMAP4460_MAX_FREQ,
+ .max_temp = OMAP4460_MAX_TEMP,
+ .min_temp = OMAP4460_MIN_TEMP,
+ .hyst_val = OMAP4460_HYST_VAL,
+ .adc_start_val = OMAP4460_ADC_START_VALUE,
+ .adc_end_val = OMAP4460_ADC_END_VALUE,
+ .update_int1 = 1000,
+ .update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 MPU temperature sensor */
+static struct temp_sensor_data omap5430_mpu_temp_sensor_data = {
+ .tshut_hot = OMAP5430_MPU_TSHUT_HOT,
+ .tshut_cold = OMAP5430_MPU_TSHUT_COLD,
+ .t_hot = OMAP5430_MPU_T_HOT,
+ .t_cold = OMAP5430_MPU_T_COLD,
+ .min_freq = OMAP5430_MPU_MIN_FREQ,
+ .max_freq = OMAP5430_MPU_MAX_FREQ,
+ .max_temp = OMAP5430_MPU_MAX_TEMP,
+ .min_temp = OMAP5430_MPU_MIN_TEMP,
+ .hyst_val = OMAP5430_MPU_HYST_VAL,
+ .adc_start_val = OMAP5430_ADC_START_VALUE,
+ .adc_end_val = OMAP5430_ADC_END_VALUE,
+ .update_int1 = 1000,
+ .update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 GPU temperature sensor */
+static struct temp_sensor_data omap5430_gpu_temp_sensor_data = {
+ .tshut_hot = OMAP5430_GPU_TSHUT_HOT,
+ .tshut_cold = OMAP5430_GPU_TSHUT_COLD,
+ .t_hot = OMAP5430_GPU_T_HOT,
+ .t_cold = OMAP5430_GPU_T_COLD,
+ .min_freq = OMAP5430_GPU_MIN_FREQ,
+ .max_freq = OMAP5430_GPU_MAX_FREQ,
+ .max_temp = OMAP5430_GPU_MAX_TEMP,
+ .min_temp = OMAP5430_GPU_MIN_TEMP,
+ .hyst_val = OMAP5430_GPU_HYST_VAL,
+ .adc_start_val = OMAP5430_ADC_START_VALUE,
+ .adc_end_val = OMAP5430_ADC_END_VALUE,
+ .update_int1 = 1000,
+ .update_int2 = 2000,
+};
+
+/* Thresholds and limits for OMAP5430 CORE temperature sensor */
+static struct temp_sensor_data omap5430_core_temp_sensor_data = {
+ .tshut_hot = OMAP5430_CORE_TSHUT_HOT,
+ .tshut_cold = OMAP5430_CORE_TSHUT_COLD,
+ .t_hot = OMAP5430_CORE_T_HOT,
+ .t_cold = OMAP5430_CORE_T_COLD,
+ .min_freq = OMAP5430_CORE_MIN_FREQ,
+ .max_freq = OMAP5430_CORE_MAX_FREQ,
+ .max_temp = OMAP5430_CORE_MAX_TEMP,
+ .min_temp = OMAP5430_CORE_MIN_TEMP,
+ .hyst_val = OMAP5430_CORE_HYST_VAL,
+ .adc_start_val = OMAP5430_ADC_START_VALUE,
+ .adc_end_val = OMAP5430_ADC_END_VALUE,
+ .update_int1 = 1000,
+ .update_int2 = 2000,
+};
+
+/*
+ * Temperature values in milli degree celsius
+ * ADC code values from 530 to 923
+ */
+static const int
+omap4460_adc_to_temp[OMAP4460_ADC_END_VALUE - OMAP4460_ADC_START_VALUE + 1] = {
+ -40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
+ -37800, -37300, -36800, -36400, -36000, -35600, -35200, -34800,
+ -34300, -33800, -33400, -33000, -32600, -32200, -31800, -31300,
+ -30800, -30400, -30000, -29600, -29200, -28700, -28200, -27800,
+ -27400, -27000, -26600, -26200, -25700, -25200, -24800, -24400,
+ -24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
+ -20600, -20200, -19700, -19200, -18800, -18400, -18000, -17600,
+ -17200, -16700, -16200, -15800, -15400, -15000, -14600, -14200,
+ -13700, -13200, -12800, -12400, -12000, -11600, -11200, -10700,
+ -10200, -9800, -9400, -9000, -8600, -8200, -7700, -7200, -6800,
+ -6400, -6000, -5600, -5200, -4800, -4300, -3800, -3400, -3000,
+ -2600, -2200, -1800, -1300, -800, -400, 0, 400, 800, 1200, 1600,
+ 2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000, 6400,
+ 6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10600, 11000,
+ 11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800,
+ 15300, 15800, 16200, 16600, 17000, 17400, 17800, 18200, 18700,
+ 19200, 19600, 20000, 20400, 20800, 21200, 21600, 22100, 22600,
+ 23000, 23400, 23800, 24200, 24600, 25000, 25400, 25900, 26400,
+ 26800, 27200, 27600, 28000, 28400, 28800, 29300, 29800, 30200,
+ 30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
+ 34400, 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800,
+ 38200, 38600, 39000, 39400, 39800, 40200, 40600, 41100, 41600,
+ 42000, 42400, 42800, 43200, 43600, 44000, 44400, 44800, 45300,
+ 45800, 46200, 46600, 47000, 47400, 47800, 48200, 48600, 49000,
+ 49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400, 52800,
+ 53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600,
+ 57000, 57400, 57800, 58200, 58700, 59200, 59600, 60000, 60400,
+ 60800, 61200, 61600, 62000, 62400, 62800, 63300, 63800, 64200,
+ 64600, 65000, 65400, 65800, 66200, 66600, 67000, 67400, 67800,
+ 68200, 68700, 69200, 69600, 70000, 70400, 70800, 71200, 71600,
+ 72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
+ 75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000,
+ 79400, 79800, 80300, 80800, 81200, 81600, 82000, 82400, 82800,
+ 83200, 83600, 84000, 84400, 84800, 85200, 85600, 86000, 86400,
+ 86800, 87300, 87800, 88200, 88600, 89000, 89400, 89800, 90200,
+ 90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400, 93800,
+ 94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600,
+ 98000, 98400, 98800, 99200, 99600, 100000, 100400, 100800, 101200,
+ 101600, 102000, 102400, 102800, 103200, 103600, 104000, 104400,
+ 104800, 105200, 105600, 106100, 106600, 107000, 107400, 107800,
+ 108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
+ 111400, 111800, 112200, 112600, 113000, 113400, 113800, 114200,
+ 114600, 115000, 115400, 115800, 116200, 116600, 117000, 117400,
+ 117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
+ 121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
+ 124600, 124900, 125000, 125000, 125000, 125000
+};
+
+static const int
+omap5430_adc_to_temp[OMAP5430_ADC_END_VALUE - OMAP5430_ADC_START_VALUE + 1] = {
+ -40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600,
+ -38200, -37800, -37300, -36800,
+ -36400, -36000, -35600, -35200, -34800, -34300, -33800, -33400, -33000,
+ -32600,
+ -32200, -31800, -31300, -30800, -30400, -30000, -29600, -29200, -28700,
+ -28200, -27800, -27400, -27000, -26600, -26200, -25700, -25200, -24800,
+ -24400, -24000, -23600, -23200, -22700, -22200, -21800, -21400, -21000,
+ -20600, -20200, -19700, -19200, -9300, -18400, -18000, -17600, -17200,
+ -16700, -16200, -15800, -15400, -15000, -14600, -14200, -13700, -13200,
+ -12800, -12400, -12000, -11600, -11200, -10700, -10200, -9800, -9400,
+ -9000,
+ -8600, -8200, -7700, -7200, -6800, -6400, -6000, -5600, -5200, -4800,
+ -4300,
+ -3800, -3400, -3000, -2600, -2200, -1800, -1300, -800, -400, 0, 400,
+ 800,
+ 1200, 1600, 2100, 2600, 3000, 3400, 3800, 4200, 4600, 5100, 5600, 6000,
+ 6400, 6800, 7200, 7600, 8000, 8500, 9000, 9400, 9800, 10200, 10800,
+ 11100,
+ 11400, 11900, 12400, 12800, 13200, 13600, 14000, 14400, 14800, 15300,
+ 15800,
+ 16200, 16600, 17000, 17400, 17800, 18200, 18700, 19200, 19600, 20000,
+ 20400,
+ 20800, 21200, 21600, 22100, 22600, 23000, 23400, 23800, 24200, 24600,
+ 25000,
+ 25400, 25900, 26400, 26800, 27200, 27600, 28000, 28400, 28800, 29300,
+ 29800,
+ 30200, 30600, 31000, 31400, 31800, 32200, 32600, 33100, 33600, 34000,
+ 34400,
+ 34800, 35200, 35600, 36000, 36400, 36800, 37300, 37800, 38200, 38600,
+ 39000,
+ 39400, 39800, 40200, 40600, 41100, 41600, 42000, 42400, 42800, 43200,
+ 43600,
+ 44000, 44400, 44800, 45300, 45800, 46200, 46600, 47000, 47400, 47800,
+ 48200,
+ 48600, 49000, 49500, 50000, 50400, 50800, 51200, 51600, 52000, 52400,
+ 52800,
+ 53200, 53700, 54200, 54600, 55000, 55400, 55800, 56200, 56600, 57000,
+ 57400,
+ 57800, 58200, 58700, 59200, 59600, 60000, 60400, 60800, 61200, 61600,
+ 62000,
+ 62400, 62800, 63300, 63800, 64200, 64600, 65000, 65400, 65800, 66200,
+ 66600,
+ 67000, 67400, 67800, 68200, 68700, 69200, 69600, 70000, 70400, 70800,
+ 71200,
+ 71600, 72000, 72400, 72800, 73200, 73600, 74100, 74600, 75000, 75400,
+ 75800,
+ 76200, 76600, 77000, 77400, 77800, 78200, 78600, 79000, 79400, 79800,
+ 80300,
+ 80800, 81200, 81600, 82000, 82400, 82800, 83200, 83600, 84000, 84400,
+ 84800,
+ 85200, 85600, 86000, 86400, 86800, 87300, 87800, 88200, 88600, 89000,
+ 89400,
+ 89800, 90200, 90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400,
+ 93800,
+ 94200, 94600, 95000, 95500, 96000, 96400, 96800, 97200, 97600, 98000,
+ 98400,
+ 98800, 99200, 99600, 100000, 100400, 100800, 101200, 101600, 102000,
+ 102400,
+ 102800, 103200, 103600, 104000, 104400, 104800, 105200, 105600, 106100,
+ 106600, 107000, 107400, 107800, 108200, 108600, 109000, 109400, 109800,
+ 110200, 110600, 111000, 111400, 111800, 112200, 112600, 113000, 113400,
+ 113800, 114200, 114600, 115000, 115400, 115800, 116200, 116600, 117000,
+ 117400, 117800, 118200, 118600, 119000, 119400, 119800, 120200, 120600,
+ 121000, 121400, 121800, 122200, 122600, 123000, 123400, 123800, 124200,
+ 124600, 124900, 125000, 125000, 125000, 125000,
+};
+
+/*
+ * TODO: Get rid from bg_readl() return value -
+ * It's useless.
+ */
+
+static int bg_readl(struct omap_bandgap *bg_ptr, u32 reg, u32 *val)
+{
+ if (!bg_ptr)
+ return -EINVAL;
+
+ *val = __raw_readl(bg_ptr->bg_base + reg);
+ return 0;
+}
+
+/*
+ * TODO: Get rid from bg_writel() return value -
+ * It's useless.
+ */
+static int bg_writel(struct omap_bandgap *bg_ptr, u32 val, u32 reg, spinlock_t *lock)
+{
+ unsigned long flags;
+
+ if (!bg_ptr)
+ return -EINVAL;
+
+ spin_lock_irqsave(lock, flags);
+ __raw_writel(val, bg_ptr->bg_base + reg);
+ spin_unlock_irqrestore(lock, flags);
+ return 0;
+}
+
+static irqreturn_t talert_irq_handler(int irq, void *data)
+{
+ struct omap_bandgap *bg_ptr = data;
+ struct temp_sensor_registers *tsr;
+ u32 t_hot = 0, t_cold = 0, temp, ctrl = 0;
+ int i, r;
+
+ bg_ptr = data;
+ /* Read the status of t_hot */
+ for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
+ tsr = bg_ptr->pdata->sensors[i].registers;
+ r = bg_readl(bg_ptr, tsr->bgap_status, &t_hot);
+ t_hot &= tsr->status_hot_mask;
+
+ /* Read the status of t_cold */
+ r |= bg_readl(bg_ptr, tsr->bgap_status, &t_cold);
+ t_cold &= tsr->status_cold_mask;
+
+ if (!t_cold && !t_hot)
+ continue;
+
+ r |= bg_readl(bg_ptr, tsr->bgap_mask_ctrl, &ctrl);
+ /*
+ * One TALERT interrupt: Two sources
+ * If the interrupt is due to t_hot then mask t_hot and
+ * and unmask t_cold else mask t_cold and unmask t_hot
+ */
+ if (t_hot) {
+ ctrl &= ~tsr->mask_hot_mask;
+ ctrl |= tsr->mask_cold_mask;
+ } else if (t_cold) {
+ ctrl &= ~tsr->mask_cold_mask;
+ ctrl |= tsr->mask_hot_mask;
+ }
+
+ r |= bg_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
+
+ if (r) {
+ dev_err(bg_ptr->dev, "failed to ack talert interrupt\n");
+ return IRQ_NONE;
+ }
+
+ /* read temperature */
+ r = bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
+ temp &= tsr->bgap_dtemp_mask;
+
+ /* report temperature to whom may concern */
+ if (bg_ptr->pdata->report_temperature)
+ bg_ptr->pdata->report_temperature(bg_ptr, i);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_bandgap_tshut_irq_handler(int irq, void *data)
+{
+ orderly_poweroff(true);
+
+ return IRQ_HANDLED;
+}
+
+static
+int adc_to_temp_conversion(struct omap_bandgap *bg_ptr, int id, int adc_val,
+ int *t)
+{
+ struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+
+ /* look up for temperature in the table and return the temperature */
+ if (adc_val < ts_data->adc_start_val || adc_val > ts_data->adc_end_val)
+ return -ERANGE;
+
+ *t = bg_ptr->conv_table[adc_val - ts_data->adc_start_val];
+
+ return 0;
+}
+
+static int temp_to_adc_conversion(long temp, struct omap_bandgap *bg_ptr, int i,
+ int *adc)
+{
+ struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[i].ts_data;
+ int high, low, mid;
+
+ low = 0;
+ high = ts_data->adc_end_val - ts_data->adc_start_val;
+ mid = (high + low) / 2;
+
+ if (temp < bg_ptr->conv_table[high] || temp > bg_ptr->conv_table[high])
+ return -EINVAL;
+
+ while (low < high) {
+ if (temp < bg_ptr->conv_table[mid])
+ high = mid - 1;
+ else
+ low = mid + 1;
+ mid = (low + high) / 2;
+ }
+
+ *adc = ts_data->adc_start_val + low;
+
+ return 0;
+}
+
+static int temp_sensor_unmask_interrupts(struct omap_bandgap *bg_ptr, int id,
+ u32 t_hot, u32 t_cold)
+{
+ struct temp_sensor_registers *tsr;
+ u32 temp = 0, reg_val = 0;
+ int err;
+
+ /* Read the current on die temperature */
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ err = bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
+ temp &= tsr->bgap_dtemp_mask;
+
+ err |= bg_readl(bg_ptr, tsr->bgap_mask_ctrl, ®_val);
+ if (temp < t_hot)
+ reg_val |= tsr->mask_hot_mask;
+ else
+ reg_val &= ~tsr->mask_hot_mask;
+
+ if (t_cold < temp)
+ reg_val |= tsr->mask_cold_mask;
+ else
+ reg_val &= ~tsr->mask_cold_mask;
+ err |= bg_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
+
+ if (err) {
+ dev_err(bg_ptr->dev, "failed to unmask interrupts\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static
+int add_hyst(int adc_val, int hyst_val, struct omap_bandgap *bg_ptr, int i,
+ u32 *sum)
+{
+ int temp, ret;
+
+ ret = adc_to_temp_conversion(bg_ptr, i, adc_val, &temp);
+ if (ret < 0)
+ return ret;
+
+ temp += hyst_val;
+
+ return temp_to_adc_conversion(temp, bg_ptr, i, sum);
+}
+
+static
+int temp_sensor_configure_thot(struct omap_bandgap *bg_ptr, int id, int t_hot)
+{
+ struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+ struct temp_sensor_registers *tsr;
+ u32 thresh_val = 0, reg_val;
+ int cold, err;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+
+ /* obtain the T cold value */
+ err = bg_readl(bg_ptr, tsr->bgap_threshold, &thresh_val);
+ cold = (thresh_val & tsr->threshold_tcold_mask) >>
+ __ffs(tsr->threshold_tcold_mask);
+ if (t_hot <= cold) {
+ /* change the t_cold to t_hot - 5000 millidegrees */
+ err |= add_hyst(t_hot, -ts_data->hyst_val, bg_ptr, id, &cold);
+ /* write the new t_cold value */
+ reg_val = thresh_val & (~tsr->threshold_tcold_mask);
+ reg_val |= cold << __ffs(tsr->threshold_tcold_mask);
+ err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
+ thresh_val = reg_val;
+ }
+
+ /* write the new t_hot value */
+ reg_val = thresh_val & ~tsr->threshold_thot_mask;
+ reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
+ err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
+ if (err) {
+ dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
+ return -EIO;
+ }
+
+ return temp_sensor_unmask_interrupts(bg_ptr, id, t_hot, cold);
+}
+
+static
+int temp_sensor_init_talert_thresholds(struct omap_bandgap *bg_ptr, int id,
+ int t_hot, int t_cold)
+{
+ struct temp_sensor_registers *tsr;
+ u32 reg_val, thresh_val;
+ int err;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ err = bg_readl(bg_ptr, tsr->bgap_threshold, &thresh_val);
+
+ /* write the new t_cold value */
+ reg_val = thresh_val & ~tsr->threshold_tcold_mask;
+ reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
+ err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
+ if (err) {
+ dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
+ return -EIO;
+ }
+
+ err = bg_readl(bg_ptr, tsr->bgap_threshold, &thresh_val);
+
+ /* write the new t_hot value */
+ reg_val = thresh_val & ~tsr->threshold_thot_mask;
+ reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask));
+ err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
+ if (err) {
+ dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
+ return -EIO;
+ }
+
+ err = bg_readl(bg_ptr, tsr->bgap_mask_ctrl, ®_val);
+ reg_val |= tsr->mask_hot_mask;
+ reg_val |= tsr->mask_cold_mask;
+ err |= bg_writel(bg_ptr, reg_val, tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
+ if (err) {
+ dev_err(bg_ptr->dev, "failed to reprogram thot threshold\n");
+ return -EIO;
+ }
+
+ return err;
+}
+
+static
+int temp_sensor_configure_tcold(struct omap_bandgap *bg_ptr, int id,
+ int t_cold)
+{
+ struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+ struct temp_sensor_registers *tsr;
+ u32 thresh_val = 0, reg_val;
+ int hot, err;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ /* obtain the T cold value */
+ err = bg_readl(bg_ptr, tsr->bgap_threshold, &thresh_val);
+ hot = (thresh_val & tsr->threshold_thot_mask) >>
+ __ffs(tsr->threshold_thot_mask);
+
+ if (t_cold >= hot) {
+ /* change the t_hot to t_cold + 5000 millidegrees */
+ err |= add_hyst(t_cold, ts_data->hyst_val, bg_ptr, id, &hot);
+ /* write the new t_hot value */
+ reg_val = thresh_val & (~tsr->threshold_thot_mask);
+ reg_val |= hot << __ffs(tsr->threshold_thot_mask);
+ err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
+ thresh_val = reg_val;
+ }
+
+ /* write the new t_cold value */
+ reg_val = thresh_val & ~tsr->threshold_tcold_mask;
+ reg_val |= (t_cold << __ffs(tsr->threshold_tcold_mask));
+ err |= bg_writel(bg_ptr, reg_val, tsr->bgap_threshold, &tsr->bg_reg_lock);
+ if (err) {
+ dev_err(bg_ptr->dev, "failed to reprogram tcold threshold\n");
+ return -EIO;
+ }
+
+ return temp_sensor_unmask_interrupts(bg_ptr, id, hot, t_cold);
+}
+
+static int temp_sensor_configure_tshut_hot(struct omap_bandgap *bg_ptr,
+ int id, int tshut_hot)
+{
+ struct temp_sensor_registers *tsr;
+ u32 reg_val;
+ int err;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ err = bg_readl(bg_ptr, tsr->tshut_threshold, ®_val);
+ reg_val &= ~tsr->tshut_hot_mask;
+ reg_val |= tshut_hot << __ffs(tsr->tshut_hot_mask);
+ err |= bg_writel(bg_ptr, reg_val, tsr->tshut_threshold, &tsr->bg_reg_lock);
+ if (err) {
+ dev_err(bg_ptr->dev, "failed to reprogram tshut thot\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int temp_sensor_configure_tshut_cold(struct omap_bandgap *bg_ptr,
+ int id, int tshut_cold)
+{
+ struct temp_sensor_registers *tsr;
+ u32 reg_val;
+ int err;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ err = bg_readl(bg_ptr, tsr->tshut_threshold, ®_val);
+ reg_val &= ~tsr->tshut_cold_mask;
+ reg_val |= tshut_cold << __ffs(tsr->tshut_cold_mask);
+ err |= bg_writel(bg_ptr, reg_val, tsr->tshut_threshold, &tsr->bg_reg_lock);
+ if (err) {
+ dev_err(bg_ptr->dev, "failed to reprogram tshut tcold\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int configure_temp_sensor_counter(struct omap_bandgap *bg_ptr, int id,
+ u32 counter)
+{
+ struct temp_sensor_registers *tsr;
+ u32 val = 0;
+ int err;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ err = bg_readl(bg_ptr, tsr->bgap_counter, &val);
+ val &= ~tsr->counter_mask;
+ val |= counter << __ffs(tsr->counter_mask);
+ err |= bg_writel(bg_ptr, val, tsr->bgap_counter, &tsr->bg_reg_lock);
+ if (err) {
+ dev_err(bg_ptr->dev, "failed to reprogram tshut tcold\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* Exposed APIs */
+/**
+ * omap_bandgap_read_thot() - reads sensor current thot
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @thot - resulting current thot value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id,
+ int *thot)
+{
+ struct temp_sensor_registers *tsr;
+ u32 temp;
+ int ret;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ ret = bg_readl(bg_ptr, tsr->bgap_threshold, &temp);
+ temp = (temp & tsr->threshold_thot_mask) >>
+ __ffs(tsr->threshold_thot_mask);
+ ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
+ if (ret) {
+ dev_err(bg_ptr->dev, "failed to read thot\n");
+ return -EIO;
+ }
+
+ *thot = temp;
+
+ return 0;
+}
+
+/**
+ * omap_bandgap_write_thot() - sets sensor current thot
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @val - desired thot value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val)
+{
+ struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+ struct temp_sensor_registers *tsr;
+ u32 t_hot;
+ int ret;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+
+ if (val < ts_data->min_temp + ts_data->hyst_val)
+ return -EINVAL;
+ ret = temp_to_adc_conversion(val, bg_ptr, id, &t_hot);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&bg_ptr->bg_mutex);
+ temp_sensor_configure_thot(bg_ptr, id, t_hot);
+ mutex_unlock(&bg_ptr->bg_mutex);
+
+ return 0;
+}
+
+/**
+ * omap_bandgap_read_tcold() - reads sensor current tcold
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @tcold - resulting current tcold value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id,
+ int *tcold)
+{
+ struct temp_sensor_registers *tsr;
+ u32 temp;
+ int ret;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ ret = bg_readl(bg_ptr, tsr->bgap_threshold, &temp);
+ temp = (temp & tsr->threshold_tcold_mask)
+ >> __ffs(tsr->threshold_tcold_mask);
+ ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
+ if (ret)
+ return -EIO;
+
+ *tcold = temp;
+
+ return 0;
+}
+
+/**
+ * omap_bandgap_write_tcold() - sets the sensor tcold
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @val - desired tcold value
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val)
+{
+ struct temp_sensor_data *ts_data = bg_ptr->pdata->sensors[id].ts_data;
+ struct temp_sensor_registers *tsr;
+ u32 t_cold;
+ int ret;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ if (val > ts_data->max_temp + ts_data->hyst_val)
+ return -EINVAL;
+
+ ret = temp_to_adc_conversion(val, bg_ptr, id, &t_cold);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&bg_ptr->bg_mutex);
+ temp_sensor_configure_tcold(bg_ptr, id, t_cold);
+ mutex_unlock(&bg_ptr->bg_mutex);
+
+ return 0;
+}
+
+/**
+ * omap_bandgap_read_update_interval() - read the sensor update interval
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @interval - resulting update interval in miliseconds
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
+ int *interval)
+{
+ struct temp_sensor_registers *tsr;
+ u32 time;
+ int ret;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ ret = bg_readl(bg_ptr, tsr->bgap_counter, &time);
+ if (ret)
+ return ret;
+ time = (time & tsr->counter_mask) >> __ffs(tsr->counter_mask);
+ time = time * 1000 / bg_ptr->clk_rate;
+
+ *interval = time;
+
+ return 0;
+}
+
+/**
+ * omap_bandgap_write_update_interval() - set the update interval
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @interval - desired update interval in miliseconds
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr,
+ int id, u32 interval)
+{
+ interval = interval * bg_ptr->clk_rate / 1000;
+ mutex_lock(&bg_ptr->bg_mutex);
+ configure_temp_sensor_counter(bg_ptr, id, interval);
+ mutex_unlock(&bg_ptr->bg_mutex);
+
+ return 0;
+}
+
+/**
+ * omap_bandgap_read_temperature() - report current temperature
+ * @bg_ptr - pointer to bandgap instance
+ * @id - sensor id
+ * @temperature - resulting temperature
+ *
+ * returns 0 on success or the proper error code
+ */
+int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
+ int *temperature)
+{
+ struct temp_sensor_registers *tsr;
+ u32 temp;
+ int ret;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ ret = bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
+ temp &= tsr->bgap_dtemp_mask;
+
+ ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
+ if (ret)
+ return -EIO;
+
+ *temperature = temp;
+
+ return 0;
+}
+
+/**
+ * enable_continuous_mode() - One time enabling of continuous conversion mode
+ * @bg_ptr - pointer to scm instance
+ */
+static int enable_continuous_mode(struct omap_bandgap *bg_ptr)
+{
+ struct temp_sensor_registers *tsr;
+ int i, r;
+ u32 val;
+
+ for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
+ tsr = bg_ptr->pdata->sensors[i].registers;
+ r = bg_readl(bg_ptr, tsr->bgap_mode_ctrl, &val);
+ val |= 1 << __ffs(tsr->mode_ctrl_mask);
+ r |= bg_writel(bg_ptr, val, tsr->bgap_mode_ctrl, &tsr->bg_reg_lock);
+ if (r)
+ dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+ }
+
+ return r ? -EIO : 0;
+}
+
+static int omap_bandgap_tshut_init(struct omap_bandgap *bg_ptr,
+ struct platform_device *pdev)
+{
+ int gpio_nr = bg_ptr->tshut_gpio;
+ int status;
+
+ /* Request for gpio_86 line */
+ status = gpio_request(gpio_nr, "tshut");
+ if (status < 0) {
+ dev_err(bg_ptr->dev,
+ "Could not request for TSHUT GPIO:%i\n", 86);
+ return status;
+ }
+ status = gpio_direction_input(gpio_nr);
+ if (status) {
+ dev_err(bg_ptr->dev,
+ "Cannot set input TSHUT GPIO %d\n", gpio_nr);
+ return status;
+ }
+
+ status = request_irq(gpio_to_irq(gpio_nr),
+ omap_bandgap_tshut_irq_handler,
+ IRQF_TRIGGER_RISING, "tshut",
+ NULL);
+ if (status) {
+ gpio_free(gpio_nr);
+ dev_err(bg_ptr->dev, "request irq failed for TSHUT");
+ }
+
+ return 0;
+}
+
+static int omap_bandgap_talert_init(struct omap_bandgap *bg_ptr,
+ struct platform_device *pdev)
+{
+ int ret;
+
+ bg_ptr->irq = platform_get_irq(pdev, 0);
+ if (bg_ptr->irq < 0) {
+ dev_err(&pdev->dev, "get_irq failed\n");
+ return bg_ptr->irq;
+ }
+ ret = request_threaded_irq(bg_ptr->irq, NULL,
+ talert_irq_handler,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "talert", bg_ptr);
+ if (ret) {
+ dev_err(&pdev->dev, "Request threaded irq failed.\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct omap_bandgap_data omap4460_data = {
+ .has_talert = true,
+ .has_tshut = true,
+ .tshut_gpio = 86,
+ .fclock_name = "bandgap_ts_fclk",
+ .div_ck_name = "div_ts_ck",
+ .conv_table = omap4460_adc_to_temp,
+ .irq = 126,
+ .sensors = {
+ {
+ .registers = &omap4460_mpu_temp_sensor_registers,
+ .ts_data = &omap4460_mpu_temp_sensor_data,
+ .domain = "cpu",
+ },
+ },
+ .sensor_count = 1,
+};
+
+static const struct omap_bandgap_data omap5430_data = {
+ .has_talert = true,
+ .has_tshut = true,
+ .tshut_gpio = 0, /* TODO. Fill correct tshut_gpio */
+ .fclock_name = "ts_clk_div_ck",
+ .div_ck_name = "ts_clk_div_ck",
+ .conv_table = omap5430_adc_to_temp,
+ .irq = 0, /* TODO. Fill correct irq */
+ .sensors = {
+ {
+ .registers = &omap5430_mpu_temp_sensor_registers,
+ .ts_data = &omap5430_mpu_temp_sensor_data,
+ .domain = "cpu",
+ },
+ {
+ .registers = &omap5430_gpu_temp_sensor_registers,
+ .ts_data = &omap5430_gpu_temp_sensor_data,
+ .domain = "gpu",
+ },
+ {
+ .registers = &omap5430_core_temp_sensor_registers,
+ .ts_data = &omap5430_core_temp_sensor_data,
+ .domain = "core",
+ },
+ },
+ .sensor_count = 3,
+};
+
+static const struct of_device_id of_omap_bandgap_match[] = {
+ /*
+ * TODO: Add support to 4430
+ * { .compatible = "ti,omap4430-bandgap", .data = , },
+ */
+ {
+ .compatible = "ti,omap4-bandgap",
+ },
+ /* Sentinel */
+ { },
+};
+
+static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct omap_bandgap *bg_ptr;
+ u32 val;
+ struct resource *io_res;
+
+ /* just for the sake */
+ if (!node) {
+ dev_err(&pdev->dev, "No platform information available\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ bg_ptr = devm_kzalloc(&pdev->dev, sizeof(struct omap_bandgap),
+ GFP_KERNEL);
+ if (!bg_ptr) {
+ dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!io_res) {
+ dev_err(&pdev->dev, "Failed to get IO resource\n");
+ return ERR_PTR(-ENOENT);
+ }
+
+// printk("\n\t\t **** omap_bandgap_build(): start %x ", io_res->start);
+// printk("\n\t\t **** omap_bandgap_build(): size %x ", resource_size(io_res));
+ bg_ptr->bg_base = ioremap(io_res->start, resource_size(io_res));
+// printk("\n\t\t **** omap_bandgap_build(): bg_base %x ", bg_ptr->bg_base);
+ if (!bg_ptr->bg_base)
+ return 0;
+
+ bg_readl(bg_ptr, 0x0, &val);
+
+ /*
+ * Check omap control core module revision to find out
+ * bandgap type
+ */
+ switch ((val & 0x3ff) >> 8) {
+ case 1:
+ /* 4430 */
+ bg_ptr->pdata = &omap4460_data;
+ break;
+ case 2:
+ /* 4460 */
+ bg_ptr->pdata = &omap4460_data;
+ break;
+ default:
+ /* Unknown omap control core module revision */
+ return 0;
+ }
+
+ if (bg_ptr->pdata->has_tshut) {
+ bg_ptr->tshut_gpio = bg_ptr->pdata->tshut_gpio;
+ if (!gpio_is_valid(bg_ptr->tshut_gpio)) {
+ dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
+ bg_ptr->tshut_gpio);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
+ return bg_ptr;
+}
+
+struct resource *platform_get_resource_dbg(struct platform_device *dev,
+ unsigned int type, unsigned int num);
+
+static
+int __devinit omap_bandgap_probe(struct platform_device *pdev)
+{
+ struct omap_bandgap *bg_ptr;
+ int clk_rate, ret = 0, i;
+
+ bg_ptr = omap_bandgap_build(pdev);
+ if (IS_ERR_OR_NULL(bg_ptr)) {
+ dev_err(&pdev->dev, "failed to fetch platform data\n");
+ return PTR_ERR(bg_ptr);
+ }
+
+ if (bg_ptr->pdata->has_talert) {
+ ret = omap_bandgap_talert_init(bg_ptr, pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize Talert IRQ\n");
+ return ret;
+ }
+ }
+
+ if (bg_ptr->pdata->has_tshut) {
+ ret = omap_bandgap_tshut_init(bg_ptr, pdev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to initialize system tshut IRQ\n");
+ goto free_talert;
+ }
+ }
+
+ bg_ptr->fclock = clk_get(NULL, bg_ptr->pdata->fclock_name);
+ ret = IS_ERR_OR_NULL(bg_ptr->fclock);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request fclock reference\n");
+ goto free_irqs;
+ }
+
+ bg_ptr->div_clk = clk_get(NULL, bg_ptr->pdata->div_ck_name);
+ ret = IS_ERR_OR_NULL(bg_ptr->div_clk);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to request div_ts_ck clock ref\n");
+ goto free_irqs;
+ }
+
+ bg_ptr->conv_table = bg_ptr->pdata->conv_table;
+ for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
+ struct temp_sensor_registers *tsr;
+ u32 val;
+
+ tsr = bg_ptr->pdata->sensors[i].registers;
+ /* Initialize register lock */
+ spin_lock_init(&tsr->bg_reg_lock);
+
+ /*
+ * check if the efuse has a non-zero value if not
+ * it is an untrimmed sample and the temperatures
+ * may not be accurate
+ */
+ ret = bg_readl(bg_ptr, tsr->bgap_efuse, &val);
+ if (ret || !val)
+ dev_info(&pdev->dev,
+ "Non-trimmed BGAP, Temp not accurate\n");
+ }
+
+ clk_rate = clk_round_rate(bg_ptr->div_clk,
+ bg_ptr->pdata->sensors[0].ts_data->max_freq);
+ if (clk_rate < bg_ptr->pdata->sensors[0].ts_data->min_freq ||
+ clk_rate == 0xffffffff) {
+ ret = -ENODEV;
+ goto put_clks;
+ }
+
+ ret = clk_set_rate(bg_ptr->div_clk, clk_rate);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot set clock rate\n");
+ goto put_clks;
+ }
+
+ bg_ptr->clk_rate = clk_rate;
+ clk_enable(bg_ptr->fclock);
+
+ mutex_init(&bg_ptr->bg_mutex);
+ bg_ptr->dev = &pdev->dev;
+ platform_set_drvdata(pdev, bg_ptr);
+
+ /* 1 clk cycle */
+ for (i = 0; i < bg_ptr->pdata->sensor_count; i++)
+ configure_temp_sensor_counter(bg_ptr, i, 1);
+
+ for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
+ struct temp_sensor_data *ts_data;
+
+ ts_data = bg_ptr->pdata->sensors[i].ts_data;
+
+ temp_sensor_init_talert_thresholds(bg_ptr, i,
+ ts_data->t_hot,
+ ts_data->t_cold);
+ temp_sensor_configure_tshut_hot(bg_ptr, i,
+ ts_data->tshut_hot);
+ temp_sensor_configure_tshut_cold(bg_ptr, i,
+ ts_data->tshut_cold);
+ }
+
+ enable_continuous_mode(bg_ptr);
+
+ /* Set .250 seconds time as default counter */
+ for (i = 0; i < bg_ptr->pdata->sensor_count; i++)
+ configure_temp_sensor_counter(bg_ptr, i,
+ bg_ptr->clk_rate / 4);
+
+ /* Every thing is good? Then expose the sensors */
+ for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
+ char *domain;
+
+ domain = bg_ptr->pdata->sensors[i].domain;
+ if (bg_ptr->pdata->expose_sensor)
+ bg_ptr->pdata->expose_sensor(bg_ptr, i, domain);
+ }
+
+ return 0;
+
+put_clks:
+ clk_disable(bg_ptr->fclock);
+ clk_put(bg_ptr->fclock);
+ clk_put(bg_ptr->div_clk);
+free_irqs:
+ free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
+ gpio_free(bg_ptr->tshut_gpio);
+free_talert:
+ free_irq(bg_ptr->irq, bg_ptr);
+
+ return ret;
+}
+
+static
+int __devexit omap_bandgap_remove(struct platform_device *pdev)
+{
+ struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
+
+ clk_disable(bg_ptr->fclock);
+ clk_put(bg_ptr->fclock);
+ clk_put(bg_ptr->div_clk);
+ free_irq(bg_ptr->irq, bg_ptr);
+ free_irq(gpio_to_irq(bg_ptr->tshut_gpio), NULL);
+ gpio_free(bg_ptr->tshut_gpio);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
+{
+ int err = 0;
+ int i;
+
+ for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
+ struct temp_sensor_registers *tsr;
+ struct temp_sensor_regval *rval;
+
+ rval = bg_ptr->pdata->sensors[i].regval;
+ tsr = bg_ptr->pdata->sensors[i].registers;
+
+ err = bg_readl(bg_ptr, tsr->bgap_mode_ctrl,
+ &rval->bg_mode_ctrl);
+ err |= bg_readl(bg_ptr, tsr->bgap_mask_ctrl,
+ &rval->bg_ctrl);
+ err |= bg_readl(bg_ptr, tsr->bgap_counter,
+ &rval->bg_counter);
+ err |= bg_readl(bg_ptr, tsr->bgap_threshold,
+ &rval->bg_threshold);
+ err |= bg_readl(bg_ptr, tsr->tshut_threshold,
+ &rval->tshut_threshold);
+
+ if (err)
+ dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+ }
+
+ return err ? -EIO : 0;
+}
+
+static int
+omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
+{
+ struct temp_sensor_registers *tsr;
+ u32 temp = 0, counter = 1000;
+ int err;
+
+ tsr = bg_ptr->pdata->sensors[id].registers;
+ /* Select single conversion mode */
+ err = bg_readl(bg_ptr, tsr->bgap_mode_ctrl, &temp);
+ temp &= ~(1 << __ffs(tsr->mode_ctrl_mask));
+ bg_writel(bg_ptr, temp, tsr->bgap_mode_ctrl, &tsr->bg_reg_lock);
+
+ /* Start of Conversion = 1 */
+ err |= bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
+ temp |= 1 << __ffs(tsr->bgap_soc_mask);
+ bg_writel(bg_ptr, temp, tsr->temp_sensor_ctrl, &tsr->bg_reg_lock);
+ /* Wait until DTEMP is updated */
+ err |= bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
+ temp &= (tsr->bgap_dtemp_mask);
+ while ((temp == 0) && --counter) {
+ err |= bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
+ temp &= (tsr->bgap_dtemp_mask);
+ }
+ /* Start of Conversion = 0 */
+ err |= bg_readl(bg_ptr, tsr->temp_sensor_ctrl, &temp);
+ temp &= ~(1 << __ffs(tsr->bgap_soc_mask));
+ err |= bg_writel(bg_ptr, temp, tsr->temp_sensor_ctrl, &tsr->bg_reg_lock);
+
+ return err ? -EIO : 0;
+}
+
+static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
+{
+ int i, err = 0;
+ u32 temp = 0;
+
+ for (i = 0; i < bg_ptr->pdata->sensor_count; i++) {
+ struct temp_sensor_registers *tsr;
+ struct temp_sensor_regval *rval;
+ u32 val = 0;
+
+ rval = bg_ptr->pdata->sensors[i].regval;
+ tsr = bg_ptr->pdata->sensors[i].registers;
+
+ err = bg_readl(bg_ptr, tsr->bgap_counter, &val);
+ if (val == 0) {
+ err |= bg_writel(bg_ptr, rval->bg_threshold,
+ tsr->bgap_threshold, &tsr->bg_reg_lock);
+ err |= bg_writel(bg_ptr, rval->tshut_threshold,
+ tsr->tshut_threshold, &tsr->bg_reg_lock);
+ /* Force immediate temperature measurement and update
+ * of the DTEMP field
+ */
+ omap_bandgap_force_single_read(bg_ptr, i);
+ err |= bg_writel(bg_ptr, rval->bg_counter,
+ tsr->bgap_counter, &tsr->bg_reg_lock);
+ err |= bg_writel(bg_ptr, rval->bg_mode_ctrl,
+ tsr->bgap_mode_ctrl, &tsr->bg_reg_lock);
+ err |= bg_writel(bg_ptr, rval->bg_ctrl,
+ tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
+ } else {
+ err |= bg_readl(bg_ptr, tsr->temp_sensor_ctrl,
+ &temp);
+ temp &= (tsr->bgap_dtemp_mask);
+ if (temp == 0) {
+ omap_bandgap_force_single_read(bg_ptr, i);
+ err |= bg_readl(bg_ptr, tsr->bgap_mask_ctrl,
+ &temp);
+ temp |= 1 << __ffs(tsr->mode_ctrl_mask);
+ err |= bg_writel(bg_ptr, temp,
+ tsr->bgap_mask_ctrl, &tsr->bg_reg_lock);
+ }
+ }
+ if (err)
+ dev_err(bg_ptr->dev, "could not save sensor %d\n", i);
+ }
+
+ return err ? -EIO : 0;
+}
+
+static int omap_bandgap_suspend(struct device *dev)
+{
+ struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
+ int err;
+
+ err = omap_bandgap_save_ctxt(bg_ptr);
+ clk_disable(bg_ptr->fclock);
+
+ return err;
+}
+
+static int omap_bandgap_resume(struct device *dev)
+{
+ struct omap_bandgap *bg_ptr = dev_get_drvdata(dev);
+
+ clk_enable(bg_ptr->fclock);
+
+ return omap_bandgap_restore_ctxt(bg_ptr);
+}
+static const struct dev_pm_ops omap_bandgap_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(omap_bandgap_suspend,
+ omap_bandgap_resume)
+};
+
+#define DEV_PM_OPS (&omap_bandgap_dev_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif
+
+static struct platform_driver omap_bandgap_sensor_driver = {
+ .probe = omap_bandgap_probe,
+ .remove = omap_bandgap_remove,
+ .driver = {
+ .name = "omap-bandgap",
+ .pm = DEV_PM_OPS,
+ .of_match_table = of_omap_bandgap_match,
+ },
+};
+
+module_platform_driver(omap_bandgap_sensor_driver);
+early_platform_init("early_omap_temperature", &omap_bandgap_sensor_driver);
+
+static int __init bg_init(void)
+{
+ return platform_driver_register(&omap_bandgap_sensor_driver);
+}
+
+static void __exit bg_exit(void)
+{
+ platform_driver_unregister(&omap_bandgap_sensor_driver);
+}
+
+module_init(bg_init);
+module_exit(bg_exit);
+
+MODULE_DESCRIPTION("OMAP4+ bandgap temperature sensor driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:omap-bandgap");
+MODULE_AUTHOR("Texas Instrument Inc.");
Index: linux-2.6/drivers/thermal/omap-bandgap.h
===================================================================
--- /dev/null
+++ linux-2.6/drivers/thermal/omap-bandgap.h
@@ -0,0 +1,64 @@
+/*
+ * OMAP4 Bandgap temperature sensor driver
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ * Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifndef __OMAP_BANDGAP_H
+#define __OMAP_BANDGAP_H
+
+struct omap_bandgap_data;
+
+/**
+ * struct omap_bandgap - bandgap device structure
+ * @dev: device pointer
+ * @pdata: platform data with sensor data
+ * @fclock: pointer to functional clock of temperature sensor
+ * @div_clk: pointer to parent clock of temperature sensor fclk
+ * @conv_table: Pointer to adc to temperature conversion table
+ * @bg_mutex: Mutex for sysfs, irq and PM
+ * @irq: MPU Irq number for thermal alert
+ * @tshut_gpio: GPIO where Tshut signal is routed
+ * @clk_rate: Holds current clock rate
+ */
+struct omap_bandgap {
+ struct device *dev;
+ const struct omap_bandgap_data *pdata;
+ struct clk *fclock;
+ struct clk *div_clk;
+ const int *conv_table;
+ struct mutex bg_mutex; /* Mutex for irq and PM */
+ int irq;
+ int tshut_gpio;
+ u32 clk_rate;
+ void __iomem *bg_base;
+};
+
+int omap_bandgap_read_thot(struct omap_bandgap *bg_ptr, int id, int *thot);
+int omap_bandgap_write_thot(struct omap_bandgap *bg_ptr, int id, int val);
+int omap_bandgap_read_tcold(struct omap_bandgap *bg_ptr, int id, int *tcold);
+int omap_bandgap_write_tcold(struct omap_bandgap *bg_ptr, int id, int val);
+int omap_bandgap_read_update_interval(struct omap_bandgap *bg_ptr, int id,
+ int *interval);
+int omap_bandgap_write_update_interval(struct omap_bandgap *bg_ptr, int id,
+ u32 interval);
+int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
+ int *temperature);
+
+#endif
^ permalink raw reply
* [RFC PATCH v2 06/11] ARM: OMAP4+: Adding the temperature sensor register set bit fields
From: Konstantin Baydarov @ 2012-06-18 11:32 UTC (permalink / raw)
To: b-cousson, kishon, kbaidarov, santosh.shilimkar, tony, paul
Cc: balbi, amit.kucheria, linux-pm, linux-arm-kernel, linux-omap,
amit.kachhap, Eduardo Valentin, Keerthy
In-Reply-To: <1337934361-1606-1-git-send-email-eduardo.valentin@ti.com>
OMAP4460 specific temperature sensor register bit fields are added.
Existing OMAP4 entries are renamed to OMAP4430.
Signed-off-by: Keerthy <j-keerthy@ti.com>
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
arch/arm/mach-omap2/include/mach/control.h | 116 ++++++++++++++++++++++++++++
1 files changed, 116 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/include/mach/control.h b/arch/arm/mach-omap2/include/mach/control.h
index cf42764..171b504 100644
--- a/arch/arm/mach-omap2/include/mach/control.h
+++ b/arch/arm/mach-omap2/include/mach/control.h
@@ -230,6 +230,122 @@
/* OMAP44xx control McBSP padconf */
#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP 0x061c
+/* TEMP_SENSOR OMAP4430 */
+#define OMAP4430_BGAP_TEMPSOFF_SHIFT 12
+#define OMAP4430_BGAP_TEMPSOFF_MASK (1 << 12)
+#define OMAP4430_BGAP_TSHUT_SHIFT 11
+#define OMAP4430_BGAP_TSHUT_MASK (1 << 11)
+#define OMAP4430_BGAP_TEMP_SENSOR_CONTCONV_SHIFT 10
+#define OMAP4430_BGAP_TEMP_SENSOR_CONTCONV_MASK (1 << 10)
+#define OMAP4430_BGAP_TEMP_SENSOR_SOC_SHIFT 9
+#define OMAP4430_BGAP_TEMP_SENSOR_SOC_MASK (1 << 9)
+#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_SHIFT 8
+#define OMAP4430_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 8)
+#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0
+#define OMAP4430_BGAP_TEMP_SENSOR_DTEMP_MASK (0xff << 0)
+
+/* TEMP_SENSOR OMAP4460 */
+#define OMAP4460_BGAP_TEMPSOFF_SHIFT 13
+#define OMAP4460_BGAP_TEMPSOFF_MASK (1 << 13)
+#define OMAP4460_BGAP_TEMP_SENSOR_SOC_SHIFT 11
+#define OMAP4460_BGAP_TEMP_SENSOR_SOC_MASK (1 << 11)
+#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_SHIFT 10
+#define OMAP4460_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 10)
+#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0
+#define OMAP4460_BGAP_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0)
+
+/* BANDGAP_CTRL */
+#define OMAP4460_SINGLE_MODE_SHIFT 31
+#define OMAP4460_SINGLE_MODE_MASK (1 << 31)
+#define OMAP4460_MASK_HOT_SHIFT 1
+#define OMAP4460_MASK_HOT_MASK (1 << 1)
+#define OMAP4460_MASK_COLD_SHIFT 0
+#define OMAP4460_MASK_COLD_MASK (1 << 0)
+
+/* BANDGAP_COUNTER */
+#define OMAP4460_COUNTER_SHIFT 0
+#define OMAP4460_COUNTER_MASK (0xffffff << 0)
+
+/* BANDGAP_THRESHOLD */
+#define OMAP4460_T_HOT_SHIFT 16
+#define OMAP4460_T_HOT_MASK (0x3ff << 16)
+#define OMAP4460_T_COLD_SHIFT 0
+#define OMAP4460_T_COLD_MASK (0x3ff << 0)
+
+/* TSHUT_THRESHOLD */
+#define OMAP4460_TSHUT_HOT_SHIFT 16
+#define OMAP4460_TSHUT_HOT_MASK (0x3ff << 16)
+#define OMAP4460_TSHUT_COLD_SHIFT 0
+#define OMAP4460_TSHUT_COLD_MASK (0x3ff << 0)
+
+/* BANDGAP_STATUS */
+#define OMAP4460_CLEAN_STOP_SHIFT 3
+#define OMAP4460_CLEAN_STOP_MASK (1 << 3)
+#define OMAP4460_BGAP_ALERT_SHIFT 2
+#define OMAP4460_BGAP_ALERT_MASK (1 << 2)
+#define OMAP4460_HOT_FLAG_SHIFT 1
+#define OMAP4460_HOT_FLAG_MASK (1 << 1)
+#define OMAP4460_COLD_FLAG_SHIFT 0
+#define OMAP4460_COLD_FLAG_MASK (1 << 0)
+
+/* TEMP_SENSOR OMAP5430 */
+#define OMAP5430_BGAP_TEMP_SENSOR_SOC_SHIFT 12
+#define OMAP5430_BGAP_TEMP_SENSOR_SOC_MASK (1 << 12)
+#define OMAP5430_BGAP_TEMPSOFF_SHIFT 11
+#define OMAP5430_BGAP_TEMPSOFF_MASK (1 << 11)
+#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_SHIFT 10
+#define OMAP5430_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 10)
+#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0
+#define OMAP5430_BGAP_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0)
+
+/* BANDGAP_CTRL */
+#define OMAP5430_MASK_HOT_CORE_SHIFT 5
+#define OMAP5430_MASK_HOT_CORE_MASK (1 << 5)
+#define OMAP5430_MASK_COLD_CORE_SHIFT 4
+#define OMAP5430_MASK_COLD_CORE_MASK (1 << 4)
+#define OMAP5430_MASK_HOT_MM_SHIFT 3
+#define OMAP5430_MASK_HOT_MM_MASK (1 << 3)
+#define OMAP5430_MASK_COLD_MM_SHIFT 2
+#define OMAP5430_MASK_COLD_MM_MASK (1 << 2)
+#define OMAP5430_MASK_HOT_MPU_SHIFT 1
+#define OMAP5430_MASK_HOT_MPU_MASK (1 << 1)
+#define OMAP5430_MASK_COLD_MPU_SHIFT 0
+#define OMAP5430_MASK_COLD_MPU_MASK (1 << 0)
+
+/* BANDGAP_COUNTER */
+#define OMAP5430_REPEAT_MODE_SHIFT 31
+#define OMAP5430_REPEAT_MODE_MASK (1 << 31)
+#define OMAP5430_COUNTER_SHIFT 0
+#define OMAP5430_COUNTER_MASK (0xffffff << 0)
+
+/* BANDGAP_THRESHOLD */
+#define OMAP5430_T_HOT_SHIFT 16
+#define OMAP5430_T_HOT_MASK (0x3ff << 16)
+#define OMAP5430_T_COLD_SHIFT 0
+#define OMAP5430_T_COLD_MASK (0x3ff << 0)
+
+/* TSHUT_THRESHOLD */
+#define OMAP5430_TSHUT_HOT_SHIFT 16
+#define OMAP5430_TSHUT_HOT_MASK (0x3ff << 16)
+#define OMAP5430_TSHUT_COLD_SHIFT 0
+#define OMAP5430_TSHUT_COLD_MASK (0x3ff << 0)
+
+/* BANDGAP_STATUS */
+#define OMAP5430_BGAP_ALERT_SHIFT 31
+#define OMAP5430_BGAP_ALERT_MASK (1 << 31)
+#define OMAP5430_HOT_CORE_FLAG_SHIFT 5
+#define OMAP5430_HOT_CORE_FLAG_MASK (1 << 5)
+#define OMAP5430_COLD_CORE_FLAG_SHIFT 4
+#define OMAP5430_COLD_CORE_FLAG_MASK (1 << 4)
+#define OMAP5430_HOT_MM_FLAG_SHIFT 3
+#define OMAP5430_HOT_MM_FLAG_MASK (1 << 3)
+#define OMAP5430_COLD_MM_FLAG_SHIFT 2
+#define OMAP5430_COLD_MM_FLAG_MASK (1 << 2)
+#define OMAP5430_HOT_MPU_FLAG_SHIFT 1
+#define OMAP5430_HOT_MPU_FLAG_MASK (1 << 1)
+#define OMAP5430_COLD_MPU_FLAG_SHIFT 0
+#define OMAP5430_COLD_MPU_FLAG_MASK (1 << 0)
+
/* AM35XX only CONTROL_GENERAL register offsets */
#define AM35XX_CONTROL_MSUSPENDMUX_6 (OMAP2_CONTROL_GENERAL + 0x0038)
#define AM35XX_CONTROL_DEVCONF2 (OMAP2_CONTROL_GENERAL + 0x0310)
--
1.7.7.1.488.ge8e1c
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox