struct link_device *shmem_create_link_device(struct platform_device *pdev) { struct modem_data *modem; struct mem_link_device *mld; struct link_device *ld; unsigned long start; unsigned long size; int err; mif_err("+++\n"); /** * Get the modem (platform) data */ modem = (struct modem_data *)pdev->dev.platform_data; if (!modem) { mif_err("ERR! modem == NULL\n"); return NULL; } if (!modem->mbx) { mif_err("%s: ERR! mbx == NULL\n", modem->link_name); return NULL; } mif_err("MODEM:%s LINK:%s\n", modem->name, modem->link_name); /** * Create a MEMORY link device instance */ mld = mem_create_link_device(MEM_SYS_SHMEM, modem); if (!mld) { mif_err("%s: ERR! create_link_device fail\n", modem->link_name); return NULL; } ld = &mld->link_dev; /** * Link local functions to the corresponding function pointers that are * optional for some link device */ ld->ioctl = shmem_ioctl; /** * Link local functions to the corresponding function pointers that are * mandatory for all memory-type link devices */ mld->remap_region = shm_request_region; mld->recv_cp2ap_irq = recv_cp2ap_irq; mld->send_ap2cp_irq = send_ap2cp_irq; /** * Link local functions to the corresponding function pointers that are * optional for some memory-type link devices */ mld->read_ap2cp_irq = read_ap2cp_irq; mld->unmap_region = shm_release_region; /** * Initialize SHMEM maps for BOOT (physical map -> logical map) */ start = shm_get_phys_base() + shm_get_boot_rgn_offset(); size = shm_get_boot_rgn_size(); err = mem_setup_boot_map(mld, start, size); if (err < 0) { mif_err("%s: ERR! setup_boot_map fail (%d)\n", ld->name, err); goto error; } /** * Initialize SHMEM maps for IPC (physical map -> logical map) */ start = shm_get_phys_base() + shm_get_ipc_rgn_offset(); size = shm_get_ipc_rgn_size(); err = mem_setup_ipc_map(mld, start, size); if (err < 0) { mif_err("%s: ERR! setup_ipc_map fail (%d)\n", ld->name, err); goto error; } /** * Retrieve SHMEM MBOX#, IRQ#, etc. */ mld->mbx_cp2ap_msg = modem->mbx->mbx_cp2ap_msg; mld->irq_cp2ap_msg = modem->mbx->irq_cp2ap_msg; mld->mbx_ap2cp_msg = modem->mbx->mbx_ap2cp_msg; mld->int_ap2cp_msg = modem->mbx->int_ap2cp_msg; /** * Register interrupt handlers */ err = mbox_request_irq(mld->irq_cp2ap_msg, shmem_irq_handler, mld); if (err) { mif_err("%s: ERR! mbox_request_irq fail (%d)\n", ld->name, err); goto error; } mif_err("---\n"); return ld; error: kfree(mld); mif_err("xxx\n"); return NULL; }
struct link_device *lli_create_link_device(struct platform_device *pdev) { struct modem_data *modem; struct mem_link_device *mld; struct link_device *ld; int err; unsigned long start; unsigned long size; #ifdef DEBUG_MODEM_IF struct dentry *debug_dir = debugfs_create_dir("svnet", NULL); #endif mif_err("+++\n"); /** * Get the modem (platform) data */ modem = (struct modem_data *)pdev->dev.platform_data; if (!modem) { mif_err("ERR! modem == NULL\n"); return NULL; } if (!modem->gpio_ap_wakeup) { mif_err("ERR! no gpio_ap_wakeup\n"); return NULL; } if (!modem->gpio_cp_status) { mif_err("ERR! no gpio_cp_status\n"); return NULL; } mif_err("MODEM:%s LINK:%s\n", modem->name, modem->link_name); /** * Create a MEMORY link device instance */ mld = mem_create_link_device(MEM_LLI_SHMEM, modem); if (!mld) { mif_err("%s: ERR! create_link_device fail\n", modem->link_name); return NULL; } g_mld = mld; ld = &mld->link_dev; ld->ready = lli_link_ready; ld->reset = lli_link_reset; ld->reload = lli_link_reload; ld->off = lli_link_off; ld->unmounted = lli_link_unmounted; ld->suspended = lli_link_suspended; ld->enable_irq = lli_enable_irq; ld->disable_irq = lli_disable_irq; /** * Link local functions to the corresponding function pointers that are * mandatory for all memory-type link devices */ mld->send_ap2cp_irq = send_ap2cp_irq; /* ** Link local functions to the corresponding function pointers */ #ifndef CONFIG_LINK_POWER_MANAGEMENT_WITH_FSM mld->finalize_cp_start = finalize_cp_start; #endif #ifdef CONFIG_LINK_POWER_MANAGEMENT mld->start_pm = start_pm; mld->stop_pm = stop_pm; mld->forbid_cp_sleep = forbid_cp_sleep; mld->permit_cp_sleep = permit_cp_sleep; mld->link_active = check_link_status; #endif #ifdef DEBUG_MODEM_IF mld->debug_info = mipi_lli_debug_info; #endif /** * Initialize SHMEM maps for IPC (physical map -> logical map) */ start = mipi_lli_get_phys_base(); size = mipi_lli_get_phys_size(); err = mem_register_ipc_rgn(mld, start, size); if (err < 0) { mif_err("%s: ERR! register_ipc_rgn fail (%d)\n", ld->name, err); goto error; } err = mem_setup_ipc_map(mld); if (err < 0) { mif_err("%s: ERR! setup_ipc_map fail (%d)\n", ld->name, err); mem_unregister_ipc_rgn(mld); goto error; } #ifdef CONFIG_LINK_DEVICE_WITH_SBD_ARCH if (ld->sbd_ipc) { struct sbd_link_device *sld = &mld->sbd_link_dev; err = create_sbd_link_device(ld, sld, mld->base, mld->size); if (err < 0) goto error; } #endif /** * Register interrupt handlers */ err = mipi_lli_register_handler(lli_irq_handler, mld); if (err) { mif_err("%s: ERR! register_handler fail (%d)\n", ld->name, err); goto error; } /* ** Retrieve GPIO#, IRQ#, and IRQ flags for PM */ mld->gpio_ap_wakeup = modem->gpio_ap_wakeup; mld->gpio_cp_wakeup = modem->gpio_cp_wakeup; mld->gpio_cp_status = modem->gpio_cp_status; mld->gpio_ap_status = modem->gpio_ap_status; mld->gpio_ipc_int2cp = modem->gpio_ipc_int2cp; #ifdef CONFIG_LINK_POWER_MANAGEMENT err = init_pm(mld); if (err) goto error; #endif #ifdef DEBUG_MODEM_IF mld->mem_dump_blob.data = mld->base; mld->mem_dump_blob.size = mld->size; debugfs_create_blob("mem_dump", S_IRUGO, debug_dir, &mld->mem_dump_blob); #endif mif_err("---\n"); return ld; error: kfree(mld); mif_err("xxx\n"); return NULL; }
struct link_device *c2c_create_link_device(struct platform_device *pdev) { struct modem_data *modem; struct mem_link_device *mld; struct link_device *ld; int err; int i; unsigned int irq; unsigned long flags; char name[MAX_NAME_LEN]; mif_err("+++\n"); /** * Get the modem (platform) data */ modem = (struct modem_data *)pdev->dev.platform_data; if (!modem) { mif_err("ERR! modem == NULL\n"); return NULL; } if (modem->irq_ap_wakeup == 0) { mif_err("ERR! no irq_ap_wakeup\n"); return NULL; } if (modem->irq_cp_status == 0) { mif_err("ERR! no irq_cp_status\n"); return NULL; } mif_err("MODEM:%s LINK:%s\n", modem->name, modem->link_name); /** * Create a MEMORY link device instance */ mld = mem_create_link_device(MEM_C2C_SHMEM, modem); if (!mld) { mif_err("%s: ERR! create_link_device fail\n", modem->link_name); return NULL; } ld = &mld->link_dev; /* ** Link local functions to the corresponding function pointers */ mld->send_ap2cp_irq = send_int2cp; mld->finalize_cp_start = finalize_cp_start; mld->forbid_cp_sleep = forbid_cp_sleep; mld->permit_cp_sleep = permit_cp_sleep; mld->link_active = link_active; /* ** Retrieve SHMEM resource */ mld->start = c2c_get_phys_base() + c2c_get_sh_rgn_offset(); mld->size = c2c_get_sh_rgn_size(); mld->base = mem_register_ipc_rgn(mld, mld->start, mld->size); if (!mld->base) { mif_err("%s: ERR! register_ipc_rgn fail\n", ld->name); goto error; } /* ** Initialize SHMEM maps (physical map -> logical map) */ err = mem_setup_ipc_map(mld); if (err < 0) { mif_err("%s: ERR! init_ipc_map fail (err %d)\n", ld->name, err); goto error; } /* ** Register interrupt handlers */ err = c2c_register_handler(c2c_irq_handler, mld); if (err) { mif_err("%s: ERR! c2c_register_handler fail (err %d)\n", ld->name, err); goto error; } /* ** Retrieve GPIO#, IRQ#, and IRQ flags for PM */ mld->gpio_ap_wakeup = modem->gpio_ap_wakeup; mld->irq_ap_wakeup = modem->irq_ap_wakeup; mld->gpio_cp_wakeup = modem->gpio_cp_wakeup; mld->gpio_cp_status = modem->gpio_cp_status; mld->irq_cp_status = modem->irq_cp_status; mld->gpio_ap_status = modem->gpio_ap_status; snprintf(name, MAX_NAME_LEN, "%s_ap_wakeup", ld->name); irq = mld->irq_ap_wakeup; flags = (IRQF_NO_THREAD | IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH); err = mif_register_isr(irq, ap_wakeup_handler, flags, name, mld); if (err) goto error; snprintf(name, MAX_NAME_LEN, "%s_cp_status", ld->name); irq = mld->irq_cp_status; flags = (IRQF_NO_THREAD | IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH); err = mif_register_isr(irq, cp_status_handler, flags, name, mld); if (err) goto error; mif_err("CP2AP_WAKEUP GPIO# = %d\n", mld->gpio_ap_wakeup); mif_err("CP2AP_WAKEUP IRQ# = %d\n", mld->irq_ap_wakeup); mif_err("AP2CP_WAKEUP GPIO# = %d\n", mld->gpio_cp_wakeup); mif_err("CP2AP_STATUS GPIO# = %d\n", mld->gpio_cp_status); mif_err("CP2AP_STATUS IRQ# = %d\n", mld->irq_cp_status); mif_err("AP2CP_STATUS GPIO# = %d\n", mld->gpio_ap_status); /* ** Initialize locks, completions, bottom halves, etc. for PM */ sprintf(name, "%s_ap_wlock", ld->name); wake_lock_init(&mld->ap_wlock, WAKE_LOCK_SUSPEND, name); sprintf(name, "%s_cp_wlock", ld->name); wake_lock_init(&mld->cp_wlock, WAKE_LOCK_SUSPEND, name); INIT_DELAYED_WORK(&mld->cp_sleep_dwork, release_cp_wakeup); spin_lock_init(&mld->pm_lock); atomic_set(&mld->ref_cnt, 0); gpio_set_value(mld->gpio_ap_status, 0); c2c_assign_gpio_ap_wakeup(mld->gpio_ap_wakeup); c2c_assign_gpio_ap_status(mld->gpio_ap_status); c2c_assign_gpio_cp_wakeup(mld->gpio_cp_wakeup); c2c_assign_gpio_cp_status(mld->gpio_cp_status); mif_err("---\n"); return ld; error: kfree(mld); mif_err("xxx\n"); return NULL; }