aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRostislav Lisovy <lisovy@gmail.com>2014-06-04 10:24:35 -0400
committerRoger Quadros <rogerq@ti.com>2014-07-11 09:15:13 -0400
commit97a288ba2cfaf18ae2a8d19b8d9ea8cb3fbe301a (patch)
tree704fa1f65df8ddfcdf73e55113cf246eb84be3e0
parentcd3de83f147601356395b57a8673e9c5ff1e59d1 (diff)
ARM: omap2+: gpmc-nand: Use dynamic platform_device_alloc()
GPMC controller supports up to 8 memory devices connected to it. Since there is one statically allocated "struct platform_device gpmc_nand_device" it is not possible to configure the system to use more than one NAND device connected to the GPMC. This modification makes it possible to use up to 8 NAND devices connected to the GPMC controller. Signed-off-by: Rostislav Lisovy <lisovy@merica.cz> Signed-off-by: Roger Quadros <rogerq@ti.com>
-rw-r--r--arch/arm/mach-omap2/gpmc-nand.c79
1 files changed, 37 insertions, 42 deletions
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 17cd39360afe..7ab486eeb769 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -24,25 +24,6 @@
24/* minimum size for IO mapping */ 24/* minimum size for IO mapping */
25#define NAND_IO_SIZE 4 25#define NAND_IO_SIZE 4
26 26
27static struct resource gpmc_nand_resource[] = {
28 {
29 .flags = IORESOURCE_MEM,
30 },
31 {
32 .flags = IORESOURCE_IRQ,
33 },
34 {
35 .flags = IORESOURCE_IRQ,
36 },
37};
38
39static struct platform_device gpmc_nand_device = {
40 .name = "omap2-nand",
41 .id = 0,
42 .num_resources = ARRAY_SIZE(gpmc_nand_resource),
43 .resource = gpmc_nand_resource,
44};
45
46static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) 27static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
47{ 28{
48 /* platforms which support all ECC schemes */ 29 /* platforms which support all ECC schemes */
@@ -93,43 +74,41 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
93{ 74{
94 int err = 0; 75 int err = 0;
95 struct gpmc_settings s; 76 struct gpmc_settings s;
96 struct device *dev = &gpmc_nand_device.dev; 77 struct platform_device *pdev;
97 78 struct resource gpmc_nand_res[] = {
98 memset(&s, 0, sizeof(struct gpmc_settings)); 79 { .flags = IORESOURCE_MEM, },
80 { .flags = IORESOURCE_IRQ, },
81 { .flags = IORESOURCE_IRQ, },
82 };
99 83
100 gpmc_nand_device.dev.platform_data = gpmc_nand_data; 84 BUG_ON(gpmc_nand_data->cs >= GPMC_CS_NUM);
101 85
102 err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE, 86 err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
103 (unsigned long *)&gpmc_nand_resource[0].start); 87 (unsigned long *)&gpmc_nand_res[0].start);
104 if (err < 0) { 88 if (err < 0) {
105 dev_err(dev, "Cannot request GPMC CS %d, error %d\n", 89 pr_err("omap2-gpmc: Cannot request GPMC CS %d, error %d\n",
106 gpmc_nand_data->cs, err); 90 gpmc_nand_data->cs, err);
107 return err; 91 return err;
108 } 92 }
109 93 gpmc_nand_res[0].end = gpmc_nand_res[0].start + NAND_IO_SIZE - 1;
110 gpmc_nand_resource[0].end = gpmc_nand_resource[0].start + 94 gpmc_nand_res[1].start = gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
111 NAND_IO_SIZE - 1; 95 gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
112
113 gpmc_nand_resource[1].start =
114 gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
115 gpmc_nand_resource[2].start =
116 gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
117 96
118 if (gpmc_t) { 97 if (gpmc_t) {
119 err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t); 98 err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t);
120 if (err < 0) { 99 if (err < 0) {
121 dev_err(dev, "Unable to set gpmc timings: %d\n", err); 100 pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n", err);
122 return err; 101 return err;
123 } 102 }
124 } 103 }
125 104
105 memset(&s, 0, sizeof(struct gpmc_settings));
126 if (gpmc_nand_data->of_node) 106 if (gpmc_nand_data->of_node)
127 gpmc_read_settings_dt(gpmc_nand_data->of_node, &s); 107 gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
128 else 108 else
129 gpmc_set_legacy(gpmc_nand_data, &s); 109 gpmc_set_legacy(gpmc_nand_data, &s);
130 110
131 s.device_nand = true; 111 s.device_nand = true;
132
133 err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s); 112 err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
134 if (err < 0) 113 if (err < 0)
135 goto out_free_cs; 114 goto out_free_cs;
@@ -141,18 +120,34 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
141 gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs); 120 gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
142 121
143 if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) { 122 if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) {
144 dev_err(dev, "Unsupported NAND ECC scheme selected\n"); 123 pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n");
145 return -EINVAL; 124 err = -EINVAL;
125 goto out_free_cs;
146 } 126 }
147 127
148 err = platform_device_register(&gpmc_nand_device); 128
149 if (err < 0) { 129 pdev = platform_device_alloc("omap2-nand", gpmc_nand_data->cs);
150 dev_err(dev, "Unable to register NAND device\n"); 130 if (pdev) {
151 goto out_free_cs; 131 err = platform_device_add_resources(pdev, gpmc_nand_res,
132 ARRAY_SIZE(gpmc_nand_res));
133 if (!err)
134 pdev->dev.platform_data = gpmc_nand_data;
135 } else {
136 err = -ENOMEM;
137 }
138 if (err)
139 goto out_free_pdev;
140
141 err = platform_device_add(pdev);
142 if (err) {
143 dev_err(&pdev->dev, "Unable to register NAND device\n");
144 goto out_free_pdev;
152 } 145 }
153 146
154 return 0; 147 return 0;
155 148
149out_free_pdev:
150 platform_device_put(pdev);
156out_free_cs: 151out_free_cs:
157 gpmc_cs_free(gpmc_nand_data->cs); 152 gpmc_cs_free(gpmc_nand_data->cs);
158 153