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"); 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; gpio_set_value(mc->gpio_cp_reset, 0); gpio_set_value(mc->gpio_cp_on, 0); 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); 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, phone_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; }
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; }
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; }