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 = {
> 

RE: [PATCH] mfd: max77686: Fix parent of rtc device

2014-12-03 Thread Yadwinder Singh Brar


On Tuesday, December 02, 2014 7:04 PM, Krzysztof Kozłowski wrote: 
 On 02.12.2014 13:45, Yadwinder Singh Brar wrote:
  rtc have different i2c client than power(pmic) block. So rtc device
  should sit under its own i2c client in device hierarchy, which
 reflects in sysfs also.
  This patch modifies code to register rtc cell with rtc-dev as
 parent.
 
  Without this patch :
  # ls /sys/class/i2c-adapter/i2c-0/0-0009/
  driver max77686-pmic  modalias   power  uevent
  max77686-clk   max77686-rtc   name   subsystem
 
  After applying patch :
  # ls /sys/class/i2c-adapter/i2c-0/0-0006/
  driver/modalias   power/ uevent
  max77686-rtc/  name   subsystem/
 
  Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
  ---
 
  Or Can we follow another (exhaustive but more cleaner) approach,
 which
  will be more like code refactoring and cleanup rather than only fix:
  Since rtc uses i2c client, which gets created using i2c_new_dummy()
  and is not shared by any other cell of max77686. So we can covert rtc
  platform driver itself to i2c client driver. It will also allow to
  expilicitly describe max77686-rtc in DT which we can't do now.
  It can be applicable to some other existing and new mfd pmic drivers.
  Any suggestion/comments ?
 
 Hi,
 
 What kind of problem is solved by this patch?


Let me try to explain once again :)
After seeing a message i2c i2c-0:  , addr=0x06, .. in dmesg log,
I was not able to find any such device in sysfs as well as device tree.
There was no device under /sys/class/i2c-dev/i2c-0/device/0-0006/
Isn't something wrong or missing ?

This patch fixes that missing parent child relation, which IMO
should be correct always, though it causes any major problem or not.

Still I am thinking, 0-0006 slave device(rtc) shouldn't also appear in DT?
As DT should describe the hardware that we are using.

Warm regards,
Yadwinder

 Best regards,
 Krzysztof
 
 
 
  ---
   drivers/mfd/max77686.c |   22 --
   1 files changed, 20 insertions(+), 2 deletions(-)
 
  diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index
  929795e..22c0948 100644
  --- a/drivers/mfd/max77686.c
  +++ b/drivers/mfd/max77686.c
  @@ -39,10 +39,13 @@
 
   static const struct mfd_cell max77686_devs[] = {
  { .name = max77686-pmic, },
  -   { .name = max77686-rtc, },
  { .name = max77686-clk, },
   };
 
  +static const struct mfd_cell max77686_rtc_dev[] = {
  +   { .name = max77686-rtc, },
  +};
  +
   static const struct mfd_cell max77802_devs[] = {
  { .name = max77802-pmic, },
  { .name = max77802-clk, },
  @@ -332,14 +335,27 @@ static int max77686_i2c_probe(struct i2c_client
 *i2c,
  goto err_del_irqc;
  }
 
  +   if (max77686-type == TYPE_MAX77686) {
  +   ret = mfd_add_devices(max77686-rtc-dev, -1,
 max77686_rtc_dev,
  +   1, NULL, 0, NULL);
  +   if (ret  0) {
  +   dev_err(max77686-rtc-dev,
  +   failed to add RTC device %d\n, ret);
  +   goto err_del_rtc_irqc;
  +   }
  +   }
  +
  ret = mfd_add_devices(max77686-dev, -1, cells, n_devs, NULL, 0,
 NULL);
  if (ret  0) {
  dev_err(i2c-dev, failed to add MFD devices: %d\n, ret);
  -   goto err_del_rtc_irqc;
  +   goto err_del_rtc_dev;
  }
 
  return 0;
 
  +err_del_rtc_dev:
  +   if (max77686-type == TYPE_MAX77686)
  +   mfd_remove_devices(max77686-rtc-dev);
   err_del_rtc_irqc:
  regmap_del_irq_chip(max77686-irq, max77686-rtc_irq_data);
   err_del_irqc:
  @@ -356,6 +372,8 @@ static int max77686_i2c_remove(struct i2c_client
 *i2c)
  struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
 
  mfd_remove_devices(max77686-dev);
  +   if (max77686-type == TYPE_MAX77686)
  +   mfd_remove_devices(max77686-rtc-dev);
 
  regmap_del_irq_chip(max77686-irq, max77686-rtc_irq_data);
  regmap_del_irq_chip(max77686-irq, max77686-irq_data);
 

--
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


RE: [PATCH] mfd: max77686: Fix parent of rtc device

2014-12-03 Thread Yadwinder Singh Brar
On Wednesday, December 03, 2014 2:56 PM, Krzysztof Kozlowski wrote:
 
 On śro, 2014-12-03 at 14:32 +0530, Yadwinder Singh Brar wrote:
 
  On Tuesday, December 02, 2014 7:04 PM, Krzysztof Kozłowski wrote:
   On 02.12.2014 13:45, Yadwinder Singh Brar wrote:
rtc have different i2c client than power(pmic) block. So rtc
device should sit under its own i2c client in device hierarchy,
which
   reflects in sysfs also.
This patch modifies code to register rtc cell with rtc-dev as
   parent.
   
Without this patch :
# ls /sys/class/i2c-adapter/i2c-0/0-0009/
driver max77686-pmic  modalias   power
 uevent
max77686-clk   max77686-rtc   name   subsystem
   
After applying patch :
# ls /sys/class/i2c-adapter/i2c-0/0-0006/
driver/modalias   power/ uevent
max77686-rtc/  name   subsystem/
   
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
   
Or Can we follow another (exhaustive but more cleaner) approach,
   which
will be more like code refactoring and cleanup rather than only
 fix:
Since rtc uses i2c client, which gets created using
i2c_new_dummy() and is not shared by any other cell of max77686.
So we can covert rtc platform driver itself to i2c client driver.
It will also allow to expilicitly describe max77686-rtc in DT
 which we can't do now.
It can be applicable to some other existing and new mfd pmic
 drivers.
Any suggestion/comments ?
  
   Hi,
  
   What kind of problem is solved by this patch?
  
 
  Let me try to explain once again :)
  After seeing a message i2c i2c-0:  , addr=0x06, .. in dmesg
 log,
  I was not able to find any such device in sysfs as well as device
 tree.
  There was no device under /sys/class/i2c-dev/i2c-0/device/0-0006/
  Isn't something wrong or missing ?
 
  This patch fixes that missing parent child relation, which IMO should
  be correct always, though it causes any major problem or not.
 
 OK, I got your point. I'm fine with both solutions and the patch looks
 good, so:
 Reviewed-by: Krzysztof Kozlowski k.kozlow...@samsung.com
 

Thanks for reviewing :).

  Still I am thinking, 0-0006 slave device(rtc) shouldn't also appear
 in DT?
  As DT should describe the hardware that we are using.
 
 Your patch properly describes the hardware. However from driver
 perspective, the RTC here is not an standalone driver and depends on
 parent (MFD) driver.
 

Hmm ... I can't see any hard dependency. I think rtc can survive as independent 
i2c device.
And rtc(@06) is more like a sibling of existing MFD driver(max77686@09)

 Although max77686 RTC could have its own DeviceTree node, I think it
 should still be put under main MFD driver's node, because the parent
 manages stuff like interrupts.
 

I think it will not sound good to have something like max77686-rtc@06
node under max77686@09 node, since both are kind of siblings.
And interrupts should not be a restricting factor, In case of
max77686 interrupt source and mask registers for rtc also lie in rtc
i2c register bank so we can add an irq_chip from rtc driver itself.

Only thing I can see which can be little bit tricky, is providing
alarm-pending info(pending interrupt) in alarm_read() callback
in rtc as currently its based on MAX77686_REG_STATUS2 which is
only common register in power(pmic) register bank of max77686.
Though in practical scenarios it may not be non zero, since
reading once source register clears this status also, but we may
have to keep it for sake of functionality completeness.

I can’t see any way(something similar to syscon) for sharing
i2c regmap between independent drivers, other than getting
reference to regmap from i2c device found by of_find_i2c_device_by_node().
Anyone can suggest better idea?


Best Regards,
Yadwinder

--
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


[PATCH] mfd: max77686: Fix parent of rtc device

2014-12-02 Thread Yadwinder Singh Brar
rtc have different i2c client than power(pmic) block. So rtc device should
sit under its own i2c client in device hierarchy, which reflects in sysfs also.
This patch modifies code to register rtc cell with rtc-dev as parent.

Without this patch :
driver max77686-pmic  modalias   power  uevent
max77686-clk   max77686-rtc   name   subsystem

After applying patch :
driver/modalias   power/ uevent
max77686-rtc/  name   subsystem/

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

Or Can we follow another (exhaustive but more cleaner) approach, which will
be more like code refactoring and cleanup rather than only fix:
Since rtc uses i2c client, which gets created using i2c_new_dummy() and is not
shared by any other cell of max77686. So we can covert rtc platform driver
itself to i2c client driver. It will also allow to expilicitly describe
max77686-rtc in DT which we can't do now.
It can be applicable to some other existing and new mfd pmic drivers.
Any suggestion/comments ?

---
 drivers/mfd/max77686.c |   22 --
 1 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index 929795e..22c0948 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -39,10 +39,13 @@
 
 static const struct mfd_cell max77686_devs[] = {
{ .name = max77686-pmic, },
-   { .name = max77686-rtc, },
{ .name = max77686-clk, },
 };
 
+static const struct mfd_cell max77686_rtc_dev[] = {
+   { .name = max77686-rtc, },
+};
+
 static const struct mfd_cell max77802_devs[] = {
{ .name = max77802-pmic, },
{ .name = max77802-clk, },
@@ -332,14 +335,27 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
goto err_del_irqc;
}
 
+   if (max77686-type == TYPE_MAX77686) {
+   ret = mfd_add_devices(max77686-rtc-dev, -1, max77686_rtc_dev,
+   1, NULL, 0, NULL);
+   if (ret  0) {
+   dev_err(max77686-rtc-dev,
+   failed to add RTC device %d\n, ret);
+   goto err_del_rtc_irqc;
+   }
+   }
+
ret = mfd_add_devices(max77686-dev, -1, cells, n_devs, NULL, 0, NULL);
if (ret  0) {
dev_err(i2c-dev, failed to add MFD devices: %d\n, ret);
-   goto err_del_rtc_irqc;
+   goto err_del_rtc_dev;
}
 
return 0;
 
+err_del_rtc_dev:
+   if (max77686-type == TYPE_MAX77686)
+   mfd_remove_devices(max77686-rtc-dev);
 err_del_rtc_irqc:
regmap_del_irq_chip(max77686-irq, max77686-rtc_irq_data);
 err_del_irqc:
@@ -356,6 +372,8 @@ static int max77686_i2c_remove(struct i2c_client *i2c)
struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
 
mfd_remove_devices(max77686-dev);
+   if (max77686-type == TYPE_MAX77686)
+   mfd_remove_devices(max77686-rtc-dev);
 
regmap_del_irq_chip(max77686-irq, max77686-rtc_irq_data);
regmap_del_irq_chip(max77686-irq, max77686-irq_data);
-- 
1.7.0.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


[PATCH] mfd: max77686: Fix parent of rtc device

2014-12-02 Thread Yadwinder Singh Brar
rtc have different i2c client than power(pmic) block. So rtc device should
sit under its own i2c client in device hierarchy, which reflects in sysfs also.
This patch modifies code to register rtc cell with rtc-dev as parent.

Without this patch :
# ls /sys/class/i2c-adapter/i2c-0/0-0009/
driver max77686-pmic  modalias   power  uevent
max77686-clk   max77686-rtc   name   subsystem

After applying patch :
# ls /sys/class/i2c-adapter/i2c-0/0-0006/
driver/modalias   power/ uevent
max77686-rtc/  name   subsystem/

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

Or Can we follow another (exhaustive but more cleaner) approach, which will
be more like code refactoring and cleanup rather than only fix:
Since rtc uses i2c client, which gets created using i2c_new_dummy() and is not
shared by any other cell of max77686. So we can covert rtc platform driver
itself to i2c client driver. It will also allow to expilicitly describe
max77686-rtc in DT which we can't do now.
It can be applicable to some other existing and new mfd pmic drivers.
Any suggestion/comments ?

---
 drivers/mfd/max77686.c |   22 --
 1 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index 929795e..22c0948 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -39,10 +39,13 @@
 
 static const struct mfd_cell max77686_devs[] = {
{ .name = max77686-pmic, },
-   { .name = max77686-rtc, },
{ .name = max77686-clk, },
 };
 
+static const struct mfd_cell max77686_rtc_dev[] = {
+   { .name = max77686-rtc, },
+};
+
 static const struct mfd_cell max77802_devs[] = {
{ .name = max77802-pmic, },
{ .name = max77802-clk, },
@@ -332,14 +335,27 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
goto err_del_irqc;
}
 
+   if (max77686-type == TYPE_MAX77686) {
+   ret = mfd_add_devices(max77686-rtc-dev, -1, max77686_rtc_dev,
+   1, NULL, 0, NULL);
+   if (ret  0) {
+   dev_err(max77686-rtc-dev,
+   failed to add RTC device %d\n, ret);
+   goto err_del_rtc_irqc;
+   }
+   }
+
ret = mfd_add_devices(max77686-dev, -1, cells, n_devs, NULL, 0, NULL);
if (ret  0) {
dev_err(i2c-dev, failed to add MFD devices: %d\n, ret);
-   goto err_del_rtc_irqc;
+   goto err_del_rtc_dev;
}
 
return 0;
 
+err_del_rtc_dev:
+   if (max77686-type == TYPE_MAX77686)
+   mfd_remove_devices(max77686-rtc-dev);
 err_del_rtc_irqc:
regmap_del_irq_chip(max77686-irq, max77686-rtc_irq_data);
 err_del_irqc:
@@ -356,6 +372,8 @@ static int max77686_i2c_remove(struct i2c_client *i2c)
struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
 
mfd_remove_devices(max77686-dev);
+   if (max77686-type == TYPE_MAX77686)
+   mfd_remove_devices(max77686-rtc-dev);
 
regmap_del_irq_chip(max77686-irq, max77686-rtc_irq_data);
regmap_del_irq_chip(max77686-irq, max77686-irq_data);
-- 
1.7.0.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


RE: [1/2] ARM: dts: Fix bootup issue on smdk5250

2014-11-25 Thread Yadwinder Singh Brar
Hi Kukjin,

 Subject: RE: [1/2] ARM: dts: Fix bootup issue on smdk5250
 
 Pankaj Dubey wrote:
 
  Hi,
 
 Hi,
 
 Yadwinder, please don't miss [PATCH 1/2] in subject, so that my e-mail
 client can't filter wrong ;)
 

Sure, but I think your mail client had played some trick, as patches
were posted with [PATCH */2] prefix.

  On Tuesday 18 November 2014 05:38 PM, Yadwinder Singh Brar wrote:
   With default config on smdk5250 latest tree throws below message :
  
   [2.226049] thermal thermal_zone0: critical temperature
 reached(224 C),shutting down
   [2.227840] reboot: Failed to start orderly shutdown: forcing
 the issue
  
   and hangs randomly because it reads wrong temperature value.
  
   I can't figure out any direct relation between LDO10 and TMU from
   board schematics which I have. So making LDO10 always-on to fix
 issue for now.
  
 Hmm...strange, I also can't see any relations now...but I need to
 contact to hardware guy before applying this, this fixes the problem
 though.
 

Ok, sure it will be good know actual relation from hardware guy.

Meanwhile can we get another patch[1] merged which was posted along
with patch just because both patches were on same file. Otherwise
there is no dependency between them and can be applied independently.

Best Regards,
Yadwinder

[1] : http://www.spinics.net/lists/linux-samsung-soc/msg39107.html

 Thanks,
 Kukjin
 
   Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
  
 
  Tested this on SMDK5250 board, system boot is fine now, hence
 
  Tested-by: Pankaj Dubey pankaj.du...@samsung.com
 
   ---
   arch/arm/boot/dts/exynos5250-smdk5250.dts |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
  
   diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts
   b/arch/arm/boot/dts/exynos5250-smdk5250.dts
   index bc27cc2..95b5b51 100644
   --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
   +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
   @@ -190,6 +190,7 @@
 regulator-name = P1.8V_LDO_OUT10;
 regulator-min-microvolt = 180;
 regulator-max-microvolt = 180;
   + regulator-always-on;
 };
  
 ldo11_reg: LDO11 {
  

--
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


[PATCH 1/2] ARM: dts: Fix bootup issue on smdk5250

2014-11-18 Thread Yadwinder Singh Brar
With default config on smdk5250 latest tree throws below message :

[2.226049] thermal thermal_zone0: critical temperature reached(224 
C),shutting down
[2.227840] reboot: Failed to start orderly shutdown: forcing the issue

and hangs randomly because it reads wrong temperature value.

I can't figure out any direct relation between LDO10 and TMU from board
schematics which I have. So making LDO10 always-on to fix issue for now.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 arch/arm/boot/dts/exynos5250-smdk5250.dts |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts 
b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index bc27cc2..95b5b51 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -190,6 +190,7 @@
regulator-name = P1.8V_LDO_OUT10;
regulator-min-microvolt = 180;
regulator-max-microvolt = 180;
+   regulator-always-on;
};
 
ldo11_reg: LDO11 {
-- 
1.7.0.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


[PATCH 2/2] ARM: dts: Add missing irq pinctrl for max77686 on smdk5250

2014-11-18 Thread Yadwinder Singh Brar
This patch adds pinctrl configuration for using configuring gpx3-2 as an
external interrupt from max77686. Though max77686 RTC is enabled and gets
probed by default, it doesnt work as its unable to get interrupt.

This patch makes max77686 RTC work and also configures it as wakeup source.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 arch/arm/boot/dts/exynos5250-smdk5250.dts |   12 
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts 
b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 95b5b51..19cd918 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -131,6 +131,9 @@
reg = 0x09;
interrupt-parent = gpx3;
interrupts = 2 IRQ_TYPE_NONE;
+   pinctrl-names = default;
+   pinctrl-0 = max77686_irq;
+   wakeup-source;
 
voltage-regulators {
ldo1_reg: LDO1 {
@@ -411,3 +414,12 @@
};
};
 };
+
+pinctrl_0 {
+   max77686_irq: max77686-irq {
+   samsung,pins = gpx3-2;
+   samsung,pin-function = 0xf;
+   samsung,pin-pud = 0;
+   samsung,pin-drv = 0;
+   };
+};
-- 
1.7.0.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


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 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

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 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 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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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-samsung-soc in
the body of a 

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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/9] clk: samsung: exynos4: Move suspend/resume handling to SoC driver

2013-10-17 Thread Yadwinder Singh Brar
Hi Tomasz,

[ ... ]
  /*
   * list of controller registers to be saved and restored during a
   * suspend/resume cycle.
 @@ -288,6 +299,70 @@ static unsigned long exynos4_clk_regs[] __initdata = {
 GATE_IP_CPU,
  };

 +static int exynos4_clk_suspend(void)
 +{
 +   samsung_clk_save(reg_base, exynos4_save_common,
 +   ARRAY_SIZE(exynos4_clk_regs));

a doubt here, Is sizeof(exynos4_clk_regs) works with
exynos4_clk_regs[] as __initdata ?

 +
 +   if (exynos4_soc == EXYNOS4210)
 +   samsung_clk_save(reg_base, exynos4_save_soc,
 +   ARRAY_SIZE(exynos4210_clk_save));

[ ... ]
 +static void exynos4_clk_sleep_init(void)

I think, this fuction can be placed in __init section.

Same in other patches as well.

Regards,
Yadwinder
--
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


Re: [PATCH 3/9] clk: samsung: exynos4: Move suspend/resume handling to SoC driver

2013-10-17 Thread Yadwinder Singh Brar
On Thu, Oct 17, 2013 at 7:46 PM, Tomasz Figa t.f...@samsung.com wrote:
 On Thursday 17 of October 2013 19:12:08 Yadwinder Singh Brar wrote:
 Hi Tomasz,

 [ ... ]
   /*
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
  @@ -288,6 +299,70 @@ static unsigned long exynos4_clk_regs[] __initdata = {
  GATE_IP_CPU,
   };
 
  +static int exynos4_clk_suspend(void)
  +{
  +   samsung_clk_save(reg_base, exynos4_save_common,
  +   ARRAY_SIZE(exynos4_clk_regs));

 a doubt here, Is sizeof(exynos4_clk_regs) works with
 exynos4_clk_regs[] as __initdata ?

 Hmm, this is a compile time constant, so I don't see why it couldn't work.


why this doubt came in mind is sizeof() is a operator.. like we can
use sizeof(x++).
--
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


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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] 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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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 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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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

[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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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

Re: [PATCH 10/16] clk: samsung: pll: Add support for rate configuration of PLL45xx

2013-08-21 Thread Yadwinder Singh Brar
Hi Tomasz,

On Tue, Aug 20, 2013 at 11:01 PM, Tomasz Figa t.f...@samsung.com wrote:
 This patch implements round_rate and set_rate callbacks of PLL45xx
 driver to allow reconfiguration of PLL at runtime.

 Signed-off-by: Tomasz Figa t.f...@samsung.com
 Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
 ---
  drivers/clk/samsung/clk-pll.c | 109 
 +-
  drivers/clk/samsung/clk-pll.h |  10 
  2 files changed, 118 insertions(+), 1 deletion(-)

 diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
 index b0398d2..cb971cb 100644
 --- a/drivers/clk/samsung/clk-pll.c
 +++ b/drivers/clk/samsung/clk-pll.c
 @@ -10,9 +10,12 @@
  */

  #include linux/errno.h
 +#include linux/hrtimer.h
  #include clk.h
  #include clk-pll.h

 +#define PLL_TIMEOUT_MS 10
 +
  struct samsung_clk_pll {
 struct clk_hw   hw;
 void __iomem*lock_reg;
 @@ -272,13 +275,20 @@ static const struct clk_ops samsung_pll36xx_clk_min_ops 
 = {
  /*
   * PLL45xx Clock Type
   */
 +#define PLL4502_LOCK_FACTOR400
 +#define PLL4508_LOCK_FACTOR240

  #define PLL45XX_MDIV_MASK  (0x3FF)
  #define PLL45XX_PDIV_MASK  (0x3F)
  #define PLL45XX_SDIV_MASK  (0x7)
 +#define PLL45XX_AFC_MASK   (0x1F)
  #define PLL45XX_MDIV_SHIFT (16)
  #define PLL45XX_PDIV_SHIFT (8)
  #define PLL45XX_SDIV_SHIFT (0)
 +#define PLL45XX_AFC_SHIFT  (0)
 +
 +#define PLL45XX_ENABLE BIT(31)
 +#define PLL45XX_LOCKED BIT(29)

  static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
 unsigned long parent_rate)
 @@ -301,8 +311,100 @@ static unsigned long samsung_pll45xx_recalc_rate(struct 
 clk_hw *hw,
 return (unsigned long)fvco;
  }

 +static bool samsung_pll45xx_mp_change(u32 pll_con0, u32 pll_con1,
 +   const struct samsung_pll_rate_table *rate)
 +{
 +   u32 old_mdiv, old_pdiv, old_afc;
 +
 +   old_mdiv = (pll_con0  PLL45XX_MDIV_SHIFT)  PLL45XX_MDIV_MASK;
 +   old_pdiv = (pll_con0  PLL45XX_PDIV_SHIFT)  PLL45XX_PDIV_MASK;
 +   old_afc = (pll_con1  PLL45XX_AFC_SHIFT)  PLL45XX_AFC_MASK;

old_afc doesn't required in this function.

 +
 +   return (old_mdiv != rate-mdiv || old_pdiv != rate-pdiv);
 +}
 +
 +static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
 +   unsigned long prate)
 +{
 +   struct samsung_clk_pll *pll = to_clk_pll(hw);
 +   const struct samsung_pll_rate_table *rate;
 +   u32 con0, con1;
 +   ktime_t start;
 +
 +   /* Get required rate settings from table */
 +   rate = samsung_get_pll_settings(pll, drate);
 +   if (!rate) {
 +   pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__,
 +   drate, __clk_get_name(hw-clk));
 +   return -EINVAL;
 +   }
 +
 +   con0 = __raw_readl(pll-con_reg);
 +   con1 = __raw_readl(pll-con_reg + 0x4);
 +
 +   if (!(samsung_pll45xx_mp_change(con0, con1, rate))) {
 +   /* If only s change, change just s value only*/
 +   con0 = ~(PLL45XX_SDIV_MASK  PLL45XX_SDIV_SHIFT);
 +   con0 |= rate-sdiv  PLL45XX_SDIV_SHIFT;
 +   __raw_writel(con0, pll-con_reg);
 +
 +   return 0;
 +   }
 +
 +   /* Set PLL PMS values. */
 +   con0 = ~((PLL45XX_MDIV_MASK  PLL45XX_MDIV_SHIFT) |
 +   (PLL45XX_PDIV_MASK  PLL45XX_PDIV_SHIFT) |
 +   (PLL45XX_SDIV_MASK  PLL45XX_SDIV_SHIFT));
 +   con0 |= (rate-mdiv  PLL45XX_MDIV_SHIFT) |
 +   (rate-pdiv  PLL45XX_PDIV_SHIFT) |
 +   (rate-sdiv  PLL45XX_SDIV_SHIFT);
 +
 +   /* Set PLL AFC value. */
 +   con1 = __raw_readl(pll-con_reg + 0x4);
 +   con1 = ~(PLL45XX_AFC_MASK  PLL45XX_AFC_SHIFT);
 +   con1 |= (rate-afc  PLL45XX_AFC_SHIFT);
 +

Do we need to take care of AFC_ENB also, if we are using AFC ?

Regards,
Yadwinder
--
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


Re: [PATCH 12/16] clk: samsung: pll: Add support for rate configuration of PLL46xx

2013-08-21 Thread Yadwinder Singh Brar
 +   con0 |= (rate-mdiv  PLL46XX_MDIV_SHIFT) |
 +   (rate-pdiv  PLL46XX_PDIV_SHIFT) |
 +   (rate-sdiv  PLL46XX_SDIV_SHIFT) |
 +   (rate-vsel  PLL46XX_VSEL_SHIFT);
 +
 +   /* Set PLL AFC, MFR and MRR values. */

This comments seems to be miss match with below code.

 +   con1 = __raw_readl(pll-con_reg + 0x4);
 +   con1 = ~((PLL46XX_KDIV_MASK  PLL46XX_KDIV_SHIFT) |
 +   (PLL46XX_MFR_MASK  PLL46XX_MFR_SHIFT) |
 +   (PLL46XX_MRR_MASK  PLL46XX_MRR_SHIFT));
 +   con1 |= (rate-kdiv  PLL46XX_KDIV_SHIFT) |
 +   (rate-mfr  PLL46XX_MFR_SHIFT) |
 +   (rate-mrr  PLL46XX_MRR_SHIFT);
 +
