SPEAr keyboard should normally disable clock during suspend and enable it
during resume.
For cases where it is expected to act as a wakeup source the clock can
remain in the same state i.e. kept enabled if it is being used.
Signed-off-by: Shiraz Hashim <redacted>
---
drivers/input/keyboard/spear-keyboard.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
All SPEAr keyboard registers are 32 bit wide and are word aligned. This
patch aligns all io access to be word size using relaxed version of
readl/writel.
Signed-off-by: Shiraz Hashim <redacted>
---
drivers/input/keyboard/spear-keyboard.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
@@ -114,8 +111,12 @@ static int spear_kbd_open(struct input_dev *dev)if(error)returnerror;+/* keyboard rate to be programmed is input clock (in MHz) - 1 */+val=clk_get_rate(kbd->clk)/1000000-1;+val=(val&MODE_CTL_PCLK_FREQ_MSK)<<MODE_CTL_PCLK_FREQ_SHIFT;+/* program keyboard */-val=MODE_CTL_SCAN_RATE_80|MODE_CTL_KEYBOARD|PCLK_FREQ_MSK|+val=MODE_CTL_SCAN_RATE_80|MODE_CTL_KEYBOARD|val|(kbd->mode<<MODE_CTL_KEYNUM_SHIFT);writel_relaxed(val,kbd->io_base+MODE_CTL_REG);writel_relaxed(1,kbd->io_base+STATUS_REG);
On some platform it may happen that the input clock to keyboard may
change thus impacting its wakeup capability.
There is no means for keyboard driver to know this frequency before
hand. Hence introduce a platform data 'suspended_rate' which indicates
the frequency during suspend at which keyboard operates.
Accordingly reprogram keyboard while going into suspend and restore
original configuration at the time of resume.
Signed-off-by: Shiraz Hashim <redacted>
---
arch/arm/plat-spear/include/plat/keyboard.h | 2 ++
drivers/input/keyboard/spear-keyboard.c | 44 +++++++++++++++++++++++++--
2 files changed, 44 insertions(+), 2 deletions(-)
@@ -160,6 +162,9 @@ static int __devinit spear_kbd_parse_dt(struct platform_device *pdev,if(of_property_read_bool(np,"autorepeat"))kbd->rep=true;+if(of_property_read_u32(np,"suspended_rate",&suspended_rate))+kbd->suspended_rate=suspended_rate;+error=of_property_read_u32(np,"st,mode",&val);if(error){dev_err(&pdev->dev,"DT: Invalid or missing mode\n");
@@ -217,6 +222,7 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev)}else{kbd->mode=pdata->mode;kbd->rep=pdata->rep;+kbd->suspended_rate=pdata->suspended_rate;}kbd->res=request_mem_region(res->start,resource_size(res),
@@ -318,17 +324,47 @@ static int spear_kbd_suspend(struct device *dev)structplatform_device*pdev=to_platform_device(dev);structspear_kbd*kbd=platform_get_drvdata(pdev);structinput_dev*input_dev=kbd->input;+unsignedintrate=0,mode_ctl_reg,val;mutex_lock(&input_dev->mutex);+/* explicitly enable clock as we may program device */+clk_enable(kbd->clk);++mode_ctl_reg=readl_relaxed(kbd->io_base+MODE_CTL_REG);+if(device_may_wakeup(&pdev->dev)){if(!enable_irq_wake(kbd->irq))kbd->irq_wake=1;++/*+*reprogramthekeyboardoperatingfrequencyasonsome+*platformitmaychangeduringsystemsuspended+*/+if(kbd->suspended_rate)+rate=kbd->suspended_rate/1000000-1;++val=mode_ctl_reg&+~(MODE_CTL_PCLK_FREQ_MSK<<MODE_CTL_PCLK_FREQ_SHIFT);+val|=(rate&MODE_CTL_PCLK_FREQ_MSK)+<<MODE_CTL_PCLK_FREQ_SHIFT;+writel_relaxed(val,kbd->io_base+MODE_CTL_REG);+}else{-if(input_dev->users)+if(input_dev->users){+writel_relaxed(mode_ctl_reg&~MODE_CTL_START_SCAN,+kbd->io_base+MODE_CTL_REG);clk_disable(kbd->clk);+}}+/* store current configuration */+if(input_dev->users)+kbd->mode_ctl_reg=mode_ctl_reg;++/* restore previous clk state */+clk_disable(kbd->clk);+mutex_unlock(&input_dev->mutex);return0;
@@ -352,6 +388,10 @@ static int spear_kbd_resume(struct device *dev)clk_enable(kbd->clk);}+/* restore current configuration */+if(input_dev->users)+writel_relaxed(kbd->mode_ctl_reg,kbd->io_base+MODE_CTL_REG);+mutex_unlock(&input_dev->mutex);return0;
Hi Shiraz,
On Mon, Jul 02, 2012 at 12:20:10PM +0530, Shiraz Hashim wrote:
quoted hunk
SPEAr keyboard should normally disable clock during suspend and enable it
during resume.
For cases where it is expected to act as a wakeup source the clock can
remain in the same state i.e. kept enabled if it is being used.
Signed-off-by: Shiraz Hashim <redacted>
---
drivers/input/keyboard/spear-keyboard.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
@@ -318,12 +318,12 @@ static int spear_kbd_suspend(struct device *dev)mutex_lock(&input_dev->mutex);-if(input_dev->users)-clk_enable(kbd->clk);-if(device_may_wakeup(&pdev->dev)){if(!enable_irq_wake(kbd->irq))kbd->irq_wake=1;+}else{+if(input_dev->users)+clk_disable(kbd->clk);}
This patch does not apply to mainline version of the driver because the
change introducing handling for enable_irq_wake() failures was rejected
from mainline. I also have not appplied the 6th patch in the series
because it depends on this one.
Also, don't you need to enable clock if device is marked as wakeup
source but happens to have no active users?
Thanks.
--
Dmitry
Hi Dmitry,
On Sat, Jul 07, 2012 at 06:11:55PM -0700, Dmitry Torokhov wrote:
Hi Shiraz,
On Mon, Jul 02, 2012 at 12:20:10PM +0530, Shiraz Hashim wrote:
quoted
SPEAr keyboard should normally disable clock during suspend and enable it
during resume.
For cases where it is expected to act as a wakeup source the clock can
remain in the same state i.e. kept enabled if it is being used.
Signed-off-by: Shiraz Hashim <redacted>
---
drivers/input/keyboard/spear-keyboard.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
@@ -318,12 +318,12 @@ static int spear_kbd_suspend(struct device *dev)mutex_lock(&input_dev->mutex);-if(input_dev->users)-clk_enable(kbd->clk);-if(device_may_wakeup(&pdev->dev)){if(!enable_irq_wake(kbd->irq))kbd->irq_wake=1;+}else{+if(input_dev->users)+clk_disable(kbd->clk);}
This patch does not apply to mainline version of the driver because the
change introducing handling for enable_irq_wake() failures was rejected
from mainline. I also have not appplied the 6th patch in the series
because it depends on this one.
Oh. Sorry, I should have been careful. I would clean up and send V2
for this.
Also, don't you need to enable clock if device is marked as wakeup
source but happens to have no active users?
The keyboard is initialized and programmed in open and disabled in
close, so I thought even if I just enable the clock in suspend
(without open being called) it would not be able to generate the
wakeup interrupt.
--
regards
Shiraz
SPEAr keyboard should normally disable clock during suspend and enable it
during resume.
For cases where it is expected to act as a wakeup source the clock can
remain in the same state i.e. kept enabled if it is being used.
Signed-off-by: Shiraz Hashim <redacted>
---
Changes since V1:
* remove discarded irq balancing patch dependency
drivers/input/keyboard/spear-keyboard.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
On some platform it may happen that the input clock to keyboard may
change during suspend, thus impacting its wakeup capability.
There is no means for keyboard driver to know this frequency before
hand. Hence introduce a platform data 'suspended_rate' which indicates
the frequency during suspend at which keyboard operates.
Accordingly reprogram keyboard while going into suspend and restore
original configuration at the time of resume.
Signed-off-by: Shiraz Hashim <redacted>
---
Changes since V1:
* remove discarded irq balancing patch dependency
* consifer kbd rate from clock APIs, if suspended_rate is not available
arch/arm/plat-spear/include/plat/keyboard.h | 2 ++
drivers/input/keyboard/spear-keyboard.c | 46 +++++++++++++++++++++++++--
2 files changed, 46 insertions(+), 2 deletions(-)
@@ -159,6 +161,9 @@ static int __devinit spear_kbd_parse_dt(struct platform_device *pdev,if(of_property_read_bool(np,"autorepeat"))kbd->rep=true;+if(of_property_read_u32(np,"suspended_rate",&suspended_rate))+kbd->suspended_rate=suspended_rate;+error=of_property_read_u32(np,"st,mode",&val);if(error){dev_err(&pdev->dev,"DT: Invalid or missing mode\n");
@@ -216,6 +221,7 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev)}else{kbd->mode=pdata->mode;kbd->rep=pdata->rep;+kbd->suspended_rate=pdata->suspended_rate;}kbd->res=request_mem_region(res->start,resource_size(res),
@@ -317,16 +323,48 @@ static int spear_kbd_suspend(struct device *dev)structplatform_device*pdev=to_platform_device(dev);structspear_kbd*kbd=platform_get_drvdata(pdev);structinput_dev*input_dev=kbd->input;+unsignedintrate=0,mode_ctl_reg,val;mutex_lock(&input_dev->mutex);+/* explicitly enable clock as we may program device */+clk_enable(kbd->clk);++mode_ctl_reg=readl_relaxed(kbd->io_base+MODE_CTL_REG);+if(device_may_wakeup(&pdev->dev)){enable_irq_wake(kbd->irq);++/*+*reprogramthekeyboardoperatingfrequencyasonsome+*platformitmaychangeduringsystemsuspended+*/+if(kbd->suspended_rate)+rate=kbd->suspended_rate/1000000-1;+else+rate=clk_get_rate(kbd->clk)/1000000-1;++val=mode_ctl_reg&+~(MODE_CTL_PCLK_FREQ_MSK<<MODE_CTL_PCLK_FREQ_SHIFT);+val|=(rate&MODE_CTL_PCLK_FREQ_MSK)+<<MODE_CTL_PCLK_FREQ_SHIFT;+writel_relaxed(val,kbd->io_base+MODE_CTL_REG);+}else{-if(input_dev->users)+if(input_dev->users){+writel_relaxed(mode_ctl_reg&~MODE_CTL_START_SCAN,+kbd->io_base+MODE_CTL_REG);clk_disable(kbd->clk);+}}+/* store current configuration */+if(input_dev->users)+kbd->mode_ctl_reg=mode_ctl_reg;++/* restore previous clk state */+clk_disable(kbd->clk);+mutex_unlock(&input_dev->mutex);return0;
@@ -347,6 +385,10 @@ static int spear_kbd_resume(struct device *dev)clk_enable(kbd->clk);}+/* restore current configuration */+if(input_dev->users)+writel_relaxed(kbd->mode_ctl_reg,kbd->io_base+MODE_CTL_REG);+mutex_unlock(&input_dev->mutex);return0;