static int emi_hibernation(int resuming) { int idx; int bank, data; static struct emi_pm *emi_saved_data; if (resuming) { if (emi_saved_data) { /* restore the previous common value */ for (idx = 0; idx < emi_num_common_cfg-4; ++idx) writel(emi_saved_data->common_cfg[idx], emi_control+EMI_COMMON_CFG(idx)); writel(emi_saved_data->common_cfg[12], emi_control + EMI_BANK_ENABLE); writel(emi_saved_data->common_cfg[13], emi_control + EMI_BANKNUMBER); writel(emi_saved_data->common_cfg[14], emiss_config + EMISS_CONFIG); writel(emi_saved_data->common_cfg[15], emiss_config + EMISS_ARBITER_CONFIG); /* restore the previous bank values */ for (bank = 0; bank < emi_num_bank; ++bank) { writel(emi_saved_data->bank[bank].base_address, emi_control + BANK_BASEADDRESS(bank)); for (data = 0; data < emi_num_bank_cfg; ++data) emi_bank_configure(bank, emi_saved_data->bank[bank].cfg); } kfree(emi_saved_data); emi_saved_data = NULL; } return 0; } emi_saved_data = kmalloc(sizeof(struct emi_pm), GFP_NOWAIT); if (!emi_saved_data) { printk(KERN_ERR "Unable to freeze the emi registers\n"); return -ENOMEM; } /* save the emi common values */ for (idx = 0; idx < emi_num_common_cfg-4; ++idx) emi_saved_data->common_cfg[idx] = readl(emi_control + EMI_COMMON_CFG(idx)); emi_saved_data->common_cfg[12] = readl(emi_control + EMI_BANK_ENABLE); emi_saved_data->common_cfg[13] = readl(emi_control + EMI_BANKNUMBER); emi_saved_data->common_cfg[14] = readl(emiss_config + EMISS_CONFIG); emi_saved_data->common_cfg[15] = readl(emiss_config + EMISS_ARBITER_CONFIG); /* save the emi bank value */ for (bank = 0; bank < emi_num_bank; ++bank) { emi_saved_data->bank[bank].base_address = readl(emi_control + BANK_BASEADDRESS(bank)); for (data = 0; data < emi_num_bank_cfg; ++data) emi_saved_data->bank[bank].cfg[data] = readl(emi_control + BANK_EMICONFIGDATA(bank, data)); } return 0; }
/* Configure EMI Bank for NAND access */ static int nand_config_emi(int bank, struct nand_timing_data *td) { uint32_t emi_clk; uint32_t emi_t_ns; uint32_t emi_p_ns; unsigned long config[4]; uint32_t rd_cycle, wr_cycle; uint32_t iord_start, iord_end; uint32_t iowr_start, iowr_end; uint32_t rd_latch; uint32_t bus_release; uint32_t wait_active_low; printk(KERN_INFO NAME ": Configuring EMI Bank %d for NAND access\n", bank); if (!td) { printk(KERN_ERR NAME "No timing data specified in platform " "data\n"); return 1; } /* Timings set in number of clock cycles */ emi_clk = clk_get_rate(clk_get(NULL, "emi_master")); emi_t_ns = 1000000000UL / emi_clk; emi_p_ns = emi_t_ns / 2; /* Convert nand timings to EMI compatible values */ rd_cycle = GET_CLK_CYCLES(td->rd_on + td->rd_off, emi_t_ns); iord_start = 0; iord_end = GET_CLK_CYCLES(td->rd_on, emi_p_ns); rd_latch = GET_CLK_CYCLES(td->rd_on, emi_t_ns); bus_release = GET_CLK_CYCLES(10, emi_t_ns); wait_active_low = 0; wr_cycle = GET_CLK_CYCLES(td->wr_on + td->wr_off, emi_t_ns); iowr_start = 0; iowr_end = GET_CLK_CYCLES(td->wr_on, emi_p_ns); /* Set up EMI configuration data */ config[0] = 0x04000699 | ((bus_release & 0xf) << 11) | ((rd_latch & 0x1f) << 20) | ((wait_active_low & 0x1) << 25); config[1] = ((rd_cycle & 0x7f) << 24) | ((iord_start & 0xf) << 12) | ((iord_end & 0xf) << 8); config[2] = ((wr_cycle & 0x7f) << 24) | ((iowr_start & 0xf) << 12) | ((iowr_end & 0xf) << 8); config[3] = 0x00; /* Configure Bank */ emi_bank_configure(bank, config); /* Disable PC mode */ emi_config_pcmode(bank, 0); return 0; }