/** * gpmi_set_timings - set GPMI timings * @pdev: pointer to GPMI platform device * @tm: pointer to structure &gpmi_nand_timing with new timings * * During initialization, GPMI uses safe sub-optimal timings, which * can be changed after reading boot control blocks */ void gpmi_set_timings(struct lba_data *data, struct gpmi_nand_timing *tm) { u32 period_ns = 1000000 / clk_get_rate(data->clk) + 1; u32 address_cycles, data_setup_cycles; u32 data_hold_cycles, data_sample_cycles; u32 busy_timeout; u32 t0; address_cycles = gpmi_cycles_ceil(tm->address_setup, period_ns); data_setup_cycles = gpmi_cycles_ceil(tm->data_setup, period_ns); data_hold_cycles = gpmi_cycles_ceil(tm->data_hold, period_ns); data_sample_cycles = gpmi_cycles_ceil(tm->dsample_time + period_ns / 4, period_ns / 2); busy_timeout = gpmi_cycles_ceil(10000000 / 4096, period_ns); t0 = BF_GPMI_TIMING0_ADDRESS_SETUP(address_cycles) | BF_GPMI_TIMING0_DATA_SETUP(data_setup_cycles) | BF_GPMI_TIMING0_DATA_HOLD(data_hold_cycles); HW_GPMI_TIMING0_WR(t0); HW_GPMI_TIMING1_WR(BF_GPMI_TIMING1_DEVICE_BUSY_TIMEOUT(busy_timeout)); #ifdef CONFIG_ARCH_STMP378X HW_GPMI_CTRL1_CLR(BM_GPMI_CTRL1_RDN_DELAY); HW_GPMI_CTRL1_SET(BF_GPMI_CTRL1_RDN_DELAY(data_sample_cycles)); #else HW_GPMI_CTRL1_CLR(BM_GPMI_CTRL1_DSAMPLE_TIME); HW_GPMI_CTRL1_SET(BF_GPMI_CTRL1_DSAMPLE_TIME(data_sample_cycles)); #endif }
void queue_plug(struct lba_data *data) { clk_enable(data->clk); if (clk <= 0) clk = 24000; /* safe setting, some chips do not work on speeds >= 24kHz */ clk_set_rate(data->clk, clk); clk = clk_get_rate(data->clk); stmp3xxx_reset_block(HW_GPMI_CTRL0_OFFSET + REGS_GPMI_BASE, 1); /* write protection OFF */ HW_GPMI_CTRL1_SET(BM_GPMI_CTRL1_DEV_RESET); /* IRQ polarity */ HW_GPMI_CTRL1_SET(BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY); /* ...and ECC module */ /*HW_GPMI_CTRL1_SET(bch_mode());*/ /* choose NAND mode (1 means ATA, 0 - NAND */ HW_GPMI_CTRL1_CLR(BM_GPMI_CTRL1_GPMI_MODE); gpmi_set_timings(data, &gpmi_safe_timing); }
void gpmi_enable_writes(bool bClearOrSet) { if (bClearOrSet) { HW_GPMI_CTRL1_SET(BM_GPMI_CTRL1_DEV_RESET); } else { HW_GPMI_CTRL1_CLR(BM_GPMI_CTRL1_DEV_RESET); } }
/** * gpmi_irq - IRQ handler * * @irq: irq no * @context: IRQ context, pointer to gpmi_nand_data */ static irqreturn_t gpmi_irq(int irq, void *context) { struct lba_data *data = context; int i; for (i = 0; i < max_chips; i++) { if (stmp3xxx_dma_is_interrupt(data->nand[i].dma_ch)) { stmp3xxx_dma_clear_interrupt(data->nand[i].dma_ch); complete(&data->nand[i].done); } } HW_GPMI_CTRL1_CLR(BM_GPMI_CTRL1_DEV_IRQ | BM_GPMI_CTRL1_TIMEOUT_IRQ); return IRQ_HANDLED; }