Beispiel #1
0
static int idpram_pre_suspend(struct idpram_link_pm_data *pm_data)
{
	int timeout_ret = 0;
	int suspend_retry = 2;
	u16 intr_out = INT_CMD(INT_MASK_CMD_PDA_SLEEP);

	pm_data->pm_states = IDPRAM_PM_SUSPEND_PREPARE;
	pm_data->last_pm_mailbox = 0;
	idpram_write_lock(pm_data, 1);

	gpio_set_value(pm_data->mdata->gpio_mbx_intr, 1);

	/* prevent PDA_ACTIVE ststus is low */
	gpio_set_value(pm_data->mdata->gpio_pda_active, 1);

	if (!atomic_read(&pm_data->read_lock)) {
		do {
			init_completion(&pm_data->idpram_down);
			dpram_write_command(pm_data->dpld, intr_out);
			mif_err("MIF: idpram sent PDA_SLEEP Mailbox(0x%X)\n",
				intr_out);
			timeout_ret =
			wait_for_completion_timeout(&pm_data->idpram_down,
				(HZ/5));
			mif_err("MIF: suspend_enter cnt = %d\n",
				suspend_retry);
		} while (!timeout_ret && suspend_retry--);

		switch (pm_data->last_pm_mailbox) {
		case INT_CMD(INT_MASK_CMD_DPRAM_DOWN):
			break;

		/* if nack or other interrup, hold wakelock for DPM resume*/
		case INT_CMD(INT_MASK_CMD_DPRAM_DOWN_NACK):
			mif_err("MIF: idpram dpram down get NACK\n");

		default:
			mif_err("MIF: CP dpram Down not ready! intr=0x%X\n",
				dpram_readh(&pm_data->dpld->dpram->mbx_cp2ap));
			wake_lock_timeout(&pm_data->hold_wlock,
				msecs_to_jiffies(500));
			idpram_write_lock(pm_data, 0);
			return 0;
		}
		/*
		* Because, if dpram was powered down, cp dpram random intr was
		* ocurred. so, fixed by muxing cp dpram intr pin to GPIO output
		* high,..
		*/
		gpio_set_value(pm_data->mdata->gpio_mbx_intr, 1);
		s3c_gpio_cfgpin(pm_data->mdata->gpio_mbx_intr, S3C_GPIO_OUTPUT);
		pm_data->pm_states = IDPRAM_PM_DPRAM_POWER_DOWN;

		return 0;
	} else {
		mif_err("MIF: idpram hold read_lock\n");
		return -EBUSY;
	}
}
static void s5p_idpram_try_resume(struct work_struct *work)
{
	struct idpram_pm_data *pm_data;
	struct dpram_link_device *dpld;
	struct link_device *ld;
	unsigned long delay;
	u16 cmd;
	mif_info("+++\n");

	pm_data = container_of(work, struct idpram_pm_data, resume_dwork.work);
	dpld = container_of(pm_data, struct dpram_link_device, pm_data);
	ld = &dpld->ld;

	if (pm_data->last_msg == INT_CMD(INT_CMD_IDPRAM_RESUME_REQ)) {
		pm_data->last_msg = 0;

		s5p_idpram_set_pm_lock(dpld, 0);
		wake_unlock(&pm_data->hold_wlock);

		delay = msecs_to_jiffies(10);
		schedule_delayed_work(&pm_data->tx_dwork, delay);

		mif_info("%s resumed\n", ld->name);
		goto exit;
	}

	if (pm_data->resume_try_cnt++ < MAX_RESUME_TRY_CNT) {
		mif_info("%s not resumed yet\n", ld->name);

		cmd = INT_CMD(INT_CMD_IDPRAM_RESUME_REQ);
		mif_info("send IDPRAM_RESUME_REQ (0x%X)\n", cmd);
		dpld->send_intr(dpld, cmd);

		delay = msecs_to_jiffies(200);
		schedule_delayed_work(&pm_data->resume_dwork, delay);
	} else {
		struct io_device *iod;
		mif_err("ERR! %s resume T-I-M-E-O-U-T\n", ld->name);

		iod = link_get_iod_with_format(ld, IPC_FMT);
		if (iod)
			iod->modem_state_changed(iod, STATE_CRASH_EXIT);

		wake_unlock(&pm_data->hold_wlock);

		/* hold wakelock until uevnet sent to rild */
		wake_lock_timeout(&pm_data->hold_wlock, HZ*7);
		s5p_idpram_set_pm_lock(dpld, 0);
	}

exit:
	mif_info("---\n");
}
static void idpram_powerup_start(struct idpram_link_pm_data *pm_data)
{
	pr_info("MIF: <%s>\n", __func__);

	pm_data->last_pm_mailbox = INT_CMD(INT_MASK_CMD_PDA_WAKEUP);
	pm_data->pm_states = IDPRAM_PM_ACTIVE;
}
void dpram_force_cp_crash(struct link_device *ld)
{
	int ret;
	struct dpram_link_device *dpld = to_dpram_link_device(ld);

	pr_info("MIF: <%s+>", __func__);

	/*
	1. set the magic number to 0x554C
	2. send mbx cmd 0x000F
	3. wait for completon
	4. CP responds with cmd = 0xCF
	5. call panic("CP Crashed");
	*/
	dpram_write_magic_code(dpld, 0x554C);

	dpram_write_command(dpld, INT_CMD(0x000F));

	init_completion(&dpld->cp_crash_done);
	ret = wait_for_completion_interruptible_timeout(
		&dpld->cp_crash_done, 20 * HZ);
	if (!ret) {
		pr_err("MIF: CP didn't ack MBX_CMD_PHONE_RESET\n");
		dpram_write_magic_code(dpld, DP_MAGIC_CODE);
	}

	pr_info("MIF: <%s->", __func__);
}
Beispiel #5
0
static int dpram_trigger_force_cp_crash(struct dpram_link_device *dpld)
{
	struct link_device *ld = &dpld->ld;
	int ret;
	int cnt = 5000;

	if (ld->mode == LINK_MODE_ULOAD) {
		mif_err("%s: CP crash is already in progress\n", ld->name);
		return 0;
	}

	ld->mode = LINK_MODE_ULOAD;
	mif_err("%s: called by %pf\n", ld->name, __builtin_return_address(0));

	dpram_wake_up(dpld);

	send_intr(dpld, INT_CMD(INT_CMD_CRASH_EXIT));

	while (cnt--) {
		ret = try_wait_for_completion(&dpld->crash_start_complete);
		if (ret)
			break;
		udelay(1000);
	}

	if (!ret) {
		mif_info("%s: ERR! No CRASH_EXIT ACK from CP\n", ld->name);
		dpram_trigger_crash(dpld);
	}

	return 0;
}
Beispiel #6
0
static void cmd_phone_start_handler(struct dpram_link_device *dpld)
{
	struct link_device *ld = &dpld->ld;
	struct io_device *iod = NULL;

	mif_info("%s: Recv 0xC8 (CP_START)\n", ld->name);

	dpram_init_ipc(dpld);

	iod = link_get_iod_with_format(ld, IPC_FMT);
	if (!iod) {
		mif_info("%s: ERR! no iod\n", ld->name);
		return;
	}

	if (dpld->ext_op && dpld->ext_op->cp_start_handler)
		dpld->ext_op->cp_start_handler(dpld);

	if (ld->mc->phone_state != STATE_ONLINE) {
		mif_info("%s: phone_state: %d -> ONLINE\n",
			ld->name, ld->mc->phone_state);
		iod->modem_state_changed(iod, STATE_ONLINE);
	}

	mif_info("%s: Send 0xC2 (INIT_END)\n", ld->name);
	send_intr(dpld, INT_CMD(INT_CMD_INIT_END));
}
static void idpram_power_down(struct idpram_link_pm_data *pm_data)
{
	pr_info("MIF: <%s>\n", __func__);

	pm_data->last_pm_mailbox = INT_CMD(INT_MASK_CMD_DPRAM_DOWN);
	complete(&pm_data->idpram_down);
}
Beispiel #8
0
static int idpram_resume_check(struct idpram_link_pm_data *pm_data)
{
	/* check last pm mailbox */
	mif_info("MIF: idpram %s, last_pm_mailbox=%x\n", __func__,
		pm_data->last_pm_mailbox);

	if (pm_data->last_pm_mailbox == INT_CMD(INT_MASK_CMD_PDA_WAKEUP)) {
		pm_data->last_pm_mailbox = 0;
		return 0;
	}

	dpram_write_command(pm_data->dpld, INT_CMD(INT_MASK_CMD_PDA_WAKEUP));
	mif_info("MIF: idpram sent PDA_WAKEUP Mailbox(0x%x)\n",
		INT_CMD(INT_MASK_CMD_PDA_WAKEUP));

	return -1;
}
static void s5p_idpram_power_up(struct dpram_link_device *dpld)
{
	struct idpram_pm_data *pm_data = &dpld->pm_data;
	mif_info("+++\n");

	pm_data->last_msg = INT_CMD(INT_CMD_IDPRAM_RESUME_REQ);
	pm_data->pm_state = IDPRAM_PM_ACTIVE;

	mif_info("---\n");
}
static void s5p_idpram_power_down(struct dpram_link_device *dpld)
{
	struct idpram_pm_data *pm_data = &dpld->pm_data;
	mif_info("+++\n");

	pm_data->last_msg = INT_CMD(INT_CMD_IDPRAM_SUSPEND_ACK);
	complete(&pm_data->down_cmpl);

	mif_info("---\n");
}
static void qsc6085_start_handler(struct dpram_link_device *dpld)
{
	struct link_device *ld = &dpld->ld;
	struct io_device *iod;

	mif_info("recv 0xC8 (CP_START)\n");

	mif_info("send 0xC1 (INIT_START)\n");
	dpld->send_intr(dpld, INT_CMD(INT_CMD_INIT_START));

	dpld->reset_dpram_ipc(dpld);

	iod = link_get_iod_with_format(ld, IPC_FMT);
	if (!iod) {
		mif_err("ERR! no iod\n");
		return;
	}
	iod->modem_state_changed(iod, STATE_ONLINE);

	mif_info("send 0xC2 (INIT_END)\n");
	dpld->send_intr(dpld, INT_CMD(INT_CMD_INIT_END));
}
static int cbp71_force_crash_exit(struct modem_ctl *mc)
{
	struct link_device *ld = get_current_link(mc->iod);
	struct dpram_link_device *dpld = to_dpram_link_device(ld);

	mif_err("force_crash_exit\n");
	mif_err("<%s>\n", mc->bootd->name);

	dpld->dpctl->send_intr(INT_CMD(INT_CMD_ERR_DISPLAY));
	mc->iod->modem_state_changed(mc->iod, STATE_CRASH_EXIT);

	return 0;
}
Beispiel #13
0
static int trigger_force_cp_crash(struct dpram_link_device *dpld)
{
	struct link_device *ld = &dpld->ld;

	if (ld->mode == LINK_MODE_ULOAD) {
		mif_err("%s: CP crash is already in progress\n", ld->mc->name);
		return 0;
	}

	ld->mode = LINK_MODE_ULOAD;
	mif_err("%s: called by %pf\n", ld->name, __builtin_return_address(0));

	dpram_wake_up(dpld);

	send_intr(dpld, INT_CMD(INT_CMD_CRASH_EXIT));

	mif_add_timer(&dpld->crash_ack_timer, FORCE_CRASH_ACK_TIMEOUT,
			handle_no_crash_ack, (unsigned long)dpld);

	return 0;
}
static int s5p_idpram_prepare_suspend(struct dpram_link_device *dpld)
{
	struct link_device *ld = &dpld->ld;
	struct idpram_pm_data *pm_data = &dpld->pm_data;
	struct modem_ctl *mc = dpld->ld.mc;
	struct completion *cmpl;
	unsigned long timeout;
	unsigned long rest;
	int cnt = 0;
	u16 cmd = INT_CMD(INT_CMD_IDPRAM_SUSPEND_REQ);
	mif_info("+++\n");

	pm_data->pm_state = IDPRAM_PM_SUSPEND_PREPARE;
	pm_data->last_msg = 0;
	s5p_idpram_set_pm_lock(dpld, 1);

	/*
	* Because, if dpram was powered down, cp dpram random intr was
	* ocurred. so, fixed by muxing cp dpram intr pin to GPIO output
	* high,..
	*/
	gpio_set_value(dpld->gpio_int2cp, 1);
	s3c_gpio_cfgpin(dpld->gpio_int2cp, S3C_GPIO_OUTPUT);

	/* prevent PDA_ACTIVE status is low */
	gpio_set_value(mc->gpio_pda_active, 1);

	cmpl = &pm_data->down_cmpl;
	timeout = IDPRAM_SUSPEND_REQ_TIMEOUT;
	cnt = 0;
	do {
		init_completion(cmpl);

		mif_info("send IDPRAM_SUSPEND_REQ (0x%X)\n", cmd);
		dpld->send_intr(dpld, cmd);

		rest = wait_for_completion_timeout(cmpl, timeout);
		if (rest == 0) {
			cnt++;
			mif_err("timeout!!! (count = %d)\n", cnt);
			if (cnt >= 3) {
				mif_err("ERR! no response from CP\n");
				break;
			}
		}
	} while (rest == 0);

	switch (pm_data->last_msg) {
	case INT_CMD(INT_CMD_IDPRAM_SUSPEND_ACK):
		mif_info("recv IDPRAM_SUSPEND_ACK (0x%X)\n", pm_data->last_msg);
		pm_data->pm_state = IDPRAM_PM_DPRAM_POWER_DOWN;
		break;

	default:
		mif_err("ERR! %s down or not ready!!! (intr 0x%04X)\n",
			ld->name, dpld->recv_intr(dpld));
		timeout = msecs_to_jiffies(500);
		wake_lock_timeout(&pm_data->hold_wlock, timeout);
		s5p_idpram_set_pm_lock(dpld, 0);
		break;
	}

	mif_info("---\n");
	return 0;
}
Beispiel #15
0
static void cmd_req_active_handler(struct dpram_link_device *dpld)
{
	send_intr(dpld, INT_CMD(INT_CMD_RES_ACTIVE));
}
static void qsc6085_req_active_handler(struct dpram_link_device *dpld)
{
	struct modem_ctl *mc = dpld->ld.mc;
	mif_info("pda_active = %d\n", gpio_get_value(mc->gpio_pda_active));
	dpld->send_intr(dpld, INT_CMD(INT_CMD_RES_ACTIVE));
}
Beispiel #17
0
static void idpram_power_down_nack(struct idpram_link_pm_data *pm_data)
{
	pm_data->last_pm_mailbox = INT_CMD(INT_MASK_CMD_DPRAM_DOWN_NACK);
	complete(&pm_data->idpram_down);
	mif_debug("MIF: <%s>\n", __func__);
}
static int idpram_pre_suspend(struct idpram_link_pm_data *pm_data)
{
	int timeout_ret = 0;
	int suspend_retry = 3;
	u16 intr_out = INT_CMD(INT_MASK_CMD_PDA_SLEEP);
	struct io_device *iod = dpram_find_iod_by_format(pm_data->dpld,
		IPC_RAMDUMP);

	pr_info("MIF: <%s+>\n", __func__);

	/*
	1. write magic number=0x554C
	2. send phone reset cmd=0x000F
	3. collect the modem ramdump
	4. modem reset
	5. modem on
	*/
#if defined(ENABLE_FORCED_CP_CRASH)
	dpram_force_cp_crash(&pm_data->dpld->ld);

	fp = mif_open_file("/sdcard/ramdump1.data");
	if (!fp)
		pr_err("MIF: <%s> file pointer is NULL\n", __func__);

	dpram_start_ramdump(&pm_data->dpld->ld, iod);

	for (; iod->ramdump_size;)
		dpram_read_ramdump(&pm_data->dpld->ld, iod);

	dpram_stop_ramdump(&pm_data->dpld->ld, iod);

	mif_close_file(fp);

	iod->mc->ops.modem_reset(iod->mc);
	iod->mc->ops.modem_on(iod->mc);

	pr_info("MIF: <%s->\n", __func__);
	return 0;
#endif

	pm_data->pm_states = IDPRAM_PM_SUSPEND_PREPARE;
	pm_data->last_pm_mailbox = 0;
	idpram_write_lock(pm_data, 1);

	gpio_set_value(pm_data->mdata->gpio_mbx_intr, 1);

	/* prevent PDA_ACTIVE status is low */
	gpio_set_value(pm_data->mdata->gpio_pda_active, 1);

	if (!atomic_read(&pm_data->read_lock)) {
		do {
			init_completion(&pm_data->idpram_down);
			dpram_write_command(pm_data->dpld, intr_out);
			pr_info("MIF: sending cmd = 0x%X\n", intr_out);
			timeout_ret =
			wait_for_completion_timeout(&pm_data->idpram_down,
				PDA_SLEEP_CMD_TIMEOUT);

			if (!timeout_ret)
				pr_err("MIF: timeout!. retry cnt = %d\n", \
					suspend_retry);
		} while (!timeout_ret && --suspend_retry);

		if (!timeout_ret && !suspend_retry)
			pr_err("MIF: no response for PDA_SLEEP cmd\n");

		pr_info("MIF: last responce from cp = 0x%X\n", \
			pm_data->last_pm_mailbox);

		switch (pm_data->last_pm_mailbox) {
		case INT_CMD(INT_MASK_CMD_DPRAM_DOWN):
			pr_info("MIF: INT_MASK_CMD_DPRAM_DOWN\n");
			break;

		/* if nack or other interrup, hold wakelock for DPM resume */
#ifndef CONFIG_CDMA_MODEM_QSC6085
		case INT_CMD(INT_MASK_CMD_DPRAM_DOWN_NACK):
			pr_info("MIF: INT_MASK_CMD_DPRAM_DOWN_NACK\n");
			break;
#endif

		default:
			pr_err("MIF: idpram down or not ready!! intr = 0x%X\n",
				dpram_readh(&pm_data->dpld->dpram->mbx_cp2ap));
			wake_lock_timeout(&pm_data->hold_wlock,
				msecs_to_jiffies(500));
			idpram_write_lock(pm_data, 0);

			/*
			1. Flash a modem which crashes when AP sends
			   cmd=PDA_SLEEP
			2. collect the modem ramdump
			3. modem reset
			4. modem on
			*/
#if defined(CP_CRASHES_ON_PDA_SLEEP_CMD)
			fp = mif_open_file("/sdcard/ramdump2.data");
			if (!fp)
				pr_err("MIF: <%s> fp is NULL\n", __func__);

			dpram_start_ramdump(&pm_data->dpld->ld, iod);

			for (; iod->ramdump_size;)
				dpram_read_ramdump(&pm_data->dpld->ld, iod);

			dpram_stop_ramdump(&pm_data->dpld->ld, iod);

			mif_close_file(fp);

			iod->mc->ops.modem_reset(iod->mc);
			iod->mc->ops.modem_on(iod->mc);
#endif

			pr_info("MIF: <%s->\n", __func__);
			return 0;
		}

		/*
		* Because, if dpram was powered down, cp dpram random intr was
		* ocurred. so, fixed by muxing cp dpram intr pin to GPIO output
		* high,..
		*/
		gpio_set_value(pm_data->mdata->gpio_mbx_intr, 1);
		s3c_gpio_cfgpin(pm_data->mdata->gpio_mbx_intr,
			S3C_GPIO_OUTPUT);
		pm_data->pm_states = IDPRAM_PM_DPRAM_POWER_DOWN;

		pr_info("MIF: <%s->\n", __func__);
		return 0;
	} else {
		pr_err("MIF: hold read_lock failed\n");
		return -EBUSY;
	}
}