snip
 --- a/drivers/clk/samsung/clk-pll.h
 +++ b/drivers/clk/samsung/clk-pll.h
 @@ -51,6 +51,28 @@ enum samsung_pll_type {
 .afc=   (_afc), \
 }

 +#define PLL_4600_RATE(_rate, _m, _p, _s, _k, _vsel)\
 +   {   \
 +   .rate   =   (_rate),\
 +   .mdiv   =   (_m),   \
 +   .pdiv   =   (_p),   \
 +   .sdiv   =   (_s),   \
 +   .kdiv   =   (_k),   \
 +   .vsel   =   (_vsel),\
 +   }
 +
 +#define PLL_4650_RATE(_rate, _m, _p, _s, _k, _mfr, _mrr, _vsel)\
 +   {   \
 +   .rate   =   (_rate),\
 +   .mdiv   =   (_m),   \
 +   .pdiv   =   (_p),   \
 +   .sdiv   =   (_s),   \
 +   .kdiv   =   (_k),   \
 +   .mfr=   (_mfr), \
 +   .mrr=   (_mrr), \
 +   .vsel   =   (_vsel),\
 +   }
 +
  /* NOTE: Rate table should be kept sorted in descending order. */

  struct samsung_pll_rate_table {
 @@ -60,6 +82,9 @@ struct samsung_pll_rate_table {
 unsigned int sdiv;
 unsigned int kdiv;
 unsigned int afc;
 +   unsigned int mfr;
 +   unsigned int mrr;
 +   unsigned int vsel;
  };


This struct seems to be expanding too much.
Can we re-think on options for using bit map same as register
definition? It can reduce code in set_rate also little bit.

Regards,
Yadwinder
--
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


Re: [PATCH 14/16] clk: samsung: exynos4: Register PLL rate tables for Exynos4210

2013-08-21 Thread Yadwinder Singh Brar
On Tue, Aug 20, 2013 at 11:01 PM, Tomasz Figa t.f...@samsung.com wrote:
 This patch adds rate tables for PLLs that can be reconfigured at runtime
 for Exynos4210 SoCs. Provided tables contain PLL coefficients for
 input clock of 24 MHz and so are registered only in this case. MPLL does
 not need runtime reconfiguration and so table for it is not provided.

 Signed-off-by: Tomasz Figa t.f...@samsung.com
 Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com
 ---
  drivers/clk/samsung/clk-exynos4.c | 45 
 +++
  1 file changed, 45 insertions(+)

 diff --git a/drivers/clk/samsung/clk-exynos4.c 
 b/drivers/clk/samsung/clk-exynos4.c
 index 34474ce..e18cfae 100644
 --- a/drivers/clk/samsung/clk-exynos4.c
 +++ b/drivers/clk/samsung/clk-exynos4.c
 @@ -992,6 +992,40 @@ static struct of_device_id ext_clk_match[] __initdata = {
 {},
  };

 +/* PLLs PMS values */
 +static struct samsung_pll_rate_table exynos4210_apll_rates[] = {
 +   PLL_45XX_RATE(12, 150,  3, 1, 28),

All these tables in this patch as well as next patch can be __initdata


Regards,
Yadwinder
--
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


Re: [PATCH 12/16] clk: samsung: pll: Add support for rate configuration of PLL46xx

2013-08-21 Thread Yadwinder Singh Brar
 snip

  --- a/drivers/clk/samsung/clk-pll.h
  +++ b/drivers/clk/samsung/clk-pll.h
  @@ -51,6 +51,28 @@ enum samsung_pll_type {
 
  .afc=   (_afc), \
 
  }
 
  +#define PLL_4600_RATE(_rate, _m, _p, _s, _k, _vsel)\
  +   {   \
  +   .rate   =   (_rate),\
  +   .mdiv   =   (_m),   \
  +   .pdiv   =   (_p),   \
  +   .sdiv   =   (_s),   \
  +   .kdiv   =   (_k),   \
  +   .vsel   =   (_vsel),\
  +   }
  +
  +#define PLL_4650_RATE(_rate, _m, _p, _s, _k, _mfr, _mrr, _vsel)
  \ +   {   \ +
   .rate   =   (_rate),\ +
  .mdiv   =   (_m),   \ +
 .pdiv   =   (_p),   \ +
  .sdiv   =   (_s),   \ +
  .kdiv   =   (_k),   \ +   .mfr
 =   (_mfr), \ +   .mrr=
(_mrr), \ +   .vsel   =
   (_vsel),\ +   }
  +
 
   /* NOTE: Rate table should be kept sorted in descending order. */
 
   struct samsung_pll_rate_table {
 
  @@ -60,6 +82,9 @@ struct samsung_pll_rate_table {
 
  unsigned int sdiv;
  unsigned int kdiv;
  unsigned int afc;
 
  +   unsigned int mfr;
  +   unsigned int mrr;
  +   unsigned int vsel;
 
   };

 This struct seems to be expanding too much.

 I don't think it's a problem. How many bytes such tables can occupy in a
 system?


no doubt comparing with memory size its negligible..
but comparing only struct size and coding lines it seems costlier :) .

 Can we re-think on options for using bit map same as register
 definition? It can reduce code in set_rate also little bit.

 IMHO it is more clear what the code does when accessing a single
 coefficient at once.

 In addition you still would need to preserve bitfields that are not changed
 by the driver

Sorry, I can't see any such problem, it will OR only the required bits.

 and also unpack some of the coefficients anyway, like pdiv
 that is used to calculate lock time.

Agree, but cases of unpacking will always be less than cases of
shifting and packing.

Anyways, its only MHO :).

Regards,
Yadwinder
--
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


Re: [PATCH 09/16] clk: samsung: pll: Use new registration method for PLL45xx

2013-08-21 Thread Yadwinder Singh Brar
  };

 +static struct __initdata samsung_pll_clock exynos4210_plls[nr_plls] = {

NIT: __initdata should be at last.

 +   [apll] = PLL_A(pll_4508, fout_apll, fout_apll, fin_pll, APLL_LOCK,
 +   APLL_CON0, fout_apll, NULL),
 +   [mpll] = PLL_A(pll_4508, fout_mpll, fout_mpll, fin_pll,
 +   E4210_MPLL_LOCK, E4210_MPLL_CON0, fout_mpll, NULL),
 +};
 +
  static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
 [apll] = PLL(pll_35xx, fout_apll, fout_apll, fin_pll,
 APLL_LOCK, APLL_CON0, NULL),
 @@ -1004,7 +1012,7 @@ static void __init exynos4_clk_init(struct device_node 
 *np,
 enum exynos4_soc exynos4_soc,
 void __iomem *reg_base, unsigned long xom)
  {
 -   struct clk *apll, *mpll, *epll, *vpll;
 +   struct clk *epll, *vpll;

 reg_base = of_iomap(np, 0);
 if (!reg_base)
 @@ -1026,17 +1034,13 @@ static void __init exynos4_clk_init(struct 
 device_node *np,
 exynos4_clk_register_finpll(xom);

 if (exynos4_soc == EXYNOS4210) {
 -   apll = samsung_clk_register_pll45xx(fout_apll, fin_pll,
 -   reg_base + APLL_CON0, pll_4508);
 -   mpll = samsung_clk_register_pll45xx(fout_mpll, fin_pll,
 -   reg_base + E4210_MPLL_CON0, pll_4508);
 +   samsung_clk_register_pll(exynos4210_plls,
 +   ARRAY_SIZE(exynos4210_plls), 
 reg_base);
 epll = samsung_clk_register_pll46xx(fout_epll, fin_pll,
 reg_base + EPLL_CON0, pll_4600);
 vpll = samsung_clk_register_pll46xx(fout_vpll, 
 mout_vpllsrc,
 reg_base + VPLL_CON0, pll_4650c);

 -   samsung_clk_add_lookup(apll, fout_apll);
 -   samsung_clk_add_lookup(mpll, fout_mpll);
 samsung_clk_add_lookup(epll, fout_epll);
 samsung_clk_add_lookup(vpll, fout_vpll);
 } else {
 diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
 index 0775554..b0398d2 100644
 --- a/drivers/clk/samsung/clk-pll.c
 +++ b/drivers/clk/samsung/clk-pll.c
 @@ -280,18 +280,10 @@ static const struct clk_ops samsung_pll36xx_clk_min_ops 
 = {
  #define PLL45XX_PDIV_SHIFT (8)
  #define PLL45XX_SDIV_SHIFT (0)

 -struct samsung_clk_pll45xx {
 -   struct clk_hw   hw;
 -   enum pll45xx_type   type;
 -   const void __iomem  *con_reg;
 -};
 -
 -#define to_clk_pll45xx(_hw) container_of(_hw, struct samsung_clk_pll45xx, hw)
 -
  static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
 unsigned long parent_rate)
  {
 -   struct samsung_clk_pll45xx *pll = to_clk_pll45xx(hw);
 +   struct samsung_clk_pll *pll = to_clk_pll(hw);
 u32 mdiv, pdiv, sdiv, pll_con;
 u64 fvco = parent_rate;

 @@ -313,43 +305,6 @@ static const struct clk_ops samsung_pll45xx_clk_ops = {
 .recalc_rate = samsung_pll45xx_recalc_rate,
  };

 -struct clk * __init samsung_clk_register_pll45xx(const char *name,
 -   const char *pname, const void __iomem *con_reg,
 -   enum pll45xx_type type)
 -{
 -   struct samsung_clk_pll45xx *pll;
 -   struct clk *clk;
 -   struct clk_init_data init;
 -
 -   pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 -   if (!pll) {
 -   pr_err(%s: could not allocate pll clk %s\n, __func__, name);
 -   return NULL;
 -   }
 -
 -   init.name = name;
 -   init.ops = samsung_pll45xx_clk_ops;
 -   init.flags = CLK_GET_RATE_NOCACHE;
 -   init.parent_names = pname;
 -   init.num_parents = 1;
 -
 -   pll-hw.init = init;
 -   pll-con_reg = con_reg;
 -   pll-type = type;
 -
 -   clk = clk_register(NULL, pll-hw);
 -   if (IS_ERR(clk)) {
 -   pr_err(%s: failed to register pll clock %s\n, __func__,
 -   name);
 -   kfree(pll);
 -   }
 -
 -   if (clk_register_clkdev(clk, name, NULL))
 -   pr_err(%s: failed to register lookup for %s, __func__, 
 name);
 -
 -   return clk;
 -}
 -
  /*
   * PLL46xx Clock Type
   */
 @@ -724,6 +679,11 @@ static void __init _samsung_clk_register_pll(struct 
 samsung_pll_clock *pll_clk,
 else
 init.ops = samsung_pll35xx_clk_ops;
 break;
 +   case pll_4500:
 +   case pll_4502:
 +   case pll_4508:
 +   init.ops = samsung_pll45xx_clk_ops;
 +   break;
 /* clk_ops for 36xx and 2650 are similar */
 case pll_36xx:
 case pll_2650:
 diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
 index 2f70e88..f3faf24 100644
 --- a/drivers/clk/samsung/clk-pll.h
 +++ 

Re: [PATCH] ARM: EXYNOS: Fix low level debug support

2013-07-23 Thread Yadwinder Singh Brar
On Mon, Jul 22, 2013 at 6:37 PM, Tomasz Figa t.f...@samsung.com wrote:
 On Monday 22 of July 2013 06:23:06 Thomas Abraham wrote:
 On 13 July 2013 04:57, Yadwinder Singh Brar yadi.b...@samsung.com
 wrote:
  Presently, using exynos_defconfig with CONFIG_DEBUG_LL and
  CONFIG_EARLY_PRINTK on, kernel is not booting, we are getting
  following:
 
  [0.00] [ cut here ]
  [0.00] kernel BUG at mm/vmalloc.c:1134!
  [0.00] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
  [0.00] Modules linked in:
  [0.00] CPU: 0 PID: 0 Comm: swapper Not tainted 3.11.0-rc1 #633
  [0.00] task: c052ec48 ti: c0524000 task.ti: c0524000
  [0.00] PC is at vm_area_add_early+0x54/0x94
  [0.00] LR is at add_static_vm_early+0xc/0x60
 
  Its because iotable_init tries to map UART again which is already
  mapped by debug_ll_io_init() call in exynos_init_io() within same
  virtal address range as requested later.

 debug_ll_io_init ioremaps debug uart address space with 4KB size
 whereas the exynos_init_io() function ioremaps a single 512KB memory
 size for all the four uart ports which envelops the mapping created by
 debug_ll_io_init. This is caught as a kernel bug.

 Right.

  This issue seems to be occured after :
  commit ee4de5d99aeac44f4507b7538b2b3faedc5205b9
  ARM: 7781/1: mmu: Add debug_ll_io_init() mappings to early mappings
 
  This patch moves S3C_UART iodesc(in iodesc_list) inside CONFIG_DEBUG_LL
  check.
 Instead of moving, all the such iodesc entries for UART controller can
 be removed for all Samsung SoC's now since the Samsung uart driver
 does a ioremap during probe and any needed iomapping for earlyprintk
 is handled by debug_ll_io_init().

 Yes. This mapping should not be here, but...

 If you look at plat-samsung/pm.c, there is a debugging code that relies on
 presence of this mapping.

Thanks for pointing this, I completely missed it.

So until this gets fixed/removed (I'm working on
 it right now), I'd suggest keeping Yadwinder's solution.


But that debugging code is under CONFIG_SAMSUNG_PM_DEBUG
and SAMSUNG_PM_DEBUG selects DEBUG_LL also.
So the problem you stated below will their always when ever it will
enter that code

 The only problem is that the code in pm.c expects _all_ UARTs to be mapped
 (see s3c_pm_resture_uarts() and co.), so in case of DEBUG_LL enabled,
 something must be done ensure that rest of the ports are mapped.


how about fixing this problem with something like below:
saving only mapped/configured UART's registers.

8
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
index ea36136..34a7371 100644
--- a/arch/arm/plat-samsung/pm.c
+++ b/arch/arm/plat-samsung/pm.c
@@ -102,10 +102,8 @@ static void s3c_pm_save_uart(unsigned int uart, struct pm_u
 static void s3c_pm_save_uarts(void)
 {
struct pm_uart_save *save = uart_save;
-   unsigned int uart;

-   for (uart = 0; uart  CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
-   s3c_pm_save_uart(uart, save);
+   s3c_pm_save_uart(CONFIG_DEBUG_S3C_UART, save);
 }

 static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)

8--

 I'm going to completely rework Samsung PM code in some time, so this
 problem will go away, but this must be fixed in 3.11.


Yes, it will be helpful if we have it fixed.

Regards,
Yadwinder
--
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


[v2 PATCH 0/2] EXYNOS: Fix low level debug support

2013-07-23 Thread Yadwinder Singh Brar
Presently, using exynos_defconfig with CONFIG_DEBUG_LL and CONFIG_EARLY_PRINTK
on, kernel is not booting, we are getting following:

[0.00] [ cut here ]
[0.00] kernel BUG at mm/vmalloc.c:1134!
[0.00] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
[0.00] Modules linked in:
[0.00] CPU: 0 PID: 0 Comm: swapper Not tainted 3.11.0-rc1 #633
[0.00] task: c052ec48 ti: c0524000 task.ti: c0524000
[0.00] PC is at vm_area_add_early+0x54/0x94
[0.00] LR is at add_static_vm_early+0xc/0x60

Its because exynos[4/5]_map_io() function ioremaps a single 512KB memory
size for all the four uart ports which envelopes the mapping created by
debug_ll_io_init(), called earlier in exynos_init_io().

This issue seems to be occured after :
commit ee4de5d99aeac44f4507b7538b2b3faedc5205b9
ARM: 7781/1: mmu: Add debug_ll_io_init() mappings to early mappings

This series removes static iodesc entries for UART controller for all Samsung
SoC's and modifies pm debug code to save/restore only the selected debug uart
registers.

changes since v1:
- removed uart iodesc entires instead of just moving inside CONFIG_DEBUG_LL
  check, as suggested by Thomas Abraham.
- Fixed the possible issue after removing uart entries pointed by Tomasz Figa.

Tested doing suspend/resume on smdk5250.

Yadwinder Singh Brar (2):
  ARM: SAMSUNG: pm: Save/restore only selected uart's registers
  ARM: EXYNOS: Fix low level debug support

 arch/arm/mach-exynos/common.c |   26 --
 arch/arm/plat-samsung/pm.c|   14 +++---
 2 files changed, 3 insertions(+), 37 deletions(-)

--
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


[PATCH 2/2] ARM: EXYNOS: Fix low level debug support

2013-07-23 Thread Yadwinder Singh Brar
Presently, using exynos_defconfig with CONFIG_DEBUG_LL and CONFIG_EARLY_PRIN
on, kernel is not booting, we are getting following:

[0.00] [ cut here ]
[0.00] kernel BUG at mm/vmalloc.c:1134!
[0.00] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
[0.00] Modules linked in:
[0.00] CPU: 0 PID: 0 Comm: swapper Not tainted 3.11.0-rc1 #633
[0.00] task: c052ec48 ti: c0524000 task.ti: c0524000
[0.00] PC is at vm_area_add_early+0x54/0x94
[0.00] LR is at add_static_vm_early+0xc/0x60

Its because exynos[4/5]_map_io() function ioremaps a single 512KB memory
size for all the four uart ports which envelopes the mapping created by
debug_ll_io_init(), called earlier in exynos_init_io().

This patch removes iodesc entries for UART controller for all Samsung SoC's,
since now the Samsung uart driver does a ioremap during probe and any needed
iomapping for earlyprintk will be handled by debug_ll_io_init().

Tested on smdk4412 and smdk5250.

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

diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 164685b..ba95e5d 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -58,7 +58,6 @@ static const char name_exynos5440[] = EXYNOS5440;
 
 static void exynos4_map_io(void);
 static void exynos5_map_io(void);
-static void exynos5440_map_io(void);
 static int exynos_init(void);
 
 static struct cpu_table cpu_ids[] __initdata = {
@@ -95,7 +94,6 @@ static struct cpu_table cpu_ids[] __initdata = {
}, {
.idcode = EXYNOS5440_SOC_ID,
.idmask = EXYNOS5_SOC_MASK,
-   .map_io = exynos5440_map_io,
.init   = exynos_init,
.name   = name_exynos5440,
},
@@ -150,11 +148,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.length = SZ_64K,
.type   = MT_DEVICE,
}, {
-   .virtual= (unsigned long)S3C_VA_UART,
-   .pfn= __phys_to_pfn(EXYNOS4_PA_UART),
-   .length = SZ_512K,
-   .type   = MT_DEVICE,
-   }, {
.virtual= (unsigned long)S5P_VA_CMU,
.pfn= __phys_to_pfn(EXYNOS4_PA_CMU),
.length = SZ_128K,
@@ -268,20 +261,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
.pfn= __phys_to_pfn(EXYNOS5_PA_PMU),
.length = SZ_64K,
.type   = MT_DEVICE,
-   }, {
-   .virtual= (unsigned long)S3C_VA_UART,
-   .pfn= __phys_to_pfn(EXYNOS5_PA_UART),
-   .length = SZ_512K,
-   .type   = MT_DEVICE,
-   },
-};
-
-static struct map_desc exynos5440_iodesc0[] __initdata = {
-   {
-   .virtual= (unsigned long)S3C_VA_UART,
-   .pfn= __phys_to_pfn(EXYNOS5440_PA_UART0),
-   .length = SZ_512K,
-   .type   = MT_DEVICE,
},
 };
 
@@ -388,11 +367,6 @@ static void __init exynos5_map_io(void)
iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
 }
 
-static void __init exynos5440_map_io(void)
-{
-   iotable_init(exynos5440_iodesc0, ARRAY_SIZE(exynos5440_iodesc0));
-}
-
 void __init exynos_init_time(void)
 {
of_clk_init(NULL);
-- 
1.7.0.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


[PATCH 1/2] ARM: SAMSUNG: pm: Save/restore only selected uart's registers

2013-07-23 Thread Yadwinder Singh Brar
Basically this code gets executed only during debugging i.e when DEBUG_LL 
SAMSUNG_PM_DEBUG is on, so required only for UART used for debugging.
Since we are removing static iodesc entries for UARTs, so now only the selected
(CONFIG_DEBUG_S3C_UART) UART will be ioremapped by the debug_ll_io_init() for
DEBUG_LL, so save/restore uart registers only for selected uart.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 arch/arm/plat-samsung/pm.c |   14 +++---
 1 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
index ea36136..d0c2301 100644
--- a/arch/arm/plat-samsung/pm.c
+++ b/arch/arm/plat-samsung/pm.c
@@ -80,7 +80,7 @@ unsigned char pm_uart_udivslot;
 
 #ifdef CONFIG_SAMSUNG_PM_DEBUG
 
-static struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
+static struct pm_uart_save uart_save;
 
 static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
 {
@@ -101,11 +101,7 @@ static void s3c_pm_save_uart(unsigned int uart, struct 
pm_uart_save *save)
 
 static void s3c_pm_save_uarts(void)
 {
-   struct pm_uart_save *save = uart_save;
-   unsigned int uart;
-
-   for (uart = 0; uart  CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
-   s3c_pm_save_uart(uart, save);
+   s3c_pm_save_uart(CONFIG_DEBUG_S3C_UART, uart_save);
 }
 
 static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
@@ -126,11 +122,7 @@ static void s3c_pm_restore_uart(unsigned int uart, struct 
pm_uart_save *save)
 
 static void s3c_pm_restore_uarts(void)
 {
-   struct pm_uart_save *save = uart_save;
-   unsigned int uart;
-
-   for (uart = 0; uart  CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
-   s3c_pm_restore_uart(uart, save);
+   s3c_pm_restore_uart(CONFIG_DEBUG_S3C_UART, uart_save);
 }
 #else
 static void s3c_pm_save_uarts(void) { }
-- 
1.7.0.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


[PATCH] ARM: EXYNOS: Fix low level debug support

2013-07-22 Thread Yadwinder Singh Brar
Presently, using exynos_defconfig with CONFIG_DEBUG_LL and CONFIG_EARLY_PRINTK
on, kernel is not booting, we are getting following:

[0.00] [ cut here ]
[0.00] kernel BUG at mm/vmalloc.c:1134!
[0.00] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
[0.00] Modules linked in:
[0.00] CPU: 0 PID: 0 Comm: swapper Not tainted 3.11.0-rc1 #633
[0.00] task: c052ec48 ti: c0524000 task.ti: c0524000
[0.00] PC is at vm_area_add_early+0x54/0x94
[0.00] LR is at add_static_vm_early+0xc/0x60

Its because iotable_init tries to map UART again which is already mapped by
debug_ll_io_init() call in exynos_init_io() within same virtal address range as
requested later.

This issue seems to be occured after :
commit ee4de5d99aeac44f4507b7538b2b3faedc5205b9
ARM: 7781/1: mmu: Add debug_ll_io_init() mappings to early mappings

This patch moves S3C_UART iodesc(in iodesc_list) inside CONFIG_DEBUG_LL check.

Tested on 4412 and 5250 smdks.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 arch/arm/mach-exynos/common.c |   20 ++--
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 164685b..7f0591f 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -150,11 +150,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.length = SZ_64K,
.type   = MT_DEVICE,
}, {
-   .virtual= (unsigned long)S3C_VA_UART,
-   .pfn= __phys_to_pfn(EXYNOS4_PA_UART),
-   .length = SZ_512K,
-   .type   = MT_DEVICE,
-   }, {
.virtual= (unsigned long)S5P_VA_CMU,
.pfn= __phys_to_pfn(EXYNOS4_PA_CMU),
.length = SZ_128K,
@@ -185,6 +180,14 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.length = SZ_4K,
.type   = MT_DEVICE,
},
+#ifndef CONFIG_DEBUG_LL
+   {
+   .virtual= (unsigned long)S3C_VA_UART,
+   .pfn= __phys_to_pfn(EXYNOS4_PA_UART),
+   .length = SZ_512K,
+   .type   = MT_DEVICE,
+   },
+#endif
 };
 
 static struct map_desc exynos4_iodesc0[] __initdata = {
@@ -268,21 +271,26 @@ static struct map_desc exynos5_iodesc[] __initdata = {
.pfn= __phys_to_pfn(EXYNOS5_PA_PMU),
.length = SZ_64K,
.type   = MT_DEVICE,
-   }, {
+   },
+#ifndef CONFIG_DEBUG_LL
+   {
.virtual= (unsigned long)S3C_VA_UART,
.pfn= __phys_to_pfn(EXYNOS5_PA_UART),
.length = SZ_512K,
.type   = MT_DEVICE,
},
+#endif
 };
 
 static struct map_desc exynos5440_iodesc0[] __initdata = {
+#ifndef CONFIG_DEBUG_LL
{
.virtual= (unsigned long)S3C_VA_UART,
.pfn= __phys_to_pfn(EXYNOS5440_PA_UART0),
.length = SZ_512K,
.type   = MT_DEVICE,
},
+#endif
 };
 
 void exynos4_restart(enum reboot_mode mode, const char *cmd)
-- 
1.7.0.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


Re: [PATCH] ARM: EXYNOS: Fix low level debug support

2013-07-22 Thread Yadwinder Singh Brar
Hi Thomas,

On Mon, Jul 22, 2013 at 4:53 PM, Thomas Abraham
thomas.abra...@linaro.org wrote:
 On 13 July 2013 04:57, Yadwinder Singh Brar yadi.b...@samsung.com wrote:
 Presently, using exynos_defconfig with CONFIG_DEBUG_LL and 
 CONFIG_EARLY_PRINTK
 on, kernel is not booting, we are getting following:

 [0.00] [ cut here ]
 [0.00] kernel BUG at mm/vmalloc.c:1134!
 [0.00] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
 [0.00] Modules linked in:
 [0.00] CPU: 0 PID: 0 Comm: swapper Not tainted 3.11.0-rc1 #633
 [0.00] task: c052ec48 ti: c0524000 task.ti: c0524000
 [0.00] PC is at vm_area_add_early+0x54/0x94
 [0.00] LR is at add_static_vm_early+0xc/0x60

 Its because iotable_init tries to map UART again which is already mapped by
 debug_ll_io_init() call in exynos_init_io() within same virtal address range 
 as
 requested later.

 debug_ll_io_init ioremaps debug uart address space with 4KB size
 whereas the exynos_init_io() function ioremaps a single 512KB memory
 size for all the four uart ports which envelops the mapping created by
 debug_ll_io_init. This is caught as a kernel bug.


Exactly !


 This issue seems to be occured after :
 commit ee4de5d99aeac44f4507b7538b2b3faedc5205b9
 ARM: 7781/1: mmu: Add debug_ll_io_init() mappings to early mappings

 This patch moves S3C_UART iodesc(in iodesc_list) inside CONFIG_DEBUG_LL 
 check.

 Instead of moving, all the such iodesc entries for UART controller can
 be removed for all Samsung SoC's now since the Samsung uart driver
 does a ioremap during probe and any needed iomapping for earlyprintk
 is handled by debug_ll_io_init().


Ok, will do it.
TBH I was not sure about removing completely.
Thanks for review.

Regards,
Yadwinder


 Tested on 4412 and 5250 smdks.

 Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
 ---
  arch/arm/mach-exynos/common.c |   20 ++--
  1 files changed, 14 insertions(+), 6 deletions(-)

 diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
 index 164685b..7f0591f 100644
 --- a/arch/arm/mach-exynos/common.c
 +++ b/arch/arm/mach-exynos/common.c
 @@ -150,11 +150,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
 .length = SZ_64K,
 .type   = MT_DEVICE,
 }, {
 -   .virtual= (unsigned long)S3C_VA_UART,
 -   .pfn= __phys_to_pfn(EXYNOS4_PA_UART),
 -   .length = SZ_512K,
 -   .type   = MT_DEVICE,
 -   }, {
 .virtual= (unsigned long)S5P_VA_CMU,
 .pfn= __phys_to_pfn(EXYNOS4_PA_CMU),
 .length = SZ_128K,
 @@ -185,6 +180,14 @@ static struct map_desc exynos4_iodesc[] __initdata = {
 .length = SZ_4K,
 .type   = MT_DEVICE,
 },
 +#ifndef CONFIG_DEBUG_LL
 +   {
 +   .virtual= (unsigned long)S3C_VA_UART,
 +   .pfn= __phys_to_pfn(EXYNOS4_PA_UART),
 +   .length = SZ_512K,
 +   .type   = MT_DEVICE,
 +   },
 +#endif
  };

  static struct map_desc exynos4_iodesc0[] __initdata = {
 @@ -268,21 +271,26 @@ static struct map_desc exynos5_iodesc[] __initdata = {
 .pfn= __phys_to_pfn(EXYNOS5_PA_PMU),
 .length = SZ_64K,
 .type   = MT_DEVICE,
 -   }, {
 +   },
 +#ifndef CONFIG_DEBUG_LL
 +   {
 .virtual= (unsigned long)S3C_VA_UART,
 .pfn= __phys_to_pfn(EXYNOS5_PA_UART),
 .length = SZ_512K,
 .type   = MT_DEVICE,
 },
 +#endif
  };

  static struct map_desc exynos5440_iodesc0[] __initdata = {
 +#ifndef CONFIG_DEBUG_LL
 {
 .virtual= (unsigned long)S3C_VA_UART,
 .pfn= __phys_to_pfn(EXYNOS5440_PA_UART0),
 .length = SZ_512K,
 .type   = MT_DEVICE,
 },
 +#endif
  };

  void exynos4_restart(enum reboot_mode mode, const char *cmd)
 --
 1.7.0.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


Re: [PATCH v2 1/6] clk: samsung: move common plls registration into separate function

2013-07-10 Thread Yadwinder Singh Brar
Hi Heiko,

On Wed, Jul 10, 2013 at 4:27 AM, Heiko Stübner he...@sntech.de wrote:
 All Samsung PLLs use similar code to register the clocks and clkdev lookups.
 Therefore move these into a separate function to reduce code duplication.

 Suggested-by: Russell King li...@arm.linux.org.uk
 Signed-off-by: Heiko Stuebner he...@sntech.de
 ---

I have posted patch for adding common pll registration function
which some how missed to get merged. I hope will get merged after rc1.
Please give a look at that :
http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg19543.html

Regards,
Yadwinder
--
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


[PATCH v7 04/11] clk: samsung: Migrate exynos4 to use common samsung_clk_register_pll()

2013-06-20 Thread Yadwinder Singh Brar
This patch migrates exynos4 pll registeration to use common
samsung_clk_register_pll() by intialising table of PLLs.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
---
 drivers/clk/samsung/clk-exynos4.c |   40 -
 1 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c 
b/drivers/clk/samsung/clk-exynos4.c
index 50af410..f2c2156 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -17,7 +17,6 @@
 #include linux/of_address.h
 
 #include clk.h
-#include clk-pll.h
 
 /* Exynos4 clock controller register offsets */
 #define SRC_LEFTBUS0x4200
@@ -97,12 +96,14 @@
 #define GATE_IP_PERIL  0xc950
 #define E4210_GATE_IP_PERIR0xc960
 #define GATE_BLOCK 0xc970
+#define E4X12_MPLL_LOCK0x10008
 #define E4X12_MPLL_CON00x10108
 #define SRC_DMC0x10200
 #define SRC_MASK_DMC   0x10300
 #define DIV_DMC0   0x10500
 #define DIV_DMC1   0x10504
 #define GATE_IP_DMC0x10900
+#define APLL_LOCK  0x14000
 #define APLL_CON0  0x14100
 #define E4210_MPLL_CON00x14108
 #define SRC_CPU0x14200
@@ -121,6 +122,12 @@ enum exynos4_soc {
EXYNOS4X12,
 };
 
+/* list of PLLs to be registered */
+enum exynos4_plls {
+   apll, mpll, epll, vpll,
+   nr_plls /* number of PLLs */
+};
+
 /*
  * Let each supported clock get a unique id. This id is used to lookup the 
clock
  * for device tree based platforms. The clocks are categorized into three
@@ -990,6 +997,17 @@ static __initdata struct of_device_id ext_clk_match[] = {
{},
 };
 
+struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
+   [apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
+   APLL_CON0, fout_apll),
+   [mpll] = PLL_A(pll_35xx, fout_mpll, fout_mpll, fin_pll,
+   E4X12_MPLL_LOCK, E4X12_MPLL_CON0, fout_mpll),
+   [epll] = PLL_A(pll_36xx, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
+   EPLL_CON0, fout_epll),
+   [vpll] = PLL_A(pll_36xx, fout_vpll, fout_vpll, fin_pll, VPLL_LOCK,
+   VPLL_CON0, fout_vpll),
+};
+
 /* register exynos4 clocks */
 void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc 
exynos4_soc, void __iomem *reg_base, unsigned long xom)
 {
@@ -1026,22 +1044,16 @@ void __init exynos4_clk_init(struct device_node *np, 
enum exynos4_soc exynos4_so
reg_base + EPLL_CON0, pll_4600);
vpll = samsung_clk_register_pll46xx(fout_vpll, mout_vpllsrc,
reg_base + VPLL_CON0, pll_4650c);
+
+   samsung_clk_add_lookup(apll, fout_apll);
+   samsung_clk_add_lookup(mpll, fout_mpll);
+   samsung_clk_add_lookup(epll, fout_epll);
+   samsung_clk_add_lookup(vpll, fout_vpll);
} else {
-   apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
-   reg_base + APLL_CON0);
-   mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
-   reg_base + E4X12_MPLL_CON0);
-   epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + EPLL_CON0);
-   vpll = samsung_clk_register_pll36xx(fout_vpll, fin_pll,
-   reg_base + VPLL_CON0);
+   samsung_clk_register_pll(exynos4_plls,
+   ARRAY_SIZE(exynos4_plls), reg_base);
}
 
-   samsung_clk_add_lookup(apll, fout_apll);
-   samsung_clk_add_lookup(mpll, fout_mpll);
-   samsung_clk_add_lookup(epll, fout_epll);
-   samsung_clk_add_lookup(vpll, fout_vpll);
-
samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
ARRAY_SIZE(exynos4_fixed_rate_clks));
samsung_clk_register_mux(exynos4_mux_clks,
-- 
1.7.0.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


[PATCH v7 08/11] clk: samsung: Add set_rate() clk_ops for PLL35xx

2013-06-20 Thread Yadwinder Singh Brar
This patch add set_rate() and round_rate() for PLL35xx

Reviewed-by: Doug Anderson diand...@chromium.org
Reviewed-by: Tomasz Figa t.f...@samsung.com
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-pll.c |  105 -
 1 files changed, 104 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index adc0659..b5c8b15 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -24,16 +24,51 @@ struct samsung_clk_pll {
 
 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
 
+static const struct samsung_pll_rate_table *samsung_get_pll_settings(
+   struct samsung_clk_pll *pll, unsigned long rate)
+{
+   const struct samsung_pll_rate_table  *rate_table = pll-rate_table;
+   int i;
+
+   for (i = 0; i  pll-rate_count; i++) {
+   if (rate == rate_table[i].rate)
+   return rate_table[i];
+   }
+
+   return NULL;
+}
+
+static long samsung_pll_round_rate(struct clk_hw *hw,
+   unsigned long drate, unsigned long *prate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   const struct samsung_pll_rate_table *rate_table = pll-rate_table;
+   int i;
+
+   /* Assumming rate_table is in descending order */
+   for (i = 0; i  pll-rate_count; i++) {
+   if (drate = rate_table[i].rate)
+   return rate_table[i].rate;
+   }
+
+   /* return minimum supported value */
+   return rate_table[i - 1].rate;
+}
+
 /*
  * PLL35xx Clock Type
  */
+/* Maximum lock time can be 270 * PDIV cycles */
+#define PLL35XX_LOCK_FACTOR(270)
 
 #define PLL35XX_MDIV_MASK   (0x3FF)
 #define PLL35XX_PDIV_MASK   (0x3F)
 #define PLL35XX_SDIV_MASK   (0x7)
+#define PLL35XX_LOCK_STAT_MASK (0x1)
 #define PLL35XX_MDIV_SHIFT  (16)
 #define PLL35XX_PDIV_SHIFT  (8)
 #define PLL35XX_SDIV_SHIFT  (0)
+#define PLL35XX_LOCK_STAT_SHIFT(29)
 
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -53,8 +88,73 @@ static unsigned long samsung_pll35xx_recalc_rate(struct 
clk_hw *hw,
return (unsigned long)fvco;
 }
 
+static inline bool samsung_pll35xx_mp_change(
+   const struct samsung_pll_rate_table *rate, u32 pll_con)
+{
+   u32 old_mdiv, old_pdiv;
+
+   old_mdiv = (pll_con  PLL35XX_MDIV_SHIFT)  PLL35XX_MDIV_MASK;
+   old_pdiv = (pll_con  PLL35XX_PDIV_SHIFT)  PLL35XX_PDIV_MASK;
+
+   return (rate-mdiv != old_mdiv || rate-pdiv != old_pdiv);
+}
+
+static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long prate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   const struct samsung_pll_rate_table *rate;
+   u32 tmp;
+
+   /* Get required rate settings from table */
+   rate = samsung_get_pll_settings(pll, drate);
+   if (!rate) {
+   pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__,
+   drate, __clk_get_name(hw-clk));
+   return -EINVAL;
+   }
+
+   tmp = __raw_readl(pll-con_reg);
+
+   if (!(samsung_pll35xx_mp_change(rate, tmp))) {
+   /* If only s change, change just s value only*/
+   tmp = ~(PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT);
+   tmp |= rate-sdiv  PLL35XX_SDIV_SHIFT;
+   __raw_writel(tmp, pll-con_reg);
+
+   return 0;
+   }
+
+   /* Set PLL lock time. */
+   __raw_writel(rate-pdiv * PLL35XX_LOCK_FACTOR,
+   pll-lock_reg);
+
+   /* Change PLL PMS values */
+   tmp = ~((PLL35XX_MDIV_MASK  PLL35XX_MDIV_SHIFT) |
+   (PLL35XX_PDIV_MASK  PLL35XX_PDIV_SHIFT) |
+   (PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT));
+   tmp |= (rate-mdiv  PLL35XX_MDIV_SHIFT) |
+   (rate-pdiv  PLL35XX_PDIV_SHIFT) |
+   (rate-sdiv  PLL35XX_SDIV_SHIFT);
+   __raw_writel(tmp, pll-con_reg);
+
+   /* wait_lock_time */
+   do {
+   cpu_relax();
+   tmp = __raw_readl(pll-con_reg);
+   } while (!(tmp  (PLL35XX_LOCK_STAT_MASK
+PLL35XX_LOCK_STAT_SHIFT)));
+   return 0;
+}
+
 static const struct clk_ops samsung_pll35xx_clk_ops = {
.recalc_rate = samsung_pll35xx_recalc_rate,
+   .round_rate = samsung_pll_round_rate,
+   .set_rate = samsung_pll35xx_set_rate,
+};
+
+static const struct clk_ops samsung_pll35xx_clk_min_ops = {
+   .recalc_rate = samsung_pll35xx_recalc_rate,
 };
 
 /*
@@ -384,7 +484,10 @@ static void __init _samsung_clk_register_pll(struct 
samsung_pll_clock *pll_clk,
/* clk_ops for 35xx and 2550 are similar */
case pll_35xx:
case pll_2550

