[msm8660]: Add fastboot key detection for QT8660
Due to a hardware design bug, keypad controller in PM8058 could not be
used for key detection. Hence detecting it by configuring PM8058 GPIOs
as normal function and accessing it over SSBI
Change-Id: I92db69fe504598a6d1dfc0736642b1cb7a02be4c
diff --git a/dev/keys/gpio_keypad.c b/dev/keys/gpio_keypad.c
index d021a78..2ec7c5d 100644
--- a/dev/keys/gpio_keypad.c
+++ b/dev/keys/gpio_keypad.c
@@ -2,7 +2,7 @@
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -43,6 +43,8 @@
#include <reg.h>
#include <platform/iomap.h>
+#define LINUX_MACHTYPE_8660_QT 3298
+
struct gpio_kp {
struct gpio_keypad_info *keypad_info;
struct timer timer;
@@ -455,7 +457,7 @@
return 0;
}
-int pm8058_gpio_config_kypd_drv(int gpio_start, int num_gpios)
+int pm8058_gpio_config_kypd_drv(int gpio_start, int num_gpios, unsigned mach_id)
{
int rc;
struct pm8058_gpio kypd_drv = {
@@ -467,6 +469,9 @@
.inv_int_pol = 1,
};
+ if(mach_id == LINUX_MACHTYPE_8660_QT)
+ kypd_drv.function = PM_GPIO_FUNC_NORMAL;
+
while (num_gpios--) {
rc = pm8058_gpio_config(gpio_start++, &kypd_drv);
if (rc) {
@@ -501,7 +506,7 @@
return 0;
}
-void ssbi_gpio_init(void)
+static void ssbi_gpio_init(unsigned int mach_id)
{
unsigned char kypd_cntl_init;
unsigned char kypd_scan_init = 0x20;
@@ -520,8 +525,16 @@
if ((*wr_function)(&kypd_scan_init, 1, SSBI_REG_KYPD_SCAN_ADDR))
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_SCAN register\n");
- pm8058_gpio_config_kypd_sns(SSBI_OFFSET_ADDR_GPIO_KYPD_SNS, columns);
- pm8058_gpio_config_kypd_drv(SSBI_OFFSET_ADDR_GPIO_KYPD_DRV, rows);
+ if(mach_id == LINUX_MACHTYPE_8660_QT)
+ {
+ pm8058_gpio_config_kypd_sns(QT_PMIC_GPIO_KYPD_SNS, rows);
+ pm8058_gpio_config_kypd_drv(QT_PMIC_GPIO_KYPD_DRV, columns, mach_id);
+ }
+ else
+ {
+ pm8058_gpio_config_kypd_sns(SSBI_OFFSET_ADDR_GPIO_KYPD_SNS, columns);
+ pm8058_gpio_config_kypd_drv(SSBI_OFFSET_ADDR_GPIO_KYPD_DRV, rows, mach_id);
+ }
}
static enum handler_return
@@ -584,8 +597,54 @@
}
+static enum handler_return
+scan_qt_keypad(struct timer *timer, time_t now, void *arg)
+{
+ unsigned int gpio;
+ unsigned int last_state=0;
+ unsigned int new_state=0;
+ unsigned int bits_changed;
+ static unsigned int key_detected=0;
+
+ /* Row GPIOs 8,9,10 are used for sensing here */
+ for(gpio=8;gpio<=10;gpio++)
+ {
+ bool status;
+ status = pm8058_gpio_get(gpio);
+ if(status == 0)
+ new_state |= (1<<(gpio-8));
+ }
+
+ bits_changed = last_state ^ new_state;
+
+ if(bits_changed)
+ {
+ unsigned int shift;
+ for(int rows=0;rows<(qwerty_keypad->keypad_info)->rows;rows++)
+ {
+ if((bits_changed & (1<<rows)) == 0)
+ continue;
+ shift = rows*8 + 3;
+ }
+ if ((qwerty_keypad->keypad_info)->keymap[shift])
+ {
+ if (shift != key_detected)
+ {
+ key_detected = shift;
+ keys_post_event((qwerty_keypad->keypad_info)->keymap[shift], 1);
+ timer_set_oneshot(timer,(qwerty_keypad->keypad_info)->poll_time,
+ scan_qt_keypad, NULL);
+ return INT_RESCHEDULE;
+ }
+ }
+ }
+ event_signal(&qwerty_keypad->full_scan, false);
+ return INT_RESCHEDULE;
+}
+
void ssbi_keypad_init(struct qwerty_keypad_info *qwerty_kp)
{
+ unsigned int mach_id;
int len;
len = sizeof(struct gpio_qwerty_kp);
@@ -594,13 +653,25 @@
memset(qwerty_keypad, 0, len);
qwerty_keypad->keypad_info = qwerty_kp;
- ssbi_gpio_init();
-
qwerty_keypad->num_of_scans = 0;
event_init(&qwerty_keypad->full_scan, false, EVENT_FLAG_AUTOUNSIGNAL);
timer_initialize(&qwerty_keypad->timer);
- timer_set_oneshot(&qwerty_keypad->timer, 0, scan_qwerty_keypad, NULL);
+
+#ifdef QT_8660_KEYPAD_HW_BUG
+ mach_id = board_machtype();
+#endif
+ ssbi_gpio_init(mach_id);
+
+ if(mach_id == LINUX_MACHTYPE_8660_QT)
+ {
+ mdelay((qwerty_keypad->keypad_info)->settle_time);
+#ifdef QT_8660_KEYPAD_HW_BUG
+ timer_set_oneshot(&qwerty_keypad->timer, 0, scan_qt_keypad, NULL);
+#endif
+ }
+ else
+ timer_set_oneshot(&qwerty_keypad->timer, 0, scan_qwerty_keypad, NULL);
/* wait for the keypad to complete one full scan */
event_wait(&qwerty_keypad->full_scan);
diff --git a/include/dev/gpio_keypad.h b/include/dev/gpio_keypad.h
index f467729..04093cc 100644
--- a/include/dev/gpio_keypad.h
+++ b/include/dev/gpio_keypad.h
@@ -2,7 +2,7 @@
* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -112,8 +112,13 @@
// GPIO configurations
#define SSBI_REG_ADDR_GPIO_BASE 0x150
+
+#define QT_PMIC_GPIO_KYPD_SNS 0x008
+#define QT_PMIC_GPIO_KYPD_DRV 0x003
+
#define SSBI_OFFSET_ADDR_GPIO_KYPD_SNS 0x000
#define SSBI_OFFSET_ADDR_GPIO_KYPD_DRV 0x008
+
#define SSBI_REG_ADDR_GPIO(n) (SSBI_REG_ADDR_GPIO_BASE + n)
#define PM_GPIO_DIR_OUT 0x01
diff --git a/platform/msm8x60/pmic.c b/platform/msm8x60/pmic.c
index 1dd0c23..0da7291 100755
--- a/platform/msm8x60/pmic.c
+++ b/platform/msm8x60/pmic.c
@@ -1,5 +1,5 @@
/*
- * * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ * * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -91,6 +91,21 @@
return 0;
}
+bool pm8058_gpio_get(unsigned int gpio)
+{
+ pm_sec_gpio_irq_id_type gpio_irq;
+ bool status;
+ int ret;
+
+ gpio_irq = gpio + PM_GPIO01_CHGED_ST_IRQ_ID;
+ ret = pm8058_get_gpio_status(gpio_irq, &status);
+
+ if(ret)
+ dprintf(CRITICAL,"pm8058_gpio_get failed\n");
+
+ return status;
+}
+
/*PM8901*/
extern int pa2_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
diff --git a/platform/msm8x60/rules.mk b/platform/msm8x60/rules.mk
index bf5e923..e4adc5b 100644
--- a/platform/msm8x60/rules.mk
+++ b/platform/msm8x60/rules.mk
@@ -10,6 +10,8 @@
DEFINES += WITH_CPU_EARLY_INIT=0 WITH_CPU_WARM_BOOT=0 \
MMC_SLOT=$(MMC_SLOT) MDP4=1
+DEFINES += QT_8660_KEYPAD_HW_BUG=1
+
INCLUDES += -I$(LOCAL_DIR)/include -I$(LK_TOP_DIR)/platform/msm_shared/include
DEVS += fbcon
diff --git a/target/msm8660_surf/init.c b/target/msm8660_surf/init.c
index f63b842..3f8616b 100644
--- a/target/msm8660_surf/init.c
+++ b/target/msm8660_surf/init.c
@@ -87,8 +87,10 @@
unsigned hw_platform = 0;
unsigned fused_chip = 0;
unsigned platform_subtype = 0;
- unsigned mach_id = LINUX_MACHTYPE_8660_FFA;
+ static unsigned mach_id = -1;
+ if(mach_id != -1)
+ return mach_id;
/* Detect external msm if this is a "fusion" */
smem_status = smem_read_alloc_entry_offset(SMEM_BOARD_INFO_LOCATION,
&format, sizeof(format), 0);
diff --git a/target/msm8660_surf/keypad.c b/target/msm8660_surf/keypad.c
index a83bde3..adcb10e 100644
--- a/target/msm8660_surf/keypad.c
+++ b/target/msm8660_surf/keypad.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -30,12 +30,30 @@
#include <dev/keys.h>
#include <dev/gpio_keypad.h>
+#define LINUX_MACHTYPE_8660_QT 3298
#define BITS_IN_ELEMENT(x) (sizeof(x)[0] * 8)
+#define KEYMAP_INDEX(row, col) (row)* BITS_IN_ELEMENT(qwerty_keys_new) + (col)
static unsigned char qwerty_keys_old[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static unsigned char qwerty_keys_new[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-#define KEYMAP_INDEX(row, col) (row)* BITS_IN_ELEMENT(qwerty_keys_new) + (col)
+static unsigned int qt_keymap[] = {
+ [KEYMAP_INDEX(0, 3)] = KEY_BACK, /* Volume down key */
+ [KEYMAP_INDEX(1, 3)] = KEY_HOME, /* Volume up key */
+};
+
+static struct qwerty_keypad_info qt_keypad = {
+ .keymap = qt_keymap,
+ .old_keys = qwerty_keys_old,
+ .rec_keys = qwerty_keys_new,
+ .rows = 3,
+ .columns = 1,
+ .num_of_reads = 3,
+ .rd_func = &pa1_ssbi2_read_bytes,
+ .wr_func = &pa1_ssbi2_write_bytes,
+ .settle_time = 32 /* msec */,
+ .poll_time = 10 /* msec */,
+};
static unsigned int qwerty_keymap[] = {
[KEYMAP_INDEX(1, 3)] = KEY_BACK, /* Volume down key */
@@ -57,5 +75,12 @@
void keypad_init(void)
{
- ssbi_keypad_init(&qwerty_keypad);
+ unsigned int mach_id;
+
+ mach_id = board_machtype();
+
+ if(mach_id == LINUX_MACHTYPE_8660_QT)
+ ssbi_keypad_init(&qt_keypad);
+ else
+ ssbi_keypad_init(&qwerty_keypad);
}