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; }
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; }
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; }
static irqreturn_t cp_active_handler(int irq, void *arg) { struct modem_ctl *mc = (struct modem_ctl *)arg; struct link_device *ld; enum modem_state old_state; enum modem_state new_state; unsigned long flags; if (!cp_online(mc)) goto exit; print_mc_state(mc); if (gpio_get_value(mc->gpio_cp_reset) == 0) goto exit; ld = get_current_link(mc->iod); spin_lock_irqsave(&mc->lock, flags); old_state = mc->phone_state; new_state = mc->phone_state; if (gpio_get_value(mc->gpio_phone_active) != 0) { if (gpio_get_value(mc->gpio_cp_on) == 0) { new_state = STATE_OFFLINE; } else if (old_state == STATE_ONLINE) { new_state = STATE_CRASH_EXIT; } else { mif_err("%s: %s: don't care!!!\n", mc->name, FUNC); } } if (new_state != old_state) { /* Change the modem state for RIL */ mc->iod->modem_state_changed(mc->iod, new_state); /* Change the modem state for CBD */ mc->bootd->modem_state_changed(mc->bootd, new_state); } spin_unlock_irqrestore(&mc->lock, flags); if ((old_state == STATE_ONLINE) && (new_state == STATE_CRASH_EXIT)) { if (timer_pending(&mc->crash_ack_timer)) del_timer(&mc->crash_ack_timer); if (ld->close_tx) ld->close_tx(ld); } exit: return IRQ_HANDLED; }
int ss300_init_modemctl_device(struct modem_ctl *mc, struct modem_data *pdata) { int ret = 0; unsigned int irq = 0; unsigned long flag = 0; char name[MAX_NAME_LEN]; mif_err("+++\n"); ret = dt_gpio_config(mc, pdata); if (ret < 0) return ret; if (!pdata->gpio_cp_on || !pdata->gpio_cp_reset || !pdata->gpio_pda_active || !pdata->gpio_phone_active || !pdata->gpio_ap_wakeup || !pdata->gpio_ap_status || !pdata->gpio_cp_wakeup || !pdata->gpio_cp_status) { mif_err("ERR! no GPIO data\n"); mif_err("xxx\n"); return -ENXIO; } mc->gpio_cp_on = pdata->gpio_cp_on; mc->gpio_cp_reset = pdata->gpio_cp_reset; mc->gpio_pda_active = pdata->gpio_pda_active; mc->gpio_phone_active = pdata->gpio_phone_active; mc->gpio_ap_wakeup = pdata->gpio_ap_wakeup; mc->gpio_ap_status = pdata->gpio_ap_status; mc->gpio_cp_wakeup = pdata->gpio_cp_wakeup; mc->gpio_cp_status = pdata->gpio_cp_status; mc->gpio_ap_dump_int = pdata->gpio_ap_dump_int; gpio_set_value(mc->gpio_cp_reset, 0); gpio_set_value(mc->gpio_cp_on, 0); print_mc_state(mc); ss300_get_ops(mc); dev_set_drvdata(mc->dev, mc); wake_lock_init(&mc_wake_lock, WAKE_LOCK_SUSPEND, "ss300_wake_lock"); mc->wake_lock = &mc_wake_lock; irq = gpio_to_irq(mc->gpio_phone_active); if (!irq) { mif_err("ERR! no irq_cp_active\n"); mif_err("xxx\n"); return -EINVAL; } mif_err("PHONE_ACTIVE IRQ# = %d\n", irq); mc->event_nfb.notifier_call = modemctl_notify_call; register_cp_crash_notifier(&mc->event_nfb); flag = IRQF_TRIGGER_RISING | IRQF_NO_THREAD | IRQF_NO_SUSPEND; snprintf(name, MAX_NAME_LEN, "%s_active", mc->name); mif_init_irq(&mc->irq_cp_active, irq, name, flag); ret = mif_request_irq(&mc->irq_cp_active, cp_active_handler, mc); if (ret) { mif_err("%s: ERR! request_irq(%s#%d) fail (%d)\n", mc->name, mc->irq_cp_active.name, mc->irq_cp_active.num, ret); mif_err("xxx\n"); return ret; } mif_err("---\n"); return 0; }