[PATCH v7 01/11] clk: samsung: Introduce a common samsung_clk_pll struct

2013-06-20 Thread Yadwinder Singh Brar
This patch unifies clk strutures used for PLL35xx  PLL36xx and
adding an extra member lock_reg, so that common code can be factored out.

Reviewed-by: Tomasz Figa t.f...@samsung.com
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-pll.c |   30 --
 1 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 89135f6..8224bde 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -13,6 +13,14 @@
 #include clk.h
 #include clk-pll.h
 
+struct samsung_clk_pll {
+   struct clk_hw   hw;
+   void __iomem*lock_reg;
+   void __iomem*con_reg;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
 /*
  * PLL35xx Clock Type
  */
@@ -24,17 +32,10 @@
 #define PLL35XX_PDIV_SHIFT  (8)
 #define PLL35XX_SDIV_SHIFT  (0)
 
-struct samsung_clk_pll35xx {
-   struct clk_hw   hw;
-   const void __iomem  *con_reg;
-};
-
-#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
-
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
 {
-   struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, pll_con;
u64 fvco = parent_rate;
 
@@ -56,7 +57,7 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
 struct clk * __init samsung_clk_register_pll35xx(const char *name,
const char *pname, const void __iomem *con_reg)
 {
-   struct samsung_clk_pll35xx *pll;
+   struct samsung_clk_pll *pll;
struct clk *clk;
struct clk_init_data init;
 
@@ -100,17 +101,10 @@ struct clk * __init samsung_clk_register_pll35xx(const 
char *name,
 #define PLL36XX_PDIV_SHIFT (8)
 #define PLL36XX_SDIV_SHIFT (0)
 
-struct samsung_clk_pll36xx {
-   struct clk_hw   hw;
-   const void __iomem  *con_reg;
-};
-
-#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
-
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
 {
-   struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
u64 fvco = parent_rate;
 
@@ -135,7 +129,7 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
 struct clk * __init samsung_clk_register_pll36xx(const char *name,
const char *pname, const void __iomem *con_reg)
 {
-   struct samsung_clk_pll36xx *pll;
+   struct samsung_clk_pll *pll;
struct clk *clk;
struct clk_init_data init;
 
-- 
1.7.0.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


[PATCH v7 11/11] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

2013-06-20 Thread Yadwinder Singh Brar
From: Vikas Sajjan vikas.saj...@linaro.org

Adds the EPLL and VPLL freq table for exynos5250 SoC.

Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos5250.c |   38 ++
 drivers/clk/samsung/clk.h|2 +
 2 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 492d119..2aabecb 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -498,6 +498,29 @@ static struct samsung_gate_clock exynos5250_gate_clks[] 
__initdata = {
GATE(g3d, g3d, aclk_400_g3d, GATE_IP_G3D, 0, 0, 0),
 };
 
+static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = {
+   /* sorted in descending order */
+   /* PLL_36XX_RATE(rate, m, p, s, k) */
+   PLL_36XX_RATE(26600, 266, 3, 3, 0),
+   /* Not in UM, but need for eDP on snow */
+   PLL_36XX_RATE(7050, 94, 2, 4, 0),
+   { },
+};
+
+static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
+   /* sorted in descending order */
+   /* PLL_36XX_RATE(rate, m, p, s, k) */
+   PLL_36XX_RATE(19200, 64, 2, 2, 0),
+   PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
+   PLL_36XX_RATE(18000, 90, 3, 2, 0),
+   PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
+   PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
+   PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
+   PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
+   PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
+   { },
+};
+
 struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
[apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
APLL_CON0, fout_apll, NULL),
@@ -524,6 +547,8 @@ static __initdata struct of_device_id ext_clk_match[] = {
 static void __init exynos5250_clk_init(struct device_node *np)
 {
void __iomem *reg_base;
+   struct clk *vpllsrc;
+   unsigned long fin_pll_rate, mout_vpllsrc_rate = 0;
 
if (np) {
reg_base = of_iomap(np, 0);
@@ -541,6 +566,19 @@ static void __init exynos5250_clk_init(struct device_node 
*np)
ext_clk_match);
samsung_clk_register_mux(exynos5250_pll_pmux_clks,
ARRAY_SIZE(exynos5250_pll_pmux_clks));
+
+   fin_pll_rate = _get_rate(fin_pll);
+
+   if (fin_pll_rate == 24 * MHZ)
+   exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
+
+   vpllsrc = __clk_lookup(mout_vpllsrc);
+   if (vpllsrc)
+   mout_vpllsrc_rate = clk_get_rate(vpllsrc);
+
+   if (mout_vpllsrc_rate == 24 * MHZ)
+   exynos5250_plls[vpll].rate_table =  vpll_24mhz_tbl;
+
samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
reg_base);
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 4a003d7..d459ef7 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -40,6 +40,8 @@ struct samsung_clock_alias {
.alias  = a,\
}
 
+#define MHZ (1000 * 1000)
+
 /**
  * struct samsung_fixed_rate_clock: information about fixed-rate clock
  * @id: platform specific id of the clock.
-- 
1.7.0.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


[PATCH v7 05/11] clk: samsung: Migrate exynos5420 to use common samsung_clk_register_pll()

2013-06-20 Thread Yadwinder Singh Brar
This patch migrates exynos5420 pll registeration to use common
samsung_clk_register_pll() by intialising table of PLLs and adding PLLs to
unique id list of clocks.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
---
 drivers/clk/samsung/clk-exynos5420.c |   86 +++---
 1 files changed, 58 insertions(+), 28 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5420.c 
b/drivers/clk/samsung/clk-exynos5420.c
index 68a96cb..3ea6b4f 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -17,13 +17,30 @@
 #include linux/of_address.h
 
 #include clk.h
-#include clk-pll.h
 
+#define APLL_LOCK  0x0
+#define APLL_CON0  0x100
 #define SRC_CPU0x200
 #define DIV_CPU0   0x500
 #define DIV_CPU1   0x504
 #define GATE_BUS_CPU   0x700
 #define GATE_SCLK_CPU  0x800
+#define CPLL_LOCK  0x10020
+#define DPLL_LOCK  0x10030
+#define EPLL_LOCK  0x10040
+#define RPLL_LOCK  0x10050
+#define IPLL_LOCK  0x10060
+#define SPLL_LOCK  0x10070
+#define VPLL_LOCK  0x10070
+#define MPLL_LOCK  0x10090
+#define CPLL_CON0  0x10120
+#define DPLL_CON0  0x10128
+#define EPLL_CON0  0x10130
+#define RPLL_CON0  0x10140
+#define IPLL_CON0  0x10150
+#define SPLL_CON0  0x10160
+#define VPLL_CON0  0x10170
+#define MPLL_CON0  0x10180
 #define SRC_TOP0   0x10200
 #define SRC_TOP1   0x10204
 #define SRC_TOP2   0x10208
@@ -75,15 +92,27 @@
 #define GATE_TOP_SCLK_MAU  0x1083c
 #define GATE_TOP_SCLK_FSYS 0x10840
 #define GATE_TOP_SCLK_PERIC0x10850
+#define BPLL_LOCK  0x20010
+#define BPLL_CON0  0x20110
 #define SRC_CDREX  0x20200
+#define KPLL_LOCK  0x28000
+#define KPLL_CON0  0x28100
 #define SRC_KFC0x28200
 #define DIV_KFC0   0x28500
 
+/* list of PLLs */
+enum exynos5420_plls {
+   apll, cpll, dpll, epll, rpll, ipll, spll, vpll, mpll,
+   bpll, kpll,
+   nr_plls /* number of PLLs */
+};
+
 enum exynos5420_clks {
none,
 
/* core clocks */
-   fin_pll,
+   fin_pll,  fout_apll, fout_cpll, fout_dpll, fout_epll, fout_rpll,
+   fout_ipll, fout_spll, fout_vpll, fout_mpll, fout_bpll, fout_kpll,
 
/* gate for special clocks (sclk) */
sclk_uart0 = 128, sclk_uart1, sclk_uart2, sclk_uart3, sclk_mmc0,
@@ -698,6 +727,31 @@ struct samsung_gate_clock exynos5420_gate_clks[] 
__initdata = {
GATE(smmu_mscl2, smmu_mscl2, aclk400_mscl, GATE_IP_MSCL, 10, 0, 0),
 };
 
+struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = {
+   [apll] = PLL(pll_2550, fout_apll, fout_apll, fin_pll, APLL_LOCK,
+   APLL_CON0),
+   [cpll] = PLL(pll_2550, fout_mpll, fout_mpll, fin_pll, MPLL_LOCK,
+   MPLL_CON0),
+   [dpll] = PLL(pll_2550, fout_dpll, fout_dpll, fin_pll, DPLL_LOCK,
+   DPLL_CON0),
+   [epll] = PLL(pll_2650, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
+   EPLL_CON0),
+   [rpll] = PLL(pll_2650, fout_rpll, fout_rpll, fin_pll, RPLL_LOCK,
+   RPLL_CON0),
+   [ipll] = PLL(pll_2550, fout_ipll, fout_ipll, fin_pll, IPLL_LOCK,
+   IPLL_CON0),
+   [spll] = PLL(pll_2550, fout_spll, fout_spll, fin_pll, SPLL_LOCK,
+   SPLL_CON0),
+   [vpll] = PLL(pll_2550, fout_vpll, fout_vpll, fin_pll, VPLL_LOCK,
+   VPLL_CON0),
+   [mpll] = PLL(pll_2550, fout_mpll, fout_mpll, fin_pll, MPLL_LOCK,
+   MPLL_CON0),
+   [bpll] = PLL(pll_2550, fout_bpll, fout_bpll, fin_pll, BPLL_LOCK,
+   BPLL_CON0),
+   [kpll] = PLL(pll_2550, fout_kpll, fout_kpll, fin_pll, KPLL_LOCK,
+   KPLL_CON0),
+};
+
 static __initdata struct of_device_id ext_clk_match[] = {
{ .compatible = samsung,exynos5420-oscclk, .data = (void *)0, },
{ },
@@ -707,8 +761,6 @@ static __initdata struct of_device_id ext_clk_match[] = {
 void __init exynos5420_clk_init(struct device_node *np)
 {
void __iomem *reg_base;
-   struct clk *apll, *bpll, *cpll, *dpll, *epll, *ipll, *kpll, *mpll;
-   struct clk *rpll, *spll, *vpll;
 
if (np) {
reg_base = of_iomap(np, 0);
@@ -724,30 +776,8 @@ void __init exynos5420_clk_init(struct device_node *np)
samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
ext_clk_match);
-
-   apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
-   reg_base + 0x100);
-   bpll = samsung_clk_register_pll35xx(fout_bpll, fin_pll

[PATCH v7 10/11] clk: samsung: Reorder MUX registration for mout_vpllsrc

2013-06-20 Thread Yadwinder Singh Brar
From: Vikas Sajjan vikas.saj...@linaro.org

While trying to get rate of mout_vpllsrc MUX (parent) for registering the
fout_vpll (child), we found get rate was failing.

So this patch moves the mout_vpllsrc MUX out of the existing common list
and registers the mout_vpllsrc MUX before the PLL registrations.

Reviewed-by: Tomasz Figa t.f...@samsung.com
Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos5250.c |7 ++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 623ae44..492d119 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -233,6 +233,10 @@ static struct samsung_fixed_factor_clock 
exynos5250_fixed_factor_clks[] __initda
FFACTOR(none, fout_bplldiv2, fout_bpll, 1, 2, 0),
 };
 
+static struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+   MUX(none, mout_vpllsrc, mout_vpllsrc_p, SRC_TOP2, 0, 1),
+};
+
 static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(none, mout_apll, mout_apll_p, SRC_CPU, 0, 1),
MUX(none, mout_cpu, mout_cpu_p, SRC_CPU, 16, 1),
@@ -240,7 +244,6 @@ static struct samsung_mux_clock exynos5250_mux_clks[] 
__initdata = {
MUX(none, sclk_mpll, mout_mpll_p, SRC_CORE1, 8, 1),
MUX(none, mout_bpll_fout, mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
MUX(none, sclk_bpll, mout_bpll_p, SRC_CDREX, 0, 1),
-   MUX(none, mout_vpllsrc, mout_vpllsrc_p, SRC_TOP2, 0, 1),
MUX(none, sclk_vpll, mout_vpll_p, SRC_TOP2, 16, 1),
MUX(none, sclk_epll, mout_epll_p, SRC_TOP2, 12, 1),
MUX(none, sclk_cpll, mout_cpll_p, SRC_TOP2, 8, 1),
@@ -536,6 +539,8 @@ static void __init exynos5250_clk_init(struct device_node 
*np)
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
+   samsung_clk_register_mux(exynos5250_pll_pmux_clks,
+   ARRAY_SIZE(exynos5250_pll_pmux_clks));
samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
reg_base);
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
-- 
1.7.0.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


[PATCH v7 00/11] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs

2013-06-20 Thread Yadwinder Singh Brar
This patch series does the following:

 1) Unifies the clk strutures  and registration function used for PLL35xx 
PLL36xx, to factor out possible common code.

 2) Defines a common rate_table which will contain recommended p, m, s and k
values for supported rates that needs to be changed for changing
corresponding PLL's rate

 3) Adds set_rate() and round_rate() clk_ops for PLL35xx and PLL36xx

changes since v6:
- Splited the patch adding samsung_clk_register_pll() into definition
addition, SoC specific migration and cleanup patches.
- Addressed some NIT comments.

changes since v5:
- Corrected to use rate table as specified in UM for exynos5250 epll.
- Took care of exynos5420 as well, as new exynos5420 clk driver came in
while rebasing on latest Kgene's for-next.

Since we spilted 1st patch into 2 different patches,
can we expect reviewed-by again for the same? 

changes since v4:
- Defined common samsung samsung_clk_register_pll() to register a list
of PLL and used a struct samsung_pll_clock for passing intialisation
data instead of passing as arguments. Now passing LOCK as well as CON0
offset as intialisation data.
- Calculated length of rate table while registering PLL instead of
getting it as intialisation data.

changes since v3:
- Used __clk_lookup() instead of adding alias for mout_vpllsrc
- Added check for changing only M value in samsung_pll36xx_set_rate()
- Modified samsung_pll35xx_mp_change()  samsung_pll35xx_set_rate()
to improve readabilty.
- Made the input rate_table as __init_data which is to be provided while
registering PLL and made a copy of that table while registering, so
that if multiple tables are their, they can be freed after getting the
P, M, S, K setting values from required one.

changes since v2:
- Added new patch to reorder the MUX registration for mout_vpllsrc MUX
before the PLL registrations. And to add the alias for the mout_vpllsrc 
MUX.
- Added a check to confirm parent rate while registrating the PLL
rate tables.

changes since v1:
- removed sorting and bsearch
- modified the definition of struct samsung_pll_rate_table
- added generic round_rate()
- rectified the ops assignment for rate table passed as NULL

Is rebased on branch kgene's for-next
https://git.kernel.org/cgit/linux/kernel/git/kgene/linux-samsung.git/log/?h=for-next

Vikas Sajjan (3):
  clk: samsung: Add set_rate() clk_ops for PLL36xx
  clk: samsung: Reorder MUX registration for mout_vpllsrc
  clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

Yadwinder Singh Brar (8):
  clk: samsung: Introduce a common samsung_clk_pll struct
  clk: samsung: Define a common samsung_clk_register_pll()
  clk: samsung: Migrate exynos5250 to use common
samsung_clk_register_pll()
  clk: samsung: Migrate exynos4 to use common
samsung_clk_register_pll()
  clk: samsung: Migrate exynos5420 to use common
samsung_clk_register_pll()
  clk: samsung: Remove unused pll registeration code for pll35xx and
pll36xx
  clk: samsung: Add support to register rate_table for samsung plls
  clk: samsung: Add set_rate() clk_ops for PLL35xx

 drivers/clk/samsung/clk-exynos4.c|   40 +++--
 drivers/clk/samsung/clk-exynos5250.c |  101 +--
 drivers/clk/samsung/clk-exynos5420.c |   86 ++---
 drivers/clk/samsung/clk-pll.c|  339 ++
 drivers/clk/samsung/clk-pll.h|   38 -
 drivers/clk/samsung/clk.h|   53 ++
 6 files changed, 519 insertions(+), 138 deletions(-)

--
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


[PATCH v7 09/11] clk: samsung: Add set_rate() clk_ops for PLL36xx

2013-06-20 Thread Yadwinder Singh Brar
From: Vikas Sajjan vikas.saj...@linaro.org

This patch adds set_rate and round_rate clk_ops for PLL36xx

Reviewed-by: Tomasz Figa t.f...@samsung.com
Reviewed-by: Doug Anderson diand...@chromium.org
Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
---
 drivers/clk/samsung/clk-pll.c |   79 -
 1 files changed, 78 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index b5c8b15..66cb1cb 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -160,6 +160,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
 /*
  * PLL36xx Clock Type
  */
+/* Maximum lock time can be 3000 * PDIV cycles */
+#define PLL36XX_LOCK_FACTOR(3000)
 
 #define PLL36XX_KDIV_MASK  (0x)
 #define PLL36XX_MDIV_MASK  (0x1FF)
@@ -168,6 +170,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
 #define PLL36XX_MDIV_SHIFT (16)
 #define PLL36XX_PDIV_SHIFT (8)
 #define PLL36XX_SDIV_SHIFT (0)
+#define PLL36XX_KDIV_SHIFT (0)
+#define PLL36XX_LOCK_STAT_SHIFT(29)
 
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -190,8 +194,78 @@ static unsigned long samsung_pll36xx_recalc_rate(struct 
clk_hw *hw,
return (unsigned long)fvco;
 }
 
+static inline bool samsung_pll36xx_mpk_change(
+   const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
+{
+   u32 old_mdiv, old_pdiv, old_kdiv;
+
+   old_mdiv = (pll_con0  PLL36XX_MDIV_SHIFT)  PLL36XX_MDIV_MASK;
+   old_pdiv = (pll_con0  PLL36XX_PDIV_SHIFT)  PLL36XX_PDIV_MASK;
+   old_kdiv = (pll_con1  PLL36XX_KDIV_SHIFT)  PLL36XX_KDIV_MASK;
+
+   return (rate-mdiv != old_mdiv || rate-pdiv != old_pdiv ||
+   rate-kdiv != old_kdiv);
+}
+
+static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long parent_rate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   u32 tmp, pll_con0, pll_con1;
+   const struct samsung_pll_rate_table *rate;
+
+   rate = samsung_get_pll_settings(pll, drate);
+   if (!rate) {
+   pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__,
+   drate, __clk_get_name(hw-clk));
+   return -EINVAL;
+   }
+
+   pll_con0 = __raw_readl(pll-con_reg);
+   pll_con1 = __raw_readl(pll-con_reg + 4);
+
+   if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
+   /* If only s change, change just s value only*/
+   pll_con0 = ~(PLL36XX_SDIV_MASK  PLL36XX_SDIV_SHIFT);
+   pll_con0 |= (rate-sdiv  PLL36XX_SDIV_SHIFT);
+   __raw_writel(pll_con0, pll-con_reg);
+
+   return 0;
+   }
+
+   /* Set PLL lock time. */
+   __raw_writel(rate-pdiv * PLL36XX_LOCK_FACTOR, pll-lock_reg);
+
+/* Change PLL PMS values */
+   pll_con0 = ~((PLL36XX_MDIV_MASK  PLL36XX_MDIV_SHIFT) |
+   (PLL36XX_PDIV_MASK  PLL36XX_PDIV_SHIFT) |
+   (PLL36XX_SDIV_MASK  PLL36XX_SDIV_SHIFT));
+   pll_con0 |= (rate-mdiv  PLL36XX_MDIV_SHIFT) |
+   (rate-pdiv  PLL36XX_PDIV_SHIFT) |
+   (rate-sdiv  PLL36XX_SDIV_SHIFT);
+   __raw_writel(pll_con0, pll-con_reg);
+
+   pll_con1 = ~(PLL36XX_KDIV_MASK  PLL36XX_KDIV_SHIFT);
+   pll_con1 |= rate-kdiv  PLL36XX_KDIV_SHIFT;
+   __raw_writel(pll_con1, pll-con_reg + 4);
+
+   /* wait_lock_time */
+   do {
+   cpu_relax();
+   tmp = __raw_readl(pll-con_reg);
+   } while (!(tmp  (1  PLL36XX_LOCK_STAT_SHIFT)));
+
+   return 0;
+}
+
 static const struct clk_ops samsung_pll36xx_clk_ops = {
.recalc_rate = samsung_pll36xx_recalc_rate,
+   .set_rate = samsung_pll36xx_set_rate,
+   .round_rate = samsung_pll_round_rate,
+};
+
+static const struct clk_ops samsung_pll36xx_clk_min_ops = {
+   .recalc_rate = samsung_pll36xx_recalc_rate,
 };
 
 /*
@@ -492,7 +566,10 @@ static void __init _samsung_clk_register_pll(struct 
samsung_pll_clock *pll_clk,
/* clk_ops for 36xx and 2650 are similar */
case pll_36xx:
case pll_2650:
-   init.ops = samsung_pll36xx_clk_ops;
+   if (!pll-rate_table)
+   init.ops = samsung_pll36xx_clk_min_ops;
+   else
+   init.ops = samsung_pll36xx_clk_ops;
break;
default:
pr_warn(%s: Unknown pll type for pll clk %s\n,
-- 
1.7.0.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


[PATCH v7 06/11] clk: samsung: Remove unused pll registeration code for pll35xx and pll36xx

2013-06-20 Thread Yadwinder Singh Brar
This patch removes samsung_clk_register_pll35xx() and
samsung_clk_register_pll36xx() registaration functions as users migrated to
new samsung_clk_register_pll().

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-pll.c |   70 -
 drivers/clk/samsung/clk-pll.h |4 --
 2 files changed, 0 insertions(+), 74 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index f20af69..7d5bea8 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -55,41 +55,6 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
.recalc_rate = samsung_pll35xx_recalc_rate,
 };
 
-struct clk * __init samsung_clk_register_pll35xx(const char *name,
-   const char *pname, const void __iomem *con_reg)
-{
-   struct samsung_clk_pll *pll;
-   struct clk *clk;
-   struct clk_init_data init;
-
-   pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-   if (!pll) {
-   pr_err(%s: could not allocate pll clk %s\n, __func__, name);
-   return NULL;
-   }
-
-   init.name = name;
-   init.ops = samsung_pll35xx_clk_ops;
-   init.flags = CLK_GET_RATE_NOCACHE;
-   init.parent_names = pname;
-   init.num_parents = 1;
-
-   pll-hw.init = init;
-   pll-con_reg = con_reg;
-
-   clk = clk_register(NULL, pll-hw);
-   if (IS_ERR(clk)) {
-   pr_err(%s: failed to register pll clock %s\n, __func__,
-   name);
-   kfree(pll);
-   }
-
-   if (clk_register_clkdev(clk, name, NULL))
-   pr_err(%s: failed to register lookup for %s, __func__, name);
-
-   return clk;
-}
-
 /*
  * PLL36xx Clock Type
  */
@@ -127,41 +92,6 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
.recalc_rate = samsung_pll36xx_recalc_rate,
 };
 
-struct clk * __init samsung_clk_register_pll36xx(const char *name,
-   const char *pname, const void __iomem *con_reg)
-{
-   struct samsung_clk_pll *pll;
-   struct clk *clk;
-   struct clk_init_data init;
-
-   pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-   if (!pll) {
-   pr_err(%s: could not allocate pll clk %s\n, __func__, name);
-   return NULL;
-   }
-
-   init.name = name;
-   init.ops = samsung_pll36xx_clk_ops;
-   init.flags = CLK_GET_RATE_NOCACHE;
-   init.parent_names = pname;
-   init.num_parents = 1;
-
-   pll-hw.init = init;
-   pll-con_reg = con_reg;
-
-   clk = clk_register(NULL, pll-hw);
-   if (IS_ERR(clk)) {
-   pr_err(%s: failed to register pll clock %s\n, __func__,
-   name);
-   kfree(pll);
-   }
-
-   if (clk_register_clkdev(clk, name, NULL))
-   pr_err(%s: failed to register lookup for %s, __func__, name);
-
-   return clk;
-}
-
 /*
  * PLL45xx Clock Type
  */
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index 0d86bf0..1536f27 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -31,10 +31,6 @@ enum pll46xx_type {
pll_4650c,
 };
 
-extern struct clk * __init samsung_clk_register_pll35xx(const char *name,
-   const char *pname, const void __iomem *con_reg);
-extern struct clk * __init samsung_clk_register_pll36xx(const char *name,
-   const char *pname, const void __iomem *con_reg);
 extern struct clk * __init samsung_clk_register_pll45xx(const char *name,
const char *pname, const void __iomem *con_reg,
enum pll45xx_type type);
-- 
1.7.0.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


[PATCH v7 03/11] clk: samsung: Migrate exynos5250 to use common samsung_clk_register_pll()

2013-06-20 Thread Yadwinder Singh Brar
This patch migrates exynos5250 pll registeration to use common
samsung_clk_register_pll() by intialising table of PLLs and adding PLLs to
unique id list of clocks.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
---
 drivers/clk/samsung/clk-exynos5250.c |   60 +++---
 1 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index f6e3031..4027c69 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -17,11 +17,22 @@
 #include linux/of_address.h
 
 #include clk.h
-#include clk-pll.h
 
+#define APLL_LOCK  0x0
+#define APLL_CON0  0x100
 #define SRC_CPU0x200
 #define DIV_CPU0   0x500
+#define MPLL_LOCK  0x4000
+#define MPLL_CON0  0x4100
 #define SRC_CORE1  0x4204
+#define CPLL_LOCK  0x10020
+#define EPLL_LOCK  0x10030
+#define VPLL_LOCK  0x10040
+#define GPLL_LOCK  0x10050
+#define CPLL_CON0  0x10120
+#define EPLL_CON0  0x10130
+#define VPLL_CON0  0x10140
+#define GPLL_CON0  0x10150
 #define SRC_TOP0   0x10210
 #define SRC_TOP1   0x10214
 #define SRC_TOP2   0x10218
@@ -61,10 +72,18 @@
 #define GATE_IP_FSYS   0x10944
 #define GATE_IP_PERIC  0x10950
 #define GATE_IP_PERIS  0x10960
+#define BPLL_LOCK  0x20010
+#define BPLL_CON0  0x20110
 #define SRC_CDREX  0x20200
 #define PLL_DIV2_SEL   0x20a24
 #define GATE_IP_DISP1  0x10928
 
+/* list of PLLs to be registered */
+enum exynos5250_plls {
+   apll, mpll, cpll, epll, vpll, gpll, bpll,
+   nr_plls /* number of PLLs */
+};
+
 /*
  * Let each supported clock get a unique id. This id is used to lookup the 
clock
  * for device tree based platforms. The clocks are categorized into three
@@ -81,7 +100,8 @@ enum exynos5250_clks {
none,
 
/* core clocks */
-   fin_pll,
+   fin_pll, fout_apll, fout_mpll, fout_bpll, fout_gpll, fout_cpll,
+   fout_epll, fout_vpll,
 
/* gate for special clocks (sclk) */
sclk_cam_bayer = 128, sclk_cam0, sclk_cam1, sclk_gscl_wa, sclk_gscl_wb,
@@ -475,6 +495,23 @@ static struct samsung_gate_clock exynos5250_gate_clks[] 
__initdata = {
GATE(g3d, g3d, aclk_400_g3d, GATE_IP_G3D, 0, 0, 0),
 };
 
+struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
+   [apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
+   APLL_CON0, fout_apll),
+   [mpll] = PLL_A(pll_35xx, fout_mpll, fout_mpll, fin_pll, MPLL_LOCK,
+   MPLL_CON0, fout_mpll),
+   [bpll] = PLL(pll_35xx, fout_bpll, fout_bpll, fin_pll, BPLL_LOCK,
+   BPLL_CON0),
+   [gpll] = PLL(pll_35xx, fout_gpll, fout_gpll, fin_pll, GPLL_LOCK,
+   GPLL_CON0),
+   [cpll] = PLL(pll_35xx, fout_cpll, fout_cpll, fin_pll, CPLL_LOCK,
+   CPLL_CON0),
+   [epll] = PLL(pll_36xx, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
+   EPLL_CON0),
+   [vpll] = PLL(pll_36xx, fout_vpll, fout_vpll, mout_vpllsrc,
+   VPLL_LOCK, VPLL_CON0),
+};
+
 static __initdata struct of_device_id ext_clk_match[] = {
{ .compatible = samsung,clock-xxti, .data = (void *)0, },
{ },
@@ -484,7 +521,6 @@ static __initdata struct of_device_id ext_clk_match[] = {
 static void __init exynos5250_clk_init(struct device_node *np)
 {
void __iomem *reg_base;
-   struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
 
if (np) {
reg_base = of_iomap(np, 0);
@@ -500,22 +536,8 @@ static void __init exynos5250_clk_init(struct device_node 
*np)
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
-
-   apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
-   reg_base + 0x100);
-   mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
-   reg_base + 0x4100);
-   bpll = samsung_clk_register_pll35xx(fout_bpll, fin_pll,
-   reg_base + 0x20110);
-   gpll = samsung_clk_register_pll35xx(fout_gpll, fin_pll,
-   reg_base + 0x10150);
-   cpll = samsung_clk_register_pll35xx(fout_cpll, fin_pll,
-   reg_base + 0x10120);
-   epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + 0x10130);
-   vpll = samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc,
-   reg_base + 0x10140);
-
+   samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls

Re: [PATCH v7 00/11] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs

2013-06-20 Thread Yadwinder Singh Brar
Hi Tomasz,

On Thu, Jun 20, 2013 at 3:30 PM, Tomasz Figa t.f...@samsung.com wrote:
 Hi Yadwinder, Vikas,

 On Tuesday 11 of June 2013 15:01:05 Yadwinder Singh Brar wrote:
 This patch series does the following:

  1) Unifies the clk strutures  and registration function used for PLL35xx
  PLL36xx, to factor out possible common code.

  2) Defines a common rate_table which will contain recommended p, m, s
 and k values for supported rates that needs to be changed for changing
 corresponding PLL's rate

  3) Adds set_rate() and round_rate() clk_ops for PLL35xx and PLL36xx

 changes since v6:
   - Splited the patch adding samsung_clk_register_pll() into definition
   addition, SoC specific migration and cleanup patches.
   - Addressed some NIT comments.

 This version looks good to me. Thanks for your work on improving this
 series again!

 Reviewed-by: Tomasz Figa t.f...@samsung.com


