1
0
Fork 0

ARM: OMAP2+: Add structure for storing GPMC settings

The GPMC has various different configuration options such as bus-width,
synchronous or asychronous mode selection, burst mode options etc.
Currently, there is no central structure for storing all these options
when configuring the GPMC for a given device. Some of the options are
stored in the GPMC timing structure and some are directly programmed
into the GPMC configuration register. Add a new structure to store
these options and convert code to use this structure. Adding this
structure will allow us to create a common function for configuring
these options.

Signed-off-by: Jon Hunter <jon-hunter@ti.com>
Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
hifive-unleashed-5.1
Jon Hunter 2013-02-21 13:46:22 -06:00
parent 9f8331562a
commit c3be5b457a
5 changed files with 72 additions and 40 deletions

View File

@ -47,6 +47,15 @@ static struct platform_device gpmc_onenand_device = {
.resource = &gpmc_onenand_resource,
};
static struct gpmc_settings onenand_async = {
.mux_add_data = GPMC_MUX_AD,
};
static struct gpmc_settings onenand_sync = {
.burst_read = true,
.mux_add_data = GPMC_MUX_AD,
};
static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
{
struct gpmc_device_timings dev_t;
@ -63,7 +72,6 @@ static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
memset(&dev_t, 0, sizeof(dev_t));
dev_t.mux = true;
dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;
dev_t.t_avdp_w = dev_t.t_avdp_r;
dev_t.t_aavdh = t_aavdh * 1000;
@ -75,7 +83,7 @@ static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
dev_t.t_wpl = t_wpl * 1000;
dev_t.t_wph = t_wph * 1000;
gpmc_calc_timings(t, &dev_t);
gpmc_calc_timings(t, &onenand_async, &dev_t);
}
static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
@ -235,10 +243,8 @@ static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
/* Set synchronous read timings */
memset(&dev_t, 0, sizeof(dev_t));
dev_t.mux = true;
dev_t.sync_read = true;
if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
dev_t.sync_write = true;
onenand_sync.sync_write = true;
} else {
dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
dev_t.t_wpl = t_wpl * 1000;
@ -261,7 +267,7 @@ static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
dev_t.cyc_aavdh_oe = 1;
dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period;
gpmc_calc_timings(t, &dev_t);
gpmc_calc_timings(t, &onenand_sync, &dev_t);
}
static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)

View File

@ -104,7 +104,7 @@ static int smc91c96_gpmc_retime(void)
dev_t.t_cez_w = t4_w * 1000;
dev_t.t_wr_cycle = (t20 - t3) * 1000;
gpmc_calc_timings(&t, &dev_t);
gpmc_calc_timings(&t, NULL, &dev_t);
return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
}

View File

