int do_setup_ddr(struct device *dev) { struct psh_ia_priv *ia_data = (struct psh_ia_priv *)dev_get_drvdata(dev); struct psh_plt_priv *plt_priv = (struct psh_plt_priv *)ia_data->platform_priv; uintptr_t ddr_phy = plt_priv->ddr_phy; uintptr_t imr2_phy = plt_priv->imr2_phy; const struct firmware *fw_entry; struct ia_cmd cmd_user = { .cmd_id = CMD_SETUP_DDR, .sensor_id = 0, }; static int fw_load_done; int load_default = 0; char fname[40]; if (fw_load_done) return 0; #ifdef VPROG2_SENSOR intel_scu_ipc_msic_vprog2(1); msleep(500); #endif again: if (!request_firmware(&fw_entry, fname, dev)) { if (!fw_entry) return -ENOMEM; psh_debug("psh fw size %d virt:0x%p\n", (int)fw_entry->size, fw_entry->data); if (fw_entry->size > APP_IMR_SIZE) { psh_err("psh fw size too big\n"); } else { struct ia_cmd cmd = { .cmd_id = CMD_RESET, .sensor_id = 0, }; memcpy(plt_priv->imr2, fw_entry->data, fw_entry->size); *(uintptr_t *)(&cmd.param) = imr2_phy; cmd.tran_id = 0x1; if (process_send_cmd(ia_data, PSH2IA_CHANNEL3, &cmd, 7)) return -1; ia_data->load_in_progress = 1; wait_for_completion_timeout(&ia_data->cmd_load_comp, 3 * HZ); fw_load_done = 1; } release_firmware(fw_entry); } else { psh_err("cannot find psh firmware(%s)\n", fname); if (!load_default) { psh_err("try to load default psh.bin\n"); snprintf(fname, 20, "psh.bin"); load_default = 1; goto again; } } ia_lbuf_read_reset(ia_data->lbuf); *(unsigned long *)(&cmd_user.param) = ddr_phy; return ia_send_cmd(ia_data, &cmd_user, 7); } static void psh2ia_channel_handle(u32 msg, u32 param, void *data) { struct pci_dev *pdev = (struct pci_dev *)data; struct psh_ia_priv *ia_data = (struct psh_ia_priv *)dev_get_drvdata(&pdev->dev); struct psh_plt_priv *plt_priv = (struct psh_plt_priv *)ia_data->platform_priv; u8 *dbuf = NULL; u16 size = 0; if (unlikely(ia_data->load_in_progress)) { ia_data->load_in_progress = 0; complete(&ia_data->cmd_load_comp); return; } while (!ia_lbuf_read_next(ia_data, &plt_priv->lbuf, &dbuf, &size)) { ia_handle_frame(ia_data, dbuf, size); } sysfs_notify(&pdev->dev.kobj, NULL, "data_size"); } static int psh_imr_init(struct pci_dev *pdev, int imr_src, uintptr_t *phy_addr, void **virt_addr, unsigned size, int bar) { struct page *pg; void __iomem *mem; int ret = 0; unsigned long start = 0, len; if (imr_src == imr_allocate) { /* dynamic alloct memory region */ pg = alloc_pages(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO, get_order(size)); if (!pg) { dev_err(&pdev->dev, "can not allocate app page imr buffer\n"); ret = -ENOMEM; goto err; } *phy_addr = page_to_phys(pg); *virt_addr = page_address(pg); } else if (imr_src == imr_pci_shim) { /* dedicate isolated memory region */ start = pci_resource_start(pdev, bar); len = pci_resource_len(pdev, bar); if (!start || !len) { dev_err(&pdev->dev, "bar %d address not set\n", bar); ret = -EINVAL; goto err; } ret = pci_request_region(pdev, bar, "psh"); if (ret) { dev_err(&pdev->dev, "failed to request psh region " "0x%lx-0x%lx\n", start, (unsigned long)pci_resource_end(pdev, bar)); goto err; } mem = ioremap_nocache(start, len); if (!mem) { dev_err(&pdev->dev, "can not ioremap app imr address\n"); ret = -EINVAL; goto err_ioremap; } *phy_addr = start; *virt_addr = (void *)mem; } else { dev_err(&pdev->dev, "Invalid chip imr source\n"); ret = -EINVAL; goto err; } return 0; err_ioremap: pci_release_region(pdev, bar); err: return ret; } static void psh_imr_free(int imr_src, void *virt_addr, unsigned size) { if (imr_src == imr_allocate) __free_pages(virt_to_page(virt_addr), get_order(size)); else if (imr_src == imr_pci_shim) iounmap((void __iomem *)virt_addr); } static int psh_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int ret = -1; struct psh_ia_priv *ia_data; struct psh_plt_priv *plt_priv; ret = pci_enable_device(pdev); if (ret) { dev_err(&pdev->dev, "fail to enable psh pci device\n"); goto pci_err; } plt_priv = kzalloc(sizeof(*plt_priv), GFP_KERNEL); if (!plt_priv) { dev_err(&pdev->dev, "can not allocate plt_priv\n"); goto plt_err; } switch (intel_mid_identify_cpu()) { case INTEL_MID_CPU_CHIP_TANGIER: if (intel_mid_soc_stepping() == 0) plt_priv->imr_src = imr_allocate; else plt_priv->imr_src = imr_pci_shim; break; case INTEL_MID_CPU_CHIP_ANNIEDALE: plt_priv->imr_src = imr_pci_shim; break; default: dev_err(&pdev->dev, "error memory region\n"); goto psh_imr2_err; break; } /* init IMR2 */ ret = psh_imr_init(pdev, plt_priv->imr_src, &plt_priv->imr2_phy, &plt_priv->imr2, APP_IMR_SIZE, 0); if (ret) goto psh_imr2_err; /* init IMR3 */ ret = psh_imr_init(pdev, plt_priv->imr_src, &plt_priv->ddr_phy, &plt_priv->ddr, BUF_IA_DDR_SIZE, 1); if (ret) goto psh_ddr_err; ret = psh_ia_common_init(&pdev->dev, &ia_data); if (ret) { dev_err(&pdev->dev, "fail to init psh_ia_common\n"); goto psh_ia_err; } ia_lbuf_read_init(&plt_priv->lbuf, plt_priv->ddr, BUF_IA_DDR_SIZE, NULL); ia_data->lbuf = &plt_priv->lbuf; plt_priv->hwmon_dev = hwmon_device_register(&pdev->dev); if (!plt_priv->hwmon_dev) { dev_err(&pdev->dev, "fail to register hwmon device\n"); goto hwmon_err; } ia_data->platform_priv = plt_priv; ret = intel_psh_ipc_bind(PSH_RECV_CH0, psh2ia_channel_handle, pdev); if (ret) { dev_err(&pdev->dev, "fail to bind channel\n"); goto irq_err; } /* just put this dev into suspend status always, since this is fake */ pm_runtime_put_noidle(&pdev->dev); pm_runtime_allow(&pdev->dev); return 0; irq_err: hwmon_device_unregister(plt_priv->hwmon_dev); hwmon_err: psh_ia_common_deinit(&pdev->dev); psh_ia_err: psh_imr_free(plt_priv->imr_src, plt_priv->ddr, BUF_IA_DDR_SIZE); psh_ddr_err: psh_imr_free(plt_priv->imr_src, plt_priv->imr2, APP_IMR_SIZE); psh_imr2_err: kfree(plt_priv); plt_err: pci_dev_put(pdev); pci_err: return ret; }
/* FIXME: it will be a platform device */ static int psh_probe(struct spi_device *client) { int ret = -EPERM; struct psh_ia_priv *ia_data; struct psh_ext_if *psh_if_info; int rc; dev_err(&client->dev, "%s\n", __func__); psh_if_info = kzalloc(sizeof(*psh_if_info), GFP_KERNEL); if (!psh_if_info) { dev_err(&client->dev, "can not allocate psh_if_info\n"); goto psh_if_err; } ret = psh_ia_common_init(&client->dev, &psh_if_info->ia_data); if (ret) { dev_err(&client->dev, "fail to init psh_ia_common\n"); goto psh_ia_err; } ia_data = psh_if_info->ia_data; /* initialize send list */ mutex_init(&psh_if_info->send_data_list.lock); mutex_init(&psh_if_info->workitem_mutex); INIT_LIST_HEAD(&psh_if_info->send_data_list.head); psh_if_info->task_flag = TASK_FLAG_CLEAR; dev_err(&client->dev, "send list inited\n"); psh_if_info->hwmon_dev = hwmon_device_register(&client->dev); if (!psh_if_info->hwmon_dev) { dev_err(&client->dev, "fail to register hwmon device\n"); goto hwmon_err; } psh_if_info->pshc = client; ia_data->platform_priv = psh_if_info; #if 0 psh_if_info->gpio_psh_ctl = acpi_get_gpio_by_index(&client->dev, 1, NULL); #endif psh_if_info->gpio_psh_ctl = -1; if (psh_if_info->gpio_psh_ctl < 0) { dev_warn(&client->dev, "fail to get psh_ctl pin by ACPI\n"); } else { rc = gpio_request(psh_if_info->gpio_psh_ctl, "psh_ctl"); if (rc) { dev_warn(&client->dev, "fail to request psh_ctl pin\n"); psh_if_info->gpio_psh_ctl = -1; } else { gpio_export(psh_if_info->gpio_psh_ctl, 1); gpio_direction_output(psh_if_info->gpio_psh_ctl, 1); gpio_set_value(psh_if_info->gpio_psh_ctl, 1); } } #if 0 psh_if_info->gpio_psh_rst = acpi_get_gpio_by_index(&client->dev, 0, NULL); #endif psh_if_info->gpio_psh_rst = GPIO_PSH_MCU_RESET; if (psh_if_info->gpio_psh_rst < 0) { dev_warn(&client->dev, "failed to get psh_rst pin by ACPI\n"); } else { rc = gpio_request(psh_if_info->gpio_psh_rst, "psh_rst"); if (rc) { dev_warn(&client->dev, "fail to request psh_rst pin\n"); psh_if_info->gpio_psh_rst = -1; } else { gpio_export(psh_if_info->gpio_psh_rst, 1); gpio_direction_output(psh_if_info->gpio_psh_rst, 1); gpio_set_value(psh_if_info->gpio_psh_rst, 1); } } // TODO update gpio_psh_int from platform_data //psh_if_info->gpio_psh_int = (int)id->driver_data; client->irq = gpio_to_irq(GPIO_PSH_INT); // force polling mode #ifdef DRV_POLLING_MODE client->irq = -1; #endif if(client->irq > 0){ psh_if_info->gpio_psh_int = GPIO_PSH_INT; rc = gpio_request(psh_if_info->gpio_psh_int, "psh_int"); if (rc) { dev_warn(&client->dev, "fail to request psh_int pin\n"); psh_if_info->gpio_psh_int = -1; } else { gpio_export(psh_if_info->gpio_psh_int, 1); } /* set the flag to to enable irq when need */ irq_set_status_flags(client->irq, IRQ_NOAUTOEN); ret = request_threaded_irq(client->irq, NULL, psh_byt_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "psh_byt", client); if (ret) { dev_err(&client->dev, "fail to request irq\n"); goto irq_err; } psh_if_info->irq_disabled = 1; } #ifdef DRV_POLLING_MODE psh_if_info->gpio_psh_int = GPIO_PSH_INT; rc = gpio_request(psh_if_info->gpio_psh_int, "psh_int"); if (rc) { dev_warn(&client->dev, "fail to request psh_int pin\n"); psh_if_info->gpio_psh_int = -1; } else { gpio_export(psh_if_info->gpio_psh_int, 1); gpio_direction_input(psh_if_info->gpio_psh_int); } #endif // psh_if_info->wq = create_singlethread_workqueue("psh_work"); /* psh_if_info->wq = alloc_ordered_workqueue("%S", WQ_MEM_RECLAIM|WQ_HIGHPRI, "psh_work");*/ psh_if_info->wq = alloc_workqueue("%s", WQ_HIGHPRI, 0, "psh_work"); #if 1 //just a profiler here timestamp_init_with_name(&client->dev, &psh_if_info->io_profiler, "profile_pull"); poller_init(&psh_if_info->poller_worker, poll_sensor_data_by_thread, psh_if_info); poller_set_frequency(&psh_if_info->poller_worker, 1000); if (!IS_SUCCESS(poller_start(&client->dev, &psh_if_info->poller_worker))) { dev_err(&client->dev, "fail to create poller\n"); goto wq_err; } /* try sync timestamp with sensorhub fw once */ ia_sync_timestamp_with_sensorhub_fw(psh_if_info->ia_data); #endif if (!psh_if_info->wq) { dev_err(&client->dev, "fail to create workqueue\n"); goto wq_err; } INIT_WORK(&psh_if_info->work, psh_work_func); //dev_err(&client->dev, "sensor polling speed: %dHZ\n", POLL_HZ_PER_SECOND); #ifdef DRV_POLLING_MODE INIT_DELAYED_WORK(&psh_if_info->dwork, poll_sensor_data); #endif #ifdef ENABLE_RPM pm_runtime_set_active(&client->dev); pm_runtime_use_autosuspend(&client->dev); pm_runtime_set_autosuspend_delay(&client->dev, 0); pm_runtime_enable(&client->dev); #endif #ifndef DRV_POLLING_MODE psh_if_info->irq_disabled = 0; enable_irq(psh_if_info->pshc->irq); #endif return 0; wq_err: free_irq(client->irq, psh_if_info->pshc); irq_err: hwmon_device_unregister(psh_if_info->hwmon_dev); hwmon_err: psh_ia_common_deinit(&client->dev); psh_ia_err: kfree(psh_if_info); psh_if_err: return ret; }