Thanks for helping to improve this series.

Thanks,
Yadwinder

 Best regards,
 Tomasz

 changes since v5:
   - Corrected to use rate table as specified in UM for exynos5250 epll.
   - Took care of exynos5420 as well, as new exynos5420 clk driver came in
   while rebasing on latest Kgene's for-next.

   Since we spilted 1st patch into 2 different patches,
   can we expect reviewed-by again for the same?

 changes since v4:
   - Defined common samsung samsung_clk_register_pll() to register a list
   of PLL and used a struct samsung_pll_clock for passing intialisation
   data instead of passing as arguments. Now passing LOCK as well as CON0
   offset as intialisation data.
   - Calculated length of rate table while registering PLL instead of
   getting it as intialisation data.

 changes since v3:
   - Used __clk_lookup() instead of adding alias for mout_vpllsrc
   - Added check for changing only M value in samsung_pll36xx_set_rate()
   - Modified samsung_pll35xx_mp_change()  samsung_pll35xx_set_rate()
   to improve readabilty.
   - Made the input rate_table as __init_data which is to be provided
 while
 registering PLL and made a copy of that table while registering, so that
 if multiple tables are their, they can be freed after getting the P, M,
 S, K setting values from required one.

 changes since v2:
   - Added new patch to reorder the MUX registration for mout_vpllsrc MUX
   before the PLL registrations. And to add the alias for the mout_vpllsrc
 MUX. - Added a check to confirm parent rate while registrating the PLL
 rate tables.

 changes since v1:
   - removed sorting and bsearch
   - modified the definition of struct samsung_pll_rate_table
   - added generic round_rate()
   - rectified the ops assignment for rate table passed as NULL

 Is rebased on branch kgene's for-next
 https://git.kernel.org/cgit/linux/kernel/git/kgene/linux-samsung.git/log/
 ?h=for-next

 Vikas Sajjan (3):
   clk: samsung: Add set_rate() clk_ops for PLL36xx
   clk: samsung: Reorder MUX registration for mout_vpllsrc
   clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

 Yadwinder Singh Brar (8):
   clk: samsung: Introduce a common samsung_clk_pll struct
   clk: samsung: Define a common samsung_clk_register_pll()
   clk: samsung: Migrate exynos5250 to use common
 samsung_clk_register_pll()
   clk: samsung: Migrate exynos4 to use common
 samsung_clk_register_pll()
   clk: samsung: Migrate exynos5420 to use common
 samsung_clk_register_pll()
   clk: samsung: Remove unused pll registeration code for pll35xx and
 pll36xx
   clk: samsung: Add support to register rate_table for samsung plls
   clk: samsung: Add set_rate() clk_ops for PLL35xx

  drivers/clk/samsung/clk-exynos4.c|   40 +++--
  drivers/clk/samsung/clk-exynos5250.c |  101 +--
  drivers/clk/samsung/clk-exynos5420.c |   86 ++---
  drivers/clk/samsung/clk-pll.c|  339
 ++ drivers/clk/samsung/clk-pll.h
 |   38 -
  drivers/clk/samsung/clk.h|   53 ++
  6 files changed, 519 insertions(+), 138 deletions(-)
 --
 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-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 3/7] clk: samsung: Add support to register rate_table for samsung plls

2013-06-19 Thread Yadwinder Singh Brar
This patch defines a common rate_table which will contain recommended p, m, s,
k values for supported rates that needs to be changed for changing
corresponding PLL's rate.

Reviewed-by: Doug Anderson diand...@chromium.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos4.c|8 
 drivers/clk/samsung/clk-exynos5250.c |   14 +++---
 drivers/clk/samsung/clk-exynos5420.c |   22 +++---
 drivers/clk/samsung/clk-pll.c|   22 --
 drivers/clk/samsung/clk-pll.h|   27 +++
 drivers/clk/samsung/clk.h|   14 +-
 6 files changed, 78 insertions(+), 29 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c 
b/drivers/clk/samsung/clk-exynos4.c
index ba25a1b..ceee66c 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -997,13 +997,13 @@ static __initdata struct of_device_id ext_clk_match[] = {
 
 struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
[apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
-   APLL_CON0, fout_apll),
+   APLL_CON0, fout_apll, NULL),
[mpll] = PLL_A(pll_35xx, fout_mpll, fout_mpll, fin_pll,
-   E4X12_MPLL_LOCK, E4X12_MPLL_CON0, fout_mpll),
+   E4X12_MPLL_LOCK, E4X12_MPLL_CON0, fout_mpll, NULL),
[epll] = PLL_A(pll_36xx, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
-   EPLL_CON0, fout_epll),
+   EPLL_CON0, fout_epll, NULL),
[vpll] = PLL_A(pll_36xx, fout_vpll, fout_vpll, fin_pll, VPLL_LOCK,
-   VPLL_CON0, fout_vpll),
+   VPLL_CON0, fout_vpll, NULL),
 };
 
 /* register exynos4 clocks */
diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index dc6a700..21f5491 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -492,19 +492,19 @@ static __initdata struct of_device_id ext_clk_match[] = {
 
 struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
[apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
-   APLL_CON0, fout_apll),
+   APLL_CON0, fout_apll, NULL),
[mpll] = PLL_A(pll_35xx, fout_mpll, fout_mpll, fin_pll, MPLL_LOCK,
-   MPLL_CON0, fout_mpll),
+   MPLL_CON0, fout_mpll, NULL),
[bpll] = PLL(pll_35xx, fout_bpll, fout_bpll, fin_pll, BPLL_LOCK,
-   BPLL_CON0),
+   BPLL_CON0, NULL),
[gpll] = PLL(pll_35xx, fout_gpll, fout_gpll, fin_pll, GPLL_LOCK,
-   GPLL_CON0),
+   GPLL_CON0, NULL),
[cpll] = PLL(pll_35xx, fout_cpll, fout_cpll, fin_pll, CPLL_LOCK,
-   CPLL_CON0),
+   CPLL_CON0, NULL),
[epll] = PLL(pll_36xx, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
-   EPLL_CON0),
+   EPLL_CON0, NULL),
[vpll] = PLL(pll_36xx, fout_vpll, fout_vpll, fin_pll, VPLL_LOCK,
-   VPLL_CON0),
+   VPLL_CON0, NULL),
 };
 
 /* register exynox5250 clocks */
diff --git a/drivers/clk/samsung/clk-exynos5420.c 
b/drivers/clk/samsung/clk-exynos5420.c
index 3ea6b4f..86dfc64 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -729,27 +729,27 @@ struct samsung_gate_clock exynos5420_gate_clks[] 
__initdata = {
 
 struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = {
[apll] = PLL(pll_2550, fout_apll, fout_apll, fin_pll, APLL_LOCK,
-   APLL_CON0),
+   APLL_CON0, NULL),
[cpll] = PLL(pll_2550, fout_mpll, fout_mpll, fin_pll, MPLL_LOCK,
-   MPLL_CON0),
+   MPLL_CON0, NULL),
[dpll] = PLL(pll_2550, fout_dpll, fout_dpll, fin_pll, DPLL_LOCK,
-   DPLL_CON0),
+   DPLL_CON0, NULL),
[epll] = PLL(pll_2650, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
-   EPLL_CON0),
+   EPLL_CON0, NULL),
[rpll] = PLL(pll_2650, fout_rpll, fout_rpll, fin_pll, RPLL_LOCK,
-   RPLL_CON0),
+   RPLL_CON0, NULL),
[ipll] = PLL(pll_2550, fout_ipll, fout_ipll, fin_pll, IPLL_LOCK,
-   IPLL_CON0),
+   IPLL_CON0, NULL),
[spll] = PLL(pll_2550, fout_spll, fout_spll, fin_pll, SPLL_LOCK,
-   SPLL_CON0),
+   SPLL_CON0, NULL),
[vpll] = PLL(pll_2550, fout_vpll, fout_vpll, fin_pll, VPLL_LOCK,
-   VPLL_CON0),
+   VPLL_CON0, NULL),
[mpll] = PLL(pll_2550, fout_mpll, fout_mpll, fin_pll, MPLL_LOCK,
-   MPLL_CON0),
+   MPLL_CON0, NULL),
[bpll] = PLL(pll_2550, fout_bpll, fout_bpll, fin_pll, BPLL_LOCK,
-   BPLL_CON0),
+   BPLL_CON0, NULL),
[kpll] = PLL(pll_2550, fout_kpll, fout_kpll, fin_pll, KPLL_LOCK,
-   KPLL_CON0),
+   KPLL_CON0, NULL

[PATCH v6 1/7] clk: samsung: Introduce a common samsung_clk_pll struct

2013-06-19 Thread Yadwinder Singh Brar
This patch unifies clk strutures used for PLL35xx  PLL36xx and
adding an extra member lock_reg, so that common code can be factored out.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-pll.c |   30 --
 1 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 89135f6..8224bde 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -13,6 +13,14 @@
 #include clk.h
 #include clk-pll.h
 
+struct samsung_clk_pll {
+   struct clk_hw   hw;
+   void __iomem*lock_reg;
+   void __iomem*con_reg;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
 /*
  * PLL35xx Clock Type
  */
@@ -24,17 +32,10 @@
 #define PLL35XX_PDIV_SHIFT  (8)
 #define PLL35XX_SDIV_SHIFT  (0)
 
-struct samsung_clk_pll35xx {
-   struct clk_hw   hw;
-   const void __iomem  *con_reg;
-};
-
-#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
-
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
 {
-   struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, pll_con;
u64 fvco = parent_rate;
 
@@ -56,7 +57,7 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
 struct clk * __init samsung_clk_register_pll35xx(const char *name,
const char *pname, const void __iomem *con_reg)
 {
-   struct samsung_clk_pll35xx *pll;
+   struct samsung_clk_pll *pll;
struct clk *clk;
struct clk_init_data init;
 
@@ -100,17 +101,10 @@ struct clk * __init samsung_clk_register_pll35xx(const 
char *name,
 #define PLL36XX_PDIV_SHIFT (8)
 #define PLL36XX_SDIV_SHIFT (0)
 
-struct samsung_clk_pll36xx {
-   struct clk_hw   hw;
-   const void __iomem  *con_reg;
-};
-
-#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
-
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
 {
-   struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
u64 fvco = parent_rate;
 
@@ -135,7 +129,7 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
 struct clk * __init samsung_clk_register_pll36xx(const char *name,
const char *pname, const void __iomem *con_reg)
 {
-   struct samsung_clk_pll36xx *pll;
+   struct samsung_clk_pll *pll;
struct clk *clk;
struct clk_init_data init;
 
-- 
1.7.0.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


[PATCH v6 4/7] clk: samsung: Add set_rate() clk_ops for PLL35xx

2013-06-19 Thread Yadwinder Singh Brar
This patch add set_rate() and round_rate() for PLL35xx

Reviewed-by: Doug Anderson diand...@chromium.org
Reviewed-by: Tomasz Figa t.f...@samsung.com
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-pll.c |  105 -
 1 files changed, 104 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index b2088dd..e3e7f0c 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -24,16 +24,51 @@ struct samsung_clk_pll {
 
 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
 
+static const struct samsung_pll_rate_table *samsung_get_pll_settings(
+   struct samsung_clk_pll *pll, unsigned long rate)
+{
+   const struct samsung_pll_rate_table  *rate_table = pll-rate_table;
+   int i;
+
+   for (i = 0; i  pll-rate_count; i++) {
+   if (rate == rate_table[i].rate)
+   return rate_table[i];
+   }
+
+   return NULL;
+}
+
+static long samsung_pll_round_rate(struct clk_hw *hw,
+   unsigned long drate, unsigned long *prate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   const struct samsung_pll_rate_table *rate_table = pll-rate_table;
+   int i;
+
+   /* Assumming rate_table is in descending order */
+   for (i = 0; i  pll-rate_count; i++) {
+   if (drate = rate_table[i].rate)
+   return rate_table[i].rate;
+   }
+
+   /* return minimum supported value */
+   return rate_table[i - 1].rate;
+}
+
 /*
  * PLL35xx Clock Type
  */
+/* Maximum lock time can be 270 * PDIV cycles */
+#define PLL35XX_LOCK_FACTOR(270)
 
 #define PLL35XX_MDIV_MASK   (0x3FF)
 #define PLL35XX_PDIV_MASK   (0x3F)
 #define PLL35XX_SDIV_MASK   (0x7)
+#define PLL35XX_LOCK_STAT_MASK (0x1)
 #define PLL35XX_MDIV_SHIFT  (16)
 #define PLL35XX_PDIV_SHIFT  (8)
 #define PLL35XX_SDIV_SHIFT  (0)
+#define PLL35XX_LOCK_STAT_SHIFT(29)
 
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -53,8 +88,73 @@ static unsigned long samsung_pll35xx_recalc_rate(struct 
clk_hw *hw,
return (unsigned long)fvco;
 }
 
+static inline bool samsung_pll35xx_mp_change(
+   const struct samsung_pll_rate_table *rate, u32 pll_con)
+{
+   u32 old_mdiv, old_pdiv;
+
+   old_mdiv = (pll_con  PLL35XX_MDIV_SHIFT)  PLL35XX_MDIV_MASK;
+   old_pdiv = (pll_con  PLL35XX_PDIV_SHIFT)  PLL35XX_PDIV_MASK;
+
+   return (rate-mdiv != old_mdiv || rate-pdiv != old_pdiv);
+}
+
+static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long prate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   const struct samsung_pll_rate_table *rate;
+   u32 tmp;
+
+   /* Get required rate settings from table */
+   rate = samsung_get_pll_settings(pll, drate);
+   if (!rate) {
+   pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__,
+   drate, __clk_get_name(hw-clk));
+   return -EINVAL;
+   }
+
+   tmp = __raw_readl(pll-con_reg);
+
+   if (!(samsung_pll35xx_mp_change(rate, tmp))) {
+   /* If only s change, change just s value only*/
+   tmp = ~(PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT);
+   tmp |= rate-sdiv  PLL35XX_SDIV_SHIFT;
+   __raw_writel(tmp, pll-con_reg);
+
+   return 0;
+   }
+
+   /* Set PLL lock time. */
+   __raw_writel(rate-pdiv * PLL35XX_LOCK_FACTOR,
+   pll-lock_reg);
+
+   /* Change PLL PMS values */
+   tmp = ~((PLL35XX_MDIV_MASK  PLL35XX_MDIV_SHIFT) |
+   (PLL35XX_PDIV_MASK  PLL35XX_PDIV_SHIFT) |
+   (PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT));
+   tmp |= (rate-mdiv  PLL35XX_MDIV_SHIFT) |
+   (rate-pdiv  PLL35XX_PDIV_SHIFT) |
+   (rate-sdiv  PLL35XX_SDIV_SHIFT);
+   __raw_writel(tmp, pll-con_reg);
+
+   /* wait_lock_time */
+   do {
+   cpu_relax();
+   tmp = __raw_readl(pll-con_reg);
+   } while (!(tmp  (PLL35XX_LOCK_STAT_MASK
+PLL35XX_LOCK_STAT_SHIFT)));
+   return 0;
+}
+
 static const struct clk_ops samsung_pll35xx_clk_ops = {
.recalc_rate = samsung_pll35xx_recalc_rate,
+   .round_rate = samsung_pll_round_rate,
+   .set_rate = samsung_pll35xx_set_rate,
+};
+
+static const struct clk_ops samsung_pll35xx_clk_min_ops = {
+   .recalc_rate = samsung_pll35xx_recalc_rate,
 };
 
 /*
@@ -386,7 +486,10 @@ void __init samsung_clk_register_pll(struct 
samsung_pll_clock *clk_list,
/* clk_ops for 35xx and 2550 are similar */
case pll_35xx:
case pll_2550

[PATCH v6 2/7] clk: samsung: Define a common samsung_clk_register_pll()

2013-06-19 Thread Yadwinder Singh Brar
This patch defines a common samsung_clk_register_pll() and its migrating the
PLL35xx  PLL36xx to use it. Other samsung PLL can also be migrated to it.
It also adds exynos5250  exynos5420 PLLs to unique id list of clocks.
Since pll2550  pll35xx and pll2650  pll36xx have exactly same clk ops
implementation, added pll2550 and pll2650 also.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos4.c|   40 +++
 drivers/clk/samsung/clk-exynos5250.c |   60 +++-
 drivers/clk/samsung/clk-exynos5420.c |   86 +++---
 drivers/clk/samsung/clk-pll.c|  132 --
 drivers/clk/samsung/clk-pll.h|   11 ++-
 drivers/clk/samsung/clk.h|   48 
 6 files changed, 242 insertions(+), 135 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c 
b/drivers/clk/samsung/clk-exynos4.c
index addc738..ba25a1b 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -17,7 +17,6 @@
 #include linux/of_address.h
 
 #include clk.h
-#include clk-pll.h
 
 /* Exynos4 clock controller register offsets */
 #define SRC_LEFTBUS0x4200
@@ -97,12 +96,14 @@
 #define GATE_IP_PERIL  0xc950
 #define E4210_GATE_IP_PERIR0xc960
 #define GATE_BLOCK 0xc970
+#define E4X12_MPLL_LOCK0x10008
 #define E4X12_MPLL_CON00x10108
 #define SRC_DMC0x10200
 #define SRC_MASK_DMC   0x10300
 #define DIV_DMC0   0x10500
 #define DIV_DMC1   0x10504
 #define GATE_IP_DMC0x10900
+#define APLL_LOCK  0x14000
 #define APLL_CON0  0x14100
 #define E4210_MPLL_CON00x14108
 #define SRC_CPU0x14200
@@ -121,6 +122,12 @@ enum exynos4_soc {
EXYNOS4X12,
 };
 
+/* list of PLLs to be registered */
+enum exynos4_plls {
+   apll, mpll, epll, vpll,
+   nr_plls /* number of PLLs */
+};
+
 /*
  * Let each supported clock get a unique id. This id is used to lookup the 
clock
  * for device tree based platforms. The clocks are categorized into three
@@ -988,6 +995,17 @@ static __initdata struct of_device_id ext_clk_match[] = {
{},
 };
 
+struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
+   [apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
+   APLL_CON0, fout_apll),
+   [mpll] = PLL_A(pll_35xx, fout_mpll, fout_mpll, fin_pll,
+   E4X12_MPLL_LOCK, E4X12_MPLL_CON0, fout_mpll),
+   [epll] = PLL_A(pll_36xx, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
+   EPLL_CON0, fout_epll),
+   [vpll] = PLL_A(pll_36xx, fout_vpll, fout_vpll, fin_pll, VPLL_LOCK,
+   VPLL_CON0, fout_vpll),
+};
+
 /* register exynos4 clocks */
 void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc 
exynos4_soc, void __iomem *reg_base, unsigned long xom)
 {
@@ -1024,22 +1042,16 @@ void __init exynos4_clk_init(struct device_node *np, 
enum exynos4_soc exynos4_so
reg_base + EPLL_CON0, pll_4600);
vpll = samsung_clk_register_pll46xx(fout_vpll, mout_vpllsrc,
reg_base + VPLL_CON0, pll_4650c);
+
+   samsung_clk_add_lookup(apll, fout_apll);
+   samsung_clk_add_lookup(mpll, fout_mpll);
+   samsung_clk_add_lookup(epll, fout_epll);
+   samsung_clk_add_lookup(vpll, fout_vpll);
} else {
-   apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
-   reg_base + APLL_CON0);
-   mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
-   reg_base + E4X12_MPLL_CON0);
-   epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + EPLL_CON0);
-   vpll = samsung_clk_register_pll36xx(fout_vpll, fin_pll,
-   reg_base + VPLL_CON0);
+   samsung_clk_register_pll(exynos4_plls,
+   ARRAY_SIZE(exynos4_plls), reg_base);
}
 
-   samsung_clk_add_lookup(apll, fout_apll);
-   samsung_clk_add_lookup(mpll, fout_mpll);
-   samsung_clk_add_lookup(epll, fout_epll);
-   samsung_clk_add_lookup(vpll, fout_vpll);
-
samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
ARRAY_SIZE(exynos4_fixed_rate_clks));
samsung_clk_register_mux(exynos4_mux_clks,
diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 7c68850..dc6a700 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -17,11 +17,22 @@
 #include linux/of_address.h
 
 #include clk.h
-#include clk-pll.h
 
+#define APLL_LOCK  0x0
+#define APLL_CON0

[PATCH v6 5/7] clk: samsung: Add set_rate() clk_ops for PLL36xx

2013-06-19 Thread Yadwinder Singh Brar
From: Vikas Sajjan vikas.saj...@linaro.org

This patch adds set_rate and round_rate clk_ops for PLL36xx

Reviewed-by: Tomasz Figa t.f...@samsung.com
Reviewed-by: Doug Anderson diand...@chromium.org
Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
---
 drivers/clk/samsung/clk-pll.c |   79 -
 1 files changed, 78 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index e3e7f0c..2197004 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -160,6 +160,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
 /*
  * PLL36xx Clock Type
  */
+/* Maximum lock time can be 3000 * PDIV cycles */
+#define PLL36XX_LOCK_FACTOR(3000)
 
 #define PLL36XX_KDIV_MASK  (0x)
 #define PLL36XX_MDIV_MASK  (0x1FF)
@@ -168,6 +170,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
 #define PLL36XX_MDIV_SHIFT (16)
 #define PLL36XX_PDIV_SHIFT (8)
 #define PLL36XX_SDIV_SHIFT (0)
+#define PLL36XX_KDIV_SHIFT (0)
+#define PLL36XX_LOCK_STAT_SHIFT(29)
 
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -190,8 +194,78 @@ static unsigned long samsung_pll36xx_recalc_rate(struct 
clk_hw *hw,
return (unsigned long)fvco;
 }
 
+static inline bool samsung_pll36xx_mpk_change(
+   const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
+{
+   u32 old_mdiv, old_pdiv, old_kdiv;
+
+   old_mdiv = (pll_con0  PLL36XX_MDIV_SHIFT)  PLL36XX_MDIV_MASK;
+   old_pdiv = (pll_con0  PLL36XX_PDIV_SHIFT)  PLL36XX_PDIV_MASK;
+   old_kdiv = (pll_con1  PLL36XX_KDIV_SHIFT)  PLL36XX_KDIV_MASK;
+
+   return (rate-mdiv != old_mdiv || rate-pdiv != old_pdiv ||
+   rate-kdiv != old_kdiv);
+}
+
+static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long parent_rate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   u32 tmp, pll_con0, pll_con1;
+   const struct samsung_pll_rate_table *rate;
+
+   rate = samsung_get_pll_settings(pll, drate);
+   if (!rate) {
+   pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__,
+   drate, __clk_get_name(hw-clk));
+   return -EINVAL;
+   }
+
+   pll_con0 = __raw_readl(pll-con_reg);
+   pll_con1 = __raw_readl(pll-con_reg + 4);
+
+   if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
+   /* If only s change, change just s value only*/
+   pll_con0 = ~(PLL36XX_SDIV_MASK  PLL36XX_SDIV_SHIFT);
+   pll_con0 |= (rate-sdiv  PLL36XX_SDIV_SHIFT);
+   __raw_writel(pll_con0, pll-con_reg);
+
+   return 0;
+   }
+
+   /* Set PLL lock time. */
+   __raw_writel(rate-pdiv * PLL36XX_LOCK_FACTOR, pll-lock_reg);
+
+/* Change PLL PMS values */
+   pll_con0 = ~((PLL36XX_MDIV_MASK  PLL36XX_MDIV_SHIFT) |
+   (PLL36XX_PDIV_MASK  PLL36XX_PDIV_SHIFT) |
+   (PLL36XX_SDIV_MASK  PLL36XX_SDIV_SHIFT));
+   pll_con0 |= (rate-mdiv  PLL36XX_MDIV_SHIFT) |
+   (rate-pdiv  PLL36XX_PDIV_SHIFT) |
+   (rate-sdiv  PLL36XX_SDIV_SHIFT);
+   __raw_writel(pll_con0, pll-con_reg);
+
+   pll_con1 = ~(PLL36XX_KDIV_MASK  PLL36XX_KDIV_SHIFT);
+   pll_con1 |= rate-kdiv  PLL36XX_KDIV_SHIFT;
+   __raw_writel(pll_con1, pll-con_reg + 4);
+
+   /* wait_lock_time */
+   do {
+   cpu_relax();
+   tmp = __raw_readl(pll-con_reg);
+   } while (!(tmp  (1  PLL36XX_LOCK_STAT_SHIFT)));
+
+   return 0;
+}
+
 static const struct clk_ops samsung_pll36xx_clk_ops = {
.recalc_rate = samsung_pll36xx_recalc_rate,
+   .set_rate = samsung_pll36xx_set_rate,
+   .round_rate = samsung_pll_round_rate,
+};
+
+static const struct clk_ops samsung_pll36xx_clk_min_ops = {
+   .recalc_rate = samsung_pll36xx_recalc_rate,
 };
 
 /*
@@ -494,7 +568,10 @@ void __init samsung_clk_register_pll(struct 
samsung_pll_clock *clk_list,
/* clk_ops for 36xx and 2650 are similar */
case pll_36xx:
case pll_2650:
-   init.ops = samsung_pll36xx_clk_ops;
+   if (!pll-rate_table)
+   init.ops = samsung_pll36xx_clk_min_ops;
+   else
+   init.ops = samsung_pll36xx_clk_ops;
break;
default:
pr_warn(%s: Unknown pll type for pll clk %s\n,
-- 
1.7.0.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


[PATCH v6 6/7] clk: samsung: Reorder MUX registration for mout_vpllsrc

2013-06-19 Thread Yadwinder Singh Brar
From: Vikas Sajjan vikas.saj...@linaro.org

While trying to get rate of mout_vpllsrc MUX (parent) for registering the
fout_vpll (child), we found get rate was failing.

So this patch moves the mout_vpllsrc MUX out of the existing common list
and registers the mout_vpllsrc MUX before the PLL registrations.

Reviewed-by: Tomasz Figa t.f...@samsung.com
Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos5250.c |7 ++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 21f5491..6881810 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -228,6 +228,10 @@ struct samsung_fixed_factor_clock 
exynos5250_fixed_factor_clks[] __initdata = {
FFACTOR(none, fout_bplldiv2, fout_bpll, 1, 2, 0),
 };
 
+struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+   MUX(none, mout_vpllsrc, mout_vpllsrc_p, SRC_TOP2, 0, 1),
+};
+
 struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(none, mout_apll, mout_apll_p, SRC_CPU, 0, 1),
MUX(none, mout_cpu, mout_cpu_p, SRC_CPU, 16, 1),
@@ -235,7 +239,6 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = 
{
MUX(none, sclk_mpll, mout_mpll_p, SRC_CORE1, 8, 1),
MUX(none, mout_bpll_fout, mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
MUX(none, sclk_bpll, mout_bpll_p, SRC_CDREX, 0, 1),
-   MUX(none, mout_vpllsrc, mout_vpllsrc_p, SRC_TOP2, 0, 1),
MUX(none, sclk_vpll, mout_vpll_p, SRC_TOP2, 16, 1),
MUX(none, sclk_epll, mout_epll_p, SRC_TOP2, 12, 1),
MUX(none, sclk_cpll, mout_cpll_p, SRC_TOP2, 8, 1),
@@ -526,6 +529,8 @@ void __init exynos5250_clk_init(struct device_node *np)
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
+   samsung_clk_register_mux(exynos5250_pll_pmux_clks,
+   ARRAY_SIZE(exynos5250_pll_pmux_clks));
samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
reg_base);
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
-- 
1.7.0.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


[PATCH v6 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

2013-06-19 Thread Yadwinder Singh Brar
Adds the EPLL and VPLL freq table for exynos5250 SoC.

Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos5250.c |   42 -
 drivers/clk/samsung/clk.h|2 +
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 6881810..13e293e 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -493,6 +493,29 @@ static __initdata struct of_device_id ext_clk_match[] = {
{ },
 };
 
+static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = {
+   /* sorted in descending order */
+   /* PLL_36XX_RATE(rate, m, p, s, k) */
+   PLL_36XX_RATE(26600, 266, 3, 3, 0),
+   /* Not in UM, but need for eDP on snow */
+   PLL_36XX_RATE(7050, 94, 2, 4, 0),
+   { },
+};
+
+static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
+   /* sorted in descending order */
+   /* PLL_36XX_RATE(rate, m, p, s, k) */
+   PLL_36XX_RATE(19200, 64, 2, 2, 0),
+   PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
+   PLL_36XX_RATE(18000, 90, 3, 2, 0),
+   PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
+   PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
+   PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
+   PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
+   PLL_36XX_RATE(32768000, 131, 3, 5, 4719)
+   { },
+};
+
 struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
[apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
APLL_CON0, fout_apll, NULL),
@@ -506,14 +529,16 @@ struct __initdata samsung_pll_clock 
exynos5250_plls[nr_plls] = {
CPLL_CON0, NULL),
[epll] = PLL(pll_36xx, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
EPLL_CON0, NULL),
-   [vpll] = PLL(pll_36xx, fout_vpll, fout_vpll, fin_pll, VPLL_LOCK,
-   VPLL_CON0, NULL),
+   [vpll] = PLL(pll_36xx, fout_vpll, fout_vpll, mout_vpllsrc,
+   VPLL_LOCK, VPLL_CON0, NULL),
 };
 
 /* register exynox5250 clocks */
 void __init exynos5250_clk_init(struct device_node *np)
 {
void __iomem *reg_base;
+   struct clk *vpllsrc;
+   unsigned long fin_pll_rate, mout_vpllsrc_rate = 0;
 
if (np) {
reg_base = of_iomap(np, 0);
@@ -531,6 +556,19 @@ void __init exynos5250_clk_init(struct device_node *np)
ext_clk_match);
samsung_clk_register_mux(exynos5250_pll_pmux_clks,
ARRAY_SIZE(exynos5250_pll_pmux_clks));
+
+   fin_pll_rate = _get_rate(fin_pll);
+
+   if (fin_pll_rate == (24 * MHZ))
+   exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
+
+   vpllsrc = __clk_lookup(mout_vpllsrc);
+   if (vpllsrc)
+   mout_vpllsrc_rate = clk_get_rate(vpllsrc);
+
+   if (mout_vpllsrc_rate == (24 * MHZ))
+   exynos5250_plls[vpll].rate_table =  vpll_24mhz_tbl;
+
samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
reg_base);
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 3e6501c..378bf98 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -40,6 +40,8 @@ struct samsung_clock_alias {
.alias  = a,\
}
 
