|  | @@ -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();
 | 
	
		
			
				|  |  | +
 |