devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Gururaja Hebbar <gururaja.hebbar@ti.com>
To: Russ Dill <Russ.Dill@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>,
	devicetree@vger.kernel.org, devicetree-discuss@lists.ozlabs.org,
	linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v4 1/4] ARM: OMAP2+: AM33XX: I2C Sleep/wake sequence support
Date: Mon, 19 Aug 2013 11:19:53 +0530	[thread overview]
Message-ID: <5211B201.2000401@ti.com> (raw)
In-Reply-To: <CA+Bv8XZ-QGhVV1mK=rRekOZzaTDN-Y9YkWYYoEc8EtvP0JouEA@mail.gmail.com>

On 8/15/2013 4:04 AM, Russ Dill wrote:
> On Wed, Aug 14, 2013 at 3:18 AM, Gururaja Hebbar <gururaja.hebbar@ti.com> wrote:
>> On 8/14/2013 3:50 AM, Russ Dill wrote:
>>> Changes since v1:
>>> * Rebased onto new am335x PM branch
>>> * Changed to use 5th param register

>>

[snip]
[snip]

>>> +
>>> +     wkup_m3_reset_data_pos();
>>> +     if (am33xx_i2c_sleep_sequence) {
>>> +             pos = wkup_m3_copy_data(am33xx_i2c_sleep_sequence,
>>> +                                             i2c_sleep_sequence_sz);
>>
>> Why do we need to copy this data (same constant data) on every iteration?
> 
> Because the CM3 firmware is reset after each suspend/resume cycle. The
> firmware reset handler reinitializes the DMEM.

Well in that why can't the i2c payload be copied to UMEM?

Thanks & regards
Gururaja

> 
>>> +             /* Lower 16 bits stores offset to sleep sequence */
>>> +             param4 &= ~0xffff;
>>> +             param4 |= pos;
>>> +     }
>>> +
>>> +     if (am33xx_i2c_wake_sequence) {
>>> +             pos = wkup_m3_copy_data(am33xx_i2c_wake_sequence,
>>> +                                             i2c_wake_sequence_sz);
>>> +             /* Upper 16 bits stores offset to wake sequence */
>>> +             param4 &= ~0xffff0000;
>>> +             param4 |= pos << 16;
>>> +     }
>>> +
>>
>> Seems above entire change can be done only once.
>>
>>>       am33xx_pm->ipc.sleep_mode       = IPC_CMD_DS0;
>>>       am33xx_pm->ipc.param1           = DS_IPC_DEFAULT;
>>>       am33xx_pm->ipc.param2           = DS_IPC_DEFAULT;
>>> +     am33xx_pm->ipc.param4           = param4;
>>>
>>>       am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
>>>
>>> @@ -386,6 +413,62 @@ static int __init am33xx_map_emif(void)
>>>       return 0;
>>>  }
>>>
>>> +static int __init am33xx_setup_sleep_sequence(void)
>>> +{
>>> +     int ret;
>>> +     int sz;
>>> +     const void *prop;
>>> +     struct device *dev;
>>> +     u32 freq_hz = 100000;
>>
>> Magic number?
> 
> It's taken from drivers/i2c/busses/i2c-omap.c
> 
>     u32 freq = 100000; /* default to 100000 Hz */
> 
> I'll add a comment to that effect.
> 
>>> +     unsigned short freq_khz;
>>> +
>>> +     /*
>>> +      * We put the device tree node in the I2C controller that will
>>> +      * be sending the sequence. i2c1 is the only controller that can
>>> +      * be accessed by the firmware as it is the only controller in the
>>> +      * WKUP domain.
>>
>> and on which the PMIC sits I believe?
> 
> Yes, but this code is designed not to be PMIC specific as one could
> chose to regulate VDD_CORE with any PMIC, or even with a standalone
> I2C controlled regulator.
> 
>>> +      */
>>> +     dev = omap_device_get_by_hwmod_name("i2c1");
>>> +     if (IS_ERR(dev))
>>> +             return PTR_ERR(dev);
>>> +
>>> +     of_property_read_u32(dev->of_node, "clock-frequency", &freq_hz);
>>> +     freq_khz = freq_hz / 1000;
>>
>> Magic number?
> 
> Nah, converting between metric prefixes this way is pretty common in the kernel.
> 
>>> +
>>> +     prop = of_get_property(dev->of_node, "sleep_sequence", &sz);
>>> +     if (prop) {
>>> +             /*
>>> +              * Length is sequence length + 2 bytes for freq_khz, and 1
>>> +              * byte for terminator.
>>> +              */
>>> +             am33xx_i2c_sleep_sequence = kzalloc(sz + 3, GFP_KERNEL);
>>> +             if (!am33xx_i2c_sleep_sequence)
>>> +                     return -ENOMEM;
>>> +             put_unaligned_le16(freq_khz, am33xx_i2c_sleep_sequence);
>>> +             memcpy(am33xx_i2c_sleep_sequence + 2, prop, sz);
>>
>> so, looking at entire code, it seems there is 3 memory space for same
>> data (or 1 original + 2 copy)
>>
>> 1. in DT
>> 2. in am33xx_i2c_[sleep/wake]_sequence
>> 3. in SRAm by call to wkup_m3_copy_data()
>>
>> why not directly copy to SRAM from DT?
> 
> As pointed out above, the firmware reset handler would wipe it out.
> 
>>> +             i2c_sleep_sequence_sz = sz + 3;
>>> +     }
>>> +
>>> +     prop = of_get_property(dev->of_node, "wake_sequence", &sz);
>>> +     if (prop) {
>>> +             am33xx_i2c_wake_sequence = kzalloc(sz + 3, GFP_KERNEL);
>>> +             if (!am33xx_i2c_wake_sequence) {
>>> +                     ret = -ENOMEM;
>>> +                     goto cleanup_sleep;
>>> +             }
>>> +             put_unaligned_le16(freq_khz, am33xx_i2c_sleep_sequence);
>>> +             memcpy(am33xx_i2c_wake_sequence + 2, prop, sz);
>>> +             i2c_wake_sequence_sz = sz + 3;
>>> +     }
>>> +
>>> +     return 0;
>>> +
>>> +cleanup_sleep:
>>> +     kfree(am33xx_i2c_sleep_sequence);
>>> +     am33xx_i2c_sleep_sequence = NULL;
>>> +     return ret;
>>> +}
>>> +
>>>  int __init am33xx_pm_init(void)
>>>  {
>>>       int ret;
>>> @@ -451,6 +534,12 @@ int __init am33xx_pm_init(void)
>>>               }
>>>       }
>>>
>>> +     ret = am33xx_setup_sleep_sequence();
>>> +     if (ret) {
>>> +             pr_err("Error fetching I2C sleep/wake sequence\n");
>>> +             goto err;
>>> +     }
>>> +
>>>       (void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
>>>
>>>       /* CEFUSE domain can be turned off post bootup */
>>> diff --git a/arch/arm/mach-omap2/pm33xx.h b/arch/arm/mach-omap2/pm33xx.h
>>> index befdd11..d0f08a5 100644
>>> --- a/arch/arm/mach-omap2/pm33xx.h
>>> +++ b/arch/arm/mach-omap2/pm33xx.h
>>> @@ -52,6 +52,8 @@ struct forced_standby_module {
>>>  };
>>>
>>>  int wkup_m3_copy_code(const u8 *data, size_t size);
>>> +void wkup_m3_reset_data_pos(void);
>>> +int wkup_m3_copy_data(const u8 *data, size_t size);
>>>  int wkup_m3_prepare(void);
>>>  void wkup_m3_register_txev_handler(void (*txev_handler)(void));
>>>
>>> diff --git a/arch/arm/mach-omap2/wkup_m3.c b/arch/arm/mach-omap2/wkup_m3.c
>>> index 8eaa7f3..a541de9 100644
>>> --- a/arch/arm/mach-omap2/wkup_m3.c
>>> +++ b/arch/arm/mach-omap2/wkup_m3.c
>>> @@ -35,6 +35,9 @@
>>>  struct wkup_m3_context {
>>>       struct device   *dev;
>>>       void __iomem    *code;
>>> +     void __iomem    *data;
>>> +     void __iomem    *data_end;
>>> +     size_t          data_size;
>>>       void (*txev_handler)(void);
>>>  };
>>>
>>> @@ -50,6 +53,30 @@ int wkup_m3_copy_code(const u8 *data, size_t size)
>>>       return 0;
>>>  }
>>>
>>> +/*
>>> + * This pair of functions allows data to be stuffed into the end of the
>>> + * CM3 data memory. This is currently used for passing the I2C sleep/wake
>>> + * sequences to the firmware.
>>> + */
>>> +
>>> +/* Clear out the pointer for data stored at the end of DMEM */
>>> +void wkup_m3_reset_data_pos(void)
>>> +{
>>> +     wkup_m3->data_end = wkup_m3->data + wkup_m3->data_size;
>>> +}
>>> +
>>> +/*
>>> + * Store a block of data at the end of DMEM, return the offset within DMEM
>>> + * that the data is stored at, or -ENOMEM if the data did not fit
>>> + */
>>> +int wkup_m3_copy_data(const u8 *data, size_t size)
>>> +{
>>> +     if (wkup_m3->data + size > wkup_m3->data_end)
>>> +             return -ENOMEM;
>>> +     wkup_m3->data_end -= size;
>>> +     memcpy_toio(wkup_m3->data_end, data, size);
>>> +     return wkup_m3->data_end - wkup_m3->data;
>>> +}
>>>
>>>  void wkup_m3_register_txev_handler(void (*txev_handler)(void))
>>>  {
>>> @@ -83,7 +110,7 @@ int wkup_m3_prepare(void)
>>>  static int wkup_m3_probe(struct platform_device *pdev)
>>>  {
>>>       int irq, ret = 0;
>>> -     struct resource *mem;
>>> +     struct resource *umem, *dmem;
>>>
>>>       pm_runtime_enable(&pdev->dev);
>>>
>>> @@ -95,14 +122,21 @@ static int wkup_m3_probe(struct platform_device *pdev)
>>>
>>>       irq = platform_get_irq(pdev, 0);
>>>       if (!irq) {
>>> -             dev_err(wkup_m3->dev, "no irq resource\n");
>>> +             dev_err(&pdev->dev, "no irq resource\n");
>>
>> unrelated change?. Better to mention this as code cleanup in commit.
> 
> Will add a comment to that effect, the underlying error should be
> fixed in the next suspend/resume patch though.
> 
>>> +             ret = -ENXIO;
>>> +             goto err;
>>> +     }
>>> +
>>> +     umem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +     if (!umem) {
>>> +             dev_err(&pdev->dev, "no UMEM resource\n");
>>>               ret = -ENXIO;
>>>               goto err;
>>>       }
>>>
>>> -     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> -     if (!mem) {
>>> -             dev_err(wkup_m3->dev, "no memory resource\n");
>>> +     dmem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>>> +     if (!dmem) {
>>> +             dev_err(&pdev->dev, "no DMEM resource\n");
>>>               ret = -ENXIO;
>>>               goto err;
>>>       }
>>> @@ -116,12 +150,21 @@ static int wkup_m3_probe(struct platform_device *pdev)
>>>
>>>       wkup_m3->dev = &pdev->dev;
>>>
>>> -     wkup_m3->code = devm_request_and_ioremap(wkup_m3->dev, mem);
>>> +     wkup_m3->code = devm_request_and_ioremap(wkup_m3->dev, umem);
>>> +     if (!wkup_m3->code) {
>>> +             dev_err(wkup_m3->dev, "could not ioremap UMEM\n");
>>
>> why not use "pdev->dev" here?
> 
> Either one works
> 
>>> +             ret = -EADDRNOTAVAIL;
>>> +             goto err;
>>> +     }
>>> +
>>> +     wkup_m3->data = devm_request_and_ioremap(wkup_m3->dev, dmem);
>>>       if (!wkup_m3->code) {
>>
>> I believe this is just a copy/paste error. s/code/data
> 
> Doh, thanks!
> 
>>> -             dev_err(wkup_m3->dev, "could not ioremap\n");
>>> +             dev_err(wkup_m3->dev, "could not ioremap DMEM\n");
>>
>> same as above.
>>
>>>               ret = -EADDRNOTAVAIL;
>>>               goto err;
>>>       }
>>> +     wkup_m3->data_size = resource_size(dmem);
>>> +     wkup_m3_reset_data_pos();
>>>
>>>       ret = devm_request_irq(wkup_m3->dev, irq, wkup_m3_txev_handler,
>>>                 IRQF_DISABLED, "wkup_m3_txev", NULL);
>>> -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe
>>> linux-omap" in the body of a message to majordomo@vger.kernel.org More
>>> majordomo info at http://vger.kernel.org/majordomo-info.html
>>>
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


  parent reply	other threads:[~2013-08-19  5:49 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-13 22:20 [PATCH v4 0/4] ARM: OMAP2+: AM33XX: VDD CORE OPP50 support Russ Dill
2013-08-13 22:20 ` [PATCH v4 1/4] ARM: OMAP2+: AM33XX: I2C Sleep/wake sequence support Russ Dill
2013-08-14 10:18   ` Gururaja Hebbar
2013-08-14 22:34     ` Russ Dill
2013-08-16  7:16       ` Gururaja Hebbar
2013-08-19  5:49       ` Gururaja Hebbar [this message]
2013-08-20 16:33         ` Russ Dill
2013-08-21  8:29           ` Gururaja Hebbar
2013-08-13 22:20 ` [PATCH v4 2/4] ARM: dts: add AM33XX vdd core opp50 suspend for Beaglebone Russ Dill
2013-08-14  8:59   ` Gururaja Hebbar
2013-08-14 22:21     ` Russ Dill
2013-08-13 22:20 ` [PATCH v4 3/4] ARM: dts: add AM33XX vdd core opp50 suspend for AM335X GP EVM Russ Dill
2013-08-13 22:20 ` [PATCH v4 4/4] ARM: dts: AM33XX vdd core opp50 suspend for EVM-SK Russ Dill
2013-08-14 13:38 ` [PATCH v4 0/4] ARM: OMAP2+: AM33XX: VDD CORE OPP50 support Jan Lübbe
2013-08-14 22:21   ` Russ Dill
2013-08-15  8:00     ` Jan Lübbe
2013-08-27 22:44     ` Kevin Hilman
2013-08-28  1:05       ` Russ Dill
2013-08-29 11:05         ` Mark Brown
2013-08-29 15:29           ` Kevin Hilman
2013-08-29 15:49             ` Mark Brown
2013-08-29 16:31               ` Russ Dill
2013-08-29 17:30                 ` Mark Brown
2013-08-29 17:47                   ` Russ Dill
2013-08-29 18:03                     ` Mark Brown
2013-08-29 18:28                       ` Russ Dill
2013-08-29 15:42           ` Russ Dill
2013-08-29 18:01             ` Mark Brown
2013-08-29 18:25               ` Russ Dill
2013-08-29 19:10                 ` Mark Brown
2013-09-03 14:06                   ` Russ Dill
2013-09-03 14:39                     ` Mark Brown
2013-08-29 15:17         ` Kevin Hilman
2013-08-29 16:10           ` Russ Dill
2013-08-29 19:11             ` Kevin Hilman
2013-08-29 20:09               ` Vaibhav Bedia
2013-08-29 21:33                 ` Kevin Hilman
2013-08-30  0:25                   ` Russ Dill
2013-08-30 16:06                     ` Kevin Hilman
2013-09-03 18:55                       ` Russ Dill
2013-09-03 19:07                         ` Kevin Hilman
2013-08-30 17:57                   ` Vaibhav Bedia

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5211B201.2000401@ti.com \
    --to=gururaja.hebbar@ti.com \
    --cc=Russ.Dill@ti.com \
    --cc=devicetree-discuss@lists.ozlabs.org \
    --cc=devicetree@vger.kernel.org \
    --cc=khilman@deeprootsystems.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-omap@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).