+#define MHZ (1000*1000)
+
 /**
  * struct samsung_fixed_rate_clock: information about fixed-rate clock
  * @id: platform specific id of the clock.
-- 
1.7.0.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


Re: [PATCH v6 2/7] clk: samsung: Define a common samsung_clk_register_pll()

2013-06-19 Thread Yadwinder Singh Brar
On Wed, Jun 19, 2013 at 10:24 PM, Tomasz Figa tomasz.f...@gmail.com wrote:
 Hi Yadwinder,

 Generally looks really good, but some comments inline.

 On Monday 10 of June 2013 18:54:14 Yadwinder Singh Brar wrote:
 This patch defines a common samsung_clk_register_pll() and its migrating
 the PLL35xx  PLL36xx to use it. Other samsung PLL can also be migrated
 to it. It also adds exynos5250  exynos5420 PLLs to unique id list of
 clocks. Since pll2550  pll35xx and pll2650  pll36xx have exactly same
 clk ops implementation, added pll2550 and pll2650 also.

 +void __init samsung_clk_register_pll(struct samsung_pll_clock
 *clk_list, +  unsigned int nr_pll, void __iomem
 *base)
 +{
 + struct samsung_clk_pll *pll;
 + struct clk *clk;
 + struct clk_init_data init;
 + struct samsung_pll_clock *list = clk_list;
 + int cnt;
 +
 + for (cnt = 0; cnt  nr_pll; cnt++, list++) {

 I'd suggest moving contents of this loop to a function like following?

 static int __init _samsung_clk_register_pll(struct samsung_pll_clock *pll,
 void __iomem *base)

 This will make the code less indented and so more readable.


Yes, will do it.

 + pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 + if (!pll) {
 + pr_err(%s: could not allocate pll clk %s\n,
 + __func__, list-name);
 + continue;
 + }
 +
 + init.name = list-name;
 + init.flags = list-flags;
 + init.parent_names = list-parent_name;
 + init.num_parents = 1;
 +
 + switch (list-type) {
 + /* clk_ops for 35xx and 2550 are similar */
 + case pll_35xx:
 + case pll_2550:
 + init.ops = samsung_pll35xx_clk_ops;
 + break;
 + /* clk_ops for 36xx and 2650 are similar */
 + case pll_36xx:
 + case pll_2650:
 + init.ops = samsung_pll36xx_clk_ops;
 + break;
 + default:
 + pr_warn(%s: Unknown pll type for pll clk %s\n,
 + __func__, list-name);
 + }
 +
 + pll-hw.init = init;
 + pll-type = list-type;
 + pll-lock_reg = base + list-lock_offset;
 + pll-con_reg = base + list-con_offset;
 +
 + clk = clk_register(NULL, pll-hw);
 + if (IS_ERR(clk)) {
 + pr_err(%s: failed to register pll clock %s\n,
 + __func__, list-name);
 + kfree(pll);
 + continue;
 + }
 +
 + samsung_clk_add_lookup(clk, list-id);
 +
 + if (list-alias)
 + if (clk_register_clkdev(clk, list-alias,
 + list-dev_name))

 What about

 if (!list-alias)
 return;

 ret = clk_register_clkdev(clk, list-alias, list-
dev_name);
 if (ret)
 pr_err(%s: failed to register lookup for %s,
 __func__, list-name);


its ok, but to me it looks more clear and precise inside if(){ },
as its length and indentation is not much deep.
If you really insist we can do it ?

 + pr_err(%s: failed to register lookup for
 %s,
 + __func__, list-name);
 + }
 +}

 +struct samsung_pll_clock {
 + unsigned intid;
 + const char  *dev_name;
 + const char  *name;
 + const char  *parent_name;
 + unsigned long   flags;
 + const int   con_offset;
 + const int   lock_offset;

 I don't see any point of having all those const qualifiers of non-
 pointers. This makes the struct useless for creating and initializing at
 runtime.


OK, will remove it.

 + enumsamsung_pll_type type;

 IMHO the enum keyword shouldn't be separated from enum name like this.


Any specific reason?  Just to keep indentation same for all members, I
used tabs :).

 Otherwise the patch looks fine. Maybe it's a bit too big - things could be
 done a bit more gradually, like:
 1) first add required structs and functions,
 2) then move existing clock drivers to use the new API, possibly one patch
 per driver,
 3) remove the old API.

 This would make the whole change easier to review and, in case of any
 regressions, easier to track down the problem.


OK, I will split it.

Thanks,
Yadwinder
--
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


[PATCH v5 2/7] clk: samsung: Define a common samsung_clk_register_pll().

2013-06-17 Thread Yadwinder Singh Brar
This patch defines a common samsung_clk_register_pll() and its migrating the
PLL35xx  PLL36xx to use it. Other samsung PLL can also be migrated to it.
This patch also adds exynos5250 PLLs in unique id list of exynos5250 clocks.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos4.c|   40 +++
 drivers/clk/samsung/clk-exynos5250.c |   60 +++-
 drivers/clk/samsung/clk-pll.c|  128 +++--
 drivers/clk/samsung/clk-pll.h|9 ++-
 drivers/clk/samsung/clk.h|   48 +
 5 files changed, 178 insertions(+), 107 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c 
b/drivers/clk/samsung/clk-exynos4.c
index addc738..ba25a1b 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -17,7 +17,6 @@
 #include linux/of_address.h
 
 #include clk.h
-#include clk-pll.h
 
 /* Exynos4 clock controller register offsets */
 #define SRC_LEFTBUS0x4200
@@ -97,12 +96,14 @@
 #define GATE_IP_PERIL  0xc950
 #define E4210_GATE_IP_PERIR0xc960
 #define GATE_BLOCK 0xc970
+#define E4X12_MPLL_LOCK0x10008
 #define E4X12_MPLL_CON00x10108
 #define SRC_DMC0x10200
 #define SRC_MASK_DMC   0x10300
 #define DIV_DMC0   0x10500
 #define DIV_DMC1   0x10504
 #define GATE_IP_DMC0x10900
+#define APLL_LOCK  0x14000
 #define APLL_CON0  0x14100
 #define E4210_MPLL_CON00x14108
 #define SRC_CPU0x14200
@@ -121,6 +122,12 @@ enum exynos4_soc {
EXYNOS4X12,
 };
 
+/* list of PLLs to be registered */
+enum exynos4_plls {
+   apll, mpll, epll, vpll,
+   nr_plls /* number of PLLs */
+};
+
 /*
  * Let each supported clock get a unique id. This id is used to lookup the 
clock
  * for device tree based platforms. The clocks are categorized into three
@@ -988,6 +995,17 @@ static __initdata struct of_device_id ext_clk_match[] = {
{},
 };
 
+struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
+   [apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
+   APLL_CON0, fout_apll),
+   [mpll] = PLL_A(pll_35xx, fout_mpll, fout_mpll, fin_pll,
+   E4X12_MPLL_LOCK, E4X12_MPLL_CON0, fout_mpll),
+   [epll] = PLL_A(pll_36xx, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
+   EPLL_CON0, fout_epll),
+   [vpll] = PLL_A(pll_36xx, fout_vpll, fout_vpll, fin_pll, VPLL_LOCK,
+   VPLL_CON0, fout_vpll),
+};
+
 /* register exynos4 clocks */
 void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc 
exynos4_soc, void __iomem *reg_base, unsigned long xom)
 {
@@ -1024,22 +1042,16 @@ void __init exynos4_clk_init(struct device_node *np, 
enum exynos4_soc exynos4_so
reg_base + EPLL_CON0, pll_4600);
vpll = samsung_clk_register_pll46xx(fout_vpll, mout_vpllsrc,
reg_base + VPLL_CON0, pll_4650c);
+
+   samsung_clk_add_lookup(apll, fout_apll);
+   samsung_clk_add_lookup(mpll, fout_mpll);
+   samsung_clk_add_lookup(epll, fout_epll);
+   samsung_clk_add_lookup(vpll, fout_vpll);
} else {
-   apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
-   reg_base + APLL_CON0);
-   mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
-   reg_base + E4X12_MPLL_CON0);
-   epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + EPLL_CON0);
-   vpll = samsung_clk_register_pll36xx(fout_vpll, fin_pll,
-   reg_base + VPLL_CON0);
+   samsung_clk_register_pll(exynos4_plls,
+   ARRAY_SIZE(exynos4_plls), reg_base);
}
 
-   samsung_clk_add_lookup(apll, fout_apll);
-   samsung_clk_add_lookup(mpll, fout_mpll);
-   samsung_clk_add_lookup(epll, fout_epll);
-   samsung_clk_add_lookup(vpll, fout_vpll);
-
samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
ARRAY_SIZE(exynos4_fixed_rate_clks));
samsung_clk_register_mux(exynos4_mux_clks,
diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 5c97e75..0418cc1 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -17,11 +17,22 @@
 #include linux/of_address.h
 
 #include clk.h
-#include clk-pll.h
 
+#define APLL_LOCK  0x0
+#define APLL_CON0  0x100
 #define SRC_CPU0x200
 #define DIV_CPU0   0x500
+#define MPLL_LOCK  0x4000
+#define MPLL_CON0  0x4100
 #define

[PATCH v5 3/7] clk: samsung: Add support to register rate_table for PLL3xxx

2013-06-17 Thread Yadwinder Singh Brar
This patch defines a common rate_table which will contain recommended p, m, s,
k values for supported rates that needs to be changed for changing
corresponding PLL's rate.

Reviewed-by: Doug Anderson diand...@chromium.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos4.c|8 
 drivers/clk/samsung/clk-exynos5250.c |   14 +++---
 drivers/clk/samsung/clk-pll.c|   22 --
 drivers/clk/samsung/clk-pll.h|   27 +++
 drivers/clk/samsung/clk.h|   14 +-
 5 files changed, 67 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c 
b/drivers/clk/samsung/clk-exynos4.c
index ba25a1b..ceee66c 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -997,13 +997,13 @@ static __initdata struct of_device_id ext_clk_match[] = {
 
 struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
[apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
-   APLL_CON0, fout_apll),
+   APLL_CON0, fout_apll, NULL),
[mpll] = PLL_A(pll_35xx, fout_mpll, fout_mpll, fin_pll,
-   E4X12_MPLL_LOCK, E4X12_MPLL_CON0, fout_mpll),
+   E4X12_MPLL_LOCK, E4X12_MPLL_CON0, fout_mpll, NULL),
[epll] = PLL_A(pll_36xx, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
-   EPLL_CON0, fout_epll),
+   EPLL_CON0, fout_epll, NULL),
[vpll] = PLL_A(pll_36xx, fout_vpll, fout_vpll, fin_pll, VPLL_LOCK,
-   VPLL_CON0, fout_vpll),
+   VPLL_CON0, fout_vpll, NULL),
 };
 
 /* register exynos4 clocks */
diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 0418cc1..a025269 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -491,19 +491,19 @@ static __initdata struct of_device_id ext_clk_match[] = {
 
 struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
[apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
-   APLL_CON0, fout_apll),
+   APLL_CON0, fout_apll, NULL),
[mpll] = PLL_A(pll_35xx, fout_mpll, fout_mpll, fin_pll, MPLL_LOCK,
-   MPLL_CON0, fout_mpll),
+   MPLL_CON0, fout_mpll, NULL),
[bpll] = PLL(pll_35xx, fout_bpll, fout_bpll, fin_pll, BPLL_LOCK,
-   BPLL_CON0),
+   BPLL_CON0, NULL),
[gpll] = PLL(pll_35xx, fout_gpll, fout_gpll, fin_pll, GPLL_LOCK,
-   GPLL_CON0),
+   GPLL_CON0, NULL),
[cpll] = PLL(pll_35xx, fout_cpll, fout_cpll, fin_pll, CPLL_LOCK,
-   CPLL_CON0),
+   CPLL_CON0, NULL),
[epll] = PLL(pll_36xx, fout_epll, fout_epll, fin_pll, EPLL_LOCK,
-   EPLL_CON0),
+   EPLL_CON0, NULL),
[vpll] = PLL(pll_36xx, fout_vpll, fout_vpll, fin_pll, VPLL_LOCK,
-   VPLL_CON0),
+   VPLL_CON0, NULL),
 };
 
 /* register exynox5250 clocks */
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index b83900c..f753c5e 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -18,6 +18,8 @@ struct samsung_clk_pll {
void __iomem*lock_reg;
void __iomem*con_reg;
enum samsung_pll_type   type;
+   unsigned intrate_count;
+   const struct samsung_pll_rate_table *rate_table;
 };
 
 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
