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