diff options
-rw-r--r-- | Documentation/devicetree/bindings/bus/ti-gpmc.txt | 8 | ||||
-rw-r--r-- | drivers/memory/omap-gpmc.c | 246 | ||||
-rw-r--r-- | include/linux/omap-gpmc.h | 5 |
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 | ||
36 | Timing properties for child nodes. All are optional and default to 0. | 42 | Timing 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 | ||
204 | struct 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 */ |
210 | struct gpmc_cs_config { | 203 | struct 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 | ||
236 | static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; | 229 | struct gpmc_device { |
237 | static struct irq_chip gpmc_irq_chip; | 230 | struct device *dev; |
238 | static int gpmc_irq_start; | 231 | int irq; |
232 | struct irq_chip irq_chip; | ||
233 | }; | ||
234 | |||
235 | static struct irq_domain *gpmc_irq_domain; | ||
239 | 236 | ||
240 | static struct resource gpmc_mem_root; | 237 | static struct resource gpmc_mem_root; |
241 | static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM]; | 238 | static 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 */ |
244 | static unsigned int gpmc_cs_num = GPMC_CS_NUM; | 241 | static unsigned int gpmc_cs_num = GPMC_CS_NUM; |
245 | static unsigned int gpmc_nr_waitpins; | 242 | static unsigned int gpmc_nr_waitpins; |
246 | static struct device *gpmc_dev; | ||
247 | static int gpmc_irq; | ||
248 | static resource_size_t phys_base, mem_size; | 243 | static resource_size_t phys_base, mem_size; |
249 | static unsigned gpmc_capability; | 244 | static unsigned gpmc_capability; |
250 | static void __iomem *gpmc_base; | 245 | static 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 | ||
1154 | int gpmc_get_client_irq(unsigned irq_config) | 1141 | int 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 | ||
1168 | static int gpmc_irq_endis(unsigned irq, bool endis) | 1155 | static 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 | ||
1187 | static void gpmc_irq_disable(struct irq_data *p) | 1169 | static 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 | ||
1192 | static void gpmc_irq_enable(struct irq_data *p) | 1174 | static 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 | ||
1197 | static void gpmc_irq_noop(struct irq_data *data) { } | 1179 | static void gpmc_irq_noop(struct irq_data *data) { } |
1198 | 1180 | ||
1199 | static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; } | 1181 | static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; } |
1200 | 1182 | ||
1201 | static int gpmc_setup_irq(void) | 1183 | static 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 | |||
1195 | static const struct irq_domain_ops gpmc_irq_domain_ops = { | ||
1196 | .map = gpmc_irq_map, | ||
1197 | .xlate = irq_domain_xlate_twocell, | ||
1198 | }; | ||
1199 | |||
1200 | static 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 | |||
1229 | static 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 | ||
1245 | static int gpmc_free_irq(void) | 1270 | static 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 | |||
2265 | fail: | ||
2266 | pm_runtime_put_sync(&pdev->dev); | ||
2267 | return rc; | ||
2231 | } | 2268 | } |
2232 | 2269 | ||
2233 | static int gpmc_remove(struct platform_device *pdev) | 2270 | static 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) | |||
2282 | postcore_initcall(gpmc_init); | 2321 | postcore_initcall(gpmc_init); |
2283 | module_exit(gpmc_exit); | 2322 | module_exit(gpmc_exit); |
2284 | 2323 | ||
2285 | static 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 | |||
2304 | static struct omap3_gpmc_regs gpmc_context; | 2324 | static struct omap3_gpmc_regs gpmc_context; |
2305 | 2325 | ||
2306 | void omap3_gpmc_save_context(void) | 2326 | void 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 |