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; }
static int mcu_platform_probe(struct platform_device *pdev) { int ret, i; struct mcu_data *data; struct mcu *mcu; u8 *base; mcu = platform_get_drvdata(pdev); intel_mcu_tty_driver = alloc_tty_driver(INTEL_MCU_TTY_MINORS); if (!intel_mcu_tty_driver) { dev_err(&pdev->dev, "fail to alloc tty driver\n"); return -ENODEV; } intel_mcu_tty_driver->name = "ttymcu"; intel_mcu_tty_driver->major = INTEL_MCU_TTY_MAJOR; intel_mcu_tty_driver->minor_start = 0; intel_mcu_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; intel_mcu_tty_driver->subtype = SERIAL_TYPE_NORMAL; intel_mcu_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; intel_mcu_tty_driver->init_termios = tty_std_termios; intel_mcu_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; intel_mcu_tty_driver->init_termios.c_ispeed = 38400; intel_mcu_tty_driver->init_termios.c_ospeed = 38400; intel_mcu_tty_driver->init_termios.c_iflag = 0; intel_mcu_tty_driver->init_termios.c_oflag = 0; intel_mcu_tty_driver->init_termios.c_lflag = 0; tty_set_operations(intel_mcu_tty_driver, &intel_mcu_ops); ret = tty_register_driver(intel_mcu_tty_driver); if (ret) { dev_err(&pdev->dev, "fail to register tty driver\n"); goto tty_reg_fail; } base = (u8 *)mcu->ddr[1]; for (i = INTEL_MCU_TTY_MINORS - 1; i >= 0; i--) { data = kzalloc(sizeof(struct mcu_data), GFP_KERNEL); if (data == NULL) { dev_err(&pdev->dev, "fail to alloc mcu data\n"); goto data_alloc_fail; } data->index = i; tty_port_init(&data->port); data->dev = tty_port_register_device(&data->port, intel_mcu_tty_driver, i, &pdev->dev); mcu_table[i] = data; data->mcu = mcu; init_completion(&data->cmp); data->lbuf.addr = base; data->lbuf.length = BUF_IA_DDR_SIZE; lbuf_read_reset(&data->lbuf); base += BUF_IA_DDR_SIZE; } ret = sysfs_create_group(&pdev->dev.kobj, &intel_mcu_tty_attribute_group); if (ret) { pr_err("failed to create the mdbg sysfs attributes\n"); sysfs_remove_group(&pdev->dev.kobj, &intel_mcu_tty_attribute_group); goto data_alloc_fail; } intel_psh_ipc_bind(PSH_RECV_CH0, raw_data_handler, mcu_table[0]); intel_psh_ipc_bind(PSH_RECV_CH1, raw_data_handler, mcu_table[1]); intel_psh_ipc_bind(PSH_RECV_CH2, cmd_handler, mcu_table[2]); pr_info("MCU detected and ready to used!\n"); return 0; data_alloc_fail: for (i = 0; i < INTEL_MCU_TTY_MINORS; i++) kfree(mcu_table[i]); tty_reg_fail: put_tty_driver(intel_mcu_tty_driver); return ret; }