From mboxrd@z Thu Jan 1 00:00:00 1970 From: Colin FoeParker Subject: RE: [PATCH 2/4] rtc: OMAP: Add system pm_power_off to rtc driver Date: Mon, 5 Nov 2012 11:39:26 -0600 Message-ID: <0520A3FE5EDCF24F88B3F1451CFC64AE059F92FA8F@edprex01> References: <1352108549-9341-1-git-send-email-anilkumar@ti.com> <1352108549-9341-3-git-send-email-anilkumar@ti.com> <5097ECAD.9010101@ti.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2390053880300757345==" Return-path: In-Reply-To: <5097ECAD.9010101-l0cyMroinI0@public.gmane.org> Content-Language: en-US List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: devicetree-discuss-bounces+gldd-devicetree-discuss=m.gmane.org-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org Sender: "devicetree-discuss" To: Benoit Cousson , AnilKumar Ch Cc: "a.zummo-BfzFCNDTiLLj+vYz1yj4TQ@public.gmane.org" , "sameo-VuQAYsv1563Yd54FQh9/CA@public.gmane.org" , "rtc-linux-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org" , "devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org" , "rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org" , "linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" , "linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org" List-Id: devicetree@vger.kernel.org --===============2390053880300757345== Content-Language: en-US Content-Type: multipart/alternative; boundary="_000_0520A3FE5EDCF24F88B3F1451CFC64AE059F92FA8Fedprex01_" --_000_0520A3FE5EDCF24F88B3F1451CFC64AE059F92FA8Fedprex01_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Benoit, "I don't know how it is connected at board level, but I'm not sure the bind= ing is the proper one." Here is a link to the Beaglebone schematic. The PMIC_PWR_EN net is the on= e that you should be interested in following. In the AM335x, this net is connected to the ALARM2 event in the RTC subsyst= em. If the ALARM2 event is triggered, and the PMIC_PWR_EN pin is configure= d correctly, the pin is driven low. In the TPS65217 series PMIC, the PWR_EN I/O can be used to put the entire c= hip into a low power state. This disables all the power rails in the PMIC = with an exception of the rail that powers the RTC power domain. So when the ALARM2 event occurs, the PWR_EN I/O is pulled low and the entir= e system into a low power "off" state. "It does not look super generic, and I'm wondering if we should not use ins= tead some regulator binding to reflect the connection of the RTC to a regul= ator. But without the board / soc spec it is hard to tell :-(" This is a good point. I know that there are other omap SOC RTC's that do n= ot support the ALARM2 implementation. That being said, I would argue that = there is more of a RTC connection with the implementation than a regulator. Anil will probably have greater insight into the pro's/con's of the impleme= ntation. -Colin Colin Foe-Parker // Software Engineer II Logic PD /// engineering design services 5 Clock Tower Place. Suite 400 Maynard, MA 01754 T // 978.243.2045 colin.foeparker-L+YfUVVR8+RBDgjK7y7TUQ@public.gmane.org www.logicpd.com / / / / / / / / / / / / / / / / / / / / / / / / / This message (including any attachments) contains confidential information = intended for a specific individual and purpose, and is protected by law. If= you are not the intended recipient, you should delete this message and are= hereby notified that any disclosure, copying, distribution, or other use o= f this message, or the taking of any action based on it, is strictly prohib= ited. -----Original Message----- From: Benoit Cousson [mailto:b-cousson-l0cyMroinI0@public.gmane.org] Sent: Monday, November 05, 2012 11:43 AM To: AnilKumar Ch; Colin FoeParker Cc: a.zummo-BfzFCNDTiLLj+vYz1yj4TQ@public.gmane.org; sameo-VuQAYsv1563Yd54FQh9/CA@public.gmane.org; tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org; grant.li= kely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org; rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org; rtc-linux-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org; lin= ux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org; devicetree-d= iscuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org Subject: Re: [PATCH 2/4] rtc: OMAP: Add system pm_power_off to rtc driver Hi Anil / Colin, On 11/05/2012 10:42 AM, AnilKumar Ch wrote: > From: Colin Foe-Parker > > Add system power off control to rtc driver which is the in-charge of > controlling the BeagleBone system power. The power_off routine can be > hooked up to "pm_power_off" system call. > > System power off sequence:- > * Set PMIC STATUS_OFF when PMIC_POWER_EN is pulled low > * Enable PMIC_POWER_EN in rtc module > * Set rtc ALARM2 time > * Enable ALARM2 interrupt > > Added while (1); after the above steps to make sure that no other > process acquire cpu. Otherwise we might see an unexpected behaviour > because we are shutting down all the power rails of SoC except RTC. > > Signed-off-by: Colin Foe-Parker > > [anilkumar-l0cyMroinI0@public.gmane.org: move poweroff additions to rtc driver] > Signed-off-by: AnilKumar Ch > > --- > Documentation/devicetree/bindings/rtc/rtc-omap.txt | 5 ++ > drivers/rtc/rtc-omap.c | 79 ++++++++++++++= +++++- > 2 files changed, 83 insertions(+), 1 deletion(-) > > diff --git a/Documentation/devicetree/bindings/rtc/rtc-omap.txt > b/Documentation/devicetree/bindings/rtc/rtc-omap.txt > index b47aa41..8d9f4f9 100644 > --- a/Documentation/devicetree/bindings/rtc/rtc-omap.txt > +++ b/Documentation/devicetree/bindings/rtc/rtc-omap.txt > @@ -6,6 +6,10 @@ Required properties: > - interrupts: rtc timer, alarm interrupts in order > - interrupt-parent: phandle for the interrupt controller > > +Optional properties: > +- ti,system-power-controller: Telling whether or not rtc is > +controlling > + the system power. I don't know how it is connected at board level, but I'm not sure the bindi= ng is the proper one. It does not look super generic, and I'm wondering if we should not use inst= ead some regulator binding to reflect the connection of the RTC to a regula= tor. But without the board / soc spec it is hard to tell :-( Regards, Benoit > + > Example: > > rtc@1c23000 { > @@ -14,4 +18,5 @@ rtc@1c23000 { > interrupts =3D <19 > 19>; > interrupt-parent =3D <&intc>; > + ti,system-power-controller; > }; > diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index > 6009714..2d90170 100644 > --- a/drivers/rtc/rtc-omap.c > +++ b/drivers/rtc/rtc-omap.c > @@ -72,6 +72,14 @@ > #define OMAP_RTC_KICK0_REG 0x6c > #define OMAP_RTC_KICK1_REG 0x70 > > +#define OMAP_RTC_ALARM2_SECONDS_REG 0x80 > +#define OMAP_RTC_ALARM2_MINUTES_REG 0x84 > +#define OMAP_RTC_ALARM2_HOURS_REG 0x88 > +#define OMAP_RTC_ALARM2_DAYS_REG 0x8c > +#define OMAP_RTC_ALARM2_MONTHS_REG 0x90 > +#define OMAP_RTC_ALARM2_YEARS_REG 0x94 > +#define OMAP_RTC_PMIC_REG 0x98 > + > /* OMAP_RTC_CTRL_REG bit fields: */ > #define OMAP_RTC_CTRL_SPLIT (1<<7) > #define OMAP_RTC_CTRL_DISABLE (1<<6) > @@ -93,15 +101,24 @@ > #define OMAP_RTC_STATUS_BUSY (1<<0) > > /* OMAP_RTC_INTERRUPTS_REG bit fields: */ > +#define OMAP_RTC_INTERRUPTS_IT_ALARM2 (1<<4) > #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) > #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) > > +/* OMAP_RTC_PMIC_REG bit fields: */ > +#define OMAP_RTC_PMIC_POWER_EN_EN (1<<16) > + > /* OMAP_RTC_KICKER values */ > #define KICK0_VALUE 0x83e70= b13 > #define KICK1_VALUE 0x95a4f= 1e0 > > #define OMAP_RTC_HAS_KICKER 0x1 > > +#define SHUTDOWN_TIME_SEC 2 > +#define SECS_IN_MIN 60 > +#define WAIT_AFTER (SECS_IN= _MIN - SHUTDOWN_TIME_SEC) > +#define WAIT_TIME_MS (SHUTDOWN_TIM= E_SEC * 1000) > + > static void __iomem *rtc_base; > > #define rtc_read(addr) readb(rtc_base + (addr= )) > @@ -290,6 +307,58 @@ static int omap_rtc_set_alarm(struct device *dev, st= ruct rtc_wkalrm *alm) > return 0; > } > > +/* > + * rtc_power_off: Set the pmic power off sequence. The RTC generates > + * pmic_pwr_enable control, which can be used to control an external > + * PMIC. > + */ > +static void rtc_power_off(void) > +{ > + u32 val; > + struct rtc_time tm; > + spinlock_t lock; > + unsigned long flags; > + > + spin_lock_init(&lock); > + > + /* Set PMIC power enable */ > + val =3D readl(rtc_base + OMAP_RTC_PMIC_REG); > + writel(val | OMAP_RTC_PMIC_POWER_EN_EN, rtc_base + > +OMAP_RTC_PMIC_REG); > + > + /* Wait few seconds instead of rollover */ > + do { > + omap_rtc_read_time(NULL, &tm); > + if (WAIT_AFTER <=3D tm.tm_sec) > + mdelay(WAIT_TIME_MS); > + } while (WAIT_AFTER <=3D tm.tm_sec); > + > + /* Add shutdown time to the current value */ > + tm.tm_sec +=3D SHUTDOWN_TIME_SEC; > + > + if (tm2bcd(&tm) < 0) > + return; > + > + pr_info("System will go to power_off state in approx. %d secs\= n", > + SHUTDOWN_TIME_SEC); > + > + /* Set the ALARM2 time */ > + rtc_write(tm.tm_sec, OMAP_RTC_ALARM2_SECONDS_REG); > + rtc_write(tm.tm_min, OMAP_RTC_ALARM2_MINUTES_REG); > + rtc_write(tm.tm_hour, OMAP_RTC_ALARM2_HOURS_REG); > + rtc_write(tm.tm_mday, OMAP_RTC_ALARM2_DAYS_REG); > + rtc_write(tm.tm_mon, OMAP_RTC_ALARM2_MONTHS_REG); > + rtc_write(tm.tm_year, OMAP_RTC_ALARM2_YEARS_REG); > + > + /* Enable alarm2 interrupt */ > + val =3D readl(rtc_base + OMAP_RTC_INTERRUPTS_REG); > + writel(val | OMAP_RTC_INTERRUPTS_IT_ALARM2, > + rtc_base + OMA= P_RTC_INTERRUPTS_REG); > + > + /* Do not allow to execute any other task */ > + spin_lock_irqsave(&lock, flags); > + while (1); > +} > + > static struct rtc_class_ops omap_rtc_ops =3D { > .read_time =3D omap_rtc_read_time, > .set_time =3D omap_rtc_set_time, > @@ -327,12 +396,16 @@ static int __init omap_rtc_probe(struct platform_de= vice *pdev) > struct resource *res, *mem; > struct rtc_device *rtc; > u8 reg, new_ctrl; > + bool pm_off =3D false; > const struct platform_device_id *id_entry; > const struct of_device_id *of_id; > > of_id =3D of_match_device(omap_rtc_of_match, &pdev->dev); > - if (of_id) > + if (of_id) { > pdev->id_entry =3D of_id->data; > + pm_off =3D of_property_read_bool(pdev->dev.of_= node, > + = "ti,system-power-controller"); > + } > > omap_rtc_timer =3D platform_get_irq(pdev, 0); > if (omap_rtc_timer <=3D 0) { > @@ -385,6 +458,10 @@ static int __init omap_rtc_probe(struct platform_dev= ice *pdev) > platform_set_drvdata(pdev, rtc); > dev_set_drvdata(&rtc->dev, mem); > > + /* RTC power off */ > + if (pm_off && !pm_power_off) > + pm_power_off =3D rtc_power_off; > + > /* clear pending irqs, and set 1/second periodic, > * which we'll use instead of update irqs > */ > --_000_0520A3FE5EDCF24F88B3F1451CFC64AE059F92FA8Fedprex01_ Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

