RE: [PATCH v3 03/11] OMAP3: PM: Adding smartreflex driver support.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@xxxxxxxxxxxxxxxxxxx]
>>Sent: Thursday, October 14, 2010 5:34 AM
>>To: Gopinath, Thara
>>Cc: linux-omap@xxxxxxxxxxxxxxx; paul@xxxxxxxxx; Cousson, Benoit; Sripathy,
>>Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH v3 03/11] OMAP3: PM: Adding smartreflex driver support.
>>
>>Thara Gopinath <thara@xxxxxx> writes:
>>
>>> SmartReflex modules do adaptive voltage control for real-time
>>> voltage adjustments. With Smartreflex the power supply voltage
>>> can be adapted to the silicon performance(manufacturing process,
>>> temperature induced performance, age induced performance etc).
>>>
>>> There are differnet classes of smartreflex implementation.
>>>     Class-0: Manufacturing Test Calibration
>>>     Class-1: Boot-Time Software Calibration
>>>     Class-2: Continuous Software Calibration
>>>     Class-3: Continuous Hardware Calibration
>>>     Class-4: Fully Integrated Power Management
>>>
>>> OMAP3 has two smartreflex modules one associated with VDD1 and the
>>> other associated with VDD2.
>>
>>s/VDD1/MPU/
>>s/VDD2/CORE/

Will correct.

>>
>>> This patch adds support for  smartreflex driver. The driver is designed
>>> for Class-1 , Class-2 and Class-3 support and is  a platform driver.
>>> Smartreflex driver can be enabled through a Kconfig option
>>> "SmartReflex support" under "System type"->"TI OMAP implementations" menu.
>>>
>>> Smartreflex autocompensation feature can be enabled runtime through
>>> a debug fs option.
>>> To enable smartreflex autocompensation feature
>>>     echo 1 > /debugfs/pm_debug/smartreflex/sr_<X>/autocomp
>>> To disable smartreflex autocompensation feature
>>>     echo 0 > /debugfs/pm_debug/smartreflex/sr_<X>/autocomp
>>>
>>> where X can be mpu, core , iva etc.
>>>
>>> This patch contains code originally in linux omap pm branch.
>>> Major contributors to this driver are
>>> Lesly A M, Rajendra Nayak, Kalle Jokiniemi, Paul Walmsley,
>>> Nishant Menon, Kevin Hilman.
>>>
>>> Signed-off-by: Thara Gopinath <thara@xxxxxx>
>>> ---
>>>  arch/arm/mach-omap2/Makefile                  |    1 +
>>>  arch/arm/mach-omap2/smartreflex.c             | 1003
>>+++++++++++++++++++++++++
>>>  arch/arm/plat-omap/Kconfig                    |   32 +
>>>  arch/arm/plat-omap/include/plat/smartreflex.h |  277 +++++++
>>>  4 files changed, 1313 insertions(+), 0 deletions(-)
>>>  create mode 100644 arch/arm/mach-omap2/smartreflex.c
>>>  create mode 100644 arch/arm/plat-omap/include/plat/smartreflex.h
>>>
>>> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
>>> index 4f74f2b..8dd32a7 100644
>>> --- a/arch/arm/mach-omap2/Makefile
>>> +++ b/arch/arm/mach-omap2/Makefile
>>> @@ -56,6 +56,7 @@ obj-$(CONFIG_ARCH_OMAP3)          += pm34xx.o sleep34xx.o
>>voltage.o \
>>>                                        cpuidle34xx.o pm_bus.o
>>>  obj-$(CONFIG_ARCH_OMAP4)           += pm44xx.o pm_bus.o
>>>  obj-$(CONFIG_PM_DEBUG)                     += pm-debug.o
>>> +obj-$(CONFIG_OMAP_SMARTREFLEX)          += smartreflex.o
>>>
>>>  AFLAGS_sleep24xx.o                 :=-Wa,-march=armv6
>>>  AFLAGS_sleep34xx.o                 :=-Wa,-march=armv7-a
>>> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-
>>omap2/smartreflex.c
>>> new file mode 100644
>>> index 0000000..7fc3138
>>> --- /dev/null
>>> +++ b/arch/arm/mach-omap2/smartreflex.c
>>> @@ -0,0 +1,1003 @@
>>> +/*
>>> + * OMAP SmartReflex Voltage Control
>>> + *
>>> + * Author: Thara Gopinath  <thara@xxxxxx>
>>> + *
>>> + * Copyright (C) 2010 Texas Instruments, Inc.
>>> + * Thara Gopinath <thara@xxxxxx>
>>> + *
>>> + * Copyright (C) 2008 Nokia Corporation
>>> + * Kalle Jokiniemi
>>> + *
>>> + * Copyright (C) 2007 Texas Instruments, Inc.
>>> + * Lesly A M <x0080970@xxxxxx>
>>> + *
>>> + * 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/interrupt.h>
>>> +#include <linux/clk.h>
>>> +#include <linux/io.h>
>>> +#include <linux/debugfs.h>
>>> +#include <linux/delay.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/pm_runtime.h>
>>> +
>>> +#include <plat/omap_device.h>
>>> +#include <plat/common.h>
>>> +#include <plat/smartreflex.h>
>>> +
>>> +#include "pm.h"
>>> +
>>> +#define SMARTREFLEX_NAME_LEN       16
>>> +#define SR_DISABLE_TIMEOUT 200
>>> +
>>> +struct dentry *sr_dbg_dir;
>>> +
>>> +struct omap_sr {
>>> +   int                     srid;
>>> +   bool                    sr_enable;
>>
>>sr_enabled is a better name

Ok.

>>
>>> +   bool                    autocomp_active;
>>> +   int                     ip_type;
>>> +   u32                     clk_length;
>>> +   u32                     err_weight;
>>> +   u32                     err_minlimit;
>>> +   u32                     err_maxlimit;
>>> +   u32                     accum_data;
>>> +   u32                     senn_avgweight;
>>> +   u32                     senp_avgweight;
>>> +   unsigned int            irq;
>>> +   void __iomem            *base;
>>> +   struct platform_device  *pdev;
>>> +   struct list_head        node;
>>> +   struct voltagedomain    *voltdm;
>>> +};
>>> +
>>> +/* sr_list contains all the instances of smartreflex module */
>>> +static LIST_HEAD(sr_list);
>>> +
>>> +static struct omap_smartreflex_class_data *sr_class;
>>> +static struct omap_smartreflex_pmic_data *sr_pmic_data;
>>> +
>>> +static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32
>>value)
>>> +{
>>> +   __raw_writel(value, (sr->base + offset));
>>> +}
>>> +
>>> +static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32
>>mask,
>>> +                                   u32 value)
>>> +{
>>> +   u32 reg_val;
>>> +   u32 errconfig_offs, errconfig_mask;
>>> +
>>> +   reg_val = __raw_readl(sr->base + offset);
>>> +   reg_val &= ~mask;
>>> +
>>> +   /*
>>> +    * Smartreflex error config register is special as it contains
>>> +    * certain status bits which if written a 1 into means a clear
>>> +    * of those bits. So in order to make sure no accidental write of
>>> +    * 1 happens to those status bits, do a clear of them in the read
>>> +    * value. Now if there is an actual reguest to write to these bits
>>> +    * they will be set in the nex step.
>>
>>s/nex/next/

typo.. will correct
>>
>>that being said, it's not clear what "the next step" is in this context.
>>There is only one write.
>>
>>This should be rephrased to say (something like) it doesn't rewrite
>>values in these bits if they are currently set, but does allow the
>>caller to write those bits.

I will rephrase this.

>>
>>> +    */
>>> +   if (sr->ip_type == SR_TYPE_V1) {
>>> +           errconfig_offs = ERRCONFIG_V1;
>>> +           errconfig_mask = ERRCONFIG_STATUS_V1_MASK;
>>> +   } else if (sr->ip_type == SR_TYPE_V2) {
>>> +           errconfig_offs = ERRCONFIG_V2;
>>> +           errconfig_mask = ERRCONFIG_VPBOUNDINTST_V2;
>>> +   }
>>> +
>>> +   if (offset == errconfig_offs)
>>> +           reg_val &= ~errconfig_mask;
>>> +
>>> +   reg_val |= value;
>>> +
>>> +   __raw_writel(reg_val, (sr->base + offset));
>>> +}
>>> +
>>> +static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
>>> +{
>>> +   return __raw_readl(sr->base + offset);
>>> +}
>>> +
>>> +static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
>>> +{
>>> +   struct omap_sr *sr_info;
>>> +
>>> +   if (!voltdm) {
>>> +           pr_err("%s: Null voltage domain passed!\n", __func__);
>>> +           return ERR_PTR(-EINVAL);
>>> +   }
>>> +
>>> +   list_for_each_entry(sr_info, &sr_list, node) {
>>> +           if (voltdm == sr_info->voltdm)
>>> +                   return sr_info;
>>> +   }
>>> +
>>> +   return ERR_PTR(-ENODATA);
>>> +}
>>>
>>> +static irqreturn_t sr_omap_isr(int irq, void *data)
>>
>>Please rename to sr_interrupt

Will do.

>>
>>> +{
>>> +   struct omap_sr *sr_info = (struct omap_sr *)data;
>>> +   u32 status = 0;
>>> +
>>> +   if (sr_info->ip_type == SR_TYPE_V1) {
>>> +           /* Read the status bits */
>>> +           status = sr_read_reg(sr_info, ERRCONFIG_V1);
>>> +
>>> +           /* Clear them by writing back */
>>> +           sr_write_reg(sr_info, ERRCONFIG_V1, status);
>>
>>Shouldn't you be using sr_modify_reg for ERRCONFIG_V1?

Nope. I am doing a read followed by writing the same value back. No need of using modify

>>
>>> +   } else if (sr_info->ip_type == SR_TYPE_V2) {
>>> +           /* Read the status bits */
>>> +           sr_read_reg(sr_info, IRQSTATUS);
>>> +
>>> +           /* Clear them by writing back */
>>> +           sr_write_reg(sr_info, IRQSTATUS, status);
>>> +   }
>>
>>Might as well use it for both.
>>
>>> +
>>> +   /* Call the class driver notify function if registered*/
>>
>>This comment does not add anything the code doesn't make clear, and
>>is not fully correct: it has to be registered, and be class 2.
>>
>>IMO, you can just remove comments like this that aren't be

Will remove this comment

>>
>>> +   if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
>>> +           sr_class->notify(sr_info->voltdm, status);
>>> +
>>> +   return IRQ_HANDLED;
>>> +}
>>> +
>>> +static void sr_set_clk_length(struct omap_sr *sr)
>>> +{
>>> +   struct clk *sys_ck;
>>> +   u32 sys_clk_speed;
>>> +
>>> +   sys_ck = clk_get(NULL, "sys_ck");
>>> +   if (IS_ERR(sys_ck)) {
>>> +           dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
>>> +                   __func__);
>>> +           return;
>>> +   }
>>> +   sys_clk_speed = clk_get_rate(sys_ck);
>>> +   clk_put(sys_ck);
>>> +
>>> +   switch (sys_clk_speed) {
>>> +   case 12000000:
>>> +           sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
>>> +           break;
>>> +   case 13000000:
>>> +           sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
>>> +           break;
>>> +   case 19200000:
>>> +           sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
>>> +           break;
>>> +   case 26000000:
>>> +           sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
>>> +           break;
>>> +   case 38400000:
>>> +           sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
>>> +           break;
>>> +   default:
>>> +           dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n",
>>> +                   __func__, sys_clk_speed);
>>> +           break;
>>> +   }
>>> +}
>>> +
>>> +static void sr_set_regfields(struct omap_sr *sr)
>>> +{
>>> +   /*
>>> +    * For time being these values are defined in smartreflex.h
>>> +    * and populated during init. May be they can be moved to board
>>> +    * file or pmic specific data structure. In that case these structure
>>> +    * fields will have to be populated using the pdata or pmic structure.
>>> +    */
>>> +   if (cpu_is_omap34xx()) {
>>> +           sr->err_weight = OMAP3430_SR_ERRWEIGHT;
>>> +           sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
>>> +           sr->accum_data = OMAP3430_SR_ACCUMDATA;
>>> +           if (!(strcmp(sr->voltdm->name, "mpu"))) {
>>> +                   sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
>>> +                   sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
>>> +           } else {
>>> +                   sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
>>> +                   sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
>>> +           }
>>> +   }
>>> +   /* TODO: 3630 and Omap4 specific bit field values */
>>> +}
>>> +
>>> +static void sr_start_vddautocomp(struct omap_sr *sr)
>>> +{
>>> +   if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
>>> +           dev_warn(&sr->pdev->dev,
>>> +                   "%s: smartreflex class driver not registered\n",
>>> +                   __func__);
>>> +           return;
>>> +   }
>>> +
>>> +   if (!sr_class->enable(sr->voltdm))
>>> +           sr->autocomp_active = true;
>>> +}
>>> +
>>> +static void sr_stop_vddautocomp(struct omap_sr *sr)
>>> +{
>>> +   if (!sr_class || !(sr_class->disable)) {
>>> +           dev_warn(&sr->pdev->dev,
>>> +                   "%s: smartreflex class driver not registered\n",
>>> +                   __func__);
>>> +           return;
>>> +   }
>>> +
>>> +   if (sr->autocomp_active) {
>>> +           sr_class->disable(sr->voltdm, 1);
>>> +           sr->autocomp_active = false;
>>> +   }
>>> +}
>>> +
>>> +/*
>>> + * This function handles the intializations which have to be done
>>> + * only when both sr device and class driver regiter has
>>> + * completed. This will be attempted to be called from both sr class
>>> + * driver register and sr device intializtion API's. Only one call
>>> + * will ultimately succeed.
>>> + *
>>> + * Currenly this function registers interrrupt handler for a particular SR
>>> + * if smartreflex class driver is already registered and has
>>> + * requested for interrupts and the SR interrupt line in present.
>>> + */
>>> +static int sr_late_init(struct omap_sr *sr_info)
>>> +{
>>> +   char *name;
>>> +   struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
>>> +   int ret = 0;
>>> +
>>> +   if (sr_class->class_type == SR_CLASS2 &&
>>> +           sr_class->notify_flags && sr_info->irq) {
>>> +
>>> +           name = kzalloc(SMARTREFLEX_NAME_LEN + 1, GFP_KERNEL);
>>> +           strcpy(name, "sr_");
>>> +           strcat(name, sr_info->voltdm->name);
>>> +           ret = request_irq(sr_info->irq, sr_omap_isr,
>>> +                           IRQF_DISABLED, name, (void *)sr_info);
>>
>>Why does this have to be IRQF_DISABLED?   This capability will be
>>disappearing from the kernel soon.
>>
>>Because there are no current users, I cannot tell, but I suspect this
>>could be use request_threaded_irq.  If not, please justify.

Why should this be request_threaded_irq?? I have to check to learn the differnces.
>>
>>> +           if (ret) {
>>
>>                         goto error;
>>
>>> +                   struct resource *mem;
>>> +
>>> +                   iounmap(sr_info->base);
>>> +                   mem = platform_get_resource(sr_info->pdev,
>>> +                           IORESOURCE_MEM, 0);
>>> +                   release_mem_region(mem->start, resource_size(mem));
>>> +                   list_del(&sr_info->node);
>>> +                   dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
>>> +                           "interrupt handler. Smartreflex will"
>>> +                           "not function as desired\n", __func__);
>>> +
>>> +                   kfree(sr_info);
>>> +                   return ret;
>>> +           }
>>
>>and move this after the return...

I did not understand this comment.

>>
>>> +   }
>>> +
>>> +   if (pdata && pdata->enable_on_init)
>>> +           sr_start_vddautocomp(sr_info);
>>> +
>>> +   return ret;
>>
>>error:
>>
>>(here.)
>>
>>> +}
>>> +
>>> +static void sr_v1_disable(struct omap_sr *sr)
>>> +{
>>> +   int timeout = 0;
>>> +
>>> +   /* Enable MCUDisableAcknowledge interrupt */
>>> +   sr_modify_reg(sr, ERRCONFIG_V1,
>>> +                   ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN);
>>> +
>>> +   /* SRCONFIG - disable SR */
>>> +   sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
>>> +
>>> +   /* Disable all other SR interrupts and clear the status */
>>> +   sr_modify_reg(sr, ERRCONFIG_V1,
>>> +                   (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
>>> +                   ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
>>> +                   (ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
>>> +                   ERRCONFIG_MCUBOUNDINTST |
>>> +                   ERRCONFIG_VPBOUNDINTST_V1));
>>> +
>>> +   /*
>>> +    * Wait for SR to be disabled.
>>> +    * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
>>> +    */
>>> +   omap_test_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
>>> +                   ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
>>> +                   timeout);
>>> +
>>> +   if (timeout >= SR_DISABLE_TIMEOUT)
>>> +           dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
>>> +                   __func__);
>>> +
>>> +   /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
>>> +   sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN,
>>> +                   ERRCONFIG_MCUDISACKINTST);
>>> +}
>>> +
>>> +static void sr_v2_disable(struct omap_sr *sr)
>>> +{
>>> +   int timeout = 0;
>>> +
>>> +   /* Enable MCUDisableAcknowledge interrupt */
>>> +   sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT);
>>> +
>>> +   /* SRCONFIG - disable SR */
>>> +   sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
>>> +
>>> +   /* Disable all other SR interrupts and clear the status */
>>> +   sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
>>> +                   ERRCONFIG_VPBOUNDINTST_V2);
>>> +   sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
>>> +                   IRQENABLE_MCUVALIDINT |
>>> +                   IRQENABLE_MCUBOUNDSINT));
>>> +   sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT |
>>> +                   IRQSTATUS_MCVALIDINT |
>>> +                   IRQSTATUS_MCBOUNDSINT));
>>> +
>>> +   /*
>>> +    * Wait for SR to be disabled.
>>> +    * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
>>> +    */
>>> +   omap_test_timeout((sr_read_reg(sr, IRQSTATUS) &
>>> +                   IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
>>> +                   timeout);
>>> +
>>> +   if (timeout >= SR_DISABLE_TIMEOUT)
>>> +           dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
>>> +                   __func__);
>>> +
>>> +   /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
>>> +   sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
>>> +   sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
>>> +}
>>> +
>>> +/* Public Functions */
>>> +
>>> +/**
>>> + * sr_configure_errgen() - Configures the smrtreflex to perform AVS using
>>the
>>> + *                  error generator module.
>>> + * @voltdm:        VDD pointer to which the SR module to be configured belongs
>>to.
>>> + *
>>> + * This API is to be called from the smartreflex class driver to
>>> + * configure the error generator module inside the smartreflex module.
>>> + * SR settings if using the ERROR module inside Smartreflex.
>>> + * SR CLASS 3 by default uses only the ERROR module where as
>>> + * SR CLASS 2 can choose between ERROR module and MINMAXAVG
>>> + * module. Returns 0 on success and error value in case of failure.
>>> + */
>>> +int sr_configure_errgen(struct voltagedomain *voltdm)
>>> +{
>>> +   u32 sr_config, sr_errconfig, errconfig_offs, vpboundint_en;
>>> +   u32 vpboundint_st, senp_en = 0, senn_en = 0;
>>> +   u8 senp_shift, senn_shift;
>>> +   struct omap_sr *sr = _sr_lookup(voltdm);
>>> +   struct omap_sr_data *pdata;
>>> +
>>> +   if (IS_ERR(sr)) {
>>> +           pr_warning("%s: omap_sr struct for sr_%s not found\n",
>>> +                   __func__, voltdm->name);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   pdata = sr->pdev->dev.platform_data;
>>> +
>>> +   if (!sr->clk_length)
>>> +           sr_set_clk_length(sr);
>>> +
>>> +   if (pdata) {
>>> +           senp_en = pdata->senp_mod;
>>> +           senn_en = pdata->senn_mod;
>>> +   } else {
>>> +           dev_warn(&sr->pdev->dev, "%s: Missing pdata\n", __func__);
>>
>>This is more of an error condition, and should probably return here with
>>an error.  Otherwise undefined values are used below.

Ok. Will return.

>>
>>> +   }
>>> +
>>> +   sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
>>> +           SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN;
>>> +
>>> +   if (sr->ip_type == SR_TYPE_V1) {
>>> +           sr_config |= SRCONFIG_DELAYCTRL;
>>> +           senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
>>> +           senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
>>> +           errconfig_offs = ERRCONFIG_V1;
>>> +           vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
>>> +           vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
>>> +   } else if (sr->ip_type == SR_TYPE_V2) {
>>> +           senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
>>> +           senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
>>> +           errconfig_offs = ERRCONFIG_V2;
>>> +           vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
>>> +           vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
>>> +   } else {
>>> +           dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
>>> +                   "module without specifying the ip\n", __func__);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
>>> +   sr_write_reg(sr, SRCONFIG, sr_config);
>>> +   sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
>>> +           (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
>>> +           (sr->err_minlimit <<  ERRCONFIG_ERRMINLIMIT_SHIFT);
>>> +   sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK |
>>> +           SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
>>> +           sr_errconfig);
>>> +
>>> +   /* Enabling the interrupts if the ERROR module is used */
>>> +   sr_modify_reg(sr, errconfig_offs,
>>> +           vpboundint_en, (vpboundint_en | vpboundint_st));
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +/**
>>> + * sr_configure_minmax() - Configures the smrtreflex to perform AVS using
>>the
>>> + *                  minmaxavg module.
>>> + * @voltdm:        VDD pointer to which the SR module to be configured belongs
>>to.
>>> + *
>>> + * This API is to be called from the smartreflex class driver to
>>> + * configure the minmaxavg module inside the smartreflex module.
>>> + * SR settings if using the ERROR module inside Smartreflex.
>>> + * SR CLASS 3 by default uses only the ERROR module where as
>>> + * SR CLASS 2 can choose between ERROR module and MINMAXAVG
>>> + * module. Returns 0 on success and error value in case of failure.
>>> + */
>>> +int sr_configure_minmax(struct voltagedomain *voltdm)
>>> +{
>>> +   u32 sr_config, sr_avgwt;
>>> +   u32 senp_en = 0, senn_en = 0;
>>> +   u8 senp_shift, senn_shift;
>>> +   struct omap_sr *sr = _sr_lookup(voltdm);
>>> +   struct omap_sr_data *pdata;
>>> +
>>> +   if (IS_ERR(sr)) {
>>> +           pr_warning("%s: omap_sr struct for sr_%s not found\n",
>>> +                   __func__, voltdm->name);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   pdata = sr->pdev->dev.platform_data;
>>> +
>>> +   if (!sr->clk_length)
>>> +           sr_set_clk_length(sr);
>>> +
>>> +   if (pdata) {
>>> +           senp_en = pdata->senp_mod;
>>> +           senn_en = pdata->senn_mod;
>>> +   } else {
>>> +           dev_warn(&sr->pdev->dev, "%s: Missing pdata\n", __func__);
>>
>>same as above

Will do the necessary

>>
>>> +   }
>>> +
>>> +   sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
>>> +           SRCONFIG_SENENABLE |
>>> +           (sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
>>> +
>>> +   if (sr->ip_type == SR_TYPE_V1) {
>>> +           sr_config |= SRCONFIG_DELAYCTRL;
>>> +           senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
>>> +           senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
>>> +   } else if (sr->ip_type == SR_TYPE_V2) {
>>> +           senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
>>> +           senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
>>> +   } else {
>>> +           dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
>>> +                   "module without specifying the ip\n", __func__);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
>>> +   sr_write_reg(sr, SRCONFIG, sr_config);
>>> +   sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
>>> +           (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
>>> +   sr_write_reg(sr, AVGWEIGHT, sr_avgwt);
>>> +
>>> +   /*
>>> +    * Enabling the interrupts if MINMAXAVG module is used.
>>> +    * TODO: check if all the interrupts are mandatory
>>> +    */
>>> +   if (sr->ip_type == SR_TYPE_V1) {
>>> +           sr_modify_reg(sr, ERRCONFIG_V1,
>>> +                   (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
>>> +                   ERRCONFIG_MCUBOUNDINTEN),
>>> +                   (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
>>> +                    ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
>>> +                    ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
>>> +   } else if (sr->ip_type == SR_TYPE_V2) {
>>> +           sr_write_reg(sr, IRQSTATUS,
>>> +                   IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT |
>>> +                   IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT);
>>> +           sr_write_reg(sr, IRQENABLE_SET,
>>> +                   IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT |
>>> +                   IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT);
>>> +   }
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +/**
>>> + * sr_enable() - Enables the smartreflex module.
>>> + * @voltdm:        VDD pointer to which the SR module to be configured belongs
>>to.
>>> + * @volt:  The voltage at which the Voltage domain associated with
>>> + *         the smartreflex module is operating at.
>>> + *         This is required only to program the correct Ntarget value.
>>> + *
>>> + * This API is to be called from the smartreflex class driver to
>>> + * enable a smartreflex module. Returns 0 on success. Returns error
>>> + * value if the voltage passed is wrong or if ntarget value is wrong.
>>> + */
>>> +int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
>>> +{
>>> +   u32 nvalue_reciprocal;
>>> +   struct omap_volt_data *volt_data;
>>> +   struct omap_sr *sr = _sr_lookup(voltdm);
>>> +   int ret;
>>> +
>>> +   if (IS_ERR(sr)) {
>>> +           pr_warning("%s: omap_sr struct for sr_%s not found\n",
>>> +                   __func__, voltdm->name);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   volt_data = omap_voltage_get_voltdata(voltdm, volt);
>>> +
>>> +   if (IS_ERR(volt_data)) {
>>> +           dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table"
>>> +                   " for nominal voltage %ld\n", __func__, volt);
>>> +           return -ENODATA;
>>> +   }
>>> +
>>> +   nvalue_reciprocal = volt_data->sr_nvalue;
>>> +
>>> +   if (!nvalue_reciprocal) {
>>> +           dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n",
>>> +                   __func__, volt);
>>> +           return -ENODATA;
>>> +   }
>>> +
>>> +   /* errminlimit is opp dependent and hence linked to voltage */
>>> +   sr->err_minlimit = volt_data->sr_errminlimit;
>>> +
>>> +   /* Enable the clocks */
>>
>>not just clocs are enabled by pm_runtime_get().  Again, probably just
>>removing the comment is better.

Will remove

>>
>>> +   if (!sr->sr_enable) {
>>> +           pm_runtime_get_sync(&sr->pdev->dev);
>>> +           sr->sr_enable = true;
>>> +   }
>>
>>But, I'm not sure why you need this sr_enabled flag.  Here, you could
>>just do pm_runtime_get_sync() and rely on the usecounting done in the
>>runtime PM core...

sr_enable flag is used in sr_disable() API to check if we really need  to disable sr or not.

>>
>>> +   /* Check if SR is already enabled. If yes do nothing */
>>> +   if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
>>> +           return 0;
>>> +
>>> +   /* Configure SR */
>>> +   ret = sr_class->configure(voltdm);
>>> +   if (ret)
>>> +           return ret;
>>> +
>>> +   sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
>>> +
>>> +   /* SRCONFIG - enable SR */
>>> +   sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
>>> +   return 0;
>>> +}
>>> +
>>> +/**
>>> + * sr_disable() - Disables the smartreflex module.
>>> + * @voltdm:        VDD pointer to which the SR module to be configured belongs
>>to.
>>> + *
>>> + * This API is to be called from the smartreflex class driver to
>>> + * disable a smartreflex module.
>>> + */
>>> +void sr_disable(struct voltagedomain *voltdm)
>>> +{
>>> +   struct omap_sr *sr = _sr_lookup(voltdm);
>>> +
>>> +   if (IS_ERR(sr)) {
>>> +           pr_warning("%s: omap_sr struct for sr_%s not found\n",
>>> +                   __func__, voltdm->name);
>>> +           return;
>>> +   }
>>> +
>>> +   /* Check if SR clocks are already disabled. If yes do nothing */
>>> +   if (!sr->sr_enable)
>>
>>...and here you just check pm_runtime_is_suspended()

mmmm.. I will give this a try.

>>
>>> +           return;
>>> +
>>> +   /* Check if SR is already disabled. If yes just disable the clocks */
>>> +   if (!(sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE))
>>> +           goto disable_clocks;
>>
>>drop the goto and just indent the next block

Ok will do.

>>
>>> +
>>> +   if (sr->ip_type == SR_TYPE_V1)
>>> +           sr_v1_disable(sr);
>>> +   else if (sr->ip_type == SR_TYPE_V2)
>>> +           sr_v2_disable(sr);
>>> +
>>> +disable_clocks:
>>> +   pm_runtime_put_sync(&sr->pdev->dev);
>>> +   sr->sr_enable = false;
>>> +}
>>> +
>>> +/**
>>> + * sr_register_class() - API to register a smartreflex class parameters.
>>> + * @class_data:    The structure containing various sr class specific
>>data.
>>> + *
>>> + * This API is to be called by the smartreflex class driver to register
>>itself
>>> + * with the smartreflex driver during init. Returns 0 on success else the
>>> + * error value.
>>> + */
>>> +int sr_register_class(struct omap_smartreflex_class_data *class_data)
>>> +{
>>> +   struct omap_sr *sr_info;
>>> +
>>> +   if (!class_data) {
>>> +           pr_warning("%s:, Smartreflex class data passed is NULL\n",
>>> +                   __func__);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   if (sr_class) {
>>> +           pr_warning("%s: Smartreflex class driver already registered\n",
>>> +                   __func__);
>>> +           return -EBUSY;
>>> +   }
>>> +
>>> +   sr_class = class_data;
>>> +
>>> +   /*
>>> +    * Call into late init to do intializations that require
>>> +    * both sr driver and sr class driver to be initiallized.
>>> +    */
>>> +   list_for_each_entry(sr_info, &sr_list, node)
>>> +           sr_late_init(sr_info);
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +/**
>>> + * omap_sr_enable() -  API to enable SR clocks and to call into the
>>> + *                 registered smartreflex class enable API.
>>> + * @voltdm:        VDD pointer to which the SR module to be configured belongs
>>to.
>>> + *
>>> + * This API is to be called from the kernel in order to enable
>>> + * a particular smartreflex module. This API will do the initial
>>> + * configurations to turn on the smartreflex module and in turn call
>>> + * into the registered smartreflex class enable API.
>>> + */
>>> +void omap_sr_enable(struct voltagedomain *voltdm)
>>> +{
>>> +   struct omap_sr *sr = _sr_lookup(voltdm);
>>> +
>>> +   if (IS_ERR(sr)) {
>>> +           pr_warning("%s: omap_sr struct for sr_%s not found\n",
>>> +                   __func__, voltdm->name);
>>> +           return;
>>> +   }
>>> +
>>> +   if (!sr->autocomp_active)
>>> +           return;
>>> +
>>> +   if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
>>> +           dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
>>> +                   "registered\n", __func__);
>>> +           return;
>>> +   }
>>> +
>>> +   sr_class->enable(voltdm);
>>> +}
>>> +
>>> +/**
>>> + * omap_sr_disable() - API to disable SR without resetting the voltage
>>> + *                 processor voltage
>>> + * @voltdm:        VDD pointer to which the SR module to be configured belongs
>>to.
>>> + *
>>> + * This API is to be called from the kernel in order to disable
>>> + * a particular smartreflex module. This API will in turn call
>>> + * into the registered smartreflex class disable API. This API will tell
>>> + * the smartreflex class disable not to reset the VP voltage after
>>> + * disabling smartreflex.
>>> + */
>>> +void omap_sr_disable(struct voltagedomain *voltdm)
>>> +{
>>> +   struct omap_sr *sr = _sr_lookup(voltdm);
>>> +
>>> +   if (IS_ERR(sr)) {
>>> +           pr_warning("%s: omap_sr struct for sr_%s not found\n",
>>> +                   __func__, voltdm->name);
>>> +           return;
>>> +   }
>>> +
>>> +   if (!sr->autocomp_active)
>>> +           return;
>>> +
>>> +   if (!sr_class || !(sr_class->disable)) {
>>> +           dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
>>> +                   "registered\n", __func__);
>>> +           return;
>>> +   }
>>> +
>>> +   sr_class->disable(voltdm, 0);
>>> +}
>>> +
>>> +/**
>>> + * omap_sr_disable_reset_volt() - API to disable SR and reset the
>>> + *                         voltage processor voltage
>>> + * @voltdm:        VDD pointer to which the SR module to be configured belongs
>>to.
>>> + *
>>> + * This API is to be called from the kernel in order to disable
>>> + * a particular smartreflex module. This API will in turn call
>>> + * into the registered smartreflex class disable API. This API will tell
>>> + * the smartreflex class disable to reset the VP voltage after
>>> + * disabling smartreflex.
>>> + */
>>> +void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
>>> +{
>>> +   struct omap_sr *sr = _sr_lookup(voltdm);
>>> +
>>> +   if (IS_ERR(sr)) {
>>> +           pr_warning("%s: omap_sr struct for sr_%s not found\n",
>>> +                   __func__, voltdm->name);
>>> +           return;
>>> +   }
>>> +
>>> +   if (!sr->autocomp_active)
>>> +           return;
>>> +
>>> +   if (!sr_class || !(sr_class->disable)) {
>>> +           dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
>>> +                   "registered\n", __func__);
>>> +           return;
>>> +   }
>>> +
>>> +   sr_class->disable(voltdm, 1);
>>> +}
>>> +
>>> +/**
>>> + * omap_sr_register_pmic() - API to register pmic specific info.
>>> + * @pmic_data:     The structure containing pmic specific data.
>>> + *
>>> + * This API is to be called from the PMIC specific code to register with
>>> + * smartreflex driver pmic specific info. Currently the only info required
>>> + * is the smartreflex init on the PMIC side.
>>> + */
>>> +void omap_sr_register_pmic(struct omap_smartreflex_pmic_data *pmic_data)
>>> +{
>>> +   if (!pmic_data) {
>>> +           pr_warning("%s: Trying to register NULL PMIC data structure"
>>> +                   "with smartreflex\n", __func__);
>>> +           return;
>>> +   }
>>> +
>>> +   sr_pmic_data = pmic_data;
>>> +}
>>> +
>>> +/* PM Debug Fs enteries to enable disable smartreflex. */
>>> +static int omap_sr_autocomp_show(void *data, u64 *val)
>>> +{
>>> +   struct omap_sr *sr_info = (struct omap_sr *) data;
>>> +
>>> +   if (!sr_info) {
>>> +           pr_warning("%s: omap_sr struct for sr_%s not found\n",
>>> +                   __func__, sr_info->voltdm->name);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   *val = sr_info->autocomp_active;
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +static int omap_sr_autocomp_store(void *data, u64 val)
>>> +{
>>> +   struct omap_sr *sr_info = (struct omap_sr *) data;
>>> +
>>> +   if (!sr_info) {
>>> +           pr_warning("%s: omap_sr struct for sr_%s not found\n",
>>> +                   __func__, sr_info->voltdm->name);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   /* Sanity check */
>>> +   if (val && (val != 1)) {
>>> +           pr_warning("%s: Invalid argument %lld\n", __func__, val);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   if (!val)
>>> +           sr_stop_vddautocomp(sr_info);
>>> +   else
>>> +           sr_start_vddautocomp(sr_info);
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
>>> +           omap_sr_autocomp_store, "%llu\n");
>>> +
>>> +static int __init omap_smartreflex_probe(struct platform_device *pdev)
>>> +{
>>> +   struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
>>> +   struct omap_device *odev = to_omap_device(pdev);
>>> +   struct omap_sr_data *pdata = pdev->dev.platform_data;
>>> +   struct resource *mem, *irq;
>>> +   struct dentry *dbg_dir;
>>> +   char *name;
>>> +   int ret = 0;
>>> +
>>> +   if (!sr_info) {
>>> +           dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
>>> +                   __func__);
>>> +           return -ENOMEM;
>>> +   }
>>> +
>>> +   if (!pdata) {
>>> +           dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +   if (!mem) {
>>> +           dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
>>> +           ret = -ENODEV;
>>> +           goto err_free_devinfo;
>>> +   }
>>> +
>>> +   irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>>> +
>>> +   pm_runtime_enable(&pdev->dev);
>>> +
>>> +   sr_info->pdev = pdev;
>>> +   sr_info->srid = pdev->id;
>>> +   sr_info->voltdm = pdata->voltdm;
>>> +   sr_info->autocomp_active = false;
>>> +   sr_info->ip_type = odev->hwmods[0]->class->rev;
>>> +   sr_info->base = ioremap(mem->start, resource_size(mem));
>>> +   if (!sr_info->base) {
>>> +           dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
>>> +           ret = -ENOMEM;
>>> +           goto err_release_region;
>>> +   }
>>> +
>>> +   if (irq)
>>> +           sr_info->irq = irq->start;
>>> +
>>> +   sr_set_clk_length(sr_info);
>>> +   sr_set_regfields(sr_info);
>>> +
>>> +   list_add(&sr_info->node, &sr_list);
>>> +
>>> +   /*
>>> +    * Call into late init to do intializations that require
>>> +    * both sr driver and sr class driver to be initiallized.
>>> +    */
>>> +   if (sr_class) {
>>> +           ret = sr_late_init(sr_info);
>>> +           if (ret) {
>>> +                   pr_warning("%s: Error in SR late init\n", __func__);
>>> +                   return ret;
>>> +           }
>>> +   }
>>> +
>>> +   dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
>>> +
>>> +   /*
>>> +    * If the Smartreflex main debugfs directory is not created, do
>>> +    * not try to create rest of the debugfs entries.
>>> +    */
>>> +   if (!sr_dbg_dir)
>>> +           return ret;
>>> +
>>> +   name = kzalloc(SMARTREFLEX_NAME_LEN + 1, GFP_KERNEL);
>>> +   if (!name) {
>>> +           dev_err(&pdev->dev, "%s: Unable to allocate name for"
>>> +                   "debufs entry", __func__);
>>> +           return ret;
>>
>>what will 'ret' be here?

Will correct this.
>>
>>> +   }
>>> +
>>> +   /* Create the debug fs enteries */
>>> +   strcpy(name, "sr_");
>>> +   strcat(name, sr_info->voltdm->name);
>>> +
>>> +   dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
>>> +   if (IS_ERR(dbg_dir)) {
>>> +           dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
>>> +                   __func__);
>>> +           return ret;
>>
>>or here?

Will correct this.

>>
>>> +   }
>>> +
>>> +   (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, dbg_dir,
>>> +                           (void *)sr_info, &pm_sr_fops);
>>> +
>>> +   return ret;
>>> +
>>> +err_release_region:
>>> +   release_mem_region(mem->start, resource_size(mem));
>>> +err_free_devinfo:
>>> +   kfree(sr_info);
>>> +
>>> +   return ret;
>>> +}
>>> +
>>> +static int __devexit omap_smartreflex_remove(struct platform_device *pdev)
>>
>>as an internal function, to be consistent with other naming, this should
>>be sr_remove.

It is omap_smartreflex_probe and remove. Do you prefer omap_sr_probe and omap_sr_remove?

>>
>>> +{
>>> +   struct omap_sr_data *pdata = pdev->dev.platform_data;
>>> +   struct omap_sr *sr_info;
>>> +   struct resource *mem;
>>> +
>>> +   if (!pdata) {
>>> +           dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   sr_info = _sr_lookup(pdata->voltdm);
>>> +   if (!sr_info) {
>>> +           dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
>>> +                   __func__);
>>> +           return -EINVAL;
>>> +   }
>>> +
>>> +   /* Disable Autocompensation if enabled before removing the module */
>>
>>surperfluous comment

Ok. Will remove.

>>
>>> +   if (sr_info->autocomp_active)
>>> +           sr_stop_vddautocomp(sr_info);
>>> +
>>> +   list_del(&sr_info->node);
>>> +   iounmap(sr_info->base);
>>> +   kfree(sr_info);
>>> +   mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +   release_mem_region(mem->start, resource_size(mem));
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +static struct platform_driver smartreflex_driver = {
>>> +   .remove         = omap_smartreflex_remove,
>>> +   .driver         = {
>>> +           .name   = "smartreflex",
>>> +   },
>>> +};
>>> +
>>> +static int __init sr_init(void)
>>> +{
>>> +   int ret = 0;
>>> +
>>> +   /*
>>> +    * sr_init is a late init. If by then a pmic specific API is not
>>> +    * registered either there is no need for anything to be done on
>>> +    * the PMIC side or somebody has forgotten to register a PMIC
>>> +    * handler. Warn for the second condition.
>>> +    */
>>> +   if (sr_pmic_data && sr_pmic_data->sr_pmic_init)
>>> +           sr_pmic_data->sr_pmic_init();
>>> +   else
>>> +           pr_warning("%s: No PMIC hook to init smartreflex\n", __func__);
>>> +
>>> +   if (pm_dbg_main_dir) {
>>> +           struct dentry *d;
>>> +
>>> +           d = debugfs_create_dir("smartreflex", pm_dbg_main_dir);
>>> +           if (!IS_ERR(d))
>>> +                   sr_dbg_dir = d;
>>> +   }
>>> +
>>> +   ret = platform_driver_probe(&smartreflex_driver,
>>> +                           omap_smartreflex_probe);
>>> +   if (ret) {
>>> +           pr_err("%s: platform driver register failed for SR\n",
>>> +                   __func__);
>>> +           return ret;
>>> +   }
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +static void __exit sr_exit(void)
>>> +{
>>> +   platform_driver_unregister(&smartreflex_driver);
>>> +}
>>> +late_initcall(sr_init);
>>> +module_exit(sr_exit);
>>> +
>>> +MODULE_DESCRIPTION("OMAP SMARTREFLEX DRIVER");
>>
>>"OMAP SmartReflex driver"

Ok.. Will Correct

>>
>>> +MODULE_LICENSE("GPL");
>>> +MODULE_ALIAS("platform:" DRIVER_NAME);
>>> +MODULE_AUTHOR("Texas Instruments Inc");
>>> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>>> index e39a417..8056349 100644
>>> --- a/arch/arm/plat-omap/Kconfig
>>> +++ b/arch/arm/plat-omap/Kconfig
>>> @@ -35,6 +35,38 @@ config OMAP_DEBUG_LEDS
>>>     depends on OMAP_DEBUG_DEVICES
>>>     default y if LEDS
>>>
>>> +config OMAP_SMARTREFLEX
>>> +   bool "SmartReflex support"
>>> +   depends on ARCH_OMAP3 && PM
>>> +   help
>>> +     Say Y if you want to enable SmartReflex.
>>> +
>>> +     SmartReflex can perform continuous dynamic voltage
>>> +     scaling around the nominal operating point voltage
>>> +     according to silicon characteristics and operating
>>> +     conditions. Enabling SmartReflex reduces power
>>> +     consumption.
>>> +
>>> +     Please note, that by default SmartReflex is only
>>> +     initialized. To enable the automatic voltage
>>> +     compensation for VDD1 and VDD2, user must write 1 to
>>
>>s/VDD1/MPU/
>>s/VDD2/CORE/

Will correct

>>
>>> +     /debug/pm_debug/Smartreflex/SR<X>/autocomp,
>>> +     where X is 1 or 2 for OMAP3
>>
>>Not fully true, on some SoCs (ES3.1) it's also enabled by default.

mmm.. Will update the commment
>>
>>> +config OMAP_SMARTREFLEX_TESTING
>>> +   bool "Smartreflex testing support"
>>> +   depends on OMAP_SMARTREFLEX
>>> +   default n
>>> +   help
>>> +     Say Y if you want to enable SmartReflex testing with SW hardcoded
>>> +     NVALUES intead of E-fuse NVALUES set in factory silicon testing.
>>> +
>>> +     In some devices the E-fuse values have not been set, even though
>>> +     SmartReflex modules are included. Using these hardcoded values set
>>> +     in software, one can test the SmartReflex features without E-fuse.
>>> +
>>> +     WARNING: Enabling this option may cause your device to hang!
>>> +
>>>  config OMAP_RESET_CLOCKS
>>>     bool "Reset unused clocks during boot"
>>>     depends on ARCH_OMAP
>>> diff --git a/arch/arm/plat-omap/include/plat/smartreflex.h b/arch/arm/plat-
>>omap/include/plat/smartreflex.h
>>> new file mode 100644
>>> index 0000000..1ad03ea
>>> --- /dev/null
>>> +++ b/arch/arm/plat-omap/include/plat/smartreflex.h
>>> @@ -0,0 +1,277 @@
>>> +/*
>>> + * OMAP Smartreflex Defines and Routines
>>> + *
>>> + * Author: Thara Gopinath  <thara@xxxxxx>
>>> + *
>>> + * Copyright (C) 2010 Texas Instruments, Inc.
>>> + * Thara Gopinath <thara@xxxxxx>
>>> + *
>>> + * Copyright (C) 2008 Nokia Corporation
>>> + * Kalle Jokiniemi
>>> + *
>>> + * Copyright (C) 2007 Texas Instruments, Inc.
>>> + * Lesly A M <x0080970@xxxxxx>
>>> + *
>>> + * 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 __ASM_ARM_OMAP_SMARTREFLEX_H
>>> +#define __ASM_ARM_OMAP_SMARTREFLEX_H
>>> +
>>> +#include <linux/platform_device.h>
>>> +#include <plat/voltage.h>
>>> +
>>> +#ifdef CONFIG_PM_DEBUG
>>> +extern struct dentry *pm_dbg_main_dir;
>>> +extern struct dentry *sr_dbg_dir;
>>> +#endif
>>> +
>>> +/*
>>> + * Different Smartreflex IPs version. The v1 is the 65nm version used in
>>> + * OMAP3430. The v2 is the update for the 45nm version of the IP
>>> + * used in OMAP3630 and OMAP4430
>>> + */
>>> +#define SR_TYPE_V1 1
>>> +#define SR_TYPE_V2 2
>>> +
>>> +/* SMART REFLEX REG ADDRESS OFFSET */
>>> +#define SRCONFIG           0x00
>>> +#define SRSTATUS           0x04
>>> +#define SENVAL                     0x08
>>> +#define SENMIN                     0x0C
>>> +#define SENMAX                     0x10
>>> +#define SENAVG                     0x14
>>> +#define AVGWEIGHT          0x18
>>> +#define NVALUERECIPROCAL   0x1c
>>> +#define SENERROR_V1                0x20
>>> +#define ERRCONFIG_V1               0x24
>>> +#define IRQ_EOI                    0x20
>>> +#define IRQSTATUS_RAW              0x24
>>> +#define IRQSTATUS          0x28
>>> +#define IRQENABLE_SET              0x2C
>>> +#define IRQENABLE_CLR              0x30
>>> +#define SENERROR_V2                0x34
>>> +#define ERRCONFIG_V2               0x38
>>> +
>>> +/* Bit/Shift Positions */
>>> +
>>> +/* SRCONFIG */
>>> +#define SRCONFIG_ACCUMDATA_SHIFT   22
>>> +#define SRCONFIG_SRCLKLENGTH_SHIFT 12
>>> +#define SRCONFIG_SENNENABLE_V1_SHIFT       5
>>> +#define SRCONFIG_SENPENABLE_V1_SHIFT       3
>>> +#define SRCONFIG_SENNENABLE_V2_SHIFT       1
>>> +#define SRCONFIG_SENPENABLE_V2_SHIFT       0
>>> +#define SRCONFIG_CLKCTRL_SHIFT             0
>>> +
>>> +#define SRCONFIG_ACCUMDATA_MASK            (0x3ff << 22)
>>> +
>>> +#define SRCONFIG_SRENABLE          BIT(11)
>>> +#define SRCONFIG_SENENABLE         BIT(10)
>>> +#define SRCONFIG_ERRGEN_EN         BIT(9)
>>> +#define SRCONFIG_MINMAXAVG_EN              BIT(8)
>>> +#define SRCONFIG_DELAYCTRL         BIT(2)
>>> +
>>> +/* AVGWEIGHT */
>>> +#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT      2
>>> +#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT      0
>>> +
>>> +/* NVALUERECIPROCAL */
>>> +#define NVALUERECIPROCAL_SENPGAIN_SHIFT    20
>>> +#define NVALUERECIPROCAL_SENNGAIN_SHIFT    16
>>> +#define NVALUERECIPROCAL_RNSENP_SHIFT      8
>>> +#define NVALUERECIPROCAL_RNSENN_SHIFT      0
>>> +
>>> +/* ERRCONFIG */
>>> +#define ERRCONFIG_ERRWEIGHT_SHIFT  16
>>> +#define ERRCONFIG_ERRMAXLIMIT_SHIFT        8
>>> +#define ERRCONFIG_ERRMINLIMIT_SHIFT        0
>>> +
>>> +#define SR_ERRWEIGHT_MASK          (0x07 << 16)
>>> +#define SR_ERRMAXLIMIT_MASK                (0xff << 8)
>>> +#define SR_ERRMINLIMIT_MASK                (0xff << 0)
>>> +
>>> +#define ERRCONFIG_VPBOUNDINTEN_V1  BIT(31)
>>> +#define ERRCONFIG_VPBOUNDINTST_V1  BIT(30)
>>> +#define    ERRCONFIG_MCUACCUMINTEN         BIT(29)
>>> +#define ERRCONFIG_MCUACCUMINTST            BIT(28)
>>> +#define    ERRCONFIG_MCUVALIDINTEN         BIT(27)
>>> +#define ERRCONFIG_MCUVALIDINTST            BIT(26)
>>> +#define ERRCONFIG_MCUBOUNDINTEN            BIT(25)
>>> +#define    ERRCONFIG_MCUBOUNDINTST         BIT(24)
>>> +#define    ERRCONFIG_MCUDISACKINTEN        BIT(23)
>>> +#define ERRCONFIG_VPBOUNDINTST_V2  BIT(23)
>>> +#define ERRCONFIG_MCUDISACKINTST   BIT(22)
>>> +#define ERRCONFIG_VPBOUNDINTEN_V2  BIT(22)
>>> +
>>> +#define ERRCONFIG_STATUS_V1_MASK   (ERRCONFIG_VPBOUNDINTST_V1 | \
>>> +                                   ERRCONFIG_MCUACCUMINTST | \
>>> +                                   ERRCONFIG_MCUVALIDINTST | \
>>> +                                   ERRCONFIG_MCUBOUNDINTST | \
>>> +                                   ERRCONFIG_MCUDISACKINTST)
>>> +/* IRQSTATUS */
>>> +#define IRQSTATUS_MCUACCUMINT              BIT(3)
>>> +#define IRQSTATUS_MCVALIDINT               BIT(2)
>>> +#define IRQSTATUS_MCBOUNDSINT              BIT(1)
>>> +#define IRQSTATUS_MCUDISABLEACKINT BIT(0)
>>> +
>>> +/* IRQENABLE_SET and IRQENABLE_CLEAR */
>>> +#define IRQENABLE_MCUACCUMINT              BIT(3)
>>> +#define IRQENABLE_MCUVALIDINT              BIT(2)
>>> +#define IRQENABLE_MCUBOUNDSINT             BIT(1)
>>> +#define IRQENABLE_MCUDISABLEACKINT BIT(0)
>>> +
>>> +/* Common Bit values */
>>> +
>>> +#define SRCLKLENGTH_12MHZ_SYSCLK   0x3c
>>> +#define SRCLKLENGTH_13MHZ_SYSCLK   0x41
>>> +#define SRCLKLENGTH_19MHZ_SYSCLK   0x60
>>> +#define SRCLKLENGTH_26MHZ_SYSCLK   0x82
>>> +#define SRCLKLENGTH_38MHZ_SYSCLK   0xC0
>>> +
>>> +/*
>>> + * 3430 specific values. Maybe these should be passed from board file or
>>> + * pmic structures.
>>> + */
>>> +#define OMAP3430_SR_ACCUMDATA              0x1f4
>>> +
>>> +#define OMAP3430_SR1_SENPAVGWEIGHT 0x03
>>> +#define OMAP3430_SR1_SENNAVGWEIGHT 0x03
>>> +
>>> +#define OMAP3430_SR2_SENPAVGWEIGHT 0x01
>>> +#define OMAP3430_SR2_SENNAVGWEIGHT 0x01
>>> +
>>> +#define OMAP3430_SR_ERRWEIGHT              0x04
>>> +#define OMAP3430_SR_ERRMAXLIMIT            0x02
>>> +
>>> +/* TODO:3630/OMAP4 values if it has to come from this file */
>>> +
>>> +/**
>>> + * omap_smartreflex_dev_data - Smartreflex device specific data
>>
>>omap_sr..

Will correct

>>
>>> + * @volts_supported        : Number of distinct voltages possible for the VDD
>>> + *                   associated with this smartreflex module.
>>> + * @efuse_sr_control       : The regisrter offset of control_fuse_sr efuse
>>> + *                   register from which sennenable and senpenable values
>>> + *                   are obtained.
>>> + * @sennenable_shift       : The shift in the control_fuse_sr register for
>>> + *                   obtaining the sennenable value for this smartreflex
>>> + *                   module.
>>> + * @senpenable_shift       : The shift in the control_fuse_sr register for
>>> + *                   obtaining the senpenable value for this smartreflex
>>> + *                   module.
>>> + * @efuse_nvalues_offs     : Array of efuse offsets from which ntarget
>>values can
>>> + *                   be retrieved. Number of efuse offsets in this arrray
>>> + *                   is equal to the volts_supported value ie one efuse
>>> + *                   register per supported voltage.
>>> + * @test_sennenable        : SENNENABLE test value
>>> + * @test_senpenable        : SENPENABLE test value.
>>> + * @test_nvalues   : Array of test ntarget values.
>>> + * @vdd_name               : Name of the voltage domain associated with this
>>> + *                   Smartreflex device.
>>> + * @volt_data              : Voltage table associated with this smartreflex
>>module
>>> + */
>>> +struct omap_sr_dev_data {
>>> +   int volts_supported;
>>> +   u32 efuse_sr_control;
>>> +   u32 sennenable_shift;
>>> +   u32 senpenable_shift;
>>> +   u32 *efuse_nvalues_offs;
>>> +   u32 test_sennenable;
>>> +   u32 test_senpenable;
>>> +   u32 *test_nvalues;
>>> +   char *vdd_name;
>>> +   struct omap_volt_data *volt_data;
>>> +};
>>> +
>>> +/**
>>> + * omap_smartreflex_pmic_data : Strucutre to be populated by pmic code to
>>pass
>>> + * pmic specific info to smartreflex driver
>>> + *
>>> + * @sr_pmic_init - API to initialize smartreflex on the PMIC side.
>>> + */
>>> +struct omap_smartreflex_pmic_data {
>>
>>omap_sr..

Will correct.
>>
>>> +   void (*sr_pmic_init) (void);
>>> +};
>>> +
>>> +#ifdef CONFIG_OMAP_SMARTREFLEX
>>> +/*
>>> + * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
>>> + * The smartreflex class driver should pass the class type.
>>> + * Should be used to populate the class_type field of the
>>> + * omap_smartreflex_class_data structure.
>>> + */
>>> +#define SR_CLASS1  0x1
>>> +#define SR_CLASS2  0x2
>>> +#define SR_CLASS3  0x3
>>> +
>>> +/**
>>> + * omap_smartreflex_class_data : Structure to be populated by
>>
>>omap_sr...

Will correct.

>>
>>> + * Smartreflex class driver with corresponding class enable disable API's
>>> + *
>>> + * @enable - API to enable a particular class smaartreflex.
>>> + * @disable - API to disable a particular class smartreflex.
>>> + * @configure - API to configure a particular class smartreflex.
>>> + * @notify - API to notify the class driver about an event in SR. Not
>>needed
>>> + *         for class3.
>>> + * @notify_flags - specify the events to be notified to the class driver
>>> + * @class_type - specify which smartreflex class. Can be used by the SR
>>driver
>>> + *         to take any class based decisions.
>>> + */
>>> +struct omap_smartreflex_class_data {
>>
>>omap_sr
>>
>>> +   int (*enable)(struct voltagedomain *voltdm);
>>> +   int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
>>> +   int (*configure)(struct voltagedomain *voltdm);
>>> +   int (*notify)(struct voltagedomain *voltdm, u32 status);
>>> +   u8 notify_flags;
>>> +   u8 class_type;
>>> +};
>>> +
>>> +/**
>>> + * omap_smartreflex_data - Smartreflex platform data
>>
>>omap_sr
Will correct

>>
>>> + * @senp_mod               : SENPENABLE value for the sr
>>> + * @senn_mod               : SENNENABLE value for sr
>>> + * @sr_nvalue              : array of n target values for sr
>>> + * @enable_on_init : whether this sr module needs to enabled at
>>> + *                   boot up or not.
>>> + * @voltdm         : Pointer to the voltage domain associated with the
>>SR
>>> + */
>>> +struct omap_sr_data {
>>> +   u32                             senp_mod;
>>> +   u32                             senn_mod;
>>> +   bool                            enable_on_init;
>>> +   struct voltagedomain            *voltdm;
>>> +};
>>> +
>>> +/*
>>> + * Smartreflex module enable/disable interface.
>>> + * NOTE: if smartreflex is not enabled from sysfs, these functions will
>>not
>>> + * do anything.
>>> + */
>>
>>The 'NOTE' comment isn't quite accurate (and probably not needed here.)
>>The 'enable_on_init' flag is another way besides sysfs for these
>>functions to be activated.
>>
>>This enable_on_init flag (also settable by board files) should probably
>>be mentioned in the changelog too where you mention how SR can be
>>enabled.

Will do this

>>
>>> +void omap_sr_enable(struct voltagedomain *voltdm);
>>> +void omap_sr_disable(struct voltagedomain *voltdm);
>>> +void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
>>> +
>>> +/* API to register the pmic specific data with the smartreflex driver. */
>>> +void omap_sr_register_pmic(struct omap_smartreflex_pmic_data *pmic_data);
>>> +
>>> +/* Smartreflex driver hooks to be called from Smartreflex class driver */
>>> +int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
>>> +void sr_disable(struct voltagedomain *voltdm);
>>> +int sr_configure_errgen(struct voltagedomain *voltdm);
>>> +int sr_configure_minmax(struct voltagedomain *voltdm);
>>> +
>>> +/* API to register the smartreflex class driver with the smartreflex
>>driver */
>>> +int sr_register_class(struct omap_smartreflex_class_data *class_data);
>>> +#else
>>> +static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
>>> +static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
>>> +static inline void omap_sr_disable_reset_volt(
>>> +           struct voltagedomain *voltdm) {}
>>> +static inline void omap_sr_register_pmic(
>>> +           struct omap_smartreflex_pmic_data *pmic_data) {}
>>> +#endif
>>> +#endif
>>
>>Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux