Esempio n. 1
0
static int tegra_gmi_char_prepare_regs(struct tegra_gmi_char_info *info)
{
	struct tegra_nor_chip_parms *chip_parm = info->plat;
	struct cs_info *csinfo = &chip_parm->csinfo;

	u32 width = chip_parm->BusWidth;
	u32 config = 0;

	config |= TEGRA_SNOR_CONFIG_DEVICE_MODE(0);
	config |= TEGRA_SNOR_CONFIG_SNOR_CS(csinfo->cs);
	config &= ~TEGRA_SNOR_CONFIG_DEVICE_TYPE;
	config |= TEGRA_SNOR_CONFIG_WP;	/* Enable writes */

	switch (width) {
	case 2:
		config &= ~TEGRA_SNOR_CONFIG_WORDWIDE;	/* 16 bit */
		break;
	case 4:
		config |= TEGRA_SNOR_CONFIG_WORDWIDE;	/* 32 bit */
		break;
	default:
		return -EINVAL;
	}

	switch (chip_parm->MuxMode) {
	case NorMuxMode_ADNonMux:
		config &= ~TEGRA_SNOR_CONFIG_MUX_MODE;
		break;
	case NorMuxMode_ADMux:
		config |= TEGRA_SNOR_CONFIG_MUX_MODE;
		break;
	default:
		return -EINVAL;
	}

	switch (chip_parm->ReadyActive) {
	case NorReadyActive_WithData:
		config &= ~TEGRA_SNOR_CONFIG_RDY_ACTIVE;
		break;
	case NorReadyActive_BeforeData:
		config |= TEGRA_SNOR_CONFIG_RDY_ACTIVE;
		break;
	default:
		return -EINVAL;
	}

	info->init_config = config;
	info->timing0_default = chip_parm->timing_default.timing0;
	info->timing0_read = chip_parm->timing_read.timing0;
	info->timing1_default = chip_parm->timing_default.timing1;
	info->timing1_read = chip_parm->timing_read.timing1;

	return 0;
}
Esempio n. 2
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));

		}
	}