Hi Benoit,

 

“I don't know how it is connected at board = level, but I'm not sure the binding is the proper one.”

 

Here is a link to the Beaglebone schematic.  The PM= IC_PWR_EN net is the one that you should be interested in following.

 

In the AM335x, this net is connected to the ALARM2 event in the RTC subsy= stem.  If the ALARM2 event is triggered, and the PMIC_PWR_EN pin is co= nfigured correctly, the pin is driven low.

 

In the TPS65217 series P= MIC, the PWR_EN I/O can be used to put the entire chip into a low power sta= te.  This disables all the power rails in the PMIC with an exception o= f the rail that powers the RTC power domain.

 

So when the ALARM2 eve= nt occurs, the PWR_EN I/O is pulled low and the entire system into a low po= wer “off” state.

&nb= sp;

“It does not look super ge= neric, and I'm wondering if we should not use instead some regulator bindin= g to reflect the connection of the RTC to a regulator.

 

But without the board / soc spec it is hard to tell :-(R= 20;

 

This is a good point.  I know that there are other= omap SOC RTC’s that do not support the ALARM2 implementation.  = That being said, I would argue that there is more of a RTC connection with = the implementation than a regulator.

=  

Anil will probably have greate= r insight into the pro’s/con’s of the implementation.

 

-= Colin

 

 

Colin Foe-Park= er // Software Engineer II

=  

 

 

Logic PD /// e= ngineering design services

5 Clock To= wer Place. Suite 400

Maynard, MA 0175= 4

T // 978.243.2045

 

colin.foe= parker-L+YfUVVR8+RBDgjK7y7TUQ@public.gmane.org

www.logicpd.com

/ / / / / / / / / / / / / / / / / / / /= / / / / /

This message (including an= y attachments) contains confidential information intended for a specific in= dividual and purpose, and is protected by law. If you are not the intended = recipient, you should delete this message and are hereby notified that any = disclosure, copying, distribution, or other use of this message, or the tak= ing of any action based on it, is strictly prohibited.

 

 <= /o:p>

-----Original Message-----
From: Benoit= Cousson [mailto:b-cousson-l0cyMroinI0@public.gmane.org]
Sent: Monday, November 05, 2012 11:4= 3 AM
To: AnilKumar Ch; Colin FoeParker
Cc: a.zummo-BfzFCNDTiLLj+vYz1yj4TQ@public.gmane.org; same= o@linux.intel.com; tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org; grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org; rob.herring= @calxeda.com; rtc-linux-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org; linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux= -arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org; devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Sub= ject: Re: [PATCH 2/4] rtc: OMAP: Add system pm_power_off to rtc driver

<= p class=3DMsoPlainText> 

Hi Anil= / Colin,

 

On 11/05/2012 10:42 AM, AnilKumar Ch wrote:

> From: Colin Foe-Parker <colin.foeparker@lo= gicpd.com>

>

> Add system power off control to rtc driver which = is the in-charge of

> controlling= the BeagleBone system power. The power_off routine can be

<= p class=3DMsoPlainText>> hooked up to "pm_power_off" system ca= ll.

>

> System power off sequence:-

> * Set PMIC STATUS_OFF when PMIC_POWER_EN is pulled low

> * Enable PMIC_POWER_EN in rtc module

> * Set rtc ALARM2 time

> * Enable ALARM2 interrupt

>

> Added w= hile (1); after the above steps to make sure that no other

<= p class=3DMsoPlainText>> process acquire cpu. Otherwise we might see an = unexpected behaviour

> because we= are shutting down all the power rails of SoC except RTC.

>

> Signe= d-off-by: Colin Foe-Parker <colin.foeparker@lo= gicpd.com>

> [anilku= mar-l0cyMroinI0@public.gmane.org: move poweroff additions to rtc driver]

> Signed-off-by: AnilKumar Ch <anilkum= ar-l0cyMroinI0@public.gmane.org>

> ---

>  Documentation/devicetree/bind= ings/rtc/rtc-omap.txt |    5 ++

>  drivers/rtc/rtc-omap.c     &n= bsp;            = ;           |  = 79 +++++++++++++++++++-

>  2= files changed, 83 insertions(+), 1 deletion(-)

>

> diff --git a/Do= cumentation/devicetree/bindings/rtc/rtc-omap.txt

> b/Documentation/devicetree/bindings/rtc/rtc-omap.txt=

> index b47aa41..8d9f4f9 100644

> --- a/Documentation/devicetree/binding= s/rtc/rtc-omap.txt

> +++ b/Documen= tation/devicetree/bindings/rtc/rtc-omap.txt

> @@ -6,6 +6,10 @@ Required properties:

>  - interrupts: rtc timer, alarm interrupts in order<= o:p>

>  - interrupt-parent: phandl= e for the interrupt controller

>&n= bsp;

> +Optional properties:=

> +- ti,system-power-controller: Telli= ng whether or not rtc is

> +contr= olling

> +  the system power.=

 

I don't know how it is connected at board level, but I'm not sure = the binding is the proper one.

It doe= s not look super generic, and I'm wondering if we should not use instead so= me regulator binding to reflect the connection of the RTC to a regulator.

 

But without the board / soc spec it is hard to tell :-(

 

Rega= rds,

Benoit

 

 =

> +

&g= t;  Example:

>  rtc@1c23000 {

> @@ -14,4 +18,5 @@ rtc@1c23000 {

>         &nb= sp;   interrupts =3D <19

>            &nb= sp;            =           19>;

>        &n= bsp;    interrupt-parent =3D <&intc>;

> +       &= nbsp;  ti,system-power-controller;

>  };

> diff --git a/dr= ivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index

> 6009714..2d90170 100644

> --- a/drivers/rtc/rtc-omap.c

> +++ b/drivers/rtc/rtc-omap.c

> @@ -72,6 +72,14 @@

>  = #define OMAP_RTC_KICK0_REG        &= nbsp;           &nbs= p;    0x6c

>  = #define OMAP_RTC_KICK1_REG        &= nbsp;           &nbs= p;    0x70

>  =

> +#define OMAP_RTC_ALARM2_SECOND= S_REG            0x8= 0

> +#define OMAP_RTC_ALARM2_MINUT= ES_REG            0x= 84

> +#define OMAP_RTC_ALARM2_HOUR= S_REG 0x88

> +#define OMAP_RTC_ALA= RM2_DAYS_REG     0x8c

> +#define OMAP_RTC_ALARM2_MONTHS_REG     =         0x90

> +#define OMAP_RTC_ALARM2_YEARS_REG   0x94

> +#define OMAP_RTC_PMIC_REG  &= nbsp;           &nbs= p;         0x98

> +

>  = /* OMAP_RTC_CTRL_REG bit fields: */

&= gt;  #define OMAP_RTC_CTRL_SPLIT      &n= bsp;            = ;      (1<<7)

>  #define OMAP_RTC_CTRL_DISABLE    &nb= sp;            =   (1<<6)

> @@ -93,15 +1= 01,24 @@

>  #define OMAP_RTC_= STATUS_BUSY          &nbs= p; (1<<0)

>  /* OMAP_RTC_INTERRUPTS_REG bit fiel= ds: */

> +#define OMAP_RTC_INTERRU= PTS_IT_ALARM2   (1<<4)

>  #define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<&= lt;3)

>  #define OMAP_RTC_INT= ERRUPTS_IT_TIMER    (1<<2)

> +/* OMAP_= RTC_PMIC_REG bit fields: */

> +#de= fine OMAP_RTC_PMIC_POWER_EN_EN       (1<&l= t;16)

> +

>  /* OMAP_RTC_KICKER values */

>  #define      &n= bsp;    KICK0_VALUE       = ;            &n= bsp;            = ;    0x83e70b13

>&n= bsp; #define           KI= CK1_VALUE           =             &nb= sp;            0x95a= 4f1e0

>  #define      &n= bsp;    OMAP_RTC_HAS_KICKER     &nb= sp;            =           0x1

>= ; +#define SHUTDOWN_TIME_SEC        = ;            &n= bsp;    2

> +#defin= e SECS_IN_MIN          &n= bsp;            = ;            &n= bsp;        60

> +#define WAIT_AFTER      &n= bsp;            = ;            &n= bsp;            = ;  (SECS_IN_MIN - SHUTDOWN_TIME_SEC)

> +#define WAIT_TIME_MS       &n= bsp;            = ;            &n= bsp;      (SHUTDOWN_TIME_SEC * 1000)

> +

>&= nbsp; static void __iomem  *rtc_base;

>  #define = rtc_read(addr)          &= nbsp;           &nbs= p;     readb(rtc_base + (addr))

> @@ -290,6 +307,58 @@ static int omap_rtc_set_alarm(str= uct device *dev, struct rtc_wkalrm *alm)

>            = return 0;

>  }

= > +/*

> + * rtc_power_off: Set = the pmic power off sequence. The RTC generates

> + * pmic_pwr_enable control, which can be used to control an= external

> + * PMIC.

> + */

&= gt; +static void rtc_power_off(void)

= > +{

> +    = ;      u32 val;

> +          struct rtc= _time tm;

> +   &nb= sp;      spinlock_t lock;

> +         = ; unsigned long flags;

> +

> +      &n= bsp;   spin_lock_init(&lock);

> +

> +   = ;       /* Set PMIC power enable */

> +      &nbs= p;   val =3D readl(rtc_base + OMAP_RTC_PMIC_REG);

<= p class=3DMsoPlainText>> +       &nbs= p;  writel(val | OMAP_RTC_PMIC_POWER_EN_EN, rtc_base +

=

> +OMAP_RTC_PMIC_REG);

> +

> +  = ;        /* Wait few seconds instead of = rollover */

> +   &= nbsp;      do {

> +           = ;            &n= bsp;  omap_rtc_read_time(NULL, &tm);

> +          =             &nb= sp;   if (WAIT_AFTER <=3D tm.tm_sec)

> +         &n= bsp;            = ;            &n= bsp;       mdelay(WAIT_TIME_MS);

> +       &= nbsp;  } while (WAIT_AFTER <=3D tm.tm_sec);

> +

> + &n= bsp;        /* Add shutdown time to the = current value */

> +  &n= bsp;       tm.tm_sec +=3D SHUTDOWN_TIME_SEC;<= o:p>

> +

> +          if (tm= 2bcd(&tm) < 0)

> + &nb= sp;            =             return;<= o:p>

> +

> +          pr_inf= o("System will go to power_off state in approx. %d secs\n",<= /o:p>

> +      =             &nb= sp;            =            SHUTDOWN_TIME_= SEC);

> +

> +         = ; /* Set the ALARM2 time */

> +&nb= sp;         rtc_write(tm.tm_sec, OM= AP_RTC_ALARM2_SECONDS_REG);

> +&nb= sp;         rtc_write(tm.tm_min, OM= AP_RTC_ALARM2_MINUTES_REG);

> +&nb= sp;         rtc_write(tm.tm_hour, O= MAP_RTC_ALARM2_HOURS_REG);

> +&nbs= p;         rtc_write(tm.tm_mday, OM= AP_RTC_ALARM2_DAYS_REG);

> + =          rtc_write(tm.tm_mon, OMAP_= RTC_ALARM2_MONTHS_REG);

> + &= nbsp;        rtc_write(tm.tm_year, OMAP_= RTC_ALARM2_YEARS_REG);

> +

> +      &n= bsp;   /* Enable alarm2 interrupt */

> +          val = =3D readl(rtc_base + OMAP_RTC_INTERRUPTS_REG);

> +          writ= el(val | OMAP_RTC_INTERRUPTS_IT_ALARM2,

> +           =             &nb= sp;            =             &nb= sp;         rtc_base + OMAP_RTC_INT= ERRUPTS_REG);

> +

> +        = ;  /* Do not allow to execute any other task */

> +         = ; spin_lock_irqsave(&lock, flags);

> +          while (1);

> +}

> +

>  static stru= ct rtc_class_ops omap_rtc_ops =3D {

&= gt;             .rea= d_time         =3D omap_rtc_read_ti= me,

>     &nbs= p;       .set_time    &nb= sp;       =3D omap_rtc_set_time,

> @@ -327,12 +396,16 @@ static int __init omap= _rtc_probe(struct platform_device *pdev)

>            = struct resource          = ;       *res, *mem;

>          &nb= sp;  struct rtc_device        =       *rtc;

= >             u8&= nbsp;           &nbs= p;            &= nbsp;           &nbs= p;     reg, new_ctrl;

> +          bool = ;            &n= bsp;            = ;             p= m_off =3D false;

>   &nb= sp;         const struct platform_d= evice_id *id_entry;

>   =           const struct of_devi= ce_id *of_id;

<= /p>

>        &= nbsp;    of_id =3D of_match_device(omap_rtc_of_match, &p= dev->dev);

> -   = ;        if (of_id)

> +        &nb= sp; if (of_id) {

>   &nb= sp;            =              pd= ev->id_entry =3D of_id->data;

&= gt; +           &nbs= p;            &= nbsp; pm_off =3D of_property_read_bool(pdev->dev.of_node,

=

> +       &nb= sp;            =             &nb= sp;            =             &nb= sp;            =     "ti,system-power-controller");

<= p class=3DMsoPlainText>> +       &nbs= p;  }

=

>        &nbs= p;    omap_rtc_timer =3D platform_get_irq(pdev, 0);

>       &nbs= p;     if (omap_rtc_timer <=3D 0) {

> @@ -385,6 +458,10 @@ static int __init omap_rtc_= probe(struct platform_device *pdev)

&= gt;             plat= form_set_drvdata(pdev, rtc);

>&nbs= p;            dev_set_drv= data(&rtc->dev, mem);

>&nbs= p;

> +    &nb= sp;     /* RTC power off */

> +          if = (pm_off && !pm_power_off)

>= ; +            =             &nb= sp; pm_power_off =3D rtc_power_off;

&= gt; +

>     &n= bsp;       /* clear pending irqs, and set 1/s= econd periodic,

>   &nbs= p;          * which we'll use = instead of update irqs

>  &nb= sp;           */

>

<= o:p> 

= --_000_0520A3FE5EDCF24F88B3F1451CFC64AE059F92FA8Fedprex01_-- --===============2390053880300757345== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ devicetree-discuss mailing list devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org https://lists.ozlabs.org/listinfo/devicetree-discuss --===============2390053880300757345==-- From mboxrd@z Thu Jan 1 00:00:00 1970 From: colin.foeparker@logicpd.com (Colin FoeParker) Date: Mon, 5 Nov 2012 11:39:26 -0600 Subject: [PATCH 2/4] rtc: OMAP: Add system pm_power_off to rtc driver In-Reply-To: <5097ECAD.9010101@ti.com> References: <1352108549-9341-1-git-send-email-anilkumar@ti.com> <1352108549-9341-3-git-send-email-anilkumar@ti.com> <5097ECAD.9010101@ti.com> Message-ID: <0520A3FE5EDCF24F88B3F1451CFC64AE059F92FA8F@edprex01> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Hi Benoit, "I don't know how it is connected at board level, but I'm not sure the binding is the proper one." Here is a link to the Beaglebone schematic. The PMIC_PWR_EN net is the one that you should be interested in following. In the AM335x, this net is connected to the ALARM2 event in the RTC subsystem. If the ALARM2 event is triggered, and the PMIC_PWR_EN pin is configured correctly, the pin is driven low. In the TPS65217 series PMIC, the PWR_EN I/O can be used to put the entire chip into a low power state. This disables all the power rails in the PMIC with an exception of the rail that powers the RTC power domain. So when the ALARM2 event occurs, the PWR_EN I/O is pulled low and the entire system into a low power "off" state. "It does not look super generic, and I'm wondering if we should not use instead some regulator binding to reflect the connection of the RTC to a regulator. But without the board / soc spec it is hard to tell :-(" This is a good point. I know that there are other omap SOC RTC's that do not support the ALARM2 implementation. That being said, I would argue that there is more of a RTC connection with the implementation than a regulator. Anil will probably have greater insight into the pro's/con's of the implementation. -Colin Colin Foe-Parker // Software Engineer II Logic PD /// engineering design services 5 Clock Tower Place. Suite 400 Maynard, MA 01754 T // 978.243.2045 colin.foeparker at logicpd.com www.logicpd.com / / / / / / / / / / / / / / / / / / / / / / / / / This message (including any attachments) contains confidential information intended for a specific individual and purpose, and is protected by law. If you are not the intended recipient, you should delete this message and are hereby notified that any disclosure, copying, distribution, or other use of this message, or the taking of any action based on it, is strictly prohibited. -----Original Message----- From: Benoit Cousson [mailto:b-cousson at ti.com] Sent: Monday, November 05, 2012 11:43 AM To: AnilKumar Ch; Colin FoeParker Cc: a.zummo at towertech.it; sameo at linux.intel.com; tony at atomide.com; grant.likely at secretlab.ca; rob.herring at calxeda.com; rtc-linux at googlegroups.com; linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org; devicetree-discuss at lists.ozlabs.org Subject: Re: [PATCH 2/4] rtc: OMAP: Add system pm_power_off to rtc driver Hi Anil / Colin, On 11/05/2012 10:42 AM, AnilKumar Ch wrote: > From: Colin Foe-Parker > > Add system power off control to rtc driver which is the in-charge of > controlling the BeagleBone system power. The power_off routine can be > hooked up to "pm_power_off" system call. > > System power off sequence:- > * Set PMIC STATUS_OFF when PMIC_POWER_EN is pulled low > * Enable PMIC_POWER_EN in rtc module > * Set rtc ALARM2 time > * Enable ALARM2 interrupt > > Added while (1); after the above steps to make sure that no other > process acquire cpu. Otherwise we might see an unexpected behaviour > because we are shutting down all the power rails of SoC except RTC. > > Signed-off-by: Colin Foe-Parker > > [anilkumar at ti.com: move poweroff additions to rtc driver] > Signed-off-by: AnilKumar Ch > > --- > Documentation/devicetree/bindings/rtc/rtc-omap.txt | 5 ++ > drivers/rtc/rtc-omap.c | 79 +++++++++++++++++++- > 2 files changed, 83 insertions(+), 1 deletion(-) > > diff --git a/Documentation/devicetree/bindings/rtc/rtc-omap.txt > b/Documentation/devicetree/bindings/rtc/rtc-omap.txt > index b47aa41..8d9f4f9 100644 > --- a/Documentation/devicetree/bindings/rtc/rtc-omap.txt > +++ b/Documentation/devicetree/bindings/rtc/rtc-omap.txt > @@ -6,6 +6,10 @@ Required properties: > - interrupts: rtc timer, alarm interrupts in order > - interrupt-parent: phandle for the interrupt controller > > +Optional properties: > +- ti,system-power-controller: Telling whether or not rtc is > +controlling > + the system power. I don't know how it is connected at board level, but I'm not sure the binding is the proper one. It does not look super generic, and I'm wondering if we should not use instead some regulator binding to reflect the connection of the RTC to a regulator. But without the board / soc spec it is hard to tell :-( Regards, Benoit > + > Example: > > rtc at 1c23000 { > @@ -14,4 +18,5 @@ rtc at 1c23000 { > interrupts = <19 > 19>; > interrupt-parent = <&intc>; > + ti,system-power-controller; > }; > diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index > 6009714..2d90170 100644 > --- a/drivers/rtc/rtc-omap.c > +++ b/drivers/rtc/rtc-omap.c > @@ -72,6 +72,14 @@ > #define OMAP_RTC_KICK0_REG 0x6c > #define OMAP_RTC_KICK1_REG 0x70 > > +#define OMAP_RTC_ALARM2_SECONDS_REG 0x80 > +#define OMAP_RTC_ALARM2_MINUTES_REG 0x84 > +#define OMAP_RTC_ALARM2_HOURS_REG 0x88 > +#define OMAP_RTC_ALARM2_DAYS_REG 0x8c > +#define OMAP_RTC_ALARM2_MONTHS_REG 0x90 > +#define OMAP_RTC_ALARM2_YEARS_REG 0x94 > +#define OMAP_RTC_PMIC_REG 0x98 > + > /* OMAP_RTC_CTRL_REG bit fields: */ > #define OMAP_RTC_CTRL_SPLIT (1<<7) > #define OMAP_RTC_CTRL_DISABLE (1<<6) > @@ -93,15 +101,24 @@ > #define OMAP_RTC_STATUS_BUSY (1<<0) > > /* OMAP_RTC_INTERRUPTS_REG bit fields: */ > +#define OMAP_RTC_INTERRUPTS_IT_ALARM2 (1<<4) > #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) > #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) > > +/* OMAP_RTC_PMIC_REG bit fields: */ > +#define OMAP_RTC_PMIC_POWER_EN_EN (1<<16) > + > /* OMAP_RTC_KICKER values */ > #define KICK0_VALUE 0x83e70b13 > #define KICK1_VALUE 0x95a4f1e0 > > #define OMAP_RTC_HAS_KICKER 0x1 > > +#define SHUTDOWN_TIME_SEC 2 > +#define SECS_IN_MIN 60 > +#define WAIT_AFTER (SECS_IN_MIN - SHUTDOWN_TIME_SEC) > +#define WAIT_TIME_MS (SHUTDOWN_TIME_SEC * 1000) > + > static void __iomem *rtc_base; > > #define rtc_read(addr) readb(rtc_base + (addr)) > @@ -290,6 +307,58 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) > return 0; > } > > +/* > + * rtc_power_off: Set the pmic power off sequence. The RTC generates > + * pmic_pwr_enable control, which can be used to control an external > + * PMIC. > + */ > +static void rtc_power_off(void) > +{ > + u32 val; > + struct rtc_time tm; > + spinlock_t lock; > + unsigned long flags; > + > + spin_lock_init(&lock); > + > + /* Set PMIC power enable */ > + val = readl(rtc_base + OMAP_RTC_PMIC_REG); > + writel(val | OMAP_RTC_PMIC_POWER_EN_EN, rtc_base + > +OMAP_RTC_PMIC_REG); > + > + /* Wait few seconds instead of rollover */ > + do { > + omap_rtc_read_time(NULL, &tm); > + if (WAIT_AFTER <= tm.tm_sec) > + mdelay(WAIT_TIME_MS); > + } while (WAIT_AFTER <= tm.tm_sec); > + > + /* Add shutdown time to the current value */ > + tm.tm_sec += SHUTDOWN_TIME_SEC; > + > + if (tm2bcd(&tm) < 0) > + return; > + > + pr_info("System will go to power_off state in approx. %d secs\n", > + SHUTDOWN_TIME_SEC); > + > + /* Set the ALARM2 time */ > + rtc_write(tm.tm_sec, OMAP_RTC_ALARM2_SECONDS_REG); > + rtc_write(tm.tm_min, OMAP_RTC_ALARM2_MINUTES_REG); > + rtc_write(tm.tm_hour, OMAP_RTC_ALARM2_HOURS_REG); > + rtc_write(tm.tm_mday, OMAP_RTC_ALARM2_DAYS_REG); > + rtc_write(tm.tm_mon, OMAP_RTC_ALARM2_MONTHS_REG); > + rtc_write(tm.tm_year, OMAP_RTC_ALARM2_YEARS_REG); > + > + /* Enable alarm2 interrupt */ > + val = readl(rtc_base + OMAP_RTC_INTERRUPTS_REG); > + writel(val | OMAP_RTC_INTERRUPTS_IT_ALARM2, > + rtc_base + OMAP_RTC_INTERRUPTS_REG); > + > + /* Do not allow to execute any other task */ > + spin_lock_irqsave(&lock, flags); > + while (1); > +} > + > static struct rtc_class_ops omap_rtc_ops = { > .read_time = omap_rtc_read_time, > .set_time = omap_rtc_set_time, > @@ -327,12 +396,16 @@ static int __init omap_rtc_probe(struct platform_device *pdev) > struct resource *res, *mem; > struct rtc_device *rtc; > u8 reg, new_ctrl; > + bool pm_off = false; > const struct platform_device_id *id_entry; > const struct of_device_id *of_id; > > of_id = of_match_device(omap_rtc_of_match, &pdev->dev); > - if (of_id) > + if (of_id) { > pdev->id_entry = of_id->data; > + pm_off = of_property_read_bool(pdev->dev.of_node, > + "ti,system-power-controller"); > + } > > omap_rtc_timer = platform_get_irq(pdev, 0); > if (omap_rtc_timer <= 0) { > @@ -385,6 +458,10 @@ static int __init omap_rtc_probe(struct platform_device *pdev) > platform_set_drvdata(pdev, rtc); > dev_set_drvdata(&rtc->dev, mem); > > + /* RTC power off */ > + if (pm_off && !pm_power_off) > + pm_power_off = rtc_power_off; > + > /* clear pending irqs, and set 1/second periodic, > * which we'll use instead of update irqs > */ > -------------- next part -------------- An HTML attachment was scrubbed... URL: