Esempio n. 1
0
static void pca_gmi_writebyte(void *pd, int reg, int val)
{
	struct tegra_nor_chip_parms *chip_parm = info->plat;
	struct cs_info *csinfo = &chip_parm->csinfo;
	unsigned int *ptr = csinfo->virt;
	struct gpio_state *state = &csinfo->gpio_cs;

	snor_tegra_writel(info, info->init_config, TEGRA_SNOR_CONFIG_REG);
	snor_tegra_writel(info, info->timing1_read, TEGRA_SNOR_TIMING1_REG);
	snor_tegra_writel(info, info->timing0_read, TEGRA_SNOR_TIMING0_REG);

	gpio_set_value(state[0].gpio_num, state[0].value);
	__raw_writeb(val, ptr + reg);
}
Esempio n. 2
0
static ssize_t gmichar_chrdev_write_helper(unsigned int *dest, char *src,
						size_t size)
{
	int i;

	snor_tegra_writel(info, info->init_config, TEGRA_SNOR_CONFIG_REG);
	snor_tegra_writel(info, info->timing1_read, TEGRA_SNOR_TIMING1_REG);
	snor_tegra_writel(info, info->timing0_read, TEGRA_SNOR_TIMING0_REG);

	udelay(1);

	for (i = 0; i < size; i++)
		__raw_writeb(src[i], dest + i);

	udelay(1);
	return size;

}
Esempio n. 3
0
static ssize_t gmichar_chrdev_read_helper(char *dest, int *src,
						size_t size)
{
	int i;

	snor_tegra_writel(info, info->init_config, TEGRA_SNOR_CONFIG_REG);
	snor_tegra_writel(info, info->timing1_read, TEGRA_SNOR_TIMING1_REG);
	snor_tegra_writel(info, info->timing0_read, TEGRA_SNOR_TIMING0_REG);

	udelay(1);

	for (i = 0; i < size; i++)
		dest[i] = __raw_readb(src + i);

	udelay(1);

	return size;
}
Esempio n. 4
0
static int __init tegra_gmi_char_probe(struct platform_device *pdev)
{
	int err = -ENODEV;
	struct tegra_nor_chip_parms *plat = pdev->dev.platform_data;
	struct device *dev = &pdev->dev;

	if (!plat) {
		pr_err("%s: no platform device info\n", __func__);
		return -EINVAL;
	}
	info = devm_kzalloc(dev, sizeof(struct tegra_gmi_char_info),
			    GFP_KERNEL);
	if (!info)
		return -ENOMEM;
	info->base = ((void __iomem *)IO_APB_VIRT +
				(TEGRA_SNOR_BASE - IO_APB_PHYS));
	info->plat = plat;
	info->dev = dev;

#ifdef CONFIG_TEGRA_GMI_ACCESS_CONTROL
	info->gmiLockHandle = register_gmi_device(DRV_NAME, 0);
	info->request_gmi_access = request_gmi_access;
	info->release_gmi_access = release_gmi_access;
	info->gmiLockHandle =	register_gmi_device(DRV_NAME, 0);
#else
	info->gmiLockHandle = NULL;
	info->request_gmi_access = NULL;
	info->release_gmi_access = NULL;
#endif

	/* Clock setting */
	info->clk = clk_get_sys("tegra-nor", NULL);
	if (IS_ERR(info->clk)) {
		pr_err("%s: can't get clock\n", __func__);
		return PTR_ERR(info->clk);
	}

	err = clk_prepare_enable(info->clk);
	if (err != 0) {
		pr_err("%s: can't enable clock\n", __func__);
		return err;
	}

	err = tegra_gmi_char_prepare_regs(info);

	if (err) {
		dev_err(dev, "Error initializing reg values\n");
		return err;
	}

	// write init config
	snor_tegra_writel(info, info->init_config, TEGRA_SNOR_CONFIG_REG);
	snor_tegra_writel(info, info->timing1_read, TEGRA_SNOR_TIMING1_REG);
	snor_tegra_writel(info, info->timing0_read, TEGRA_SNOR_TIMING0_REG);

	platform_set_drvdata(pdev, info);

	info->gmi_class = class_create(THIS_MODULE, DRV_NAME);

	if (IS_ERR(info->gmi_class)) {
		err = PTR_ERR(info->gmi_class);
		return err;
	}

	err = alloc_chrdev_region(&info->gmi_dev_t, 0, 1, DRV_NAME);

	if (err < 0) {
		class_destroy(info->gmi_class);
		pr_err("%s: failed to allocate device region\n", DRV_NAME);
		return err;
	}

	cdev_init(&info->gmi_cdev, &gmichar_fops);
	err = cdev_add(&info->gmi_cdev, info->gmi_dev_t, 1);

	if (err)
		return err;

	info->gmi_device = device_create(info->gmi_class, NULL,
					info->gmi_dev_t, info, DRV_NAME);

	if (IS_ERR(info->gmi_device)) {
		pr_err("device create failed for %s\n", DRV_NAME);
		cdev_del(&info->gmi_cdev);
		goto fail;
	}

	return 0;
fail:
	pr_err("Tegra GMI CHAR probe failed\n");
	return err;
}
Esempio n. 5
0
static void tegra_flash_dma(struct map_info *map,
			    void *to, unsigned long from, ssize_t len)
{
	u32 snor_config, dma_config = 0;
	int dma_transfer_count = 0, word32_count = 0;
	u32 nor_address, current_transfer = 0;
	u32 copy_to = (u32)to;
	struct tegra_nor_info *c =
	    container_of(map, struct tegra_nor_info, map);
	struct tegra_nor_chip_parms *chip_parm = &c->plat->chip_parms;
	unsigned int bytes_remaining = len;

	snor_config = c->init_config;
	snor_tegra_writel(c, c->timing0_read, TEGRA_SNOR_TIMING0_REG);
	snor_tegra_writel(c, c->timing1_read, TEGRA_SNOR_TIMING1_REG);

	if (len > 32) {
		word32_count = len >> 2;
		bytes_remaining = len & 0x00000003;
		/*
		 * The parameters can be setup in any order since we write to
		 * controller register only after all parameters are set.
		 */
		/* SNOR CONFIGURATION SETUP */
		switch(chip_parm->ReadMode)
		{
			case NorReadMode_Async:
				snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(0);
				break;

			case NorReadMode_Page:
				switch(chip_parm->PageLength)
				{
					case NorPageLength_Unsupported :
						snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(0);
						break;

					case NorPageLength_4Word :
						snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(1);
						snor_config |= TEGRA_SNOR_CONFIG_PAGE_SZ(1);
						break;

					case NorPageLength_8Word :
						snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(1);
						snor_config |= TEGRA_SNOR_CONFIG_PAGE_SZ(2);
						break;
				}
				break;

			case NorReadMode_Burst:
				snor_config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(2);
				switch(chip_parm->BurstLength)
				{
					case NorBurstLength_CntBurst :
						snor_config |= TEGRA_SNOR_CONFIG_BURST_LEN(0);
						break;
					case NorBurstLength_8Word :
						snor_config |= TEGRA_SNOR_CONFIG_BURST_LEN(1);
						break;

					case NorBurstLength_16Word :
						snor_config |= TEGRA_SNOR_CONFIG_BURST_LEN(2);
						break;

					case NorBurstLength_32Word :
						snor_config |= TEGRA_SNOR_CONFIG_BURST_LEN(3);
						break;
				}
				break;
		}
		snor_config |= TEGRA_SNOR_CONFIG_MST_ENB;
		/* SNOR DMA CONFIGURATION SETUP */
		/* NOR -> AHB */
		dma_config &= ~TEGRA_SNOR_DMA_CFG_DIR;
		/* One word burst */
		dma_config |= TEGRA_SNOR_DMA_CFG_BRST_SZ(4);

		for (nor_address = (unsigned int)(map->phys + from);
		     word32_count > 0;
		     word32_count -= current_transfer,
		     dma_transfer_count += current_transfer,
		     nor_address += (current_transfer * 4),
		     copy_to += (current_transfer * 4)) {

			current_transfer =
			    (word32_count > TEGRA_SNOR_DMA_LIMIT_WORDS)
			    ? (TEGRA_SNOR_DMA_LIMIT_WORDS) : word32_count;
			/* Start NOR operation */
			snor_config |= TEGRA_SNOR_CONFIG_GO;
			dma_config |= TEGRA_SNOR_DMA_CFG_GO;
			/* Enable interrupt before every transaction since the
			 * interrupt handler disables it */
			dma_config |= TEGRA_SNOR_DMA_CFG_INT_ENB;
			/* Num of AHB (32-bit) words to transferred minus 1 */
			dma_config |=
			    TEGRA_SNOR_DMA_CFG_WRD_CNT(current_transfer - 1);
			snor_tegra_writel(c, c->dma_phys_buffer,
					  TEGRA_SNOR_AHB_ADDR_PTR_REG);
			snor_tegra_writel(c, nor_address,
					  TEGRA_SNOR_NOR_ADDR_PTR_REG);
			snor_tegra_writel(c, snor_config,
					  TEGRA_SNOR_CONFIG_REG);
			snor_tegra_writel(c, dma_config,
					  TEGRA_SNOR_DMA_CFG_REG);
			if (wait_for_dma_completion(c)) {
				dev_err(c->dev, "timout waiting for DMA\n");
				/* Transfer the remaining words by memcpy */
				bytes_remaining += (word32_count << 2);
				break;
			}
			dma_sync_single_for_cpu(c->dev, c->dma_phys_buffer,
				(current_transfer << 2), DMA_FROM_DEVICE);
			memcpy((char *)(copy_to), (char *)(c->dma_virt_buffer),
				(current_transfer << 2));

		}
	}