@ -817,9 +817,9 @@ static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
/* XXX: can the cycles be avoided ? */
static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
struct gpmc_device_timings *dev_t)
struct gpmc_device_timings *dev_t,
bool mux)
{
bool mux = dev_t->mux;
u32 temp;
/* adv_rd_off */
@ -872,9 +872,9 @@ static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
}
static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
struct gpmc_device_timings *dev_t)
struct gpmc_device_timings *dev_t,
bool mux)
{
bool mux = dev_t->mux;
u32 temp;
/* adv_wr_off */
@ -934,9 +934,9 @@ static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
}
static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
struct gpmc_device_timings *dev_t)
struct gpmc_device_timings *dev_t,
bool mux)
{
bool mux = dev_t->mux;
u32 temp;
/* adv_rd_off */
@ -974,9 +974,9 @@ static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
}
static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t,
struct gpmc_device_timings *dev_t)
struct gpmc_device_timings *dev_t,
bool mux)
{
bool mux = dev_t->mux;
u32 temp;
/* adv_wr_off */
@ -1046,7 +1046,8 @@ static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t,
}
static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
struct gpmc_device_timings *dev_t)
struct gpmc_device_timings *dev_t,
bool sync)
{
u32 temp;
@ -1060,7 +1061,7 @@ static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
gpmc_t->cs_on + dev_t->t_ce_avd);
gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp);
if (dev_t->sync_write || dev_t->sync_read)
if (sync)
gpmc_calc_sync_common_timings(gpmc_t, dev_t);
return 0;
@ -1095,21 +1096,29 @@ static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
}
int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
struct gpmc_device_timings *dev_t)
struct gpmc_settings *gpmc_s,
struct gpmc_device_timings *dev_t)
{
bool mux = false, sync = false;
if (gpmc_s) {
mux = gpmc_s->mux_add_data ? true : false;
sync = (gpmc_s->sync_read || gpmc_s->sync_write);
}
memset(gpmc_t, 0, sizeof(*gpmc_t));
gpmc_calc_common_timings(gpmc_t, dev_t);
gpmc_calc_common_timings(gpmc_t, dev_t, sync);
if (dev_t->sync_read)
gpmc_calc_sync_read_timings(gpmc_t, dev_t);
if (gpmc_s && gpmc_s->sync_read)
gpmc_calc_sync_read_timings(gpmc_t, dev_t, mux);
else
gpmc_calc_async_read_timings(gpmc_t, dev_t);
gpmc_calc_async_read_timings(gpmc_t, dev_t, mux);
if (dev_t->sync_write)
gpmc_calc_sync_write_timings(gpmc_t, dev_t);
if (gpmc_s && gpmc_s->sync_write)
gpmc_calc_sync_write_timings(gpmc_t, dev_t, mux);
else
gpmc_calc_async_write_timings(gpmc_t, dev_t);
gpmc_calc_async_write_timings(gpmc_t, dev_t, mux);
/* TODO: remove, see function definition */
gpmc_convert_ps_to_ns(gpmc_t);

View File

@ -60,8 +60,8 @@
#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
#define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8)
#define GPMC_CONFIG1_MUXNONMUX GPMC_CONFIG1_MUXTYPE(0)
#define GPMC_CONFIG1_MUXAAD GPMC_CONFIG1_MUXTYPE(1)
#define GPMC_CONFIG1_MUXADDDATA GPMC_CONFIG1_MUXTYPE(2)
#define GPMC_CONFIG1_MUXAAD GPMC_CONFIG1_MUXTYPE(GPMC_MUX_AAD)
#define GPMC_CONFIG1_MUXADDDATA GPMC_CONFIG1_MUXTYPE(GPMC_MUX_AD)
#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
#define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1))
@ -76,6 +76,8 @@
#define GPMC_IRQ_FIFOEVENTENABLE 0x01
#define GPMC_IRQ_COUNT_EVENT 0x02
#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */
#define GPMC_MUX_AD 2 /* Addr-Data multiplex */
/* bool type time settings */
struct gpmc_bool_timings {
@ -181,10 +183,6 @@ struct gpmc_device_timings {
u8 cyc_wpl; /* write deassertion time in cycles */
u32 cyc_iaa; /* initial access time in cycles */
bool mux; /* address & data muxed */
bool sync_write;/* synchronous write */
bool sync_read; /* synchronous read */
/* extra delays */
bool ce_xdelay;
bool avd_xdelay;
@ -192,8 +190,24 @@ struct gpmc_device_timings {
bool we_xdelay;
};
struct gpmc_settings {
bool burst_wrap; /* enables wrap bursting */
bool burst_read; /* enables read page/burst mode */
bool burst_write; /* enables write page/burst mode */
bool device_nand; /* device is NAND */
bool sync_read; /* enables synchronous reads */
bool sync_write; /* enables synchronous writes */
bool wait_on_read; /* monitor wait on reads */
bool wait_on_write; /* monitor wait on writes */
u32 burst_len; /* page/burst length */
u32 device_width; /* device bus width (8 or 16 bit) */
u32 mux_add_data; /* multiplex address & data */
u32 wait_pin; /* wait-pin to be used */
};
extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
struct gpmc_device_timings *dev_t);
struct gpmc_settings *gpmc_s,
struct gpmc_device_timings *dev_t);
extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
extern int gpmc_get_client_irq(unsigned irq_config);

View File

@ -26,6 +26,15 @@
static u8 async_cs, sync_cs;
static unsigned refclk_psec;
static struct gpmc_settings tusb_async = {
.mux_add_data = GPMC_MUX_AD,
};
static struct gpmc_settings tusb_sync = {
.sync_read = true,
.sync_write = true,
.mux_add_data = GPMC_MUX_AD,
};
/* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
@ -37,8 +46,6 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
memset(&dev_t, 0, sizeof(dev_t));
dev_t.mux = true;
dev_t.t_ceasu = 8 * 1000;
dev_t.t_avdasu = t_acsnh_advnh - 7000;
dev_t.t_ce_avd = 1000;
@ -52,7 +59,7 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
dev_t.t_wpl = 300;
dev_t.cyc_aavdh_we = 1;
gpmc_calc_timings(&t, &dev_t);
gpmc_calc_timings(&t, &tusb_async, &dev_t);
return gpmc_cs_set_timings(async_cs, &t);
}
@ -65,10 +72,6 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
memset(&dev_t, 0, sizeof(dev_t));
dev_t.mux = true;
dev_t.sync_read = true;
dev_t.sync_write = true;
dev_t.clk = 11100;
dev_t.t_bacc = 1000;
dev_t.t_ces = 1000;
@ -84,7 +87,7 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
dev_t.cyc_wpl = 6;
dev_t.t_ce_rdyz = 7000;
gpmc_calc_timings(&t, &dev_t);
gpmc_calc_timings(&t, &tusb_sync, &dev_t);
return gpmc_cs_set_timings(sync_cs, &t);
}