| 
					
				 | 
			
			
				@@ -84,3 +84,134 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define GPMC_CS0_OFFSET		0x60 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define GPMC_CS_SIZE		0x30 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define	GPMC_BCH_SIZE		0x10 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define GPMC_MEM_START		0x00000000 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define GPMC_MEM_END		0x3FFFFFFF 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define BOOT_ROM_SPACE		0x100000	/* 1MB */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define GPMC_CHUNK_SHIFT	24		/* 16 MB */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define GPMC_SECTION_SHIFT	28		/* 128 MB */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define CS_NUM_SHIFT		24 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define ENABLE_PREFETCH		(0x1 << 7) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define DMA_MPU_MODE		2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define	GPMC_REVISION_MAJOR(l)		((l >> 4) & 0xf) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define	GPMC_REVISION_MINOR(l)		(l & 0xf) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define	GPMC_HAS_WR_ACCESS		0x1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define	GPMC_HAS_WR_DATA_MUX_BUS	0x2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* XXX: Only NAND irq has been considered,currently these are the only ones used 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define	GPMC_NR_IRQ		2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct gpmc_client_irq	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned		irq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32			bitmask; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* Structure to save gpmc cs context */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct gpmc_cs_config { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 config1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 config2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 config3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 config4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 config5; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 config6; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 config7; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int is_valid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Structure to save/restore gpmc context 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * to support core off on OMAP3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct omap3_gpmc_regs { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 sysconfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 irqenable; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 timeout_ctrl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 config; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 prefetch_config1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 prefetch_config2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 prefetch_control; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct gpmc_cs_config cs_context[GPMC_CS_NUM]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct irq_chip gpmc_irq_chip; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static unsigned gpmc_irq_start; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct resource	gpmc_mem_root; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct resource	gpmc_cs_mem[GPMC_CS_NUM]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static DEFINE_SPINLOCK(gpmc_mem_lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct device *gpmc_dev; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int gpmc_irq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static resource_size_t phys_base, mem_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static unsigned gpmc_capability; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void __iomem *gpmc_base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct clk *gpmc_l3_clk; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static irqreturn_t gpmc_handle_irq(int irq, void *dev); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void gpmc_write_reg(int idx, u32 val) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	__raw_writel(val, gpmc_base + idx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static u32 gpmc_read_reg(int idx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return __raw_readl(gpmc_base + idx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void gpmc_cs_write_reg(int cs, int idx, u32 val) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	void __iomem *reg_addr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	__raw_writel(val, reg_addr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+u32 gpmc_cs_read_reg(int cs, int idx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	void __iomem *reg_addr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return __raw_readl(reg_addr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* TODO: Add support for gpmc_fck to clock framework and use it */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+unsigned long gpmc_get_fclk_period(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long rate = clk_get_rate(gpmc_l3_clk); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (rate == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		printk(KERN_WARNING "gpmc_l3_clk not enabled\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	rate /= 1000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	rate = 1000000000 / rate;	/* In picoseconds */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return rate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+unsigned int gpmc_ns_to_ticks(unsigned int time_ns) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long tick_ps; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Calculate in picosecs to yield more exact results */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	tick_ps = gpmc_get_fclk_period(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return (time_ns * 1000 + tick_ps - 1) / tick_ps; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+unsigned int gpmc_ps_to_ticks(unsigned int time_ps) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long tick_ps; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Calculate in picosecs to yield more exact results */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	tick_ps = gpmc_get_fclk_period(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 |