static irqreturn_t qpnp_resin_bark_irq(int irq, void *_pon) { int rc; struct qpnp_pon *pon = _pon; struct qpnp_pon_config *cfg; /* disable the bark interrupt */ disable_irq_nosync(irq); /* disable reset */ rc = qpnp_pon_masked_write(pon, QPNP_PON_RESIN_S2_CNTL(pon->base), QPNP_PON_S2_CNTL_EN, 0); if (rc) { dev_err(&pon->spmi->dev, "Unable to configure S2 enable\n"); goto err_exit; } cfg = qpnp_get_cfg(pon, PON_RESIN); if (!cfg) { dev_err(&pon->spmi->dev, "Invalid config pointer\n"); goto err_exit; } /* report the key event */ input_report_key(pon->pon_input, cfg->key_code, 1); input_sync(pon->pon_input); /* schedule work to check the bark status for key-release */ schedule_delayed_work(&pon->bark_work, QPNP_KEY_STATUS_DELAY); err_exit: return IRQ_HANDLED; }
static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) { int rc; struct qpnp_pon_config *cfg = NULL; u8 pon_rt_sts = 0, pon_rt_bit = 0; cfg = qpnp_get_cfg(pon, pon_type); if (!cfg) return -EINVAL; /* Check if key reporting is supported */ if (!cfg->key_code) return 0; /* check the RT status to get the current status of the line */ rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid, QPNP_PON_RT_STS(pon->base), &pon_rt_sts, 1); if (rc) { dev_err(&pon->spmi->dev, "Unable to read PON RT status\n"); return rc; } switch (cfg->pon_type) { case PON_KPDPWR: pon_rt_bit = QPNP_PON_KPDPWR_N_SET; break; case PON_RESIN: pon_rt_bit = QPNP_PON_RESIN_N_SET; break; case PON_CBLPWR: pon_rt_bit = QPNP_PON_CBLPWR_N_SET; break; default: return -EINVAL; } input_report_key(pon->pon_input, cfg->key_code, (pon_rt_sts & pon_rt_bit)); input_sync(pon->pon_input); if((cfg->key_code == 116) && (pon_rt_sts & pon_rt_bit)){ pon->powerkey_state = 1; }else if((cfg->key_code == 116) && !(pon_rt_sts & pon_rt_bit)){ pon->powerkey_state = 0; } #if CONFIG_SEC_DEBUG sec_debug_check_crash_key(cfg->key_code, pon->powerkey_state); #endif #if defined(CONFIG_MACH_MONTBLANC) check_pkey_press=pon->powerkey_state; #endif return 0; }
static void bark_work_func(struct work_struct *work) { int rc; u8 pon_rt_sts = 0; struct qpnp_pon_config *cfg; struct qpnp_pon *pon = container_of(work, struct qpnp_pon, bark_work.work); /* enable reset */ rc = qpnp_pon_masked_write(pon, QPNP_PON_RESIN_S2_CNTL(pon->base), QPNP_PON_S2_CNTL_EN, QPNP_PON_S2_CNTL_EN); if (rc) { dev_err(&pon->spmi->dev, "Unable to configure S2 enable\n"); goto err_return; } /* bark RT status update delay */ msleep(100); /* read the bark RT status */ rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid, QPNP_PON_RT_STS(pon->base), &pon_rt_sts, 1); if (rc) { dev_err(&pon->spmi->dev, "Unable to read PON RT status\n"); goto err_return; } if (!(pon_rt_sts & QPNP_PON_RESIN_BARK_N_SET)) { cfg = qpnp_get_cfg(pon, PON_RESIN); if (!cfg) { dev_err(&pon->spmi->dev, "Invalid config pointer\n"); goto err_return; } /* report the key event and enable the bark IRQ */ input_report_key(pon->pon_input, cfg->key_code, 0); input_sync(pon->pon_input); enable_irq(cfg->bark_irq); } else { /* disable reset */ rc = qpnp_pon_masked_write(pon, QPNP_PON_RESIN_S2_CNTL(pon->base), QPNP_PON_S2_CNTL_EN, 0); if (rc) { dev_err(&pon->spmi->dev, "Unable to configure S2 enable\n"); goto err_return; } /* re-arm the work */ schedule_delayed_work(&pon->bark_work, QPNP_KEY_STATUS_DELAY); } err_return: return; }