static void stop_pm(struct mem_link_device *mld)
{
	print_pm_status(mld);

	mif_disable_irq(&mld->irq_ap_wakeup);
	mif_disable_irq(&mld->irq_cp_status);
}
Exemplo n.º 2
0
static void stop_link_pm(struct modem_link_pm *pm)
{
	unsigned long flags;
	enum pm_state state;
	enum pm_event event;

	spin_lock_irqsave(&pm->lock, flags);

	if (!pm->active)
		goto exit;

	pm->active = false;

	mif_disable_irq(&pm->cp2ap_wakeup_irq);
	mif_err("%s: PM %s_irq#%d handler disabled\n", pm->link_name,
		pm->cp2ap_wakeup_irq.name, pm->cp2ap_wakeup_irq.num);

	mif_disable_irq(&pm->cp2ap_status_irq);
	mif_err("%s: PM %s_irq#%d handler disabled\n", pm->link_name,
		pm->cp2ap_status_irq.name, pm->cp2ap_status_irq.num);

	state = pm->fsm.state;
	event = PM_EVENT_STOP_PM;
	set_pm_fsm(pm, state, PM_STATE_UNMOUNTED, event);
	print_pm_event(pm, event);

exit:
	spin_unlock_irqrestore(&pm->lock, flags);
}
Exemplo n.º 3
0
static int ss300_off(struct modem_ctl *mc)
{
	struct io_device *iod = mc->iod;
	struct link_device *ld = get_current_link(iod);
	unsigned long flags;
	int i;

	mif_disable_irq(&mc->irq_cp_active);

	mif_info("%s: %s: +++\n", mc->name, FUNC);

	print_mc_state(mc);

	spin_lock_irqsave(&mc->lock, flags);

	if (cp_offline(mc)) {
		spin_unlock_irqrestore(&mc->lock, flags);
		mif_err("%s: %s: OFFLINE already!!!\n", mc->name, FUNC);
		goto exit;
	}

	iod->modem_state_changed(iod, STATE_OFFLINE);

	spin_unlock_irqrestore(&mc->lock, flags);

	if (ld->close_tx)
		ld->close_tx(ld);

#if 0
	wait_for_link_unmount(mc, ld);
#endif

	if (gpio_get_value(mc->gpio_cp_on) == 0) {
		mif_err("%s: cp_on == 0\n", mc->name);
		goto exit;
	}

	/* wait for cp_active for 3 seconds */
	for (i = 0; i < 150; i++) {
		if (gpio_get_value(mc->gpio_phone_active))
			break;
		msleep(20);
	}

	print_mc_state(mc);

	if (ld->off)
		ld->off(ld);

	if (gpio_get_value(mc->gpio_cp_reset)) {
		mif_err("%s: %s: cp_reset -> 0\n", mc->name, FUNC);
		gpio_set_value(mc->gpio_cp_reset, 0);
		print_mc_state(mc);
	}

exit:
	mif_info("%s: %s: ---\n", mc->name, FUNC);
	return 0;
}
Exemplo n.º 4
0
static int ss300_on(struct modem_ctl *mc)
{
	struct link_device *ld = get_current_link(mc->iod);
	int cp_on;
	int cp_reset;
	int cp_active;
	int cp_status;
	unsigned long flags;

	mif_err("+++\n");

	spin_lock_irqsave(&ld->lock, flags);

	cp_on = gpio_get_value(mc->gpio_cp_on);
	cp_reset  = gpio_get_value(mc->gpio_cp_reset);
	cp_active = gpio_get_value(mc->gpio_phone_active);
	cp_status = gpio_get_value(mc->gpio_cp_status);

	mif_err("state:%s cp_on:%d cp_reset:%d cp_active:%d cp_status:%d\n",
		mc_state(mc), cp_on, cp_reset, cp_active, cp_status);

	mc->phone_state = STATE_OFFLINE;

	gpio_set_value(mc->gpio_pda_active, 1);

	if (mc->wake_lock && !wake_lock_active(mc->wake_lock)) {
		wake_lock(mc->wake_lock);
		mif_err("%s->wake_lock locked\n", mc->name);
	}

	if (ld->ready)
		ld->ready(ld);

	spin_unlock_irqrestore(&ld->lock, flags);

	mif_disable_irq(&mc->irq_cp_active);

	gpio_set_value(mc->gpio_cp_on, 0);
	msleep(100);

	gpio_set_value(mc->gpio_cp_reset, 0);
	msleep(500);

	gpio_set_value(mc->gpio_cp_on, 1);
	msleep(100);

	if (ld->reset)
		ld->reset(ld);

	gpio_set_value(mc->gpio_cp_reset, 1);
	msleep(300);

	mif_err("---\n");
	return 0;
}
Exemplo n.º 5
0
static int ss300_on(struct modem_ctl *mc)
{
	struct io_device *iod = mc->iod;
	struct link_device *ld = get_current_link(iod);
	unsigned long flags;

	mif_disable_irq(&mc->irq_cp_active);

	mif_info("%s: %s: +++\n", mc->name, FUNC);

	print_mc_state(mc);

	spin_lock_irqsave(&mc->lock, flags);

	iod->modem_state_changed(iod, STATE_OFFLINE);

	gpio_set_value(mc->gpio_pda_active, 1);

	if (mc->wake_lock && !wake_lock_active(mc->wake_lock)) {
		wake_lock(mc->wake_lock);
		mif_err("%s->wake_lock locked\n", mc->name);
	}

	if (ld->ready)
		ld->ready(ld);

	spin_unlock_irqrestore(&mc->lock, flags);

	gpio_set_value(mc->gpio_cp_on, 0);
	msleep(100);

	gpio_set_value(mc->gpio_cp_reset, 0);
	print_mc_state(mc);
	msleep(500);

	gpio_set_value(mc->gpio_cp_on, 1);
	msleep(100);

	if (ld->reset)
		ld->reset(ld);

	if (mc->gpio_ap_dump_int)
		gpio_set_value(mc->gpio_ap_dump_int, 0);

	gpio_set_value(mc->gpio_cp_reset, 1);
	print_mc_state(mc);
	msleep(300);

	mif_info("%s: %s: ---\n", mc->name, FUNC);
	return 0;
}
Exemplo n.º 6
0
static int ss333_dump_reset(struct modem_ctl *mc)
{
	struct io_device *iod = mc->iod;
	struct link_device *ld = get_current_link(iod);
	unsigned int gpio_cp_reset = mc->gpio_cp_reset;
	unsigned long flags;

	mif_disable_irq(&mc->irq_cp_active);

	mif_info("%s: %s: +++\n", mc->name, FUNC);

	print_mc_state(mc);

	spin_lock_irqsave(&mc->lock, flags);

	iod->modem_state_changed(iod, STATE_CRASH_EXIT);

	if (mc->wake_lock && !wake_lock_active(mc->wake_lock)) {
		wake_lock(mc->wake_lock);
		mif_err("%s->wake_lock locked\n", mc->name);
	}

	if (ld->off)
		ld->off(ld);

	spin_unlock_irqrestore(&mc->lock, flags);

	gpio_set_value(gpio_cp_reset, 0);
	print_mc_state(mc);
	udelay(200);

	if (ld->reset)
		ld->reset(ld);

	gpio_set_value(gpio_cp_reset, 1);
	print_mc_state(mc);
	msleep(300);

	gpio_set_value(mc->gpio_ap_status, 1);

	mif_info("%s: %s: ---\n", mc->name, FUNC);
	return 0;
}
Exemplo n.º 7
0
static int ss300_dump_reset(struct modem_ctl *mc)
{
	struct link_device *ld = get_current_link(mc->iod);
	unsigned int gpio_cp_reset = mc->gpio_cp_reset;
	unsigned long flags;

	spin_lock_irqsave(&ld->lock, flags);

	mif_err("+++\n");

	if (mc->wake_lock && !wake_lock_active(mc->wake_lock)) {
		wake_lock(mc->wake_lock);
		mif_err("%s->wake_lock locked\n", mc->name);
	}

	if (ld->ready)
		ld->ready(ld);

	spin_unlock_irqrestore(&ld->lock, flags);

	mif_disable_irq(&mc->irq_cp_active);

	gpio_set_value(gpio_cp_reset, 0);
	udelay(200);

	if (ld->reset)
		ld->reset(ld);

	gpio_set_value(gpio_cp_reset, 1);
	msleep(300);

	gpio_set_value(mc->gpio_ap_status, 1);

	mif_err("---\n");
	return 0;
}
static int init_pm(struct mem_link_device *mld)
{
	int err;
	unsigned int gpio;
	unsigned int irq_ap_wakeup;
	unsigned int irq_cp_status;
	unsigned long flags;

	gpio_set_value(mld->gpio_ap_status, 0);

	/*
	Retrieve GPIO#, IRQ#, and IRQ flags for PM
	*/
	gpio = mld->gpio_ap_wakeup;
	irq_ap_wakeup = gpio_to_irq(gpio);
	mif_err("CP2AP_WAKEUP GPIO:%d IRQ:%d\n", gpio, irq_ap_wakeup);

	gpio = mld->gpio_cp_wakeup;
	mif_err("AP2CP_WAKEUP GPIO:%d\n", gpio);

	gpio = mld->gpio_cp_status;
	irq_cp_status = gpio_to_irq(gpio);
	mif_err("CP2AP_STATUS GPIO:%d IRQ:%d\n", gpio, irq_cp_status);

	gpio = mld->gpio_ap_status;
	mif_err("AP2CP_STATUS GPIO:%d\n", gpio);

	/*
	Initialize locks, completions, bottom halves, etc.
	*/
	wake_lock_init(&mld->ap_wlock, WAKE_LOCK_SUSPEND, "lli_ap_wlock");

	wake_lock_init(&mld->cp_wlock, WAKE_LOCK_SUSPEND, "lli_cp_wlock");

	INIT_DELAYED_WORK(&mld->cp_sleep_dwork, release_cp_wakeup);

	spin_lock_init(&mld->pm_lock);
	spin_lock_init(&mld->sig_lock);
	atomic_set(&mld->ref_cnt, 0);

	/*
	Enable IRQs for PM
	*/
	print_pm_status(mld);

	flags = (IRQF_TRIGGER_HIGH | IRQF_ONESHOT);

	mif_init_irq(&mld->irq_ap_wakeup, irq_ap_wakeup,
		     "lli_cp2ap_wakeup", flags);
	err = mif_request_irq(&mld->irq_ap_wakeup, ap_wakeup_interrupt, mld);
	if (err)
		return err;
	mif_disable_irq(&mld->irq_ap_wakeup);

	mif_init_irq(&mld->irq_cp_status, irq_cp_status,
		     "lli_cp2ap_status", flags);
	err = mif_request_irq(&mld->irq_cp_status, cp_status_handler, mld);
	if (err)
		return err;
	mif_disable_irq(&mld->irq_cp_status);

	return 0;
}
Exemplo n.º 9
0
int init_link_device_pm(struct link_device *ld,
			struct modem_link_pm *pm,
			struct link_pm_svc *pm_svc,
			void (*fail_fn)(struct modem_link_pm *),
			void (*cp_fail_fn)(struct modem_link_pm *))
{
	struct modem_data *mdata = ld->mdm_data;
	int err;
	int cp2ap_wakeup;
	int cp2ap_status;
	unsigned int num;
	unsigned long flags;
	char name[MAX_NAME_LEN];

	/*
	Set up variables for PM
	*/
	pm->link_name = ld->name;
	pm->fail_handler = fail_fn;
	pm->cp_fail_handler = cp_fail_fn;

	/*
	Retrieve GPIO pins and IRQ numbers for PM
	*/
	pm->gpio_cp2ap_wakeup = mdata->gpio_ap_wakeup;
	pm->gpio_ap2cp_wakeup = mdata->gpio_cp_wakeup;
	pm->gpio_cp2ap_status = mdata->gpio_cp_status;
	pm->gpio_ap2cp_status = mdata->gpio_ap_status;

	num = gpio_to_irq(pm->gpio_cp2ap_wakeup);
	flags = IRQF_NO_THREAD | IRQF_NO_SUSPEND | IRQF_ONESHOT;
	snprintf(name, MAX_NAME_LEN, "%s_cp2ap_wakeup", pm->link_name);
	mif_init_irq(&pm->cp2ap_wakeup_irq, num, name, flags);

	num = gpio_to_irq(pm->gpio_cp2ap_status);
	flags = IRQF_NO_THREAD | IRQF_NO_SUSPEND | IRQF_ONESHOT;
	snprintf(name, MAX_NAME_LEN, "%s_cp2ap_status", pm->link_name);
	mif_init_irq(&pm->cp2ap_status_irq, num, name, flags);

	mif_err("CP2AP_WAKEUP GPIO:%d IRQ:%d\n",
		pm->gpio_cp2ap_wakeup, pm->cp2ap_wakeup_irq.num);

	mif_err("AP2CP_WAKEUP GPIO:%d\n", pm->gpio_ap2cp_wakeup);

	mif_err("CP2AP_STATUS GPIO:%d IRQ:%d\n",
		pm->gpio_cp2ap_status, pm->cp2ap_status_irq.num);

	mif_err("AP2CP_STATUS GPIO:%d\n", pm->gpio_ap2cp_status);

	/*
	Register cp2ap_wakeup IRQ handler
	*/
	cp2ap_wakeup = gpio_get_value(pm->gpio_cp2ap_wakeup);
	change_irq_level(pm->cp2ap_wakeup_irq.num, cp2ap_wakeup);

	err = mif_request_irq(&pm->cp2ap_wakeup_irq, cp2ap_wakeup_handler, pm);
	if (err) {
		mif_err("%s: ERR! request_irq(%s#%d) fail (%d)\n",
			pm->link_name, pm->cp2ap_wakeup_irq.name,
			pm->cp2ap_wakeup_irq.num, err);
		return err;
	}
	mif_disable_irq(&pm->cp2ap_wakeup_irq);

	mif_err("%s: %s_irq#%d handler registered\n", pm->link_name,
		pm->cp2ap_wakeup_irq.name, pm->cp2ap_wakeup_irq.num);

	/*
	Register cp2ap_status IRQ handler
	*/
	cp2ap_status = gpio_get_value(pm->gpio_cp2ap_status);
	change_irq_level(pm->cp2ap_status_irq.num, cp2ap_status);

	err = mif_request_irq(&pm->cp2ap_status_irq, cp2ap_status_handler, pm);
	if (err) {
		mif_err("%s: ERR! request_irq(%s#%d) fail (%d)\n",
			pm->link_name, pm->cp2ap_status_irq.name,
			pm->cp2ap_status_irq.num, err);
		free_irq(pm->cp2ap_wakeup_irq.num, pm);
		return err;
	}
	mif_disable_irq(&pm->cp2ap_status_irq);

	mif_err("%s: %s_irq#%d handler registered\n", pm->link_name,
		pm->cp2ap_status_irq.name, pm->cp2ap_status_irq.num);

	/*
	Initialize common variables for PM
	*/
	spin_lock_init(&pm->lock);

	snprintf(pm->wlock_name, MAX_NAME_LEN, "%s_pm_wlock", pm->link_name);
	wake_lock_init(&pm->wlock, WAKE_LOCK_SUSPEND, pm->wlock_name);

	snprintf(pm->wq_name, MAX_NAME_LEN, "%s_pm_wq", pm->link_name);
	flags = WQ_NON_REENTRANT | WQ_UNBOUND | WQ_HIGHPRI;
	pm->wq = alloc_workqueue(pm->wq_name, flags, 1);
	if (!pm->wq) {
		mif_err("%s: ERR! fail to create %s\n",
			pm->link_name, pm->wq_name);
		return -EFAULT;
	}

	INIT_DELAYED_WORK(&pm->cp_free_dwork, cp_free_work_func);

	init_pm_fsm(pm);

	/*
	Register PM functions set by the common link PM framework and used by
	each link device driver
	*/
	pm->start = start_link_pm;
	pm->stop = stop_link_pm;
	pm->request_hold = request_hold;
	pm->release_hold = release_hold;
	pm->link_active = link_active;

	return 0;
}