@@ -350,7 +352,7 @@ void __init samsung_clk_register_pll(struct 
samsung_pll_clock *clk_list,
struct clk *clk;
struct clk_init_data init;
struct samsung_pll_clock *list = clk_list;
-   int cnt;
+   int cnt, len;
 
for (cnt = 0; cnt  nr_pll; cnt++, list++) {
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
@@ -365,6 +367,21 @@ void __init samsung_clk_register_pll(struct 
samsung_pll_clock *clk_list,
init.parent_names = list-parent_name;
init.num_parents = 1;
 
+   if (list-rate_table) {
+   /* find count of rates in rate_table */
+   for (len = 0; list-rate_table[len].rate != 0; )
+   len++;
+
+   pll-rate_count = len;
+   pll-rate_table = kmemdup(list-rate_table,
+   list-rate_count *
+   sizeof(struct samsung_pll_rate_table),
+   GFP_KERNEL);
+   WARN(!pll-rate_table,
+   %s: could not allocate rate table for %s\n,
+   __func__, list-name);
+   }
+
switch (list-type) {
case pll_35xx:
init.ops = samsung_pll35xx_clk_ops

[PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

2013-06-17 Thread Yadwinder Singh Brar
Adds the EPLL and VPLL freq table for exynos5250 SoC.

Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos5250.c |   38 ++
 drivers/clk/samsung/clk.h|2 +
 2 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 09da356..d2743f9 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -492,6 +492,29 @@ static __initdata struct of_device_id ext_clk_match[] = {
{ },
 };
 
+static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = {
+   /* sorted in descending order */
+   /* PLL_36XX_RATE(rate, m, p, s, k) */
+   PLL_36XX_RATE(26600, 266, 3, 3, 0),
+   /* Not in UM, but need for eDP on snow */
+   PLL_36XX_RATE(7050, 94, 2, 4, 0),
+   { },
+};
+
+static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
+   /* sorted in descending order */
+   /* PLL_36XX_RATE(rate, m, p, s, k) */
+   PLL_36XX_RATE(19200, 48, 3, 1, 0),
+   PLL_36XX_RATE(180633600, 45, 3, 1, 10381),
+   PLL_36XX_RATE(18000, 45, 3, 1, 0),
+   PLL_36XX_RATE(73728000, 73, 3, 3, 47710),
+   PLL_36XX_RATE(67737600, 90, 4, 3, 20762),
+   PLL_36XX_RATE(49152000, 49, 3, 3, 9962),
+   PLL_36XX_RATE(45158400, 45, 3, 3, 10381),
+   PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
+   { },
+};
+
 struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
[apll] = PLL_A(pll_35xx, fout_apll, fout_apll, fin_pll, APLL_LOCK,
APLL_CON0, fout_apll, NULL),
@@ -513,6 +536,8 @@ struct __initdata samsung_pll_clock 
exynos5250_plls[nr_plls] = {
 void __init exynos5250_clk_init(struct device_node *np)
 {
void __iomem *reg_base;
+   struct clk *vpllsrc;
+   unsigned long fin_pll_rate, mout_vpllsrc_rate = 0;
 
if (np) {
reg_base = of_iomap(np, 0);
@@ -530,6 +555,19 @@ void __init exynos5250_clk_init(struct device_node *np)
ext_clk_match);
samsung_clk_register_mux(exynos5250_pll_pmux_clks,
ARRAY_SIZE(exynos5250_pll_pmux_clks));
+
+   fin_pll_rate = _get_rate(fin_pll);
+
+   if (fin_pll_rate == (24 * MHZ))
+   exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
+
+   vpllsrc = __clk_lookup(mout_vpllsrc);
+   if (vpllsrc)
+   mout_vpllsrc_rate = clk_get_rate(vpllsrc);
+
+   if (mout_vpllsrc_rate == (24 * MHZ))
+   exynos5250_plls[vpll].rate_table =  vpll_24mhz_tbl;
+
samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
reg_base);
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 3e6501c..378bf98 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -40,6 +40,8 @@ struct samsung_clock_alias {
.alias  = a,\
}
 
+#define MHZ (1000*1000)
+
 /**
  * struct samsung_fixed_rate_clock: information about fixed-rate clock
  * @id: platform specific id of the clock.
-- 
1.7.0.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


[PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct.

2013-06-17 Thread Yadwinder Singh Brar
This patch unifies clk strutures used for PLL35xx  PLL36xx and
adding an extra member lock_reg, so that common code can be factored out.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-pll.c |   30 --
 1 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 89135f6..8224bde 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -13,6 +13,14 @@
 #include clk.h
 #include clk-pll.h
 
+struct samsung_clk_pll {
+   struct clk_hw   hw;
+   void __iomem*lock_reg;
+   void __iomem*con_reg;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
 /*
  * PLL35xx Clock Type
  */
@@ -24,17 +32,10 @@
 #define PLL35XX_PDIV_SHIFT  (8)
 #define PLL35XX_SDIV_SHIFT  (0)
 
-struct samsung_clk_pll35xx {
-   struct clk_hw   hw;
-   const void __iomem  *con_reg;
-};
-
-#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
-
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
 {
-   struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, pll_con;
u64 fvco = parent_rate;
 
@@ -56,7 +57,7 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
 struct clk * __init samsung_clk_register_pll35xx(const char *name,
const char *pname, const void __iomem *con_reg)
 {
-   struct samsung_clk_pll35xx *pll;
+   struct samsung_clk_pll *pll;
struct clk *clk;
struct clk_init_data init;
 
@@ -100,17 +101,10 @@ struct clk * __init samsung_clk_register_pll35xx(const 
char *name,
 #define PLL36XX_PDIV_SHIFT (8)
 #define PLL36XX_SDIV_SHIFT (0)
 
-struct samsung_clk_pll36xx {
-   struct clk_hw   hw;
-   const void __iomem  *con_reg;
-};
-
-#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
-
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
 {
-   struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
u64 fvco = parent_rate;
 
@@ -135,7 +129,7 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
 struct clk * __init samsung_clk_register_pll36xx(const char *name,
const char *pname, const void __iomem *con_reg)
 {
-   struct samsung_clk_pll36xx *pll;
+   struct samsung_clk_pll *pll;
struct clk *clk;
struct clk_init_data init;
 
-- 
1.7.0.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


[PATCH v5 5/7] clk: samsung: Add set_rate() clk_ops for PLL36xx

2013-06-17 Thread Yadwinder Singh Brar
From: Vikas Sajjan vikas.saj...@linaro.org

This patch adds set_rate and round_rate clk_ops for PLL36xx

Reviewed-by: Tomasz Figa t.f...@samsung.com
Reviewed-by: Doug Anderson diand...@chromium.org
Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
---
 drivers/clk/samsung/clk-pll.c |   78 -
 1 files changed, 77 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index df419aa..2adf761 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -159,6 +159,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
 /*
  * PLL36xx Clock Type
  */
+/* Maximum lock time can be 3000 * PDIV cycles */
+#define PLL36XX_LOCK_FACTOR(3000)
 
 #define PLL36XX_KDIV_MASK  (0x)
 #define PLL36XX_MDIV_MASK  (0x1FF)
@@ -167,6 +169,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
 #define PLL36XX_MDIV_SHIFT (16)
 #define PLL36XX_PDIV_SHIFT (8)
 #define PLL36XX_SDIV_SHIFT (0)
+#define PLL36XX_KDIV_SHIFT (0)
+#define PLL36XX_LOCK_STAT_SHIFT(29)
 
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -189,8 +193,77 @@ static unsigned long samsung_pll36xx_recalc_rate(struct 
clk_hw *hw,
return (unsigned long)fvco;
 }
 
+static inline bool samsung_pll36xx_mpk_change(
+   const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
+{
+   u32 old_mdiv, old_pdiv, old_kdiv;
+
+   old_mdiv = (pll_con0  PLL36XX_MDIV_SHIFT)  PLL36XX_MDIV_MASK;
+   old_pdiv = (pll_con0  PLL36XX_PDIV_SHIFT)  PLL36XX_PDIV_MASK;
+   old_kdiv = (pll_con1  PLL36XX_KDIV_SHIFT)  PLL36XX_KDIV_MASK;
+
+   return (rate-mdiv != old_mdiv || rate-pdiv != old_pdiv ||
+   rate-kdiv != old_kdiv);
+}
+
+static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long parent_rate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   u32 tmp, pll_con0, pll_con1;
+   const struct samsung_pll_rate_table *rate;
+
+   rate = samsung_get_pll_settings(pll, drate);
+   if (!rate) {
+   pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__,
+   drate, __clk_get_name(hw-clk));
+   return -EINVAL;
+   }
+
+   pll_con0 = __raw_readl(pll-con_reg);
+   pll_con1 = __raw_readl(pll-con_reg + 4);
+
+   if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
+   /* If only s change, change just s value only*/
+   pll_con0 = ~(PLL36XX_SDIV_MASK  PLL36XX_SDIV_SHIFT);
+   pll_con0 |= (rate-sdiv  PLL36XX_SDIV_SHIFT);
+   __raw_writel(pll_con0, pll-con_reg);
+   return 0;
+   }
+
+   /* Set PLL lock time. */
+   __raw_writel(rate-pdiv * PLL36XX_LOCK_FACTOR, pll-lock_reg);
+
+/* Change PLL PMS values */
+   pll_con0 = ~((PLL36XX_MDIV_MASK  PLL36XX_MDIV_SHIFT) |
+   (PLL36XX_PDIV_MASK  PLL36XX_PDIV_SHIFT) |
+   (PLL36XX_SDIV_MASK  PLL36XX_SDIV_SHIFT));
+   pll_con0 |= (rate-mdiv  PLL36XX_MDIV_SHIFT) |
+   (rate-pdiv  PLL36XX_PDIV_SHIFT) |
+   (rate-sdiv  PLL36XX_SDIV_SHIFT);
+   __raw_writel(pll_con0, pll-con_reg);
+
+   pll_con1 = ~(PLL36XX_KDIV_MASK  PLL36XX_KDIV_SHIFT);
+   pll_con1 |= rate-kdiv  PLL36XX_KDIV_SHIFT;
+   __raw_writel(pll_con1, pll-con_reg + 4);
+
+   /* wait_lock_time */
+   do {
+   cpu_relax();
+   tmp = __raw_readl(pll-con_reg);
+   } while (!(tmp  (1  PLL36XX_LOCK_STAT_SHIFT)));
+
+   return 0;
+}
+
 static const struct clk_ops samsung_pll36xx_clk_ops = {
.recalc_rate = samsung_pll36xx_recalc_rate,
+   .set_rate = samsung_pll36xx_set_rate,
+   .round_rate = samsung_pll_round_rate,
+};
+
+static const struct clk_ops samsung_pll36xx_clk_min_ops = {
+   .recalc_rate = samsung_pll36xx_recalc_rate,
 };
 
 /*
@@ -489,7 +562,10 @@ void __init samsung_clk_register_pll(struct 
samsung_pll_clock *clk_list,
init.ops = samsung_pll35xx_clk_ops;
break;
case pll_36xx:
-   init.ops = samsung_pll36xx_clk_ops;
+   if (!pll-rate_table)
+   init.ops = samsung_pll36xx_clk_min_ops;
+   else
+   init.ops = samsung_pll36xx_clk_ops;
break;
default:
pr_warn(%s: Unknown pll type for pll clk %s\n,
-- 
1.7.0.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


[PATCH v5 4/7] clk: samsung: Add set_rate() clk_ops for PLL35xx

2013-06-17 Thread Yadwinder Singh Brar
This patch add set_rate() and round_rate() for PLL35xx

Reviewed-by: Doug Anderson diand...@chromium.org
Reviewed-by: Tomasz Figa t.f...@samsung.com
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-pll.c |  104 -
 1 files changed, 103 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index f753c5e..df419aa 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -24,16 +24,51 @@ struct samsung_clk_pll {
 
 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
 
+static const struct samsung_pll_rate_table *samsung_get_pll_settings(
+   struct samsung_clk_pll *pll, unsigned long rate)
+{
+   const struct samsung_pll_rate_table  *rate_table = pll-rate_table;
+   int i;
+
+   for (i = 0; i  pll-rate_count; i++) {
+   if (rate == rate_table[i].rate)
+   return rate_table[i];
+   }
+
+   return NULL;
+}
+
+static long samsung_pll_round_rate(struct clk_hw *hw,
+   unsigned long drate, unsigned long *prate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   const struct samsung_pll_rate_table *rate_table = pll-rate_table;
+   int i;
+
+   /* Assumming rate_table is in descending order */
+   for (i = 0; i  pll-rate_count; i++) {
+   if (drate = rate_table[i].rate)
+   return rate_table[i].rate;
+   }
+
+   /* return minimum supported value */
+   return rate_table[i - 1].rate;
+}
+
 /*
  * PLL35xx Clock Type
  */
+/* Maximum lock time can be 270 * PDIV cycles */
+#define PLL35XX_LOCK_FACTOR(270)
 
 #define PLL35XX_MDIV_MASK   (0x3FF)
 #define PLL35XX_PDIV_MASK   (0x3F)
 #define PLL35XX_SDIV_MASK   (0x7)
+#define PLL35XX_LOCK_STAT_MASK (0x1)
 #define PLL35XX_MDIV_SHIFT  (16)
 #define PLL35XX_PDIV_SHIFT  (8)
 #define PLL35XX_SDIV_SHIFT  (0)
+#define PLL35XX_LOCK_STAT_SHIFT(29)
 
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -53,8 +88,72 @@ static unsigned long samsung_pll35xx_recalc_rate(struct 
clk_hw *hw,
return (unsigned long)fvco;
 }
 
+static inline bool samsung_pll35xx_mp_change(
+   const struct samsung_pll_rate_table *rate, u32 pll_con)
+{
+   u32 old_mdiv, old_pdiv;
+
+   old_mdiv = (pll_con  PLL35XX_MDIV_SHIFT)  PLL35XX_MDIV_MASK;
+   old_pdiv = (pll_con  PLL35XX_PDIV_SHIFT)  PLL35XX_PDIV_MASK;
+
+   return (rate-mdiv != old_mdiv || rate-pdiv != old_pdiv);
+}
+
+static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long prate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   const struct samsung_pll_rate_table *rate;
+   u32 tmp;
+
+   /* Get required rate settings from table */
+   rate = samsung_get_pll_settings(pll, drate);
+   if (!rate) {
+   pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__,
+   drate, __clk_get_name(hw-clk));
+   return -EINVAL;
+   }
+
+   tmp = __raw_readl(pll-con_reg);
+
+   if (!(samsung_pll35xx_mp_change(rate, tmp))) {
+   /* If only s change, change just s value only*/
+   tmp = ~(PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT);
+   tmp |= rate-sdiv  PLL35XX_SDIV_SHIFT;
+   __raw_writel(tmp, pll-con_reg);
+   return 0;
+   }
+
+   /* Set PLL lock time. */
+   __raw_writel(rate-pdiv * PLL35XX_LOCK_FACTOR,
+   pll-lock_reg);
+
+   /* Change PLL PMS values */
+   tmp = ~((PLL35XX_MDIV_MASK  PLL35XX_MDIV_SHIFT) |
+   (PLL35XX_PDIV_MASK  PLL35XX_PDIV_SHIFT) |
+   (PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT));
+   tmp |= (rate-mdiv  PLL35XX_MDIV_SHIFT) |
+   (rate-pdiv  PLL35XX_PDIV_SHIFT) |
+   (rate-sdiv  PLL35XX_SDIV_SHIFT);
+   __raw_writel(tmp, pll-con_reg);
+
+   /* wait_lock_time */
+   do {
+   cpu_relax();
+   tmp = __raw_readl(pll-con_reg);
+   } while (!(tmp  (PLL35XX_LOCK_STAT_MASK
+PLL35XX_LOCK_STAT_SHIFT)));
+   return 0;
+}
+
 static const struct clk_ops samsung_pll35xx_clk_ops = {
.recalc_rate = samsung_pll35xx_recalc_rate,
+   .round_rate = samsung_pll_round_rate,
+   .set_rate = samsung_pll35xx_set_rate,
+};
+
+static const struct clk_ops samsung_pll35xx_clk_min_ops = {
+   .recalc_rate = samsung_pll35xx_recalc_rate,
 };
 
 /*
@@ -384,7 +483,10 @@ void __init samsung_clk_register_pll(struct 
samsung_pll_clock *clk_list,
 
switch (list-type) {
case pll_35xx:
-   init.ops = samsung_pll35xx_clk_ops

[PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs

2013-06-17 Thread Yadwinder Singh Brar
This patch series does the following:

 1) Unifies the clk strutures  and registration function used for PLL35xx 
PLL36xx, to factor out possible common code.

 2) Defines a common rate_table which will contain recommended p, m, s and k
values for supported rates that needs to be changed for changing
corresponding PLL's rate

 3) Adds set_rate() and round_rate() clk_ops for PLL35xx and PLL36xx

changes since v4:
- Defined common samsung samsung_clk_register_pll() to register a list
of PLL and used a struct samsung_pll_clock for passing intialisation
data instead of passing as arguments. Now passing LOCK as well as CON0
offset as intialisation data.
- Calculated length of rate table while registering PLL instead of
getting it as intialisation data.

changes since v3:
- Used __clk_lookup() instead of adding alias for mout_vpllsrc
- Added check for changing only M value in samsung_pll36xx_set_rate()
- Modified samsung_pll35xx_mp_change()  samsung_pll35xx_set_rate()
to improve readabilty.
- Made the input rate_table as __init_data which is to be provided while
registering PLL and made a copy of that table while registering, so
that if multiple tables are their, they can be freed after getting the
P, M, S, K setting values from required one.

changes since v2:
- Added new patch to reorder the MUX registration for mout_vpllsrc MUX
before the PLL registrations. And to add the alias for the mout_vpllsrc 
MUX.
- Added a check to confirm parent rate while registrating the PLL
rate tables.

changes since v1:
- removed sorting and bsearch
- modified the definition of struct samsung_pll_rate_table
- added generic round_rate()
- rectified the ops assignment for rate table passed as NULL
  during PLL registration

Is rebased on branch kgene's for-next
https://git.kernel.org/cgit/linux/kernel/git/kgene/linux-samsung.git/log/?h=for-next

Vikas Sajjan (2):
  clk: samsung: Add set_rate() clk_ops for PLL36xx
  clk: samsung: Reorder MUX registration for mout_vpllsrc

Yadwinder Singh Brar (5):
  clk: samsung: Introduce a common samsung_clk_pll struct.
  clk: samsung: Define a common samsung_clk_register_pll().
  clk: samsung: Add support to register rate_table for PLL3xxx
  clk: samsung: Add set_rate() clk_ops for PLL35xx
  clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

 drivers/clk/samsung/clk-exynos4.c|   40 +++--
 drivers/clk/samsung/clk-exynos5250.c |  101 +--
 drivers/clk/samsung/clk-pll.c|  330 ++
 drivers/clk/samsung/clk-pll.h|   36 -
 drivers/clk/samsung/clk.h|   54 ++
 5 files changed, 449 insertions(+), 112 deletions(-)

--
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


[PATCH v5 6/7] clk: samsung: Reorder MUX registration for mout_vpllsrc

2013-06-17 Thread Yadwinder Singh Brar
From: Vikas Sajjan vikas.saj...@linaro.org

While trying to get rate of mout_vpllsrc MUX (parent) for registering the
fout_vpll (child), we found get rate was failing.

So this patch moves the mout_vpllsrc MUX out of the existing common list
and registers the mout_vpllsrc MUX before the PLL registrations.

Reviewed-by: Tomasz Figa t.f...@samsung.com
Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos5250.c |7 ++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index a025269..09da356 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -227,6 +227,10 @@ struct samsung_fixed_factor_clock 
exynos5250_fixed_factor_clks[] __initdata = {
FFACTOR(none, fout_bplldiv2, fout_bpll, 1, 2, 0),
 };
 
+struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+   MUX(none, mout_vpllsrc, mout_vpllsrc_p, SRC_TOP2, 0, 1),
+};
+
 struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(none, mout_apll, mout_apll_p, SRC_CPU, 0, 1),
MUX(none, mout_cpu, mout_cpu_p, SRC_CPU, 16, 1),
@@ -234,7 +238,6 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = 
{
MUX(none, sclk_mpll, mout_mpll_p, SRC_CORE1, 8, 1),
MUX(none, mout_bpll_fout, mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
MUX(none, sclk_bpll, mout_bpll_p, SRC_CDREX, 0, 1),
-   MUX(none, mout_vpllsrc, mout_vpllsrc_p, SRC_TOP2, 0, 1),
MUX(none, sclk_vpll, mout_vpll_p, SRC_TOP2, 16, 1),
MUX(none, sclk_epll, mout_epll_p, SRC_TOP2, 12, 1),
MUX(none, sclk_cpll, mout_cpll_p, SRC_TOP2, 8, 1),
@@ -525,6 +528,8 @@ void __init exynos5250_clk_init(struct device_node *np)
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
+   samsung_clk_register_mux(exynos5250_pll_pmux_clks,
+   ARRAY_SIZE(exynos5250_pll_pmux_clks));
samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
reg_base);
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
-- 
1.7.0.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


Re: [PATCH v4 1/6] clk: samsung: Use clk-base instead of directly using clk-con0 for PLL3xxx

2013-06-13 Thread Yadwinder Singh Brar
On Thu, Jun 13, 2013 at 3:32 AM, Andrew Bresticker
abres...@chromium.org wrote:
 Doug,

 Hmm, if done properly, it could simplify PLL registration in SoC clock
 initialization code a lot.

 I'm not sure if this is really the best solution (feel free to suggest
 anything better), but we could put PLLs in an array, like other clocks,
 e.g.

 ... exynos4210_pll_clks[] = {
 CLK_PLL45XX(...),
 CLK_PLL45XX(...),
 CLK_PLL46XX(...),
 CLK_PLL46XX(...),
 };

 and then just call a helper like

 samsung_clk_register_pll(exynos4210_pll_clks,
 ARRAY_SIZE(exynos4210_pll_clks));

 Something like that looks like what I was thinking.  I'd have to see
 it actually coded up to see if there's something I'm missing that
 would prevent us from doing that, but I don't see anything.

 The only issue I see with this is that we may only want to register a
 rate table with a PLL only if fin_pll is running at a certain rate.
 On 5250 and 5420, for example, we have EPLL and VPLL rate tables that
 should only be registered if fin_pll is 24Mhz.  We may have to
 register those separately, but this approach seems fine otherwise.


As Andrew Bresticker said, we will face problem with different table,
and it will give some pain while handling such cases but I think
overall code may look better.

Similar thoughts were their in my mind also, but i didn't want to
disturb this series :).
Anyways, I think we can do it now only rather going for incremental
patches after this series.
I was thinking to make samsung_clk_register_pll itself  little
generic instead
of using helper, as we are almost duplicating code for most PLLs.

A rough picture in my mind was,
After implementing  generic samung_clk_register_pll(), code may look like
below. Its just an idea, please feel free to correct it.
Later we can factor out other common clk.ops for PLLs also.

this diff is over this series.
Assuming a generic samung_clk_register_pll() is their(which i think is
not impossible)
8--

--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -493,6 +493,20 @@ static __initdata struct samsung_pll_rate_table
epll_24mhz_tbl[] = {
PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
 };

+struct __initdata samsung_pll_init_data samsung_plls[] = {
+   PLL(pll_3500, fout_apll, fin_pll, APLL_LOCK, APLL_CON0, NULL),
+   PLL(pll_3500, fout_mpll, fin_pll, MPLL_LOCK, MPLL_CON0, NULL),
+   PLL(pll_3500, fout_bpll, fin_pll,BPLL_LOCK, BPLL_CON0, NULL),
+   PLL(pll_3500, fout_gpll, fin_pll,GPLL_LOCK, GPLL_CON0, NULL),
+   PLL(pll_3500, fout_cpll, fin_pll,BPLL_LOCK, CPLL_CON0, NULL),
+};
+
+struct __initdata samsung_pll_init_data epll_init_data =
+   PLL(pll_3600, fout_epll, fin_pll, EPLL_LOCK, EPLL_CON0, NULL);
+
+struct __initdata samsung_pll_init_data vpll_init_data =
+   PLL(pll_3600, fout_epll, fin_pll, VPLL_LOCK, VPLL_CON0, NULL);
+
 /* register exynox5250 clocks */
 void __init exynos5250_clk_init(struct device_node *np)
 {
@@ -519,44 +533,22 @@ void __init exynos5250_clk_init(struct device_node *np)
samsung_clk_register_mux(exynos5250_pll_pmux_clks,
ARRAY_SIZE(exynos5250_pll_pmux_clks));

-   fin_pll_rate = _get_rate(fin_pll);
+   samsung_clk_register_pll(samsung_plls, ARRAY_SIZE(samsung_plls));
+
vpllsrc = __clk_lookup(mout_vpllsrc);
if (vpllsrc)
mout_vpllsrc_rate = clk_get_rate(vpllsrc);

-   apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
-   reg_base, NULL, 0);
-   mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
-   reg_base + 0x4000, NULL, 0);
-   bpll = samsung_clk_register_pll35xx(fout_bpll, fin_pll,
-   reg_base + 0x20010, NULL, 0);
-   gpll = samsung_clk_register_pll35xx(fout_gpll, fin_pll,
-   reg_base + 0x10050, NULL, 0);
-   cpll = samsung_clk_register_pll35xx(fout_cpll, fin_pll,
-   reg_base + 0x10020, NULL, 0);
-
+   fin_pll_rate = _get_rate(fin_pll);
if (fin_pll_rate == (24 * MHZ)) {
-   epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + 0x10030, epll_24mhz_tbl,
-   ARRAY_SIZE(epll_24mhz_tbl));
-   } else {
-   pr_warn(%s: valid epll rate_table missing for\n
-   parent fin_pll:%lu hz\n, __func__, fin_pll_rate);
-   epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + 0x10030, NULL, 0);
+   epll_init_data.rate_table =  epll_24mhz_tb;
}
+   samsung_clk_register_pll(fout_epll_data, 1);

if (mout_vpllsrc_rate == (24 * MHZ)) {
-   vpll = samsung_clk_register_pll36xx(fout_vpll, 

Re: [PATCH v4 1/6] clk: samsung: Use clk-base instead of directly using clk-con0 for PLL3xxx

2013-06-13 Thread Yadwinder Singh Brar
On Thu, Jun 13, 2013 at 3:00 PM, Tomasz Figa tomasz.f...@gmail.com wrote:
 On Thursday 13 of June 2013 12:32:05 Yadwinder Singh Brar wrote:
 On Thu, Jun 13, 2013 at 3:32 AM, Andrew Bresticker

 abres...@chromium.org wrote:
  Doug,
 
  Hmm, if done properly, it could simplify PLL registration in SoC
  clock
  initialization code a lot.
 
  I'm not sure if this is really the best solution (feel free to
  suggest
  anything better), but we could put PLLs in an array, like other
  clocks,
  e.g.
 
  ... exynos4210_pll_clks[] = {
 
  CLK_PLL45XX(...),
  CLK_PLL45XX(...),
  CLK_PLL46XX(...),
  CLK_PLL46XX(...),
 
  };
 
  and then just call a helper like
 
  samsung_clk_register_pll(exynos4210_pll_clks,
 
  ARRAY_SIZE(exynos4210_pll_clks));
 
  Something like that looks like what I was thinking.  I'd have to see
  it actually coded up to see if there's something I'm missing that
  would prevent us from doing that, but I don't see anything.
 
  The only issue I see with this is that we may only want to register a
  rate table with a PLL only if fin_pll is running at a certain rate.
  On 5250 and 5420, for example, we have EPLL and VPLL rate tables that
  should only be registered if fin_pll is 24Mhz.  We may have to
  register those separately, but this approach seems fine otherwise.

 As Andrew Bresticker said, we will face problem with different table,
 and it will give some pain while handling such cases but I think
 overall code may look better.

 Similar thoughts were their in my mind also, but i didn't want to
 disturb this series :).

 Yes, I was thinking the same as well, but now that Exynos5420 doesn't
 follow the 0x100 register spacing, we have a problem :) .

 Anyways, I think we can do it now only rather going for incremental
 patches after this series.
 I was thinking to make samsung_clk_register_pll itself  little
 generic instead
 of using helper, as we are almost duplicating code for most PLLs.

 A rough picture in my mind was,
 After implementing  generic samung_clk_register_pll(), code may look
 like below. Its just an idea, please feel free to correct it.
 Later we can factor out other common clk.ops for PLLs also.

 this diff is over this series.
 Assuming a generic samung_clk_register_pll() is their(which i think is
 not impossible)
 8--
 

 --- a/drivers/clk/samsung/clk-exynos5250.c
 +++ b/drivers/clk/samsung/clk-exynos5250.c
 @@ -493,6 +493,20 @@ static __initdata struct samsung_pll_rate_table
 epll_24mhz_tbl[] = {
 PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
  };

 +struct __initdata samsung_pll_init_data samsung_plls[] = {
 +   PLL(pll_3500, fout_apll, fin_pll, APLL_LOCK, APLL_CON0,
 NULL), +   PLL(pll_3500, fout_mpll, fin_pll, MPLL_LOCK,
 MPLL_CON0, NULL), +   PLL(pll_3500, fout_bpll,
 fin_pll,BPLL_LOCK, BPLL_CON0, NULL), +   PLL(pll_3500,
 fout_gpll, fin_pll,GPLL_LOCK, GPLL_CON0, NULL), +
 PLL(pll_3500, fout_cpll, fin_pll,BPLL_LOCK, CPLL_CON0, NULL), +};
 +
 +struct __initdata samsung_pll_init_data epll_init_data =
 +   PLL(pll_3600, fout_epll, fin_pll, EPLL_LOCK, EPLL_CON0,
 NULL); +
 +struct __initdata samsung_pll_init_data vpll_init_data =
 +   PLL(pll_3600, fout_epll, fin_pll, VPLL_LOCK, VPLL_CON0,
 NULL); +

 This is mostly what I had in my mind. In addition I think I might have a
 solution for rate tables:

 If we create another array

 struct samsung_pll_rate_table *rate_tables_24mhz[] = {
 apll_rate_table_24mhz,
 mpll_rate_table_24mhz, /* can be NULL as well, if no
 support for rate change */
 epll_rate_table_24mhz,
 vpll_rate_table_24mhz,
 /* ... */
 };

 which lists rate tables for given input frequency. This relies on making
 rate tables end with a sentinel, to remove the need of passing array
 sizes.


I think we may also have to make assumption that entries in the arrays
rate_tables_24mhz[] and samsung_plls[] should be in same order in
both arrays, and which may not be fair assumption, otherwise we
have to use some mechanism to identify which rate_table is for which PLL,
which will increase code and complexity.
Am I missed something or you are thinking something else?

Any thoughts from Doug or others ?

  /* register exynox5250 clocks */
  void __init exynos5250_clk_init(struct device_node *np)
  {
 @@ -519,44 +533,22 @@ void __init exynos5250_clk_init(struct device_node
 *np) samsung_clk_register_mux(exynos5250_pll_pmux_clks,
 ARRAY_SIZE(exynos5250_pll_pmux_clks));

 -   fin_pll_rate = _get_rate(fin_pll);
 +   samsung_clk_register_pll(samsung_plls,
 ARRAY_SIZE(samsung_plls)); +

 ...and then pass it here like:

 if (fin_pll_rate == 24 * MHZ) {
 samsung_clk_register_pll(samsung_plls,
 ARRAY_SIZE(samsung_plls

Re: [PATCH v4 1/6] clk: samsung: Use clk-base instead of directly using clk-con0 for PLL3xxx

2013-06-13 Thread Yadwinder Singh Brar
On Fri, Jun 14, 2013 at 12:13 AM, Tomasz Figa tomasz.f...@gmail.com wrote:
 On Friday 14 of June 2013 00:05:31 Yadwinder Singh Brar wrote:
 On Thu, Jun 13, 2013 at 3:00 PM, Tomasz Figa tomasz.f...@gmail.com
 wrote:
  On Thursday 13 of June 2013 12:32:05 Yadwinder Singh Brar wrote:
  On Thu, Jun 13, 2013 at 3:32 AM, Andrew Bresticker
 
  abres...@chromium.org wrote:
   Doug,
  
   Hmm, if done properly, it could simplify PLL registration in SoC
   clock
   initialization code a lot.
  
   I'm not sure if this is really the best solution (feel free to
   suggest
   anything better), but we could put PLLs in an array, like other
   clocks,
   e.g.
  
   ... exynos4210_pll_clks[] = {
  
   CLK_PLL45XX(...),
   CLK_PLL45XX(...),
   CLK_PLL46XX(...),
   CLK_PLL46XX(...),
  
   };
  
   and then just call a helper like
  
   samsung_clk_register_pll(exynos4210_pll_clks,
  
   ARRAY_SIZE(exynos4210_pll_clks));
  
   Something like that looks like what I was thinking.  I'd have to
   see
   it actually coded up to see if there's something I'm missing that
   would prevent us from doing that, but I don't see anything.
  
   The only issue I see with this is that we may only want to register
   a
   rate table with a PLL only if fin_pll is running at a certain rate.
   On 5250 and 5420, for example, we have EPLL and VPLL rate tables
   that
   should only be registered if fin_pll is 24Mhz.  We may have to
   register those separately, but this approach seems fine otherwise.
 
  As Andrew Bresticker said, we will face problem with different table,
  and it will give some pain while handling such cases but I think
  overall code may look better.
 
  Similar thoughts were their in my mind also, but i didn't want to
  disturb this series :).
 
  Yes, I was thinking the same as well, but now that Exynos5420 doesn't
  follow the 0x100 register spacing, we have a problem :) .
 
  Anyways, I think we can do it now only rather going for incremental
  patches after this series.
  I was thinking to make samsung_clk_register_pll itself  little
  generic instead
  of using helper, as we are almost duplicating code for most PLLs.
 
  A rough picture in my mind was,
  After implementing  generic samung_clk_register_pll(), code may look
  like below. Its just an idea, please feel free to correct it.
  Later we can factor out other common clk.ops for PLLs also.
 
  this diff is over this series.
  Assuming a generic samung_clk_register_pll() is their(which i think
  is
  not impossible)
  8---
  --- 
 
  --- a/drivers/clk/samsung/clk-exynos5250.c
  +++ b/drivers/clk/samsung/clk-exynos5250.c
  @@ -493,6 +493,20 @@ static __initdata struct samsung_pll_rate_table
  epll_24mhz_tbl[] = {
 
  PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
 
   };
 
  +struct __initdata samsung_pll_init_data samsung_plls[] = {
  +   PLL(pll_3500, fout_apll, fin_pll, APLL_LOCK, APLL_CON0,
  NULL), +   PLL(pll_3500, fout_mpll, fin_pll, MPLL_LOCK,
  MPLL_CON0, NULL), +   PLL(pll_3500, fout_bpll,
  fin_pll,BPLL_LOCK, BPLL_CON0, NULL), +   PLL(pll_3500,
  fout_gpll, fin_pll,GPLL_LOCK, GPLL_CON0, NULL), +
  PLL(pll_3500, fout_cpll, fin_pll,BPLL_LOCK, CPLL_CON0, NULL), +};
  +
  +struct __initdata samsung_pll_init_data epll_init_data =
  +   PLL(pll_3600, fout_epll, fin_pll, EPLL_LOCK, EPLL_CON0,
  NULL); +
  +struct __initdata samsung_pll_init_data vpll_init_data =
  +   PLL(pll_3600, fout_epll, fin_pll, VPLL_LOCK, VPLL_CON0,
  NULL); +
 
  This is mostly what I had in my mind. In addition I think I might have
  a solution for rate tables:
 
  If we create another array
 
  struct samsung_pll_rate_table *rate_tables_24mhz[] = {
 
  apll_rate_table_24mhz,
  mpll_rate_table_24mhz, /* can be NULL as well, if no
 
  support for rate change */
 
  epll_rate_table_24mhz,
  vpll_rate_table_24mhz,
  /* ... */
 
  };
 
  which lists rate tables for given input frequency. This relies on
  making rate tables end with a sentinel, to remove the need of passing
  array sizes.

 I think we may also have to make assumption that entries in the arrays
 rate_tables_24mhz[] and samsung_plls[] should be in same order in
 both arrays, and which may not be fair assumption, otherwise we
 have to use some mechanism to identify which rate_table is for which
 PLL, which will increase code and complexity.
 Am I missed something or you are thinking something else?

 Yes, this is exactly what I thought. The order and size of
 rate_tables_24mhz[] would have to be the same as of samsung_plls[], which
 shouldn't be a problem technically, but adds another responsibility to the
 person who defines them.


OK. but I think this is not a fair assumption.

 Any thoughts from Doug or others

Re: [PATCH v3 3/6] clk: samsung: Add set_rate() clk_ops for PLL35xx

2013-06-12 Thread Yadwinder Singh Brar
On Sat, Jun 8, 2013 at 5:42 PM, Tomasz Figa tomasz.f...@gmail.com wrote:
 On Friday 31 of May 2013 18:01:33 Vikas Sajjan wrote:
 From: Yadwinder Singh Brar yadi.b...@samsung.com

 This patch add set_rate() and round_rate() for PLL35xx

 Reviewed-by: Doug Anderson diand...@chromium.org
 Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
 ---
  drivers/clk/samsung/clk-pll.c |  103
 - 1 file changed, 102
 insertions(+), 1 deletion(-)

 diff --git a/drivers/clk/samsung/clk-pll.c
 b/drivers/clk/samsung/clk-pll.c index 8226528..9591560 100644
 --- a/drivers/clk/samsung/clk-pll.c
 +++ b/drivers/clk/samsung/clk-pll.c
 @@ -27,6 +27,36 @@ struct samsung_clk_pll {
  #define pll_writel(pll, val, offset) \
   __raw_writel(val, (void __iomem *)(pll-base + (offset)));

 +static const struct samsung_pll_rate_table *samsung_get_pll_settings(
 + struct samsung_clk_pll *pll, unsigned long
 rate)
 +{
 + const struct samsung_pll_rate_table  *rate_table = pll-
rate_table;
 + int i;
 +
 + for (i = 0; i  pll-rate_count; i++) {
 + if (rate == rate_table[i].rate)
 + return rate_table[i];
 + }
 +
 + return NULL;
 +}
 +
 +static long samsung_pll_round_rate(struct clk_hw *hw,
 + unsigned long drate, unsigned long *prate)
 +{
 + struct samsung_clk_pll *pll = to_clk_pll(hw);
 + const struct samsung_pll_rate_table *rate_table = pll-rate_table;
 + int i;
 +
 + /* Assumming rate_table is in descending order */
 + for (i = 0; i  pll-rate_count; i++) {
 + if (drate = rate_table[i].rate)
 + return rate_table[i].rate;
 + }
 +
 + /* return minimum supported value */
 + return rate_table[i - 1].rate;
 +}
  /*
   * PLL35xx Clock Type
   */
 @@ -34,12 +64,17 @@ struct samsung_clk_pll {
  #define PLL35XX_CON0_OFFSET  (0x100)
  #define PLL35XX_CON1_OFFSET  (0x104)

 +/* Maximum lock time can be 270 * PDIV cycles */
 +#define PLL35XX_LOCK_FACTOR  (270)
 +
  #define PLL35XX_MDIV_MASK   (0x3FF)
  #define PLL35XX_PDIV_MASK   (0x3F)
  #define PLL35XX_SDIV_MASK   (0x7)
 +#define PLL35XX_LOCK_STAT_MASK  (0x1)
  #define PLL35XX_MDIV_SHIFT  (16)
  #define PLL35XX_PDIV_SHIFT  (8)
  #define PLL35XX_SDIV_SHIFT  (0)
 +#define PLL35XX_LOCK_STAT_SHIFT  (29)

  static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
   unsigned long parent_rate)
 @@ -59,8 +94,70 @@ static unsigned long
 samsung_pll35xx_recalc_rate(struct clk_hw *hw, return (unsigned
 long)fvco;
  }

 +static inline bool samsung_pll35xx_mp_change(u32 mdiv, u32 pdiv, u32
 pll_con) +{
 + if ((mdiv != ((pll_con  PLL35XX_MDIV_SHIFT) 
 PLL35XX_MDIV_MASK)) ||
 + (pdiv != ((pll_con  PLL35XX_PDIV_SHIFT) 
 PLL35XX_PDIV_MASK)))
 + return 1;
 + else
 + return 0;

 Readability of this function could be improved by moving some code out of
 the if clause, like:

 static inline bool samsung_pll35xx_mp_change(u32 mdiv,
 u32 pdiv, u32 pll_con)
 {
 u32 old_mdiv, old_pdiv;

 old_mdiv = (pll_con  PLL35XX_MDIV_SHIFT)  PLL35XX_MDIV_MASK;
 old_pdiv = (pll_con  PLL35XX_PDIV_SHIFT)  PLL35XX_PDIV_MASK;

 return (mdiv != old_mdiv || pdiv != old_pdiv);
 }


Yes, it looks neater, I have modified it V4.

 +}
 +
 +static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long
 drate, +  unsigned long prate)
 +{
 + struct samsung_clk_pll *pll = to_clk_pll(hw);
 + const struct samsung_pll_rate_table *rate;
 + u32 tmp;
 +
 + /* Get required rate settings from table */
 + rate = samsung_get_pll_settings(pll, drate);
 + if (!rate) {
 + pr_err(%s: Invalid rate : %lu for pll clk %s\n,
 __func__,
 + drate, __clk_get_name(hw-clk));
 + return -EINVAL;
 + }
 +
 + tmp = pll_readl(pll, PLL35XX_CON0_OFFSET);
 +
 + if (!(samsung_pll35xx_mp_change(rate-mdiv, rate-pdiv, tmp))) {
 + /* If only s change, change just s value only*/
 + tmp = ~(PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT);
 + tmp |= rate-sdiv  PLL35XX_SDIV_SHIFT;
 + pll_writel(pll, tmp, PLL35XX_CON0_OFFSET);

 To improve readability of this code, return 0 could be added here and
 following code could be moved out of the else clause.


Hmm... I can't see much difference but I have taken this also.

Thanks,
Yadwinder

 Best regards,
 Tomasz

 + } else {
 + /* Set PLL lock time. */
 + pll_writel(pll, rate-pdiv * PLL35XX_LOCK_FACTOR,
 + PLL35XX_LOCK_OFFSET);
 +
 + /* Change PLL PMS values */
 + tmp = ~((PLL35XX_MDIV_MASK  PLL35XX_MDIV_SHIFT) |
 + (PLL35XX_PDIV_MASK

[PATCH v4 0/6] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs

2013-06-12 Thread Yadwinder Singh Brar
This patch series does the following:

 1) Unifies the clk strutures used for PLL35xx  PLL36xx and usues clk-base
instead of clk-con0, to factor out possible common code.

 2) Defines a common rate_table which will contain recommended p, m, s and k
values for supported rates that needs to be changed for changing
corresponding PLL's rate

 3) Adds set_rate() and round_rate() clk_ops for PLL35xx and PLL36xx

changes since v3:
- Used __clk_lookup() instead of adding alias for mout_vpllsrc
- Added check for changing only M value in samsung_pll36xx_set_rate()
- Modified samsung_pll35xx_mp_change()  samsung_pll35xx_set_rate()
to improve readabilty.
- Made the input rate_table as __init_data which is to be provided while
registering PLL and made a copy of that table while registering, so
that if multiple tables are their, they can be freed after getting the
P, M, S, K setting values from required one.

changes since v2:
- Added new patch to reorder the MUX registration for mout_vpllsrc MUX
before the PLL registrations. And to add the alias for the mout_vpllsrc 
MUX.
- Added a check to confirm parent rate while registrating the PLL
rate tables.

changes since v1:
- removed sorting and bsearch
- modified the definition of struct samsung_pll_rate_table
- added generic round_rate()
- rectified the ops assignment for rate table passed as NULL
  during PLL registration

Is rebased on branch kgene's for-next
https://git.kernel.org/cgit/linux/kernel/git/kgene/linux-samsung.git/log/?h=for-next

Vikas Sajjan (3):
  clk: samsung: Add set_rate() clk_ops for PLL36xx
  clk: samsung: Reorder MUX registration for mout_vpllsrc
  clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

Yadwinder Singh Brar (3):
  clk: samsung: Use clk-base instead of directly using clk-con0 for
PLL3xxx
  clk: samsung: Add support to register rate_table for PLL3xxx
  clk: samsung: Add set_rate() clk_ops for PLL35xx

 drivers/clk/samsung/clk-exynos4.c|   10 +-
 drivers/clk/samsung/clk-exynos5250.c |   73 +--
 drivers/clk/samsung/clk-pll.c|  255 ++
 drivers/clk/samsung/clk-pll.h|   35 +-
 drivers/clk/samsung/clk.h|2 +
 5 files changed, 332 insertions(+), 43 deletions(-)

--
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


[PATCH v4 1/6] clk: samsung: Use clk-base instead of directly using clk-con0 for PLL3xxx

2013-06-12 Thread Yadwinder Singh Brar
This patch unifies clk strutures used for PLL35xx  PLL36xx and uses clk-base
instead of directly using clk-con0, so that possible common code can be
factored out.
It also introdues common pll_[readl/writel] macros for the users of common
samsung_clk_pll struct.

Reviewed-by: Tomasz Figa t.f...@samsung.com
Reviewed-by: Doug Anderson diand...@chromium.org
Tested-by: Doug Anderson diand...@chromium.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos4.c|   10 --
 drivers/clk/samsung/clk-exynos5250.c |   14 
 drivers/clk/samsung/clk-pll.c|   54 ++---
 drivers/clk/samsung/clk-pll.h|4 +-
 4 files changed, 44 insertions(+), 38 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c 
b/drivers/clk/samsung/clk-exynos4.c
index addc738..ba33bc6 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -97,12 +97,14 @@
 #define GATE_IP_PERIL  0xc950
 #define E4210_GATE_IP_PERIR0xc960
 #define GATE_BLOCK 0xc970
+#define E4X12_MPLL_LOCK0x10008
 #define E4X12_MPLL_CON00x10108
 #define SRC_DMC0x10200
 #define SRC_MASK_DMC   0x10300
 #define DIV_DMC0   0x10500
 #define DIV_DMC1   0x10504
 #define GATE_IP_DMC0x10900
+#define APLL_LOCK  0x14000
 #define APLL_CON0  0x14100
 #define E4210_MPLL_CON00x14108
 #define SRC_CPU0x14200
@@ -1026,13 +1028,13 @@ void __init exynos4_clk_init(struct device_node *np, 
enum exynos4_soc exynos4_so
reg_base + VPLL_CON0, pll_4650c);
} else {
apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
-   reg_base + APLL_CON0);
+   reg_base + APLL_LOCK);
mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
-   reg_base + E4X12_MPLL_CON0);
+   reg_base + E4X12_MPLL_LOCK);
epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + EPLL_CON0);
+   reg_base + EPLL_LOCK);
vpll = samsung_clk_register_pll36xx(fout_vpll, fin_pll,
-   reg_base + VPLL_CON0);
+   reg_base + VPLL_LOCK);
}
 
samsung_clk_add_lookup(apll, fout_apll);
diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 5c97e75..687b580 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -491,19 +491,19 @@ void __init exynos5250_clk_init(struct device_node *np)
ext_clk_match);
 
apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
-   reg_base + 0x100);
+   reg_base);
mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
-   reg_base + 0x4100);
+   reg_base + 0x4000);
bpll = samsung_clk_register_pll35xx(fout_bpll, fin_pll,
-   reg_base + 0x20110);
+   reg_base + 0x20010);
gpll = samsung_clk_register_pll35xx(fout_gpll, fin_pll,
-   reg_base + 0x10150);
+   reg_base + 0x10050);
cpll = samsung_clk_register_pll35xx(fout_cpll, fin_pll,
-   reg_base + 0x10120);
+   reg_base + 0x10020);
epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + 0x10130);
+   reg_base + 0x10030);
vpll = samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc,
-   reg_base + 0x10140);
+   reg_base + 0x10040);
 
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
ARRAY_SIZE(exynos5250_fixed_rate_clks));
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 89135f6..a7d8ad9 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -13,9 +13,24 @@
 #include clk.h
 #include clk-pll.h
 
