summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/bus/ti-gpmc.txt8
-rw-r--r--drivers/memory/omap-gpmc.c246
-rw-r--r--include/linux/omap-gpmc.h5
3 files changed, 144 insertions, 115 deletions
diff --git a/Documentation/devicetree/bindings/bus/ti-gpmc.txt b/Documentation/devicetree/bindings/bus/ti-gpmc.txt
index 01683707060b..13f13786f992 100644
--- a/Documentation/devicetree/bindings/bus/ti-gpmc.txt
+++ b/Documentation/devicetree/bindings/bus/ti-gpmc.txt
@@ -32,6 +32,12 @@ Required properties:
32 bootloader) are used for the physical address decoding. 32 bootloader) are used for the physical address decoding.
33 As this will change in the future, filling correct 33 As this will change in the future, filling correct
34 values here is a requirement. 34 values here is a requirement.
35 - interrupt-controller: The GPMC driver implements and interrupt controller for
36 the NAND events "fifoevent" and "termcount".
37 The interrupt number mapping is as follows
38 0 - NAND_fifoevent
39 1 - NAND_termcount
40 - interrupt-cells: Must be set to 2
35 41
36Timing properties for child nodes. All are optional and default to 0. 42Timing properties for child nodes. All are optional and default to 0.
37 43
@@ -130,6 +136,8 @@ Example for an AM33xx board:
130 #address-cells = <2>; 136 #address-cells = <2>;
131 #size-cells = <1>; 137 #size-cells = <1>;
132 ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */ 138 ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
139 interrupt-controller;
140 #interrupt-cells = <2>;
133 141
134 /* child nodes go here */ 142 /* child nodes go here */
135 }; 143 };
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 90dfba5a8f55..e28d6bc2500a 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -22,6 +22,7 @@
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/interrupt.h> 24#include <linux/interrupt.h>
25#include <linux/irqdomain.h>
25#include <linux/platform_device.h> 26#include <linux/platform_device.h>
26#include <linux/of.h> 27#include <linux/of.h>
27#include <linux/of_address.h> 28#include <linux/of_address.h>
@@ -127,7 +128,6 @@
127#define GPMC_CONFIG_RDY_BSY 0x00000001 128#define GPMC_CONFIG_RDY_BSY 0x00000001
128#define GPMC_CONFIG_DEV_SIZE 0x00000002 129#define GPMC_CONFIG_DEV_SIZE 0x00000002
129#define GPMC_CONFIG_DEV_TYPE 0x00000003 130#define GPMC_CONFIG_DEV_TYPE 0x00000003
130#define GPMC_SET_IRQ_STATUS 0x00000004
131 131
132#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) 132#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
133#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) 133#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
@@ -176,8 +176,6 @@
176#define GPMC_CONFIG_WRITEPROTECT 0x00000010 176#define GPMC_CONFIG_WRITEPROTECT 0x00000010
177#define WR_RD_PIN_MONITORING 0x00600000 177#define WR_RD_PIN_MONITORING 0x00600000
178 178
179#define GPMC_ENABLE_IRQ 0x0000000d
180
181/* ECC commands */ 179/* ECC commands */
182#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ 180#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */
183#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ 181#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */
@@ -201,11 +199,6 @@ struct gpmc_cs_data {
201 struct resource mem; 199 struct resource mem;
202}; 200};
203 201
204struct gpmc_client_irq {
205 unsigned irq;
206 u32 bitmask;
207};
208
209/* Structure to save gpmc cs context */ 202/* Structure to save gpmc cs context */
210struct gpmc_cs_config { 203struct gpmc_cs_config {
211 u32 config1; 204 u32 config1;
@@ -233,9 +226,13 @@ struct omap3_gpmc_regs {
233 struct gpmc_cs_config cs_context[GPMC_CS_NUM]; 226 struct gpmc_cs_config cs_context[GPMC_CS_NUM];
234}; 227};
235 228
236static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; 229struct gpmc_device {
237static struct irq_chip gpmc_irq_chip; 230 struct device *dev;
238static int gpmc_irq_start; 231 int irq;
232 struct irq_chip irq_chip;
233};
234
235static struct irq_domain *gpmc_irq_domain;
239 236
240static struct resource gpmc_mem_root; 237static struct resource gpmc_mem_root;
241static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM]; 238static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM];
@@ -243,8 +240,6 @@ static DEFINE_SPINLOCK(gpmc_mem_lock);
243/* Define chip-selects as reserved by default until probe completes */ 240/* Define chip-selects as reserved by default until probe completes */
244static unsigned int gpmc_cs_num = GPMC_CS_NUM; 241static unsigned int gpmc_cs_num = GPMC_CS_NUM;
245static unsigned int gpmc_nr_waitpins; 242static unsigned int gpmc_nr_waitpins;
246static struct device *gpmc_dev;
247static int gpmc_irq;
248static resource_size_t phys_base, mem_size; 243static resource_size_t phys_base, mem_size;
249static unsigned gpmc_capability; 244static unsigned gpmc_capability;
250static void __iomem *gpmc_base; 245static void __iomem *gpmc_base;
@@ -1056,14 +1051,6 @@ int gpmc_configure(int cmd, int wval)
1056 u32 regval; 1051 u32 regval;
1057 1052
1058 switch (cmd) { 1053 switch (cmd) {
1059 case GPMC_ENABLE_IRQ:
1060 gpmc_write_reg(GPMC_IRQENABLE, wval);
1061 break;
1062
1063 case GPMC_SET_IRQ_STATUS:
1064 gpmc_write_reg(GPMC_IRQSTATUS, wval);
1065 break;
1066
1067 case GPMC_CONFIG_WP: 1054 case GPMC_CONFIG_WP:
1068 regval = gpmc_read_reg(GPMC_CONFIG); 1055 regval = gpmc_read_reg(GPMC_CONFIG);
1069 if (wval) 1056 if (wval)
@@ -1153,85 +1140,97 @@ EXPORT_SYMBOL_GPL(gpmc_omap_get_nand_ops);
1153 1140
1154int gpmc_get_client_irq(unsigned irq_config) 1141int gpmc_get_client_irq(unsigned irq_config)
1155{ 1142{
1156 int i; 1143 if (!gpmc_irq_domain) {
1157 1144 pr_warn("%s called before GPMC IRQ domain available\n",
1158 if (hweight32(irq_config) > 1) 1145 __func__);
1159 return 0; 1146 return 0;
1147 }
1160 1148
1161 for (i = 0; i < GPMC_NR_IRQ; i++) 1149 if (irq_config >= GPMC_NR_IRQ)
1162 if (gpmc_client_irq[i].bitmask & irq_config) 1150 return 0;
1163 return gpmc_client_irq[i].irq;
1164 1151
1165 return 0; 1152 return irq_create_mapping(gpmc_irq_domain, irq_config);
1166} 1153}
1167 1154
1168static int gpmc_irq_endis(unsigned irq, bool endis) 1155static int gpmc_irq_endis(unsigned long hwirq, bool endis)
1169{ 1156{
1170 int i;
1171 u32 regval; 1157 u32 regval;
1172 1158
1173 for (i = 0; i < GPMC_NR_IRQ; i++) 1159 regval = gpmc_read_reg(GPMC_IRQENABLE);
1174 if (irq == gpmc_client_irq[i].irq) { 1160 if (endis)
1175 regval = gpmc_read_reg(GPMC_IRQENABLE); 1161 regval |= BIT(hwirq);
1176 if (endis) 1162 else
1177 regval |= gpmc_client_irq[i].bitmask; 1163 regval &= ~BIT(hwirq);
1178 else 1164 gpmc_write_reg(GPMC_IRQENABLE, regval);
1179 regval &= ~gpmc_client_irq[i].bitmask;
1180 gpmc_write_reg(GPMC_IRQENABLE, regval);
1181 break;
1182 }
1183 1165
1184 return 0; 1166 return 0;
1185} 1167}
1186 1168
1187static void gpmc_irq_disable(struct irq_data *p) 1169static void gpmc_irq_disable(struct irq_data *p)
1188{ 1170{
1189 gpmc_irq_endis(p->irq, false); 1171 gpmc_irq_endis(p->hwirq, false);
1190} 1172}
1191 1173
1192static void gpmc_irq_enable(struct irq_data *p) 1174static void gpmc_irq_enable(struct irq_data *p)
1193{ 1175{
1194 gpmc_irq_endis(p->irq, true); 1176 gpmc_irq_endis(p->hwirq, true);
1195} 1177}
1196 1178
1197static void gpmc_irq_noop(struct irq_data *data) { } 1179static void gpmc_irq_noop(struct irq_data *data) { }
1198 1180
1199static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; } 1181static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
1200 1182
1201static int gpmc_setup_irq(void) 1183static int gpmc_irq_map(struct irq_domain *d, unsigned int virq,
1184 irq_hw_number_t hw)
1202{ 1185{
1203 int i; 1186 struct gpmc_device *gpmc = d->host_data;
1187
1188 irq_set_chip_data(virq, gpmc);
1189 irq_set_chip_and_handler(virq, &gpmc->irq_chip, handle_simple_irq);
1190 irq_modify_status(virq, IRQ_NOREQUEST, IRQ_NOAUTOEN);
1191
1192 return 0;
1193}
1194
1195static const struct irq_domain_ops gpmc_irq_domain_ops = {
1196 .map = gpmc_irq_map,
1197 .xlate = irq_domain_xlate_twocell,
1198};
1199
1200static irqreturn_t gpmc_handle_irq(int irq, void *data)
1201{
1202 int hwirq, virq;
1204 u32 regval; 1203 u32 regval;
1204 struct gpmc_device *gpmc = data;
1205 1205
1206 if (!gpmc_irq) 1206 regval = gpmc_read_reg(GPMC_IRQSTATUS);
1207 return -EINVAL;
1208 1207
1209 gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0); 1208 if (!regval)
1210 if (gpmc_irq_start < 0) { 1209 return IRQ_NONE;
1211 pr_err("irq_alloc_descs failed\n");
1212 return gpmc_irq_start;
1213 }
1214 1210
1215 gpmc_irq_chip.name = "gpmc"; 1211 for (hwirq = 0; hwirq < GPMC_NR_IRQ; hwirq++) {
1216 gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret; 1212 if (regval & BIT(hwirq)) {
1217 gpmc_irq_chip.irq_enable = gpmc_irq_enable; 1213 virq = irq_find_mapping(gpmc_irq_domain, hwirq);
1218 gpmc_irq_chip.irq_disable = gpmc_irq_disable; 1214 if (!virq) {
1219 gpmc_irq_chip.irq_shutdown = gpmc_irq_noop; 1215 dev_warn(gpmc->dev,
1220 gpmc_irq_chip.irq_ack = gpmc_irq_noop; 1216 "spurious irq detected hwirq %d, virq %d\n",
1221 gpmc_irq_chip.irq_mask = gpmc_irq_noop; 1217 hwirq, virq);
1222 gpmc_irq_chip.irq_unmask = gpmc_irq_noop; 1218 }
1223 1219
1224 gpmc_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE; 1220 generic_handle_irq(virq);
1225 gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT; 1221 }
1226
1227 for (i = 0; i < GPMC_NR_IRQ; i++) {
1228 gpmc_client_irq[i].irq = gpmc_irq_start + i;
1229 irq_set_chip_and_handler(gpmc_client_irq[i].irq,
1230 &gpmc_irq_chip, handle_simple_irq);
1231 irq_modify_status(gpmc_client_irq[i].irq, IRQ_NOREQUEST,
1232 IRQ_NOAUTOEN);
1233 } 1222 }
1234 1223
1224 gpmc_write_reg(GPMC_IRQSTATUS, regval);
1225
1226 return IRQ_HANDLED;
1227}
1228
1229static int gpmc_setup_irq(struct gpmc_device *gpmc)
1230{
1231 u32 regval;
1232 int rc;
1233
1235 /* Disable interrupts */ 1234 /* Disable interrupts */
1236 gpmc_write_reg(GPMC_IRQENABLE, 0); 1235 gpmc_write_reg(GPMC_IRQENABLE, 0);
1237 1236
@@ -1239,22 +1238,46 @@ static int gpmc_setup_irq(void)
1239 regval = gpmc_read_reg(GPMC_IRQSTATUS); 1238 regval = gpmc_read_reg(GPMC_IRQSTATUS);
1240 gpmc_write_reg(GPMC_IRQSTATUS, regval); 1239 gpmc_write_reg(GPMC_IRQSTATUS, regval);
1241 1240
1242 return request_irq(gpmc_irq, gpmc_handle_irq, 0, "gpmc", NULL); 1241 gpmc->irq_chip.name = "gpmc";
1242 gpmc->irq_chip.irq_startup = gpmc_irq_noop_ret;
1243 gpmc->irq_chip.irq_enable = gpmc_irq_enable;
1244 gpmc->irq_chip.irq_disable = gpmc_irq_disable;
1245 gpmc->irq_chip.irq_shutdown = gpmc_irq_noop;
1246 gpmc->irq_chip.irq_ack = gpmc_irq_noop;
1247 gpmc->irq_chip.irq_mask = gpmc_irq_noop;
1248 gpmc->irq_chip.irq_unmask = gpmc_irq_noop;
1249
1250 gpmc_irq_domain = irq_domain_add_linear(gpmc->dev->of_node,
1251 GPMC_NR_IRQ,
1252 &gpmc_irq_domain_ops,
1253 gpmc);
1254 if (!gpmc_irq_domain) {
1255 dev_err(gpmc->dev, "IRQ domain add failed\n");
1256 return -ENODEV;
1257 }
1258
1259 rc = request_irq(gpmc->irq, gpmc_handle_irq, 0, "gpmc", gpmc);
1260 if (rc) {
1261 dev_err(gpmc->dev, "failed to request irq %d: %d\n",
1262 gpmc->irq, rc);
1263 irq_domain_remove(gpmc_irq_domain);
1264 gpmc_irq_domain = NULL;
1265 }
1266
1267 return rc;
1243} 1268}
1244 1269
1245static int gpmc_free_irq(void) 1270static int gpmc_free_irq(struct gpmc_device *gpmc)
1246{ 1271{
1247 int i; 1272 int hwirq;
1248 1273
1249 if (gpmc_irq) 1274 free_irq(gpmc->irq, gpmc);
1250 free_irq(gpmc_irq, NULL);
1251 1275
1252 for (i = 0; i < GPMC_NR_IRQ; i++) { 1276 for (hwirq = 0; hwirq < GPMC_NR_IRQ; hwirq++)
1253 irq_set_handler(gpmc_client_irq[i].irq, NULL); 1277 irq_dispose_mapping(irq_find_mapping(gpmc_irq_domain, hwirq));
1254 irq_set_chip(gpmc_client_irq[i].irq, &no_irq_chip);
1255 }
1256 1278
1257 irq_free_descs(gpmc_irq_start, GPMC_NR_IRQ); 1279 irq_domain_remove(gpmc_irq_domain);
1280 gpmc_irq_domain = NULL;
1258 1281
1259 return 0; 1282 return 0;
1260} 1283}
@@ -2154,6 +2177,14 @@ static int gpmc_probe(struct platform_device *pdev)
2154 int rc; 2177 int rc;
2155 u32 l; 2178 u32 l;
2156 struct resource *res; 2179 struct resource *res;
2180 struct gpmc_device *gpmc;
2181
2182 gpmc = devm_kzalloc(&pdev->dev, sizeof(*gpmc), GFP_KERNEL);
2183 if (!gpmc)
2184 return -ENOMEM;
2185
2186 gpmc->dev = &pdev->dev;
2187 platform_set_drvdata(pdev, gpmc);
2157 2188
2158 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2189 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2159 if (res == NULL) 2190 if (res == NULL)
@@ -2167,15 +2198,16 @@ static int gpmc_probe(struct platform_device *pdev)
2167 return PTR_ERR(gpmc_base); 2198 return PTR_ERR(gpmc_base);
2168 2199
2169 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 2200 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
2170 if (res == NULL) 2201 if (!res) {
2171 dev_warn(&pdev->dev, "Failed to get resource: irq\n"); 2202 dev_err(&pdev->dev, "Failed to get resource: irq\n");
2172 else 2203 return -ENOENT;
2173 gpmc_irq = res->start; 2204 }
2205
2206 gpmc->irq = res->start;
2174 2207
2175 gpmc_l3_clk = devm_clk_get(&pdev->dev, "fck"); 2208 gpmc_l3_clk = devm_clk_get(&pdev->dev, "fck");
2176 if (IS_ERR(gpmc_l3_clk)) { 2209 if (IS_ERR(gpmc_l3_clk)) {
2177 dev_err(&pdev->dev, "Failed to get GPMC fck\n"); 2210 dev_err(&pdev->dev, "Failed to get GPMC fck\n");
2178 gpmc_irq = 0;
2179 return PTR_ERR(gpmc_l3_clk); 2211 return PTR_ERR(gpmc_l3_clk);
2180 } 2212 }
2181 2213
@@ -2187,8 +2219,6 @@ static int gpmc_probe(struct platform_device *pdev)
2187 pm_runtime_enable(&pdev->dev); 2219 pm_runtime_enable(&pdev->dev);
2188 pm_runtime_get_sync(&pdev->dev); 2220 pm_runtime_get_sync(&pdev->dev);
2189 2221
2190 gpmc_dev = &pdev->dev;
2191
2192 l = gpmc_read_reg(GPMC_REVISION); 2222 l = gpmc_read_reg(GPMC_REVISION);
2193 2223
2194 /* 2224 /*
@@ -2207,13 +2237,16 @@ static int gpmc_probe(struct platform_device *pdev)
2207 gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS; 2237 gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS;
2208 if (GPMC_REVISION_MAJOR(l) > 0x5) 2238 if (GPMC_REVISION_MAJOR(l) > 0x5)
2209 gpmc_capability |= GPMC_HAS_MUX_AAD; 2239 gpmc_capability |= GPMC_HAS_MUX_AAD;
2210 dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l), 2240 dev_info(gpmc->dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
2211 GPMC_REVISION_MINOR(l)); 2241 GPMC_REVISION_MINOR(l));
2212 2242
2213 gpmc_mem_init(); 2243 gpmc_mem_init();
2214 2244
2215 if (gpmc_setup_irq() < 0) 2245 rc = gpmc_setup_irq(gpmc);
2216 dev_warn(gpmc_dev, "gpmc_setup_irq failed\n"); 2246 if (rc) {
2247 dev_err(gpmc->dev, "gpmc_setup_irq failed\n");
2248 goto fail;
2249 }
2217 2250
2218 if (!pdev->dev.of_node) { 2251 if (!pdev->dev.of_node) {
2219 gpmc_cs_num = GPMC_CS_NUM; 2252 gpmc_cs_num = GPMC_CS_NUM;
@@ -2222,21 +2255,27 @@ static int gpmc_probe(struct platform_device *pdev)
2222 2255
2223 rc = gpmc_probe_dt(pdev); 2256 rc = gpmc_probe_dt(pdev);
2224 if (rc < 0) { 2257 if (rc < 0) {
2225 pm_runtime_put_sync(&pdev->dev); 2258 dev_err(gpmc->dev, "failed to probe DT parameters\n");
2226 dev_err(gpmc_dev, "failed to probe DT parameters\n"); 2259 gpmc_free_irq(gpmc);
2227 return rc; 2260 goto fail;
2228 } 2261 }
2229 2262
2230 return 0; 2263 return 0;
2264
2265fail:
2266 pm_runtime_put_sync(&pdev->dev);
2267 return rc;
2231} 2268}
2232 2269
2233static int gpmc_remove(struct platform_device *pdev) 2270static int gpmc_remove(struct platform_device *pdev)
2234{ 2271{
2235 gpmc_free_irq(); 2272 struct gpmc_device *gpmc = platform_get_drvdata(pdev);
2273
2274 gpmc_free_irq(gpmc);
2236 gpmc_mem_exit(); 2275 gpmc_mem_exit();
2237 pm_runtime_put_sync(&pdev->dev); 2276 pm_runtime_put_sync(&pdev->dev);
2238 pm_runtime_disable(&pdev->dev); 2277 pm_runtime_disable(&pdev->dev);
2239 gpmc_dev = NULL; 2278
2240 return 0; 2279 return 0;
2241} 2280}
2242 2281
@@ -2282,25 +2321,6 @@ static __exit void gpmc_exit(void)
2282postcore_initcall(gpmc_init); 2321postcore_initcall(gpmc_init);
2283module_exit(gpmc_exit); 2322module_exit(gpmc_exit);
2284 2323
2285static irqreturn_t gpmc_handle_irq(int irq, void *dev)
2286{
2287 int i;
2288 u32 regval;
2289
2290 regval = gpmc_read_reg(GPMC_IRQSTATUS);
2291
2292 if (!regval)
2293 return IRQ_NONE;
2294
2295 for (i = 0; i < GPMC_NR_IRQ; i++)
2296 if (regval & gpmc_client_irq[i].bitmask)
2297 generic_handle_irq(gpmc_client_irq[i].irq);
2298
2299 gpmc_write_reg(GPMC_IRQSTATUS, regval);
2300
2301 return IRQ_HANDLED;
2302}
2303
2304static struct omap3_gpmc_regs gpmc_context; 2324static struct omap3_gpmc_regs gpmc_context;
2305 2325
2306void omap3_gpmc_save_context(void) 2326void omap3_gpmc_save_context(void)
diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h
index dc2ada6fb9b4..9e9d79e8efa5 100644
--- a/include/linux/omap-gpmc.h
+++ b/include/linux/omap-gpmc.h
@@ -11,8 +11,9 @@
11 11
12#define GPMC_CONFIG_WP 0x00000005 12#define GPMC_CONFIG_WP 0x00000005
13 13
14#define GPMC_IRQ_FIFOEVENTENABLE 0x01 14/* IRQ numbers in GPMC IRQ domain for legacy boot use */
15#define GPMC_IRQ_COUNT_EVENT 0x02 15#define GPMC_IRQ_FIFOEVENTENABLE 0
16#define GPMC_IRQ_COUNT_EVENT 1
16 17
17/** 18/**
18 * gpmc_nand_ops - Interface between NAND and GPMC 19 * gpmc_nand_ops - Interface between NAND and GPMC