1919#include <linux/mfd/syscon.h>
2020#include <linux/regmap.h>
2121
22- #define SNVS_LPSR_REG 0x4C /* LP Status Register */
23- #define SNVS_LPCR_REG 0x38 /* LP Control Register */
24- #define SNVS_HPSR_REG 0x14
25- #define SNVS_HPSR_BTN BIT(6)
26- #define SNVS_LPSR_SPO BIT(18)
27- #define SNVS_LPCR_DEP_EN BIT(5)
22+ #define SNVS_HPVIDR1_REG 0xF8
23+ #define SNVS_LPSR_REG 0x4C /* LP Status Register */
24+ #define SNVS_LPCR_REG 0x38 /* LP Control Register */
25+ #define SNVS_HPSR_REG 0x14
26+ #define SNVS_HPSR_BTN BIT(6)
27+ #define SNVS_LPSR_SPO BIT(18)
28+ #define SNVS_LPCR_DEP_EN BIT(5)
2829
29- #define DEBOUNCE_TIME 30
30- #define REPEAT_INTERVAL 60
30+ #define DEBOUNCE_TIME 30
31+ #define REPEAT_INTERVAL 60
3132
3233struct pwrkey_drv_data {
3334 struct regmap * snvs ;
@@ -37,6 +38,7 @@ struct pwrkey_drv_data {
3738 int wakeup ;
3839 struct timer_list check_timer ;
3940 struct input_dev * input ;
41+ u8 minor_rev ;
4042};
4143
4244static void imx_imx_snvs_check_for_events (struct timer_list * t )
@@ -67,13 +69,29 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
6769{
6870 struct platform_device * pdev = dev_id ;
6971 struct pwrkey_drv_data * pdata = platform_get_drvdata (pdev );
72+ struct input_dev * input = pdata -> input ;
7073 u32 lp_status ;
7174
72- pm_wakeup_event (pdata -> input -> dev .parent , 0 );
75+ pm_wakeup_event (input -> dev .parent , 0 );
7376
7477 regmap_read (pdata -> snvs , SNVS_LPSR_REG , & lp_status );
75- if (lp_status & SNVS_LPSR_SPO )
76- mod_timer (& pdata -> check_timer , jiffies + msecs_to_jiffies (DEBOUNCE_TIME ));
78+ if (lp_status & SNVS_LPSR_SPO ) {
79+ if (pdata -> minor_rev == 0 ) {
80+ /*
81+ * The first generation i.MX6 SoCs only sends an
82+ * interrupt on button release. To mimic power-key
83+ * usage, we'll prepend a press event.
84+ */
85+ input_report_key (input , pdata -> keycode , 1 );
86+ input_sync (input );
87+ input_report_key (input , pdata -> keycode , 0 );
88+ input_sync (input );
89+ pm_relax (input -> dev .parent );
90+ } else {
91+ mod_timer (& pdata -> check_timer ,
92+ jiffies + msecs_to_jiffies (DEBOUNCE_TIME ));
93+ }
94+ }
7795
7896 /* clear SPO status */
7997 regmap_write (pdata -> snvs , SNVS_LPSR_REG , SNVS_LPSR_SPO );
@@ -90,10 +108,11 @@ static void imx_snvs_pwrkey_act(void *pdata)
90108
91109static int imx_snvs_pwrkey_probe (struct platform_device * pdev )
92110{
93- struct pwrkey_drv_data * pdata = NULL ;
94- struct input_dev * input = NULL ;
111+ struct pwrkey_drv_data * pdata ;
112+ struct input_dev * input ;
95113 struct device_node * np ;
96114 int error ;
115+ u32 vid ;
97116
98117 /* Get SNVS register Page */
99118 np = pdev -> dev .of_node ;
@@ -121,6 +140,9 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
121140 if (pdata -> irq < 0 )
122141 return - EINVAL ;
123142
143+ regmap_read (pdata -> snvs , SNVS_HPVIDR1_REG , & vid );
144+ pdata -> minor_rev = vid & 0xff ;
145+
124146 regmap_update_bits (pdata -> snvs , SNVS_LPCR_REG , SNVS_LPCR_DEP_EN , SNVS_LPCR_DEP_EN );
125147
126148 /* clear the unexpected interrupt before driver ready */
0 commit comments