Esempio n. 1
0
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;
}