+struct samsung_clk_pll {
+   struct clk_hw   hw;
+   const void __iomem  *base;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
+#define pll_readl(pll, offset) \
+   __raw_readl((void __iomem *)(pll-base + (offset)));
+#define pll_writel(pll, val, offset)   \
+   __raw_writel(val, (void __iomem *)(pll-base + (offset)));
+
 /*
  * PLL35xx Clock Type
  */
+#define PLL35XX_LOCK_OFFSET(0x0)
+#define PLL35XX_CON0_OFFSET(0x100)
+#define PLL35XX_CON1_OFFSET

[PATCH v4 3/6] clk: samsung: Add set_rate() clk_ops for PLL35xx

2013-06-12 Thread Yadwinder Singh Brar
This patch add set_rate() and round_rate() for PLL35xx

Reviewed-by: Doug Anderson diand...@chromium.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-pll.c |  104 -
 1 files changed, 103 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index cba73a4..319b52b 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -27,6 +27,37 @@ struct samsung_clk_pll {
 #define pll_writel(pll, val, offset)   \
__raw_writel(val, (void __iomem *)(pll-base + (offset)));
 
+static const struct samsung_pll_rate_table *samsung_get_pll_settings(
+   struct samsung_clk_pll *pll, unsigned long rate)
+{
+   const struct samsung_pll_rate_table  *rate_table = pll-rate_table;
+   int i;
+
+   for (i = 0; i  pll-rate_count; i++) {
+   if (rate == rate_table[i].rate)
+   return rate_table[i];
+   }
+
+   return NULL;
+}
+
+static long samsung_pll_round_rate(struct clk_hw *hw,
+   unsigned long drate, unsigned long *prate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   const struct samsung_pll_rate_table *rate_table = pll-rate_table;
+   int i;
+
+   /* Assumming rate_table is in descending order */
+   for (i = 0; i  pll-rate_count; i++) {
+   if (drate = rate_table[i].rate)
+   return rate_table[i].rate;
+   }
+
+   /* return minimum supported value */
+   return rate_table[i - 1].rate;
+}
+
 /*
  * PLL35xx Clock Type
  */
@@ -34,12 +65,17 @@ struct samsung_clk_pll {
 #define PLL35XX_CON0_OFFSET(0x100)
 #define PLL35XX_CON1_OFFSET(0x104)
 
+/* Maximum lock time can be 270 * PDIV cycles */
+#define PLL35XX_LOCK_FACTOR(270)
+
 #define PLL35XX_MDIV_MASK   (0x3FF)
 #define PLL35XX_PDIV_MASK   (0x3F)
 #define PLL35XX_SDIV_MASK   (0x7)
+#define PLL35XX_LOCK_STAT_MASK  (0x1)
 #define PLL35XX_MDIV_SHIFT  (16)
 #define PLL35XX_PDIV_SHIFT  (8)
 #define PLL35XX_SDIV_SHIFT  (0)
+#define PLL35XX_LOCK_STAT_SHIFT(29)
 
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -59,8 +95,72 @@ static unsigned long samsung_pll35xx_recalc_rate(struct 
clk_hw *hw,
return (unsigned long)fvco;
 }
 
+static inline bool samsung_pll35xx_mp_change(
+   const struct samsung_pll_rate_table *rate, u32 pll_con)
+{
+   u32 old_mdiv, old_pdiv;
+
+   old_mdiv = (pll_con  PLL35XX_MDIV_SHIFT)  PLL35XX_MDIV_MASK;
+   old_pdiv = (pll_con  PLL35XX_PDIV_SHIFT)  PLL35XX_PDIV_MASK;
+
+   return (rate-mdiv != old_mdiv || rate-pdiv != old_pdiv);
+}
+
+static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long prate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   const struct samsung_pll_rate_table *rate;
+   u32 tmp;
+
+   /* Get required rate settings from table */
+   rate = samsung_get_pll_settings(pll, drate);
+   if (!rate) {
+   pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__,
+   drate, __clk_get_name(hw-clk));
+   return -EINVAL;
+   }
+
+   tmp = pll_readl(pll, PLL35XX_CON0_OFFSET);
+
+   if (!(samsung_pll35xx_mp_change(rate, tmp))) {
+   /* If only s change, change just s value only*/
+   tmp = ~(PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT);
+   tmp |= rate-sdiv  PLL35XX_SDIV_SHIFT;
+   pll_writel(pll, tmp, PLL35XX_CON0_OFFSET);
+   } else {
+   /* Set PLL lock time. */
+   pll_writel(pll, rate-pdiv * PLL35XX_LOCK_FACTOR,
+   PLL35XX_LOCK_OFFSET);
+
+   /* Change PLL PMS values */
+   tmp = ~((PLL35XX_MDIV_MASK  PLL35XX_MDIV_SHIFT) |
+   (PLL35XX_PDIV_MASK  PLL35XX_PDIV_SHIFT) |
+   (PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT));
+   tmp |= (rate-mdiv  PLL35XX_MDIV_SHIFT) |
+   (rate-pdiv  PLL35XX_PDIV_SHIFT) |
+   (rate-sdiv  PLL35XX_SDIV_SHIFT);
+   pll_writel(pll, tmp, PLL35XX_CON0_OFFSET);
+
+   /* wait_lock_time */
+   do {
+   cpu_relax();
+   tmp = pll_readl(pll, PLL35XX_CON0_OFFSET);
+   } while (!(tmp  (PLL35XX_LOCK_STAT_MASK
+PLL35XX_LOCK_STAT_SHIFT)));
+   }
+
+   return 0;
+}
+
 static const struct clk_ops samsung_pll35xx_clk_ops = {
.recalc_rate = samsung_pll35xx_recalc_rate,
+   .round_rate = samsung_pll_round_rate,
+   .set_rate = samsung_pll35xx_set_rate,
+};
+
+static const

[PATCH v4 2/6] clk: samsung: Add support to register rate_table for PLL3xxx

2013-06-12 Thread Yadwinder Singh Brar
This patch defines a common rate_table which will contain recommended p, m, s,
k values for supported rates that needs to be changed for changing
corresponding PLL's rate.

Reviewed-by: Doug Anderson diand...@chromium.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos4.c|8 +++---
 drivers/clk/samsung/clk-exynos5250.c |   14 ++--
 drivers/clk/samsung/clk-pll.c|   22 +++-
 drivers/clk/samsung/clk-pll.h|   35 -
 4 files changed, 64 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c 
b/drivers/clk/samsung/clk-exynos4.c
index ba33bc6..e02a342 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1028,13 +1028,13 @@ void __init exynos4_clk_init(struct device_node *np, 
enum exynos4_soc exynos4_so
reg_base + VPLL_CON0, pll_4650c);
} else {
apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
-   reg_base + APLL_LOCK);
+   reg_base + APLL_LOCK, NULL, 0);
mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
-   reg_base + E4X12_MPLL_LOCK);
+   reg_base + E4X12_MPLL_LOCK, NULL, 0);
epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + EPLL_LOCK);
+   reg_base + EPLL_LOCK, NULL, 0);
vpll = samsung_clk_register_pll36xx(fout_vpll, fin_pll,
-   reg_base + VPLL_LOCK);
+   reg_base + VPLL_LOCK, NULL, 0);
}
 
samsung_clk_add_lookup(apll, fout_apll);
diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 687b580..ddf10ca 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -491,19 +491,19 @@ void __init exynos5250_clk_init(struct device_node *np)
ext_clk_match);
 
apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
-   reg_base);
+   reg_base, NULL, 0);
mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
-   reg_base + 0x4000);
+   reg_base + 0x4000, NULL, 0);
bpll = samsung_clk_register_pll35xx(fout_bpll, fin_pll,
-   reg_base + 0x20010);
+   reg_base + 0x20010, NULL, 0);
gpll = samsung_clk_register_pll35xx(fout_gpll, fin_pll,
-   reg_base + 0x10050);
+   reg_base + 0x10050, NULL, 0);
cpll = samsung_clk_register_pll35xx(fout_cpll, fin_pll,
-   reg_base + 0x10020);
+   reg_base + 0x10020, NULL, 0);
epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + 0x10030);
+   reg_base + 0x10030, NULL, 0);
vpll = samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc,
-   reg_base + 0x10040);
+   reg_base + 0x10040, NULL, 0);
 
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
ARRAY_SIZE(exynos5250_fixed_rate_clks));
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index a7d8ad9..cba73a4 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -16,6 +16,8 @@
 struct samsung_clk_pll {
struct clk_hw   hw;
const void __iomem  *base;
+   const struct samsung_pll_rate_table *rate_table;
+   unsigned int rate_count;
 };
 
 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
@@ -62,7 +64,9 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
 };
 
 struct clk * __init samsung_clk_register_pll35xx(const char *name,
-   const char *pname, const void __iomem *base)
+   const char *pname, const void __iomem *base,
+   const struct samsung_pll_rate_table *rate_table,
+   const unsigned int rate_count)
 {
struct samsung_clk_pll *pll;
struct clk *clk;
@@ -80,6 +84,12 @@ struct clk * __init samsung_clk_register_pll35xx(const char 
*name,
init.parent_names = pname;
init.num_parents = 1;
 
+   if (rate_table  rate_count) {
+   pll-rate_count = rate_count;
+   pll-rate_table = kmemdup(rate_table, rate_count *
+   sizeof(struct samsung_pll_rate_table), GFP_KERNEL);
+   }
+
pll-hw.init = init;
pll-base = base;
 
@@ -137,7 +147,9 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
 };
 
 struct clk * __init samsung_clk_register_pll36xx(const

[PATCH v4 4/6] clk: samsung: Add set_rate() clk_ops for PLL36xx

2013-06-12 Thread Yadwinder Singh Brar
From: Vikas Sajjan vikas.saj...@linaro.org

This patch adds set_rate and round_rate clk_ops for PLL36xx

Reviewed-by: Tomasz Figa t.f...@samsung.com
Reviewed-by: Doug Anderson diand...@chromium.org
Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
---
 drivers/clk/samsung/clk-pll.c |   79 -
 1 files changed, 78 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 319b52b..42b60b5 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -215,6 +215,9 @@ struct clk * __init samsung_clk_register_pll35xx(const char 
*name,
 #define PLL36XX_CON0_OFFSET(0x100)
 #define PLL36XX_CON1_OFFSET(0x104)
 
+/* Maximum lock time can be 3000 * PDIV cycles */
+#define PLL36XX_LOCK_FACTOR(3000)
+
 #define PLL36XX_KDIV_MASK  (0x)
 #define PLL36XX_MDIV_MASK  (0x1FF)
 #define PLL36XX_PDIV_MASK  (0x3F)
@@ -222,6 +225,8 @@ struct clk * __init samsung_clk_register_pll35xx(const char 
*name,
 #define PLL36XX_MDIV_SHIFT (16)
 #define PLL36XX_PDIV_SHIFT (8)
 #define PLL36XX_SDIV_SHIFT (0)
+#define PLL36XX_KDIV_SHIFT (0)
+#define PLL36XX_LOCK_STAT_SHIFT(29)
 
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -244,8 +249,78 @@ static unsigned long samsung_pll36xx_recalc_rate(struct 
clk_hw *hw,
return (unsigned long)fvco;
 }
 
+static inline bool samsung_pll36xx_mpk_change(
+   const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
+{
+   u32 old_mdiv, old_pdiv, old_kdiv;
+
+   old_mdiv = (pll_con0  PLL36XX_MDIV_SHIFT)  PLL36XX_MDIV_MASK;
+   old_pdiv = (pll_con0  PLL36XX_PDIV_SHIFT)  PLL36XX_PDIV_MASK;
+   old_kdiv = (pll_con1  PLL36XX_KDIV_SHIFT)  PLL36XX_KDIV_MASK;
+
+   return (rate-mdiv != old_mdiv || rate-pdiv != old_pdiv ||
+   rate-kdiv != old_kdiv);
+}
+
+static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long parent_rate)
+{
+   struct samsung_clk_pll *pll = to_clk_pll(hw);
+   u32 tmp, pll_con0, pll_con1;
+   const struct samsung_pll_rate_table *rate;
+
+   rate = samsung_get_pll_settings(pll, drate);
+   if (!rate) {
+   pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__,
+   drate, __clk_get_name(hw-clk));
+   return -EINVAL;
+   }
+
+   pll_con0 = pll_readl(pll, PLL36XX_CON0_OFFSET);
+   pll_con1 = pll_readl(pll, PLL36XX_CON1_OFFSET);
+
+   if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
+   /* If only s change, change just s value only*/
+   pll_con0 = ~(PLL36XX_SDIV_MASK  PLL36XX_SDIV_SHIFT);
+   pll_con0 |= (rate-sdiv  PLL36XX_SDIV_SHIFT);
+   pll_writel(pll, pll_con0, PLL36XX_CON0_OFFSET);
+   return 0;
+   }
+
+   /* Set PLL lock time. */
+   pll_writel(pll, (rate-pdiv * PLL36XX_LOCK_FACTOR),
+   PLL36XX_LOCK_OFFSET);
+
+/* Change PLL PMS values */
+   pll_con0 = ~((PLL36XX_MDIV_MASK  PLL36XX_MDIV_SHIFT) |
+   (PLL36XX_PDIV_MASK  PLL36XX_PDIV_SHIFT) |
+   (PLL36XX_SDIV_MASK  PLL36XX_SDIV_SHIFT));
+   pll_con0 |= (rate-mdiv  PLL36XX_MDIV_SHIFT) |
+   (rate-pdiv  PLL36XX_PDIV_SHIFT) |
+   (rate-sdiv  PLL36XX_SDIV_SHIFT);
+   pll_writel(pll, pll_con0, PLL36XX_CON0_OFFSET);
+
+   pll_con1 = ~(PLL36XX_KDIV_MASK  PLL36XX_KDIV_SHIFT);
+   pll_con1 |= rate-kdiv  PLL36XX_KDIV_SHIFT;
+   pll_writel(pll, pll_con1, PLL36XX_CON1_OFFSET);
+
+   /* wait_lock_time */
+   do {
+   cpu_relax();
+   tmp = pll_readl(pll, PLL36XX_CON0_OFFSET);
+   } while (!(tmp  (1  PLL36XX_LOCK_STAT_SHIFT)));
+
+   return 0;
+}
+
 static const struct clk_ops samsung_pll36xx_clk_ops = {
.recalc_rate = samsung_pll36xx_recalc_rate,
+   .set_rate = samsung_pll36xx_set_rate,
+   .round_rate = samsung_pll_round_rate,
+};
+
+static const struct clk_ops samsung_pll36xx_clk_min_ops = {
+   .recalc_rate = samsung_pll36xx_recalc_rate,
 };
 
 struct clk * __init samsung_clk_register_pll36xx(const char *name,
@@ -264,7 +339,6 @@ struct clk * __init samsung_clk_register_pll36xx(const char 
*name,
}
 
init.name = name;
-   init.ops = samsung_pll36xx_clk_ops;
init.flags = CLK_GET_RATE_NOCACHE;
init.parent_names = pname;
init.num_parents = 1;
@@ -273,6 +347,9 @@ struct clk * __init samsung_clk_register_pll36xx(const char 
*name,
pll-rate_count = rate_count;
pll-rate_table = kmemdup(rate_table, rate_count *
sizeof(struct samsung_pll_rate_table), GFP_KERNEL);
+   init.ops = samsung_pll36xx_clk_ops;
+   } else {
+ 

[PATCH v4 5/6] clk: samsung: Reorder MUX registration for mout_vpllsrc

2013-06-12 Thread Yadwinder Singh Brar
From: Vikas Sajjan vikas.saj...@linaro.org

While trying to get rate of mout_vpllsrc MUX (parent) for registering the
fout_vpll (child), we found get rate was failing.

So this patch moves the mout_vpllsrc MUX out of the existing common list
and registers the mout_vpllsrc MUX before the PLL registrations.

Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/clk/samsung/clk-exynos5250.c |8 +++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index ddf10ca..70cc6cf 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -207,6 +207,10 @@ struct samsung_fixed_factor_clock 
exynos5250_fixed_factor_clks[] __initdata = {
FFACTOR(none, fout_bplldiv2, fout_bpll, 1, 2, 0),
 };
 
+struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+   MUX(none, mout_vpllsrc, mout_vpllsrc_p, SRC_TOP2, 0, 1),
+};
+
 struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(none, mout_apll, mout_apll_p, SRC_CPU, 0, 1),
MUX(none, mout_cpu, mout_cpu_p, SRC_CPU, 16, 1),
@@ -214,7 +218,6 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = 
{
MUX(none, sclk_mpll, mout_mpll_p, SRC_CORE1, 8, 1),
MUX(none, mout_bpll_fout, mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
MUX(none, sclk_bpll, mout_bpll_p, SRC_CDREX, 0, 1),
-   MUX(none, mout_vpllsrc, mout_vpllsrc_p, SRC_TOP2, 0, 1),
MUX(none, sclk_vpll, mout_vpll_p, SRC_TOP2, 16, 1),
MUX(none, sclk_epll, mout_epll_p, SRC_TOP2, 12, 1),
MUX(none, sclk_cpll, mout_cpll_p, SRC_TOP2, 8, 1),
@@ -490,6 +493,9 @@ void __init exynos5250_clk_init(struct device_node *np)
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
 
+   samsung_clk_register_mux(exynos5250_pll_pmux_clks,
+   ARRAY_SIZE(exynos5250_pll_pmux_clks));
+
apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
reg_base, NULL, 0);
mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
-- 
1.7.0.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


[PATCH v4 6/6] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

2013-06-12 Thread Yadwinder Singh Brar
Adds the EPLL and VPLL freq table for exynos5250 SoC.

Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org
---
 drivers/clk/samsung/clk-exynos5250.c |   53 --
 drivers/clk/samsung/clk.h|2 +
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c 
b/drivers/clk/samsung/clk-exynos5250.c
index 70cc6cf..f98c19d 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -472,11 +472,34 @@ static __initdata struct of_device_id ext_clk_match[] = {
{ },
 };
 
+static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = {
+   /* sorted in descending order */
+   /* PLL_36XX_RATE(rate, m, p, s, k) */
+   PLL_36XX_RATE(26600, 266, 3, 3, 0),
+   /* Not in UM, but need for eDP on snow */
+   PLL_36XX_RATE(7050, 94, 2, 4, 0),
+};
+
+static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
+   /* sorted in descending order */
+   /* PLL_36XX_RATE(rate, m, p, s, k) */
+   PLL_36XX_RATE(19200, 48, 3, 1, 0),
+   PLL_36XX_RATE(180633600, 45, 3, 1, 10381),
+   PLL_36XX_RATE(18000, 45, 3, 1, 0),
+   PLL_36XX_RATE(73728000, 73, 3, 3, 47710),
+   PLL_36XX_RATE(67737600, 90, 4, 3, 20762),
+   PLL_36XX_RATE(49152000, 49, 3, 3, 9962),
+   PLL_36XX_RATE(45158400, 45, 3, 3, 10381),
+   PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
+};
+
 /* register exynox5250 clocks */
 void __init exynos5250_clk_init(struct device_node *np)
 {
void __iomem *reg_base;
struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
+   struct clk *vpllsrc;
+   unsigned long fin_pll_rate, mout_vpllsrc_rate = 0;
 
if (np) {
reg_base = of_iomap(np, 0);
@@ -496,6 +519,11 @@ void __init exynos5250_clk_init(struct device_node *np)
samsung_clk_register_mux(exynos5250_pll_pmux_clks,
ARRAY_SIZE(exynos5250_pll_pmux_clks));
 
+   fin_pll_rate = _get_rate(fin_pll);
+   vpllsrc = __clk_lookup(mout_vpllsrc);
+   if (vpllsrc)
+   mout_vpllsrc_rate = clk_get_rate(vpllsrc);
+
apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
reg_base, NULL, 0);
mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
@@ -506,10 +534,29 @@ void __init exynos5250_clk_init(struct device_node *np)
reg_base + 0x10050, NULL, 0);
cpll = samsung_clk_register_pll35xx(fout_cpll, fin_pll,
reg_base + 0x10020, NULL, 0);
-   epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
-   reg_base + 0x10030, NULL, 0);
-   vpll = samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc,
+
+   if (fin_pll_rate == (24 * MHZ)) {
+   epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
+   reg_base + 0x10030, epll_24mhz_tbl,
+   ARRAY_SIZE(epll_24mhz_tbl));
+   } else {
+   pr_warn(%s: valid epll rate_table missing for\n
+   parent fin_pll:%lu hz\n, __func__, fin_pll_rate);
+   epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
+   reg_base + 0x10030, NULL, 0);
+   }
+
+   if (mout_vpllsrc_rate == (24 * MHZ)) {
+   vpll = samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc
+   , reg_base + 0x10040, vpll_24mhz_tbl,
+   ARRAY_SIZE(vpll_24mhz_tbl));
+   } else {
+   pr_warn(%s: valid vpll rate_table missing for\n
+   parent mout_vpllsrc_rate:%lu hz\n, __func__,
+   mout_vpllsrc_rate);
+   samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc,
reg_base + 0x10040, NULL, 0);
+   }
 
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
ARRAY_SIZE(exynos5250_fixed_rate_clks));
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index e4ad6ea..c997649 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -20,6 +20,8 @@
 #include linux/of.h
 #include linux/of_address.h
 
+#define MHZ (1000*1000)
+
 /**
  * struct samsung_clock_alias: information about mux clock
  * @id: platform specific id of the clock.
-- 
1.7.0.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


Re: [PATCH v2 2/5] clk: samsung: Add support to register rate_table for PLL3xxx

2013-06-06 Thread Yadwinder Singh Brar
On Wed, Jun 5, 2013 at 7:10 PM, Tomasz Figa t.f...@samsung.com wrote:
 Hi Yadwinder,

 On Tuesday 04 of June 2013 17:02:48 Yadwinder Singh Brar wrote:
 Hi Tomasz,

 On Mon, Jun 3, 2013 at 8:55 PM, Tomasz Figa t.f...@samsung.com wrote:
  Hi Yadwinder,
 
  On Thursday 30 of May 2013 12:25:40 Yadwinder Singh Brar wrote:
  Hi Doug,
 
  On Thu, May 30, 2013 at 5:14 AM, Doug Anderson diand...@chromium.org
 
  wrote:
   Vikas / Yadwinder,
  
   On Wed, May 29, 2013 at 6:37 AM, Vikas Sajjan vikas.saj...@linaro.org
 
  wrote:
   From: Yadwinder Singh Brar yadi.b...@samsung.com
  
   This patch defines a common rate_table which will contain recommended
   p,
   m, s, k values for supported rates that needs to be changed for
   changing
   corresponding PLL's rate.
  
   Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
   ---
  
drivers/clk/samsung/clk-exynos4.c|8 
drivers/clk/samsung/clk-exynos5250.c |   14 +++---
drivers/clk/samsung/clk-pll.c|   14 --
drivers/clk/samsung/clk-pll.h|   33
+++-- 4 files changed, 54 insertions(+),
15
deletions(-)
  
   I also reviewed this in our gerrit
   https://gerrit.chromium.org/gerrit/#/c/56742/, but I'll summarize
   here for the list...
  
struct clk * __init samsung_clk_register_pll35xx(const char *name,
  
   -   const char *pname, const void __iomem *base)
   +   const char *pname, const void __iomem *base,
   +   const struct samsung_pll_rate_table
   *rate_table,
   +   const unsigned int rate_count)
  
   Feels like you should document here that rate_table needs to be sorted
   and the sort order.
 
  sure,  we will add comment  to sort the table in descending order.
 
   +struct samsung_pll_rate_table {
   +   unsigned  int rate;
  
   nit: extra space before int should be removed.
 
  ok
 
   Also: you can include rate here if you need a convenient place to
   store it (which sadly means that this structure can't be const).
   ...but I do like Tomasz's idea of actually calculating it.  You can't
   know it at compile time since the parent rate comes from the device
   tree.
  
   compatible = samsung,clock-xxti;
   clock-frequency = 2400;
 
  Actually this table should contain the recommended values
  and if we see the user manual, the input(parent) rate is also a part
  of recommended
  table of different output rate for a particular PLL for that SoC.
 
  From what I understood in the documentation is that there is a set of
  recommended P, M, S (, K) tuples for each PLL and they are not dependent
  on
  input frequency - f_in and f_out are provided in the table just for
  reference to see the relation between output frequency and input
  frequency.

 If input rate(f_in) gets changed for PLL, then the corresponding
 output rates(f_out)
 will change by using same(common) set of  recommended P, M, S (, K),
 and the new set of  output rates(f_out) may not be the _required_ set
 of target rates.
 So we need different set of P, M, S (,K) values for different f_in.

 Table should contain set of P, M, S (,K) values for the _required_
 target(f_out) rates
 for a particular input(f_in) rate.

 I'm not sure what required rates you are talking about. For most PLLs the list
 of available frequencies seems to be defined by the set of supported PMS 
 values
 and those are the frequencies that can be set by consumers, not the other way
 around.

 There are some cases when some particular frequency must be generated, like
 PLLs used for audio or video clock sources, but this just means that there
 must be an entry in PMS table that gives PLL configuration which produces such
 frequency with used PLL input clock.


Yes, I was talking about same cases. Perhaps,I think it holds true in general
for PLLs, whose set_rate can be called.

  I think we should ask some H/W engineer about that to make sure and choose
  the proper implementation, which will work properly for future cases,
  instead of ending with something that works just with current cases.

 We already asked hardware engineer about PMS values for PLL,
 and we got a table containing recommended  P, M ,S values for a given
 f_in(24 MHz)
 and required f_out rates.

 This doesn't answer the question about using those PMS values with different
 input rate.

 Kukjin, maybe you can give some information on this or point to a person who
 could?

 Please let me know, why you think we are specific to current cases only ?

 I don't like the idea of having separate tables for each input rate. Just
 imagine how much data would have to be added if boards with several different
 input rates showed up.


I think by declaring all these different table as __init,
and creating a copy to be used while registering, we can
save a little memory as well as the unnecessary cost which
we have to bear while doing set_rate() and round_rate

Re: [PATCH v2 2/5] clk: samsung: Add support to register rate_table for PLL3xxx

2013-06-04 Thread Yadwinder Singh Brar
Hi Tomasz,

On Mon, Jun 3, 2013 at 8:55 PM, Tomasz Figa t.f...@samsung.com wrote:
 Hi Yadwinder,

 On Thursday 30 of May 2013 12:25:40 Yadwinder Singh Brar wrote:
 Hi Doug,

 On Thu, May 30, 2013 at 5:14 AM, Doug Anderson diand...@chromium.org
 wrote:
  Vikas / Yadwinder,
 
  On Wed, May 29, 2013 at 6:37 AM, Vikas Sajjan vikas.saj...@linaro.org
 wrote:
  From: Yadwinder Singh Brar yadi.b...@samsung.com
 
  This patch defines a common rate_table which will contain recommended p,
  m, s, k values for supported rates that needs to be changed for changing
  corresponding PLL's rate.
 
  Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
  ---
 
   drivers/clk/samsung/clk-exynos4.c|8 
   drivers/clk/samsung/clk-exynos5250.c |   14 +++---
   drivers/clk/samsung/clk-pll.c|   14 --
   drivers/clk/samsung/clk-pll.h|   33
   +++-- 4 files changed, 54 insertions(+), 15
   deletions(-)
 
  I also reviewed this in our gerrit
  https://gerrit.chromium.org/gerrit/#/c/56742/, but I'll summarize
  here for the list...
 
   struct clk * __init samsung_clk_register_pll35xx(const char *name,
 
  -   const char *pname, const void __iomem *base)
  +   const char *pname, const void __iomem *base,
  +   const struct samsung_pll_rate_table *rate_table,
  +   const unsigned int rate_count)
 
  Feels like you should document here that rate_table needs to be sorted
  and the sort order.

 sure,  we will add comment  to sort the table in descending order.

  +struct samsung_pll_rate_table {
  +   unsigned  int rate;
 
  nit: extra space before int should be removed.

 ok

  Also: you can include rate here if you need a convenient place to
  store it (which sadly means that this structure can't be const).
  ...but I do like Tomasz's idea of actually calculating it.  You can't
  know it at compile time since the parent rate comes from the device
  tree.
 
  compatible = samsung,clock-xxti;
  clock-frequency = 2400;

 Actually this table should contain the recommended values
 and if we see the user manual, the input(parent) rate is also a part
 of recommended
 table of different output rate for a particular PLL for that SoC.

 From what I understood in the documentation is that there is a set of
 recommended P, M, S (, K) tuples for each PLL and they are not dependent on
 input frequency - f_in and f_out are provided in the table just for reference
 to see the relation between output frequency and input frequency.


If input rate(f_in) gets changed for PLL, then the corresponding
output rates(f_out)
will change by using same(common) set of  recommended P, M, S (, K),
and the new set of  output rates(f_out) may not be the _required_ set
of target rates.
So we need different set of P, M, S (,K) values for different f_in.

Table should contain set of P, M, S (,K) values for the _required_
target(f_out) rates
for a particular input(f_in) rate.

 I think we should ask some H/W engineer about that to make sure and choose the
 proper implementation, which will work properly for future cases, instead of
 ending with something that works just with current cases.


We already asked hardware engineer about PMS values for PLL,
and we got a table containing recommended  P, M ,S values for a given
f_in(24 MHz)
and required f_out rates.

Please let me know, why you think we are specific to current cases only ?

Regards,
Yadwinder

 Best regards,
 --
 Tomasz Figa
 Linux Kernel Developer
 Samsung RD Institute Poland
 Samsung Electronics

 So as Tomasz said input(parent) rate may change with board,
 then, do those corresponding recommended p, m, s, k will be valid?

 In case, input(parent) rate changes then we may need different set of p, m
 ,s, k values recommended for new input rate to get required(recommended to
 use) output rate.

 So, we think its better that the p, m, s and k along with the parent
 is known at the compile time ( or DT ?),
 as these p, m, s, k values are very much coupled with the parent rate
 to achieve the
  required(recommended to use) output rate.

 Also, since the sorted table is required (sorted based on rate),
 its better to have the rate in a const rate table.

 And the whole set of recommended values should come from same place(DT
 or static table),
 to keep the things simple and consistent.

 Moreover, practically for a particular SoC , we use the recommended
 input(parent) rate only for a PLL.
 So we should keep the things simple here presently.

  +   unsigned int pdiv;
  +   unsigned int mdiv;
  +   unsigned int sdiv;
  +   unsigned int kdiv;
 
  I think kdiv is signed.

 No, as these values should be the recommended values to be written in
 corresponding  register bits. So it should remain unsigned.

 K value should be considered as negative only while recalculating rate.

 As per exynos5250 user manual's section 7.3.2 :
  K value

Re: [RESEND PATCH 2/5] clk: samsung: Add support to register rate_table for PLL3xxx

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

On Sat, May 25, 2013 at 3:34 AM, Tomasz Figa tomasz.f...@gmail.com wrote:
 Hi,

 Please see my comments inline.

 On Friday 24 of May 2013 16:01:15 Vikas Sajjan wrote:
 From: Yadwinder Singh Brar yadi.b...@samsung.com

 This patch defines a common rate_table which will contain recommended p,
 m, s and k values for supported rates that needs to be changed for
 changing corresponding PLL's rate.
 It also sorts the rate table while registering the PLL rate table.
 So that this sorted table can be used for making the searching of
 required rate efficient.

 Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
 ---
  drivers/clk/samsung/clk-exynos4.c|8 
  drivers/clk/samsung/clk-exynos5250.c |   14 +++---
  drivers/clk/samsung/clk-pll.c|   35
 -- drivers/clk/samsung/clk-pll.h
 |   27 -- 4 files changed, 69 insertions(+), 15
 deletions(-)

 diff --git a/drivers/clk/samsung/clk-exynos4.c
 b/drivers/clk/samsung/clk-exynos4.c index cf7d4e7..beff8a1 100644
 --- a/drivers/clk/samsung/clk-exynos4.c
 +++ b/drivers/clk/samsung/clk-exynos4.c
 @@ -1021,13 +1021,13 @@ void __init exynos4_clk_init(struct device_node
 *np, enum exynos4_soc exynos4_so reg_base + VPLL_CON0, pll_4650c);
   } else {
   apll = samsung_clk_register_pll35xx(fout_apll,
 fin_pll,
 - reg_base + APLL_LOCK);
 + reg_base + APLL_LOCK, NULL, 0);
   mpll = samsung_clk_register_pll35xx(fout_mpll,
 fin_pll,
 - reg_base + E4X12_MPLL_LOCK);
 + reg_base + E4X12_MPLL_LOCK, NULL,
 0);
   epll = samsung_clk_register_pll36xx(fout_epll,
 fin_pll,
 - reg_base + EPLL_LOCK);
 + reg_base + EPLL_LOCK, NULL, 0);
   vpll = samsung_clk_register_pll36xx(fout_vpll,
 fin_pll,
 - reg_base + VPLL_LOCK);
 + reg_base + VPLL_LOCK, NULL, 0);
   }

   samsung_clk_add_lookup(apll, fout_apll);
 diff --git a/drivers/clk/samsung/clk-exynos5250.c
 b/drivers/clk/samsung/clk-exynos5250.c index 687b580..ddf10ca 100644
 --- a/drivers/clk/samsung/clk-exynos5250.c
 +++ b/drivers/clk/samsung/clk-exynos5250.c
 @@ -491,19 +491,19 @@ void __init exynos5250_clk_init(struct device_node
 *np) ext_clk_match);

   apll = samsung_clk_register_pll35xx(fout_apll, fin_pll,
 - reg_base);
 + reg_base, NULL, 0);
   mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll,
 - reg_base + 0x4000);
 + reg_base + 0x4000, NULL, 0);
   bpll = samsung_clk_register_pll35xx(fout_bpll, fin_pll,
 - reg_base + 0x20010);
 + reg_base + 0x20010, NULL, 0);
   gpll = samsung_clk_register_pll35xx(fout_gpll, fin_pll,
 - reg_base + 0x10050);
 + reg_base + 0x10050, NULL, 0);
   cpll = samsung_clk_register_pll35xx(fout_cpll, fin_pll,
 - reg_base + 0x10020);
 + reg_base + 0x10020, NULL, 0);
   epll = samsung_clk_register_pll36xx(fout_epll, fin_pll,
 - reg_base + 0x10030);
 + reg_base + 0x10030, NULL, 0);
   vpll = samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc,
 - reg_base + 0x10040);
 + reg_base + 0x10040, NULL, 0);

   samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
   ARRAY_SIZE(exynos5250_fixed_rate_clks));
 diff --git a/drivers/clk/samsung/clk-pll.c
 b/drivers/clk/samsung/clk-pll.c index 01f17cf..b8c0260 100644
 --- a/drivers/clk/samsung/clk-pll.c
 +++ b/drivers/clk/samsung/clk-pll.c
 @@ -10,12 +10,15 @@
  */

  #include linux/errno.h
 +#include linux/sort.h
  #include clk.h
  #include clk-pll.h

  struct samsung_clk_pll {
   struct clk_hw   hw;
   const void __iomem  *base;
 + struct samsung_pll_rate_table *rate_table;
 + unsigned int rate_count;
  };

  #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
 @@ -25,6 +28,14 @@ struct samsung_clk_pll {
  #define pll_writel(pll, val, offset) \
   __raw_writel(val, (void __iomem *)(pll-base + (offset)));

 +static int samsung_compare_rate(const void *_a, const void *_b)
 +{
 + const struct samsung_pll_rate_table *a = _a;
 + const struct samsung_pll_rate_table *b = _b;
 +
 + return a-rate - b-rate;
 +}
 +
  /*
   * PLL35xx Clock Type
   */
 @@ -62,7 +73,9 @@ static const struct clk_ops samsung_pll35xx_clk_ops =
 { };

  struct clk * __init samsung_clk_register_pll35xx(const char *name,
 - const char *pname, const void __iomem *base)
 + const char *pname

Re: [RESEND PATCH 3/5] clk: samsung: Add set_rate() clk_ops for PLL35xx

2013-05-27 Thread Yadwinder Singh Brar
On Sat, May 25, 2013 at 3:49 AM, Tomasz Figa tomasz.f...@gmail.com wrote:
 Hi,

 On Friday 24 of May 2013 16:01:16 Vikas Sajjan wrote:
 From: Yadwinder Singh Brar yadi.b...@samsung.com

 Adds set_rate() and round_rate() clk_ops for PLL35xx

 The round_rate() implemenation as of now is dummy, it returns the same
 rate which is passed as input.

 Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
 ---
  drivers/clk/samsung/clk-pll.c |   95
 - 1 file changed, 94
 insertions(+), 1 deletion(-)

 diff --git a/drivers/clk/samsung/clk-pll.c
 b/drivers/clk/samsung/clk-pll.c index b8c0260..291cc9e 100644
 --- a/drivers/clk/samsung/clk-pll.c
 +++ b/drivers/clk/samsung/clk-pll.c
 @@ -11,6 +11,7 @@

  #include linux/errno.h
  #include linux/sort.h
 +#include linux/bsearch.h
  #include clk.h
  #include clk-pll.h

 @@ -36,6 +37,21 @@ static int samsung_compare_rate(const void *_a, const
 void *_b) return a-rate - b-rate;
  }

 +static struct samsung_pll_rate_table *samsung_get_pll_settings(
 + struct samsung_clk_pll *pll, unsigned long
 rate)
 +{
 + struct samsung_pll_rate_table req_rate, *tmp;
 +
 + req_rate.rate = rate;
 + tmp = bsearch(req_rate, pll-rate_table, pll-rate_count,
 + sizeof(struct samsung_pll_rate_table),
 + samsung_compare_rate);

 Binary search over  10 entries? Isn't it a bit of overkill?


Sorry, i couldn't see any over kill?  And it may NOT be always  10.

 + if (tmp)
 + return tmp;
 +
 + return NULL;
 +}
 +
  /*
   * PLL35xx Clock Type
   */
 @@ -46,9 +62,15 @@ static int samsung_compare_rate(const void *_a, const
 void *_b) #define PLL35XX_MDIV_MASK   (0x3FF)
  #define PLL35XX_PDIV_MASK   (0x3F)
  #define PLL35XX_SDIV_MASK   (0x7)
 +#define PLL35XX_LOCK_STAT_MASK  (0x1)
  #define PLL35XX_MDIV_SHIFT  (16)
  #define PLL35XX_PDIV_SHIFT  (8)
  #define PLL35XX_SDIV_SHIFT  (0)
 +#define PLL35XX_LOCK_STAT_SHIFT (29)
 +
 +#define PLL35XX_MDIV(_tmp) ((_tmp)  (PLL35XX_MDIV_MASK 
 PLL35XX_MDIV_SHIFT)) +#define PLL35XX_PDIV(_tmp) ((_tmp) 
 (PLL35XX_PDIV_MASK  PLL35XX_PDIV_SHIFT)) +#define PLL35XX_SDIV(_tmp)
 ((_tmp)  (PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT))

  static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
   unsigned long parent_rate)
 @@ -68,8 +90,76 @@ static unsigned long
 samsung_pll35xx_recalc_rate(struct clk_hw *hw, return (unsigned
 long)fvco;
  }

 -static const struct clk_ops samsung_pll35xx_clk_ops = {
 +static inline bool samsung_pll35xx_mp_change(u32 mdiv, u32 pdiv, u32
 pll_con) +{
 + if ((mdiv != PLL35XX_MDIV(pll_con)) || (pdiv !=
 PLL35XX_PDIV(pll_con))) + return 1;
 + else
 + return 0;
 +}
 +
 +static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long
 drate, +  unsigned long prate)
 +{
 + struct samsung_clk_pll *pll = to_clk_pll(hw);
 + struct samsung_pll_rate_table *rate;
 +
 + u32 tmp, mdiv, pdiv, sdiv;
 +
 + /* Get required rate settings from table */
 + rate = samsung_get_pll_settings(pll, drate);
 + if (!rate) {
 + pr_err(%s: Invalid rate : %lu for pll clk %s\n,
 __func__,
 + drate, __clk_get_name(hw-clk));
 + return -EINVAL;
 + }
 +
 + mdiv = PLL35XX_MDIV(rate-pll_con0);
 + pdiv = PLL35XX_PDIV(rate-pll_con0);
 + sdiv = PLL35XX_SDIV(rate-pll_con0);

 You wouldn't need to use those macros if all coefficients were stored as
 separate fields in the struct.


Agree, I will use that.

 +
 + tmp = pll_readl(pll, PLL35XX_CON0_OFFSET);
 +
 + if (!(samsung_pll35xx_mp_change(mdiv, pdiv, tmp))) {
 + /* If only s change, change just s value only*/
 + tmp = ~(PLL35XX_SDIV_MASK  PLL35XX_SDIV_SHIFT);
 + tmp |= sdiv;

 This line is correct, but it looks like it wasn't, because:
 a) the name suggests that it contains the raw value of S coefficient
 b) it's real value is hidden between a macro, name of which suggests the
 same as in a) as well.

 This makes the code hard to read.


