예제 #1
0
파일: psh.c 프로젝트: wejgomi/nexus-player
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;
}
예제 #2
0
/* 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;
}