Merge changes Ia430dd32,I3b17cd2d
* changes:
copper: Add support for fastboot and recovery keys
copper: use dtb address from image header
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index c8c7e17..dbcd8dd 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -628,7 +628,6 @@
}
/* Read device device tree in the "tags_add */
- hdr->tags_addr = 0x8400000;
if(mmc_read(ptn + offset + dt_entry_ptr->offset,
(void *)hdr->tags_addr, dt_entry_ptr->size)) {
dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
diff --git a/dev/pmic/pm8x41/include/pm8x41.h b/dev/pmic/pm8x41/include/pm8x41.h
index 411a063..e5a4b10 100644
--- a/dev/pmic/pm8x41/include/pm8x41.h
+++ b/dev/pmic/pm8x41/include/pm8x41.h
@@ -29,6 +29,34 @@
#ifndef _PM8x41_H_
#define _PM8x41_H_
+#define PM_GPIO_DIR_OUT 0x01
+#define PM_GPIO_DIR_IN 0x00
+#define PM_GPIO_DIR_BOTH 0x02
+
+#define PM_GPIO_PULL_UP_30 0
+#define PM_GPIO_PULL_UP_1_5 1
+#define PM_GPIO_PULL_UP_31_5 2
+/* 1.5uA + 30uA boost */
+#define PM_GPIO_PULL_UP_1_5_30 3
+#define PM_GPIO_PULL_RESV_1 4
+#define PM_GPIO_PULL_RESV_2 5
+
+struct pm8x41_gpio {
+ int direction;
+ int output_buffer;
+ int output_value;
+ int pull;
+ int vin_sel;
+ int out_strength;
+ int function;
+ int inv_int_pol;
+ int disable_pin;
+};
+
+int pm8x41_gpio_get(uint8_t gpio, uint8_t *status);
+int pm8x41_gpio_config(uint8_t gpio, struct pm8x41_gpio *config);
void pm8x41_set_boot_done();
+int pm8x41_vol_down_key_status();
+
#endif
diff --git a/dev/pmic/pm8x41/include/pm8x41_hw.h b/dev/pmic/pm8x41/include/pm8x41_hw.h
index 36dd422..0889bb9 100644
--- a/dev/pmic/pm8x41/include/pm8x41_hw.h
+++ b/dev/pmic/pm8x41/include/pm8x41_hw.h
@@ -29,14 +29,50 @@
#ifndef _PM8x41_HW_H_
#define _PM8x41_HW_H_
-/* Slave IDs */
-#define PM8x41_SMBB_SLAVE_ID 0
-/* Peripheral Base Addresses */
-#define PM8x41_SMBB_PERIPHERAL_ID_BASE 0x1600
+/* SMBB Registers */
+#define SMBB_MISC_BOOT_DONE 0x1642
-/* Register Offsets */
-#define SMBB_MISC_BOOT_DONE 0x42
-#define BOOT_DONE_SHIFT 7
+/* SMBB bit values */
+#define BOOT_DONE_BIT 7
+
+
+/* GPIO Registers */
+#define GPIO_PERIPHERAL_BASE 0xC000
+/* Peripheral base address for GPIO_X */
+#define GPIO_N_PERIPHERAL_BASE(x) (GPIO_PERIPHERAL_BASE + ((x) - 1) * 0x100)
+
+/* Register offsets within GPIO */
+#define GPIO_STATUS 0x08
+#define GPIO_MODE_CTL 0x40
+#define GPIO_DIG_VIN_CTL 0x41
+#define GPIO_DIG_PULL_CTL 0x42
+#define GPIO_DIG_OUT_CTL 0x45
+#define GPIO_EN_CTL 0x46
+
+/* GPIO bit values */
+#define PERPH_EN_BIT 7
+#define GPIO_STATUS_VAL_BIT 0
+
+
+/* PON Peripheral registers */
+#define PON_INT_RT_STS 0x810
+#define PON_INT_SET_TYPE 0x811
+#define PON_INT_POLARITY_HIGH 0x812
+#define PON_INT_POLARITY_LOW 0x813
+#define PON_INT_LATCHED_CLR 0x814
+#define PON_INT_EN_SET 0x815
+#define PON_INT_LATCHED_STS 0x818
+#define PON_INT_PENDING_STS 0x819
+#define PON_RESIN_N_RESET_S1_TIMER 0x844 /* bits 0:3 : S1_TIMER */
+#define PON_RESIN_N_RESET_S2_TIMER 0x845 /* bits 0:2 : S2_TIMER */
+#define PON_RESIN_N_RESET_S2_CTL 0x846 /* bit 7: S2_RESET_EN, bit 0:3 : RESET_TYPE */
+
+/* PON Peripheral register bit values */
+#define RESIN_BARK_INT_BIT 4
+#define S2_RESET_EN_BIT 7
+
+#define S2_RESET_TYPE_WARM 0x1
+#define PON_RESIN_N_RESET_S2_TIMER_MAX_VALUE 0x7
#endif
diff --git a/dev/pmic/pm8x41/pm8x41.c b/dev/pmic/pm8x41/pm8x41.c
index d3b6cd1..4eac64f 100644
--- a/dev/pmic/pm8x41/pm8x41.c
+++ b/dev/pmic/pm8x41/pm8x41.c
@@ -26,28 +26,167 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <bits.h>
#include <debug.h>
#include <reg.h>
#include <spmi.h>
#include <pm8x41_hw.h>
+#include <pm8x41.h>
+#include <platform/timer.h>
-/* Function to set the boot done flag */
-void pm8x41_set_boot_done()
+/* Local Macros */
+#define REG_READ(_a) pm8x41_reg_read(_a)
+#define REG_WRITE(_a, _v) pm8x41_reg_write(_a, _v)
+
+#define REG_OFFSET(_addr) ((_addr) & 0xFF)
+#define PERIPH_ID(_addr) (((_addr) & 0xFF00) >> 8)
+#define SLAVE_ID(_addr) ((_addr) >> 16)
+
+
+/* Local functions */
+static uint8_t pm8x41_reg_read(uint32_t addr)
+{
+ uint8_t val = 0;
+ struct pmic_arb_cmd cmd;
+ struct pmic_arb_param param;
+
+ cmd.address = PERIPH_ID(addr);
+ cmd.offset = REG_OFFSET(addr);
+ cmd.slave_id = SLAVE_ID(addr);
+ cmd.priority = 0;
+
+ param.buffer = &val;
+ param.size = 1;
+
+ pmic_arb_read_cmd(&cmd, ¶m);
+
+ return val;
+}
+
+static void pm8x41_reg_write(uint32_t addr, uint8_t val)
{
struct pmic_arb_cmd cmd;
struct pmic_arb_param param;
- uint8_t boot_done;
- cmd.address = ((uint16_t)(PM8x41_SMBB_PERIPHERAL_ID_BASE) >> 8);
- cmd.offset = SMBB_MISC_BOOT_DONE;
+ cmd.address = PERIPH_ID(addr);
+ cmd.offset = REG_OFFSET(addr);
+ cmd.slave_id = SLAVE_ID(addr);
cmd.priority = 0;
- cmd.slave_id = PM8x41_SMBB_SLAVE_ID;
- /* Enable the module */
- boot_done = 1 << BOOT_DONE_SHIFT;
- param.buffer = &boot_done;
- param.size = 1;
+ param.buffer = &val;
+ param.size = 1;
- pmic_arb_write_cmd(&cmd,¶m);
+ pmic_arb_write_cmd(&cmd, ¶m);
+}
+/* Exported functions */
+
+/* Set the boot done flag */
+void pm8x41_set_boot_done()
+{
+ uint8_t val;
+
+ val = REG_READ(SMBB_MISC_BOOT_DONE);
+ val |= BIT(BOOT_DONE_BIT);
+ REG_WRITE(SMBB_MISC_BOOT_DONE, val);
+}
+
+/* Configure GPIO */
+int pm8x41_gpio_config(uint8_t gpio, struct pm8x41_gpio *config)
+{
+ uint8_t val;
+ uint32_t gpio_base = GPIO_N_PERIPHERAL_BASE(gpio);
+
+ /* Disable the GPIO */
+ val = REG_READ(gpio_base + GPIO_EN_CTL);
+ val &= ~BIT(PERPH_EN_BIT);
+ REG_WRITE(gpio_base + GPIO_EN_CTL, val);
+
+ /* Select the mode */
+ val = config->function | (config->direction << 4);
+ REG_WRITE(gpio_base + GPIO_MODE_CTL, val);
+
+ /* Set the right pull */
+ val = config->pull;
+ REG_WRITE(gpio_base + GPIO_DIG_PULL_CTL, val);
+
+ /* Select the VIN */
+ val = config->vin_sel;
+ REG_WRITE(gpio_base + GPIO_DIG_VIN_CTL, val);
+
+ /* Enable the GPIO */
+ val = REG_READ(gpio_base + GPIO_EN_CTL);
+ val |= BIT(PERPH_EN_BIT);
+ REG_WRITE(gpio_base + GPIO_EN_CTL, val);
+
+ return 1;
+}
+
+/* Reads the status of requested gpio */
+int pm8x41_gpio_get(uint8_t gpio, uint8_t *status)
+{
+ uint32_t gpio_base = GPIO_N_PERIPHERAL_BASE(gpio);
+
+ *status = REG_READ(gpio_base + GPIO_STATUS);
+
+ /* Return the value of the GPIO pin */
+ *status &= BIT(GPIO_STATUS_VAL_BIT);
+
+ dprintf(SPEW, "GPIO %d status is %d\n", gpio, *status);
+
+ return 1;
+}
+
+/* Prepare PON RESIN S2 reset */
+void pm8x41_vol_down_key_prepare()
+{
+ uint8_t val;
+
+ /* disable s2 reset */
+ REG_WRITE(PON_RESIN_N_RESET_S2_CTL, 0x0);
+
+ /* configure s1 timer to 0 */
+ REG_WRITE(PON_RESIN_N_RESET_S1_TIMER, 0x0);
+
+ /* configure s2 timer to 2s */
+ REG_WRITE(PON_RESIN_N_RESET_S2_TIMER, PON_RESIN_N_RESET_S2_TIMER_MAX_VALUE);
+
+ /* configure reset type */
+ REG_WRITE(PON_RESIN_N_RESET_S2_CTL, S2_RESET_TYPE_WARM);
+
+ val = REG_READ(PON_RESIN_N_RESET_S2_CTL);
+
+ /* enable s2 reset */
+ val |= BIT(S2_RESET_EN_BIT);
+ REG_WRITE(PON_RESIN_N_RESET_S2_CTL, val);
+}
+
+/* Volume_Down key detect cleanup */
+void pm8x41_vol_down_key_done()
+{
+ /* disable s2 reset */
+ REG_WRITE(PON_RESIN_N_RESET_S2_CTL, 0x0);
+}
+
+/* Volume_Down key status */
+int pm8x41_vol_down_key_status()
+{
+ uint8_t rt_sts = 0;
+
+ /* Enable S2 reset so we can detect the volume down key press */
+ pm8x41_vol_down_key_prepare();
+
+ /* Delay before interrupt triggering.
+ * See PON_DEBOUNCE_CTL reg.
+ */
+ mdelay(100);
+
+ rt_sts = REG_READ(PON_INT_RT_STS);
+
+ /* Must disable S2 reset otherwise PMIC will reset if key
+ * is held longer than S2 timer.
+ */
+ pm8x41_vol_down_key_done();
+
+ return (rt_sts & BIT(RESIN_BARK_INT_BIT));
}
diff --git a/target/copper/init.c b/target/copper/init.c
index 7e9f2c6..a11e23b 100644
--- a/target/copper/init.c
+++ b/target/copper/init.c
@@ -39,7 +39,8 @@
#include <board.h>
#include <smem.h>
#include <baseband.h>
-
+#include <dev/keys.h>
+#include <pm8x41.h>
static unsigned int target_id;
@@ -57,6 +58,50 @@
#endif
}
+/* Return 1 if vol_up pressed */
+static int target_volume_up()
+{
+ uint8_t status = 0;
+ struct pm8x41_gpio gpio;
+
+ /* CDP vol_up seems to be always grounded. So gpio status is read as 0,
+ * whether key is pressed or not.
+ * Ignore volume_up key on CDP for now.
+ */
+ if (board_hardware_id() == HW_PLATFORM_SURF)
+ return 0;
+
+ /* Configure the GPIO */
+ gpio.direction = PM_GPIO_DIR_IN;
+ gpio.function = 0;
+ gpio.pull = PM_GPIO_PULL_UP_30;
+ gpio.vin_sel = 0;
+
+ pm8x41_gpio_config(5, &gpio);
+
+ /* Get status of P_GPIO_5 */
+ pm8x41_gpio_get(5, &status);
+
+ return !status; /* active low */
+}
+
+/* Return 1 if vol_down pressed */
+int target_volume_down()
+{
+ return pm8x41_vol_down_key_status();
+}
+
+static void target_keystatus()
+{
+ keys_init();
+
+ if(target_volume_down())
+ keys_post_event(KEY_VOLUMEDOWN, 1);
+
+ if(target_volume_up())
+ keys_post_event(KEY_VOLUMEUP, 1);
+}
+
void target_init(void)
{
uint32_t base_addr;
@@ -67,6 +112,8 @@
spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
+ target_keystatus();
+
/* Trying Slot 1*/
slot = 1;
base_addr = mmc_sdc_base[slot - 1];
@@ -91,7 +138,8 @@
/* Do any target specific intialization needed before entering fastboot mode */
void target_fastboot_init(void)
{
-
+ /* Set the BOOT_DONE flag in PM8921 */
+ pm8x41_set_boot_done();
}
/* Detect the target type */
@@ -109,3 +157,12 @@
else
board->baseband = BASEBAND_MSM;
}
+
+void target_serialno(unsigned char *buf)
+{
+ unsigned int serialno;
+ if (target_is_emmc_boot()) {
+ serialno = mmc_get_psn();
+ snprintf((char *)buf, 13, "%x", serialno);
+ }
+}