We can rename sdiv to sdiv_regval ?? , to improve readability.

 + pll_writel(pll, tmp, PLL35XX_CON0_OFFSET);
 + } else {
 + /* Set PLL lock time.
 +Maximum lock time can be 270 * PDIV cycles */
 + pll_writel(pll, (pdiv  PLL35XX_PDIV_SHIFT) * 270,
 + PLL35XX_LOCK_OFFSET);

 Hmm, magic constant in the code? Shouldn't it be defined as a macro?


Ya, I will define it.

 +
 + /* Change PLL PMS values */
 + tmp = ~((PLL35XX_MDIV_MASK  PLL35XX_MDIV_SHIFT) |
 + (PLL35XX_PDIV_MASK  PLL35XX_PDIV_SHIFT)
 |
 + (PLL35XX_SDIV_MASK 
 PLL35XX_SDIV_SHIFT));
 + tmp |= mdiv | pdiv | sdiv;

 This looks strange as well, even if it's correct

[PATCH] regulator: Add ramp_delay to regulator constraints to get used as a configurable parameter.

2012-06-11 Thread Yadwinder Singh Brar
For some hardwares ramp_delay for BUCKs is a configurable parameter which can
be configured through DT or board file.This patch adds ramp_delay to regulator
constraints and allow user to configure it for regulators which supports this
feature, through DT or board file. It will provide two ways of setting the
ramp_delay for a regulator:
First, by setting it as constraints in board file(for configurable
regulators) and set_machine_constraints() will take care of setting it on
hardware by calling(the provided) .set_ramp_delay() operation(callback).
Second, by setting it as data in regulator_desc(as fixed/default
ramp_delay rate) for a regulator in driver.

regulator_set_voltage_time_sel() will give preference to
constraints-ramp_delay while reading ramp_delay rate for regulator. Similarly
users should also take care accordingly while refering ramp_delay rate(in case
of implementing their private .set_voltage_time_sel() callbacks for different
regulators).

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

diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt 
b/Documentation/devicetree/bindings/regulator/regulator.txt
index 5b7a408..d0a7b12 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/regulator.txt
@@ -10,6 +10,7 @@ Optional properties:
 - regulator-always-on: boolean, regulator should never be disabled
 - regulator-boot-on: bootloader/firmware enabled regulator
 - name-supply: phandle to the parent supply/regulator node
+- regulator-ramp-delay: ramp delay for regulator(in mV/uS)
 
 Example:
 
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 63507a5..0ffd917 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -967,6 +967,14 @@ static int set_machine_constraints(struct regulator_dev 
*rdev,
}
}
 
+   if (rdev-constraints-ramp_delay  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);
+   goto out;
+   }
+   }
+
print_constraints(rdev);
return 0;
 out:
@@ -2305,10 +2313,17 @@ int regulator_set_voltage_time_sel(struct regulator_dev 
*rdev,
   unsigned int old_selector,
   unsigned int new_selector)
 {
-   if (rdev-desc-ramp_delay  rdev-desc-uV_step)
-   return DIV_ROUND_UP(rdev-desc-uV_step *
-   abs(new_selector - old_selector),
-   rdev-desc-ramp_delay * 1000);
+   if (rdev-desc-uV_step) {
+   if (rdev-constraints-ramp_delay)
+   return DIV_ROUND_UP(rdev-desc-uV_step *
+   abs(new_selector - old_selector),
+   rdev-constraints-ramp_delay * 1000);
+   if (rdev-desc-ramp_delay)
+   return DIV_ROUND_UP(rdev-desc-uV_step *
+   abs(new_selector - old_selector),
+   rdev-desc-ramp_delay * 1000);
+   rdev_warn(rdev, ramp_delay not set\n);
+   }
return 0;
 }
 
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 56593b7..e2a7310 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -20,7 +20,7 @@ static void of_get_regulation_constraints(struct device_node 
*np,
struct regulator_init_data **init_data)
 {
const __be32 *min_uV, *max_uV, *uV_offset;
-   const __be32 *min_uA, *max_uA;
+   const __be32 *min_uA, *max_uA, *ramp_delay;
struct regulation_constraints *constraints = (*init_data)-constraints;
 
constraints-name = of_get_property(np, regulator-name, NULL);
@@ -60,6 +60,10 @@ static void of_get_regulation_constraints(struct device_node 
*np,
constraints-always_on = true;
else /* status change should be possible if not always on. */
constraints-valid_ops_mask |= REGULATOR_CHANGE_STATUS;
+
+   ramp_delay = of_get_property(np, regulator-ramp-delay, NULL);
+   if (ramp_delay)
+   constraints-min_uV = be32_to_cpu(*ramp_delay);
 }
 
 /**
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index ae5c253..ddc155d 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -67,6 +67,8 @@ enum

Re: [PATCH v3 2/2] regulator: Add support for MAX77686.

2012-05-23 Thread Yadwinder Singh Brar
On Wed, May 23, 2012 at 9:46 AM, Yadwinder Singh Brar
yadi.bra...@gmail.com wrote:
 (adding Kyungmin Park and Samuel Ortiz)

 Hi,

 Yes, It happened unintentionally. I didn't know about your patch
 before submitting
 the initial version of my patches. I agree with you, I will review
 your patches and
 will try to incorporate extra features from your patches.


Now I have seen your patches for mfd and regulator drivers.
Apparently, it seems that mostly we same features in our patches.
Their is no extra feature to be incorporated form your patches.
Rather I found device tree support is additional in our patches
and mainly their are some differences related to DVS_GPIO and
opmode stuff in our patches:
1- Since we are not implementing and using DVS feature
through GPIOs, so all(incomplete) stuff related to dvs_gpio
is not required currently in our mfd driver presently.
2- Since presently, we are not implementing suspend_enable/disable
callbacks in regulator driver, So we don't need opmode related
stuff now because I think regulators should come up in normal mode
only through .enable callback function.

 On Wed, May 23, 2012 at 7:10 AM,  jonghwa3@samsung.com wrote:
 Hi, Yadwinder,
 As you know, both of us, recently, had competition for one driver
 whether you intend or not. And now, i think it is time to stop this and
 to find appropriate goal. From now on, i won't update this driver no
 more. I recommend you to review my patch and apply feature that you can
 apply. And also check comments that i wrote below.


Thanks,
Yadwinder.
--
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


Re: [PATCH v3 1/2] mfd: Add support for MAX77686.

2012-05-22 Thread Yadwinder Singh Brar
CC' ing to maintainer.
(I forget to add maintainer in cc, sorry for noise).

On Tue, May 22, 2012 at 11:26 AM,  yadi.bra...@gmail.com wrote:
 From: Yadwinder Singh Brar yadi.b...@samsung.com

 MAX77686 is a mulitifunction device with PMIC, RTC and Charger on chip. Th
 driver provides common support for accessing the device. This is initial
 version of this driver that supports to enable the chip with its primary I
 bus.It also includes IRQ and device tree support for MAX77686 chip.

 Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
 Reviewed-by: Mark Brown broo...@opensource.wolfsonmicro.com
 ---
  Documentation/devicetree/bindings/mfd/max77686.txt |   61 
  drivers/mfd/Kconfig                                |   21 ++
  drivers/mfd/Makefile                               |    1 +
  drivers/mfd/max77686-irq.c                         |  255 
  drivers/mfd/max77686.c                             |  322 
 
  include/linux/mfd/max77686-private.h               |  282 +
  include/linux/mfd/max77686.h                       |  100 ++
  7 files changed, 1042 insertions(+), 0 deletions(-)
  create mode 100644 Documentation/devicetree/bindings/mfd/max77686.txt
  create mode 100644 drivers/mfd/max77686-irq.c
  create mode 100644 drivers/mfd/max77686.c
  create mode 100644 include/linux/mfd/max77686-private.h
  create mode 100644 include/linux/mfd/max77686.h

 diff --git a/Documentation/devicetree/bindings/mfd/max77686.txt 
 b/Documentation/devicetree/bindings/mfd/max77686.txt
 new file mode 100644
 index 000..78a47bd
 --- /dev/null
 +++ b/Documentation/devicetree/bindings/mfd/max77686.txt
 @@ -0,0 +1,61 @@
 +Maxim MAX77686 multi-function device
 +
 +MAX77686 is a Mulitifunction device with PMIC, RTC and Charger on chip. It is
 +interfaced to host controller using i2c interface. PMIC and Charger 
 submodules
 +are addressed using same i2c slave address where as RTC submodule uses
 +different slave address,presently for which we are statically creating i2c
 +client while probing.This document describes the binding for mfd device and
 +PMIC submodule.
 +
 +Required properties:
 +- compatible : Must be maxim,max77686;
 +- reg : Specifiec the i2c slave address of PMIC block.
 +- interrupts : This i2c device has an IRQ line connected to the main SoC.
 +- interrupt-parent : The parent interrupt controller.
 +
 +Optional node:
 +- max77686,buck_ramp_delay : Ramp delay to be setup for buck2,34.
 +
 +- voltage-regulators : The regulators of max77686 have to be instantiated
 +  under subnode named voltage-regulators uing the following format.
 +
 +       regulator_name {
 +               standard regulator constraints
 +       };
 +       refer Documentation/devicetree/bindings/regulator/regulator.txt
 +
 +  The names of regulator should be as follow:
 +
 +       -LDOn   :       for LDOs, where n can lie in range 1 to 26.
 +                       example: LDO1, LDO2, LDO26.
 +       -BUCKn  :       for BUCKs, where n can lie in range 1 to 9.
 +                       example: BUCK1, BUCK5, BUCK9.
 +
 +
 +Example:
 +
 +       max77686_pmic@09 {
 +               compatible = maxim,max77686;
 +               interrupt-parent = wakeup_eint;
 +               interrupts = 26 0;
 +               reg = 0x09;
 +
 +               max77686,buck_ramp_delay = 2;         /* default */
 +
 +               voltage-regulators {
 +                       ldo11_reg: LDO11 {
 +                               regulator-name = vdd_ldo11;
 +                               regulator-min-microvolt = 190;
 +                               regulator-max-microvolt = 190;
 +                               regulator-always-on;
 +                       };
 +
 +                       buck1_reg: BUCK1 {
 +                               regulator-name = vdd_mif;
 +                               regulator-min-microvolt = 95;
 +                               regulator-max-microvolt = 130;
 +                               regulator-always-on;
 +                               regulator-boot-on;
 +                       };
 +       }
 +
 diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
 index a4fd173..d8285e5 100644
 --- a/drivers/mfd/Kconfig
 +++ b/drivers/mfd/Kconfig
 @@ -442,6 +442,27 @@ config MFD_MAX8998
          additional drivers must be enabled in order to use the functionality
          of the device.

 +config MFD_MAX77686
 +       bool Maxim Semiconductor MAX77686 PMIC Support
 +       depends on I2C=y  GENERIC_HARDIRQS
 +       select MFD_CORE
 +       select REGMAP_I2C
 +       help
 +         Say yes here to support for Maxim Semiconductor MAX77686.
 +         This is a Power Management IC with RTC on chip.
 +         This driver provides common support for accessing the device;
 +         additional drivers must be enabled in order to use the functionality
 +         of the device.
 +
 +config DEBUG_MAX77686
 +       bool MAX77686 PMIC debugging
 +       depends

Re: [PATCH v3 2/2] regulator: Add support for MAX77686.

2012-05-22 Thread Yadwinder Singh Brar
(adding Kyungmin Park and Samuel Ortiz)

Hi,

Yes, It happened unintentionally. I didn't know about your patch
before submitting
the initial version of my patches. I agree with you, I will review
your patches and
will try to incorporate extra features from your patches.

On Wed, May 23, 2012 at 7:10 AM,  jonghwa3@samsung.com wrote:
 Hi, Yadwinder,
 As you know, both of us, recently, had competition for one driver
 whether you intend or not. And now, i think it is time to stop this and
 to find appropriate goal. From now on, i won't update this driver no
 more. I recommend you to review my patch and apply feature that you can
 apply. And also check comments that i wrote below.

 On 2012년 05월 22일 14:57, yadi.bra...@gmail.com wrote:

 From: Yadwinder Singh Brar yadi.b...@samsung.com

 Add support for PMIC/regulator portion of MAX77686 multifunction device.
 MAX77686 provides LDOs[1-26] and BUCKs[1-9]. This is initial release of driv
 which supports setting and getting the voltage of a regulator with I2C
 interface.

 +     return DIV_ROUND_UP(rdev-desc-uV_step *
 +                         abs(new_sel - old_sel),
 +                         100);
 +}
 +


 Does LDO also need waiting for voltage change? I afraid it's not.


Yes, according to technical reference manual which I have, ramp rate for
LDOs is also 100mV/us.

 +
 +     if (pdata-ramp_delay  MAX77686_RAMP_RATE_13MV ||
 +             pdata-ramp_delay  MAX77686_RAMP_RATE_100MV)
 +             pdata-ramp_delay = MAX77686_RAMP_RATE_27MV;    /* default */

If pdata doesn't have proper ramp_delay, it will get value
MAX77686_RAMP_RATE_27MV.

 +
 +     max77686-ramp_delay = pdata-ramp_delay - 1;


 I think it is better to check pdata-ramp_delay is available.
 If pdata doesn't have ramp_delay member it might be error.


Yes, we have taken care of this case above before setting value of
max77686-ramp_delay.

 +     max77686_update_reg(i2c, MAX77686_REG_BUCK2CTRL1,
 +             max77686-ramp_delay  6, RAMP_MASK);
 +     max77686_update_reg(i2c, MAX77686_REG_BUCK3CTRL1,
 +             max77686-ramp_delay  6, RAMP_MASK);
 +     max77686_update_reg(i2c, MAX77686_REG_BUCK4CTRL1,
 +             max77686-ramp_delay  6, RAMP_MASK);
 +


 Why do you use i2c client still? If you registered regmap you can use
 its API. I recommend you to use regmap_update_bits() directly.



Yes, we are using regmap_update_bits().  max77686_update_reg() is just
a wrapper over it.

 +     platform_set_drvdata(pdev, max77686);
 +


 MAX77686 has crystal oscillator in it. And original version of this
 driver which was written by Chiwoon Byun, registers it as a regulator.
 As Mark says, we have to change it to use generic clock API. Where do
 you think should we put them into? In my opinion, it is proper that just
 leave them in regulator driver because this driver is almost core of
 PMIC. I already applied generic API in my local repository but i
 couldn't test yet. Because it crashed with SOC's private clock API.
 Anyway if you register 32khz clock with generic API ,DEFINE_CLK_GATE()
 will help you out which defined in linux/clk-private.h.


Yes, I was also thinking about where to put it. I am not sure whether this
is a proper place to put them. Anyway I will again think about it.

Thanks,
Yadwinder.
--
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


Re: [PATCH v3 2/2] regulator: Add support for MAX77686.

2012-05-22 Thread Yadwinder Singh Brar
Hi,

On Wed, May 23, 2012 at 7:20 AM,  jonghwa3@samsung.com wrote:
 Hi, again.
 On 2012년 05월 22일 14:57, yadi.bra...@gmail.com wrote:


 +static __devinit int max77686_pmic_probe(struct platform_device *pdev)
 +{

 +
 +     for (i = 0; i  pdata-num_regulators; i++) {
 +             config.dev = max77686-dev;
 +             config.init_data = pdata-regulators[i].init_data;
 +             config.driver_data = max77686;
 +             config.regmap = iodev-regmap;
 +
 +             rdev[i] = regulator_register(regulators[i], config);


 I'm sorry that i missed one. You have to register all regulators
 unconditionally. Mark brown commented about this to my former patch.

 'No, you should unconditionally register all regulators the device
 physically has.  This is useful for debug and simplifies the code.'
                                                - from Mark Brown


Yes, we are registering all regulators here.
As pdata-num_regulators will be equal to ARRAY_SIZE(regulators)

Thanks,
Yadwinder.
--
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


Re: [PATCH v3 2/2] regulator: Add support for MAX77686.

2012-05-22 Thread Yadwinder Singh Brar
On Wed, May 23, 2012 at 10:10 AM,  jonghwa3@samsung.com wrote:
 On 2012년 05월 23일 13:16, Yadwinder Singh Brar wrote:

 +     max77686_update_reg(i2c, MAX77686_REG_BUCK2CTRL1,
 +             max77686-ramp_delay  6, RAMP_MASK);
 +     max77686_update_reg(i2c, MAX77686_REG_BUCK3CTRL1,
 +             max77686-ramp_delay  6, RAMP_MASK);
 +     max77686_update_reg(i2c, MAX77686_REG_BUCK4CTRL1,
 +             max77686-ramp_delay  6, RAMP_MASK);
 +


 Why do you use i2c client still? If you registered regmap you can use
 its API. I recommend you to use regmap_update_bits() directly.



 Yes, we are using regmap_update_bits().  max77686_update_reg() is just
 a wrapper over it.



 Yes, i know what you mean. However it doesn't need max77686_update_reg()
 any more since it uses regmap API. Why don't you just pass iodev-regmap
 to regmap_update_bits(). It is clear that there is no reason for using
 i2c client as a medium. Please check regulator and mfd driver of my
 previous patch.


I agree with you we can use directly  regmap API. But I preferred
max77686_update_reg() because its a common practice to use
common read/write API which we define in mfd driver to access
that particular mfd device from other drivers.

Regards,
Yadwinder.
--
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


Re: [PATCH v2 2/2] regulator: Add support for MAX77686.

2012-05-21 Thread Yadwinder Singh Brar
Hi Mark,

On Sun, May 20, 2012 at 3:30 PM, Mark Brown
broo...@opensource.wolfsonmicro.com wrote:
 On Thu, May 17, 2012 at 07:09:27PM +0530, Yadwinder Singh Brar wrote:

 Looks mostly good.  A couple of fairly small things:

 +static int max77686_get_voltage_sel(struct regulator_dev *rdev)
 +{

 This looks like it should be regulator_get_voltage_sel_regmap().

 +static int max77686_set_voltage_sel(struct regulator_dev *rdev,
 +                                     unsigned sel)
 +{

 This looks like it should be regulator_set_voltage_sel_regmap().


Yes, We can use  regulator_set_voltage_sel_regmap(), I will replace it.

 +     max77686-ramp_delay = pdata-ramp_delay - 1;
 +     max77686_update_reg(i2c, MAX77686_REG_BUCK2CTRL1,
 +             RAMP_VALUE, RAMP_MASK);
 +     max77686_update_reg(i2c, MAX77686_REG_BUCK3CTRL1,
 +             RAMP_VALUE, RAMP_MASK);
 +     max77686_update_reg(i2c, MAX77686_REG_BUCK4CTRL1,
 +             RAMP_VALUE, RAMP_MASK);

 This code is unclear because RAMP_VALUE looks like a constant that has
 nothing to do with ramp_delay when in fact it's actually this:

 +#define RAMP_VALUE (max77686-ramp_delay  6)

 which isn't constant - this is why I queried this last time.  Just
 remove the define and write this out directly.  The way the code is
 written at the minute it looks like ramp_delay is just stored and not
 referred to unless you go searching around the rest of the driver.

Ok, I will remove it.

Thanks,
Yadwinder.
--
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


[PATCH v2 0/2] regulator: Add initial suport for max77686

2012-05-17 Thread Yadwinder Singh Brar
This patch series adds support for max77686 which is a multifunction device 
which
includes regulator (pmic), rtc and charger sub-blocks within it. The support for
mfd driver and regulator driver are added by this patch series. This patch 
series
also includes device tree and irqdomain support for mfd and regulator portions.

Implemented the required modification, stated in the recieved review comments.
changes since V1:
-added regmap support.
-implemented .get_voltage_sel, .set_voltage_sel and .set_voltage_time_sel after
 removing .get_voltage and .set_voltage in regulator driver.
-used of_regulator_match() for parsing DT.
-added Documentation for Devive Tree binding.

This patch series is based on mark_regulator/for-next and has been tested on
GAIA board.

Yadwinder Singh Brar (2):
  mfd: Add support for MAX77686.
  regulator: Add support for MAX77686.

 Documentation/devicetree/bindings/mfd/max77686.txt |   63 +++
 drivers/mfd/Kconfig|   21 +
 drivers/mfd/Makefile   |1 +
 drivers/mfd/max77686-irq.c |  255 ++
 drivers/mfd/max77686.c |  322 
 drivers/regulator/Kconfig  |9 +
 drivers/regulator/Makefile |1 +
 drivers/regulator/max77686.c   |  512 
 include/linux/mfd/max77686-private.h   |  282 +++
 include/linux/mfd/max77686.h   |  100 
 10 files changed, 1566 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/max77686.txt
 create mode 100644 drivers/mfd/max77686-irq.c
 create mode 100644 drivers/mfd/max77686.c
 create mode 100644 drivers/regulator/max77686.c
 create mode 100644 include/linux/mfd/max77686-private.h
 create mode 100644 include/linux/mfd/max77686.h

--
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


[PATCH v2 2/2] regulator: Add support for MAX77686.

2012-05-17 Thread Yadwinder Singh Brar
Add support for PMIC/regulator portion of MAX77686 multifunction device.
MAX77686 provides LDOs[1-26] and BUCKs[1-9]. This is initial release of driver
which supports setting and getting the voltage of a regulator with I2C
interface.

Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com
---
 drivers/regulator/Kconfig|9 +
 drivers/regulator/Makefile   |1 +
 drivers/regulator/max77686.c |  512 ++
 3 files changed, 522 insertions(+), 0 deletions(-)
 create mode 100644 drivers/regulator/max77686.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 4ad4e8d..a41d2cf 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -195,6 +195,15 @@ config REGULATOR_MAX8998
  via I2C bus. The provided regulator is suitable for S3C6410
  and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
 
+config REGULATOR_MAX77686
+   tristate Maxim 77686 regulator
+   depends on MFD_MAX77686
+   help
+ This driver controls a Maxim 77686 voltage regulator via I2C
+ bus. The provided regulator is suitable for Exynos5 chips to
+ control VDD_ARM and VDD_INT voltages.It supports LDOs[1-26]
+ and BUCKs[1-9].
+
 config REGULATOR_PCAP
tristate Motorola PCAP2 regulator driver
depends on EZX_PCAP
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index dcc56dc..949b1f2 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
 obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
 obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
+obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
 obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
new file mode 100644
index 000..7379c29
--- /dev/null
+++ b/drivers/regulator/max77686.c
@@ -0,0 +1,512 @@
+/*
+ * max77686.c - Regulator driver for the Maxim 77686
+ *
+ * Copyright (C) 2012 Samsung Electronics Co. Ltd.
+ * Chiwoong Byun woong.b...@samsung.com
+ * Yadwinder Singh Brar yadi.b...@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 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
+ *
+ * This driver is based on max8997.c
+ */
+
+#include linux/module.h
+#include linux/bug.h
+#include linux/delay.h
+#include linux/err.h
+#include linux/gpio.h
+#include linux/slab.h
+#include linux/platform_device.h
+#include linux/regulator/driver.h
+#include linux/regulator/machine.h
+#include linux/regulator/of_regulator.h
+#include linux/mfd/max77686.h
+#include linux/mfd/max77686-private.h
+
+#define RAMP_VALUE (max77686-ramp_delay  6)
+
+struct max77686_data {
+   struct device *dev;
+   struct max77686_dev *iodev;
+   int num_regulators;
+   struct regulator_dev **rdev;
+   int ramp_delay; /* index of ramp_delay */
+
+   /*GPIO-DVS feature is not enabled with the
+*current version of MAX77686 driver.*/
+};
+
+static int max77686_get_enable_register(struct regulator_dev *rdev,
+   int *reg, int *mask, int *pattern)
+{
+   int rid = rdev_get_id(rdev);
+
+   switch (rid) {
+   case MAX77686_LDO1...MAX77686_LDO26:
+   *reg = MAX77686_REG_LDO1CTRL1 + (rid - MAX77686_LDO1);
+   *mask = 0xc0;
+   *pattern = 0xc0;
+   break;
+   case MAX77686_BUCK1:
+   *reg = MAX77686_REG_BUCK1CTRL;
+   *mask = 0x03;
+   *pattern = 0x03;
+   break;
+   case MAX77686_BUCK2:
+   *reg = MAX77686_REG_BUCK2CTRL1;
+   *mask = 0x30;
+   *pattern = 0x10;
+   break;
+   case MAX77686_BUCK3:
+   *reg = MAX77686_REG_BUCK3CTRL1;
+   *mask = 0x30;
+   *pattern = 0x10;
+   break;
+   case MAX77686_BUCK4:
+   *reg = MAX77686_REG_BUCK4CTRL1;
+   *mask = 0x30;
+   *pattern = 0x10;
+   break;
+   case MAX77686_BUCK5...MAX77686_BUCK9:
+   *reg

  1   2   >