Re: [PATCH 3/3] rtc: s5m: Make register configuration per S2MPS device to remove exceptions

2015-12-29 Thread Yadwinder Singh Brar
Hi Krysztof,

On Tue, Dec 29, 2015 at 5:53 PM, Krzysztof Kozlowski
 wrote:
> Before updating time and alarm the driver must set appropriate mask in
> UDR register. For that purpose the driver uses common register
> configuration and a lot of exceptions per device in the code. The
> exceptions are not obvious, for example except the change in the logic
> sometimes the fields are swapped (WUDR and AUDR between S2MPS14 and
> S2MPS15). This leads to quite complicated code.
>
> Try to make it more obvious by:
> 1. Documenting the UDR masks for devices and operations.
> 2. Adding fields in register configuration structure for each operation
>(read time, write time and alarm).
> 3. Splitting the configuration per S2MPS13, S2MPS14 and S2MPS15 thus
>removing exceptions for them.
>
> Signed-off-by: Krzysztof Kozlowski 
>
> ---
>
> Tested only on S2MPS11 (Odroid XU4).
> ---
>  drivers/rtc/rtc-s5m.c   | 110 
> +++-
>  include/linux/mfd/samsung/rtc.h |   2 +
>  2 files changed, 77 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
> index 559db8f72117..7407d7394bb4 100644
> --- a/drivers/rtc/rtc-s5m.c
> +++ b/drivers/rtc/rtc-s5m.c
> @@ -38,7 +38,22 @@
>   */
>  #define UDR_READ_RETRY_CNT 5
>
> -/* Registers used by the driver which are different between chipsets. */
> +/*
> + * Registers used by the driver which are different between chipsets.
> + *
> + * Operations like read time and write alarm/time require updating
> + * specific fields in UDR register. These fields usually are auto-cleared
> + * (with some exceptions).
> + *
> + * Table of operations per device:
> + *
> + * Device | Write time | Read time | Write alarm
> + * =
> + * S5M8767| UDR + TIME |   | UDR
> + * S2MPS11/14 | WUDR   | RUDR  | WUDR + RUDR
> + * S2MPS13| WUDR   | RUDR  | WUDR + AUDR
> + * S2MPS15| WUDR   | RUDR  | AUDR
> + */
>  struct s5m_rtc_reg_config {
> /* Number of registers used for setting time/alarm0/alarm1 */
> unsigned int regs_count;
> @@ -58,8 +73,13 @@ struct s5m_rtc_reg_config {
> unsigned int udr_update;
> /* Auto-cleared mask in UDR field for writing time and alarm */
> unsigned int autoclear_udr_mask;
> -   /* Mask for UDR field in 'udr_update' register */
> -   unsigned int udr_mask;
> +   /*
> +* Masks in UDR field for time and alarm operations.
> +* The read time mask can be 0. Rest should not.
> +*/
> +   unsigned int read_time_udr_mask;
> +   unsigned int write_time_udr_mask;
> +   unsigned int write_alarm_udr_mask;
>  };
>
>  /* Register map for S5M8763 and S5M8767 */
> @@ -71,14 +91,44 @@ static const struct s5m_rtc_reg_config s5m_rtc_regs = {
> .alarm1 = S5M_ALARM1_SEC,
> .udr_update = S5M_RTC_UDR_CON,
> .autoclear_udr_mask = S5M_RTC_UDR_MASK,
> -   .udr_mask   = S5M_RTC_UDR_MASK,
> +   .read_time_udr_mask = 0, /* Not needed */
> +   .write_time_udr_mask= S5M_RTC_UDR_MASK | S5M_RTC_TIME_EN_MASK,
> +   .write_alarm_udr_mask   = S5M_RTC_UDR_MASK,
> +};
> +
> +/* Register map for S2MPS13 */
> +static const struct s5m_rtc_reg_config s2mps13_rtc_regs = {
> +   .regs_count = 7,
> +   .time   = S2MPS_RTC_SEC,
> +   .ctrl   = S2MPS_RTC_CTRL,
> +   .alarm0 = S2MPS_ALARM0_SEC,
> +   .alarm1 = S2MPS_ALARM1_SEC,
> +   .udr_update = S2MPS_RTC_UDR_CON,
> +   .autoclear_udr_mask = S2MPS_RTC_WUDR_MASK,
> +   .read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
> +   .write_time_udr_mask= S2MPS_RTC_WUDR_MASK,
> +   .write_alarm_udr_mask   = S2MPS_RTC_WUDR_MASK | S2MPS13_RTC_AUDR_MASK,
> +};
> +
> +/* Register map for S2MPS11/14 */
> +static const struct s5m_rtc_reg_config s2mps14_rtc_regs = {
> +   .regs_count = 7,
> +   .time   = S2MPS_RTC_SEC,
> +   .ctrl   = S2MPS_RTC_CTRL,
> +   .alarm0 = S2MPS_ALARM0_SEC,
> +   .alarm1 = S2MPS_ALARM1_SEC,
> +   .udr_update = S2MPS_RTC_UDR_CON,
> +   .autoclear_udr_mask = S2MPS_RTC_WUDR_MASK,
> +   .read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
> +   .write_time_udr_mask= S2MPS_RTC_WUDR_MASK,
> +   .write_alarm_udr_mask   = S2MPS_RTC_WUDR_MASK | S2MPS_RTC_RUDR_MASK,
>  };
>
>  /*
> - * Register map for S2MPS14.
> - * It may be also suitable for S2MPS11 but this was not tested.
> + * Register map for S2MPS15 - in comparison to S2MPS14 the WUDR and AUDR bits
> + * are swapped.
>   */
> -static const struct s5m_rtc_reg_config s2mps_rtc_regs = {
> +static const struct s5m_rtc_reg_config s2mps15_rtc_regs = {
> .regs_count = 7,
> .time  

Re: [PATCH 3/3] rtc: s5m: Make register configuration per S2MPS device to remove exceptions

2015-12-29 Thread Yadwinder Singh Brar
Hi Krysztof,

On Tue, Dec 29, 2015 at 5:53 PM, Krzysztof Kozlowski
 wrote:
> Before updating time and alarm the driver must set appropriate mask in
> UDR register. For that purpose the driver uses common register
> configuration and a lot of exceptions per device in the code. The
> exceptions are not obvious, for example except the change in the logic
> sometimes the fields are swapped (WUDR and AUDR between S2MPS14 and
> S2MPS15). This leads to quite complicated code.
>
> Try to make it more obvious by:
> 1. Documenting the UDR masks for devices and operations.
> 2. Adding fields in register configuration structure for each operation
>(read time, write time and alarm).
> 3. Splitting the configuration per S2MPS13, S2MPS14 and S2MPS15 thus
>removing exceptions for them.
>
> Signed-off-by: Krzysztof Kozlowski 
>
> ---
>
> Tested only on S2MPS11 (Odroid XU4).
> ---
>  drivers/rtc/rtc-s5m.c   | 110 
> +++-
>  include/linux/mfd/samsung/rtc.h |   2 +
>  2 files changed, 77 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
> index 559db8f72117..7407d7394bb4 100644
> --- a/drivers/rtc/rtc-s5m.c
> +++ b/drivers/rtc/rtc-s5m.c
> @@ -38,7 +38,22 @@
>   */
>  #define UDR_READ_RETRY_CNT 5
>
> -/* Registers used by the driver which are different between chipsets. */
> +/*
> + * Registers used by the driver which are different between chipsets.
> + *
> + * Operations like read time and write alarm/time require updating
> + * specific fields in UDR register. These fields usually are auto-cleared
> + * (with some exceptions).
> + *
> + * Table of operations per device:
> + *
> + * Device | Write time | Read time | Write alarm
> + * =
> + * S5M8767| UDR + TIME |   | UDR
> + * S2MPS11/14 | WUDR   | RUDR  | WUDR + RUDR
> + * S2MPS13| WUDR   | RUDR  | WUDR + AUDR
> + * S2MPS15| WUDR   | RUDR  | AUDR
> + */
>  struct s5m_rtc_reg_config {
> /* Number of registers used for setting time/alarm0/alarm1 */
> unsigned int regs_count;
> @@ -58,8 +73,13 @@ struct s5m_rtc_reg_config {
> unsigned int udr_update;
> /* Auto-cleared mask in UDR field for writing time and alarm */
> unsigned int autoclear_udr_mask;
> -   /* Mask for UDR field in 'udr_update' register */
> -   unsigned int udr_mask;
> +   /*
> +* Masks in UDR field for time and alarm operations.
> +* The read time mask can be 0. Rest should not.
> +*/
> +   unsigned int read_time_udr_mask;
> +   unsigned int write_time_udr_mask;
> +   unsigned int write_alarm_udr_mask;
>  };
>
>  /* Register map for S5M8763 and S5M8767 */
> @@ -71,14 +91,44 @@ static const struct s5m_rtc_reg_config s5m_rtc_regs = {
> .alarm1 = S5M_ALARM1_SEC,
> .udr_update = S5M_RTC_UDR_CON,
> .autoclear_udr_mask = S5M_RTC_UDR_MASK,
> -   .udr_mask   = S5M_RTC_UDR_MASK,
> +   .read_time_udr_mask = 0, /* Not needed */
> +   .write_time_udr_mask= S5M_RTC_UDR_MASK | S5M_RTC_TIME_EN_MASK,
> +   .write_alarm_udr_mask   = S5M_RTC_UDR_MASK,
> +};
> +
> +/* Register map for S2MPS13 */
> +static const struct s5m_rtc_reg_config s2mps13_rtc_regs = {
> +   .regs_count = 7,
> +   .time   = S2MPS_RTC_SEC,
> +   .ctrl   = S2MPS_RTC_CTRL,
> +   .alarm0 = S2MPS_ALARM0_SEC,
> +   .alarm1 = S2MPS_ALARM1_SEC,
> +   .udr_update = S2MPS_RTC_UDR_CON,
> +   .autoclear_udr_mask = S2MPS_RTC_WUDR_MASK,
> +   .read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
> +   .write_time_udr_mask= S2MPS_RTC_WUDR_MASK,
> +   .write_alarm_udr_mask   = S2MPS_RTC_WUDR_MASK | S2MPS13_RTC_AUDR_MASK,
> +};
> +
> +/* Register map for S2MPS11/14 */
> +static const struct s5m_rtc_reg_config s2mps14_rtc_regs = {
> +   .regs_count = 7,
> +   .time   = S2MPS_RTC_SEC,
> +   .ctrl   = S2MPS_RTC_CTRL,
> +   .alarm0 = S2MPS_ALARM0_SEC,
> +   .alarm1 = S2MPS_ALARM1_SEC,
> +   .udr_update = S2MPS_RTC_UDR_CON,
> +   .autoclear_udr_mask = S2MPS_RTC_WUDR_MASK,
> +   .read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
> +   .write_time_udr_mask= S2MPS_RTC_WUDR_MASK,
> +   .write_alarm_udr_mask   = S2MPS_RTC_WUDR_MASK | S2MPS_RTC_RUDR_MASK,
>  };
>
>  /*
> - * Register map for S2MPS14.
> - * It may be also suitable for S2MPS11 but this was not tested.
> + * Register map for S2MPS15 - in comparison to S2MPS14 the WUDR and AUDR bits
> + * are swapped.
>   */
> -static const struct s5m_rtc_reg_config s2mps_rtc_regs = {
> +static const struct s5m_rtc_reg_config s2mps15_rtc_regs = {
> 

[PATCH v2] thermal: cpu_cooling: Update always cpufreq policy with thermal constraints

2014-11-07 Thread Yadwinder Singh Brar
Existing code updates cupfreq policy only while executing
cpufreq_apply_cooling() function (i.e. when notify_device != NOTIFY_INVALID).
It doesn't apply constraints when cpufreq policy update happens from any other
place but it should update the cpufreq policy with thermal constraints every
time when there is a cpufreq policy update, to keep state of
cpufreq_cooling_device and max_feq of cpufreq policy in sync. For instance
while resuming cpufreq updates cpufreq_policy and it restores default
policy->usr_policy values irrespective of cooling device's cpufreq_state since
notification gets missed because (notify_device == NOTIFY_INVALID).
Another problem, is that userspace is able to change max_freq irrespective of
cooling device's state, as notification gets missed.

This patch modifies code to maintain a global cpufreq_dev_list and applies
constraints of all matching cooling devices for policy's cpu when there is any
policy update(ends up applying the lowest max_freq among the matching cpu
cooling devices).

This patch also removes redundant check (max_freq > policy->user_policy.max),
as cpufreq framework takes care of user_policy constraints already where ever
required, otherwise its causing an issue while increasing max_freq in normal
scenerio as it restores max_freq with policy->user_policy.max which is old
(smaller) value.

Signed-off-by: Yadwinder Singh Brar 
---

changes since v1:
- Updated commit message as suggested by Eduardo Valentin
- fixed an issue in incresing value of scaling_max_freq from sysfs after
  decreasing it once in normal thermal conditions also.

---
 drivers/thermal/cpu_cooling.c |   37 +
 1 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 1ab0018..ad09e51 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -50,15 +50,14 @@ struct cpufreq_cooling_device {
unsigned int cpufreq_state;
unsigned int cpufreq_val;
struct cpumask allowed_cpus;
+   struct list_head node;
 };
 static DEFINE_IDR(cpufreq_idr);
 static DEFINE_MUTEX(cooling_cpufreq_lock);
 
 static unsigned int cpufreq_dev_count;
 
-/* notify_table passes value to the CPUFREQ_ADJUST callback function. */
-#define NOTIFY_INVALID NULL
-static struct cpufreq_cooling_device *notify_device;
+static LIST_HEAD(cpufreq_dev_list);
 
 /**
  * get_idr - function to get a unique id.
@@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct 
cpufreq_cooling_device *cpufreq_device,
 
cpufreq_device->cpufreq_state = cooling_state;
cpufreq_device->cpufreq_val = clip_freq;
-   notify_device = cpufreq_device;
 
for_each_cpu(cpuid, mask) {
if (is_cpufreq_valid(cpuid))
cpufreq_update_policy(cpuid);
}
 
-   notify_device = NOTIFY_INVALID;
-
return 0;
 }
 
@@ -316,21 +312,28 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
 {
struct cpufreq_policy *policy = data;
unsigned long max_freq = 0;
+   struct cpufreq_cooling_device *cpufreq_dev;
 
-   if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
+   if (event != CPUFREQ_ADJUST)
return 0;
 
-   if (cpumask_test_cpu(policy->cpu, _device->allowed_cpus))
-   max_freq = notify_device->cpufreq_val;
-   else
-   return 0;
+   mutex_lock(_cpufreq_lock);
+   list_for_each_entry(cpufreq_dev, _dev_list, node) {
+   if (!cpumask_test_cpu(policy->cpu,
+   _dev->allowed_cpus))
+   continue;
+
+   if (!cpufreq_dev->cpufreq_val)
+   cpufreq_dev->cpufreq_val = get_cpu_frequency(
+   cpumask_any(_dev->allowed_cpus),
+   cpufreq_dev->cpufreq_state);
 
-   /* Never exceed user_policy.max */
-   if (max_freq > policy->user_policy.max)
-   max_freq = policy->user_policy.max;
+   max_freq = cpufreq_dev->cpufreq_val;
 
-   if (policy->max != max_freq)
-   cpufreq_verify_within_limits(policy, 0, max_freq);
+   if (policy->max != max_freq)
+   cpufreq_verify_within_limits(policy, 0, max_freq);
+   }
+   mutex_unlock(_cpufreq_lock);
 
return 0;
 }
@@ -486,6 +489,7 @@ __cpufreq_cooling_register(struct device_node *np,
cpufreq_register_notifier(_cpufreq_notifier_block,
  CPUFREQ_POLICY_NOTIFIER);
cpufreq_dev_count++;
+   list_add(_dev->node, _dev_list);
 
mutex_unlock(_cpufreq_lock);
 
@@ -549,6 +553,7 @@ void cpufreq_cooling_unregister(struct 
thermal_cooling_device *cdev)
 
cpufreq_dev = cdev->devdata;
mutex_lock(_c

RE: [PATCH] thermal: cpu_cooling: Update always cpufreq policy with thermal constraints

2014-11-07 Thread Yadwinder Singh Brar
Hello Eduardo Valentin, 

On Thursday, November 06, 2014 1:19 PM, Eduardo Valentin wrote:
> Hello Yadwinder,
> 
> On Thu, Nov 06, 2014 at 04:26:27PM +0530, Yadwinder Singh Brar wrote:
> > Hello Eduardo Valentin,
> >
> > On Thursday, November 06, 2014 2:17 AM, Eduardo Valentin wrote:
> > > Hello Yadwinder,
> > >
> > > On Wed, Nov 05, 2014 at 05:46:25PM +0530, Yadwinder Singh Brar
> wrote:
> > > > Existing code updates cupfreq policy only while executing
> > > > cpufreq_apply_cooling() function (i.e. when notify_device !=
> > > NOTIFY_INVALID).
> > >
> > > Correct. The case you mention is when we receive a notification
> from
> > > cpufreq. But also, updates the cpufreq policy when the cooling
> > > device changes state, a call from thermal framework.
> >
> > I mentioned thermal framework case only, existing code updates
> cupfreq
> > policy only when (notify_device != NOTIFY_INVALID), which happens
> only
> > when notification comes from cpufreq_update_policy while changing
> > cooling device's state(i.e. cpufreq_apply_cooling()).
> > In case of other notifications notify_device is always
> NOTIFY_INVALID.
> 
> I see your point.
> 
> >
> > >
> > > > It doesn't apply constraints when cpufreq policy update happens
> > > > from any other place but it should update the cpufreq policy with
> > > > thermal constraints every time when there is a cpufreq policy
> > > > update, to keep state of cpufreq_cooling_device and max_feq of
> > > > cpufreq policy in
> > > sync.
> > >
> > > I am not sure I follow you here. Can you please elaborate on 'any
> > > other places'? Could you please mention (also in the commit log)
> > > what are the case the current code does not cover? For instance,
> the
> > > cpufreq_apply_cooling gets called on notification coming from
> > > thermal subsystem, and for changes in cpufreq subsystem,
> > > cpufreq_thermal_notifier is called.
> > >
> >
> > "Other places" mean possible places from where
> cpufreq_update_policy()
> > can be called at runtime, an instance in present kernel is
> cpufreq_resume().
> > But since cpufreq_update_policy() is an exposed API, I think for
> > robustness, generic cpu cooling should be able to take care of any
> > possible case(in future as well).
> >
> 
> OK. I understand now. Can you please improve your commit message by
> adding the descriptions you mentioned here?
>

Sure, will post updated patch.
 
> > > >
> > > > This patch modifies code to maintain a global cpufreq_dev_list
> and
> > > get
> > > > corresponding cpufreq_cooling_device for policy's cpu from
> > > > cpufreq_dev_list when there is any policy update.
> > >
> > > OK. Please give real examples of when the current code fails to
> > > catch the event.
> > >
> >
> > While resuming cpufreq updates cpufreq_policy for boot cpu and it
> > restores default policy->usr_policy irrespective of cooling device's
> > cpufreq_state since notification gets missed because (notify_device
> ==
> > NOTIFY_INVALID).
> > Another thing, Rather I would say an issue, I observed is that
> > Userspace is able to change max_freq irrespective of cooling device's
> > state, as notification gets missed.
> >
> 
> Include also the examples above you gave.
> 
> Have you verified if with this patch the issue with userland goes away?
> 

Yes, Userspace is not able to set scaling_max_freq more than the
cooling device constraint(cpufreq_val).

But I have a question here, Is it OK to silently set scaling_max_freq
less than the requested value from userspace ? 

> > >
> > > BR,
> > >
> > > Eduardo Valentin
> > >
> > > >
> > > > Signed-off-by: Yadwinder Singh Brar 
> > > > ---
> > > >  drivers/thermal/cpu_cooling.c |   37 ---
> 
> > > --
> > > >  1 files changed, 20 insertions(+), 17 deletions(-)
> > > >
> > > > diff --git a/drivers/thermal/cpu_cooling.c
> > > > b/drivers/thermal/cpu_cooling.c index 1ab0018..5546278 100644
> > > > --- a/drivers/thermal/cpu_cooling.c
> > > > +++ b/drivers/thermal/cpu_cooling.c
> > > > @@ -50,15 +50,14 @@ struct cpufreq_cooling_device {
> > > > unsigned int cpufreq_state;
> > > > unsigned int cpufreq_val;
> > > > struct cpumask allowed_cp

RE: [PATCH] thermal: cpu_cooling: Update always cpufreq policy with thermal constraints

2014-11-07 Thread Yadwinder Singh Brar
Hello Eduardo Valentin, 

On Thursday, November 06, 2014 1:19 PM, Eduardo Valentin wrote:
 Hello Yadwinder,
 
 On Thu, Nov 06, 2014 at 04:26:27PM +0530, Yadwinder Singh Brar wrote:
  Hello Eduardo Valentin,
 
  On Thursday, November 06, 2014 2:17 AM, Eduardo Valentin wrote:
   Hello Yadwinder,
  
   On Wed, Nov 05, 2014 at 05:46:25PM +0530, Yadwinder Singh Brar
 wrote:
Existing code updates cupfreq policy only while executing
cpufreq_apply_cooling() function (i.e. when notify_device !=
   NOTIFY_INVALID).
  
   Correct. The case you mention is when we receive a notification
 from
   cpufreq. But also, updates the cpufreq policy when the cooling
   device changes state, a call from thermal framework.
 
  I mentioned thermal framework case only, existing code updates
 cupfreq
  policy only when (notify_device != NOTIFY_INVALID), which happens
 only
  when notification comes from cpufreq_update_policy while changing
  cooling device's state(i.e. cpufreq_apply_cooling()).
  In case of other notifications notify_device is always
 NOTIFY_INVALID.
 
 I see your point.
 
 
  
It doesn't apply constraints when cpufreq policy update happens
from any other place but it should update the cpufreq policy with
thermal constraints every time when there is a cpufreq policy
update, to keep state of cpufreq_cooling_device and max_feq of
cpufreq policy in
   sync.
  
   I am not sure I follow you here. Can you please elaborate on 'any
   other places'? Could you please mention (also in the commit log)
   what are the case the current code does not cover? For instance,
 the
   cpufreq_apply_cooling gets called on notification coming from
   thermal subsystem, and for changes in cpufreq subsystem,
   cpufreq_thermal_notifier is called.
  
 
  Other places mean possible places from where
 cpufreq_update_policy()
  can be called at runtime, an instance in present kernel is
 cpufreq_resume().
  But since cpufreq_update_policy() is an exposed API, I think for
  robustness, generic cpu cooling should be able to take care of any
  possible case(in future as well).
 
 
 OK. I understand now. Can you please improve your commit message by
 adding the descriptions you mentioned here?


Sure, will post updated patch.
 
   
This patch modifies code to maintain a global cpufreq_dev_list
 and
   get
corresponding cpufreq_cooling_device for policy's cpu from
cpufreq_dev_list when there is any policy update.
  
   OK. Please give real examples of when the current code fails to
   catch the event.
  
 
  While resuming cpufreq updates cpufreq_policy for boot cpu and it
  restores default policy-usr_policy irrespective of cooling device's
  cpufreq_state since notification gets missed because (notify_device
 ==
  NOTIFY_INVALID).
  Another thing, Rather I would say an issue, I observed is that
  Userspace is able to change max_freq irrespective of cooling device's
  state, as notification gets missed.
 
 
 Include also the examples above you gave.
 
 Have you verified if with this patch the issue with userland goes away?
 

Yes, Userspace is not able to set scaling_max_freq more than the
cooling device constraint(cpufreq_val).

But I have a question here, Is it OK to silently set scaling_max_freq
less than the requested value from userspace ? 

  
   BR,
  
   Eduardo Valentin
  
   
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/thermal/cpu_cooling.c |   37 ---
 
   --
 1 files changed, 20 insertions(+), 17 deletions(-)
   
diff --git a/drivers/thermal/cpu_cooling.c
b/drivers/thermal/cpu_cooling.c index 1ab0018..5546278 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -50,15 +50,14 @@ struct cpufreq_cooling_device {
unsigned int cpufreq_state;
unsigned int cpufreq_val;
struct cpumask allowed_cpus;
+   struct list_head node;
 };
 static DEFINE_IDR(cpufreq_idr);
 static DEFINE_MUTEX(cooling_cpufreq_lock);
   
 static unsigned int cpufreq_dev_count;
   
-/* notify_table passes value to the CPUFREQ_ADJUST callback
   function.
*/ -#define NOTIFY_INVALID NULL -static struct
cpufreq_cooling_device *notify_device;
+static LIST_HEAD(cpufreq_dev_list);
   
 /**
  * get_idr - function to get a unique id.
@@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct
cpufreq_cooling_device *cpufreq_device,
   
cpufreq_device-cpufreq_state = cooling_state;
cpufreq_device-cpufreq_val = clip_freq;
-   notify_device = cpufreq_device;
   
for_each_cpu(cpuid, mask) {
if (is_cpufreq_valid(cpuid))
cpufreq_update_policy(cpuid);
}
   
-   notify_device = NOTIFY_INVALID;
-
return 0;
 }
   
@@ -316,21 +312,27 @@ static int cpufreq_thermal_notifier(struct
notifier_block *nb

[PATCH v2] thermal: cpu_cooling: Update always cpufreq policy with thermal constraints

2014-11-07 Thread Yadwinder Singh Brar
Existing code updates cupfreq policy only while executing
cpufreq_apply_cooling() function (i.e. when notify_device != NOTIFY_INVALID).
It doesn't apply constraints when cpufreq policy update happens from any other
place but it should update the cpufreq policy with thermal constraints every
time when there is a cpufreq policy update, to keep state of
cpufreq_cooling_device and max_feq of cpufreq policy in sync. For instance
while resuming cpufreq updates cpufreq_policy and it restores default
policy-usr_policy values irrespective of cooling device's cpufreq_state since
notification gets missed because (notify_device == NOTIFY_INVALID).
Another problem, is that userspace is able to change max_freq irrespective of
cooling device's state, as notification gets missed.

This patch modifies code to maintain a global cpufreq_dev_list and applies
constraints of all matching cooling devices for policy's cpu when there is any
policy update(ends up applying the lowest max_freq among the matching cpu
cooling devices).

This patch also removes redundant check (max_freq  policy-user_policy.max),
as cpufreq framework takes care of user_policy constraints already where ever
required, otherwise its causing an issue while increasing max_freq in normal
scenerio as it restores max_freq with policy-user_policy.max which is old
(smaller) value.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---

changes since v1:
- Updated commit message as suggested by Eduardo Valentin
- fixed an issue in incresing value of scaling_max_freq from sysfs after
  decreasing it once in normal thermal conditions also.

---
 drivers/thermal/cpu_cooling.c |   37 +
 1 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 1ab0018..ad09e51 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -50,15 +50,14 @@ struct cpufreq_cooling_device {
unsigned int cpufreq_state;
unsigned int cpufreq_val;
struct cpumask allowed_cpus;
+   struct list_head node;
 };
 static DEFINE_IDR(cpufreq_idr);
 static DEFINE_MUTEX(cooling_cpufreq_lock);
 
 static unsigned int cpufreq_dev_count;
 
-/* notify_table passes value to the CPUFREQ_ADJUST callback function. */
-#define NOTIFY_INVALID NULL
-static struct cpufreq_cooling_device *notify_device;
+static LIST_HEAD(cpufreq_dev_list);
 
 /**
  * get_idr - function to get a unique id.
@@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct 
cpufreq_cooling_device *cpufreq_device,
 
cpufreq_device-cpufreq_state = cooling_state;
cpufreq_device-cpufreq_val = clip_freq;
-   notify_device = cpufreq_device;
 
for_each_cpu(cpuid, mask) {
if (is_cpufreq_valid(cpuid))
cpufreq_update_policy(cpuid);
}
 
-   notify_device = NOTIFY_INVALID;
-
return 0;
 }
 
@@ -316,21 +312,28 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
 {
struct cpufreq_policy *policy = data;
unsigned long max_freq = 0;
+   struct cpufreq_cooling_device *cpufreq_dev;
 
-   if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
+   if (event != CPUFREQ_ADJUST)
return 0;
 
-   if (cpumask_test_cpu(policy-cpu, notify_device-allowed_cpus))
-   max_freq = notify_device-cpufreq_val;
-   else
-   return 0;
+   mutex_lock(cooling_cpufreq_lock);
+   list_for_each_entry(cpufreq_dev, cpufreq_dev_list, node) {
+   if (!cpumask_test_cpu(policy-cpu,
+   cpufreq_dev-allowed_cpus))
+   continue;
+
+   if (!cpufreq_dev-cpufreq_val)
+   cpufreq_dev-cpufreq_val = get_cpu_frequency(
+   cpumask_any(cpufreq_dev-allowed_cpus),
+   cpufreq_dev-cpufreq_state);
 
-   /* Never exceed user_policy.max */
-   if (max_freq  policy-user_policy.max)
-   max_freq = policy-user_policy.max;
+   max_freq = cpufreq_dev-cpufreq_val;
 
-   if (policy-max != max_freq)
-   cpufreq_verify_within_limits(policy, 0, max_freq);
+   if (policy-max != max_freq)
+   cpufreq_verify_within_limits(policy, 0, max_freq);
+   }
+   mutex_unlock(cooling_cpufreq_lock);
 
return 0;
 }
@@ -486,6 +489,7 @@ __cpufreq_cooling_register(struct device_node *np,
cpufreq_register_notifier(thermal_cpufreq_notifier_block,
  CPUFREQ_POLICY_NOTIFIER);
cpufreq_dev_count++;
+   list_add(cpufreq_dev-node, cpufreq_dev_list);
 
mutex_unlock(cooling_cpufreq_lock);
 
@@ -549,6 +553,7 @@ void cpufreq_cooling_unregister(struct 
thermal_cooling_device *cdev)
 
cpufreq_dev = cdev-devdata;
mutex_lock

RE: [PATCH] thermal: cpu_cooling: Update always cpufreq policy with thermal constraints

2014-11-06 Thread Yadwinder Singh Brar
Hello Eduardo Valentin,

On Thursday, November 06, 2014 2:17 AM, Eduardo Valentin wrote:
> Hello Yadwinder,
> 
> On Wed, Nov 05, 2014 at 05:46:25PM +0530, Yadwinder Singh Brar wrote:
> > Existing code updates cupfreq policy only while executing
> > cpufreq_apply_cooling() function (i.e. when notify_device !=
> NOTIFY_INVALID).
> 
> Correct. The case you mention is when we receive a notification from
> cpufreq. But also, updates the cpufreq policy when the cooling device
> changes state, a call from thermal framework.

I mentioned thermal framework case only, existing code updates
cupfreq policy only when (notify_device != NOTIFY_INVALID),
which happens only when notification comes from cpufreq_update_policy
while changing cooling device's state(i.e. cpufreq_apply_cooling()).
In case of other notifications notify_device is always NOTIFY_INVALID.

> 
> > It doesn't apply constraints when cpufreq policy update happens from
> > any other place but it should update the cpufreq policy with thermal
> > constraints every time when there is a cpufreq policy update, to keep
> > state of cpufreq_cooling_device and max_feq of cpufreq policy in
> sync.
> 
> I am not sure I follow you here. Can you please elaborate on 'any other
> places'? Could you please mention (also in the commit log) what are the
> case the current code does not cover? For instance, the
> cpufreq_apply_cooling gets called on notification coming from thermal
> subsystem, and for changes in cpufreq subsystem,
> cpufreq_thermal_notifier is called.
> 

"Other places" mean possible places from where cpufreq_update_policy()
can be called at runtime, an instance in present kernel is cpufreq_resume().
But since cpufreq_update_policy() is an exposed API, I think
for robustness, generic cpu cooling should be able to take care of any
possible case(in future as well).

> >
> > This patch modifies code to maintain a global cpufreq_dev_list and
> get
> > corresponding cpufreq_cooling_device for policy's cpu from
> > cpufreq_dev_list when there is any policy update.
> 
> OK. Please give real examples of when the current code fails to catch
> the event.
> 

While resuming cpufreq updates cpufreq_policy for boot cpu and it
restores default policy->usr_policy irrespective of cooling device's
cpufreq_state since notification gets missed because (notify_device ==
NOTIFY_INVALID).
Another thing, Rather I would say an issue, I observed is that
Userspace is able to change max_freq irrespective of cooling
device's state, as notification gets missed.
  
> 
> BR,
> 
> Eduardo Valentin
> 
> >
> > Signed-off-by: Yadwinder Singh Brar 
> > ---
> >  drivers/thermal/cpu_cooling.c |   37 ---
> --
> >  1 files changed, 20 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/thermal/cpu_cooling.c
> > b/drivers/thermal/cpu_cooling.c index 1ab0018..5546278 100644
> > --- a/drivers/thermal/cpu_cooling.c
> > +++ b/drivers/thermal/cpu_cooling.c
> > @@ -50,15 +50,14 @@ struct cpufreq_cooling_device {
> > unsigned int cpufreq_state;
> > unsigned int cpufreq_val;
> > struct cpumask allowed_cpus;
> > +   struct list_head node;
> >  };
> >  static DEFINE_IDR(cpufreq_idr);
> >  static DEFINE_MUTEX(cooling_cpufreq_lock);
> >
> >  static unsigned int cpufreq_dev_count;
> >
> > -/* notify_table passes value to the CPUFREQ_ADJUST callback
> function.
> > */ -#define NOTIFY_INVALID NULL -static struct cpufreq_cooling_device
> > *notify_device;
> > +static LIST_HEAD(cpufreq_dev_list);
> >
> >  /**
> >   * get_idr - function to get a unique id.
> > @@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct
> > cpufreq_cooling_device *cpufreq_device,
> >
> > cpufreq_device->cpufreq_state = cooling_state;
> > cpufreq_device->cpufreq_val = clip_freq;
> > -   notify_device = cpufreq_device;
> >
> > for_each_cpu(cpuid, mask) {
> > if (is_cpufreq_valid(cpuid))
> > cpufreq_update_policy(cpuid);
> > }
> >
> > -   notify_device = NOTIFY_INVALID;
> > -
> > return 0;
> >  }
> >
> > @@ -316,21 +312,27 @@ static int cpufreq_thermal_notifier(struct
> > notifier_block *nb,  {
> > struct cpufreq_policy *policy = data;
> > unsigned long max_freq = 0;
> > +   struct cpufreq_cooling_device *cpufreq_dev;
> >
> > -   if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
> > +   if (event != CPUFREQ_ADJUST)
> > return 0;
> >
> > -   if (cpumask_test_cpu(policy->cpu, _device->allowed_cp

RE: [PATCH] thermal: cpu_cooling: Update always cpufreq policy with thermal constraints

2014-11-06 Thread Yadwinder Singh Brar
Hello Eduardo Valentin,

On Thursday, November 06, 2014 2:17 AM, Eduardo Valentin wrote:
 Hello Yadwinder,
 
 On Wed, Nov 05, 2014 at 05:46:25PM +0530, Yadwinder Singh Brar wrote:
  Existing code updates cupfreq policy only while executing
  cpufreq_apply_cooling() function (i.e. when notify_device !=
 NOTIFY_INVALID).
 
 Correct. The case you mention is when we receive a notification from
 cpufreq. But also, updates the cpufreq policy when the cooling device
 changes state, a call from thermal framework.

I mentioned thermal framework case only, existing code updates
cupfreq policy only when (notify_device != NOTIFY_INVALID),
which happens only when notification comes from cpufreq_update_policy
while changing cooling device's state(i.e. cpufreq_apply_cooling()).
In case of other notifications notify_device is always NOTIFY_INVALID.

 
  It doesn't apply constraints when cpufreq policy update happens from
  any other place but it should update the cpufreq policy with thermal
  constraints every time when there is a cpufreq policy update, to keep
  state of cpufreq_cooling_device and max_feq of cpufreq policy in
 sync.
 
 I am not sure I follow you here. Can you please elaborate on 'any other
 places'? Could you please mention (also in the commit log) what are the
 case the current code does not cover? For instance, the
 cpufreq_apply_cooling gets called on notification coming from thermal
 subsystem, and for changes in cpufreq subsystem,
 cpufreq_thermal_notifier is called.
 

Other places mean possible places from where cpufreq_update_policy()
can be called at runtime, an instance in present kernel is cpufreq_resume().
But since cpufreq_update_policy() is an exposed API, I think
for robustness, generic cpu cooling should be able to take care of any
possible case(in future as well).

 
  This patch modifies code to maintain a global cpufreq_dev_list and
 get
  corresponding cpufreq_cooling_device for policy's cpu from
  cpufreq_dev_list when there is any policy update.
 
 OK. Please give real examples of when the current code fails to catch
 the event.
 

While resuming cpufreq updates cpufreq_policy for boot cpu and it
restores default policy-usr_policy irrespective of cooling device's
cpufreq_state since notification gets missed because (notify_device ==
NOTIFY_INVALID).
Another thing, Rather I would say an issue, I observed is that
Userspace is able to change max_freq irrespective of cooling
device's state, as notification gets missed.
  
 
 BR,
 
 Eduardo Valentin
 
 
  Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
  ---
   drivers/thermal/cpu_cooling.c |   37 ---
 --
   1 files changed, 20 insertions(+), 17 deletions(-)
 
  diff --git a/drivers/thermal/cpu_cooling.c
  b/drivers/thermal/cpu_cooling.c index 1ab0018..5546278 100644
  --- a/drivers/thermal/cpu_cooling.c
  +++ b/drivers/thermal/cpu_cooling.c
  @@ -50,15 +50,14 @@ struct cpufreq_cooling_device {
  unsigned int cpufreq_state;
  unsigned int cpufreq_val;
  struct cpumask allowed_cpus;
  +   struct list_head node;
   };
   static DEFINE_IDR(cpufreq_idr);
   static DEFINE_MUTEX(cooling_cpufreq_lock);
 
   static unsigned int cpufreq_dev_count;
 
  -/* notify_table passes value to the CPUFREQ_ADJUST callback
 function.
  */ -#define NOTIFY_INVALID NULL -static struct cpufreq_cooling_device
  *notify_device;
  +static LIST_HEAD(cpufreq_dev_list);
 
   /**
* get_idr - function to get a unique id.
  @@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct
  cpufreq_cooling_device *cpufreq_device,
 
  cpufreq_device-cpufreq_state = cooling_state;
  cpufreq_device-cpufreq_val = clip_freq;
  -   notify_device = cpufreq_device;
 
  for_each_cpu(cpuid, mask) {
  if (is_cpufreq_valid(cpuid))
  cpufreq_update_policy(cpuid);
  }
 
  -   notify_device = NOTIFY_INVALID;
  -
  return 0;
   }
 
  @@ -316,21 +312,27 @@ static int cpufreq_thermal_notifier(struct
  notifier_block *nb,  {
  struct cpufreq_policy *policy = data;
  unsigned long max_freq = 0;
  +   struct cpufreq_cooling_device *cpufreq_dev;
 
  -   if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
  +   if (event != CPUFREQ_ADJUST)
  return 0;
 
  -   if (cpumask_test_cpu(policy-cpu, notify_device-allowed_cpus))
  -   max_freq = notify_device-cpufreq_val;
  -   else
  -   return 0;
  +   mutex_lock(cooling_cpufreq_lock);
  +   list_for_each_entry(cpufreq_dev, cpufreq_dev_list, node) {
  +   if (!cpumask_test_cpu(policy-cpu,
  +   cpufreq_dev-allowed_cpus))
  +   continue;
 
  -   /* Never exceed user_policy.max */
  -   if (max_freq  policy-user_policy.max)
  -   max_freq = policy-user_policy.max;
  +   max_freq = cpufreq_dev-cpufreq_val;
 

I think I missed to post updated patch,
Actually it should be :

+   if (!cpufreq_dev-cpufreq_val

[PATCH] thermal: cpu_cooling: Update always cpufreq policy with thermal constraints

2014-11-05 Thread Yadwinder Singh Brar
Existing code updates cupfreq policy only while executing
cpufreq_apply_cooling() function (i.e. when notify_device != NOTIFY_INVALID).
It doesn't apply constraints when cpufreq policy update happens from any other
place but it should update the cpufreq policy with thermal constraints every
time when there is a cpufreq policy update, to keep state of
cpufreq_cooling_device and max_feq of cpufreq policy in sync.

This patch modifies code to maintain a global cpufreq_dev_list and get
corresponding cpufreq_cooling_device for policy's cpu from cpufreq_dev_list
when there is any policy update.

Signed-off-by: Yadwinder Singh Brar 
---
 drivers/thermal/cpu_cooling.c |   37 -
 1 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 1ab0018..5546278 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -50,15 +50,14 @@ struct cpufreq_cooling_device {
unsigned int cpufreq_state;
unsigned int cpufreq_val;
struct cpumask allowed_cpus;
+   struct list_head node;
 };
 static DEFINE_IDR(cpufreq_idr);
 static DEFINE_MUTEX(cooling_cpufreq_lock);
 
 static unsigned int cpufreq_dev_count;
 
-/* notify_table passes value to the CPUFREQ_ADJUST callback function. */
-#define NOTIFY_INVALID NULL
-static struct cpufreq_cooling_device *notify_device;
+static LIST_HEAD(cpufreq_dev_list);
 
 /**
  * get_idr - function to get a unique id.
@@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct 
cpufreq_cooling_device *cpufreq_device,
 
cpufreq_device->cpufreq_state = cooling_state;
cpufreq_device->cpufreq_val = clip_freq;
-   notify_device = cpufreq_device;
 
for_each_cpu(cpuid, mask) {
if (is_cpufreq_valid(cpuid))
cpufreq_update_policy(cpuid);
}
 
-   notify_device = NOTIFY_INVALID;
-
return 0;
 }
 
@@ -316,21 +312,27 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
 {
struct cpufreq_policy *policy = data;
unsigned long max_freq = 0;
+   struct cpufreq_cooling_device *cpufreq_dev;
 
-   if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
+   if (event != CPUFREQ_ADJUST)
return 0;
 
-   if (cpumask_test_cpu(policy->cpu, _device->allowed_cpus))
-   max_freq = notify_device->cpufreq_val;
-   else
-   return 0;
+   mutex_lock(_cpufreq_lock);
+   list_for_each_entry(cpufreq_dev, _dev_list, node) {
+   if (!cpumask_test_cpu(policy->cpu,
+   _dev->allowed_cpus))
+   continue;
 
-   /* Never exceed user_policy.max */
-   if (max_freq > policy->user_policy.max)
-   max_freq = policy->user_policy.max;
+   max_freq = cpufreq_dev->cpufreq_val;
 
-   if (policy->max != max_freq)
-   cpufreq_verify_within_limits(policy, 0, max_freq);
+   /* Never exceed user_policy.max */
+   if (max_freq > policy->user_policy.max)
+   max_freq = policy->user_policy.max;
+
+   if (policy->max != max_freq)
+   cpufreq_verify_within_limits(policy, 0, max_freq);
+   }
+   mutex_unlock(_cpufreq_lock);
 
return 0;
 }
@@ -486,7 +488,7 @@ __cpufreq_cooling_register(struct device_node *np,
cpufreq_register_notifier(_cpufreq_notifier_block,
  CPUFREQ_POLICY_NOTIFIER);
cpufreq_dev_count++;
-
+   list_add(_dev->node, _dev_list);
mutex_unlock(_cpufreq_lock);
 
return cool_dev;
@@ -549,6 +551,7 @@ void cpufreq_cooling_unregister(struct 
thermal_cooling_device *cdev)
 
cpufreq_dev = cdev->devdata;
mutex_lock(_cpufreq_lock);
+   list_del(_dev->node);
cpufreq_dev_count--;
 
/* Unregister the notifier for the last cpufreq cooling device */
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] thermal: cpu_cooling: Update always cpufreq policy with thermal constraints

2014-11-05 Thread Yadwinder Singh Brar
Existing code updates cupfreq policy only while executing
cpufreq_apply_cooling() function (i.e. when notify_device != NOTIFY_INVALID).
It doesn't apply constraints when cpufreq policy update happens from any other
place but it should update the cpufreq policy with thermal constraints every
time when there is a cpufreq policy update, to keep state of
cpufreq_cooling_device and max_feq of cpufreq policy in sync.

This patch modifies code to maintain a global cpufreq_dev_list and get
corresponding cpufreq_cooling_device for policy's cpu from cpufreq_dev_list
when there is any policy update.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/thermal/cpu_cooling.c |   37 -
 1 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 1ab0018..5546278 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -50,15 +50,14 @@ struct cpufreq_cooling_device {
unsigned int cpufreq_state;
unsigned int cpufreq_val;
struct cpumask allowed_cpus;
+   struct list_head node;
 };
 static DEFINE_IDR(cpufreq_idr);
 static DEFINE_MUTEX(cooling_cpufreq_lock);
 
 static unsigned int cpufreq_dev_count;
 
-/* notify_table passes value to the CPUFREQ_ADJUST callback function. */
-#define NOTIFY_INVALID NULL
-static struct cpufreq_cooling_device *notify_device;
+static LIST_HEAD(cpufreq_dev_list);
 
 /**
  * get_idr - function to get a unique id.
@@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct 
cpufreq_cooling_device *cpufreq_device,
 
cpufreq_device-cpufreq_state = cooling_state;
cpufreq_device-cpufreq_val = clip_freq;
-   notify_device = cpufreq_device;
 
for_each_cpu(cpuid, mask) {
if (is_cpufreq_valid(cpuid))
cpufreq_update_policy(cpuid);
}
 
-   notify_device = NOTIFY_INVALID;
-
return 0;
 }
 
@@ -316,21 +312,27 @@ static int cpufreq_thermal_notifier(struct notifier_block 
*nb,
 {
struct cpufreq_policy *policy = data;
unsigned long max_freq = 0;
+   struct cpufreq_cooling_device *cpufreq_dev;
 
-   if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
+   if (event != CPUFREQ_ADJUST)
return 0;
 
-   if (cpumask_test_cpu(policy-cpu, notify_device-allowed_cpus))
-   max_freq = notify_device-cpufreq_val;
-   else
-   return 0;
+   mutex_lock(cooling_cpufreq_lock);
+   list_for_each_entry(cpufreq_dev, cpufreq_dev_list, node) {
+   if (!cpumask_test_cpu(policy-cpu,
+   cpufreq_dev-allowed_cpus))
+   continue;
 
-   /* Never exceed user_policy.max */
-   if (max_freq  policy-user_policy.max)
-   max_freq = policy-user_policy.max;
+   max_freq = cpufreq_dev-cpufreq_val;
 
-   if (policy-max != max_freq)
-   cpufreq_verify_within_limits(policy, 0, max_freq);
+   /* Never exceed user_policy.max */
+   if (max_freq  policy-user_policy.max)
+   max_freq = policy-user_policy.max;
+
+   if (policy-max != max_freq)
+   cpufreq_verify_within_limits(policy, 0, max_freq);
+   }
+   mutex_unlock(cooling_cpufreq_lock);
 
return 0;
 }
@@ -486,7 +488,7 @@ __cpufreq_cooling_register(struct device_node *np,
cpufreq_register_notifier(thermal_cpufreq_notifier_block,
  CPUFREQ_POLICY_NOTIFIER);
cpufreq_dev_count++;
-
+   list_add(cpufreq_dev-node, cpufreq_dev_list);
mutex_unlock(cooling_cpufreq_lock);
 
return cool_dev;
@@ -549,6 +551,7 @@ void cpufreq_cooling_unregister(struct 
thermal_cooling_device *cdev)
 
cpufreq_dev = cdev-devdata;
mutex_lock(cooling_cpufreq_lock);
+   list_del(cpufreq_dev-node);
cpufreq_dev_count--;
 
/* Unregister the notifier for the last cpufreq cooling device */
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 05/14] clk: Add generic driver for Maxim PMIC clocks

2014-06-29 Thread Yadwinder Singh Brar
Hi Javier,

On Thu, Jun 26, 2014 at 11:45 PM, Javier Martinez Canillas
 wrote:
> Maxim Integrated Power Management ICs are very similar with
> regard to their clock outputs. Most of the clock drivers for
> these chips are duplicating code and are simpler enough that
> can be converted to use a generic driver to consolidate code
> and avoid duplication.
>
> Signed-off-by: Javier Martinez Canillas 
> Reviewed-by: Krzysztof Kozlowski 
> ---
>
> Changes since v4:
>  - Return recalc 0 if clock isn't enabled in Suggested by Yadwinder Singh 
> Brar.
>

It seems you didn't implement or posted same patch again :) .

> Changes since v3:
>  - Add current copyright information. Suggested by Krzysztof Kozlowski
>  - Do a single allocation for struct max_gen_clk. Suggested by Krzysztof 
> Kozlowski
>  - Add EXPORT_SYMBOL() for exported symbols. Suggested by Krzysztof Kozlowski
>
>  drivers/clk/Kconfig   |   3 +
>  drivers/clk/Makefile  |   1 +
>  drivers/clk/clk-max-gen.c | 195 
> ++
>  drivers/clk/clk-max-gen.h |  32 
>  4 files changed, 231 insertions(+)
>  create mode 100644 drivers/clk/clk-max-gen.c
>  create mode 100644 drivers/clk/clk-max-gen.h
>

[ .. ]

> +
> +static unsigned long max_gen_recalc_rate(struct clk_hw *hw,
> +unsigned long parent_rate)
> +{
> +   return 32768;
> +}

Its still same here.

> +
> +struct clk_ops max_gen_clk_ops = {
> +   .prepare= max_gen_clk_prepare,
> +   .unprepare  = max_gen_clk_unprepare,
> +   .is_prepared= max_gen_clk_is_prepared,
> +   .recalc_rate= max_gen_recalc_rate,
> +};
> +EXPORT_SYMBOL_GPL(max_gen_clk_ops);
> +
> +static struct clk *max_gen_clk_register(struct device *dev,
> +   struct max_gen_clk *max_gen)
> +{
> +   struct clk *clk;
> +   struct clk_hw *hw = _gen->hw;
> +
> +   clk = clk_register(dev, hw);
> +   if (IS_ERR(clk))
> +   return clk;
> +
> +   max_gen->lookup = kzalloc(sizeof(struct clk_lookup), GFP_KERNEL);

As I suggested in other patch[1] also, its better to use
clkdev_alloc() instead of kzalloc() here.

> +   if (!max_gen->lookup)
> +   return ERR_PTR(-ENOMEM);
> +
> +   max_gen->lookup->con_id = hw->init->name;

Also IMO,  init->name should be over-written if name is provided in DT,
otherwise generic "clock-output-names" property will go futile,
perhaps it should be done before clk_register.

Regards,
Yadwinder

[1] : https://lkml.org/lkml/2014/6/27/197

> +   max_gen->lookup->clk = clk;
> +
> +   clkdev_add(max_gen->lookup);
> +
> +   return clk;
> +}
> +
> +int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap,
> + u32 reg, struct clk_init_data *clks_init, int num_init)
> +{
> +   int i, ret;
> +   struct max_gen_clk *max_gen_clks;
> +   struct clk **clocks;
> +   struct device *dev = >dev;
> +
> +   clocks = devm_kzalloc(dev, sizeof(struct clk *) * num_init, 
> GFP_KERNEL);
> +   if (!clocks)
> +   return -ENOMEM;
> +
> +   max_gen_clks = devm_kzalloc(dev, sizeof(struct max_gen_clk)
> +   * num_init, GFP_KERNEL);
> +   if (!max_gen_clks)
> +   return -ENOMEM;
> +
> +   for (i = 0; i < num_init; i++) {
> +   max_gen_clks[i].regmap = regmap;
> +   max_gen_clks[i].mask = 1 << i;
> +   max_gen_clks[i].reg = reg;
> +   max_gen_clks[i].hw.init = _init[i];
> +
> +   clocks[i] = max_gen_clk_register(dev, _gen_clks[i]);
> +   if (IS_ERR(clocks[i])) {
> +   ret = PTR_ERR(clocks[i]);
> +   dev_err(dev, "failed to register %s\n",
> +   max_gen_clks[i].hw.init->name);
> +   goto err_clocks;
> +   }
> +   }
> +
> +   platform_set_drvdata(pdev, clocks);
> +
> +   if (dev->of_node) {
> +   struct clk_onecell_data *of_data;
> +
> +   of_data = devm_kzalloc(dev, sizeof(*of_data), GFP_KERNEL);
> +   if (!of_data) {
> +   ret = -ENOMEM;
> +   goto err_clocks;
> +   }
> +
> +   of_data->clks = clocks;
> +   of_data->clk_num = num_init;
> +   ret = of_clk_add_provider(dev->of_node, 
> of_clk_src_onecell_get,
> + of_data);
> +
> + 

Re: [PATCH v2] clk: s2mps11: Fix double free corruption during driver unbind

2014-06-29 Thread Yadwinder Singh Brar
f0)
> [   31.228027] [] (cpu_startup_entry) from [<400086c4>] (0x400086c4)
> [   31.234968] ---[ end Kernel panic - not syncing: Fatal exception
>
> Fixes: 7cc560dea415 ("clk: s2mps11: Add support for s2mps11")
> Cc: 
> Signed-off-by: Krzysztof Kozlowski 
>
> ---
>
> Changes since v1:
> 1. Allocate memory for clk_lookup with clkdev_alloc() instead of
>kzalloc(). Suggested by Yadwinder Singh Brar.
> ---

Reviewed-by: Yadwinder Singh Brar 

Regards,
Yadwinder

>  drivers/clk/clk-s2mps11.c | 7 ++-
>  1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
> index 9b7b5859a420..3757e9e72d37 100644
> --- a/drivers/clk/clk-s2mps11.c
> +++ b/drivers/clk/clk-s2mps11.c
> @@ -230,16 +230,13 @@ static int s2mps11_clk_probe(struct platform_device 
> *pdev)
> goto err_reg;
> }
>
> -   s2mps11_clk->lookup = devm_kzalloc(>dev,
> -   sizeof(struct clk_lookup), 
> GFP_KERNEL);
> +   s2mps11_clk->lookup = clkdev_alloc(s2mps11_clk->clk,
> +   s2mps11_name(s2mps11_clk), NULL);
> if (!s2mps11_clk->lookup) {
> ret = -ENOMEM;
> goto err_lup;
> }
>
> -   s2mps11_clk->lookup->con_id = s2mps11_name(s2mps11_clk);
> -   s2mps11_clk->lookup->clk = s2mps11_clk->clk;
> -
> clkdev_add(s2mps11_clk->lookup);
> }
>
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] clk: s2mps11: Fix double free corruption during driver unbind

2014-06-29 Thread Yadwinder Singh Brar
 panic - not syncing: Fatal exception

 Fixes: 7cc560dea415 (clk: s2mps11: Add support for s2mps11)
 Cc: sta...@vger.kernel.org
 Signed-off-by: Krzysztof Kozlowski k.kozlow...@samsung.com

 ---

 Changes since v1:
 1. Allocate memory for clk_lookup with clkdev_alloc() instead of
kzalloc(). Suggested by Yadwinder Singh Brar.
 ---

Reviewed-by: Yadwinder Singh Brar yadi.b...@samsung.com

Regards,
Yadwinder

  drivers/clk/clk-s2mps11.c | 7 ++-
  1 file changed, 2 insertions(+), 5 deletions(-)

 diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
 index 9b7b5859a420..3757e9e72d37 100644
 --- a/drivers/clk/clk-s2mps11.c
 +++ b/drivers/clk/clk-s2mps11.c
 @@ -230,16 +230,13 @@ static int s2mps11_clk_probe(struct platform_device 
 *pdev)
 goto err_reg;
 }

 -   s2mps11_clk-lookup = devm_kzalloc(pdev-dev,
 -   sizeof(struct clk_lookup), 
 GFP_KERNEL);
 +   s2mps11_clk-lookup = clkdev_alloc(s2mps11_clk-clk,
 +   s2mps11_name(s2mps11_clk), NULL);
 if (!s2mps11_clk-lookup) {
 ret = -ENOMEM;
 goto err_lup;
 }

 -   s2mps11_clk-lookup-con_id = s2mps11_name(s2mps11_clk);
 -   s2mps11_clk-lookup-clk = s2mps11_clk-clk;
 -
 clkdev_add(s2mps11_clk-lookup);
 }

 --
 1.9.1

 --
 To unsubscribe from this list: send the line unsubscribe linux-kernel in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
 Please read the FAQ at  http://www.tux.org/lkml/


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 05/14] clk: Add generic driver for Maxim PMIC clocks

2014-06-29 Thread Yadwinder Singh Brar
Hi Javier,

On Thu, Jun 26, 2014 at 11:45 PM, Javier Martinez Canillas
javier.marti...@collabora.co.uk wrote:
 Maxim Integrated Power Management ICs are very similar with
 regard to their clock outputs. Most of the clock drivers for
 these chips are duplicating code and are simpler enough that
 can be converted to use a generic driver to consolidate code
 and avoid duplication.

 Signed-off-by: Javier Martinez Canillas javier.marti...@collabora.co.uk
 Reviewed-by: Krzysztof Kozlowski k.kozlow...@samsung.com
 ---

 Changes since v4:
  - Return recalc 0 if clock isn't enabled in Suggested by Yadwinder Singh 
 Brar.


It seems you didn't implement or posted same patch again :) .

 Changes since v3:
  - Add current copyright information. Suggested by Krzysztof Kozlowski
  - Do a single allocation for struct max_gen_clk. Suggested by Krzysztof 
 Kozlowski
  - Add EXPORT_SYMBOL() for exported symbols. Suggested by Krzysztof Kozlowski

  drivers/clk/Kconfig   |   3 +
  drivers/clk/Makefile  |   1 +
  drivers/clk/clk-max-gen.c | 195 
 ++
  drivers/clk/clk-max-gen.h |  32 
  4 files changed, 231 insertions(+)
  create mode 100644 drivers/clk/clk-max-gen.c
  create mode 100644 drivers/clk/clk-max-gen.h


[ .. ]

 +
 +static unsigned long max_gen_recalc_rate(struct clk_hw *hw,
 +unsigned long parent_rate)
 +{
 +   return 32768;
 +}

Its still same here.

 +
 +struct clk_ops max_gen_clk_ops = {
 +   .prepare= max_gen_clk_prepare,
 +   .unprepare  = max_gen_clk_unprepare,
 +   .is_prepared= max_gen_clk_is_prepared,
 +   .recalc_rate= max_gen_recalc_rate,
 +};
 +EXPORT_SYMBOL_GPL(max_gen_clk_ops);
 +
 +static struct clk *max_gen_clk_register(struct device *dev,
 +   struct max_gen_clk *max_gen)
 +{
 +   struct clk *clk;
 +   struct clk_hw *hw = max_gen-hw;
 +
 +   clk = clk_register(dev, hw);
 +   if (IS_ERR(clk))
 +   return clk;
 +
 +   max_gen-lookup = kzalloc(sizeof(struct clk_lookup), GFP_KERNEL);

As I suggested in other patch[1] also, its better to use
clkdev_alloc() instead of kzalloc() here.

 +   if (!max_gen-lookup)
 +   return ERR_PTR(-ENOMEM);
 +
 +   max_gen-lookup-con_id = hw-init-name;

Also IMO,  init-name should be over-written if name is provided in DT,
otherwise generic clock-output-names property will go futile,
perhaps it should be done before clk_register.

Regards,
Yadwinder

[1] : https://lkml.org/lkml/2014/6/27/197

 +   max_gen-lookup-clk = clk;
 +
 +   clkdev_add(max_gen-lookup);
 +
 +   return clk;
 +}
 +
 +int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap,
 + u32 reg, struct clk_init_data *clks_init, int num_init)
 +{
 +   int i, ret;
 +   struct max_gen_clk *max_gen_clks;
 +   struct clk **clocks;
 +   struct device *dev = pdev-dev;
 +
 +   clocks = devm_kzalloc(dev, sizeof(struct clk *) * num_init, 
 GFP_KERNEL);
 +   if (!clocks)
 +   return -ENOMEM;
 +
 +   max_gen_clks = devm_kzalloc(dev, sizeof(struct max_gen_clk)
 +   * num_init, GFP_KERNEL);
 +   if (!max_gen_clks)
 +   return -ENOMEM;
 +
 +   for (i = 0; i  num_init; i++) {
 +   max_gen_clks[i].regmap = regmap;
 +   max_gen_clks[i].mask = 1  i;
 +   max_gen_clks[i].reg = reg;
 +   max_gen_clks[i].hw.init = clks_init[i];
 +
 +   clocks[i] = max_gen_clk_register(dev, max_gen_clks[i]);
 +   if (IS_ERR(clocks[i])) {
 +   ret = PTR_ERR(clocks[i]);
 +   dev_err(dev, failed to register %s\n,
 +   max_gen_clks[i].hw.init-name);
 +   goto err_clocks;
 +   }
 +   }
 +
 +   platform_set_drvdata(pdev, clocks);
 +
 +   if (dev-of_node) {
 +   struct clk_onecell_data *of_data;
 +
 +   of_data = devm_kzalloc(dev, sizeof(*of_data), GFP_KERNEL);
 +   if (!of_data) {
 +   ret = -ENOMEM;
 +   goto err_clocks;
 +   }
 +
 +   of_data-clks = clocks;
 +   of_data-clk_num = num_init;
 +   ret = of_clk_add_provider(dev-of_node, 
 of_clk_src_onecell_get,
 + of_data);
 +
 +   if (ret) {
 +   dev_err(dev, failed to register OF clock 
 provider\n);
 +   goto err_clocks;
 +   }
 +   }
 +
 +   return 0;
 +
 +err_clocks:
 +   for (--i; i = 0; --i) {
 +   clkdev_drop(max_gen_clks[i].lookup);
 +   clk_unregister(max_gen_clks[i].hw.clk);
 +   }
 +
 +   return ret;
 +}
 +EXPORT_SYMBOL_GPL(max_gen_clk_probe);
 +
 +int max_gen_clk_remove(struct

Re: [PATCH] clk: s2mps11: Fix double free corruption during driver unbind

2014-06-27 Thread Yadwinder Singh Brar
Hi Krzystof,

On Fri, Jun 27, 2014 at 4:04 PM, Krzysztof Kozlowski
 wrote:
> After unbinding the driver memory was corrupted by double free of
> clk_lookup structure. This lead to OOPS when re-binding the driver
> again.
>
> The driver allocated memory for 'clk_lookup' with devm_kzalloc. During
> driver removal this memory was freed twice: once by clkdev_drop() and
> second by devm code.
>

Ideally memory should be allocated and deallocated in same place
either driver or framework, so in this case if framework(clkdev_drop)
deallocates memory, framework itself should also allocate it.
So IMO this bug should be fixed using clkdev_alloc() instead of kzalloc().

Regards,
Yadwinder

> Kernel panic log:
> [   30.839284] Unable to handle kernel paging request at virtual address 
> 5f343173
> [   30.846476] pgd = dee14000
> [   30.849165] [5f343173] *pgd=
> [   30.852703] Internal error: Oops: 805 [#1] PREEMPT SMP ARM
> [   30.858166] Modules linked in:
> [   30.861208] CPU: 0 PID: 1 Comm: bash Not tainted 
> 3.16.0-rc2-00239-g94bdf617b07e-dirty #40
> [   30.869364] task: df478000 ti: df48 task.ti: df48
> [   30.874752] PC is at clkdev_add+0x2c/0x38
> [   30.878738] LR is at clkdev_add+0x18/0x38
> [   30.882732] pc : []lr : []psr: 6013
> [   30.882732] sp : df481e78  ip : 0001  fp : c0700ed8
> [   30.894187] r10: 000c  r9 :   r8 : c07b0e3c
> [   30.899396] r7 : 0002  r6 : df45f9d0  r5 : df421390  r4 : c0700d6c
> [   30.905906] r3 : 5f343173  r2 : c0700d84  r1 : 6013  r0 : c0700d6c
> [   30.912417] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment 
> user
> [   30.919534] Control: 10c53c7d  Table: 5ee1406a  DAC: 0015
> [   30.925262] Process bash (pid: 1, stack limit = 0xdf480240)
> [   30.930817] Stack: (0xdf481e78 to 0xdf482000)
> [   30.935159] 1e60:   
> 1000 df6de610
> [   30.943321] 1e80: df7f4558 c0355650 c05ec6ec c0700eb0 df6de600 df7f4510 
> dec9d69c 0014
> [   30.951480] 1ea0: 00167b48 df6de610 c0700e30 c0713518  c0700e30 
> dec9d69c 0006
> [   30.959639] 1ec0: 00167b48 c02c1b7c c02c1b64 df6de610 c07aff48 c02c0420 
> c06fb150 c047cc20
> [   30.967798] 1ee0: df6de610 df6de610 c0700e30 df6de644 c06fb150 000c 
> dec9d690 c02bef90
> [   30.975957] 1f00: dec9c6c0 dece4c00 df481f80 dece4c00 000c c02be73c 
> 000c c016ca8c
> [   30.984116] 1f20: c016ca48   c016c1f4   
> b6f18000 df481f80
> [   30.992276] 1f40: df7f66c0 000c df48 df48 b6f18000 c011094c 
> df47839c 6013
> [   31.000435] 1f60:   df7f66c0 df7f66c0 000c df48 
> b6f18000 c0110dd4
> [   31.008594] 1f80:   000c b6ec05d8 000c b6f18000 
> 0004 c000f2a8
> [   31.016753] 1fa0: 1000 c000f0e0 b6ec05d8 000c 0001 b6f18000 
> 000c 
> [   31.024912] 1fc0: b6ec05d8 000c b6f18000 0004 000c 0001 
>  00167b48
> [   31.033071] 1fe0:  bed83a80 b6e004f0 b6e5122c 6010 0001 
>  
> [   31.041248] [] (clkdev_add) from [] 
> (s2mps11_clk_probe+0x2b4/0x3b4)
> [   31.049223] [] (s2mps11_clk_probe) from [] 
> (platform_drv_probe+0x18/0x48)
> [   31.057728] [] (platform_drv_probe) from [] 
> (driver_probe_device+0x13c/0x384)
> [   31.066579] [] (driver_probe_device) from [] 
> (bind_store+0x88/0xd8)
> [   31.074564] [] (bind_store) from [] 
> (drv_attr_store+0x20/0x2c)
> [   31.082118] [] (drv_attr_store) from [] 
> (sysfs_kf_write+0x44/0x48)
> [   31.090016] [] (sysfs_kf_write) from [] 
> (kernfs_fop_write+0xc0/0x17c)
> [   31.098176] [] (kernfs_fop_write) from [] 
> (vfs_write+0xa0/0x1c4)
> [   31.105899] [] (vfs_write) from [] 
> (SyS_write+0x40/0x8c)
> [   31.112931] [] (SyS_write) from [] 
> (ret_fast_syscall+0x0/0x3c)
> [   31.120481] Code: e2842018 e584501c e1a4 e885000c (e5835000)
> [   31.126596] ---[ end trace efad45bfa3a61b05 ]---
> [   31.131181] Kernel panic - not syncing: Fatal exception
> [   31.136368] CPU1: stopping
> [   31.139054] CPU: 1 PID: 0 Comm: swapper/1 Tainted: G  D   
> 3.16.0-rc2-00239-g94bdf617b07e-dirty #40
> [   31.148697] [] (unwind_backtrace) from [] 
> (show_stack+0x10/0x14)
> [   31.156419] [] (show_stack) from [] 
> (dump_stack+0x80/0xcc)
> [   31.163622] [] (dump_stack) from [] 
> (handle_IPI+0x130/0x15c)
> [   31.170998] [] (handle_IPI) from [] 
> (gic_handle_irq+0x60/0x68)
> [   31.178549] [] (gic_handle_irq) from [] 
> (__irq_svc+0x40/0x70)
> [   31.186009] Exception stack(0xdf4bdf88 to 0xdf4bdfd0)
> [   31.191046] df80:   ffed    
> df4bc000 c06d042c
> [   31.199207] dfa0:  ffed c06d03c0  c070c288  
>  df4bdfd0
> [   31.207363] dfc0: c0010324 c0010328 6013 
> [   31.212402] [] (__irq_svc) from [] 
> (arch_cpu_idle+0x28/0x30)
> [   31.219783] [] (arch_cpu_idle) from [] 
> (cpu_startup_entry+0x2c4/0x3f0)
> [   

Re: [PATCH] clk: s2mps11: Fix double free corruption during driver unbind

2014-06-27 Thread Yadwinder Singh Brar
Hi Krzystof,

On Fri, Jun 27, 2014 at 4:04 PM, Krzysztof Kozlowski
k.kozlow...@samsung.com wrote:
 After unbinding the driver memory was corrupted by double free of
 clk_lookup structure. This lead to OOPS when re-binding the driver
 again.

 The driver allocated memory for 'clk_lookup' with devm_kzalloc. During
 driver removal this memory was freed twice: once by clkdev_drop() and
 second by devm code.


Ideally memory should be allocated and deallocated in same place
either driver or framework, so in this case if framework(clkdev_drop)
deallocates memory, framework itself should also allocate it.
So IMO this bug should be fixed using clkdev_alloc() instead of kzalloc().

Regards,
Yadwinder

 Kernel panic log:
 [   30.839284] Unable to handle kernel paging request at virtual address 
 5f343173
 [   30.846476] pgd = dee14000
 [   30.849165] [5f343173] *pgd=
 [   30.852703] Internal error: Oops: 805 [#1] PREEMPT SMP ARM
 [   30.858166] Modules linked in:
 [   30.861208] CPU: 0 PID: 1 Comm: bash Not tainted 
 3.16.0-rc2-00239-g94bdf617b07e-dirty #40
 [   30.869364] task: df478000 ti: df48 task.ti: df48
 [   30.874752] PC is at clkdev_add+0x2c/0x38
 [   30.878738] LR is at clkdev_add+0x18/0x38
 [   30.882732] pc : [c0350908]lr : [c03508f4]psr: 6013
 [   30.882732] sp : df481e78  ip : 0001  fp : c0700ed8
 [   30.894187] r10: 000c  r9 :   r8 : c07b0e3c
 [   30.899396] r7 : 0002  r6 : df45f9d0  r5 : df421390  r4 : c0700d6c
 [   30.905906] r3 : 5f343173  r2 : c0700d84  r1 : 6013  r0 : c0700d6c
 [   30.912417] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment 
 user
 [   30.919534] Control: 10c53c7d  Table: 5ee1406a  DAC: 0015
 [   30.925262] Process bash (pid: 1, stack limit = 0xdf480240)
 [   30.930817] Stack: (0xdf481e78 to 0xdf482000)
 [   30.935159] 1e60:   
 1000 df6de610
 [   30.943321] 1e80: df7f4558 c0355650 c05ec6ec c0700eb0 df6de600 df7f4510 
 dec9d69c 0014
 [   30.951480] 1ea0: 00167b48 df6de610 c0700e30 c0713518  c0700e30 
 dec9d69c 0006
 [   30.959639] 1ec0: 00167b48 c02c1b7c c02c1b64 df6de610 c07aff48 c02c0420 
 c06fb150 c047cc20
 [   30.967798] 1ee0: df6de610 df6de610 c0700e30 df6de644 c06fb150 000c 
 dec9d690 c02bef90
 [   30.975957] 1f00: dec9c6c0 dece4c00 df481f80 dece4c00 000c c02be73c 
 000c c016ca8c
 [   30.984116] 1f20: c016ca48   c016c1f4   
 b6f18000 df481f80
 [   30.992276] 1f40: df7f66c0 000c df48 df48 b6f18000 c011094c 
 df47839c 6013
 [   31.000435] 1f60:   df7f66c0 df7f66c0 000c df48 
 b6f18000 c0110dd4
 [   31.008594] 1f80:   000c b6ec05d8 000c b6f18000 
 0004 c000f2a8
 [   31.016753] 1fa0: 1000 c000f0e0 b6ec05d8 000c 0001 b6f18000 
 000c 
 [   31.024912] 1fc0: b6ec05d8 000c b6f18000 0004 000c 0001 
  00167b48
 [   31.033071] 1fe0:  bed83a80 b6e004f0 b6e5122c 6010 0001 
  
 [   31.041248] [c0350908] (clkdev_add) from [c0355650] 
 (s2mps11_clk_probe+0x2b4/0x3b4)
 [   31.049223] [c0355650] (s2mps11_clk_probe) from [c02c1b7c] 
 (platform_drv_probe+0x18/0x48)
 [   31.057728] [c02c1b7c] (platform_drv_probe) from [c02c0420] 
 (driver_probe_device+0x13c/0x384)
 [   31.066579] [c02c0420] (driver_probe_device) from [c02bef90] 
 (bind_store+0x88/0xd8)
 [   31.074564] [c02bef90] (bind_store) from [c02be73c] 
 (drv_attr_store+0x20/0x2c)
 [   31.082118] [c02be73c] (drv_attr_store) from [c016ca8c] 
 (sysfs_kf_write+0x44/0x48)
 [   31.090016] [c016ca8c] (sysfs_kf_write) from [c016c1f4] 
 (kernfs_fop_write+0xc0/0x17c)
 [   31.098176] [c016c1f4] (kernfs_fop_write) from [c011094c] 
 (vfs_write+0xa0/0x1c4)
 [   31.105899] [c011094c] (vfs_write) from [c0110dd4] 
 (SyS_write+0x40/0x8c)
 [   31.112931] [c0110dd4] (SyS_write) from [c000f0e0] 
 (ret_fast_syscall+0x0/0x3c)
 [   31.120481] Code: e2842018 e584501c e1a4 e885000c (e5835000)
 [   31.126596] ---[ end trace efad45bfa3a61b05 ]---
 [   31.131181] Kernel panic - not syncing: Fatal exception
 [   31.136368] CPU1: stopping
 [   31.139054] CPU: 1 PID: 0 Comm: swapper/1 Tainted: G  D   
 3.16.0-rc2-00239-g94bdf617b07e-dirty #40
 [   31.148697] [c0016480] (unwind_backtrace) from [c0012950] 
 (show_stack+0x10/0x14)
 [   31.156419] [c0012950] (show_stack) from [c0480db8] 
 (dump_stack+0x80/0xcc)
 [   31.163622] [c0480db8] (dump_stack) from [c001499c] 
 (handle_IPI+0x130/0x15c)
 [   31.170998] [c001499c] (handle_IPI) from [c000862c] 
 (gic_handle_irq+0x60/0x68)
 [   31.178549] [c000862c] (gic_handle_irq) from [c0013480] 
 (__irq_svc+0x40/0x70)
 [   31.186009] Exception stack(0xdf4bdf88 to 0xdf4bdfd0)
 [   31.191046] df80:   ffed    
 df4bc000 c06d042c
 [   31.199207] dfa0:  ffed c06d03c0  c070c288  
  df4bdfd0
 [   31.207363] dfc0: c0010324 

Re: [PATCH v4 05/14] clk: Add generic driver for Maxim PMIC clocks

2014-06-26 Thread Yadwinder Singh Brar
Hi Javier,

Sorry for jumping in late, but just one concern mentioned inline.

[ .. ]

> +
> +static unsigned long max_gen_recalc_rate(struct clk_hw *hw,
> +unsigned long parent_rate)
> +{
> +   return 32768;
> +}

Isn't more safer(correct), if it check and return 0 when clk is
disabled(unprepared) ?

Regards,
Yadwinder

> +
> +struct clk_ops max_gen_clk_ops = {
> +   .prepare= max_gen_clk_prepare,
> +   .unprepare  = max_gen_clk_unprepare,
> +   .is_prepared= max_gen_clk_is_prepared,
> +   .recalc_rate= max_gen_recalc_rate,
> +};
> +EXPORT_SYMBOL_GPL(max_gen_clk_ops);
> +
> +static struct clk *max_gen_clk_register(struct device *dev,
> +   struct max_gen_clk *max_gen)
> +{
> +   struct clk *clk;
> +   struct clk_hw *hw = _gen->hw;
> +
> +   clk = clk_register(dev, hw);
> +   if (IS_ERR(clk))
> +   return clk;
> +
> +   max_gen->lookup = kzalloc(sizeof(struct clk_lookup), GFP_KERNEL);
> +   if (!max_gen->lookup)
> +   return ERR_PTR(-ENOMEM);
> +
> +   max_gen->lookup->con_id = hw->init->name;
> +   max_gen->lookup->clk = clk;
> +
> +   clkdev_add(max_gen->lookup);
> +
> +   return clk;
> +}
> +
> +int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap,
> + u32 reg, struct clk_init_data *clks_init, int num_init)
> +{
> +   int i, ret;
> +   struct max_gen_clk *max_gen_clks;
> +   struct clk **clocks;
> +   struct device *dev = >dev;
> +
> +   clocks = devm_kzalloc(dev, sizeof(struct clk *) * num_init, 
> GFP_KERNEL);
> +   if (!clocks)
> +   return -ENOMEM;
> +
> +   max_gen_clks = devm_kzalloc(dev, sizeof(struct max_gen_clk)
> +   * num_init, GFP_KERNEL);
> +   if (!max_gen_clks)
> +   return -ENOMEM;
> +
> +   for (i = 0; i < num_init; i++) {
> +   max_gen_clks[i].regmap = regmap;
> +   max_gen_clks[i].mask = 1 << i;
> +   max_gen_clks[i].reg = reg;
> +   max_gen_clks[i].hw.init = _init[i];
> +
> +   clocks[i] = max_gen_clk_register(dev, _gen_clks[i]);
> +   if (IS_ERR(clocks[i])) {
> +   ret = PTR_ERR(clocks[i]);
> +   dev_err(dev, "failed to register %s\n",
> +   max_gen_clks[i].hw.init->name);
> +   goto err_clocks;
> +   }
> +   }
> +
> +   platform_set_drvdata(pdev, clocks);
> +
> +   if (dev->of_node) {
> +   struct clk_onecell_data *of_data;
> +
> +   of_data = devm_kzalloc(dev, sizeof(*of_data), GFP_KERNEL);
> +   if (!of_data) {
> +   ret = -ENOMEM;
> +   goto err_clocks;
> +   }
> +
> +   of_data->clks = clocks;
> +   of_data->clk_num = num_init;
> +   ret = of_clk_add_provider(dev->of_node, 
> of_clk_src_onecell_get,
> + of_data);
> +
> +   if (ret) {
> +   dev_err(dev, "failed to register OF clock 
> provider\n");
> +   goto err_clocks;
> +   }
> +   }
> +
> +   return 0;
> +
> +err_clocks:
> +   for (--i; i >= 0; --i) {
> +   clkdev_drop(max_gen_clks[i].lookup);
> +   clk_unregister(max_gen_clks[i].hw.clk);
> +   }
> +
> +   return ret;
> +}
> +EXPORT_SYMBOL_GPL(max_gen_clk_probe);
> +
> +int max_gen_clk_remove(struct platform_device *pdev, int num_init)
> +{
> +   struct clk **clocks = platform_get_drvdata(pdev);
> +   struct device *dev = pdev->dev.parent;
> +   int i;
> +
> +   if (dev->of_node)
> +   of_clk_del_provider(dev->of_node);
> +
> +   for (i = 0; i < num_init; i++) {
> +   struct clk_hw *hw = __clk_get_hw(clocks[i]);
> +   struct max_gen_clk *max_gen = to_max_gen_clk(hw);
> +
> +   clkdev_drop(max_gen->lookup);
> +   clk_unregister(clocks[i]);
> +   }
> +   return 0;
> +}
> +EXPORT_SYMBOL_GPL(max_gen_clk_remove);
> diff --git a/drivers/clk/clk-max-gen.h b/drivers/clk/clk-max-gen.h
> new file mode 100644
> index 000..997e86f
> --- /dev/null
> +++ b/drivers/clk/clk-max-gen.h
> @@ -0,0 +1,32 @@
> +/*
> + * clk-max-gen.h - Generic clock driver for Maxim PMICs clocks
> + *
> + * Copyright (C) 2014 Google, Inc
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * 

Re: [PATCH v4 05/14] clk: Add generic driver for Maxim PMIC clocks

2014-06-26 Thread Yadwinder Singh Brar
Hi Javier,

Sorry for jumping in late, but just one concern mentioned inline.

[ .. ]

 +
 +static unsigned long max_gen_recalc_rate(struct clk_hw *hw,
 +unsigned long parent_rate)
 +{
 +   return 32768;
 +}

Isn't more safer(correct), if it check and return 0 when clk is
disabled(unprepared) ?

Regards,
Yadwinder

 +
 +struct clk_ops max_gen_clk_ops = {
 +   .prepare= max_gen_clk_prepare,
 +   .unprepare  = max_gen_clk_unprepare,
 +   .is_prepared= max_gen_clk_is_prepared,
 +   .recalc_rate= max_gen_recalc_rate,
 +};
 +EXPORT_SYMBOL_GPL(max_gen_clk_ops);
 +
 +static struct clk *max_gen_clk_register(struct device *dev,
 +   struct max_gen_clk *max_gen)
 +{
 +   struct clk *clk;
 +   struct clk_hw *hw = max_gen-hw;
 +
 +   clk = clk_register(dev, hw);
 +   if (IS_ERR(clk))
 +   return clk;
 +
 +   max_gen-lookup = kzalloc(sizeof(struct clk_lookup), GFP_KERNEL);
 +   if (!max_gen-lookup)
 +   return ERR_PTR(-ENOMEM);
 +
 +   max_gen-lookup-con_id = hw-init-name;
 +   max_gen-lookup-clk = clk;
 +
 +   clkdev_add(max_gen-lookup);
 +
 +   return clk;
 +}
 +
 +int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap,
 + u32 reg, struct clk_init_data *clks_init, int num_init)
 +{
 +   int i, ret;
 +   struct max_gen_clk *max_gen_clks;
 +   struct clk **clocks;
 +   struct device *dev = pdev-dev;
 +
 +   clocks = devm_kzalloc(dev, sizeof(struct clk *) * num_init, 
 GFP_KERNEL);
 +   if (!clocks)
 +   return -ENOMEM;
 +
 +   max_gen_clks = devm_kzalloc(dev, sizeof(struct max_gen_clk)
 +   * num_init, GFP_KERNEL);
 +   if (!max_gen_clks)
 +   return -ENOMEM;
 +
 +   for (i = 0; i  num_init; i++) {
 +   max_gen_clks[i].regmap = regmap;
 +   max_gen_clks[i].mask = 1  i;
 +   max_gen_clks[i].reg = reg;
 +   max_gen_clks[i].hw.init = clks_init[i];
 +
 +   clocks[i] = max_gen_clk_register(dev, max_gen_clks[i]);
 +   if (IS_ERR(clocks[i])) {
 +   ret = PTR_ERR(clocks[i]);
 +   dev_err(dev, failed to register %s\n,
 +   max_gen_clks[i].hw.init-name);
 +   goto err_clocks;
 +   }
 +   }
 +
 +   platform_set_drvdata(pdev, clocks);
 +
 +   if (dev-of_node) {
 +   struct clk_onecell_data *of_data;
 +
 +   of_data = devm_kzalloc(dev, sizeof(*of_data), GFP_KERNEL);
 +   if (!of_data) {
 +   ret = -ENOMEM;
 +   goto err_clocks;
 +   }
 +
 +   of_data-clks = clocks;
 +   of_data-clk_num = num_init;
 +   ret = of_clk_add_provider(dev-of_node, 
 of_clk_src_onecell_get,
 + of_data);
 +
 +   if (ret) {
 +   dev_err(dev, failed to register OF clock 
 provider\n);
 +   goto err_clocks;
 +   }
 +   }
 +
 +   return 0;
 +
 +err_clocks:
 +   for (--i; i = 0; --i) {
 +   clkdev_drop(max_gen_clks[i].lookup);
 +   clk_unregister(max_gen_clks[i].hw.clk);
 +   }
 +
 +   return ret;
 +}
 +EXPORT_SYMBOL_GPL(max_gen_clk_probe);
 +
 +int max_gen_clk_remove(struct platform_device *pdev, int num_init)
 +{
 +   struct clk **clocks = platform_get_drvdata(pdev);
 +   struct device *dev = pdev-dev.parent;
 +   int i;
 +
 +   if (dev-of_node)
 +   of_clk_del_provider(dev-of_node);
 +
 +   for (i = 0; i  num_init; i++) {
 +   struct clk_hw *hw = __clk_get_hw(clocks[i]);
 +   struct max_gen_clk *max_gen = to_max_gen_clk(hw);
 +
 +   clkdev_drop(max_gen-lookup);
 +   clk_unregister(clocks[i]);
 +   }
 +   return 0;
 +}
 +EXPORT_SYMBOL_GPL(max_gen_clk_remove);
 diff --git a/drivers/clk/clk-max-gen.h b/drivers/clk/clk-max-gen.h
 new file mode 100644
 index 000..997e86f
 --- /dev/null
 +++ b/drivers/clk/clk-max-gen.h
 @@ -0,0 +1,32 @@
 +/*
 + * clk-max-gen.h - Generic clock driver for Maxim PMICs clocks
 + *
 + * Copyright (C) 2014 Google, Inc
 + *
 + * This program is free software; you can redistribute  it and/or modify it
 + * under  the terms of  the GNU General  Public License as published by the
 + * Free Software Foundation;  either version 2 of the  License, or (at your
 + * option) any later version.
 + *
 + * 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.
 + *
 + */
 +
 +#ifndef __CLK_MAX_GEN_H__
 +#define 

Re: [PATCH 2/3] regulator: s2mps11: Merge S2MPA01 driver

2014-05-27 Thread Yadwinder Singh Brar
On Tue, May 27, 2014 at 1:26 PM, Krzysztof Kozlowski
 wrote:
> On wto, 2014-05-27 at 12:00 +0530, Yadwinder Singh Brar wrote:
>> On Mon, May 26, 2014 at 6:50 PM, Krzysztof Kozlowski
>>  wrote:
>> > Add S2MPA01 support to the s2mps11 regulator driver. This obsoletes the
>> > s2mpa01 regulator driver.
>> >
>> > Signed-off-by: Krzysztof Kozlowski 
>>
>> > @@ -216,30 +250,20 @@ static int s2mps11_set_ramp_delay(struct 
>> > regulator_dev *rdev, int ramp_delay)
>> > ramp_delay = s2mps11->ramp_delay16;
>> > break;
>> > case S2MPX_BUCK2:
>> > -   if (!ramp_delay) {
>> > -   ramp_enable = 0;
>> > -   break;
>> > -   }
>> > -
>>
>> What if we want to disable ramp_delay from DT ?
>
> It will work OK because at the beginning of s2mps11_set_ramp_delay():
> unsigned int ramp_disable = !ramp_delay;
> This 'ramp_disable' is later used if enable/disable is supported.
>>

Oh! I missed you defined a new variable "ramp_disable",
 since ramp_disable is already a label defined in same function.
It should be different, i think.

>> > -   s2mps11->ramp_delay2 = ramp_delay;
>> > +   if (s2mps11->dev_type == S2MPS11X ||
>> > +   ramp_delay > s2mps11->ramp_delay2)
>> > +   s2mps11->ramp_delay2 = ramp_delay;
>> > +   else /* S2MPA01 && ramp_delay <= s2mpa01->ramp_delay24 */
>> > +   ramp_delay = s2mps11->ramp_delay2;
>>
>> Here ramp_delay = 0(ramp_disable case) is also getting over written,
>> if required to take care of it later.
>
> The same, it is already stored as 'ramp_disable' local variable.
>
>>
>> > break;
>> > case S2MPX_BUCK3:
>> > -   if (!ramp_delay) {
>> > -   ramp_enable = 0;
>> > -   break;
>> > -   }
>>
>> [snip]
>>
>> >
>> > -   if (!ramp_enable)
>> > -   goto ramp_disable;
>> > -
>> > -   /* Ramp delay can be enabled/disabled only for buck[2346] */
>> > if (ramp_reg->enable_supported) {
>> > +   if (ramp_disable)
>>
>> typo ?if (!ramp_enable) / if (!ramp_delay) ?
>
> I think it is good. I changed the 'ramp_enable' into 'ramp_disable'.
>

ok, but very next statement is
 goto ramp_disable;

which seems odd and obfuscated me.

> Anyway while reviewing the code I found that I didn't updated the case
> statements with new BUCKX enum values and the register for
> enable/disable is hard-coded. I'll fix it.
>>
>> > +   goto ramp_disable;
>> > +
>>
>>
>> Also TBH, I can't get rationale behind this merge, As i can't see
>> considerable reduction in no of C code lines in comp of added
>> complexity.
>>  Is there considerable advantage in binary stats of single driver as
>> compare to independent drivers?
>
> Overall more code is removed than added:
> 6 files changed, 454 insertions(+), 719 deletions(-)
> but you are right that the code for ramp delay is now more complex. What
> is worth noting now most of ramp delay settings are moved to an array:
>
> static const struct s2mpx_ramp_reg s2mps11_ramp_regs[] = {
> [S2MPX_BUCK1]   = s2mps11_ramp_reg(BUCK16),
> [S2MPX_BUCK2]   = s2mps11_buck2346_ramp_reg(BUCK2, RAMP, BUCK2),
> [S2MPX_BUCK3]   = s2mps11_buck2346_ramp_reg(BUCK34, RAMP, BUCK3)
>
> instead of being hard-coded into the big switch statement like it was
> before.
>
> Alternative solution to complex ramp delay setting is to just use
> original functions: s2mps11_set_ramp_delay and s2mpa01_set_ramp_delay.
>
> These chips are really similar so having two drivers seems like doubling
> the effort for maintaining them.
>

I think maintaining a complex or a big file(in case we keep original
functions), itself will be an effort consuming thing and moreover
binary size of a single driver will also increase considerable as
compare to independent drivers (if its not case of multiplatform
kernel).

Anyways, i think its matter of preference of all, It will be OK, if
for others( especially maintainers, Mark ?), its OK.


Best Regards,
Yadwinder

> Thanks for comments.
>
> Best regards,
> Krzysztof
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] regulator: s2mps11: Merge S2MPA01 driver

2014-05-27 Thread Yadwinder Singh Brar
On Mon, May 26, 2014 at 6:50 PM, Krzysztof Kozlowski
 wrote:
> Add S2MPA01 support to the s2mps11 regulator driver. This obsoletes the
> s2mpa01 regulator driver.
>
> Signed-off-by: Krzysztof Kozlowski 

> @@ -216,30 +250,20 @@ static int s2mps11_set_ramp_delay(struct regulator_dev 
> *rdev, int ramp_delay)
> ramp_delay = s2mps11->ramp_delay16;
> break;
> case S2MPX_BUCK2:
> -   if (!ramp_delay) {
> -   ramp_enable = 0;
> -   break;
> -   }
> -

What if we want to disable ramp_delay from DT ?

> -   s2mps11->ramp_delay2 = ramp_delay;
> +   if (s2mps11->dev_type == S2MPS11X ||
> +   ramp_delay > s2mps11->ramp_delay2)
> +   s2mps11->ramp_delay2 = ramp_delay;
> +   else /* S2MPA01 && ramp_delay <= s2mpa01->ramp_delay24 */
> +   ramp_delay = s2mps11->ramp_delay2;

Here ramp_delay = 0(ramp_disable case) is also getting over written,
if required to take care of it later.

> break;
> case S2MPX_BUCK3:
> -   if (!ramp_delay) {
> -   ramp_enable = 0;
> -   break;
> -   }

[snip]

>
> -   if (!ramp_enable)
> -   goto ramp_disable;
> -
> -   /* Ramp delay can be enabled/disabled only for buck[2346] */
> if (ramp_reg->enable_supported) {
> +   if (ramp_disable)

typo ?if (!ramp_enable) / if (!ramp_delay) ?

> +   goto ramp_disable;
> +


Also TBH, I can't get rationale behind this merge, As i can't see
considerable reduction in no of C code lines in comp of added
complexity.
 Is there considerable advantage in binary stats of single driver as
compare to independent drivers?


Regards,
Yadwinder
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] regulator: s2mps11: Refactor setting ramp delay

2014-05-27 Thread Yadwinder Singh Brar
Hi Krzysztof,


On Mon, May 26, 2014 at 6:50 PM, Krzysztof Kozlowski
 wrote:
> Prepare for merging the s2mpa01 regulator driver into s2mps11 by:
> 1. Adding common id for buck regulators.
> 2. Splitting shared ramp delay settings to match S2MPA01.
> 3. Adding a configuration of registers for setting ramp delay for each
>buck regulator.
>
> The functionality of the driver should not change as this patch only
> prepares for supporting S2MPA01 device.
>
> Signed-off-by: Krzysztof Kozlowski 
> ---
>  drivers/regulator/s2mps11.c | 210 
> ++--
>  1 file changed, 144 insertions(+), 66 deletions(-)
>

[snip]

>
> -   if (ramp_delay > s2mps11->ramp_delay34)
> -   s2mps11->ramp_delay34 = ramp_delay;
> +   if (ramp_delay > s2mps11->ramp_delay3)
> +   s2mps11->ramp_delay3 = ramp_delay;
> else
> -   ramp_delay = s2mps11->ramp_delay34;
> -
> -   ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT;
> -   ramp_reg = S2MPS11_REG_RAMP;
> +   ramp_delay = s2mps11->ramp_delay3;
> break;
> case S2MPS11_BUCK4:
> -   enable_shift = S2MPS11_BUCK4_RAMP_EN_SHIFT;
> if (!ramp_delay) {
> ramp_enable = 0;
> break;
> }
>
> -   if (ramp_delay > s2mps11->ramp_delay34)
> -   s2mps11->ramp_delay34 = ramp_delay;
> +   if (ramp_delay > s2mps11->ramp_delay4)
> +   s2mps11->ramp_delay4 = ramp_delay;
> else
> -   ramp_delay = s2mps11->ramp_delay34;
> -
> -   ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT;
> -   ramp_reg = S2MPS11_REG_RAMP;
> +   ramp_delay = s2mps11->ramp_delay4;

Main rationale behind shared value is completely omitted here, in
other cases also,
after just giving a NOTE in documentation asking user to make sure to
pass same value.
It doesn't seem safe, simply leaving a scope of stability issue (in
case ramp_delay3 > ramp_delay4).

Regards,
Yadwinder
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] regulator: s2mps11: Refactor setting ramp delay

2014-05-27 Thread Yadwinder Singh Brar
Hi Krzysztof,


On Mon, May 26, 2014 at 6:50 PM, Krzysztof Kozlowski
k.kozlow...@samsung.com wrote:
 Prepare for merging the s2mpa01 regulator driver into s2mps11 by:
 1. Adding common id for buck regulators.
 2. Splitting shared ramp delay settings to match S2MPA01.
 3. Adding a configuration of registers for setting ramp delay for each
buck regulator.

 The functionality of the driver should not change as this patch only
 prepares for supporting S2MPA01 device.

 Signed-off-by: Krzysztof Kozlowski k.kozlow...@samsung.com
 ---
  drivers/regulator/s2mps11.c | 210 
 ++--
  1 file changed, 144 insertions(+), 66 deletions(-)


[snip]


 -   if (ramp_delay  s2mps11-ramp_delay34)
 -   s2mps11-ramp_delay34 = ramp_delay;
 +   if (ramp_delay  s2mps11-ramp_delay3)
 +   s2mps11-ramp_delay3 = ramp_delay;
 else
 -   ramp_delay = s2mps11-ramp_delay34;
 -
 -   ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT;
 -   ramp_reg = S2MPS11_REG_RAMP;
 +   ramp_delay = s2mps11-ramp_delay3;
 break;
 case S2MPS11_BUCK4:
 -   enable_shift = S2MPS11_BUCK4_RAMP_EN_SHIFT;
 if (!ramp_delay) {
 ramp_enable = 0;
 break;
 }

 -   if (ramp_delay  s2mps11-ramp_delay34)
 -   s2mps11-ramp_delay34 = ramp_delay;
 +   if (ramp_delay  s2mps11-ramp_delay4)
 +   s2mps11-ramp_delay4 = ramp_delay;
 else
 -   ramp_delay = s2mps11-ramp_delay34;
 -
 -   ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT;
 -   ramp_reg = S2MPS11_REG_RAMP;
 +   ramp_delay = s2mps11-ramp_delay4;

Main rationale behind shared value is completely omitted here, in
other cases also,
after just giving a NOTE in documentation asking user to make sure to
pass same value.
It doesn't seem safe, simply leaving a scope of stability issue (in
case ramp_delay3  ramp_delay4).

Regards,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] regulator: s2mps11: Merge S2MPA01 driver

2014-05-27 Thread Yadwinder Singh Brar
On Mon, May 26, 2014 at 6:50 PM, Krzysztof Kozlowski
k.kozlow...@samsung.com wrote:
 Add S2MPA01 support to the s2mps11 regulator driver. This obsoletes the
 s2mpa01 regulator driver.

 Signed-off-by: Krzysztof Kozlowski k.kozlow...@samsung.com

 @@ -216,30 +250,20 @@ static int s2mps11_set_ramp_delay(struct regulator_dev 
 *rdev, int ramp_delay)
 ramp_delay = s2mps11-ramp_delay16;
 break;
 case S2MPX_BUCK2:
 -   if (!ramp_delay) {
 -   ramp_enable = 0;
 -   break;
 -   }
 -

What if we want to disable ramp_delay from DT ?

 -   s2mps11-ramp_delay2 = ramp_delay;
 +   if (s2mps11-dev_type == S2MPS11X ||
 +   ramp_delay  s2mps11-ramp_delay2)
 +   s2mps11-ramp_delay2 = ramp_delay;
 +   else /* S2MPA01  ramp_delay = s2mpa01-ramp_delay24 */
 +   ramp_delay = s2mps11-ramp_delay2;

Here ramp_delay = 0(ramp_disable case) is also getting over written,
if required to take care of it later.

 break;
 case S2MPX_BUCK3:
 -   if (!ramp_delay) {
 -   ramp_enable = 0;
 -   break;
 -   }

[snip]


 -   if (!ramp_enable)
 -   goto ramp_disable;
 -
 -   /* Ramp delay can be enabled/disabled only for buck[2346] */
 if (ramp_reg-enable_supported) {
 +   if (ramp_disable)

typo ?if (!ramp_enable) / if (!ramp_delay) ?

 +   goto ramp_disable;
 +


Also TBH, I can't get rationale behind this merge, As i can't see
considerable reduction in no of C code lines in comp of added
complexity.
 Is there considerable advantage in binary stats of single driver as
compare to independent drivers?


Regards,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] regulator: s2mps11: Merge S2MPA01 driver

2014-05-27 Thread Yadwinder Singh Brar
On Tue, May 27, 2014 at 1:26 PM, Krzysztof Kozlowski
k.kozlow...@samsung.com wrote:
 On wto, 2014-05-27 at 12:00 +0530, Yadwinder Singh Brar wrote:
 On Mon, May 26, 2014 at 6:50 PM, Krzysztof Kozlowski
 k.kozlow...@samsung.com wrote:
  Add S2MPA01 support to the s2mps11 regulator driver. This obsoletes the
  s2mpa01 regulator driver.
 
  Signed-off-by: Krzysztof Kozlowski k.kozlow...@samsung.com

  @@ -216,30 +250,20 @@ static int s2mps11_set_ramp_delay(struct 
  regulator_dev *rdev, int ramp_delay)
  ramp_delay = s2mps11-ramp_delay16;
  break;
  case S2MPX_BUCK2:
  -   if (!ramp_delay) {
  -   ramp_enable = 0;
  -   break;
  -   }
  -

 What if we want to disable ramp_delay from DT ?

 It will work OK because at the beginning of s2mps11_set_ramp_delay():
 unsigned int ramp_disable = !ramp_delay;
 This 'ramp_disable' is later used if enable/disable is supported.


Oh! I missed you defined a new variable ramp_disable,
 since ramp_disable is already a label defined in same function.
It should be different, i think.

  -   s2mps11-ramp_delay2 = ramp_delay;
  +   if (s2mps11-dev_type == S2MPS11X ||
  +   ramp_delay  s2mps11-ramp_delay2)
  +   s2mps11-ramp_delay2 = ramp_delay;
  +   else /* S2MPA01  ramp_delay = s2mpa01-ramp_delay24 */
  +   ramp_delay = s2mps11-ramp_delay2;

 Here ramp_delay = 0(ramp_disable case) is also getting over written,
 if required to take care of it later.

 The same, it is already stored as 'ramp_disable' local variable.


  break;
  case S2MPX_BUCK3:
  -   if (!ramp_delay) {
  -   ramp_enable = 0;
  -   break;
  -   }

 [snip]

 
  -   if (!ramp_enable)
  -   goto ramp_disable;
  -
  -   /* Ramp delay can be enabled/disabled only for buck[2346] */
  if (ramp_reg-enable_supported) {
  +   if (ramp_disable)

 typo ?if (!ramp_enable) / if (!ramp_delay) ?

 I think it is good. I changed the 'ramp_enable' into 'ramp_disable'.


ok, but very next statement is
 goto ramp_disable;

which seems odd and obfuscated me.

 Anyway while reviewing the code I found that I didn't updated the case
 statements with new BUCKX enum values and the register for
 enable/disable is hard-coded. I'll fix it.

  +   goto ramp_disable;
  +


 Also TBH, I can't get rationale behind this merge, As i can't see
 considerable reduction in no of C code lines in comp of added
 complexity.
  Is there considerable advantage in binary stats of single driver as
 compare to independent drivers?

 Overall more code is removed than added:
 6 files changed, 454 insertions(+), 719 deletions(-)
 but you are right that the code for ramp delay is now more complex. What
 is worth noting now most of ramp delay settings are moved to an array:

 static const struct s2mpx_ramp_reg s2mps11_ramp_regs[] = {
 [S2MPX_BUCK1]   = s2mps11_ramp_reg(BUCK16),
 [S2MPX_BUCK2]   = s2mps11_buck2346_ramp_reg(BUCK2, RAMP, BUCK2),
 [S2MPX_BUCK3]   = s2mps11_buck2346_ramp_reg(BUCK34, RAMP, BUCK3)

 instead of being hard-coded into the big switch statement like it was
 before.

 Alternative solution to complex ramp delay setting is to just use
 original functions: s2mps11_set_ramp_delay and s2mpa01_set_ramp_delay.

 These chips are really similar so having two drivers seems like doubling
 the effort for maintaining them.


I think maintaining a complex or a big file(in case we keep original
functions), itself will be an effort consuming thing and moreover
binary size of a single driver will also increase considerable as
compare to independent drivers (if its not case of multiplatform
kernel).

Anyways, i think its matter of preference of all, It will be OK, if
for others( especially maintainers, Mark ?), its OK.


Best Regards,
Yadwinder

 Thanks for comments.

 Best regards,
 Krzysztof

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] clk: s2mps11: Add support for S2MPS14 clocks

2014-03-12 Thread Yadwinder Singh Brar
On Mon, Mar 10, 2014 at 6:04 PM, Krzysztof Kozlowski
 wrote:
> This patch adds support for S2MPS14 PMIC clocks (BT and AP) to the
> s2mps11 clock driver.
>
> Signed-off-by: Krzysztof Kozlowski 
> ---

Reviewed-by: Yadwinder Singh Brar 

Just a trivial thing, Kconfig description can also be updated.

Regards,
Yadwinder

>  drivers/clk/clk-s2mps11.c |   61 
> ++---
>  1 file changed, 46 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
> index 508875535e1e..8dafb552274f 100644
> --- a/drivers/clk/clk-s2mps11.c
> +++ b/drivers/clk/clk-s2mps11.c
> @@ -1,7 +1,7 @@
>  /*
>   * clk-s2mps11.c - Clock driver for S2MPS11.
>   *
> - * Copyright (C) 2013 Samsung Electornics
> + * Copyright (C) 2013,2014 Samsung Electornics
>   *
>   * This program is free software; you can redistribute  it and/or modify it
>   * under  the terms of  the GNU General  Public License as published by the
> @@ -13,10 +13,6 @@
>   * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> - *
>   */
>
>  #include 
> @@ -27,6 +23,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>
> @@ -125,7 +122,21 @@ static struct clk_init_data 
> s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
> },
>  };
>
> -static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev)
> +static struct clk_init_data s2mps14_clks_init[S2MPS11_CLKS_NUM] = {
> +   [S2MPS11_CLK_AP] = {
> +   .name = "s2mps14_ap",
> +   .ops = _clk_ops,
> +   .flags = CLK_IS_ROOT,
> +   },
> +   [S2MPS11_CLK_BT] = {
> +   .name = "s2mps14_bt",
> +   .ops = _clk_ops,
> +   .flags = CLK_IS_ROOT,
> +   },
> +};
> +
> +static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev,
> +   struct clk_init_data *clks_init)
>  {
> struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
> struct device_node *clk_np;
> @@ -145,9 +156,12 @@ static struct device_node *s2mps11_clk_parse_dt(struct 
> platform_device *pdev)
> if (!clk_table)
> return ERR_PTR(-ENOMEM);
>
> -   for (i = 0; i < S2MPS11_CLKS_NUM; i++)
> +   for (i = 0; i < S2MPS11_CLKS_NUM; i++) {
> +   if (!clks_init[i].name)
> +   continue; /* Skip clocks not present in some devices 
> */
> of_property_read_string_index(clk_np, "clock-output-names", i,
> -   _clks_init[i].name);
> +   _init[i].name);
> +   }
>
> return clk_np;
>  }
> @@ -158,6 +172,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
> struct s2mps11_clk *s2mps11_clks, *s2mps11_clk;
> struct device_node *clk_np = NULL;
> unsigned int s2mps11_reg;
> +   struct clk_init_data *clks_init;
> int i, ret = 0;
> u32 val;
>
> @@ -168,25 +183,33 @@ static int s2mps11_clk_probe(struct platform_device 
> *pdev)
>
> s2mps11_clk = s2mps11_clks;
>
> -   clk_np = s2mps11_clk_parse_dt(pdev);
> -   if (IS_ERR(clk_np))
> -   return PTR_ERR(clk_np);
> -
> switch (platform_get_device_id(pdev)->driver_data) {
> case S2MPS11X:
> s2mps11_reg = S2MPS11_REG_RTC_CTRL;
> +   clks_init = s2mps11_clks_init;
> +   break;
> +   case S2MPS14X:
> +   s2mps11_reg = S2MPS14_REG_RTCCTRL;
> +   clks_init = s2mps14_clks_init;
> break;
> case S5M8767X:
> s2mps11_reg = S5M8767_REG_CTRL1;
> +   clks_init = s2mps11_clks_init;
> break;
> default:
> dev_err(>dev, "Invalid device type\n");
> return -EINVAL;
> };
>
> +   clk_np = s2mps11_clk_parse_dt(pdev, clks_init);
> +   if (IS_ERR(clk_np))
> +   return PTR_ERR(clk_np);
> +
> for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) {
> +   if (!clks_init[i].name)
> +   continue; /* Skip clocks not present in some devices 
> */
> s2mps11_clk->iodev = iodev;
&g

Re: [PATCH 1/3] clk: s2mps11: Add support for S2MPS14 clocks

2014-03-12 Thread Yadwinder Singh Brar
On Mon, Mar 10, 2014 at 6:04 PM, Krzysztof Kozlowski
k.kozlow...@samsung.com wrote:
 This patch adds support for S2MPS14 PMIC clocks (BT and AP) to the
 s2mps11 clock driver.

 Signed-off-by: Krzysztof Kozlowski k.kozlow...@samsung.com
 ---

Reviewed-by: Yadwinder Singh Brar yadi.b...@samsung.com

Just a trivial thing, Kconfig description can also be updated.

Regards,
Yadwinder

  drivers/clk/clk-s2mps11.c |   61 
 ++---
  1 file changed, 46 insertions(+), 15 deletions(-)

 diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
 index 508875535e1e..8dafb552274f 100644
 --- a/drivers/clk/clk-s2mps11.c
 +++ b/drivers/clk/clk-s2mps11.c
 @@ -1,7 +1,7 @@
  /*
   * clk-s2mps11.c - Clock driver for S2MPS11.
   *
 - * Copyright (C) 2013 Samsung Electornics
 + * Copyright (C) 2013,2014 Samsung Electornics
   *
   * This program is free software; you can redistribute  it and/or modify it
   * under  the terms of  the GNU General  Public License as published by the
 @@ -13,10 +13,6 @@
   * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 - *
   */

  #include linux/module.h
 @@ -27,6 +23,7 @@
  #include linux/clk-provider.h
  #include linux/platform_device.h
  #include linux/mfd/samsung/s2mps11.h
 +#include linux/mfd/samsung/s2mps14.h
  #include linux/mfd/samsung/s5m8767.h
  #include linux/mfd/samsung/core.h

 @@ -125,7 +122,21 @@ static struct clk_init_data 
 s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
 },
  };

 -static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev)
 +static struct clk_init_data s2mps14_clks_init[S2MPS11_CLKS_NUM] = {
 +   [S2MPS11_CLK_AP] = {
 +   .name = s2mps14_ap,
 +   .ops = s2mps11_clk_ops,
 +   .flags = CLK_IS_ROOT,
 +   },
 +   [S2MPS11_CLK_BT] = {
 +   .name = s2mps14_bt,
 +   .ops = s2mps11_clk_ops,
 +   .flags = CLK_IS_ROOT,
 +   },
 +};
 +
 +static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev,
 +   struct clk_init_data *clks_init)
  {
 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev-dev.parent);
 struct device_node *clk_np;
 @@ -145,9 +156,12 @@ static struct device_node *s2mps11_clk_parse_dt(struct 
 platform_device *pdev)
 if (!clk_table)
 return ERR_PTR(-ENOMEM);

 -   for (i = 0; i  S2MPS11_CLKS_NUM; i++)
 +   for (i = 0; i  S2MPS11_CLKS_NUM; i++) {
 +   if (!clks_init[i].name)
 +   continue; /* Skip clocks not present in some devices 
 */
 of_property_read_string_index(clk_np, clock-output-names, i,
 -   s2mps11_clks_init[i].name);
 +   clks_init[i].name);
 +   }

 return clk_np;
  }
 @@ -158,6 +172,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
 struct s2mps11_clk *s2mps11_clks, *s2mps11_clk;
 struct device_node *clk_np = NULL;
 unsigned int s2mps11_reg;
 +   struct clk_init_data *clks_init;
 int i, ret = 0;
 u32 val;

 @@ -168,25 +183,33 @@ static int s2mps11_clk_probe(struct platform_device 
 *pdev)

 s2mps11_clk = s2mps11_clks;

 -   clk_np = s2mps11_clk_parse_dt(pdev);
 -   if (IS_ERR(clk_np))
 -   return PTR_ERR(clk_np);
 -
 switch (platform_get_device_id(pdev)-driver_data) {
 case S2MPS11X:
 s2mps11_reg = S2MPS11_REG_RTC_CTRL;
 +   clks_init = s2mps11_clks_init;
 +   break;
 +   case S2MPS14X:
 +   s2mps11_reg = S2MPS14_REG_RTCCTRL;
 +   clks_init = s2mps14_clks_init;
 break;
 case S5M8767X:
 s2mps11_reg = S5M8767_REG_CTRL1;
 +   clks_init = s2mps11_clks_init;
 break;
 default:
 dev_err(pdev-dev, Invalid device type\n);
 return -EINVAL;
 };

 +   clk_np = s2mps11_clk_parse_dt(pdev, clks_init);
 +   if (IS_ERR(clk_np))
 +   return PTR_ERR(clk_np);
 +
 for (i = 0; i  S2MPS11_CLKS_NUM; i++, s2mps11_clk++) {
 +   if (!clks_init[i].name)
 +   continue; /* Skip clocks not present in some devices 
 */
 s2mps11_clk-iodev = iodev;
 -   s2mps11_clk-hw.init = s2mps11_clks_init[i];
 +   s2mps11_clk-hw.init = clks_init[i];
 s2mps11_clk-mask = 1  i;
 s2mps11_clk-reg = s2mps11_reg;

 @@ -220,8 +243,12 @@ static int s2mps11_clk_probe(struct platform_device 
 *pdev)
 }

 if (clk_table) {
 -   for (i = 0; i

Re: [PATCH v2 09/14] regulator: s2mps11: Add support for S2MPS14 regulators

2014-02-13 Thread Yadwinder Singh Brar
On Thu, Feb 13, 2014 at 2:44 PM, Krzysztof Kozlowski
 wrote:
> Add support for S2MPS14 PMIC regulators to s2mps11 driver. The S2MPS14
> has fewer BUCK-s and LDO-s than S2MPS11. It also does not support
> controlling the BUCK ramp delay.
>
> Signed-off-by: Krzysztof Kozlowski 
> Cc: Mark Brown 
> Cc: Liam Girdwood 
> ---

Reviewed-by: Yadwinder Singh Brar 

Regards,
Yadwinder

>  drivers/regulator/s2mps11.c |  252 
> ---
>  1 file changed, 191 insertions(+), 61 deletions(-)
>
> diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
> index 246b25d58c2b..f56ac6f776ae 100644
> --- a/drivers/regulator/s2mps11.c
> +++ b/drivers/regulator/s2mps11.c
> @@ -1,13 +1,18 @@
>  /*
>   * s2mps11.c
>   *
> - * Copyright (c) 2012 Samsung Electronics Co., Ltd
> + * Copyright (c) 2012-2014 Samsung Electronics Co., Ltd
>   *  http://www.samsung.com
>   *
> - *  This program is free software; you can redistribute  it and/or modify it
> - *  under  the terms of  the GNU General  Public License as published by the
> - *  Free Software Foundation;  either version 2 of the  License, or (at your
> - *  option) any later version.
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + *
> + * 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.
>   *
>   */
>
> @@ -24,6 +29,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>
>  struct s2mps11_info {
> struct regulator_dev **rdev;
> @@ -235,7 +241,7 @@ static struct regulator_ops s2mps11_buck_ops = {
> .set_ramp_delay = s2mps11_set_ramp_delay,
>  };
>
> -#define regulator_desc_ldo1(num)   {   \
> +#define regulator_desc_s2mps11_ldo1(num)   {   \
> .name   = "LDO"#num,\
> .id = S2MPS11_LDO##num, \
> .ops= _ldo_ops, \
> @@ -249,7 +255,7 @@ static struct regulator_ops s2mps11_buck_ops = {
> .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \
> .enable_mask= S2MPS11_ENABLE_MASK   \
>  }
> -#define regulator_desc_ldo2(num)   {   \
> +#define regulator_desc_s2mps11_ldo2(num) { \
> .name   = "LDO"#num,\
> .id = S2MPS11_LDO##num, \
> .ops= _ldo_ops, \
> @@ -264,7 +270,7 @@ static struct regulator_ops s2mps11_buck_ops = {
> .enable_mask= S2MPS11_ENABLE_MASK   \
>  }
>
> -#define regulator_desc_buck1_4(num){   \
> +#define regulator_desc_s2mps11_buck1_4(num) {  \
> .name   = "BUCK"#num,   \
> .id = S2MPS11_BUCK##num,\
> .ops= _buck_ops,\
> @@ -280,7 +286,7 @@ static struct regulator_ops s2mps11_buck_ops = {
> .enable_mask= S2MPS11_ENABLE_MASK   \
>  }
>
> -#define regulator_desc_buck5   {   \
> +#define regulator_desc_s2mps11_buck5 { \
> .name   = "BUCK5",  \
> .id = S2MPS11_BUCK5,\
> .ops= _buck_ops,\
> @@ -296,7 +302,7 @@ static struct regulator_ops s2mps11_buck_ops = {
> .enable_mask= S2MPS11_ENABLE_MASK   \
>  }
>
> -#define regulator_desc_buck6_8(num){   \
> +#define regulator_desc_s2mps11_buck6_8(num) {  \
> .name   = "BUCK"#num,   \
> .id = S2MPS11_BUCK##num,\
> .ops= _buck_ops,\
> @@ -312,7 +318,7 @@ static struct regulator_ops s2mps11_buck_ops = {
> .enable_mask= S2MPS11_ENABLE_MASK   \
>  }
>
> -#define regulator_desc_buck9   {   \
> +#define regulator_desc_s2mps11_buck9 { \
> .name   = "BUCK9",  \
> .id  

Re: [PATCH v2 07/14] regulator: s2mps11: Copy supported regulators from initconst

2014-02-13 Thread Yadwinder Singh Brar
Hi,

On Thu, Feb 13, 2014 at 2:44 PM, Krzysztof Kozlowski
 wrote:
> Add __initconst to 'regulator_desc' array with supported regulators.
> During probe choose how many and which regulators will be supported
> according to device ID. Then copy the 'regulator_desc' array to
> allocated memory so the regulator core can use it.
>
> Additionally allocate array of of_regulator_match() dynamically (based
> on number of regulators) instead of allocation on the stack.
>
> This is needed for supporting different devices in s2mps11
> driver and actually prepares the regulator driver for supporting the
> S2MPS14 device.
>
> Code for supporting the S2MPS14 device will add its own array of
> 'regulator_desc' (also marked as __initconst). This way memory footprint
> of the driver will be reduced (approximately 'regulators_desc' array for
> S2MPS11 occupies 5 kB on 32-bit ARM, for S2MPS14 will occupy 3 kB).
>
> Signed-off-by: Krzysztof Kozlowski 
> Signed-off-by: Chanwoo Choi 
> Cc: Mark Brown 
> Cc: Liam Girdwood 
> Cc: Yadwinder Singh Brar 
> ---

Just observed one trivial thing that in this patch, spacing is not
provided before and after multiplication binary operator ( _ * _ ),
which is recommended by linux spacing convention.

Other than that it looks fine to me, pls feel free to add

Reviewed-by: Yadwinder Singh Brar 


Regards,
Yadwinder

>  drivers/regulator/s2mps11.c |   74 
> +--
>  1 file changed, 64 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
> index d44bd5b3fe8e..246b25d58c2b 100644
> --- a/drivers/regulator/s2mps11.c
> +++ b/drivers/regulator/s2mps11.c
> @@ -25,10 +25,9 @@
>  #include 
>  #include 
>
> -#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators)
> -
>  struct s2mps11_info {
> -   struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX];
> +   struct regulator_dev **rdev;
> +   unsigned int rdev_num;
>
> int ramp_delay2;
> int ramp_delay34;
> @@ -345,7 +344,7 @@ static struct regulator_ops s2mps11_buck_ops = {
> .enable_mask= S2MPS11_ENABLE_MASK   \
>  }
>
> -static const struct regulator_desc regulators[] = {
> +static const struct regulator_desc s2mps11_regulators[] __initconst = {
> regulator_desc_ldo2(1),
> regulator_desc_ldo1(2),
> regulator_desc_ldo1(3),
> @@ -396,21 +395,62 @@ static const struct regulator_desc regulators[] = {
> regulator_desc_buck10,
>  };
>
> +/*
> + * Allocates memory under 'regulators' pointer and copies there array
> + * of regulator_desc for given device.
> + *
> + * Returns number of regulators or negative ERRNO on error.
> + */
> +static int __init
> +s2mps11_pmic_init_regulators_desc(struct platform_device *pdev,
> +   struct regulator_desc **regulators)
> +{
> +   const struct regulator_desc *regulators_init;
> +   enum sec_device_type dev_type;
> +   int rdev_num;
> +
> +   dev_type = platform_get_device_id(pdev)->driver_data;
> +   switch (dev_type) {
> +   case S2MPS11X:
> +   rdev_num = ARRAY_SIZE(s2mps11_regulators);
> +   regulators_init = s2mps11_regulators;
> +   break;
> +   default:
> +   dev_err(>dev, "Invalid device type: %u\n", dev_type);
> +   return -EINVAL;
> +   };
> +
> +   *regulators = devm_kzalloc(>dev, sizeof(**regulators)*rdev_num,
> +   GFP_KERNEL);
> +   if (!*regulators)
> +   return -ENOMEM;
> +
> +   memcpy(*regulators, regulators_init, sizeof(**regulators)*rdev_num);
> +
> +   return rdev_num;
> +}
> +
>  static int s2mps11_pmic_probe(struct platform_device *pdev)
>  {
> struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
> -   struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
> -   struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX];
> +   struct sec_platform_data *pdata = iodev->pdata;
> +   struct of_regulator_match *rdata = NULL;
> struct device_node *reg_np = NULL;
> struct regulator_config config = { };
> struct s2mps11_info *s2mps11;
> int i, ret;
> +   struct regulator_desc *regulators = NULL;
> +   unsigned int rdev_num;
>
> s2mps11 = devm_kzalloc(>dev, sizeof(struct s2mps11_info),
> GFP_KERNEL);
> if (!s2mps11)
> return -ENOMEM;
>
> +   rdev_num = s2mps11_pmic_init_regulators_desc(pdev, );
> +   if (rdev_num < 0)
> +   return rdev_num;
> +
> 

Re: [PATCH v2 11/14] regulator: s2mps11: Add opmode for S2MPS14 regulators

2014-02-13 Thread Yadwinder Singh Brar
Hi,

On Thu, Feb 13, 2014 at 2:44 PM, Krzysztof Kozlowski
 wrote:
> S2MPS11/S2MPS14 regulators support different modes of operation:
>  - Always off;
>  - On/Off controlled by pin/GPIO (PWREN/LDOEN/EMMCEN);
>  - Always on;
> This is very similar to S5M8767 regulator driver which also supports
> opmodes (although S5M8767 have also low-power mode).
>
> This patch adds parsing the operation mode from DTS by reading a
> "op_mode" property from regulator child node.
>

First thing since "op_mode" is not generic property, I think it should
be appended with some driver specific prefix.

But IMHO its quite generic property used and required by many other
PMICs(almost all used by Samsung).
I would like to use this opportunity to discuss about adding it as
generic regulator constraint(as initial_mode)
by providing a default mapping of generic Regulator operating
modes(kernel specific) to operating modes supported by hardware in
regulator driver itself.

Regards,
Yadwinder
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 11/14] regulator: s2mps11: Add opmode for S2MPS14 regulators

2014-02-13 Thread Yadwinder Singh Brar
Hi,

On Thu, Feb 13, 2014 at 2:44 PM, Krzysztof Kozlowski
k.kozlow...@samsung.com wrote:
 S2MPS11/S2MPS14 regulators support different modes of operation:
  - Always off;
  - On/Off controlled by pin/GPIO (PWREN/LDOEN/EMMCEN);
  - Always on;
 This is very similar to S5M8767 regulator driver which also supports
 opmodes (although S5M8767 have also low-power mode).

 This patch adds parsing the operation mode from DTS by reading a
 op_mode property from regulator child node.


First thing since op_mode is not generic property, I think it should
be appended with some driver specific prefix.

But IMHO its quite generic property used and required by many other
PMICs(almost all used by Samsung).
I would like to use this opportunity to discuss about adding it as
generic regulator constraint(as initial_mode)
by providing a default mapping of generic Regulator operating
modes(kernel specific) to operating modes supported by hardware in
regulator driver itself.

Regards,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 07/14] regulator: s2mps11: Copy supported regulators from initconst

2014-02-13 Thread Yadwinder Singh Brar
Hi,

On Thu, Feb 13, 2014 at 2:44 PM, Krzysztof Kozlowski
k.kozlow...@samsung.com wrote:
 Add __initconst to 'regulator_desc' array with supported regulators.
 During probe choose how many and which regulators will be supported
 according to device ID. Then copy the 'regulator_desc' array to
 allocated memory so the regulator core can use it.

 Additionally allocate array of of_regulator_match() dynamically (based
 on number of regulators) instead of allocation on the stack.

 This is needed for supporting different devices in s2mps11
 driver and actually prepares the regulator driver for supporting the
 S2MPS14 device.

 Code for supporting the S2MPS14 device will add its own array of
 'regulator_desc' (also marked as __initconst). This way memory footprint
 of the driver will be reduced (approximately 'regulators_desc' array for
 S2MPS11 occupies 5 kB on 32-bit ARM, for S2MPS14 will occupy 3 kB).

 Signed-off-by: Krzysztof Kozlowski k.kozlow...@samsung.com
 Signed-off-by: Chanwoo Choi cw00.c...@samsung.com
 Cc: Mark Brown broo...@kernel.org
 Cc: Liam Girdwood lgirdw...@gmail.com
 Cc: Yadwinder Singh Brar yadi.bra...@gmail.com
 ---

Just observed one trivial thing that in this patch, spacing is not
provided before and after multiplication binary operator ( _ * _ ),
which is recommended by linux spacing convention.

Other than that it looks fine to me, pls feel free to add

Reviewed-by: Yadwinder Singh Brar yadi.b...@samsung.com


Regards,
Yadwinder

  drivers/regulator/s2mps11.c |   74 
 +--
  1 file changed, 64 insertions(+), 10 deletions(-)

 diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
 index d44bd5b3fe8e..246b25d58c2b 100644
 --- a/drivers/regulator/s2mps11.c
 +++ b/drivers/regulator/s2mps11.c
 @@ -25,10 +25,9 @@
  #include linux/mfd/samsung/core.h
  #include linux/mfd/samsung/s2mps11.h

 -#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators)
 -
  struct s2mps11_info {
 -   struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX];
 +   struct regulator_dev **rdev;
 +   unsigned int rdev_num;

 int ramp_delay2;
 int ramp_delay34;
 @@ -345,7 +344,7 @@ static struct regulator_ops s2mps11_buck_ops = {
 .enable_mask= S2MPS11_ENABLE_MASK   \
  }

 -static const struct regulator_desc regulators[] = {
 +static const struct regulator_desc s2mps11_regulators[] __initconst = {
 regulator_desc_ldo2(1),
 regulator_desc_ldo1(2),
 regulator_desc_ldo1(3),
 @@ -396,21 +395,62 @@ static const struct regulator_desc regulators[] = {
 regulator_desc_buck10,
  };

 +/*
 + * Allocates memory under 'regulators' pointer and copies there array
 + * of regulator_desc for given device.
 + *
 + * Returns number of regulators or negative ERRNO on error.
 + */
 +static int __init
 +s2mps11_pmic_init_regulators_desc(struct platform_device *pdev,
 +   struct regulator_desc **regulators)
 +{
 +   const struct regulator_desc *regulators_init;
 +   enum sec_device_type dev_type;
 +   int rdev_num;
 +
 +   dev_type = platform_get_device_id(pdev)-driver_data;
 +   switch (dev_type) {
 +   case S2MPS11X:
 +   rdev_num = ARRAY_SIZE(s2mps11_regulators);
 +   regulators_init = s2mps11_regulators;
 +   break;
 +   default:
 +   dev_err(pdev-dev, Invalid device type: %u\n, dev_type);
 +   return -EINVAL;
 +   };
 +
 +   *regulators = devm_kzalloc(pdev-dev, sizeof(**regulators)*rdev_num,
 +   GFP_KERNEL);
 +   if (!*regulators)
 +   return -ENOMEM;
 +
 +   memcpy(*regulators, regulators_init, sizeof(**regulators)*rdev_num);
 +
 +   return rdev_num;
 +}
 +
  static int s2mps11_pmic_probe(struct platform_device *pdev)
  {
 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev-dev.parent);
 -   struct sec_platform_data *pdata = dev_get_platdata(iodev-dev);
 -   struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX];
 +   struct sec_platform_data *pdata = iodev-pdata;
 +   struct of_regulator_match *rdata = NULL;
 struct device_node *reg_np = NULL;
 struct regulator_config config = { };
 struct s2mps11_info *s2mps11;
 int i, ret;
 +   struct regulator_desc *regulators = NULL;
 +   unsigned int rdev_num;

 s2mps11 = devm_kzalloc(pdev-dev, sizeof(struct s2mps11_info),
 GFP_KERNEL);
 if (!s2mps11)
 return -ENOMEM;

 +   rdev_num = s2mps11_pmic_init_regulators_desc(pdev, regulators);
 +   if (rdev_num  0)
 +   return rdev_num;
 +
 if (!iodev-dev-of_node) {
 if (pdata) {
 goto common_reg;
 @@ -421,7 +461,16 @@ static int s2mps11_pmic_probe(struct platform_device 
 *pdev)
 }
 }

 -   for (i = 0; i  S2MPS11_REGULATOR_CNT; i++)
 +   s2mps11

Re: [PATCH v2 09/14] regulator: s2mps11: Add support for S2MPS14 regulators

2014-02-13 Thread Yadwinder Singh Brar
On Thu, Feb 13, 2014 at 2:44 PM, Krzysztof Kozlowski
k.kozlow...@samsung.com wrote:
 Add support for S2MPS14 PMIC regulators to s2mps11 driver. The S2MPS14
 has fewer BUCK-s and LDO-s than S2MPS11. It also does not support
 controlling the BUCK ramp delay.

 Signed-off-by: Krzysztof Kozlowski k.kozlow...@samsung.com
 Cc: Mark Brown broo...@kernel.org
 Cc: Liam Girdwood lgirdw...@gmail.com
 ---

Reviewed-by: Yadwinder Singh Brar yadi.b...@samsung.com

Regards,
Yadwinder

  drivers/regulator/s2mps11.c |  252 
 ---
  1 file changed, 191 insertions(+), 61 deletions(-)

 diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
 index 246b25d58c2b..f56ac6f776ae 100644
 --- a/drivers/regulator/s2mps11.c
 +++ b/drivers/regulator/s2mps11.c
 @@ -1,13 +1,18 @@
  /*
   * s2mps11.c
   *
 - * Copyright (c) 2012 Samsung Electronics Co., Ltd
 + * Copyright (c) 2012-2014 Samsung Electronics Co., Ltd
   *  http://www.samsung.com
   *
 - *  This program is free software; you can redistribute  it and/or modify it
 - *  under  the terms of  the GNU General  Public License as published by the
 - *  Free Software Foundation;  either version 2 of the  License, or (at your
 - *  option) any later version.
 + * This program is free software; you can redistribute  it and/or modify it
 + * under  the terms of  the GNU General  Public License as published by the
 + * Free Software Foundation;  either version 2 of the  License, or (at your
 + * option) any later version.
 + *
 + * 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.
   *
   */

 @@ -24,6 +29,7 @@
  #include linux/regulator/of_regulator.h
  #include linux/mfd/samsung/core.h
  #include linux/mfd/samsung/s2mps11.h
 +#include linux/mfd/samsung/s2mps14.h

  struct s2mps11_info {
 struct regulator_dev **rdev;
 @@ -235,7 +241,7 @@ static struct regulator_ops s2mps11_buck_ops = {
 .set_ramp_delay = s2mps11_set_ramp_delay,
  };

 -#define regulator_desc_ldo1(num)   {   \
 +#define regulator_desc_s2mps11_ldo1(num)   {   \
 .name   = LDO#num,\
 .id = S2MPS11_LDO##num, \
 .ops= s2mps11_ldo_ops, \
 @@ -249,7 +255,7 @@ static struct regulator_ops s2mps11_buck_ops = {
 .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \
 .enable_mask= S2MPS11_ENABLE_MASK   \
  }
 -#define regulator_desc_ldo2(num)   {   \
 +#define regulator_desc_s2mps11_ldo2(num) { \
 .name   = LDO#num,\
 .id = S2MPS11_LDO##num, \
 .ops= s2mps11_ldo_ops, \
 @@ -264,7 +270,7 @@ static struct regulator_ops s2mps11_buck_ops = {
 .enable_mask= S2MPS11_ENABLE_MASK   \
  }

 -#define regulator_desc_buck1_4(num){   \
 +#define regulator_desc_s2mps11_buck1_4(num) {  \
 .name   = BUCK#num,   \
 .id = S2MPS11_BUCK##num,\
 .ops= s2mps11_buck_ops,\
 @@ -280,7 +286,7 @@ static struct regulator_ops s2mps11_buck_ops = {
 .enable_mask= S2MPS11_ENABLE_MASK   \
  }

 -#define regulator_desc_buck5   {   \
 +#define regulator_desc_s2mps11_buck5 { \
 .name   = BUCK5,  \
 .id = S2MPS11_BUCK5,\
 .ops= s2mps11_buck_ops,\
 @@ -296,7 +302,7 @@ static struct regulator_ops s2mps11_buck_ops = {
 .enable_mask= S2MPS11_ENABLE_MASK   \
  }

 -#define regulator_desc_buck6_8(num){   \
 +#define regulator_desc_s2mps11_buck6_8(num) {  \
 .name   = BUCK#num,   \
 .id = S2MPS11_BUCK##num,\
 .ops= s2mps11_buck_ops,\
 @@ -312,7 +318,7 @@ static struct regulator_ops s2mps11_buck_ops = {
 .enable_mask= S2MPS11_ENABLE_MASK   \
  }

 -#define regulator_desc_buck9   {   \
 +#define regulator_desc_s2mps11_buck9 { \
 .name   = BUCK9,  \
 .id = S2MPS11_BUCK9,\
 .ops= s2mps11_buck_ops,\
 @@ -328,7 +334,7 @@ static struct regulator_ops s2mps11_buck_ops = {
 .enable_mask= S2MPS11_ENABLE_MASK

Re: [PATCH 07/14] regulator: s2mps11: Choose number of supported regulators during probe

2014-02-12 Thread Yadwinder Singh Brar
Hi,


>
> +   dev_type = platform_get_device_id(pdev)->driver_data;
> +   switch (dev_type) {
> +   case S2MPS11X:
> +   s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
> +   regulators = s2mps11_regulators;

How about creating and passing copy of s2mps11_regulators at runtime
and making s2mps11_regulators __initdata ?

Regards,
Yadwinder
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 07/14] regulator: s2mps11: Choose number of supported regulators during probe

2014-02-12 Thread Yadwinder Singh Brar
Hi,



 +   dev_type = platform_get_device_id(pdev)-driver_data;
 +   switch (dev_type) {
 +   case S2MPS11X:
 +   s2mps11-rdev_num = ARRAY_SIZE(s2mps11_regulators);
 +   regulators = s2mps11_regulators;

How about creating and passing copy of s2mps11_regulators at runtime
and making s2mps11_regulators __initdata ?

Regards,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v2 1/4] power: asv: Add common ASV support for Samsung SoCs

2013-12-26 Thread Yadwinder Singh Brar
Hi Tomasz,

Sorry for being late.

On Sun, Dec 15, 2013 at 10:51 PM, Tomasz Figa  wrote:
> On Sunday 15 of December 2013 22:30:13 Yadwinder Singh Brar wrote:
> [snip]
>> >> +
>> >> + return NULL;
>> >> +}
>> >> +
>> >> +unsigned int asv_get_volt(enum asv_type_id target_type,
>> >> + unsigned int target_freq)
>> >
>> > Do you need this function at all? I believe this is all about populating
>> > device's OPP array with frequencies and voltages according to its ASV
>> > level. Users will be able to query for required voltage using standard OPP
>> > calls then, without a need for ASV specific functions like this one.
>> >
>>
>> Yes, I had put a comment in initial version after commit message :
>> "Hopefully asv_get_volt() can go out in future, once all users start using 
>> OPP
>> library." , which seems to be missed in this version.
>> I had kept it for the time being in initial version, to keep it
>> usable(for testing) with
>> existing cpufreq drivers, which need to reworked and may take time.
>
> Hmm, at the moment none of cpufreq drivers use ASV, so they need to be
> reworked anyway to use it either by the means of a private get_volt
> function or OPP framework. I agree that OPP may require more work,
> though.
>
> If we decide to keep this function in final version, a comment should be
> added saying that its usage is deprecated in favor of generic OPP helpers.
>

yes.

>>
>> [snip]
>> >> +
>> >> + for (i = 0; i < asv_info->nr_dvfs_level; i++) {
>> >> + if (dev_pm_opp_add(dev, dvfs_table[i].freq * 1000,
>> >> + dvfs_table[i].volt)) {
>> >> + dev_warn(dev, "Failed to add OPP %d\n",
>> >> +  dvfs_table[i].freq);
>> >
>> > Hmm, shouldn't it be considered a failure instead?
>> >
>>
>> hmm, not really always. Theoretically system with some less(failed to add)
>> levels can work. Moreover I had prefered to keep it only warning, just to
>> keep the behaviour of  asv_init_opp_table() similar to that of its
>> counter part of_init_opp_table().
>
> I'm not quite convinced about it. If dev_pm_opp_add() fails, doesn't it mean
> that something broke seriously in upper layer and we should propagate the
> error down? Especially when looking at opp_add(), the only failure
> conditions I can find are memory allocation errors which mean that the
> system is unlikely to operate correctly anyway.
>

yes, for the time being i had prefered to keep it similar to
of_init_opp_table() behaviour wise.
If required both should be fixed.


>> [snip]
>> >
>> > Hmm, I don't see a point of these three separate callbacks above.
>> >
>> > In general, I'd suggest a different architecture. I'd see this more as:
>> >
>> > 1) Platform code registers static platform device to instantiate SoC ASV
>> >driver.
>> > 2) SoC specific ASV driver probes, reads group ID from hardware register,
>> >calls register_asv_member() with appropriate DVFS table for detected
>> >group.
>> > 3) Driver using ASV calls asv_init_opp_table() with its struct device and
>> >ASV member name, which causes the ASV code to fill device's operating
>> >point using OPP calls.
>> >
>> > Now client driver has all the information it needs and the work of ASV
>> > subsystem is done. The control flow between drivers would be much simpler
>> > and no callbacks would have to be called.
>> >
>>
>> Architecture stated above seems to be a subset(one possible way of use),
>> of the proposed architecture. If someone really have nothing much to do,
>> he can adopt the above stated approach using this framework also,
>> callbacks are not mandatory.
>
> I believe that kernel design principles are to first start with something
> simple and then if a real need for an extension shows up then extend
> existing code base with missing features.
>

Sorry, I can't see it complex as with architecture stated above
also we have to implement similar structure in drivers as we are already
doing now individually in each soc driver.

>>
>> Since we usually have more things to do other than only reading
>> fused group value and simply parsing a table index, so in drivers we have to
>> implement functions to segregate stuff and different people do it in
>> different way. Its an attempt to provide a way to keep structure(funct

Re: [RFC v2 1/4] power: asv: Add common ASV support for Samsung SoCs

2013-12-26 Thread Yadwinder Singh Brar
Hi Tomasz,

Sorry for being late.

On Sun, Dec 15, 2013 at 10:51 PM, Tomasz Figa tomasz.f...@gmail.com wrote:
 On Sunday 15 of December 2013 22:30:13 Yadwinder Singh Brar wrote:
 [snip]
  +
  + return NULL;
  +}
  +
  +unsigned int asv_get_volt(enum asv_type_id target_type,
  + unsigned int target_freq)
 
  Do you need this function at all? I believe this is all about populating
  device's OPP array with frequencies and voltages according to its ASV
  level. Users will be able to query for required voltage using standard OPP
  calls then, without a need for ASV specific functions like this one.
 

 Yes, I had put a comment in initial version after commit message :
 Hopefully asv_get_volt() can go out in future, once all users start using 
 OPP
 library. , which seems to be missed in this version.
 I had kept it for the time being in initial version, to keep it
 usable(for testing) with
 existing cpufreq drivers, which need to reworked and may take time.

 Hmm, at the moment none of cpufreq drivers use ASV, so they need to be
 reworked anyway to use it either by the means of a private get_volt
 function or OPP framework. I agree that OPP may require more work,
 though.

 If we decide to keep this function in final version, a comment should be
 added saying that its usage is deprecated in favor of generic OPP helpers.


yes.


 [snip]
  +
  + for (i = 0; i  asv_info-nr_dvfs_level; i++) {
  + if (dev_pm_opp_add(dev, dvfs_table[i].freq * 1000,
  + dvfs_table[i].volt)) {
  + dev_warn(dev, Failed to add OPP %d\n,
  +  dvfs_table[i].freq);
 
  Hmm, shouldn't it be considered a failure instead?
 

 hmm, not really always. Theoretically system with some less(failed to add)
 levels can work. Moreover I had prefered to keep it only warning, just to
 keep the behaviour of  asv_init_opp_table() similar to that of its
 counter part of_init_opp_table().

 I'm not quite convinced about it. If dev_pm_opp_add() fails, doesn't it mean
 that something broke seriously in upper layer and we should propagate the
 error down? Especially when looking at opp_add(), the only failure
 conditions I can find are memory allocation errors which mean that the
 system is unlikely to operate correctly anyway.


yes, for the time being i had prefered to keep it similar to
of_init_opp_table() behaviour wise.
If required both should be fixed.


 [snip]
 
  Hmm, I don't see a point of these three separate callbacks above.
 
  In general, I'd suggest a different architecture. I'd see this more as:
 
  1) Platform code registers static platform device to instantiate SoC ASV
 driver.
  2) SoC specific ASV driver probes, reads group ID from hardware register,
 calls register_asv_member() with appropriate DVFS table for detected
 group.
  3) Driver using ASV calls asv_init_opp_table() with its struct device and
 ASV member name, which causes the ASV code to fill device's operating
 point using OPP calls.
 
  Now client driver has all the information it needs and the work of ASV
  subsystem is done. The control flow between drivers would be much simpler
  and no callbacks would have to be called.
 

 Architecture stated above seems to be a subset(one possible way of use),
 of the proposed architecture. If someone really have nothing much to do,
 he can adopt the above stated approach using this framework also,
 callbacks are not mandatory.

 I believe that kernel design principles are to first start with something
 simple and then if a real need for an extension shows up then extend
 existing code base with missing features.


Sorry, I can't see it complex as with architecture stated above
also we have to implement similar structure in drivers as we are already
doing now individually in each soc driver.


 Since we usually have more things to do other than only reading
 fused group value and simply parsing a table index, so in drivers we have to
 implement functions to segregate stuff and different people do it in
 different way. Its an attempt to provide a way to keep structure(functions)
 similar for easy understanding and factoring out of common code.

 I fail to see those more things. Could you elaborate a bit about them?

Usually we need to implement functions in drivers clearly demarking following :
1- Reading chip info (which can be done at probe time only once for all).
2- Parse/Calculate(modify) ASV group.
3- Any Group specific one time setting. eg ABB settings.
4- Parsing and modifying table ( implementing Voltage locking, if
required based on locking info bits).


Best Regards,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v2 1/4] power: asv: Add common ASV support for Samsung SoCs

2013-12-15 Thread Yadwinder Singh Brar
Hi Tomasz,

Thanks for your thorough review and nice suggestions.

[snip]
>> +}
>> +
>> +static struct asv_member *asv_get_mem(enum asv_type_id asv_type)
>
> I don't really like this enum based look-up. It's hard to define an enum
> that covers any possible existing and future platforms that would not be
> bloated with single platform specific entries. IMHO something string based
> could be more scalable.
>

Yes, I also agree string based look-up will be better. I was thinking
to convert to it,
after initial discussion over the APIs.

>> +{
>> + struct asv_member *asv_mem;
>> + struct asv_info *asv_info;
>> +
>> + list_for_each_entry(asv_mem, _list, node) {
>> + asv_info = asv_mem->asv_info;
>> + if (asv_type == asv_info->type)
>> + return asv_mem;
>> + }
>
> Don't you need any kind of locking here? A mutex in add_asv_member()
> suggests that read access to the list should be protected as well.
>

hmmm, yes should be their for completeness of code.

>> +
>> + return NULL;
>> +}
>> +
>> +unsigned int asv_get_volt(enum asv_type_id target_type,
>> + unsigned int target_freq)
>
> Do you need this function at all? I believe this is all about populating
> device's OPP array with frequencies and voltages according to its ASV
> level. Users will be able to query for required voltage using standard OPP
> calls then, without a need for ASV specific functions like this one.
>

Yes, I had put a comment in initial version after commit message :
"Hopefully asv_get_volt() can go out in future, once all users start using OPP
library." , which seems to be missed in this version.
I had kept it for the time being in initial version, to keep it
usable(for testing) with
existing cpufreq drivers, which need to reworked and may take time.

[snip]
>> +
>> + for (i = 0; i < asv_info->nr_dvfs_level; i++) {
>> + if (dev_pm_opp_add(dev, dvfs_table[i].freq * 1000,
>> + dvfs_table[i].volt)) {
>> + dev_warn(dev, "Failed to add OPP %d\n",
>> +  dvfs_table[i].freq);
>
> Hmm, shouldn't it be considered a failure instead?
>

hmm, not really always. Theoretically system with some less(failed to add)
levels can work. Moreover I had prefered to keep it only warning, just to
keep the behaviour of  asv_init_opp_table() similar to that of its
counter part of_init_opp_table().

>> + continue;
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static struct asv_member *asv_init_member(struct asv_info *asv_info)
>> +{
>> + struct asv_member *asv_mem;
>> + int ret = 0;
>> +
>> + if (!asv_info) {
>> + pr_err("No ASV info provided\n");
>> + return NULL;
>
> I'd suggest adopting the ERR_PTR() convention, which allows returning more
> information about the error.
>

Will it be really usefull here?, as we are not checking return value
of any function.
Bur for some cases below, i will also like to get it used.

>> + }
>> +
>> + asv_mem = kzalloc(sizeof(*asv_mem), GFP_KERNEL);
>> + if (!asv_mem) {
>> + pr_err("Allocation failed for member: %s\n", asv_info->name);
>> + return NULL;
>> + }

[snip]
>
> Hmm, I don't see a point of these three separate callbacks above.
>
> In general, I'd suggest a different architecture. I'd see this more as:
>
> 1) Platform code registers static platform device to instantiate SoC ASV
>driver.
> 2) SoC specific ASV driver probes, reads group ID from hardware register,
>calls register_asv_member() with appropriate DVFS table for detected
>group.
> 3) Driver using ASV calls asv_init_opp_table() with its struct device and
>ASV member name, which causes the ASV code to fill device's operating
>point using OPP calls.
>
> Now client driver has all the information it needs and the work of ASV
> subsystem is done. The control flow between drivers would be much simpler
> and no callbacks would have to be called.
>

Architecture stated above seems to be a subset(one possible way of use),
of the proposed architecture. If someone really have nothing much to do,
he can adopt the above stated approach using this framework also,
callbacks are not mandatory.

Since we usually have more things to do other than only reading
fused group value and simply parsing a table index, so in drivers we have to
implement functions to segregate stuff and different people do it in
different way. Its an attempt to provide a way to keep structure(functions)
similar for easy understanding and factoring out of common code.

Moreover, I feels need of callbacks if we have to do something depending
upon(specific) the user/instance of  ASV member. One thing came
in my mind was dev_node may be required if we may think of parsing
ASV table from DT and may be more things in future.


I would like to get rectified, other nit/suggestions stated by you 

Re: [RFC v2 1/4] power: asv: Add common ASV support for Samsung SoCs

2013-12-15 Thread Yadwinder Singh Brar
Hi Abhilash,

[ ... ]
>> + * @nr_dvfs_level: Number of dvfs levels supported by member.
>> + * @dvfs_table: Table containing supported ASV freqs and corresponding 
>> volts.
>> + * @asv_grp: ASV group of member.
>> + * @flags: ASV flags
> What are the ASV flags you had in mind ?

Right now we don't have any, some thing like delayed
init of asv table depending upon dev_node/user(instance)
was coming in my mind.
Actually I missed to remove it for the time being.

Thanks for your review and other suggestions.

Regards,
Yadwinder
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v2 1/4] power: asv: Add common ASV support for Samsung SoCs

2013-12-15 Thread Yadwinder Singh Brar
Hi Abhilash,

[ ... ]
 + * @nr_dvfs_level: Number of dvfs levels supported by member.
 + * @dvfs_table: Table containing supported ASV freqs and corresponding 
 volts.
 + * @asv_grp: ASV group of member.
 + * @flags: ASV flags
 What are the ASV flags you had in mind ?

Right now we don't have any, some thing like delayed
init of asv table depending upon dev_node/user(instance)
was coming in my mind.
Actually I missed to remove it for the time being.

Thanks for your review and other suggestions.

Regards,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC v2 1/4] power: asv: Add common ASV support for Samsung SoCs

2013-12-15 Thread Yadwinder Singh Brar
Hi Tomasz,

Thanks for your thorough review and nice suggestions.

[snip]
 +}
 +
 +static struct asv_member *asv_get_mem(enum asv_type_id asv_type)

 I don't really like this enum based look-up. It's hard to define an enum
 that covers any possible existing and future platforms that would not be
 bloated with single platform specific entries. IMHO something string based
 could be more scalable.


Yes, I also agree string based look-up will be better. I was thinking
to convert to it,
after initial discussion over the APIs.

 +{
 + struct asv_member *asv_mem;
 + struct asv_info *asv_info;
 +
 + list_for_each_entry(asv_mem, asv_list, node) {
 + asv_info = asv_mem-asv_info;
 + if (asv_type == asv_info-type)
 + return asv_mem;
 + }

 Don't you need any kind of locking here? A mutex in add_asv_member()
 suggests that read access to the list should be protected as well.


hmmm, yes should be their for completeness of code.

 +
 + return NULL;
 +}
 +
 +unsigned int asv_get_volt(enum asv_type_id target_type,
 + unsigned int target_freq)

 Do you need this function at all? I believe this is all about populating
 device's OPP array with frequencies and voltages according to its ASV
 level. Users will be able to query for required voltage using standard OPP
 calls then, without a need for ASV specific functions like this one.


Yes, I had put a comment in initial version after commit message :
Hopefully asv_get_volt() can go out in future, once all users start using OPP
library. , which seems to be missed in this version.
I had kept it for the time being in initial version, to keep it
usable(for testing) with
existing cpufreq drivers, which need to reworked and may take time.

[snip]
 +
 + for (i = 0; i  asv_info-nr_dvfs_level; i++) {
 + if (dev_pm_opp_add(dev, dvfs_table[i].freq * 1000,
 + dvfs_table[i].volt)) {
 + dev_warn(dev, Failed to add OPP %d\n,
 +  dvfs_table[i].freq);

 Hmm, shouldn't it be considered a failure instead?


hmm, not really always. Theoretically system with some less(failed to add)
levels can work. Moreover I had prefered to keep it only warning, just to
keep the behaviour of  asv_init_opp_table() similar to that of its
counter part of_init_opp_table().

 + continue;
 + }
 + }
 +
 + return 0;
 +}
 +
 +static struct asv_member *asv_init_member(struct asv_info *asv_info)
 +{
 + struct asv_member *asv_mem;
 + int ret = 0;
 +
 + if (!asv_info) {
 + pr_err(No ASV info provided\n);
 + return NULL;

 I'd suggest adopting the ERR_PTR() convention, which allows returning more
 information about the error.


Will it be really usefull here?, as we are not checking return value
of any function.
Bur for some cases below, i will also like to get it used.

 + }
 +
 + asv_mem = kzalloc(sizeof(*asv_mem), GFP_KERNEL);
 + if (!asv_mem) {
 + pr_err(Allocation failed for member: %s\n, asv_info-name);
 + return NULL;
 + }

[snip]

 Hmm, I don't see a point of these three separate callbacks above.

 In general, I'd suggest a different architecture. I'd see this more as:

 1) Platform code registers static platform device to instantiate SoC ASV
driver.
 2) SoC specific ASV driver probes, reads group ID from hardware register,
calls register_asv_member() with appropriate DVFS table for detected
group.
 3) Driver using ASV calls asv_init_opp_table() with its struct device and
ASV member name, which causes the ASV code to fill device's operating
point using OPP calls.

 Now client driver has all the information it needs and the work of ASV
 subsystem is done. The control flow between drivers would be much simpler
 and no callbacks would have to be called.


Architecture stated above seems to be a subset(one possible way of use),
of the proposed architecture. If someone really have nothing much to do,
he can adopt the above stated approach using this framework also,
callbacks are not mandatory.

Since we usually have more things to do other than only reading
fused group value and simply parsing a table index, so in drivers we have to
implement functions to segregate stuff and different people do it in
different way. Its an attempt to provide a way to keep structure(functions)
similar for easy understanding and factoring out of common code.

Moreover, I feels need of callbacks if we have to do something depending
upon(specific) the user/instance of  ASV member. One thing came
in my mind was dev_node may be required if we may think of parsing
ASV table from DT and may be more things in future.


I would like to get rectified, other nit/suggestions stated by you in
next version.


Thanks  Regards,
 Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a 

Re: [RFC 0/4] Add basic support for ASV

2013-11-14 Thread Yadwinder Singh Brar
[adding Sachin]

Hi Tomasz,

On Fri, Nov 15, 2013 at 12:06 AM, Tomasz Figa  wrote:
> Hi Yadwinder,
>
> On Monday 11 of November 2013 23:27:08 Yadwinder Singh Brar wrote:
>> gentle ping for suggestions/reviews ..
>
> Hmm, I must have somehow missed this series when you orignally sent it.
> Can I ask you to resend it, as I don't have it in my e-mail client archive
> any longer?
>
> While at it, I would also ask you to add my private e-mail address
> (this one) and linux-pm mailing list to Cc list.
>

hmm, I am on travel still for few more days, so it may be difficult for me
to resend it quickly. But I think Sachin may help me here.
Sachin can you please rebase and repost it ?

Regards,
Yadwinder
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC 0/4] Add basic support for ASV

2013-11-14 Thread Yadwinder Singh Brar
Hi MyungJoo,

Thanks for your review.

On Wed, Nov 13, 2013 at 11:33 AM, MyungJoo Ham  wrote:
> On Mon, Nov 11, 2013 at 11:27 PM, Yadwinder Singh Brar
>  wrote:
>> gentle ping for suggestions/reviews ..
>>
>>
>> On Wed, Sep 11, 2013 at 8:14 PM, Yadwinder Singh Brar
>>  wrote:
>>> This series is to add basic common infrastructure for ASV.
>>>  Basically ASV is a technique used on samsung SoCs, which provides the
>>> recommended supply voltage for dvfs of arm, mif etc. For a given operating
>>> frequency, the voltage is recommended based on SoC's ASV group.
>>> ASV group gets fussed on SoCs during process of mass production.
>
> ASV is an instance of AVS. Please recondier and try to reuse
> what's already there (drivers/power/avs)
>
> Quote from drivers/power/avs/Kconfig:
>   "At a given operating point the voltage is adapted depending on
>   static factors (chip manufacturing process) and dynamic factors
>   (temperature depending performance)."
> It seems that the current ASV is subset of AVS.

Yes, both seems to be for similar purpose but  still significantly
different from each other. I would like to describe/differentiate it
little bit here
for explanation for others, that it is AVS(adaptive voltage scaling) which
seems to be an IP/module doing adaptive voltage scaling where as
ours is ASV(Adaptive scaling voltage), it provides only (adaptive) voltage
for scaling to other drivers.

> Although the current implementation of AVS does not provide significant
> infrastructure to its sisters, we may start by sharing the directory.
>

Yes, we can just share directory only right now, other then that i
didn't see any thing can be common.
Firstly i had put in that directory itself, later being doubtful i
moved it to new directory but we can share directory.
Any ideas/comments from others ?

Regards,
Yadwinder

>
> Added Jean Pihet, who has submitted AVS (TI).
>
> Cheers,
> MyungJoo.
>
>>>
>>> This series includes:
>>>  - basic common infrastructue for ASV. It provides common APIs for user 
>>> drivers
>>> like cpufreq & devfreq and and an interface for SoC specific drivers to
>>> register ASV members(instances)
>>>  - a common platform driver to register ASV members for exynos SoCs
>>>  - an example providing minimal support (only for ARM ASV) for exynos5250 
>>> chips
>>>
>>> Its just basic skelton which I wanted to get it reviewed or discussed in
>>> early stage, before going ahead on further development based on it.
>>>  Presently example is based on static ASV table provided in SoC specific 
>>> file,
>>> which I expects to go into DT. But exactly how and where needs to be 
>>> discussed,
>>> may be in next revisions once we get through the basic skelton.
>>>  Also the location of driver in kernel may also seem odd to someone and
>>> many more things :).
>>>
>>> Looking for your valuable reviews and suggestions.
>>>
>>> Thanks
>>>
>>> Yadwinder Singh Brar (4):
>>>   power: asv: Add common ASV support for samsung SoCs
>>>   power: asv: Add a common asv driver for exynos SoCs.
>>>   power: asv: Add support for exynos5250
>>>   arm: exynos5: Register static platform device for ASV.
>>>
>>>  arch/arm/mach-exynos/mach-exynos5-dt.c   |3 +
>>>  drivers/power/Kconfig|1 +
>>>  drivers/power/Makefile   |1 +
>>>  drivers/power/asv/Kconfig|   24 
>>>  drivers/power/asv/Makefile   |2 +
>>>  drivers/power/asv/exynos-asv.c   |   81 ++
>>>  drivers/power/asv/exynos-asv.h   |   22 
>>>  drivers/power/asv/exynos5250-asv.c   |  141 
>>>  drivers/power/asv/samsung-asv.c  |  175 
>>> ++
>>>  include/linux/power/samsung-asv-driver.h |   61 +++
>>>  include/linux/power/samsung-asv.h|   37 +++
>>>  11 files changed, 548 insertions(+), 0 deletions(-)
>>>  create mode 100644 drivers/power/asv/Kconfig
>>>  create mode 100644 drivers/power/asv/Makefile
>>>  create mode 100644 drivers/power/asv/exynos-asv.c
>>>  create mode 100644 drivers/power/asv/exynos-asv.h
>>>  create mode 100644 drivers/power/asv/exynos5250-asv.c
>>>  create mode 100644 drivers/power/asv/samsung-asv.c
>>>  create mode 100644 include/linux/power/samsung-asv-driver.h
>>>  create mode 100644 include/linux/power/samsung-asv.h
>>>
>>&g

Re: [RFC 0/4] Add basic support for ASV

2013-11-14 Thread Yadwinder Singh Brar
Hi MyungJoo,

Thanks for your review.

On Wed, Nov 13, 2013 at 11:33 AM, MyungJoo Ham myungjoo@samsung.com wrote:
 On Mon, Nov 11, 2013 at 11:27 PM, Yadwinder Singh Brar
 yadi.bra...@gmail.com wrote:
 gentle ping for suggestions/reviews ..


 On Wed, Sep 11, 2013 at 8:14 PM, Yadwinder Singh Brar
 yadi.b...@samsung.com wrote:
 This series is to add basic common infrastructure for ASV.
  Basically ASV is a technique used on samsung SoCs, which provides the
 recommended supply voltage for dvfs of arm, mif etc. For a given operating
 frequency, the voltage is recommended based on SoC's ASV group.
 ASV group gets fussed on SoCs during process of mass production.

 ASV is an instance of AVS. Please recondier and try to reuse
 what's already there (drivers/power/avs)

 Quote from drivers/power/avs/Kconfig:
   At a given operating point the voltage is adapted depending on
   static factors (chip manufacturing process) and dynamic factors
   (temperature depending performance).
 It seems that the current ASV is subset of AVS.

Yes, both seems to be for similar purpose but  still significantly
different from each other. I would like to describe/differentiate it
little bit here
for explanation for others, that it is AVS(adaptive voltage scaling) which
seems to be an IP/module doing adaptive voltage scaling where as
ours is ASV(Adaptive scaling voltage), it provides only (adaptive) voltage
for scaling to other drivers.

 Although the current implementation of AVS does not provide significant
 infrastructure to its sisters, we may start by sharing the directory.


Yes, we can just share directory only right now, other then that i
didn't see any thing can be common.
Firstly i had put in that directory itself, later being doubtful i
moved it to new directory but we can share directory.
Any ideas/comments from others ?

Regards,
Yadwinder


 Added Jean Pihet, who has submitted AVS (TI).

 Cheers,
 MyungJoo.


 This series includes:
  - basic common infrastructue for ASV. It provides common APIs for user 
 drivers
 like cpufreq  devfreq and and an interface for SoC specific drivers to
 register ASV members(instances)
  - a common platform driver to register ASV members for exynos SoCs
  - an example providing minimal support (only for ARM ASV) for exynos5250 
 chips

 Its just basic skelton which I wanted to get it reviewed or discussed in
 early stage, before going ahead on further development based on it.
  Presently example is based on static ASV table provided in SoC specific 
 file,
 which I expects to go into DT. But exactly how and where needs to be 
 discussed,
 may be in next revisions once we get through the basic skelton.
  Also the location of driver in kernel may also seem odd to someone and
 many more things :).

 Looking for your valuable reviews and suggestions.

 Thanks

 Yadwinder Singh Brar (4):
   power: asv: Add common ASV support for samsung SoCs
   power: asv: Add a common asv driver for exynos SoCs.
   power: asv: Add support for exynos5250
   arm: exynos5: Register static platform device for ASV.

  arch/arm/mach-exynos/mach-exynos5-dt.c   |3 +
  drivers/power/Kconfig|1 +
  drivers/power/Makefile   |1 +
  drivers/power/asv/Kconfig|   24 
  drivers/power/asv/Makefile   |2 +
  drivers/power/asv/exynos-asv.c   |   81 ++
  drivers/power/asv/exynos-asv.h   |   22 
  drivers/power/asv/exynos5250-asv.c   |  141 
  drivers/power/asv/samsung-asv.c  |  175 
 ++
  include/linux/power/samsung-asv-driver.h |   61 +++
  include/linux/power/samsung-asv.h|   37 +++
  11 files changed, 548 insertions(+), 0 deletions(-)
  create mode 100644 drivers/power/asv/Kconfig
  create mode 100644 drivers/power/asv/Makefile
  create mode 100644 drivers/power/asv/exynos-asv.c
  create mode 100644 drivers/power/asv/exynos-asv.h
  create mode 100644 drivers/power/asv/exynos5250-asv.c
  create mode 100644 drivers/power/asv/samsung-asv.c
  create mode 100644 include/linux/power/samsung-asv-driver.h
  create mode 100644 include/linux/power/samsung-asv.h


 ___
 linux-arm-kernel mailing list
 linux-arm-ker...@lists.infradead.org
 http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

 ___
 linux-arm-kernel mailing list
 linux-arm-ker...@lists.infradead.org
 http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



 --
 MyungJoo Ham, Ph.D.
 System S/W Lab, S/W Center, Samsung Electronics
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC 0/4] Add basic support for ASV

2013-11-14 Thread Yadwinder Singh Brar
[adding Sachin]

Hi Tomasz,

On Fri, Nov 15, 2013 at 12:06 AM, Tomasz Figa tomasz.f...@gmail.com wrote:
 Hi Yadwinder,

 On Monday 11 of November 2013 23:27:08 Yadwinder Singh Brar wrote:
 gentle ping for suggestions/reviews ..

 Hmm, I must have somehow missed this series when you orignally sent it.
 Can I ask you to resend it, as I don't have it in my e-mail client archive
 any longer?

 While at it, I would also ask you to add my private e-mail address
 (this one) and linux-pm mailing list to Cc list.


hmm, I am on travel still for few more days, so it may be difficult for me
to resend it quickly. But I think Sachin may help me here.
Sachin can you please rebase and repost it ?

Regards,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC 0/4] Add basic support for ASV

2013-11-11 Thread Yadwinder Singh Brar
gentle ping for suggestions/reviews ..


On Wed, Sep 11, 2013 at 8:14 PM, Yadwinder Singh Brar
 wrote:
> This series is to add basic common infrastructure for ASV.
>  Basically ASV is a technique used on samsung SoCs, which provides the
> recommended supply voltage for dvfs of arm, mif etc. For a given operating
> frequency, the voltage is recommended based on SoC's ASV group.
> ASV group gets fussed on SoCs during process of mass production.
>
> This series includes:
>  - basic common infrastructue for ASV. It provides common APIs for user 
> drivers
> like cpufreq & devfreq and and an interface for SoC specific drivers to
> register ASV members(instances)
>  - a common platform driver to register ASV members for exynos SoCs
>  - an example providing minimal support (only for ARM ASV) for exynos5250 
> chips
>
> Its just basic skelton which I wanted to get it reviewed or discussed in
> early stage, before going ahead on further development based on it.
>  Presently example is based on static ASV table provided in SoC specific file,
> which I expects to go into DT. But exactly how and where needs to be 
> discussed,
> may be in next revisions once we get through the basic skelton.
>  Also the location of driver in kernel may also seem odd to someone and
> many more things :).
>
> Looking for your valuable reviews and suggestions.
>
> Thanks
>
> Yadwinder Singh Brar (4):
>   power: asv: Add common ASV support for samsung SoCs
>   power: asv: Add a common asv driver for exynos SoCs.
>   power: asv: Add support for exynos5250
>   arm: exynos5: Register static platform device for ASV.
>
>  arch/arm/mach-exynos/mach-exynos5-dt.c   |3 +
>  drivers/power/Kconfig|1 +
>  drivers/power/Makefile   |1 +
>  drivers/power/asv/Kconfig|   24 
>  drivers/power/asv/Makefile   |2 +
>  drivers/power/asv/exynos-asv.c   |   81 ++
>  drivers/power/asv/exynos-asv.h   |   22 
>  drivers/power/asv/exynos5250-asv.c   |  141 
>  drivers/power/asv/samsung-asv.c  |  175 
> ++
>  include/linux/power/samsung-asv-driver.h |   61 +++
>  include/linux/power/samsung-asv.h|   37 +++
>  11 files changed, 548 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/power/asv/Kconfig
>  create mode 100644 drivers/power/asv/Makefile
>  create mode 100644 drivers/power/asv/exynos-asv.c
>  create mode 100644 drivers/power/asv/exynos-asv.h
>  create mode 100644 drivers/power/asv/exynos5250-asv.c
>  create mode 100644 drivers/power/asv/samsung-asv.c
>  create mode 100644 include/linux/power/samsung-asv-driver.h
>  create mode 100644 include/linux/power/samsung-asv.h
>
>
> ___
> linux-arm-kernel mailing list
> linux-arm-ker...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/4] clk: clk-s2mps11: Add support for clocks in S5M8767 MFD

2013-11-11 Thread Yadwinder Singh Brar
On Thu, Oct 31, 2013 at 3:48 PM, Tushar Behera  wrote:
> Since clock operation within S2MPS11 and S5M8767 are similar, we can
> support both the devices within a single driver.
>
> Signed-off-by: Tushar Behera 
> CC: Yadwinder Singh Brar 
> CC: Mike Turquette 
> ---

Reviewed-by: Yadwinder Singh Brar 

Regards,
Yadwinder

>  drivers/clk/Kconfig   |6 --
>  drivers/clk/clk-s2mps11.c |5 +
>  2 files changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 5c51115..7f2aef2 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -65,10 +65,12 @@ config COMMON_CLK_SI5351
>   generators.
>
>  config COMMON_CLK_S2MPS11
> -   tristate "Clock driver for S2MPS11 MFD"
> +   tristate "Clock driver for S2MPS11/S5M8767 MFD"
> depends on MFD_SEC_CORE
> ---help---
> - This driver supports S2MPS11 crystal oscillator clock.
> + This driver supports S2MPS11/S5M8767 crystal oscillator clock. These
> + multi-function devices have 3 fixed-rate oscillators, clocked at
> + 32KHz each.
>
>  config CLK_TWL6040
> tristate "External McPDM functional clock from twl6040"
> diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
> index 2262cb4..19c075c 100644
> --- a/drivers/clk/clk-s2mps11.c
> +++ b/drivers/clk/clk-s2mps11.c
> @@ -27,6 +27,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>
>  #define s2mps11_name(a) (a->hw.init->name)
> @@ -175,6 +176,9 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
> case S2MPS11X:
> s2mps11_reg = S2MPS11_REG_RTC_CTRL;
> break;
> +   case S5M8767X:
> +   s2mps11_reg = S5M8767_REG_CTRL1;
> +   break;
> default:
> dev_err(>dev, "Invalid device type\n");
> return -EINVAL;
> @@ -254,6 +258,7 @@ static int s2mps11_clk_remove(struct platform_device 
> *pdev)
>
>  static const struct platform_device_id s2mps11_clk_id[] = {
> { "s2mps11-clk", S2MPS11X},
> +   { "s5m8767-clk", S5M8767X},
> { },
>  };
>  MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
> --
> 1.7.9.5
>
>
> ___
> linux-arm-kernel mailing list
> linux-arm-ker...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/4] clk: clk-s2mps11: Refactor for including support for other MFD clocks

2013-11-11 Thread Yadwinder Singh Brar
On Thu, Oct 31, 2013 at 3:48 PM, Tushar Behera  wrote:
> The clocks in S2MPS11 and S5M8767 are managed in the same way, baring
> a difference in the register offset. It would be better to update
> existing S2MPS11 driver to support the clocks in S5M8767, rather than
> creating an almost duplicate driver altogether.
>
> Signed-off-by: Tushar Behera 
> CC: Yadwinder Singh Brar 
> CC: Mike Turquette 
> ---

Reviewed-by: Yadwinder Singh Brar 

Regards,
Yadwinder

>  drivers/clk/clk-s2mps11.c |   20 
>  1 file changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
> index 7be41e6..2262cb4 100644
> --- a/drivers/clk/clk-s2mps11.c
> +++ b/drivers/clk/clk-s2mps11.c
> @@ -48,6 +48,7 @@ struct s2mps11_clk {
> struct clk_lookup *lookup;
> u32 mask;
> bool enabled;
> +   unsigned int reg;
>  };
>
>  static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
> @@ -61,7 +62,7 @@ static int s2mps11_clk_prepare(struct clk_hw *hw)
> int ret;
>
> ret = regmap_update_bits(s2mps11->iodev->regmap,
> -   S2MPS11_REG_RTC_CTRL,
> +s2mps11->reg,
>  s2mps11->mask, s2mps11->mask);
> if (!ret)
> s2mps11->enabled = true;
> @@ -74,7 +75,7 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw)
> struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
> int ret;
>
> -   ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL,
> +   ret = regmap_update_bits(s2mps11->iodev->regmap, s2mps11->reg,
>s2mps11->mask, ~s2mps11->mask);
>
> if (!ret)
> @@ -155,6 +156,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
> struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
> struct s2mps11_clk *s2mps11_clks, *s2mps11_clk;
> struct device_node *clk_np = NULL;
> +   unsigned int s2mps11_reg;
> int i, ret = 0;
> u32 val;
>
> @@ -169,13 +171,23 @@ static int s2mps11_clk_probe(struct platform_device 
> *pdev)
> if (IS_ERR(clk_np))
> return PTR_ERR(clk_np);
>
> +   switch(platform_get_device_id(pdev)->driver_data) {
> +   case S2MPS11X:
> +   s2mps11_reg = S2MPS11_REG_RTC_CTRL;
> +   break;
> +   default:
> +   dev_err(>dev, "Invalid device type\n");
> +   return -EINVAL;
> +   };
> +
> for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) {
> s2mps11_clk->iodev = iodev;
> s2mps11_clk->hw.init = _clks_init[i];
> s2mps11_clk->mask = 1 << i;
> +   s2mps11_clk->reg = s2mps11_reg;
>
> ret = regmap_read(s2mps11_clk->iodev->regmap,
> - S2MPS11_REG_RTC_CTRL, );
> + s2mps11_clk->reg, );
> if (ret < 0)
> goto err_reg;
>
> @@ -241,7 +253,7 @@ static int s2mps11_clk_remove(struct platform_device 
> *pdev)
>  }
>
>  static const struct platform_device_id s2mps11_clk_id[] = {
> -   { "s2mps11-clk", 0},
> +   { "s2mps11-clk", S2MPS11X},
> { },
>  };
>  MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" 
> in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/4] clk: clk-s2mps11: Refactor for including support for other MFD clocks

2013-11-11 Thread Yadwinder Singh Brar
On Thu, Oct 31, 2013 at 3:48 PM, Tushar Behera tushar.beh...@linaro.org wrote:
 The clocks in S2MPS11 and S5M8767 are managed in the same way, baring
 a difference in the register offset. It would be better to update
 existing S2MPS11 driver to support the clocks in S5M8767, rather than
 creating an almost duplicate driver altogether.

 Signed-off-by: Tushar Behera tushar.beh...@linaro.org
 CC: Yadwinder Singh Brar yadi.b...@samsung.com
 CC: Mike Turquette mturque...@linaro.org
 ---

Reviewed-by: Yadwinder Singh Brar yadi.b...@samsung.com

Regards,
Yadwinder

  drivers/clk/clk-s2mps11.c |   20 
  1 file changed, 16 insertions(+), 4 deletions(-)

 diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
 index 7be41e6..2262cb4 100644
 --- a/drivers/clk/clk-s2mps11.c
 +++ b/drivers/clk/clk-s2mps11.c
 @@ -48,6 +48,7 @@ struct s2mps11_clk {
 struct clk_lookup *lookup;
 u32 mask;
 bool enabled;
 +   unsigned int reg;
  };

  static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
 @@ -61,7 +62,7 @@ static int s2mps11_clk_prepare(struct clk_hw *hw)
 int ret;

 ret = regmap_update_bits(s2mps11-iodev-regmap,
 -   S2MPS11_REG_RTC_CTRL,
 +s2mps11-reg,
  s2mps11-mask, s2mps11-mask);
 if (!ret)
 s2mps11-enabled = true;
 @@ -74,7 +75,7 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw)
 struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
 int ret;

 -   ret = regmap_update_bits(s2mps11-iodev-regmap, S2MPS11_REG_RTC_CTRL,
 +   ret = regmap_update_bits(s2mps11-iodev-regmap, s2mps11-reg,
s2mps11-mask, ~s2mps11-mask);

 if (!ret)
 @@ -155,6 +156,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev-dev.parent);
 struct s2mps11_clk *s2mps11_clks, *s2mps11_clk;
 struct device_node *clk_np = NULL;
 +   unsigned int s2mps11_reg;
 int i, ret = 0;
 u32 val;

 @@ -169,13 +171,23 @@ static int s2mps11_clk_probe(struct platform_device 
 *pdev)
 if (IS_ERR(clk_np))
 return PTR_ERR(clk_np);

 +   switch(platform_get_device_id(pdev)-driver_data) {
 +   case S2MPS11X:
 +   s2mps11_reg = S2MPS11_REG_RTC_CTRL;
 +   break;
 +   default:
 +   dev_err(pdev-dev, Invalid device type\n);
 +   return -EINVAL;
 +   };
 +
 for (i = 0; i  S2MPS11_CLKS_NUM; i++, s2mps11_clk++) {
 s2mps11_clk-iodev = iodev;
 s2mps11_clk-hw.init = s2mps11_clks_init[i];
 s2mps11_clk-mask = 1  i;
 +   s2mps11_clk-reg = s2mps11_reg;

 ret = regmap_read(s2mps11_clk-iodev-regmap,
 - S2MPS11_REG_RTC_CTRL, val);
 + s2mps11_clk-reg, val);
 if (ret  0)
 goto err_reg;

 @@ -241,7 +253,7 @@ static int s2mps11_clk_remove(struct platform_device 
 *pdev)
  }

  static const struct platform_device_id s2mps11_clk_id[] = {
 -   { s2mps11-clk, 0},
 +   { s2mps11-clk, S2MPS11X},
 { },
  };
  MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
 --
 1.7.9.5

 --
 To unsubscribe from this list: send the line unsubscribe linux-samsung-soc 
 in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/4] clk: clk-s2mps11: Add support for clocks in S5M8767 MFD

2013-11-11 Thread Yadwinder Singh Brar
On Thu, Oct 31, 2013 at 3:48 PM, Tushar Behera tushar.beh...@linaro.org wrote:
 Since clock operation within S2MPS11 and S5M8767 are similar, we can
 support both the devices within a single driver.

 Signed-off-by: Tushar Behera tushar.beh...@linaro.org
 CC: Yadwinder Singh Brar yadi.b...@samsung.com
 CC: Mike Turquette mturque...@linaro.org
 ---

Reviewed-by: Yadwinder Singh Brar yadi.b...@samsung.com

Regards,
Yadwinder

  drivers/clk/Kconfig   |6 --
  drivers/clk/clk-s2mps11.c |5 +
  2 files changed, 9 insertions(+), 2 deletions(-)

 diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
 index 5c51115..7f2aef2 100644
 --- a/drivers/clk/Kconfig
 +++ b/drivers/clk/Kconfig
 @@ -65,10 +65,12 @@ config COMMON_CLK_SI5351
   generators.

  config COMMON_CLK_S2MPS11
 -   tristate Clock driver for S2MPS11 MFD
 +   tristate Clock driver for S2MPS11/S5M8767 MFD
 depends on MFD_SEC_CORE
 ---help---
 - This driver supports S2MPS11 crystal oscillator clock.
 + This driver supports S2MPS11/S5M8767 crystal oscillator clock. These
 + multi-function devices have 3 fixed-rate oscillators, clocked at
 + 32KHz each.

  config CLK_TWL6040
 tristate External McPDM functional clock from twl6040
 diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
 index 2262cb4..19c075c 100644
 --- a/drivers/clk/clk-s2mps11.c
 +++ b/drivers/clk/clk-s2mps11.c
 @@ -27,6 +27,7 @@
  #include linux/clk-provider.h
  #include linux/platform_device.h
  #include linux/mfd/samsung/s2mps11.h
 +#include linux/mfd/samsung/s5m8767.h
  #include linux/mfd/samsung/core.h

  #define s2mps11_name(a) (a-hw.init-name)
 @@ -175,6 +176,9 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
 case S2MPS11X:
 s2mps11_reg = S2MPS11_REG_RTC_CTRL;
 break;
 +   case S5M8767X:
 +   s2mps11_reg = S5M8767_REG_CTRL1;
 +   break;
 default:
 dev_err(pdev-dev, Invalid device type\n);
 return -EINVAL;
 @@ -254,6 +258,7 @@ static int s2mps11_clk_remove(struct platform_device 
 *pdev)

  static const struct platform_device_id s2mps11_clk_id[] = {
 { s2mps11-clk, S2MPS11X},
 +   { s5m8767-clk, S5M8767X},
 { },
  };
  MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
 --
 1.7.9.5


 ___
 linux-arm-kernel mailing list
 linux-arm-ker...@lists.infradead.org
 http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC 0/4] Add basic support for ASV

2013-11-11 Thread Yadwinder Singh Brar
gentle ping for suggestions/reviews ..


On Wed, Sep 11, 2013 at 8:14 PM, Yadwinder Singh Brar
yadi.b...@samsung.com wrote:
 This series is to add basic common infrastructure for ASV.
  Basically ASV is a technique used on samsung SoCs, which provides the
 recommended supply voltage for dvfs of arm, mif etc. For a given operating
 frequency, the voltage is recommended based on SoC's ASV group.
 ASV group gets fussed on SoCs during process of mass production.

 This series includes:
  - basic common infrastructue for ASV. It provides common APIs for user 
 drivers
 like cpufreq  devfreq and and an interface for SoC specific drivers to
 register ASV members(instances)
  - a common platform driver to register ASV members for exynos SoCs
  - an example providing minimal support (only for ARM ASV) for exynos5250 
 chips

 Its just basic skelton which I wanted to get it reviewed or discussed in
 early stage, before going ahead on further development based on it.
  Presently example is based on static ASV table provided in SoC specific file,
 which I expects to go into DT. But exactly how and where needs to be 
 discussed,
 may be in next revisions once we get through the basic skelton.
  Also the location of driver in kernel may also seem odd to someone and
 many more things :).

 Looking for your valuable reviews and suggestions.

 Thanks

 Yadwinder Singh Brar (4):
   power: asv: Add common ASV support for samsung SoCs
   power: asv: Add a common asv driver for exynos SoCs.
   power: asv: Add support for exynos5250
   arm: exynos5: Register static platform device for ASV.

  arch/arm/mach-exynos/mach-exynos5-dt.c   |3 +
  drivers/power/Kconfig|1 +
  drivers/power/Makefile   |1 +
  drivers/power/asv/Kconfig|   24 
  drivers/power/asv/Makefile   |2 +
  drivers/power/asv/exynos-asv.c   |   81 ++
  drivers/power/asv/exynos-asv.h   |   22 
  drivers/power/asv/exynos5250-asv.c   |  141 
  drivers/power/asv/samsung-asv.c  |  175 
 ++
  include/linux/power/samsung-asv-driver.h |   61 +++
  include/linux/power/samsung-asv.h|   37 +++
  11 files changed, 548 insertions(+), 0 deletions(-)
  create mode 100644 drivers/power/asv/Kconfig
  create mode 100644 drivers/power/asv/Makefile
  create mode 100644 drivers/power/asv/exynos-asv.c
  create mode 100644 drivers/power/asv/exynos-asv.h
  create mode 100644 drivers/power/asv/exynos5250-asv.c
  create mode 100644 drivers/power/asv/samsung-asv.c
  create mode 100644 include/linux/power/samsung-asv-driver.h
  create mode 100644 include/linux/power/samsung-asv.h


 ___
 linux-arm-kernel mailing list
 linux-arm-ker...@lists.infradead.org
 http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 0/2] cpufreq: exynos: Fixes for v3.12

2013-10-11 Thread Yadwinder Singh Brar
On Wed, Oct 9, 2013 at 5:38 PM, Lukasz Majewski  wrote:
> Attached commits provide cpufreq regression fixes for Trats and Trats2
> Exynos4 boards.
> Since v3.12 Exynos4 uses common clock framework for clock manipulation.
> Those patches restore correct output for cpuinfo_cur_freq [1] sysfs
> attribute.
> Without them, the [1] provides default frequency (800 MHz) set at driver
> initialization.
>
>
> Lukasz Majewski (2):
>   cpufreq: exynos4x12: Use the common clock framework to set APLL clock
> rate
>   cpufreq: exynos4210: Use the common clock framework to set APLL clock
> rate
>

Just as a fix for 3.12, these patches looks OK to me.

Reviewed-by: Yadwinder Singh Brar 


Regards,
Yadwinder

>  drivers/cpufreq/exynos4210-cpufreq.c |   67 -
>  drivers/cpufreq/exynos4x12-cpufreq.c |   69 
> --
>  2 files changed, 16 insertions(+), 120 deletions(-)
>
> --
> 1.7.10.4
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 0/2] cpufreq: exynos: Fixes for v3.12

2013-10-11 Thread Yadwinder Singh Brar
On Wed, Oct 9, 2013 at 5:38 PM, Lukasz Majewski l.majew...@samsung.com wrote:
 Attached commits provide cpufreq regression fixes for Trats and Trats2
 Exynos4 boards.
 Since v3.12 Exynos4 uses common clock framework for clock manipulation.
 Those patches restore correct output for cpuinfo_cur_freq [1] sysfs
 attribute.
 Without them, the [1] provides default frequency (800 MHz) set at driver
 initialization.


 Lukasz Majewski (2):
   cpufreq: exynos4x12: Use the common clock framework to set APLL clock
 rate
   cpufreq: exynos4210: Use the common clock framework to set APLL clock
 rate


Just as a fix for 3.12, these patches looks OK to me.

Reviewed-by: Yadwinder Singh Brar yadi.b...@samsung.com


Regards,
Yadwinder

  drivers/cpufreq/exynos4210-cpufreq.c |   67 -
  drivers/cpufreq/exynos4x12-cpufreq.c |   69 
 --
  2 files changed, 16 insertions(+), 120 deletions(-)

 --
 1.7.10.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] clk: samsung: Add clock driver for s5pc100

2013-09-27 Thread Yadwinder Singh Brar
Hi Tomasz,

On Thu, Sep 26, 2013 at 7:30 PM, Tomasz Figa  wrote:
> Hi Yadwinder,
>
> I haven't reviewed this series yet, but let me clarify some things from
> your comments.
>
> On Thursday 26 of September 2013 17:38:58 Yadwinder Singh Brar wrote:
>> > +
>> > +/* Helper macros to define clock arrays. */
>> > +#define FIXED_RATE_CLOCKS(name)\
>> > +   static struct samsung_fixed_rate_clock name[]
>> > +#define MUX_CLOCKS(name)   \
>> > +   static struct samsung_mux_clock name[]
>> > +#define DIV_CLOCKS(name)   \
>> > +   static struct samsung_div_clock name[]
>> > +#define GATE_CLOCKS(name)  \
>> > +   static struct samsung_gate_clock name[]
>> > +
>>
>> These macros seems little bit odd in our common practice,
>> perhaps these are making code harder to read below.
>>
>
> They allow array declaration to fit into single line. I agree that it is
> not particularly easy to read at first sight, but shouldn't really be
> much of nuisance.

Defining a macro just to use once/twice, especially hiding the
definition of some array, doesn't looks justified.

>In addition, most of this driver is based on macros
> like this, e.g. GATE(), MUX(), PNAME(), etc.
>
>> > +PNAME(mout_i2s_2_p) = {
>> > +   "fout_epll",
>> > +   "i2scdclk0",
>> > +   "dout_audio0",
>> > +   "none"
>> > +};
>> > +
>>
>> Using one line per parent isn't increasing length of file unnecessarily?
>
> I believe this improves readability. Do we really care about size of
> source code that much, over readability?
>

yes, its looks little bit clean but in this case I felt, its making
the traversability in file difficult due to length of file.

>> > +   ALIAS(SCLK_AUDIO0, "soc-audio.0", "sclk_audio"),
>> > +   ALIAS(SCLK_AUDIO1, "soc-audio.1", "sclk_audio"),
>> > +   ALIAS(SCLK_AUDIO2, "soc-audio.2", "sclk_audio"),
>> > +   ALIAS(KEYIF, NULL, "keypad"),
>> > +
>> > +   ALIAS(MFC, "s5p-mfc", "sclk_mfc"),
>> > +   ALIAS(G2D, "s5p-g2d", "fimg2d"),
>> > +
>> > +};
>> > +
>>
>> Any reason/hidden advantage for using a separate of ALIAS,
>> instead of using MUX_A/GATE_A ?
>
> Yes, not even hidden. Alias is not a property of clock. One clock can
> have multiple aliases, e.g. the same clock being input to multiple
> devices.
>

Yes, its required if same clk has different alias for different devices,
but while using same alias for different(all, in this case) devices,
doesn't seems advantageous.

Regards,
Yadwinder
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] clk: samsung: Add clock driver for s5pc100

2013-09-27 Thread Yadwinder Singh Brar
Hi Tomasz,

On Thu, Sep 26, 2013 at 7:30 PM, Tomasz Figa t.f...@samsung.com wrote:
 Hi Yadwinder,

 I haven't reviewed this series yet, but let me clarify some things from
 your comments.

 On Thursday 26 of September 2013 17:38:58 Yadwinder Singh Brar wrote:
  +
  +/* Helper macros to define clock arrays. */
  +#define FIXED_RATE_CLOCKS(name)\
  +   static struct samsung_fixed_rate_clock name[]
  +#define MUX_CLOCKS(name)   \
  +   static struct samsung_mux_clock name[]
  +#define DIV_CLOCKS(name)   \
  +   static struct samsung_div_clock name[]
  +#define GATE_CLOCKS(name)  \
  +   static struct samsung_gate_clock name[]
  +

 These macros seems little bit odd in our common practice,
 perhaps these are making code harder to read below.


 They allow array declaration to fit into single line. I agree that it is
 not particularly easy to read at first sight, but shouldn't really be
 much of nuisance.

Defining a macro just to use once/twice, especially hiding the
definition of some array, doesn't looks justified.

In addition, most of this driver is based on macros
 like this, e.g. GATE(), MUX(), PNAME(), etc.

  +PNAME(mout_i2s_2_p) = {
  +   fout_epll,
  +   i2scdclk0,
  +   dout_audio0,
  +   none
  +};
  +

 Using one line per parent isn't increasing length of file unnecessarily?

 I believe this improves readability. Do we really care about size of
 source code that much, over readability?


yes, its looks little bit clean but in this case I felt, its making
the traversability in file difficult due to length of file.

  +   ALIAS(SCLK_AUDIO0, soc-audio.0, sclk_audio),
  +   ALIAS(SCLK_AUDIO1, soc-audio.1, sclk_audio),
  +   ALIAS(SCLK_AUDIO2, soc-audio.2, sclk_audio),
  +   ALIAS(KEYIF, NULL, keypad),
  +
  +   ALIAS(MFC, s5p-mfc, sclk_mfc),
  +   ALIAS(G2D, s5p-g2d, fimg2d),
  +
  +};
  +

 Any reason/hidden advantage for using a separate of ALIAS,
 instead of using MUX_A/GATE_A ?

 Yes, not even hidden. Alias is not a property of clock. One clock can
 have multiple aliases, e.g. the same clock being input to multiple
 devices.


Yes, its required if same clk has different alias for different devices,
but while using same alias for different(all, in this case) devices,
doesn't seems advantageous.

Regards,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] clk: samsung: Add clock driver for s5pc100

2013-09-26 Thread Yadwinder Singh Brar
Hi Mateusz,


After a quick view, just few things regarding coding styles.

[...]
> +#defineGENERAL_STATUS  0x0104
> +#defineCAM_MUX_SEL 0x0300
> +#defineMIXER_OUT_SEL   0x0304
> +#defineLPMP3_MODE_SEL  0x0308
> +#define MIPI_PHY_CON0  0x0400
> +#define MIPI_PHY_CON1  0x0414
> +#define HDMI_PHY_CON0  0x0420

How about aligning all above with same no. of tabs?

> +
> +/* Helper macros to define clock arrays. */
> +#define FIXED_RATE_CLOCKS(name)\
> +   static struct samsung_fixed_rate_clock name[]
> +#define MUX_CLOCKS(name)   \
> +   static struct samsung_mux_clock name[]
> +#define DIV_CLOCKS(name)   \
> +   static struct samsung_div_clock name[]
> +#define GATE_CLOCKS(name)  \
> +   static struct samsung_gate_clock name[]
> +

These macros seems little bit odd in our common practice,
perhaps these are making code harder to read below.

> +/* Helper macros for gate types present on S5PC100. */
> +#define GATE_BUS(_id, cname, pname, o, b) \
> +   GATE(_id, cname, pname, o, b, 0, 0)
> +#define GATE_SCLK(_id, cname, pname, o, b) \
> +   GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0)
> +#define GATE_ON(_id, cname, pname, o, b) \
> +   GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
> +
[...]
> +PNAME(mout_hclk_2_p) = {
> +   "fout_epll",
> +   "i2scdclk0"
> +};
> +
> +PNAME(mout_i2s_2_p) = {
> +   "fout_epll",
> +   "i2scdclk0",
> +   "dout_audio0",
> +   "none"
> +};
> +

Using one line per parent isn't increasing length of file unnecessarily?

[ ... ]
> +
> +/* list of all parent clock list */
> +static struct samsung_clock_alias s5pc100_clock_aliases[] = {
> +   ALIAS(FIMC0, "s5pc100-fimc.0", "fimc"),
> +   ALIAS(FIMC1, "s5pc100-fimc.1", "fimc"),
> +   ALIAS(FIMC2, "s5pc100-fimc.2", "fimc"),
> +   ALIAS(MOUT_FIMC2, NULL, "mout_fimc2"),
> +   ALIAS(MOUT_FIMC1, NULL, "mout_fimc1"),
> +   ALIAS(MOUT_FIMC0, NULL, "mout_fimc0"),
> +   ALIAS(SCLK_FIMC0, "s5pc100-fimc.0", "sclk_fimc"),
> +   ALIAS(SCLK_FIMC1, "s5pc100-fimc.1", "sclk_fimc"),
> +   ALIAS(SCLK_FIMC2, "s5pc100-fimc.2", "sclk_fimc"),
> +
> +   ALIAS(MOUT_APLL, NULL, "mout_apll"),
> +   ALIAS(MOUT_MPLL, NULL, "mout_mpll"),
> +   ALIAS(MOUT_EPLL, NULL, "mout_epll"),
> +   ALIAS(MOUT_HPLL, NULL, "mout_hpll"),
> +   ALIAS(MOUT_HPLL, NULL, "sclk_hpll"),
> +   ALIAS(UART0, "s3c6400-uart.0", "uart"),
> +   ALIAS(UART1, "s3c6400-uart.1", "uart"),
> +   ALIAS(UART2, "s3c6400-uart.2", "uart"),
> +   ALIAS(UART3, "s3c6400-uart.3", "uart"),
> +   ALIAS(UART0, "s3c6400-uart.0", "clk_uart_baud0"),
> +   ALIAS(UART1, "s3c6400-uart.1", "clk_uart_baud0"),
> +   ALIAS(UART2, "s3c6400-uart.2", "clk_uart_baud0"),
> +   ALIAS(UART3, "s3c6400-uart.3", "clk_uart_baud0"),
> +   ALIAS(UART0, "s3c6400-uart.0", "clk_uart_baud2"),
> +   ALIAS(UART1, "s3c6400-uart.1", "clk_uart_baud2"),
> +   ALIAS(UART2, "s3c6400-uart.2", "clk_uart_baud2"),
> +   ALIAS(UART3, "s3c6400-uart.3", "clk_uart_baud2"),
> +   ALIAS(SCLK_UART, "s3c6400-uart.0", "clk_uart_baud3"),
> +   ALIAS(SCLK_UART, "s3c6400-uart.1", "clk_uart_baud3"),
> +   ALIAS(SCLK_UART, "s3c6400-uart.2", "clk_uart_baud3"),
> +   ALIAS(SCLK_UART, "s3c6400-uart.3", "clk_uart_baud3"),
> +
> +   ALIAS(HSMMC0, "s3c-sdhci.0", "hsmmc"),
> +   ALIAS(HSMMC1, "s3c-sdhci.1", "hsmmc"),
> +   ALIAS(HSMMC2, "s3c-sdhci.2", "hsmmc"),
> +   ALIAS(HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
> +   ALIAS(HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
> +   ALIAS(HSMMC2, "s3c-sdhci.2", "mmc_busclk.0"),
> +   ALIAS(SCLK_MMC0, "s3c-sdhci.0", "mmc_busclk.2"),
> +   ALIAS(SCLK_MMC1, "s3c-sdhci.1", "mmc_busclk.2"),
> +   ALIAS(SCLK_MMC2, "s3c-sdhci.2", "mmc_busclk.2"),
> +   ALIAS(SCLK_MMC0_48, "s3c-sdhci.0", "mmc_busclk.3"),
> +   ALIAS(SCLK_MMC1_48, "s3c-sdhci.1", "mmc_busclk.3"),
> +   ALIAS(SCLK_MMC2_48, "s3c-sdhci.2", "mmc_busclk.3"),
> +
> +   ALIAS(SPI0, "s5pc100-spi.0", "spi"),
> +   ALIAS(SPI1, "s5pc100-spi.1", "spi"),
> +   ALIAS(SPI2, "s5pc100-spi.2", "spi"),
> +   ALIAS(SPI0, "s5pc100-spi.0", "spi_busclk0"),
> +   ALIAS(SPI1, "s5pc100-spi.1", "spi_busclk0"),
> +   ALIAS(SPI2, "s5pc100-spi.2", "spi_busclk0"),
> +   ALIAS(SCLK_SPI0_48, "s5pc100-spi.0", "spi_busclk1"),
> +   ALIAS(SCLK_SPI1_48, "s5pc100-spi.1", "spi_busclk1"),
> +   ALIAS(SCLK_SPI2_48, "s5pc100-spi.2", "spi_busclk1"),
> +   ALIAS(SCLK_SPI0, "s5pc100-spi.0", "spi_busclk2"),
> +   ALIAS(SCLK_SPI1, "s5pc100-spi.1", "spi_busclk2"),
> +   ALIAS(SCLK_SPI2, "s5pc100-spi.2", "spi_busclk2"),
> +   ALIAS(PDMA0, "dma-pl330.0", "apb_pclk"),
> +   ALIAS(PDMA1, "dma-pl330.1", "apb_pclk"),
> +   ALIAS(PWM, NULL, "timers"),
> +
> +   ALIAS(JPEG, NULL, 

Re: [PATCH 1/2] cpufreq: exynos4x12: Use the common clock framework to set APLL clock rate

2013-09-26 Thread Yadwinder Singh Brar
Hi Tomasz,

>> On Wed, Sep 25, 2013 at 4:52 PM, Lukasz Majewski  
>> wrote:
>> > In the exynos4x12_set_apll() function, the APLL frequency is set with
>> > direct register manipulation.
>> >
>> > Such approach is not allowed in the common clock framework. The frequency
>> > is changed, but the corresponding clock value is not updated. This causes
>> > wrong frequency read from cpufreq's cpuinfo_cur_freq sysfs attribute.
>> >
>>
>> This patch looks incomplete, leaving the driver in untidy state, perhaps its
>> doesn't fix the above stated problem completely. what about
>> if (!exynos4x12_pms_change(old_index, new_index)) becomes true?
>>
>> IMHO, this driver needs lot more work in addition to this patch to cleanly 
>> and
>> completely move the cpufreq driver to common clock framework.
>
> I agree that the other case needs to be handled as well. Basically the
> whole conditional block dependent on exynos4x12_pms_change() can be safely
> dropped, because this condition is already handled in PLL driver.
>

Exactly!

> Lukasz is already working on further rework of this driver to clean it up
> from legacy code, but this will have to wait for 3.13, as 3.12 is already
> in rc stage and only fixes can be accepted for it.
>
>> For fixing this issue urgently, setting CLK_GET_RATE_NOCACHE for apll
>> in clk driver can also be quicker fix.
>
> Unfortunately this is not how this flag works. It only makes
> clk_get_rate() call ->recalc_rate() operation of the clock instead of
> instantly returning cached rate - it doesn't seem to work recursively.
>

hmm.. yes it can't help in our case as it recursively walks only the subtree
of clk but in our case we are changing rate of parent.

Regards,
Yadwinder
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] cpufreq: exynos4x12: Use the common clock framework to set APLL clock rate

2013-09-26 Thread Yadwinder Singh Brar
Hi Tomasz,

 On Wed, Sep 25, 2013 at 4:52 PM, Lukasz Majewski l.majew...@samsung.com 
 wrote:
  In the exynos4x12_set_apll() function, the APLL frequency is set with
  direct register manipulation.
 
  Such approach is not allowed in the common clock framework. The frequency
  is changed, but the corresponding clock value is not updated. This causes
  wrong frequency read from cpufreq's cpuinfo_cur_freq sysfs attribute.
 

 This patch looks incomplete, leaving the driver in untidy state, perhaps its
 doesn't fix the above stated problem completely. what about
 if (!exynos4x12_pms_change(old_index, new_index)) becomes true?

 IMHO, this driver needs lot more work in addition to this patch to cleanly 
 and
 completely move the cpufreq driver to common clock framework.

 I agree that the other case needs to be handled as well. Basically the
 whole conditional block dependent on exynos4x12_pms_change() can be safely
 dropped, because this condition is already handled in PLL driver.


Exactly!

 Lukasz is already working on further rework of this driver to clean it up
 from legacy code, but this will have to wait for 3.13, as 3.12 is already
 in rc stage and only fixes can be accepted for it.

 For fixing this issue urgently, setting CLK_GET_RATE_NOCACHE for apll
 in clk driver can also be quicker fix.

 Unfortunately this is not how this flag works. It only makes
 clk_get_rate() call -recalc_rate() operation of the clock instead of
 instantly returning cached rate - it doesn't seem to work recursively.


hmm.. yes it can't help in our case as it recursively walks only the subtree
of clk but in our case we are changing rate of parent.

Regards,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] clk: samsung: Add clock driver for s5pc100

2013-09-26 Thread Yadwinder Singh Brar
Hi Mateusz,


After a quick view, just few things regarding coding styles.

[...]
 +#defineGENERAL_STATUS  0x0104
 +#defineCAM_MUX_SEL 0x0300
 +#defineMIXER_OUT_SEL   0x0304
 +#defineLPMP3_MODE_SEL  0x0308
 +#define MIPI_PHY_CON0  0x0400
 +#define MIPI_PHY_CON1  0x0414
 +#define HDMI_PHY_CON0  0x0420

How about aligning all above with same no. of tabs?

 +
 +/* Helper macros to define clock arrays. */
 +#define FIXED_RATE_CLOCKS(name)\
 +   static struct samsung_fixed_rate_clock name[]
 +#define MUX_CLOCKS(name)   \
 +   static struct samsung_mux_clock name[]
 +#define DIV_CLOCKS(name)   \
 +   static struct samsung_div_clock name[]
 +#define GATE_CLOCKS(name)  \
 +   static struct samsung_gate_clock name[]
 +

These macros seems little bit odd in our common practice,
perhaps these are making code harder to read below.

 +/* Helper macros for gate types present on S5PC100. */
 +#define GATE_BUS(_id, cname, pname, o, b) \
 +   GATE(_id, cname, pname, o, b, 0, 0)
 +#define GATE_SCLK(_id, cname, pname, o, b) \
 +   GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0)
 +#define GATE_ON(_id, cname, pname, o, b) \
 +   GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
 +
[...]
 +PNAME(mout_hclk_2_p) = {
 +   fout_epll,
 +   i2scdclk0
 +};
 +
 +PNAME(mout_i2s_2_p) = {
 +   fout_epll,
 +   i2scdclk0,
 +   dout_audio0,
 +   none
 +};
 +

Using one line per parent isn't increasing length of file unnecessarily?

[ ... ]
 +
 +/* list of all parent clock list */
 +static struct samsung_clock_alias s5pc100_clock_aliases[] = {
 +   ALIAS(FIMC0, s5pc100-fimc.0, fimc),
 +   ALIAS(FIMC1, s5pc100-fimc.1, fimc),
 +   ALIAS(FIMC2, s5pc100-fimc.2, fimc),
 +   ALIAS(MOUT_FIMC2, NULL, mout_fimc2),
 +   ALIAS(MOUT_FIMC1, NULL, mout_fimc1),
 +   ALIAS(MOUT_FIMC0, NULL, mout_fimc0),
 +   ALIAS(SCLK_FIMC0, s5pc100-fimc.0, sclk_fimc),
 +   ALIAS(SCLK_FIMC1, s5pc100-fimc.1, sclk_fimc),
 +   ALIAS(SCLK_FIMC2, s5pc100-fimc.2, sclk_fimc),
 +
 +   ALIAS(MOUT_APLL, NULL, mout_apll),
 +   ALIAS(MOUT_MPLL, NULL, mout_mpll),
 +   ALIAS(MOUT_EPLL, NULL, mout_epll),
 +   ALIAS(MOUT_HPLL, NULL, mout_hpll),
 +   ALIAS(MOUT_HPLL, NULL, sclk_hpll),
 +   ALIAS(UART0, s3c6400-uart.0, uart),
 +   ALIAS(UART1, s3c6400-uart.1, uart),
 +   ALIAS(UART2, s3c6400-uart.2, uart),
 +   ALIAS(UART3, s3c6400-uart.3, uart),
 +   ALIAS(UART0, s3c6400-uart.0, clk_uart_baud0),
 +   ALIAS(UART1, s3c6400-uart.1, clk_uart_baud0),
 +   ALIAS(UART2, s3c6400-uart.2, clk_uart_baud0),
 +   ALIAS(UART3, s3c6400-uart.3, clk_uart_baud0),
 +   ALIAS(UART0, s3c6400-uart.0, clk_uart_baud2),
 +   ALIAS(UART1, s3c6400-uart.1, clk_uart_baud2),
 +   ALIAS(UART2, s3c6400-uart.2, clk_uart_baud2),
 +   ALIAS(UART3, s3c6400-uart.3, clk_uart_baud2),
 +   ALIAS(SCLK_UART, s3c6400-uart.0, clk_uart_baud3),
 +   ALIAS(SCLK_UART, s3c6400-uart.1, clk_uart_baud3),
 +   ALIAS(SCLK_UART, s3c6400-uart.2, clk_uart_baud3),
 +   ALIAS(SCLK_UART, s3c6400-uart.3, clk_uart_baud3),
 +
 +   ALIAS(HSMMC0, s3c-sdhci.0, hsmmc),
 +   ALIAS(HSMMC1, s3c-sdhci.1, hsmmc),
 +   ALIAS(HSMMC2, s3c-sdhci.2, hsmmc),
 +   ALIAS(HSMMC0, s3c-sdhci.0, mmc_busclk.0),
 +   ALIAS(HSMMC1, s3c-sdhci.1, mmc_busclk.0),
 +   ALIAS(HSMMC2, s3c-sdhci.2, mmc_busclk.0),
 +   ALIAS(SCLK_MMC0, s3c-sdhci.0, mmc_busclk.2),
 +   ALIAS(SCLK_MMC1, s3c-sdhci.1, mmc_busclk.2),
 +   ALIAS(SCLK_MMC2, s3c-sdhci.2, mmc_busclk.2),
 +   ALIAS(SCLK_MMC0_48, s3c-sdhci.0, mmc_busclk.3),
 +   ALIAS(SCLK_MMC1_48, s3c-sdhci.1, mmc_busclk.3),
 +   ALIAS(SCLK_MMC2_48, s3c-sdhci.2, mmc_busclk.3),
 +
 +   ALIAS(SPI0, s5pc100-spi.0, spi),
 +   ALIAS(SPI1, s5pc100-spi.1, spi),
 +   ALIAS(SPI2, s5pc100-spi.2, spi),
 +   ALIAS(SPI0, s5pc100-spi.0, spi_busclk0),
 +   ALIAS(SPI1, s5pc100-spi.1, spi_busclk0),
 +   ALIAS(SPI2, s5pc100-spi.2, spi_busclk0),
 +   ALIAS(SCLK_SPI0_48, s5pc100-spi.0, spi_busclk1),
 +   ALIAS(SCLK_SPI1_48, s5pc100-spi.1, spi_busclk1),
 +   ALIAS(SCLK_SPI2_48, s5pc100-spi.2, spi_busclk1),
 +   ALIAS(SCLK_SPI0, s5pc100-spi.0, spi_busclk2),
 +   ALIAS(SCLK_SPI1, s5pc100-spi.1, spi_busclk2),
 +   ALIAS(SCLK_SPI2, s5pc100-spi.2, spi_busclk2),
 +   ALIAS(PDMA0, dma-pl330.0, apb_pclk),
 +   ALIAS(PDMA1, dma-pl330.1, apb_pclk),
 +   ALIAS(PWM, NULL, timers),
 +
 +   ALIAS(JPEG, NULL, jpeg),
 +   ALIAS(MFC, s5p-mfc, mfc),
 +   ALIAS(TV, s5p-sdo, dac),
 +   ALIAS(MIXER, s5p-mixer, mixer),
 +   ALIAS(VP, s5p-mixer, vp),
 +   ALIAS(HDMI, s5p-hdmi, hdmi),
 +   ALIAS(SCLK_HDMI, s5p-hdmi, hdmiphy),
 +
 +   ALIAS(USB_OTG, NULL, otg),
 +   ALIAS(USB_HOST, NULL, usb-host),
 +  

Re: [PATCH 1/2] cpufreq: exynos4x12: Use the common clock framework to set APLL clock rate

2013-09-25 Thread Yadwinder Singh Brar
Hi Lukasz,

On Wed, Sep 25, 2013 at 4:52 PM, Lukasz Majewski  wrote:
> In the exynos4x12_set_apll() function, the APLL frequency is set with
> direct register manipulation.
>
> Such approach is not allowed in the common clock framework. The frequency
> is changed, but the corresponding clock value is not updated. This causes
> wrong frequency read from cpufreq's cpuinfo_cur_freq sysfs attribute.
>

This patch looks incomplete, leaving the driver in untidy state, perhaps its
doesn't fix the above stated problem completely. what about
if (!exynos4x12_pms_change(old_index, new_index)) becomes true?

IMHO, this driver needs lot more work in addition to this patch to cleanly and
completely move the cpufreq driver to common clock framework.

For fixing this issue urgently, setting CLK_GET_RATE_NOCACHE for apll
in clk driver can also be quicker fix.

Regards,
Yadwinder

> Tested at:
> - Exynos4412 - Trats2 board (linux 3.12-rc1)
>
> Signed-off-by: Lukasz Majewski 
> Reviewed-by: Bartlomiej Zolnierkiewicz 
> Reviewed-by: Tomasz Figa 
> ---
>  drivers/cpufreq/exynos4x12-cpufreq.c |   23 ---
>  1 file changed, 4 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c 
> b/drivers/cpufreq/exynos4x12-cpufreq.c
> index 08b7477..b2f51c9 100644
> --- a/drivers/cpufreq/exynos4x12-cpufreq.c
> +++ b/drivers/cpufreq/exynos4x12-cpufreq.c
> @@ -128,9 +128,9 @@ static void exynos4x12_set_clkdiv(unsigned int div_index)
>
>  static void exynos4x12_set_apll(unsigned int index)
>  {
> -   unsigned int tmp, pdiv;
> +   unsigned int tmp, freq = apll_freq_4x12[index].freq;
>
> -   /* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
> +   /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
> clk_set_parent(moutcore, mout_mpll);
>
> do {
> @@ -140,24 +140,9 @@ static void exynos4x12_set_apll(unsigned int index)
> tmp &= 0x7;
> } while (tmp != 0x2);
>
> -   /* 2. Set APLL Lock time */
> -   pdiv = ((apll_freq_4x12[index].mps >> 8) & 0x3f);
> +   clk_set_rate(mout_apll, freq * 1000);
>
> -   __raw_writel((pdiv * 250), EXYNOS4_APLL_LOCK);
> -
> -   /* 3. Change PLL PMS values */
> -   tmp = __raw_readl(EXYNOS4_APLL_CON0);
> -   tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
> -   tmp |= apll_freq_4x12[index].mps;
> -   __raw_writel(tmp, EXYNOS4_APLL_CON0);
> -
> -   /* 4. wait_lock_time */
> -   do {
> -   cpu_relax();
> -   tmp = __raw_readl(EXYNOS4_APLL_CON0);
> -   } while (!(tmp & (0x1 << EXYNOS4_APLLCON0_LOCKED_SHIFT)));
> -
> -   /* 5. MUX_CORE_SEL = APLL */
> +   /* MUX_CORE_SEL = APLL */
> clk_set_parent(moutcore, mout_apll);
>
> do {
> --
> 1.7.10.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" 
> in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] cpufreq: exynos4x12: Use the common clock framework to set APLL clock rate

2013-09-25 Thread Yadwinder Singh Brar
Hi Lukasz,

On Wed, Sep 25, 2013 at 4:52 PM, Lukasz Majewski l.majew...@samsung.com wrote:
 In the exynos4x12_set_apll() function, the APLL frequency is set with
 direct register manipulation.

 Such approach is not allowed in the common clock framework. The frequency
 is changed, but the corresponding clock value is not updated. This causes
 wrong frequency read from cpufreq's cpuinfo_cur_freq sysfs attribute.


This patch looks incomplete, leaving the driver in untidy state, perhaps its
doesn't fix the above stated problem completely. what about
if (!exynos4x12_pms_change(old_index, new_index)) becomes true?

IMHO, this driver needs lot more work in addition to this patch to cleanly and
completely move the cpufreq driver to common clock framework.

For fixing this issue urgently, setting CLK_GET_RATE_NOCACHE for apll
in clk driver can also be quicker fix.

Regards,
Yadwinder

 Tested at:
 - Exynos4412 - Trats2 board (linux 3.12-rc1)

 Signed-off-by: Lukasz Majewski l.majew...@samsung.com
 Reviewed-by: Bartlomiej Zolnierkiewicz b.zolnier...@samsung.com
 Reviewed-by: Tomasz Figa t.f...@samsung.com
 ---
  drivers/cpufreq/exynos4x12-cpufreq.c |   23 ---
  1 file changed, 4 insertions(+), 19 deletions(-)

 diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c 
 b/drivers/cpufreq/exynos4x12-cpufreq.c
 index 08b7477..b2f51c9 100644
 --- a/drivers/cpufreq/exynos4x12-cpufreq.c
 +++ b/drivers/cpufreq/exynos4x12-cpufreq.c
 @@ -128,9 +128,9 @@ static void exynos4x12_set_clkdiv(unsigned int div_index)

  static void exynos4x12_set_apll(unsigned int index)
  {
 -   unsigned int tmp, pdiv;
 +   unsigned int tmp, freq = apll_freq_4x12[index].freq;

 -   /* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
 +   /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
 clk_set_parent(moutcore, mout_mpll);

 do {
 @@ -140,24 +140,9 @@ static void exynos4x12_set_apll(unsigned int index)
 tmp = 0x7;
 } while (tmp != 0x2);

 -   /* 2. Set APLL Lock time */
 -   pdiv = ((apll_freq_4x12[index].mps  8)  0x3f);
 +   clk_set_rate(mout_apll, freq * 1000);

 -   __raw_writel((pdiv * 250), EXYNOS4_APLL_LOCK);
 -
 -   /* 3. Change PLL PMS values */
 -   tmp = __raw_readl(EXYNOS4_APLL_CON0);
 -   tmp = ~((0x3ff  16) | (0x3f  8) | (0x7  0));
 -   tmp |= apll_freq_4x12[index].mps;
 -   __raw_writel(tmp, EXYNOS4_APLL_CON0);
 -
 -   /* 4. wait_lock_time */
 -   do {
 -   cpu_relax();
 -   tmp = __raw_readl(EXYNOS4_APLL_CON0);
 -   } while (!(tmp  (0x1  EXYNOS4_APLLCON0_LOCKED_SHIFT)));
 -
 -   /* 5. MUX_CORE_SEL = APLL */
 +   /* MUX_CORE_SEL = APLL */
 clk_set_parent(moutcore, mout_apll);

 do {
 --
 1.7.10.4

 --
 To unsubscribe from this list: send the line unsubscribe linux-samsung-soc 
 in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC 4/4] arm: exynos5: Register static platform device for ASV.

2013-09-11 Thread Yadwinder Singh Brar
Since ASV is not a hardware controller so we cann't add device tree node for
it. This patch registers a static platform device exynos ASV.

Signed-off-by: Yadwinder Singh Brar 
---
 arch/arm/mach-exynos/mach-exynos5-dt.c |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c 
b/arch/arm/mach-exynos/mach-exynos5-dt.c
index f874b77..5ce58e1 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -28,6 +28,7 @@ static void __init exynos5_dt_machine_init(void)
struct device_node *i2c_np;
const char *i2c_compat = "samsung,s3c2440-i2c";
unsigned int tmp;
+   struct platform_device_info devinfo = { .name = "exynos-asv", };
 
/*
 * Exynos5's legacy i2c controller and new high speed i2c
@@ -48,6 +49,8 @@ static void __init exynos5_dt_machine_init(void)
}
 
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+   platform_device_register_full();
 }
 
 static char const *exynos5_dt_compat[] __initdata = {
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC 1/4] power: asv: Add common ASV support for samsung SoCs

2013-09-11 Thread Yadwinder Singh Brar
This patch introduces a common ASV(Adaptive Supply Voltage) basic framework
for samsung SoCs. It provides common APIs (to be called by users to get ASV
values or init opp_table) and an interface for SoC specific drivers to
register ASV members(instances).

Signed-off-by: Yadwinder Singh Brar 
---

Hopefully asv_get_volt() can go out in future, once all users start using OPP
library.

---
 drivers/power/Kconfig|1 +
 drivers/power/Makefile   |1 +
 drivers/power/asv/Kconfig|   11 ++
 drivers/power/asv/Makefile   |1 +
 drivers/power/asv/samsung-asv.c  |  175 ++
 include/linux/power/samsung-asv-driver.h |   61 +++
 include/linux/power/samsung-asv.h|   37 +++
 7 files changed, 287 insertions(+), 0 deletions(-)
 create mode 100644 drivers/power/asv/Kconfig
 create mode 100644 drivers/power/asv/Makefile
 create mode 100644 drivers/power/asv/samsung-asv.c
 create mode 100644 include/linux/power/samsung-asv-driver.h
 create mode 100644 include/linux/power/samsung-asv.h

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 7b8979c..2e6b087 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -367,3 +367,4 @@ source "drivers/power/reset/Kconfig"
 endif # POWER_SUPPLY
 
 source "drivers/power/avs/Kconfig"
+source "drivers/power/asv/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 653bf6c..da93c46 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)  += max8998_charger.o
 obj-$(CONFIG_CHARGER_BQ2415X)  += bq2415x_charger.o
 obj-$(CONFIG_POWER_AVS)+= avs/
+obj-$(CONFIG_POWER_ASV)+= asv/
 obj-$(CONFIG_CHARGER_SMB347)   += smb347-charger.o
 obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
 obj-$(CONFIG_POWER_RESET)  += reset/
diff --git a/drivers/power/asv/Kconfig b/drivers/power/asv/Kconfig
new file mode 100644
index 000..7cd84bd
--- /dev/null
+++ b/drivers/power/asv/Kconfig
@@ -0,0 +1,11 @@
+menuconfig POWER_ASV
+   bool "Adaptive Supply Voltage support"
+   help
+ ASV is a technique used on samsung SoCs, which provides the
+ recommended supply voltage for some specific parts(like arm, mif etc)
+ of SoCs which supports dvfs. For a given operating frequency, the
+ voltage is recommended based on SoCs ASV group.
+ ASV group info is provided in the chip id info which depends on chip
+ manufacturing process.
+
+ Say Y here to enable Adaptive Supply voltage support.
diff --git a/drivers/power/asv/Makefile b/drivers/power/asv/Makefile
new file mode 100644
index 000..62921da
--- /dev/null
+++ b/drivers/power/asv/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_POWER_ASV)+= asv.o
diff --git a/drivers/power/asv/asv.c b/drivers/power/asv/asv.c
new file mode 100644
index 000..61f4a83
--- /dev/null
+++ b/drivers/power/asv/asv.c
@@ -0,0 +1,175 @@
+/*
+ * ASV(Adaptive Supply Voltage) common core
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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.
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static LIST_HEAD(asv_list);
+static DEFINE_MUTEX(asv_mutex);
+
+struct asv_member {
+   struct list_headnode;
+   struct asv_info *asv_info;
+};
+
+static void add_asv_member(struct asv_member *asv_mem)
+{
+   mutex_lock(_mutex);
+   list_add_tail(_mem->node, _list);
+   mutex_unlock(_mutex);
+}
+
+static struct asv_member *asv_get_mem(enum asv_type_id asv_type)
+{
+   struct asv_member *asv_mem;
+   struct asv_info *asv_info;
+
+   list_for_each_entry(asv_mem, _list, node) {
+   asv_info = asv_mem->asv_info;
+   if (asv_type == asv_info->type)
+   return asv_mem;
+   }
+
+   return NULL;
+}
+
+unsigned int asv_get_volt(enum asv_type_id target_type,
+   unsigned int target_freq)
+{
+   struct asv_member *asv_mem = asv_get_mem(target_type);
+   struct asv_freq_table *dvfs_table;
+   struct asv_info *asv_info;
+   unsigned int i;
+
+   if (!asv_mem)
+   return 0;
+
+   asv_info = asv_mem->asv_info;
+   dvfs_table = asv_info->dvfs_table;
+
+   for (i = 0; i < asv_info->nr_dvfs_level; i++) {
+   if (dvfs_table[i].freq == target_freq)
+   return dvfs_table[i].volt;
+   }
+
+   return 0;
+}
+
+int asv_init_opp_table(struct device *dev, enum asv_type_id target_type)
+{
+   struct asv_member

[RFC 3/4] power: asv: Add support for exynos5250

2013-09-11 Thread Yadwinder Singh Brar
This patch adds basic support (only for ARM ASV) for exynos5250 chips which
have fused ASV group.

Signed-off-by: Yadwinder Singh Brar 
---
 drivers/power/asv/Makefile |2 +-
 drivers/power/asv/exynos-asv.c |9 +++
 drivers/power/asv/exynos-asv.h |1 +
 drivers/power/asv/exynos5250-asv.c |  141 
 4 files changed, 152 insertions(+), 1 deletions(-)
 create mode 100644 drivers/power/asv/exynos5250-asv.c

diff --git a/drivers/power/asv/Makefile b/drivers/power/asv/Makefile
index 9a94868..a471c8e 100644
--- a/drivers/power/asv/Makefile
+++ b/drivers/power/asv/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_POWER_ASV)+= asv.o
-obj-$(CONFIG_POWER_EXYNOS_ASV) += exynos-asv.o
+obj-$(CONFIG_POWER_EXYNOS_ASV) += exynos-asv.o exynos5250-asv.o
diff --git a/drivers/power/asv/exynos-asv.c b/drivers/power/asv/exynos-asv.c
index d3f43a4..7449b55 100644
--- a/drivers/power/asv/exynos-asv.c
+++ b/drivers/power/asv/exynos-asv.c
@@ -46,9 +46,18 @@ static int exynos_asv_probe(struct platform_device *pdev)
exynos_asv_info->base = base;
 
/* call SoC specific intialisation routine */
+   if (of_machine_is_compatible("samsung,exynos5250")) {
+   ret = exynos5250_asv_init(exynos_asv_info);
+   if (ret) {
+   pr_err("%s: exynos5250_asv_init failed : %d\n",
+   __func__, ret);
+   goto err;
+   }
+   }
 
register_asv_member(exynos_asv_info->asv_list, exynos_asv_info->nr_mem);
 
+err:
iounmap(base);
 err_map:
of_node_put(chip_id);
diff --git a/drivers/power/asv/exynos-asv.h b/drivers/power/asv/exynos-asv.h
index 89a1ae8..a31becb 100644
--- a/drivers/power/asv/exynos-asv.h
+++ b/drivers/power/asv/exynos-asv.h
@@ -18,4 +18,5 @@ struct exynos_asv_common {
void __iomem *base;
 };
 
+extern int exynos5250_asv_init(struct exynos_asv_common *exynos_info);
 #endif /* __EXYNOS_ASV_D_H */
diff --git a/drivers/power/asv/exynos5250-asv.c 
b/drivers/power/asv/exynos5250-asv.c
new file mode 100644
index 000..293b3f1
--- /dev/null
+++ b/drivers/power/asv/exynos5250-asv.c
@@ -0,0 +1,141 @@
+/* exynos5250 - ASV(Adaptive Supply Voltage)
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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.
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include "exynos-asv.h"
+
+#define FUSED_SG_OFFSET3
+#define ORIG_SG_OFFSET 17
+#define ORIG_SG_MASK   0xF
+#define MOD_SG_OFFSET  21
+#define MOD_SG_MASK0x7
+
+#define ARM_LEVEL_NR   16
+#define ARM_GRP_NR 12
+
+#define CHIP_ID_OFFSET 0x4
+
+struct exynos5250_asv_info {
+   unsigned int package_id;
+   /* we may need more info as global data */
+};
+
+static struct exynos5250_asv_info asv_group __initdata;
+
+static unsigned int asv_voltage[ARM_LEVEL_NR][ARM_GRP_NR + 1] __initdata = {
+   { 170, 130, 1275000, 1275000, 1262500, 125, 1225000,
+   1212500, 120, 1187500, 1175000, 115, 1125000 }, /* L0 */
+   { 160, 125, 1225000, 1225000, 1212500, 120, 1187500,
+   1175000, 1162500, 115, 1137500, 1112500, 110 }, /* L1 */
+   { 150, 1225000, 1187500, 1175000, 1162500, 115, 1137500,
+   1125000, 1112500, 110, 1087500, 1075000, 1062500 }, /* L2 */
+   { 140, 120, 1125000, 1125000, 1125000, 1112500, 110,
+   1087500, 1075000, 1062500, 105, 1037500, 1025000 }, /* L3 */
+   { 130, 115, 110, 110, 110, 1087500, 1075000,
+   1062500, 105, 1037500, 1025000, 1012500, 100 }, /* L4 */
+   { 120, 1125000, 1075000, 1075000, 1062500, 105, 1037500,
+   1025000, 1012500, 100,  987500,  975000,  975000 }, /* L5 */
+   { 110, 110, 105, 105, 1037500, 1025000, 1012500,
+   100,  987500,  975000,  962500,  95,  925000 }, /* L6 */
+   { 100, 1075000, 1037500, 1037500, 1012500, 100,  987500,
+   975000,  962500,  95,  937500,  925000,  912500 },  /* L7 */
+   { 90, 105, 1025000, 1012500,  987500,  975000,  962500,
+   95,  937500,  925000,  912500,  912500,  90 },  /* L8 */
+   { 80, 1025000, 100,  987500,  975000,  962500,  95,
+   937500,  925000,  912500,  90,  90,  90 },  /* L9 */
+   { 70, 1012500,  975000,  962500,  95,  937500,  925000,
+   912500,  90,  90,  90,  90,  90 },  /* L10 */
+   { 60, 100,  962500,  95,  937500,  925000,  912500,
+   90,  90,  90,  90,  90,  90 },  /* L11 */
+  

[RFC 2/4] power: asv: Add a common asv driver for exynos SoCs.

2013-09-11 Thread Yadwinder Singh Brar
This patch adds a common platform driver to register ASV members for exynos
SoCs.

Signed-off-by: Yadwinder Singh Brar 
---
 drivers/power/asv/Kconfig  |   13 +++
 drivers/power/asv/Makefile |1 +
 drivers/power/asv/exynos-asv.c |   72 
 drivers/power/asv/exynos-asv.h |   21 +++
 4 files changed, 107 insertions(+), 0 deletions(-)
 create mode 100644 drivers/power/asv/exynos-asv.c
 create mode 100644 drivers/power/asv/exynos-asv.h

diff --git a/drivers/power/asv/Kconfig b/drivers/power/asv/Kconfig
index 7cd84bd..6104b09 100644
--- a/drivers/power/asv/Kconfig
+++ b/drivers/power/asv/Kconfig
@@ -9,3 +9,16 @@ menuconfig POWER_ASV
  manufacturing process.
 
  Say Y here to enable Adaptive Supply voltage support.
+
+if POWER_ASV
+
+config POWER_EXYNOS_ASV
+   bool "Adaptive Supply Voltage for Exynos"
+   help
+ Exynos supports ASV depending upon the ASV group fused on chip.
+ Users can request ASV specific to a frequency for a particular member
+ from corresponding DVFS driver.
+
+ Say Y here to enable Exynos Adaptive Voltage Scaling.
+
+endif
diff --git a/drivers/power/asv/Makefile b/drivers/power/asv/Makefile
index 62921da..9a94868 100644
--- a/drivers/power/asv/Makefile
+++ b/drivers/power/asv/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_POWER_ASV)+= asv.o
+obj-$(CONFIG_POWER_EXYNOS_ASV) += exynos-asv.o
diff --git a/drivers/power/asv/exynos-asv.c b/drivers/power/asv/exynos-asv.c
new file mode 100644
index 000..d3f43a4
--- /dev/null
+++ b/drivers/power/asv/exynos-asv.c
@@ -0,0 +1,72 @@
+/* Common Exynos ASV(Adaptive Supply Voltage) driver
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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.
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "exynos-asv.h"
+
+static int exynos_asv_probe(struct platform_device *pdev)
+{
+   struct device_node *chip_id;
+   struct exynos_asv_common *exynos_asv_info;
+   void __iomem *base;
+   int ret = 0;
+
+   exynos_asv_info = kzalloc(sizeof(struct exynos_asv_common), GFP_KERNEL);
+   if (!exynos_asv_info)
+   return -ENOMEM;
+
+   chip_id = of_find_compatible_node(NULL, NULL,
+   "samsung,exynos4210-chipid");
+   if (!chip_id) {
+   pr_err("%s: unable to find chipid\n", __func__);
+   ret = -ENODEV;
+   goto err_node;
+   }
+
+   base = of_iomap(chip_id, 0);
+   if (!base) {
+   pr_err("%s: unable to map chip_id register\n", __func__);
+   ret = -ENOMEM;
+   goto err_map;
+   }
+
+   exynos_asv_info->base = base;
+
+   /* call SoC specific intialisation routine */
+
+   register_asv_member(exynos_asv_info->asv_list, exynos_asv_info->nr_mem);
+
+   iounmap(base);
+err_map:
+   of_node_put(chip_id);
+err_node:
+   kfree(exynos_asv_info);
+
+   return ret;
+}
+
+static struct platform_driver exynos_asv_platdrv = {
+   .driver = {
+   .name   = "exynos-asv",
+   .owner  = THIS_MODULE,
+   },
+   .probe  = exynos_asv_probe,
+};
+module_platform_driver(exynos_asv_platdrv);
+
+MODULE_AUTHOR("Yadwinder Singh Brar");
+MODULE_DESCRIPTION("Common Exynos ASV driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/asv/exynos-asv.h b/drivers/power/asv/exynos-asv.h
new file mode 100644
index 000..89a1ae8
--- /dev/null
+++ b/drivers/power/asv/exynos-asv.h
@@ -0,0 +1,21 @@
+/*
+ * Exynos - Adaptive Supply Voltage Driver Header File
+ *
+ * copyright (c) 2013 samsung electronics co., ltd.
+ * http://www.samsung.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.
+*/
+
+#ifndef __EXYNOS_ASV_D_H
+#define __EXYNOS_ASV_D_H __FILE__
+
+struct exynos_asv_common {
+   struct asv_info *asv_list;
+   unsigned int nr_mem;
+   void __iomem *base;
+};
+
+#endif /* __EXYNOS_ASV_D_H */
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC 0/4] Add basic support for ASV

2013-09-11 Thread Yadwinder Singh Brar
This series is to add basic common infrastructure for ASV.
 Basically ASV is a technique used on samsung SoCs, which provides the
recommended supply voltage for dvfs of arm, mif etc. For a given operating
frequency, the voltage is recommended based on SoC's ASV group.
ASV group gets fussed on SoCs during process of mass production.

This series includes:
 - basic common infrastructue for ASV. It provides common APIs for user drivers
like cpufreq & devfreq and and an interface for SoC specific drivers to
register ASV members(instances)
 - a common platform driver to register ASV members for exynos SoCs
 - an example providing minimal support (only for ARM ASV) for exynos5250 chips

Its just basic skelton which I wanted to get it reviewed or discussed in
early stage, before going ahead on further development based on it.
 Presently example is based on static ASV table provided in SoC specific file,
which I expects to go into DT. But exactly how and where needs to be discussed,
may be in next revisions once we get through the basic skelton.
 Also the location of driver in kernel may also seem odd to someone and
many more things :).

Looking for your valuable reviews and suggestions.

Thanks

Yadwinder Singh Brar (4):
  power: asv: Add common ASV support for samsung SoCs
  power: asv: Add a common asv driver for exynos SoCs.
  power: asv: Add support for exynos5250
  arm: exynos5: Register static platform device for ASV.

 arch/arm/mach-exynos/mach-exynos5-dt.c   |3 +
 drivers/power/Kconfig|1 +
 drivers/power/Makefile   |1 +
 drivers/power/asv/Kconfig|   24 
 drivers/power/asv/Makefile   |2 +
 drivers/power/asv/exynos-asv.c   |   81 ++
 drivers/power/asv/exynos-asv.h   |   22 
 drivers/power/asv/exynos5250-asv.c   |  141 
 drivers/power/asv/samsung-asv.c  |  175 ++
 include/linux/power/samsung-asv-driver.h |   61 +++
 include/linux/power/samsung-asv.h|   37 +++
 11 files changed, 548 insertions(+), 0 deletions(-)
 create mode 100644 drivers/power/asv/Kconfig
 create mode 100644 drivers/power/asv/Makefile
 create mode 100644 drivers/power/asv/exynos-asv.c
 create mode 100644 drivers/power/asv/exynos-asv.h
 create mode 100644 drivers/power/asv/exynos5250-asv.c
 create mode 100644 drivers/power/asv/samsung-asv.c
 create mode 100644 include/linux/power/samsung-asv-driver.h
 create mode 100644 include/linux/power/samsung-asv.h

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC 0/4] Add basic support for ASV

2013-09-11 Thread Yadwinder Singh Brar
This series is to add basic common infrastructure for ASV.
 Basically ASV is a technique used on samsung SoCs, which provides the
recommended supply voltage for dvfs of arm, mif etc. For a given operating
frequency, the voltage is recommended based on SoC's ASV group.
ASV group gets fussed on SoCs during process of mass production.

This series includes:
 - basic common infrastructue for ASV. It provides common APIs for user drivers
like cpufreq  devfreq and and an interface for SoC specific drivers to
register ASV members(instances)
 - a common platform driver to register ASV members for exynos SoCs
 - an example providing minimal support (only for ARM ASV) for exynos5250 chips

Its just basic skelton which I wanted to get it reviewed or discussed in
early stage, before going ahead on further development based on it.
 Presently example is based on static ASV table provided in SoC specific file,
which I expects to go into DT. But exactly how and where needs to be discussed,
may be in next revisions once we get through the basic skelton.
 Also the location of driver in kernel may also seem odd to someone and
many more things :).

Looking for your valuable reviews and suggestions.

Thanks

Yadwinder Singh Brar (4):
  power: asv: Add common ASV support for samsung SoCs
  power: asv: Add a common asv driver for exynos SoCs.
  power: asv: Add support for exynos5250
  arm: exynos5: Register static platform device for ASV.

 arch/arm/mach-exynos/mach-exynos5-dt.c   |3 +
 drivers/power/Kconfig|1 +
 drivers/power/Makefile   |1 +
 drivers/power/asv/Kconfig|   24 
 drivers/power/asv/Makefile   |2 +
 drivers/power/asv/exynos-asv.c   |   81 ++
 drivers/power/asv/exynos-asv.h   |   22 
 drivers/power/asv/exynos5250-asv.c   |  141 
 drivers/power/asv/samsung-asv.c  |  175 ++
 include/linux/power/samsung-asv-driver.h |   61 +++
 include/linux/power/samsung-asv.h|   37 +++
 11 files changed, 548 insertions(+), 0 deletions(-)
 create mode 100644 drivers/power/asv/Kconfig
 create mode 100644 drivers/power/asv/Makefile
 create mode 100644 drivers/power/asv/exynos-asv.c
 create mode 100644 drivers/power/asv/exynos-asv.h
 create mode 100644 drivers/power/asv/exynos5250-asv.c
 create mode 100644 drivers/power/asv/samsung-asv.c
 create mode 100644 include/linux/power/samsung-asv-driver.h
 create mode 100644 include/linux/power/samsung-asv.h

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC 2/4] power: asv: Add a common asv driver for exynos SoCs.

2013-09-11 Thread Yadwinder Singh Brar
This patch adds a common platform driver to register ASV members for exynos
SoCs.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/power/asv/Kconfig  |   13 +++
 drivers/power/asv/Makefile |1 +
 drivers/power/asv/exynos-asv.c |   72 
 drivers/power/asv/exynos-asv.h |   21 +++
 4 files changed, 107 insertions(+), 0 deletions(-)
 create mode 100644 drivers/power/asv/exynos-asv.c
 create mode 100644 drivers/power/asv/exynos-asv.h

diff --git a/drivers/power/asv/Kconfig b/drivers/power/asv/Kconfig
index 7cd84bd..6104b09 100644
--- a/drivers/power/asv/Kconfig
+++ b/drivers/power/asv/Kconfig
@@ -9,3 +9,16 @@ menuconfig POWER_ASV
  manufacturing process.
 
  Say Y here to enable Adaptive Supply voltage support.
+
+if POWER_ASV
+
+config POWER_EXYNOS_ASV
+   bool Adaptive Supply Voltage for Exynos
+   help
+ Exynos supports ASV depending upon the ASV group fused on chip.
+ Users can request ASV specific to a frequency for a particular member
+ from corresponding DVFS driver.
+
+ Say Y here to enable Exynos Adaptive Voltage Scaling.
+
+endif
diff --git a/drivers/power/asv/Makefile b/drivers/power/asv/Makefile
index 62921da..9a94868 100644
--- a/drivers/power/asv/Makefile
+++ b/drivers/power/asv/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_POWER_ASV)+= asv.o
+obj-$(CONFIG_POWER_EXYNOS_ASV) += exynos-asv.o
diff --git a/drivers/power/asv/exynos-asv.c b/drivers/power/asv/exynos-asv.c
new file mode 100644
index 000..d3f43a4
--- /dev/null
+++ b/drivers/power/asv/exynos-asv.c
@@ -0,0 +1,72 @@
+/* Common Exynos ASV(Adaptive Supply Voltage) driver
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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.
+*/
+
+#include linux/err.h
+#include linux/io.h
+#include linux/slab.h
+#include linux/of_address.h
+#include linux/module.h
+#include linux/platform_device.h
+#include linux/power/asv-driver.h
+#include exynos-asv.h
+
+static int exynos_asv_probe(struct platform_device *pdev)
+{
+   struct device_node *chip_id;
+   struct exynos_asv_common *exynos_asv_info;
+   void __iomem *base;
+   int ret = 0;
+
+   exynos_asv_info = kzalloc(sizeof(struct exynos_asv_common), GFP_KERNEL);
+   if (!exynos_asv_info)
+   return -ENOMEM;
+
+   chip_id = of_find_compatible_node(NULL, NULL,
+   samsung,exynos4210-chipid);
+   if (!chip_id) {
+   pr_err(%s: unable to find chipid\n, __func__);
+   ret = -ENODEV;
+   goto err_node;
+   }
+
+   base = of_iomap(chip_id, 0);
+   if (!base) {
+   pr_err(%s: unable to map chip_id register\n, __func__);
+   ret = -ENOMEM;
+   goto err_map;
+   }
+
+   exynos_asv_info-base = base;
+
+   /* call SoC specific intialisation routine */
+
+   register_asv_member(exynos_asv_info-asv_list, exynos_asv_info-nr_mem);
+
+   iounmap(base);
+err_map:
+   of_node_put(chip_id);
+err_node:
+   kfree(exynos_asv_info);
+
+   return ret;
+}
+
+static struct platform_driver exynos_asv_platdrv = {
+   .driver = {
+   .name   = exynos-asv,
+   .owner  = THIS_MODULE,
+   },
+   .probe  = exynos_asv_probe,
+};
+module_platform_driver(exynos_asv_platdrv);
+
+MODULE_AUTHOR(Yadwinder Singh Braryadi.b...@samsung.com);
+MODULE_DESCRIPTION(Common Exynos ASV driver);
+MODULE_LICENSE(GPL);
diff --git a/drivers/power/asv/exynos-asv.h b/drivers/power/asv/exynos-asv.h
new file mode 100644
index 000..89a1ae8
--- /dev/null
+++ b/drivers/power/asv/exynos-asv.h
@@ -0,0 +1,21 @@
+/*
+ * Exynos - Adaptive Supply Voltage Driver Header File
+ *
+ * copyright (c) 2013 samsung electronics co., ltd.
+ * http://www.samsung.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.
+*/
+
+#ifndef __EXYNOS_ASV_D_H
+#define __EXYNOS_ASV_D_H __FILE__
+
+struct exynos_asv_common {
+   struct asv_info *asv_list;
+   unsigned int nr_mem;
+   void __iomem *base;
+};
+
+#endif /* __EXYNOS_ASV_D_H */
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC 3/4] power: asv: Add support for exynos5250

2013-09-11 Thread Yadwinder Singh Brar
This patch adds basic support (only for ARM ASV) for exynos5250 chips which
have fused ASV group.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/power/asv/Makefile |2 +-
 drivers/power/asv/exynos-asv.c |9 +++
 drivers/power/asv/exynos-asv.h |1 +
 drivers/power/asv/exynos5250-asv.c |  141 
 4 files changed, 152 insertions(+), 1 deletions(-)
 create mode 100644 drivers/power/asv/exynos5250-asv.c

diff --git a/drivers/power/asv/Makefile b/drivers/power/asv/Makefile
index 9a94868..a471c8e 100644
--- a/drivers/power/asv/Makefile
+++ b/drivers/power/asv/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_POWER_ASV)+= asv.o
-obj-$(CONFIG_POWER_EXYNOS_ASV) += exynos-asv.o
+obj-$(CONFIG_POWER_EXYNOS_ASV) += exynos-asv.o exynos5250-asv.o
diff --git a/drivers/power/asv/exynos-asv.c b/drivers/power/asv/exynos-asv.c
index d3f43a4..7449b55 100644
--- a/drivers/power/asv/exynos-asv.c
+++ b/drivers/power/asv/exynos-asv.c
@@ -46,9 +46,18 @@ static int exynos_asv_probe(struct platform_device *pdev)
exynos_asv_info-base = base;
 
/* call SoC specific intialisation routine */
+   if (of_machine_is_compatible(samsung,exynos5250)) {
+   ret = exynos5250_asv_init(exynos_asv_info);
+   if (ret) {
+   pr_err(%s: exynos5250_asv_init failed : %d\n,
+   __func__, ret);
+   goto err;
+   }
+   }
 
register_asv_member(exynos_asv_info-asv_list, exynos_asv_info-nr_mem);
 
+err:
iounmap(base);
 err_map:
of_node_put(chip_id);
diff --git a/drivers/power/asv/exynos-asv.h b/drivers/power/asv/exynos-asv.h
index 89a1ae8..a31becb 100644
--- a/drivers/power/asv/exynos-asv.h
+++ b/drivers/power/asv/exynos-asv.h
@@ -18,4 +18,5 @@ struct exynos_asv_common {
void __iomem *base;
 };
 
+extern int exynos5250_asv_init(struct exynos_asv_common *exynos_info);
 #endif /* __EXYNOS_ASV_D_H */
diff --git a/drivers/power/asv/exynos5250-asv.c 
b/drivers/power/asv/exynos5250-asv.c
new file mode 100644
index 000..293b3f1
--- /dev/null
+++ b/drivers/power/asv/exynos5250-asv.c
@@ -0,0 +1,141 @@
+/* exynos5250 - ASV(Adaptive Supply Voltage)
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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.
+*/
+
+#include linux/err.h
+#include linux/io.h
+#include linux/slab.h
+#include linux/power/asv-driver.h
+#include exynos-asv.h
+
+#define FUSED_SG_OFFSET3
+#define ORIG_SG_OFFSET 17
+#define ORIG_SG_MASK   0xF
+#define MOD_SG_OFFSET  21
+#define MOD_SG_MASK0x7
+
+#define ARM_LEVEL_NR   16
+#define ARM_GRP_NR 12
+
+#define CHIP_ID_OFFSET 0x4
+
+struct exynos5250_asv_info {
+   unsigned int package_id;
+   /* we may need more info as global data */
+};
+
+static struct exynos5250_asv_info asv_group __initdata;
+
+static unsigned int asv_voltage[ARM_LEVEL_NR][ARM_GRP_NR + 1] __initdata = {
+   { 170, 130, 1275000, 1275000, 1262500, 125, 1225000,
+   1212500, 120, 1187500, 1175000, 115, 1125000 }, /* L0 */
+   { 160, 125, 1225000, 1225000, 1212500, 120, 1187500,
+   1175000, 1162500, 115, 1137500, 1112500, 110 }, /* L1 */
+   { 150, 1225000, 1187500, 1175000, 1162500, 115, 1137500,
+   1125000, 1112500, 110, 1087500, 1075000, 1062500 }, /* L2 */
+   { 140, 120, 1125000, 1125000, 1125000, 1112500, 110,
+   1087500, 1075000, 1062500, 105, 1037500, 1025000 }, /* L3 */
+   { 130, 115, 110, 110, 110, 1087500, 1075000,
+   1062500, 105, 1037500, 1025000, 1012500, 100 }, /* L4 */
+   { 120, 1125000, 1075000, 1075000, 1062500, 105, 1037500,
+   1025000, 1012500, 100,  987500,  975000,  975000 }, /* L5 */
+   { 110, 110, 105, 105, 1037500, 1025000, 1012500,
+   100,  987500,  975000,  962500,  95,  925000 }, /* L6 */
+   { 100, 1075000, 1037500, 1037500, 1012500, 100,  987500,
+   975000,  962500,  95,  937500,  925000,  912500 },  /* L7 */
+   { 90, 105, 1025000, 1012500,  987500,  975000,  962500,
+   95,  937500,  925000,  912500,  912500,  90 },  /* L8 */
+   { 80, 1025000, 100,  987500,  975000,  962500,  95,
+   937500,  925000,  912500,  90,  90,  90 },  /* L9 */
+   { 70, 1012500,  975000,  962500,  95,  937500,  925000,
+   912500,  90,  90,  90,  90,  90 },  /* L10 */
+   { 60, 100,  962500,  95,  937500,  925000,  912500,
+   90,  90,  90,  90,  90

[RFC 4/4] arm: exynos5: Register static platform device for ASV.

2013-09-11 Thread Yadwinder Singh Brar
Since ASV is not a hardware controller so we cann't add device tree node for
it. This patch registers a static platform device exynos ASV.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 arch/arm/mach-exynos/mach-exynos5-dt.c |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c 
b/arch/arm/mach-exynos/mach-exynos5-dt.c
index f874b77..5ce58e1 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -28,6 +28,7 @@ static void __init exynos5_dt_machine_init(void)
struct device_node *i2c_np;
const char *i2c_compat = samsung,s3c2440-i2c;
unsigned int tmp;
+   struct platform_device_info devinfo = { .name = exynos-asv, };
 
/*
 * Exynos5's legacy i2c controller and new high speed i2c
@@ -48,6 +49,8 @@ static void __init exynos5_dt_machine_init(void)
}
 
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+   platform_device_register_full(devinfo);
 }
 
 static char const *exynos5_dt_compat[] __initdata = {
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC 1/4] power: asv: Add common ASV support for samsung SoCs

2013-09-11 Thread Yadwinder Singh Brar
This patch introduces a common ASV(Adaptive Supply Voltage) basic framework
for samsung SoCs. It provides common APIs (to be called by users to get ASV
values or init opp_table) and an interface for SoC specific drivers to
register ASV members(instances).

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---

Hopefully asv_get_volt() can go out in future, once all users start using OPP
library.

---
 drivers/power/Kconfig|1 +
 drivers/power/Makefile   |1 +
 drivers/power/asv/Kconfig|   11 ++
 drivers/power/asv/Makefile   |1 +
 drivers/power/asv/samsung-asv.c  |  175 ++
 include/linux/power/samsung-asv-driver.h |   61 +++
 include/linux/power/samsung-asv.h|   37 +++
 7 files changed, 287 insertions(+), 0 deletions(-)
 create mode 100644 drivers/power/asv/Kconfig
 create mode 100644 drivers/power/asv/Makefile
 create mode 100644 drivers/power/asv/samsung-asv.c
 create mode 100644 include/linux/power/samsung-asv-driver.h
 create mode 100644 include/linux/power/samsung-asv.h

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 7b8979c..2e6b087 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -367,3 +367,4 @@ source drivers/power/reset/Kconfig
 endif # POWER_SUPPLY
 
 source drivers/power/avs/Kconfig
+source drivers/power/asv/Kconfig
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 653bf6c..da93c46 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)  += max8998_charger.o
 obj-$(CONFIG_CHARGER_BQ2415X)  += bq2415x_charger.o
 obj-$(CONFIG_POWER_AVS)+= avs/
+obj-$(CONFIG_POWER_ASV)+= asv/
 obj-$(CONFIG_CHARGER_SMB347)   += smb347-charger.o
 obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
 obj-$(CONFIG_POWER_RESET)  += reset/
diff --git a/drivers/power/asv/Kconfig b/drivers/power/asv/Kconfig
new file mode 100644
index 000..7cd84bd
--- /dev/null
+++ b/drivers/power/asv/Kconfig
@@ -0,0 +1,11 @@
+menuconfig POWER_ASV
+   bool Adaptive Supply Voltage support
+   help
+ ASV is a technique used on samsung SoCs, which provides the
+ recommended supply voltage for some specific parts(like arm, mif etc)
+ of SoCs which supports dvfs. For a given operating frequency, the
+ voltage is recommended based on SoCs ASV group.
+ ASV group info is provided in the chip id info which depends on chip
+ manufacturing process.
+
+ Say Y here to enable Adaptive Supply voltage support.
diff --git a/drivers/power/asv/Makefile b/drivers/power/asv/Makefile
new file mode 100644
index 000..62921da
--- /dev/null
+++ b/drivers/power/asv/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_POWER_ASV)+= asv.o
diff --git a/drivers/power/asv/asv.c b/drivers/power/asv/asv.c
new file mode 100644
index 000..61f4a83
--- /dev/null
+++ b/drivers/power/asv/asv.c
@@ -0,0 +1,175 @@
+/*
+ * ASV(Adaptive Supply Voltage) common core
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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.
+*/
+
+#include linux/io.h
+#include linux/opp.h
+#include linux/slab.h
+#include linux/device.h
+#include linux/power/asv-driver.h
+
+static LIST_HEAD(asv_list);
+static DEFINE_MUTEX(asv_mutex);
+
+struct asv_member {
+   struct list_headnode;
+   struct asv_info *asv_info;
+};
+
+static void add_asv_member(struct asv_member *asv_mem)
+{
+   mutex_lock(asv_mutex);
+   list_add_tail(asv_mem-node, asv_list);
+   mutex_unlock(asv_mutex);
+}
+
+static struct asv_member *asv_get_mem(enum asv_type_id asv_type)
+{
+   struct asv_member *asv_mem;
+   struct asv_info *asv_info;
+
+   list_for_each_entry(asv_mem, asv_list, node) {
+   asv_info = asv_mem-asv_info;
+   if (asv_type == asv_info-type)
+   return asv_mem;
+   }
+
+   return NULL;
+}
+
+unsigned int asv_get_volt(enum asv_type_id target_type,
+   unsigned int target_freq)
+{
+   struct asv_member *asv_mem = asv_get_mem(target_type);
+   struct asv_freq_table *dvfs_table;
+   struct asv_info *asv_info;
+   unsigned int i;
+
+   if (!asv_mem)
+   return 0;
+
+   asv_info = asv_mem-asv_info;
+   dvfs_table = asv_info-dvfs_table;
+
+   for (i = 0; i  asv_info-nr_dvfs_level; i++) {
+   if (dvfs_table[i].freq == target_freq)
+   return dvfs_table[i].volt;
+   }
+
+   return 0;
+}
+
+int asv_init_opp_table(struct device *dev, enum asv_type_id target_type

Re: [PATCH 1/3] clk: s2mps11: Add support for s2mps11

2013-08-05 Thread Yadwinder Singh Brar
Hi Mike,

On Tue, Aug 6, 2013 at 4:53 AM, Mike Turquette  wrote:
> Quoting Yadwinder Singh Brar (2013-07-07 04:44:20)
>> This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz
>> outputs of mfd-s2mps11 with common clock framework.
>>
>> Signed-off-by: Yadwinder Singh Brar 
>
> Yadwinder,
>
> Looks good to me with the exception of a binding description document.
> Can you provide one and squash it into this commit?
>

Binding description is provided in next patch :
[PATCH 2/3] mfd: sec: Add clock cell for s2mps11  :
https://lkml.org/lkml/2013/7/16/228

Since its a MFD, so i preferred to add documentation in same file
under mfd, same was done for regulators also.
If its fine with you then, I think that patch can go through MFD tree
as same file is touched in for-next of MFD tree.


Thanks,
Yadwinder
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] clk: s2mps11: Add support for s2mps11

2013-08-05 Thread Yadwinder Singh Brar
Hi Mike,

On Tue, Aug 6, 2013 at 4:53 AM, Mike Turquette mturque...@linaro.org wrote:
 Quoting Yadwinder Singh Brar (2013-07-07 04:44:20)
 This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz
 outputs of mfd-s2mps11 with common clock framework.

 Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com

 Yadwinder,

 Looks good to me with the exception of a binding description document.
 Can you provide one and squash it into this commit?


Binding description is provided in next patch :
[PATCH 2/3] mfd: sec: Add clock cell for s2mps11  :
https://lkml.org/lkml/2013/7/16/228

Since its a MFD, so i preferred to add documentation in same file
under mfd, same was done for regulators also.
If its fine with you then, I think that patch can go through MFD tree
as same file is touched in for-next of MFD tree.


Thanks,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] clk: s2mps11: Add support for s2mps11

2013-07-26 Thread Yadwinder Singh Brar
Gentle ping ...

Any review comments?

On Sun, Jul 7, 2013 at 5:14 PM, Yadwinder Singh Brar
 wrote:
> This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz
> outputs of mfd-s2mps11 with common clock framework.
>
> Signed-off-by: Yadwinder Singh Brar 
> ---
>  drivers/clk/Kconfig   |6 +
>  drivers/clk/Makefile  |1 +
>  drivers/clk/clk-s2mps11.c |  273 
> +
>  3 files changed, 280 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-s2mps11.c
>
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 0357ac4..3fdf10e 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -65,6 +65,12 @@ config COMMON_CLK_SI5351
>   This driver supports Silicon Labs 5351A/B/C programmable clock
>   generators.
>
> +config COMMON_CLK_S2MPS11
> +   tristate "Clock driver for S2MPS11 MFD"
> +   depends on MFD_SEC_CORE
> +   ---help---
> + This driver supports S2MPS11 crystal oscillator clock.
> +
>  config CLK_TWL6040
> tristate "External McPDM functional clock from twl6040"
> depends on TWL6040_CORE
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 137d3e7..5fd642d 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -38,4 +38,5 @@ obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
>  obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
>  obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
>  obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
> +obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
>  obj-$(CONFIG_CLK_TWL6040)  += clk-twl6040.o
> diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
> new file mode 100644
> index 000..7be41e6
> --- /dev/null
> +++ b/drivers/clk/clk-s2mps11.c
> @@ -0,0 +1,273 @@
> +/*
> + * clk-s2mps11.c - Clock driver for S2MPS11.
> + *
> + * Copyright (C) 2013 Samsung Electornics
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + *
> + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define s2mps11_name(a) (a->hw.init->name)
> +
> +static struct clk **clk_table;
> +static struct clk_onecell_data clk_data;
> +
> +enum {
> +   S2MPS11_CLK_AP = 0,
> +   S2MPS11_CLK_CP,
> +   S2MPS11_CLK_BT,
> +   S2MPS11_CLKS_NUM,
> +};
> +
> +struct s2mps11_clk {
> +   struct sec_pmic_dev *iodev;
> +   struct clk_hw hw;
> +   struct clk *clk;
> +   struct clk_lookup *lookup;
> +   u32 mask;
> +   bool enabled;
> +};
> +
> +static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
> +{
> +   return container_of(hw, struct s2mps11_clk, hw);
> +}
> +
> +static int s2mps11_clk_prepare(struct clk_hw *hw)
> +{
> +   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
> +   int ret;
> +
> +   ret = regmap_update_bits(s2mps11->iodev->regmap,
> +   S2MPS11_REG_RTC_CTRL,
> +s2mps11->mask, s2mps11->mask);
> +   if (!ret)
> +   s2mps11->enabled = true;
> +
> +   return ret;
> +}
> +
> +static void s2mps11_clk_unprepare(struct clk_hw *hw)
> +{
> +   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
> +   int ret;
> +
> +   ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL,
> +  s2mps11->mask, ~s2mps11->mask);
> +
> +   if (!ret)
> +   s2mps11->enabled = false;
> +}
> +
> +static int s2mps11_clk_is_enabled(struct clk_hw *hw)
> +{
> +   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
> +
> +   return s2mps11->enabled;
> +}
> +
> +static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
> +unsigned long 

Re: [PATCH 1/3] clk: s2mps11: Add support for s2mps11

2013-07-26 Thread Yadwinder Singh Brar
Gentle ping ...

Any review comments?

On Sun, Jul 7, 2013 at 5:14 PM, Yadwinder Singh Brar
yadi.b...@samsung.com wrote:
 This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz
 outputs of mfd-s2mps11 with common clock framework.

 Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
 ---
  drivers/clk/Kconfig   |6 +
  drivers/clk/Makefile  |1 +
  drivers/clk/clk-s2mps11.c |  273 
 +
  3 files changed, 280 insertions(+), 0 deletions(-)
  create mode 100644 drivers/clk/clk-s2mps11.c

 diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
 index 0357ac4..3fdf10e 100644
 --- a/drivers/clk/Kconfig
 +++ b/drivers/clk/Kconfig
 @@ -65,6 +65,12 @@ config COMMON_CLK_SI5351
   This driver supports Silicon Labs 5351A/B/C programmable clock
   generators.

 +config COMMON_CLK_S2MPS11
 +   tristate Clock driver for S2MPS11 MFD
 +   depends on MFD_SEC_CORE
 +   ---help---
 + This driver supports S2MPS11 crystal oscillator clock.
 +
  config CLK_TWL6040
 tristate External McPDM functional clock from twl6040
 depends on TWL6040_CORE
 diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
 index 137d3e7..5fd642d 100644
 --- a/drivers/clk/Makefile
 +++ b/drivers/clk/Makefile
 @@ -38,4 +38,5 @@ obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
  obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
  obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
  obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
 +obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
  obj-$(CONFIG_CLK_TWL6040)  += clk-twl6040.o
 diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
 new file mode 100644
 index 000..7be41e6
 --- /dev/null
 +++ b/drivers/clk/clk-s2mps11.c
 @@ -0,0 +1,273 @@
 +/*
 + * clk-s2mps11.c - Clock driver for S2MPS11.
 + *
 + * Copyright (C) 2013 Samsung Electornics
 + *
 + * This program is free software; you can redistribute  it and/or modify it
 + * under  the terms of  the GNU General  Public License as published by the
 + * Free Software Foundation;  either version 2 of the  License, or (at your
 + * option) any later version.
 + *
 + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 + *
 + */
 +
 +#include linux/module.h
 +#include linux/err.h
 +#include linux/of.h
 +#include linux/clkdev.h
 +#include linux/regmap.h
 +#include linux/clk-provider.h
 +#include linux/platform_device.h
 +#include linux/mfd/samsung/s2mps11.h
 +#include linux/mfd/samsung/core.h
 +
 +#define s2mps11_name(a) (a-hw.init-name)
 +
 +static struct clk **clk_table;
 +static struct clk_onecell_data clk_data;
 +
 +enum {
 +   S2MPS11_CLK_AP = 0,
 +   S2MPS11_CLK_CP,
 +   S2MPS11_CLK_BT,
 +   S2MPS11_CLKS_NUM,
 +};
 +
 +struct s2mps11_clk {
 +   struct sec_pmic_dev *iodev;
 +   struct clk_hw hw;
 +   struct clk *clk;
 +   struct clk_lookup *lookup;
 +   u32 mask;
 +   bool enabled;
 +};
 +
 +static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
 +{
 +   return container_of(hw, struct s2mps11_clk, hw);
 +}
 +
 +static int s2mps11_clk_prepare(struct clk_hw *hw)
 +{
 +   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
 +   int ret;
 +
 +   ret = regmap_update_bits(s2mps11-iodev-regmap,
 +   S2MPS11_REG_RTC_CTRL,
 +s2mps11-mask, s2mps11-mask);
 +   if (!ret)
 +   s2mps11-enabled = true;
 +
 +   return ret;
 +}
 +
 +static void s2mps11_clk_unprepare(struct clk_hw *hw)
 +{
 +   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
 +   int ret;
 +
 +   ret = regmap_update_bits(s2mps11-iodev-regmap, S2MPS11_REG_RTC_CTRL,
 +  s2mps11-mask, ~s2mps11-mask);
 +
 +   if (!ret)
 +   s2mps11-enabled = false;
 +}
 +
 +static int s2mps11_clk_is_enabled(struct clk_hw *hw)
 +{
 +   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
 +
 +   return s2mps11-enabled;
 +}
 +
 +static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
 +unsigned long parent_rate)
 +{
 +   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
 +   if (s2mps11-enabled)
 +   return 32768;
 +   else
 +   return 0;
 +}
 +
 +static struct clk_ops s2mps11_clk_ops = {
 +   .prepare= s2mps11_clk_prepare,
 +   .unprepare  = s2mps11_clk_unprepare,
 +   .is_enabled = s2mps11_clk_is_enabled,
 +   .recalc_rate

[PATCH 0/3] Add clk driver to register s2mps11 clocks

2013-07-16 Thread Yadwinder Singh Brar
This series adds support to register three(AP/CP/BT) buffered 32.768 KHz
outputs of mfd-s2mps11 with common clock framework and removes clocks from
regulators list.

Yadwinder Singh Brar (3):
  clk: s2mps11: Add support for s2mps11
  mfd: sec: Add clock cell for s2mps11
  mfd: s2mps11: Remove clocks from regulators list

 Documentation/devicetree/bindings/mfd/s2mps11.txt |   20 ++
 drivers/clk/Kconfig   |6 +
 drivers/clk/Makefile  |1 +
 drivers/clk/clk-s2mps11.c |  273 +
 drivers/mfd/sec-core.c|4 +-
 include/linux/mfd/samsung/s2mps11.h   |6 +-
 6 files changed, 304 insertions(+), 6 deletions(-)
 create mode 100644 drivers/clk/clk-s2mps11.c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] clk: s2mps11: Add support for s2mps11

2013-07-16 Thread Yadwinder Singh Brar
This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz
outputs of mfd-s2mps11 with common clock framework.

Signed-off-by: Yadwinder Singh Brar 
---
 drivers/clk/Kconfig   |6 +
 drivers/clk/Makefile  |1 +
 drivers/clk/clk-s2mps11.c |  273 +
 3 files changed, 280 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-s2mps11.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 0357ac4..3fdf10e 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -65,6 +65,12 @@ config COMMON_CLK_SI5351
  This driver supports Silicon Labs 5351A/B/C programmable clock
  generators.
 
+config COMMON_CLK_S2MPS11
+   tristate "Clock driver for S2MPS11 MFD"
+   depends on MFD_SEC_CORE
+   ---help---
+ This driver supports S2MPS11 crystal oscillator clock.
+
 config CLK_TWL6040
tristate "External McPDM functional clock from twl6040"
depends on TWL6040_CORE
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 137d3e7..5fd642d 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -38,4 +38,5 @@ obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
+obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
 obj-$(CONFIG_CLK_TWL6040)  += clk-twl6040.o
diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
new file mode 100644
index 000..7be41e6
--- /dev/null
+++ b/drivers/clk/clk-s2mps11.c
@@ -0,0 +1,273 @@
+/*
+ * clk-s2mps11.c - Clock driver for S2MPS11.
+ *
+ * Copyright (C) 2013 Samsung Electornics
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define s2mps11_name(a) (a->hw.init->name)
+
+static struct clk **clk_table;
+static struct clk_onecell_data clk_data;
+
+enum {
+   S2MPS11_CLK_AP = 0,
+   S2MPS11_CLK_CP,
+   S2MPS11_CLK_BT,
+   S2MPS11_CLKS_NUM,
+};
+
+struct s2mps11_clk {
+   struct sec_pmic_dev *iodev;
+   struct clk_hw hw;
+   struct clk *clk;
+   struct clk_lookup *lookup;
+   u32 mask;
+   bool enabled;
+};
+
+static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
+{
+   return container_of(hw, struct s2mps11_clk, hw);
+}
+
+static int s2mps11_clk_prepare(struct clk_hw *hw)
+{
+   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+   int ret;
+
+   ret = regmap_update_bits(s2mps11->iodev->regmap,
+   S2MPS11_REG_RTC_CTRL,
+s2mps11->mask, s2mps11->mask);
+   if (!ret)
+   s2mps11->enabled = true;
+
+   return ret;
+}
+
+static void s2mps11_clk_unprepare(struct clk_hw *hw)
+{
+   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+   int ret;
+
+   ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL,
+  s2mps11->mask, ~s2mps11->mask);
+
+   if (!ret)
+   s2mps11->enabled = false;
+}
+
+static int s2mps11_clk_is_enabled(struct clk_hw *hw)
+{
+   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+
+   return s2mps11->enabled;
+}
+
+static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+   if (s2mps11->enabled)
+   return 32768;
+   else
+   return 0;
+}
+
+static struct clk_ops s2mps11_clk_ops = {
+   .prepare= s2mps11_clk_prepare,
+   .unprepare  = s2mps11_clk_unprepare,
+   .is_enabled = s2mps11_clk_is_enabled,
+   .recalc_rate= s2mps11_clk_recalc_rate,
+};
+
+static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
+   [S2MPS11_CLK_AP] = {
+   .name = "s2mps11_ap",
+   .ops = _clk_ops,
+   .flags = CLK_IS_ROOT,
+   },
+   [S2MPS11_CLK_CP] = {
+   .name = "s2mps11_cp",
+   .ops = _clk_ops,
+   .

[PATCH 2/3] mfd: sec: Add clock cell for s2mps11

2013-07-16 Thread Yadwinder Singh Brar
This patch adds clock to list of mfd cells for s2mps11 and DT documentation
for clock part.

Signed-off-by: Yadwinder Singh Brar 
---
 Documentation/devicetree/bindings/mfd/s2mps11.txt |   20 
 drivers/mfd/sec-core.c|4 +++-
 2 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt 
b/Documentation/devicetree/bindings/mfd/s2mps11.txt
index 36269c4..e41dd16 100644
--- a/Documentation/devicetree/bindings/mfd/s2mps11.txt
+++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt
@@ -16,6 +16,21 @@ Optional properties:
 - interrupts: Interrupt specifiers for interrupt sources.
 
 Optional nodes:
+- clocks: s2mps11 provides three(AP/CP/BT) buffered 32.768 KHz outputs, so to
+  register these as clocks with common clock framework instantiate a sub-node
+  named "clocks". It uses the common clock binding documented in :
+  [Documentation/devicetree/bindings/clock/clock-bindings.txt]
+  - #clock-cells: should be 1.
+
+  - The following is the list of clocks generated by the controller. Each clock
+is assigned an identifier and client nodes use this identifier to specify
+the clock which they consume.
+Clock   ID
+--
+32KhzAP0
+32KhzCP1
+32KhzBT2
+
 - regulators: The regulators of s2mps11 that have to be instantiated should be
 included in a sub-node named 'regulators'. Regulator nodes included in this
 sub-node should be of the format as listed below.
@@ -55,6 +70,11 @@ Example:
compatible = "samsung,s2mps11-pmic";
reg = <0x66>;
 
+   s2m_osc: clocks{
+   #clock-cells = 1;
+   clock-output-names = "xx", "yy", "zz";
+   };
+
regulators {
ldo1_reg: LDO1 {
regulator-name = "VDD_ABB_3.3V";
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 760da8a..eaee5ec 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -58,7 +58,9 @@ static struct mfd_cell s5m8767_devs[] = {
 static struct mfd_cell s2mps11_devs[] = {
{
.name = "s2mps11-pmic",
-   },
+   }, {
+   .name = "s2mps11-clk",
+   }
 };
 
 #ifdef CONFIG_OF
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] mfd: s2mps11: Remove clocks from regulators list

2013-07-16 Thread Yadwinder Singh Brar
Since these are fixed rate clocks which are registered with common clock
framework so remove these from list of regulators which were unnecessarily
incrementing the count(S2MPS11_REGULATOR_MAX) of regulators.

Signed-off-by: Yadwinder Singh Brar 
---
 include/linux/mfd/samsung/s2mps11.h |6 +-
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/samsung/s2mps11.h 
b/include/linux/mfd/samsung/s2mps11.h
index d0d52ea..b3ddf98 100644
--- a/include/linux/mfd/samsung/s2mps11.h
+++ b/include/linux/mfd/samsung/s2mps11.h
@@ -167,11 +167,8 @@ enum s2mps11_regulators {
S2MPS11_BUCK8,
S2MPS11_BUCK9,
S2MPS11_BUCK10,
-   S2MPS11_AP_EN32KHZ,
-   S2MPS11_CP_EN32KHZ,
-   S2MPS11_BT_EN32KHZ,
 
-   S2MPS11_REG_MAX,
+   S2MPS11_REGULATOR_MAX,
 };
 
 #define S2MPS11_BUCK_MIN1  60
@@ -203,6 +200,5 @@ enum s2mps11_regulators {
 #define S2MPS11_BUCK4_RAMP_EN_SHIFT1
 #define S2MPS11_BUCK6_RAMP_EN_SHIFT0
 #define S2MPS11_PMIC_EN_SHIFT  6
-#define S2MPS11_REGULATOR_MAX (S2MPS11_REG_MAX - 3)
 
 #endif /*  __LINUX_MFD_S2MPS11_H */
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] regulator: s2mps11: Add linux/of.h header

2013-07-16 Thread Yadwinder Singh Brar
This patch adds linux/of.h required to fix an error and warning reported by
kbuild test robot for some x86 config file.

Signed-off-by: Yadwinder Singh Brar 
---
 drivers/regulator/s2mps11.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index e1aadbd..350e04f 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] regulator: s2mps11: Add linux/of.h header

2013-07-16 Thread Yadwinder Singh Brar
This patch adds linux/of.h required to fix an error and warning reported by
kbuild test robot for some x86 config file.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/regulator/s2mps11.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index e1aadbd..350e04f 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -17,6 +17,7 @@
 #include linux/slab.h
 #include linux/module.h
 #include linux/regmap.h
+#include linux/of.h
 #include linux/platform_device.h
 #include linux/regulator/driver.h
 #include linux/regulator/machine.h
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] mfd: s2mps11: Remove clocks from regulators list

2013-07-16 Thread Yadwinder Singh Brar
Since these are fixed rate clocks which are registered with common clock
framework so remove these from list of regulators which were unnecessarily
incrementing the count(S2MPS11_REGULATOR_MAX) of regulators.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 include/linux/mfd/samsung/s2mps11.h |6 +-
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/include/linux/mfd/samsung/s2mps11.h 
b/include/linux/mfd/samsung/s2mps11.h
index d0d52ea..b3ddf98 100644
--- a/include/linux/mfd/samsung/s2mps11.h
+++ b/include/linux/mfd/samsung/s2mps11.h
@@ -167,11 +167,8 @@ enum s2mps11_regulators {
S2MPS11_BUCK8,
S2MPS11_BUCK9,
S2MPS11_BUCK10,
-   S2MPS11_AP_EN32KHZ,
-   S2MPS11_CP_EN32KHZ,
-   S2MPS11_BT_EN32KHZ,
 
-   S2MPS11_REG_MAX,
+   S2MPS11_REGULATOR_MAX,
 };
 
 #define S2MPS11_BUCK_MIN1  60
@@ -203,6 +200,5 @@ enum s2mps11_regulators {
 #define S2MPS11_BUCK4_RAMP_EN_SHIFT1
 #define S2MPS11_BUCK6_RAMP_EN_SHIFT0
 #define S2MPS11_PMIC_EN_SHIFT  6
-#define S2MPS11_REGULATOR_MAX (S2MPS11_REG_MAX - 3)
 
 #endif /*  __LINUX_MFD_S2MPS11_H */
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] mfd: sec: Add clock cell for s2mps11

2013-07-16 Thread Yadwinder Singh Brar
This patch adds clock to list of mfd cells for s2mps11 and DT documentation
for clock part.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 Documentation/devicetree/bindings/mfd/s2mps11.txt |   20 
 drivers/mfd/sec-core.c|4 +++-
 2 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt 
b/Documentation/devicetree/bindings/mfd/s2mps11.txt
index 36269c4..e41dd16 100644
--- a/Documentation/devicetree/bindings/mfd/s2mps11.txt
+++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt
@@ -16,6 +16,21 @@ Optional properties:
 - interrupts: Interrupt specifiers for interrupt sources.
 
 Optional nodes:
+- clocks: s2mps11 provides three(AP/CP/BT) buffered 32.768 KHz outputs, so to
+  register these as clocks with common clock framework instantiate a sub-node
+  named clocks. It uses the common clock binding documented in :
+  [Documentation/devicetree/bindings/clock/clock-bindings.txt]
+  - #clock-cells: should be 1.
+
+  - The following is the list of clocks generated by the controller. Each clock
+is assigned an identifier and client nodes use this identifier to specify
+the clock which they consume.
+Clock   ID
+--
+32KhzAP0
+32KhzCP1
+32KhzBT2
+
 - regulators: The regulators of s2mps11 that have to be instantiated should be
 included in a sub-node named 'regulators'. Regulator nodes included in this
 sub-node should be of the format as listed below.
@@ -55,6 +70,11 @@ Example:
compatible = samsung,s2mps11-pmic;
reg = 0x66;
 
+   s2m_osc: clocks{
+   #clock-cells = 1;
+   clock-output-names = xx, yy, zz;
+   };
+
regulators {
ldo1_reg: LDO1 {
regulator-name = VDD_ABB_3.3V;
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 760da8a..eaee5ec 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -58,7 +58,9 @@ static struct mfd_cell s5m8767_devs[] = {
 static struct mfd_cell s2mps11_devs[] = {
{
.name = s2mps11-pmic,
-   },
+   }, {
+   .name = s2mps11-clk,
+   }
 };
 
 #ifdef CONFIG_OF
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] clk: s2mps11: Add support for s2mps11

2013-07-16 Thread Yadwinder Singh Brar
This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz
outputs of mfd-s2mps11 with common clock framework.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/Kconfig   |6 +
 drivers/clk/Makefile  |1 +
 drivers/clk/clk-s2mps11.c |  273 +
 3 files changed, 280 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-s2mps11.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 0357ac4..3fdf10e 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -65,6 +65,12 @@ config COMMON_CLK_SI5351
  This driver supports Silicon Labs 5351A/B/C programmable clock
  generators.
 
+config COMMON_CLK_S2MPS11
+   tristate Clock driver for S2MPS11 MFD
+   depends on MFD_SEC_CORE
+   ---help---
+ This driver supports S2MPS11 crystal oscillator clock.
+
 config CLK_TWL6040
tristate External McPDM functional clock from twl6040
depends on TWL6040_CORE
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 137d3e7..5fd642d 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -38,4 +38,5 @@ obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
+obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
 obj-$(CONFIG_CLK_TWL6040)  += clk-twl6040.o
diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
new file mode 100644
index 000..7be41e6
--- /dev/null
+++ b/drivers/clk/clk-s2mps11.c
@@ -0,0 +1,273 @@
+/*
+ * clk-s2mps11.c - Clock driver for S2MPS11.
+ *
+ * Copyright (C) 2013 Samsung Electornics
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include linux/module.h
+#include linux/err.h
+#include linux/of.h
+#include linux/clkdev.h
+#include linux/regmap.h
+#include linux/clk-provider.h
+#include linux/platform_device.h
+#include linux/mfd/samsung/s2mps11.h
+#include linux/mfd/samsung/core.h
+
+#define s2mps11_name(a) (a-hw.init-name)
+
+static struct clk **clk_table;
+static struct clk_onecell_data clk_data;
+
+enum {
+   S2MPS11_CLK_AP = 0,
+   S2MPS11_CLK_CP,
+   S2MPS11_CLK_BT,
+   S2MPS11_CLKS_NUM,
+};
+
+struct s2mps11_clk {
+   struct sec_pmic_dev *iodev;
+   struct clk_hw hw;
+   struct clk *clk;
+   struct clk_lookup *lookup;
+   u32 mask;
+   bool enabled;
+};
+
+static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
+{
+   return container_of(hw, struct s2mps11_clk, hw);
+}
+
+static int s2mps11_clk_prepare(struct clk_hw *hw)
+{
+   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+   int ret;
+
+   ret = regmap_update_bits(s2mps11-iodev-regmap,
+   S2MPS11_REG_RTC_CTRL,
+s2mps11-mask, s2mps11-mask);
+   if (!ret)
+   s2mps11-enabled = true;
+
+   return ret;
+}
+
+static void s2mps11_clk_unprepare(struct clk_hw *hw)
+{
+   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+   int ret;
+
+   ret = regmap_update_bits(s2mps11-iodev-regmap, S2MPS11_REG_RTC_CTRL,
+  s2mps11-mask, ~s2mps11-mask);
+
+   if (!ret)
+   s2mps11-enabled = false;
+}
+
+static int s2mps11_clk_is_enabled(struct clk_hw *hw)
+{
+   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+
+   return s2mps11-enabled;
+}
+
+static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
+   if (s2mps11-enabled)
+   return 32768;
+   else
+   return 0;
+}
+
+static struct clk_ops s2mps11_clk_ops = {
+   .prepare= s2mps11_clk_prepare,
+   .unprepare  = s2mps11_clk_unprepare,
+   .is_enabled = s2mps11_clk_is_enabled,
+   .recalc_rate= s2mps11_clk_recalc_rate,
+};
+
+static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
+   [S2MPS11_CLK_AP] = {
+   .name = s2mps11_ap,
+   .ops = s2mps11_clk_ops,
+   .flags = CLK_IS_ROOT,
+   },
+   [S2MPS11_CLK_CP

[PATCH 0/3] Add clk driver to register s2mps11 clocks

2013-07-16 Thread Yadwinder Singh Brar
This series adds support to register three(AP/CP/BT) buffered 32.768 KHz
outputs of mfd-s2mps11 with common clock framework and removes clocks from
regulators list.

Yadwinder Singh Brar (3):
  clk: s2mps11: Add support for s2mps11
  mfd: sec: Add clock cell for s2mps11
  mfd: s2mps11: Remove clocks from regulators list

 Documentation/devicetree/bindings/mfd/s2mps11.txt |   20 ++
 drivers/clk/Kconfig   |6 +
 drivers/clk/Makefile  |1 +
 drivers/clk/clk-s2mps11.c |  273 +
 drivers/mfd/sec-core.c|4 +-
 include/linux/mfd/samsung/s2mps11.h   |6 +-
 6 files changed, 304 insertions(+), 6 deletions(-)
 create mode 100644 drivers/clk/clk-s2mps11.c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [v2 PATCH 6/6] mfd: s2mps11: Add device tree support

2013-07-08 Thread Yadwinder Singh Brar
On Mon, Jul 8, 2013 at 6:58 PM, Mark Brown  wrote:
> On Sat, Jun 29, 2013 at 06:21:20PM +0530, Yadwinder Singh Brar wrote:
>> This patch adds DT compatible string for s2mps11 and binding documentation.
>>
>> Signed-off-by: Yadwinder Singh Brar 
>
> Reviewed-by: Mark Brown 
>
> It looks like this should be OK to merge via the MFD tree separately to
> the regulator changes, or I can apply it to the regualtor tree if that's
> easier for people.

Yes, it can be merged via MFD, thats why I put it at last.
Either way it will fine.

Thanks,
Yadwinder
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 2/6] regulator: s2mps11: Implement set_ramp_rate callback for bucks

2013-07-08 Thread Yadwinder Singh Brar
Implementing set_ramp_rate() and using standard constraints for getting
ramp_delay and ramp_disable, instead of getting it as s2mps11 specific data
through platform data, makes driver more compliant with framework and reduces
the complexity for adding DT support.

Signed-off-by: Yadwinder Singh Brar 
---
 drivers/regulator/s2mps11.c |  117 +++
 include/linux/mfd/samsung/s2mps11.h |   11 +++
 2 files changed, 128 insertions(+), 0 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index a671eb6..4bebcb6 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -104,6 +105,121 @@ static int s2mps11_regulator_set_voltage_time_sel(struct 
regulator_dev *rdev,
return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
 }
 
+static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+   struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
+   unsigned int ramp_val, ramp_shift, ramp_reg = S2MPS11_REG_RAMP_BUCK;
+   unsigned int ramp_enable = 1, enable_shift = 0;
+   int ret;
+
+   switch (rdev->desc->id) {
+   case S2MPS11_BUCK1:
+   if (ramp_delay > s2mps11->ramp_delay16)
+   s2mps11->ramp_delay16 = ramp_delay;
+   else
+   ramp_delay = s2mps11->ramp_delay16;
+
+   ramp_shift = S2MPS11_BUCK16_RAMP_SHIFT;
+   break;
+   case S2MPS11_BUCK2:
+   enable_shift = S2MPS11_BUCK2_RAMP_EN_SHIFT;
+   if (!ramp_delay) {
+   ramp_enable = 0;
+   break;
+   }
+
+   s2mps11->ramp_delay2 = ramp_delay;
+   ramp_shift = S2MPS11_BUCK2_RAMP_SHIFT;
+   ramp_reg = S2MPS11_REG_RAMP;
+   break;
+   case S2MPS11_BUCK3:
+   enable_shift = S2MPS11_BUCK3_RAMP_EN_SHIFT;
+   if (!ramp_delay) {
+   ramp_enable = 0;
+   break;
+   }
+
+   if (ramp_delay > s2mps11->ramp_delay34)
+   s2mps11->ramp_delay34 = ramp_delay;
+   else
+   ramp_delay = s2mps11->ramp_delay34;
+
+   ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT;
+   ramp_reg = S2MPS11_REG_RAMP;
+   break;
+   case S2MPS11_BUCK4:
+   enable_shift = S2MPS11_BUCK4_RAMP_EN_SHIFT;
+   if (!ramp_delay) {
+   ramp_enable = 0;
+   break;
+   }
+
+   if (ramp_delay > s2mps11->ramp_delay34)
+   s2mps11->ramp_delay34 = ramp_delay;
+   else
+   ramp_delay = s2mps11->ramp_delay34;
+
+   ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT;
+   ramp_reg = S2MPS11_REG_RAMP;
+   break;
+   case S2MPS11_BUCK5:
+   s2mps11->ramp_delay5 = ramp_delay;
+   ramp_shift = S2MPS11_BUCK5_RAMP_SHIFT;
+   break;
+   case S2MPS11_BUCK6:
+   enable_shift = S2MPS11_BUCK6_RAMP_EN_SHIFT;
+   if (!ramp_delay) {
+   ramp_enable = 0;
+   break;
+   }
+
+   if (ramp_delay > s2mps11->ramp_delay16)
+   s2mps11->ramp_delay16 = ramp_delay;
+   else
+   ramp_delay = s2mps11->ramp_delay16;
+
+   ramp_shift = S2MPS11_BUCK16_RAMP_SHIFT;
+   break;
+   case S2MPS11_BUCK7:
+   case S2MPS11_BUCK8:
+   case S2MPS11_BUCK10:
+   if (ramp_delay > s2mps11->ramp_delay7810)
+   s2mps11->ramp_delay7810 = ramp_delay;
+   else
+   ramp_delay = s2mps11->ramp_delay7810;
+
+   ramp_shift = S2MPS11_BUCK7810_RAMP_SHIFT;
+   break;
+   case S2MPS11_BUCK9:
+   s2mps11->ramp_delay9 = ramp_delay;
+   ramp_shift = S2MPS11_BUCK9_RAMP_SHIFT;
+   break;
+   default:
+   return 0;
+   }
+
+   if (!ramp_enable)
+   goto ramp_disable;
+
+   if (enable_shift) {
+   ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP,
+   1 << enable_shift, 1 << enable_shift);
+   if (ret) {
+   dev_err(>dev, "failed to enable ramp rate\n");
+   return ret;
+   }
+   }
+
+   ramp_val = get_ramp_delay(ramp_delay);
+
+   return regmap_update_bits(rdev->regmap, ramp_reg,
+ ramp_val << ramp_shift, 1 << ramp_shift);
+
+ramp_disable:
+ 

[v2 PATCH 3/6] regulator: s2mps11: Add DT support

2013-07-08 Thread Yadwinder Singh Brar
This patch adds DT support for parsing regulators constraints for parent(mfd)
node and moves some common intialising code out of loop while registering.

Signed-off-by: Yadwinder Singh Brar 
---
 drivers/regulator/s2mps11.c |   48 +-
 1 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 4bebcb6..4157759 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -20,9 +20,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
+#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators)
+
 struct s2mps11_info {
struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX];
 
@@ -407,22 +410,38 @@ static int s2mps11_pmic_probe(struct platform_device 
*pdev)
 {
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
+   struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX];
+   struct device_node *reg_np = NULL;
struct regulator_config config = { };
struct s2mps11_info *s2mps11;
int i, ret;
unsigned char ramp_enable, ramp_reg = 0;
 
-   if (!pdata) {
-   dev_err(pdev->dev.parent, "Platform data not supplied\n");
-   return -ENODEV;
-   }
-
s2mps11 = devm_kzalloc(>dev, sizeof(struct s2mps11_info),
GFP_KERNEL);
if (!s2mps11)
return -ENOMEM;
 
-   platform_set_drvdata(pdev, s2mps11);
+   if (!iodev->dev->of_node)
+   goto p_data;
+
+   for (i = 0; i < S2MPS11_REGULATOR_CNT; i++)
+   rdata[i].name = regulators[i].name;
+
+   reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators");
+   if (!reg_np) {
+   dev_err(>dev, "could not find regulators sub-node\n");
+   return -EINVAL;
+   }
+
+   of_regulator_match(>dev, reg_np, rdata, S2MPS11_REGULATOR_MAX);
+
+   goto common_reg;
+p_data:
+   if (!pdata) {
+   dev_err(pdev->dev.parent, "Platform data not supplied\n");
+   return -ENODEV;
+   }
 
s2mps11->ramp_delay2 = pdata->buck2_ramp_delay;
s2mps11->ramp_delay34 = pdata->buck34_ramp_delay;
@@ -454,12 +473,19 @@ static int s2mps11_pmic_probe(struct platform_device 
*pdev)
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
 
-   for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
+common_reg:
+   platform_set_drvdata(pdev, s2mps11);
 
-   config.dev = >dev;
-   config.regmap = iodev->regmap;
-   config.init_data = pdata->regulators[i].initdata;
-   config.driver_data = s2mps11;
+   config.dev = >dev;
+   config.regmap = iodev->regmap;
+   config.driver_data = s2mps11;
+   for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
+   if (!reg_np) {
+   config.init_data = pdata->regulators[i].initdata;
+   } else {
+   config.init_data = rdata[i].init_data;
+   config.of_node = rdata[i].of_node;
+   }
 
s2mps11->rdev[i] = regulator_register([i], );
if (IS_ERR(s2mps11->rdev[i])) {
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 1/6] regulator: core: Add support for disabling ramp delay

2013-07-08 Thread Yadwinder Singh Brar
Some hardwares support disabling ramp delay, so adding ramp_disable flag to
constraints. It will be used to figure out whether ramp_delay in constraints
is explicitly set to zero or its unintialized (zero by default).
And we don't need to call set_voltage_time_sel() for regulators for whom ramp
delay is disabled in constraints.

Signed-off-by: Yadwinder Singh Brar 
---
 .../devicetree/bindings/regulator/regulator.txt|2 ++
 drivers/regulator/core.c   |6 --
 drivers/regulator/of_regulator.c   |   12 +---
 include/linux/regulator/machine.h  |1 +
 4 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt 
b/Documentation/devicetree/bindings/regulator/regulator.txt
index 48a3b8e..2bd8f09 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/regulator.txt
@@ -12,6 +12,8 @@ Optional properties:
 - regulator-allow-bypass: allow the regulator to go into bypass mode
 - -supply: phandle to the parent supply/regulator node
 - regulator-ramp-delay: ramp delay for regulator(in uV/uS)
+  For hardwares which support disabling ramp rate, it should be explicitly
+  intialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay.
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 288c75a..6e6371c 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -984,7 +984,8 @@ static int set_machine_constraints(struct regulator_dev 
*rdev,
}
}
 
-   if (rdev->constraints->ramp_delay && ops->set_ramp_delay) {
+   if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable)
+   && ops->set_ramp_delay) {
ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
if (ret < 0) {
rdev_err(rdev, "failed to set ramp_delay\n");
@@ -2438,7 +2439,8 @@ static int _regulator_do_set_voltage(struct regulator_dev 
*rdev,
}
 
/* Call set_voltage_time_sel if successfully obtained old_selector */
-   if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 &&
+   if (ret == 0 && !rdev->constraints->ramp_disable &&
+   _regulator_is_enabled(rdev) && old_selector >= 0 &&
old_selector != selector && rdev->desc->ops->set_voltage_time_sel) {
 
delay = rdev->desc->ops->set_voltage_time_sel(rdev,
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index f3c8f8f..7827384 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -21,6 +21,7 @@ static void of_get_regulation_constraints(struct device_node 
*np,
 {
const __be32 *min_uV, *max_uV, *uV_offset;
const __be32 *min_uA, *max_uA, *ramp_delay;
+   struct property *prop;
struct regulation_constraints *constraints = &(*init_data)->constraints;
 
constraints->name = of_get_property(np, "regulator-name", NULL);
@@ -64,9 +65,14 @@ static void of_get_regulation_constraints(struct device_node 
*np,
if (of_property_read_bool(np, "regulator-allow-bypass"))
constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
 
-   ramp_delay = of_get_property(np, "regulator-ramp-delay", NULL);
-   if (ramp_delay)
-   constraints->ramp_delay = be32_to_cpu(*ramp_delay);
+   prop = of_find_property(np, "regulator-ramp-delay", NULL);
+   if (prop && prop->value) {
+   ramp_delay = prop->value;
+   if (*ramp_delay)
+   constraints->ramp_delay = be32_to_cpu(*ramp_delay);
+   else
+   constraints->ramp_disable = true;
+   }
 }
 
 /**
diff --git a/include/linux/regulator/machine.h 
b/include/linux/regulator/machine.h
index 36adbc8..999b20c 100644
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -134,6 +134,7 @@ struct regulation_constraints {
unsigned always_on:1;   /* regulator never off when system is on */
unsigned boot_on:1; /* bootloader/firmware enabled regulator */
unsigned apply_uV:1;/* apply uV constraint if min == max */
+   unsigned ramp_disable:1; /* disable ramp delay */
 };
 
 /**
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 6/6] mfd: s2mps11: Add device tree support

2013-07-08 Thread Yadwinder Singh Brar
This patch adds DT compatible string for s2mps11 and binding documentation.

Signed-off-by: Yadwinder Singh Brar 
---
 Documentation/devicetree/bindings/mfd/s2mps11.txt |   89 +
 drivers/mfd/sec-core.c|3 +
 2 files changed, 92 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/s2mps11.txt

diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt 
b/Documentation/devicetree/bindings/mfd/s2mps11.txt
new file mode 100644
index 000..36269c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt
@@ -0,0 +1,89 @@
+
+* Samsung S2MPS11 Voltage and Current Regulator
+
+The Samsung S2MP211 is a multi-function device which includes voltage and
+current regulators, RTC, charger controller and other sub-blocks. It is
+interfaced to the host controller using a I2C interface. Each sub-block is
+addressed by the host system using different I2C slave address.
+
+Required properties:
+- compatible: Should be "samsung,s2mps11-pmic".
+- reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the interrupts from s2mps11 are delivered to.
+- interrupts: Interrupt specifiers for interrupt sources.
+
+Optional nodes:
+- regulators: The regulators of s2mps11 that have to be instantiated should be
+included in a sub-node named 'regulators'. Regulator nodes included in this
+sub-node should be of the format as listed below.
+
+   regulator_name {
+   [standard regulator constraints];
+   };
+
+ regulator-ramp-delay for BUCKs = [6250/12500/25000(default)/5] uV/us
+
+ BUCK[2/3/4/6] supports disabling ramp delay on hardware, so explictly
+ regulator-ramp-delay = <0> can be used for them to disable ramp delay.
+ In absence of regulator-ramp-delay property, default ramp delay will be used.
+
+NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
+for a particular group of BUCKs. So provide same regulator-ramp-delay.
+Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
+BUCK[3, 4], and BUCK[7, 8, 10]
+
+The regulator constraints inside the regulator nodes use the standard regulator
+bindings which are documented elsewhere.
+
+The following are the names of the regulators that the s2mps11 pmic block
+supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
+as per the datasheet of s2mps11.
+
+   - LDOn
+ - valid values for n are 1 to 28
+ - Example: LDO0, LD01, LDO28
+   - BUCKn
+ - valid values for n are 1 to 9.
+ - Example: BUCK1, BUCK2, BUCK9
+
+Example:
+
+   s2mps11_pmic@66 {
+   compatible = "samsung,s2mps11-pmic";
+   reg = <0x66>;
+
+   regulators {
+   ldo1_reg: LDO1 {
+   regulator-name = "VDD_ABB_3.3V";
+   regulator-min-microvolt = <330>;
+   regulator-max-microvolt = <330>;
+   };
+
+   ldo2_reg: LDO2 {
+   regulator-name = "VDD_ALIVE_1.1V";
+   regulator-min-microvolt = <110>;
+   regulator-max-microvolt = <110>;
+   regulator-always-on;
+   };
+
+   buck1_reg: BUCK1 {
+   regulator-name = "vdd_mif";
+   regulator-min-microvolt = <95>;
+   regulator-max-microvolt = <135>;
+   regulator-always-on;
+   regulator-boot-on;
+   };
+
+   buck2_reg: BUCK2 {
+   regulator-name = "vdd_arm";
+   regulator-min-microvolt = <95>;
+   regulator-max-microvolt = <135>;
+   regulator-always-on;
+   regulator-boot-on;
+   regulator-ramp-delay = <5>;
+   };
+   };
+   };
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 77ee26e..760da8a 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -66,6 +66,9 @@ static struct of_device_id sec_dt_match[] = {
{   .compatible = "samsung,s5m8767-pmic",
.data = (void *)S5M8767X,
},
+   {   .compatible = "samsung,s2mps11-pmic",
+   .data = (void *)S2MPS11X,
+   },
{},
 };
 #endif
-- 
1.7.0.4

--
To unsubscribe from this list: send 

[v2 PATCH 4/6] regulator: s2mps11: Convert driver completely to use set_ramp_delay callback

2013-07-08 Thread Yadwinder Singh Brar
Since now we have ramp_delay and ramp_disable as standard regulator
constraints and DT part using it so this patch removes legacy part i.e. getting
ramp_delayxx and ramp_enable from pdata since it can be passed as
standard regulator constraints.

Signed-off-by: Yadwinder Singh Brar 
---
 drivers/regulator/s2mps11.c |   62 ++
 1 files changed, 9 insertions(+), 53 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 4157759..e1aadbd 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -35,11 +35,6 @@ struct s2mps11_info {
int ramp_delay16;
int ramp_delay7810;
int ramp_delay9;
-
-   bool buck6_ramp;
-   bool buck2_ramp;
-   bool buck3_ramp;
-   bool buck4_ramp;
 };
 
 static int get_ramp_delay(int ramp_delay)
@@ -67,26 +62,18 @@ static int s2mps11_regulator_set_voltage_time_sel(struct 
regulator_dev *rdev,
 
switch (rdev->desc->id) {
case S2MPS11_BUCK2:
-   if (!s2mps11->buck2_ramp)
-   return 0;
ramp_delay = s2mps11->ramp_delay2;
break;
case S2MPS11_BUCK3:
-   if (!s2mps11->buck3_ramp)
-   return 0;
ramp_delay = s2mps11->ramp_delay34;
break;
case S2MPS11_BUCK4:
-   if (!s2mps11->buck4_ramp)
-   return 0;
ramp_delay = s2mps11->ramp_delay34;
break;
case S2MPS11_BUCK5:
ramp_delay = s2mps11->ramp_delay5;
break;
case S2MPS11_BUCK6:
-   if (!s2mps11->buck6_ramp)
-   return 0;
case S2MPS11_BUCK1:
ramp_delay = s2mps11->ramp_delay16;
break;
@@ -415,15 +402,21 @@ static int s2mps11_pmic_probe(struct platform_device 
*pdev)
struct regulator_config config = { };
struct s2mps11_info *s2mps11;
int i, ret;
-   unsigned char ramp_enable, ramp_reg = 0;
 
s2mps11 = devm_kzalloc(>dev, sizeof(struct s2mps11_info),
GFP_KERNEL);
if (!s2mps11)
return -ENOMEM;
 
-   if (!iodev->dev->of_node)
-   goto p_data;
+   if (!iodev->dev->of_node) {
+   if (pdata) {
+   goto common_reg;
+   } else {
+   dev_err(pdev->dev.parent,
+   "Platform data or DT node not supplied\n");
+   return -ENODEV;
+   }
+   }
 
for (i = 0; i < S2MPS11_REGULATOR_CNT; i++)
rdata[i].name = regulators[i].name;
@@ -436,43 +429,6 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 
of_regulator_match(>dev, reg_np, rdata, S2MPS11_REGULATOR_MAX);
 
-   goto common_reg;
-p_data:
-   if (!pdata) {
-   dev_err(pdev->dev.parent, "Platform data not supplied\n");
-   return -ENODEV;
-   }
-
-   s2mps11->ramp_delay2 = pdata->buck2_ramp_delay;
-   s2mps11->ramp_delay34 = pdata->buck34_ramp_delay;
-   s2mps11->ramp_delay5 = pdata->buck5_ramp_delay;
-   s2mps11->ramp_delay16 = pdata->buck16_ramp_delay;
-   s2mps11->ramp_delay7810 = pdata->buck7810_ramp_delay;
-   s2mps11->ramp_delay9 = pdata->buck9_ramp_delay;
-
-   s2mps11->buck6_ramp = pdata->buck6_ramp_enable;
-   s2mps11->buck2_ramp = pdata->buck2_ramp_enable;
-   s2mps11->buck3_ramp = pdata->buck3_ramp_enable;
-   s2mps11->buck4_ramp = pdata->buck4_ramp_enable;
-
-   ramp_enable = (s2mps11->buck2_ramp << 3) | (s2mps11->buck3_ramp << 2) |
-   (s2mps11->buck4_ramp << 1) | s2mps11->buck6_ramp ;
-
-   if (ramp_enable) {
-   if (s2mps11->buck2_ramp)
-   ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6;
-   if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
-   ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4;
-   sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
-   }
-
-   ramp_reg &= 0x00;
-   ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6;
-   ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4;
-   ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2;
-   ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
-   sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
-
 common_reg:
platform_set_drvdata(pdev, s2mps11);
 
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 0/6] Add DT support for s2mps11

2013-07-08 Thread Yadwinder Singh Brar
Mainly this series adds dt support for s2mps11 in mfd and regulator driver.

changes since v1:
- As suggested by Mark, used regulator-ramp-delay = <0> as ramp_disable and
  Moved the ramp_disable into regulator constraints as it is quite generic.
- Implemented set_ramp_delay callback, to make driver simple and in more
  compliance with framework.
- Modified Documentation accordingly.
- Fixed some NITs pointed by Sachin.

It also includes a patch to remove some redundant checks in 
_regulator_do_set_voltage().

Yadwinder Singh Brar (6):
  regulator: core: Add support for disabling ramp delay
  regulator: s2mps11: Implement set_ramp_rate callback for bucks
  regulator: s2mps11: Add DT support
  regulator: s2mps11: Convert driver completely to use set_ramp_delay
callback
  regulator: core: Remove redundant checks
  mfd: s2mps11: Add device tree support

 Documentation/devicetree/bindings/mfd/s2mps11.txt  |   89 +
 .../devicetree/bindings/regulator/regulator.txt|2 +
 drivers/mfd/sec-core.c |3 +
 drivers/regulator/core.c   |7 +-
 drivers/regulator/of_regulator.c   |   12 +-
 drivers/regulator/s2mps11.c|  203 +++-
 include/linux/mfd/samsung/s2mps11.h|   11 +
 include/linux/regulator/machine.h  |1 +
 8 files changed, 270 insertions(+), 58 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/s2mps11.txt

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 5/6] regulator: core: Remove redundant checks

2013-07-08 Thread Yadwinder Singh Brar
In function _regulator_do_set_voltage(), old_selector gets intialised only
if (_regulator_is_enabled(rdev) && rdev->desc->ops->set_voltage_time_sel &&
rdev->desc->ops->get_voltage_sel)) is true.

Before calling set_voltage_time_sel() we checks if (old_selector >= 0) and it
will true if it got intialised properly. so we don't need to check again
_regulator_is_enabled(rdev) && rdev->desc->ops->set_voltage_time_sel before
calling set_voltage_time_sel().

Signed-off-by: Yadwinder Singh Brar 
---
 drivers/regulator/core.c |5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 6e6371c..15368f3 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2439,9 +2439,8 @@ static int _regulator_do_set_voltage(struct regulator_dev 
*rdev,
}
 
/* Call set_voltage_time_sel if successfully obtained old_selector */
-   if (ret == 0 && !rdev->constraints->ramp_disable &&
-   _regulator_is_enabled(rdev) && old_selector >= 0 &&
-   old_selector != selector && rdev->desc->ops->set_voltage_time_sel) {
+   if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0
+   && old_selector != selector) {
 
delay = rdev->desc->ops->set_voltage_time_sel(rdev,
old_selector, selector);
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 0/6] Add DT support for s2mps11

2013-07-08 Thread Yadwinder Singh Brar
Mainly this series adds dt support for s2mps11 in mfd and regulator driver.

changes since v1:
- As suggested by Mark, used regulator-ramp-delay = 0 as ramp_disable and
  Moved the ramp_disable into regulator constraints as it is quite generic.
- Implemented set_ramp_delay callback, to make driver simple and in more
  compliance with framework.
- Modified Documentation accordingly.
- Fixed some NITs pointed by Sachin.

It also includes a patch to remove some redundant checks in 
_regulator_do_set_voltage().

Yadwinder Singh Brar (6):
  regulator: core: Add support for disabling ramp delay
  regulator: s2mps11: Implement set_ramp_rate callback for bucks
  regulator: s2mps11: Add DT support
  regulator: s2mps11: Convert driver completely to use set_ramp_delay
callback
  regulator: core: Remove redundant checks
  mfd: s2mps11: Add device tree support

 Documentation/devicetree/bindings/mfd/s2mps11.txt  |   89 +
 .../devicetree/bindings/regulator/regulator.txt|2 +
 drivers/mfd/sec-core.c |3 +
 drivers/regulator/core.c   |7 +-
 drivers/regulator/of_regulator.c   |   12 +-
 drivers/regulator/s2mps11.c|  203 +++-
 include/linux/mfd/samsung/s2mps11.h|   11 +
 include/linux/regulator/machine.h  |1 +
 8 files changed, 270 insertions(+), 58 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/s2mps11.txt

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 4/6] regulator: s2mps11: Convert driver completely to use set_ramp_delay callback

2013-07-08 Thread Yadwinder Singh Brar
Since now we have ramp_delay and ramp_disable as standard regulator
constraints and DT part using it so this patch removes legacy part i.e. getting
ramp_delayxx and ramp_enable from pdata since it can be passed as
standard regulator constraints.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/regulator/s2mps11.c |   62 ++
 1 files changed, 9 insertions(+), 53 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 4157759..e1aadbd 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -35,11 +35,6 @@ struct s2mps11_info {
int ramp_delay16;
int ramp_delay7810;
int ramp_delay9;
-
-   bool buck6_ramp;
-   bool buck2_ramp;
-   bool buck3_ramp;
-   bool buck4_ramp;
 };
 
 static int get_ramp_delay(int ramp_delay)
@@ -67,26 +62,18 @@ static int s2mps11_regulator_set_voltage_time_sel(struct 
regulator_dev *rdev,
 
switch (rdev-desc-id) {
case S2MPS11_BUCK2:
-   if (!s2mps11-buck2_ramp)
-   return 0;
ramp_delay = s2mps11-ramp_delay2;
break;
case S2MPS11_BUCK3:
-   if (!s2mps11-buck3_ramp)
-   return 0;
ramp_delay = s2mps11-ramp_delay34;
break;
case S2MPS11_BUCK4:
-   if (!s2mps11-buck4_ramp)
-   return 0;
ramp_delay = s2mps11-ramp_delay34;
break;
case S2MPS11_BUCK5:
ramp_delay = s2mps11-ramp_delay5;
break;
case S2MPS11_BUCK6:
-   if (!s2mps11-buck6_ramp)
-   return 0;
case S2MPS11_BUCK1:
ramp_delay = s2mps11-ramp_delay16;
break;
@@ -415,15 +402,21 @@ static int s2mps11_pmic_probe(struct platform_device 
*pdev)
struct regulator_config config = { };
struct s2mps11_info *s2mps11;
int i, ret;
-   unsigned char ramp_enable, ramp_reg = 0;
 
s2mps11 = devm_kzalloc(pdev-dev, sizeof(struct s2mps11_info),
GFP_KERNEL);
if (!s2mps11)
return -ENOMEM;
 
-   if (!iodev-dev-of_node)
-   goto p_data;
+   if (!iodev-dev-of_node) {
+   if (pdata) {
+   goto common_reg;
+   } else {
+   dev_err(pdev-dev.parent,
+   Platform data or DT node not supplied\n);
+   return -ENODEV;
+   }
+   }
 
for (i = 0; i  S2MPS11_REGULATOR_CNT; i++)
rdata[i].name = regulators[i].name;
@@ -436,43 +429,6 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
 
of_regulator_match(pdev-dev, reg_np, rdata, S2MPS11_REGULATOR_MAX);
 
-   goto common_reg;
-p_data:
-   if (!pdata) {
-   dev_err(pdev-dev.parent, Platform data not supplied\n);
-   return -ENODEV;
-   }
-
-   s2mps11-ramp_delay2 = pdata-buck2_ramp_delay;
-   s2mps11-ramp_delay34 = pdata-buck34_ramp_delay;
-   s2mps11-ramp_delay5 = pdata-buck5_ramp_delay;
-   s2mps11-ramp_delay16 = pdata-buck16_ramp_delay;
-   s2mps11-ramp_delay7810 = pdata-buck7810_ramp_delay;
-   s2mps11-ramp_delay9 = pdata-buck9_ramp_delay;
-
-   s2mps11-buck6_ramp = pdata-buck6_ramp_enable;
-   s2mps11-buck2_ramp = pdata-buck2_ramp_enable;
-   s2mps11-buck3_ramp = pdata-buck3_ramp_enable;
-   s2mps11-buck4_ramp = pdata-buck4_ramp_enable;
-
-   ramp_enable = (s2mps11-buck2_ramp  3) | (s2mps11-buck3_ramp  2) |
-   (s2mps11-buck4_ramp  1) | s2mps11-buck6_ramp ;
-
-   if (ramp_enable) {
-   if (s2mps11-buck2_ramp)
-   ramp_reg |= get_ramp_delay(s2mps11-ramp_delay2)  6;
-   if (s2mps11-buck3_ramp || s2mps11-buck4_ramp)
-   ramp_reg |= get_ramp_delay(s2mps11-ramp_delay34)  4;
-   sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
-   }
-
-   ramp_reg = 0x00;
-   ramp_reg |= get_ramp_delay(s2mps11-ramp_delay5)  6;
-   ramp_reg |= get_ramp_delay(s2mps11-ramp_delay16)  4;
-   ramp_reg |= get_ramp_delay(s2mps11-ramp_delay7810)  2;
-   ramp_reg |= get_ramp_delay(s2mps11-ramp_delay9);
-   sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
-
 common_reg:
platform_set_drvdata(pdev, s2mps11);
 
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 5/6] regulator: core: Remove redundant checks

2013-07-08 Thread Yadwinder Singh Brar
In function _regulator_do_set_voltage(), old_selector gets intialised only
if (_regulator_is_enabled(rdev)  rdev-desc-ops-set_voltage_time_sel 
rdev-desc-ops-get_voltage_sel)) is true.

Before calling set_voltage_time_sel() we checks if (old_selector = 0) and it
will true if it got intialised properly. so we don't need to check again
_regulator_is_enabled(rdev)  rdev-desc-ops-set_voltage_time_sel before
calling set_voltage_time_sel().

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/regulator/core.c |5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 6e6371c..15368f3 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2439,9 +2439,8 @@ static int _regulator_do_set_voltage(struct regulator_dev 
*rdev,
}
 
/* Call set_voltage_time_sel if successfully obtained old_selector */
-   if (ret == 0  !rdev-constraints-ramp_disable 
-   _regulator_is_enabled(rdev)  old_selector = 0 
-   old_selector != selector  rdev-desc-ops-set_voltage_time_sel) {
+   if (ret == 0  !rdev-constraints-ramp_disable  old_selector = 0
+old_selector != selector) {
 
delay = rdev-desc-ops-set_voltage_time_sel(rdev,
old_selector, selector);
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 6/6] mfd: s2mps11: Add device tree support

2013-07-08 Thread Yadwinder Singh Brar
This patch adds DT compatible string for s2mps11 and binding documentation.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 Documentation/devicetree/bindings/mfd/s2mps11.txt |   89 +
 drivers/mfd/sec-core.c|3 +
 2 files changed, 92 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/s2mps11.txt

diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt 
b/Documentation/devicetree/bindings/mfd/s2mps11.txt
new file mode 100644
index 000..36269c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt
@@ -0,0 +1,89 @@
+
+* Samsung S2MPS11 Voltage and Current Regulator
+
+The Samsung S2MP211 is a multi-function device which includes voltage and
+current regulators, RTC, charger controller and other sub-blocks. It is
+interfaced to the host controller using a I2C interface. Each sub-block is
+addressed by the host system using different I2C slave address.
+
+Required properties:
+- compatible: Should be samsung,s2mps11-pmic.
+- reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the interrupts from s2mps11 are delivered to.
+- interrupts: Interrupt specifiers for interrupt sources.
+
+Optional nodes:
+- regulators: The regulators of s2mps11 that have to be instantiated should be
+included in a sub-node named 'regulators'. Regulator nodes included in this
+sub-node should be of the format as listed below.
+
+   regulator_name {
+   [standard regulator constraints];
+   };
+
+ regulator-ramp-delay for BUCKs = [6250/12500/25000(default)/5] uV/us
+
+ BUCK[2/3/4/6] supports disabling ramp delay on hardware, so explictly
+ regulator-ramp-delay = 0 can be used for them to disable ramp delay.
+ In absence of regulator-ramp-delay property, default ramp delay will be used.
+
+NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
+for a particular group of BUCKs. So provide same regulator-ramp-delayvalue.
+Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
+BUCK[3, 4], and BUCK[7, 8, 10]
+
+The regulator constraints inside the regulator nodes use the standard regulator
+bindings which are documented elsewhere.
+
+The following are the names of the regulators that the s2mps11 pmic block
+supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
+as per the datasheet of s2mps11.
+
+   - LDOn
+ - valid values for n are 1 to 28
+ - Example: LDO0, LD01, LDO28
+   - BUCKn
+ - valid values for n are 1 to 9.
+ - Example: BUCK1, BUCK2, BUCK9
+
+Example:
+
+   s2mps11_pmic@66 {
+   compatible = samsung,s2mps11-pmic;
+   reg = 0x66;
+
+   regulators {
+   ldo1_reg: LDO1 {
+   regulator-name = VDD_ABB_3.3V;
+   regulator-min-microvolt = 330;
+   regulator-max-microvolt = 330;
+   };
+
+   ldo2_reg: LDO2 {
+   regulator-name = VDD_ALIVE_1.1V;
+   regulator-min-microvolt = 110;
+   regulator-max-microvolt = 110;
+   regulator-always-on;
+   };
+
+   buck1_reg: BUCK1 {
+   regulator-name = vdd_mif;
+   regulator-min-microvolt = 95;
+   regulator-max-microvolt = 135;
+   regulator-always-on;
+   regulator-boot-on;
+   };
+
+   buck2_reg: BUCK2 {
+   regulator-name = vdd_arm;
+   regulator-min-microvolt = 95;
+   regulator-max-microvolt = 135;
+   regulator-always-on;
+   regulator-boot-on;
+   regulator-ramp-delay = 5;
+   };
+   };
+   };
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 77ee26e..760da8a 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -66,6 +66,9 @@ static struct of_device_id sec_dt_match[] = {
{   .compatible = samsung,s5m8767-pmic,
.data = (void *)S5M8767X,
},
+   {   .compatible = samsung,s2mps11-pmic,
+   .data = (void *)S2MPS11X,
+   },
{},
 };
 #endif
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[v2 PATCH 1/6] regulator: core: Add support for disabling ramp delay

2013-07-08 Thread Yadwinder Singh Brar
Some hardwares support disabling ramp delay, so adding ramp_disable flag to
constraints. It will be used to figure out whether ramp_delay in constraints
is explicitly set to zero or its unintialized (zero by default).
And we don't need to call set_voltage_time_sel() for regulators for whom ramp
delay is disabled in constraints.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 .../devicetree/bindings/regulator/regulator.txt|2 ++
 drivers/regulator/core.c   |6 --
 drivers/regulator/of_regulator.c   |   12 +---
 include/linux/regulator/machine.h  |1 +
 4 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt 
b/Documentation/devicetree/bindings/regulator/regulator.txt
index 48a3b8e..2bd8f09 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/regulator.txt
@@ -12,6 +12,8 @@ Optional properties:
 - regulator-allow-bypass: allow the regulator to go into bypass mode
 - name-supply: phandle to the parent supply/regulator node
 - regulator-ramp-delay: ramp delay for regulator(in uV/uS)
+  For hardwares which support disabling ramp rate, it should be explicitly
+  intialised to zero (regulator-ramp-delay = 0) for disabling ramp delay.
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 288c75a..6e6371c 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -984,7 +984,8 @@ static int set_machine_constraints(struct regulator_dev 
*rdev,
}
}
 
-   if (rdev-constraints-ramp_delay  ops-set_ramp_delay) {
+   if ((rdev-constraints-ramp_delay || rdev-constraints-ramp_disable)
+ops-set_ramp_delay) {
ret = ops-set_ramp_delay(rdev, rdev-constraints-ramp_delay);
if (ret  0) {
rdev_err(rdev, failed to set ramp_delay\n);
@@ -2438,7 +2439,8 @@ static int _regulator_do_set_voltage(struct regulator_dev 
*rdev,
}
 
/* Call set_voltage_time_sel if successfully obtained old_selector */
-   if (ret == 0  _regulator_is_enabled(rdev)  old_selector = 0 
+   if (ret == 0  !rdev-constraints-ramp_disable 
+   _regulator_is_enabled(rdev)  old_selector = 0 
old_selector != selector  rdev-desc-ops-set_voltage_time_sel) {
 
delay = rdev-desc-ops-set_voltage_time_sel(rdev,
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index f3c8f8f..7827384 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -21,6 +21,7 @@ static void of_get_regulation_constraints(struct device_node 
*np,
 {
const __be32 *min_uV, *max_uV, *uV_offset;
const __be32 *min_uA, *max_uA, *ramp_delay;
+   struct property *prop;
struct regulation_constraints *constraints = (*init_data)-constraints;
 
constraints-name = of_get_property(np, regulator-name, NULL);
@@ -64,9 +65,14 @@ static void of_get_regulation_constraints(struct device_node 
*np,
if (of_property_read_bool(np, regulator-allow-bypass))
constraints-valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
 
-   ramp_delay = of_get_property(np, regulator-ramp-delay, NULL);
-   if (ramp_delay)
-   constraints-ramp_delay = be32_to_cpu(*ramp_delay);
+   prop = of_find_property(np, regulator-ramp-delay, NULL);
+   if (prop  prop-value) {
+   ramp_delay = prop-value;
+   if (*ramp_delay)
+   constraints-ramp_delay = be32_to_cpu(*ramp_delay);
+   else
+   constraints-ramp_disable = true;
+   }
 }
 
 /**
diff --git a/include/linux/regulator/machine.h 
b/include/linux/regulator/machine.h
index 36adbc8..999b20c 100644
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -134,6 +134,7 @@ struct regulation_constraints {
unsigned always_on:1;   /* regulator never off when system is on */
unsigned boot_on:1; /* bootloader/firmware enabled regulator */
unsigned apply_uV:1;/* apply uV constraint if min == max */
+   unsigned ramp_disable:1; /* disable ramp delay */
 };
 
 /**
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 3/6] regulator: s2mps11: Add DT support

2013-07-08 Thread Yadwinder Singh Brar
This patch adds DT support for parsing regulators constraints for parent(mfd)
node and moves some common intialising code out of loop while registering.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/regulator/s2mps11.c |   48 +-
 1 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 4bebcb6..4157759 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -20,9 +20,12 @@
 #include linux/platform_device.h
 #include linux/regulator/driver.h
 #include linux/regulator/machine.h
+#include linux/regulator/of_regulator.h
 #include linux/mfd/samsung/core.h
 #include linux/mfd/samsung/s2mps11.h
 
+#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators)
+
 struct s2mps11_info {
struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX];
 
@@ -407,22 +410,38 @@ static int s2mps11_pmic_probe(struct platform_device 
*pdev)
 {
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev-dev.parent);
struct sec_platform_data *pdata = dev_get_platdata(iodev-dev);
+   struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX];
+   struct device_node *reg_np = NULL;
struct regulator_config config = { };
struct s2mps11_info *s2mps11;
int i, ret;
unsigned char ramp_enable, ramp_reg = 0;
 
-   if (!pdata) {
-   dev_err(pdev-dev.parent, Platform data not supplied\n);
-   return -ENODEV;
-   }
-
s2mps11 = devm_kzalloc(pdev-dev, sizeof(struct s2mps11_info),
GFP_KERNEL);
if (!s2mps11)
return -ENOMEM;
 
-   platform_set_drvdata(pdev, s2mps11);
+   if (!iodev-dev-of_node)
+   goto p_data;
+
+   for (i = 0; i  S2MPS11_REGULATOR_CNT; i++)
+   rdata[i].name = regulators[i].name;
+
+   reg_np = of_find_node_by_name(iodev-dev-of_node, regulators);
+   if (!reg_np) {
+   dev_err(pdev-dev, could not find regulators sub-node\n);
+   return -EINVAL;
+   }
+
+   of_regulator_match(pdev-dev, reg_np, rdata, S2MPS11_REGULATOR_MAX);
+
+   goto common_reg;
+p_data:
+   if (!pdata) {
+   dev_err(pdev-dev.parent, Platform data not supplied\n);
+   return -ENODEV;
+   }
 
s2mps11-ramp_delay2 = pdata-buck2_ramp_delay;
s2mps11-ramp_delay34 = pdata-buck34_ramp_delay;
@@ -454,12 +473,19 @@ static int s2mps11_pmic_probe(struct platform_device 
*pdev)
ramp_reg |= get_ramp_delay(s2mps11-ramp_delay9);
sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
 
-   for (i = 0; i  S2MPS11_REGULATOR_MAX; i++) {
+common_reg:
+   platform_set_drvdata(pdev, s2mps11);
 
-   config.dev = pdev-dev;
-   config.regmap = iodev-regmap;
-   config.init_data = pdata-regulators[i].initdata;
-   config.driver_data = s2mps11;
+   config.dev = pdev-dev;
+   config.regmap = iodev-regmap;
+   config.driver_data = s2mps11;
+   for (i = 0; i  S2MPS11_REGULATOR_MAX; i++) {
+   if (!reg_np) {
+   config.init_data = pdata-regulators[i].initdata;
+   } else {
+   config.init_data = rdata[i].init_data;
+   config.of_node = rdata[i].of_node;
+   }
 
s2mps11-rdev[i] = regulator_register(regulators[i], config);
if (IS_ERR(s2mps11-rdev[i])) {
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[v2 PATCH 2/6] regulator: s2mps11: Implement set_ramp_rate callback for bucks

2013-07-08 Thread Yadwinder Singh Brar
Implementing set_ramp_rate() and using standard constraints for getting
ramp_delay and ramp_disable, instead of getting it as s2mps11 specific data
through platform data, makes driver more compliant with framework and reduces
the complexity for adding DT support.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/regulator/s2mps11.c |  117 +++
 include/linux/mfd/samsung/s2mps11.h |   11 +++
 2 files changed, 128 insertions(+), 0 deletions(-)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index a671eb6..4bebcb6 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -16,6 +16,7 @@
 #include linux/gpio.h
 #include linux/slab.h
 #include linux/module.h
+#include linux/regmap.h
 #include linux/platform_device.h
 #include linux/regulator/driver.h
 #include linux/regulator/machine.h
@@ -104,6 +105,121 @@ static int s2mps11_regulator_set_voltage_time_sel(struct 
regulator_dev *rdev,
return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
 }
 
+static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+   struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
+   unsigned int ramp_val, ramp_shift, ramp_reg = S2MPS11_REG_RAMP_BUCK;
+   unsigned int ramp_enable = 1, enable_shift = 0;
+   int ret;
+
+   switch (rdev-desc-id) {
+   case S2MPS11_BUCK1:
+   if (ramp_delay  s2mps11-ramp_delay16)
+   s2mps11-ramp_delay16 = ramp_delay;
+   else
+   ramp_delay = s2mps11-ramp_delay16;
+
+   ramp_shift = S2MPS11_BUCK16_RAMP_SHIFT;
+   break;
+   case S2MPS11_BUCK2:
+   enable_shift = S2MPS11_BUCK2_RAMP_EN_SHIFT;
+   if (!ramp_delay) {
+   ramp_enable = 0;
+   break;
+   }
+
+   s2mps11-ramp_delay2 = ramp_delay;
+   ramp_shift = S2MPS11_BUCK2_RAMP_SHIFT;
+   ramp_reg = S2MPS11_REG_RAMP;
+   break;
+   case S2MPS11_BUCK3:
+   enable_shift = S2MPS11_BUCK3_RAMP_EN_SHIFT;
+   if (!ramp_delay) {
+   ramp_enable = 0;
+   break;
+   }
+
+   if (ramp_delay  s2mps11-ramp_delay34)
+   s2mps11-ramp_delay34 = ramp_delay;
+   else
+   ramp_delay = s2mps11-ramp_delay34;
+
+   ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT;
+   ramp_reg = S2MPS11_REG_RAMP;
+   break;
+   case S2MPS11_BUCK4:
+   enable_shift = S2MPS11_BUCK4_RAMP_EN_SHIFT;
+   if (!ramp_delay) {
+   ramp_enable = 0;
+   break;
+   }
+
+   if (ramp_delay  s2mps11-ramp_delay34)
+   s2mps11-ramp_delay34 = ramp_delay;
+   else
+   ramp_delay = s2mps11-ramp_delay34;
+
+   ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT;
+   ramp_reg = S2MPS11_REG_RAMP;
+   break;
+   case S2MPS11_BUCK5:
+   s2mps11-ramp_delay5 = ramp_delay;
+   ramp_shift = S2MPS11_BUCK5_RAMP_SHIFT;
+   break;
+   case S2MPS11_BUCK6:
+   enable_shift = S2MPS11_BUCK6_RAMP_EN_SHIFT;
+   if (!ramp_delay) {
+   ramp_enable = 0;
+   break;
+   }
+
+   if (ramp_delay  s2mps11-ramp_delay16)
+   s2mps11-ramp_delay16 = ramp_delay;
+   else
+   ramp_delay = s2mps11-ramp_delay16;
+
+   ramp_shift = S2MPS11_BUCK16_RAMP_SHIFT;
+   break;
+   case S2MPS11_BUCK7:
+   case S2MPS11_BUCK8:
+   case S2MPS11_BUCK10:
+   if (ramp_delay  s2mps11-ramp_delay7810)
+   s2mps11-ramp_delay7810 = ramp_delay;
+   else
+   ramp_delay = s2mps11-ramp_delay7810;
+
+   ramp_shift = S2MPS11_BUCK7810_RAMP_SHIFT;
+   break;
+   case S2MPS11_BUCK9:
+   s2mps11-ramp_delay9 = ramp_delay;
+   ramp_shift = S2MPS11_BUCK9_RAMP_SHIFT;
+   break;
+   default:
+   return 0;
+   }
+
+   if (!ramp_enable)
+   goto ramp_disable;
+
+   if (enable_shift) {
+   ret = regmap_update_bits(rdev-regmap, S2MPS11_REG_RAMP,
+   1  enable_shift, 1  enable_shift);
+   if (ret) {
+   dev_err(rdev-dev, failed to enable ramp rate\n);
+   return ret;
+   }
+   }
+
+   ramp_val = get_ramp_delay(ramp_delay);
+
+   return regmap_update_bits(rdev-regmap, ramp_reg,
+ ramp_val  ramp_shift, 1  ramp_shift);
+
+ramp_disable:
+   return

Re: [v2 PATCH 6/6] mfd: s2mps11: Add device tree support

2013-07-08 Thread Yadwinder Singh Brar
On Mon, Jul 8, 2013 at 6:58 PM, Mark Brown broo...@kernel.org wrote:
 On Sat, Jun 29, 2013 at 06:21:20PM +0530, Yadwinder Singh Brar wrote:
 This patch adds DT compatible string for s2mps11 and binding documentation.

 Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com

 Reviewed-by: Mark Brown broo...@linaro.org

 It looks like this should be OK to merge via the MFD tree separately to
 the regulator changes, or I can apply it to the regualtor tree if that's
 easier for people.

Yes, it can be merged via MFD, thats why I put it at last.
Either way it will fine.

Thanks,
Yadwinder
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   >