aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Hunter <jon-hunter@ti.com>2013-02-21 16:25:23 -0500
committerJon Hunter <jon-hunter@ti.com>2013-04-01 15:53:41 -0400
commitaa8d4767da2a2a29a628dc0dadb59a010f0ec18e (patch)
tree2cd2bc90120b1c914477a35e922e7678908b1268
parentc3be5b457ae1bb6dc93ef25bfa03e595969acbfc (diff)
ARM: OMAP2+: Add function for configuring 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 common function for configuring these options and various devices set these options by either programming the GPMC CONFIG1 register directly or by calling gpmc_cs_configure() to set some of the options. Add a new function for configuring all of the GPMC options. Having a common function for configuring this options will simplify code and ease the migration to device-tree. Also add a new capability flag to detect devices that support the address-address-data multiplexing mode. Signed-off-by: Jon Hunter <jon-hunter@ti.com> Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
-rw-r--r--arch/arm/mach-omap2/gpmc.c100
-rw-r--r--arch/arm/mach-omap2/gpmc.h6
2 files changed, 106 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 20747fbc686a..ee5d0e970c62 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -107,6 +107,7 @@
107 107
108#define GPMC_HAS_WR_ACCESS 0x1 108#define GPMC_HAS_WR_ACCESS 0x1
109#define GPMC_HAS_WR_DATA_MUX_BUS 0x2 109#define GPMC_HAS_WR_DATA_MUX_BUS 0x2
110#define GPMC_HAS_MUX_AAD 0x4
110 111
111#define GPMC_NR_WAITPINS 4 112#define GPMC_NR_WAITPINS 4
112 113
@@ -1126,6 +1127,90 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
1126 return 0; 1127 return 0;
1127} 1128}
1128 1129
1130/**
1131 * gpmc_cs_program_settings - programs non-timing related settings
1132 * @cs: GPMC chip-select to program
1133 * @p: pointer to GPMC settings structure
1134 *
1135 * Programs non-timing related settings for a GPMC chip-select, such as
1136 * bus-width, burst configuration, etc. Function should be called once
1137 * for each chip-select that is being used and must be called before
1138 * calling gpmc_cs_set_timings() as timing parameters in the CONFIG1
1139 * register will be initialised to zero by this function. Returns 0 on
1140 * success and appropriate negative error code on failure.
1141 */
1142int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
1143{
1144 u32 config1;
1145
1146 if ((!p->device_width) || (p->device_width > GPMC_DEVWIDTH_16BIT)) {
1147 pr_err("%s: invalid width %d!", __func__, p->device_width);
1148 return -EINVAL;
1149 }
1150
1151 /* Address-data multiplexing not supported for NAND devices */
1152 if (p->device_nand && p->mux_add_data) {
1153 pr_err("%s: invalid configuration!\n", __func__);
1154 return -EINVAL;
1155 }
1156
1157 if ((p->mux_add_data > GPMC_MUX_AD) ||
1158 ((p->mux_add_data == GPMC_MUX_AAD) &&
1159 !(gpmc_capability & GPMC_HAS_MUX_AAD))) {
1160 pr_err("%s: invalid multiplex configuration!\n", __func__);
1161 return -EINVAL;
1162 }
1163
1164 /* Page/burst mode supports lengths of 4, 8 and 16 bytes */
1165 if (p->burst_read || p->burst_write) {
1166 switch (p->burst_len) {
1167 case GPMC_BURST_4:
1168 case GPMC_BURST_8:
1169 case GPMC_BURST_16:
1170 break;
1171 default:
1172 pr_err("%s: invalid page/burst-length (%d)\n",
1173 __func__, p->burst_len);
1174 return -EINVAL;
1175 }
1176 }
1177
1178 if ((p->wait_on_read || p->wait_on_write) &&
1179 (p->wait_pin > gpmc_nr_waitpins)) {
1180 pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
1181 return -EINVAL;
1182 }
1183
1184 config1 = GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
1185
1186 if (p->sync_read)
1187 config1 |= GPMC_CONFIG1_READTYPE_SYNC;
1188 if (p->sync_write)
1189 config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
1190 if (p->wait_on_read)
1191 config1 |= GPMC_CONFIG1_WAIT_READ_MON;
1192 if (p->wait_on_write)
1193 config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
1194 if (p->wait_on_read || p->wait_on_write)
1195 config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
1196 if (p->device_nand)
1197 config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
1198 if (p->mux_add_data)
1199 config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
1200 if (p->burst_read)
1201 config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
1202 if (p->burst_write)
1203 config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
1204 if (p->burst_read || p->burst_write) {
1205 config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
1206 config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
1207 }
1208
1209 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1);
1210
1211 return 0;
1212}
1213
1129#ifdef CONFIG_OF 1214#ifdef CONFIG_OF
1130static struct of_device_id gpmc_dt_ids[] = { 1215static struct of_device_id gpmc_dt_ids[] = {
1131 { .compatible = "ti,omap2420-gpmc" }, 1216 { .compatible = "ti,omap2420-gpmc" },
@@ -1372,8 +1457,23 @@ static int gpmc_probe(struct platform_device *pdev)
1372 gpmc_dev = &pdev->dev; 1457 gpmc_dev = &pdev->dev;
1373 1458
1374 l = gpmc_read_reg(GPMC_REVISION); 1459 l = gpmc_read_reg(GPMC_REVISION);
1460
1461 /*
1462 * FIXME: Once device-tree migration is complete the below flags
1463 * should be populated based upon the device-tree compatible
1464 * string. For now just use the IP revision. OMAP3+ devices have
1465 * the wr_access and wr_data_mux_bus register fields. OMAP4+
1466 * devices support the addr-addr-data multiplex protocol.
1467 *
1468 * GPMC IP revisions:
1469 * - OMAP24xx = 2.0
1470 * - OMAP3xxx = 5.0
1471 * - OMAP44xx/54xx/AM335x = 6.0
1472 */
1375 if (GPMC_REVISION_MAJOR(l) > 0x4) 1473 if (GPMC_REVISION_MAJOR(l) > 0x4)
1376 gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS; 1474 gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS;
1475 if (GPMC_REVISION_MAJOR(l) > 0x5)
1476 gpmc_capability |= GPMC_HAS_MUX_AAD;
1377 dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l), 1477 dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
1378 GPMC_REVISION_MINOR(l)); 1478 GPMC_REVISION_MINOR(l));
1379 1479
diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
index 39e4e04acdc9..ce6ae218f41f 100644
--- a/arch/arm/mach-omap2/gpmc.h
+++ b/arch/arm/mach-omap2/gpmc.h
@@ -76,6 +76,11 @@
76#define GPMC_IRQ_FIFOEVENTENABLE 0x01 76#define GPMC_IRQ_FIFOEVENTENABLE 0x01
77#define GPMC_IRQ_COUNT_EVENT 0x02 77#define GPMC_IRQ_COUNT_EVENT 0x02
78 78
79#define GPMC_BURST_4 4 /* 4 word burst */
80#define GPMC_BURST_8 8 /* 8 word burst */
81#define GPMC_BURST_16 16 /* 16 word burst */
82#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */
83#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */
79#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */ 84#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */
80#define GPMC_MUX_AD 2 /* Addr-Data multiplex */ 85#define GPMC_MUX_AD 2 /* Addr-Data multiplex */
81 86
@@ -217,6 +222,7 @@ extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
217extern void gpmc_cs_write_reg(int cs, int idx, u32 val); 222extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
218extern int gpmc_calc_divider(unsigned int sync_clk); 223extern int gpmc_calc_divider(unsigned int sync_clk);
219extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t); 224extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
225extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p);
220extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base); 226extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
221extern void gpmc_cs_free(int cs); 227extern void gpmc_cs_free(int cs);
222extern void omap3_gpmc_save_context(void); 228extern void omap3_gpmc_save_context(void);