break trunk temporary - upgrade to 2.6.21.1 and iptables 1.3.7
[openwrt.git] / target / linux / ixp4xx-2.6 / patches / 139-ixp4xx_net_driver_mtd_load_fw.patch
1 ---
2  drivers/net/ixp4xx/Kconfig             |   10 +
3  drivers/net/ixp4xx/Makefile            |    1 
4  drivers/net/ixp4xx/npe_ucode.c         |  185 +++++++++++++++++++++++++++++++++
5  drivers/net/ixp4xx/ucode_dl.c          |   43 ++++---
6  include/asm-arm/arch-ixp4xx/platform.h |   19 +++
7  include/linux/ixp_npe.h                |    1 
8  6 files changed, 239 insertions(+), 20 deletions(-)
9
10 Index: linux-2.6.20-rc3/drivers/net/ixp4xx/Kconfig
11 ===================================================================
12 --- linux-2.6.20-rc3.orig/drivers/net/ixp4xx/Kconfig
13 +++ linux-2.6.20-rc3/drivers/net/ixp4xx/Kconfig
14 @@ -11,6 +11,7 @@
15         tristate "IXP4xx NPE support"
16         depends on ARCH_IXP4XX
17         depends on NET_ETHERNET
18 +       select CRC16
19         help
20           The IXP4XX NPE driver supports the 3 CPU co-processors called
21           "Network Processing Engines" (NPE). It adds support fo downloading
22 @@ -18,7 +19,7 @@
23           More about this at: Documentation/networking/ixp4xx/README.
24           You can either use this OR the Intel Access Library (IAL)
25  
26 -config IXP4XX_FW_LOAD
27 +config IXP4XX_NPE_FW_LOAD
28         bool "Use Firmware hotplug for Microcode download"
29         depends on IXP4XX_NPE
30         select HOTPLUG
31 @@ -28,6 +29,13 @@
32           /usr/lib/hotplug/firmware/NPE-[ABC]
33           see Documentation/firmware_class/hotplug-script
34  
35 +config IXP4XX_NPE_FW_MTD
36 +       bool "Load firmware from an mtd partition"
37 +       depends on IXP4XX_NPE && MTD_IXP4XX
38 +       help
39 +         With this option, the driver will search for
40 +         the firmware into an MTD partition.
41 +
42  config IXP4XX_MAC
43         tristate "IXP4xx MAC support"
44         depends on IXP4XX_NPE
45 Index: linux-2.6.20-rc3/drivers/net/ixp4xx/Makefile
46 ===================================================================
47 --- linux-2.6.20-rc3.orig/drivers/net/ixp4xx/Makefile
48 +++ linux-2.6.20-rc3/drivers/net/ixp4xx/Makefile
49 @@ -1,5 +1,6 @@
50  obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o
51  obj-$(CONFIG_IXP4XX_NPE) += ixp4xx_npe.o
52 +obj-$(CONFIG_IXP4XX_NPE_FW_MTD) += npe_ucode.o
53  obj-$(CONFIG_IXP4XX_MAC) += ixp4xx_mac.o
54  obj-$(CONFIG_IXP4XX_CRYPTO) += ixp4xx_crypto.o
55  
56 Index: linux-2.6.20-rc3/drivers/net/ixp4xx/npe_ucode.c
57 ===================================================================
58 --- /dev/null
59 +++ linux-2.6.20-rc3/drivers/net/ixp4xx/npe_ucode.c
60 @@ -0,0 +1,185 @@
61 +/*
62 + * Provide an NPE platform device for microcode handling
63 + *
64 + * Copyright (C) 2006 Christian Hohnstaedt <chohnstaedt@innominate.com>
65 + *
66 + * This file is released under the GPLv2
67 + */
68 +
69 +#include <linux/kernel.h>
70 +#include <linux/platform_device.h>
71 +#include <linux/init.h>
72 +#include <linux/slab.h>
73 +#include <linux/firmware.h>
74 +#include <linux/mtd/mtd.h>
75 +
76 +#include <linux/ixp_npe.h>
77 +
78 +#define DL_MAGIC 0xfeedf00d
79 +#define DL_MAGIC_SWAP 0x0df0edfe
80 +
81 +#define IMG_SIZE(image) (((image)->size * sizeof(u32)) + \
82 +               sizeof(struct dl_image))
83 +
84 +#define IMG_REV_MAJOR(id) (((id) >> 8) & 0x0f)
85 +#define IMG_REV_MINOR(id) ((id) & 0x0f)
86 +#define IMG_FUNC(id) (((id) >> 16) & 0xff)
87 +#define IMG_NPE(id) (((id) >> 24) & 0x0f)
88 +#define IMG_IXP(id) (((id) >> 28) & 0x0f)
89 +
90 +static struct platform_driver ixp4xx_npe_ucode_driver;
91 +static unsigned char *partition_name = NULL;
92 +
93 +static void print_image_info(u32 id, u32 offset, u32 size)
94 +{
95 +       unsigned char idx;
96 +       const char *names[] = { "IXP425", "IXP465", "unknown" };
97 +
98 +       idx = IMG_IXP(id) < 2 ? IMG_IXP(id) : 2;
99 +
100 +       printk(KERN_INFO "npe: found at 0x%x, %s/NPE-%c func: %02x, rev: %x.%x, "
101 +               "size: %5d, id: %08x\n", offset, names[idx], IMG_NPE(id) + 'A',
102 +               IMG_FUNC(id), IMG_REV_MAJOR(id), IMG_REV_MINOR(id), size, id);
103 +}
104 +
105 +void npe_swap_image(struct dl_image *image)
106 +{
107 +       unsigned int i;
108 +
109 +       image->magic = swab32(image->magic);
110 +       image->id = swab32(image->id);
111 +       image->size = swab32(image->size);
112 +
113 +       for (i = 0; i < image->size; i++)
114 +               image->u.data[i] = swab32(image->u.data[i]);
115 +}
116 +
117 +static void npe_find_microcode(struct mtd_info *mtd)
118 +{
119 +       u32 buf;
120 +       u32 magic = htonl(DL_MAGIC);
121 +       u32 id, size;
122 +       size_t retlen;
123 +       int err;
124 +       unsigned int offset = 0;
125 +
126 +       printk("npe: searching for firmware...\n");
127 +
128 +       while (offset < mtd->size) {
129 +
130 +               err = mtd->read(mtd, offset, 4, &retlen, (u_char *) &buf);
131 +               offset += retlen;
132 +
133 +               if (buf != magic)
134 +                       continue;
135 +
136 +               err = mtd->read(mtd, offset, 4, &retlen, (u_char *) &id);
137 +               offset += retlen;
138 +
139 +               if (id == magic)
140 +                       break;
141 +
142 +               id = ntohl(id);
143 +
144 +               err = mtd->read(mtd, offset, 4, &retlen, (u_char *) &size);
145 +               offset += retlen;
146 +
147 +               size = (ntohl(size) * 4) + 12;
148 +
149 +               print_image_info(id, offset - 12, size);
150 +
151 +               if (size < 24000 && ( IMG_FUNC(id) == 0x01 || IMG_FUNC(id) == 0x00) ) { // XXX fix size/detection
152 +
153 +                       struct dl_image *image = kmalloc(size, GFP_KERNEL);
154 +
155 +                       /* we are going to load it, rewind offset */
156 +                       offset -= 12;
157 +
158 +                       if (image) {
159 +                               err = mtd->read(mtd, offset, size, &retlen, (u_char *) image);
160 +
161 +                               if (err == 0 && retlen == size) {
162 +                                       if (image->magic == DL_MAGIC_SWAP)
163 +                                               npe_swap_image(image);
164 +
165 +                                       store_npe_image(image, NULL);
166 +                               } else {
167 +                                       printk(KERN_ERR "unable to read firmware\n");
168 +                               }
169 +
170 +                               kfree(image);
171 +                       }
172 +
173 +                       offset += size;
174 +               }
175 +       }
176 +}
177 +
178 +static void npe_flash_add(struct mtd_info *mtd)
179 +{
180 +       if (partition_name == NULL)
181 +               return;
182 +
183 +       if (strcmp(mtd->name, partition_name) == 0) {
184 +               npe_find_microcode(mtd);
185 +       }
186 +}
187 +
188 +static void npe_flash_remove(struct mtd_info *mtd) {
189 +}
190 +
191 +static struct mtd_notifier npe_flash_notifier = {
192 +       .add = npe_flash_add,
193 +       .remove = npe_flash_remove,
194 +};
195 +
196 +static int npe_ucode_probe(struct platform_device *pdev)
197 +{
198 +       struct npe_ucode_platform_data *data = pdev->dev.platform_data;
199 +
200 +       if (partition_name)
201 +               return -EEXIST;
202 +
203 +       if (data && data->mtd_partition) {
204 +               partition_name = data->mtd_partition;
205 +               return 0;
206 +       }
207 +
208 +       return -EINVAL;
209 +}
210 +
211 +static int npe_ucode_remove(struct platform_device *pdev)
212 +{
213 +       return 0;
214 +}
215 +
216 +static struct platform_driver ixp4xx_npe_ucode_driver = {
217 +       .driver = {
218 +               .name   = "ixp4xx_npe_ucode",
219 +               .owner  = THIS_MODULE,
220 +       },
221 +       .probe  = npe_ucode_probe,
222 +       .remove = npe_ucode_remove,
223 +};
224 +
225 +static int __init npe_ucode_init(void)
226 +{
227 +       int ret;
228 +
229 +       ret = platform_driver_register(&ixp4xx_npe_ucode_driver);
230 +       register_mtd_user(&npe_flash_notifier);
231 +
232 +       return ret;
233 +}
234 +
235 +static void __exit npe_ucode_exit(void)
236 +{
237 +       unregister_mtd_user(&npe_flash_notifier);
238 +       platform_driver_unregister(&ixp4xx_npe_ucode_driver);
239 +}
240 +
241 +module_init(npe_ucode_init);
242 +module_exit(npe_ucode_exit);
243 +
244 +MODULE_LICENSE("GPL");
245 +MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
246 Index: linux-2.6.20-rc3/drivers/net/ixp4xx/ucode_dl.c
247 ===================================================================
248 --- linux-2.6.20-rc3.orig/drivers/net/ixp4xx/ucode_dl.c
249 +++ linux-2.6.20-rc3/drivers/net/ixp4xx/ucode_dl.c
250 @@ -16,6 +16,7 @@
251  #include <linux/firmware.h>
252  #include <linux/dma-mapping.h>
253  #include <linux/byteorder/swab.h>
254 +#include <linux/crc16.h>
255  #include <asm/uaccess.h>
256  #include <asm/io.h>
257  
258 @@ -26,6 +27,12 @@
259  #define DL_MAGIC 0xfeedf00d
260  #define DL_MAGIC_SWAP 0x0df0edfe
261  
262 +#define IMG_REV_MAJOR(id) (((id) >> 8) & 0x0f)
263 +#define IMG_REV_MINOR(id) ((id) & 0x0f)
264 +#define IMG_FUNC(id) (((id) >> 16) & 0xff)
265 +#define IMG_NPE(id) (((id) >> 24) & 0x0f)
266 +#define IMG_IXP(id) (((id) >> 28) & 0x0f)
267 +
268  #define EOF_BLOCK 0xf
269  #define IMG_SIZE(image) (((image)->size * sizeof(u32)) + \
270                 sizeof(struct dl_image))
271 @@ -38,21 +45,6 @@
272         data,
273  };
274  
275 -struct dl_block {
276 -       u32 type;
277 -       u32 offset;
278 -};
279 -
280 -struct dl_image {
281 -       u32 magic;
282 -       u32 id;
283 -       u32 size;
284 -       union {
285 -               u32 data[0];
286 -               struct dl_block block[0];
287 -       } u;
288 -};
289 -
290  struct dl_codeblock {
291         u32 npe_addr;
292         u32 size;
293 @@ -127,20 +119,33 @@
294         return 0;
295  }
296  
297 -static int store_npe_image(struct dl_image *image, struct device *dev)
298 +int store_npe_image(struct dl_image *image, struct device *dev)
299  {
300         struct dl_block *blk;
301         struct dl_codeblock *cb;
302         struct npe_info *npe;
303         int ret=0;
304 +       u16 crc;
305  
306         if (!dev) {
307 -               dev = get_npe_by_id( (image->id >> 24) & 0xf);
308 +               dev = get_npe_by_id(IMG_NPE(image->id));
309                 return_npe_dev(dev);
310         }
311         if (!dev)
312                 return -ENODEV;
313  
314 +       if (image->size > 24000) { // XXX fix max size
315 +               printk(KERN_ERR "npe: firmware too large\n");
316 +               return -EFBIG;
317 +       }
318 +
319 +       if (IMG_REV_MAJOR(image->id) != 2) {
320 +               printk(KERN_ERR "npe: only revision 2 is supported at this time\n");
321 +               return -EINVAL;
322 +       }
323 +
324 +       crc = crc16(0, (u8 *) image, IMG_SIZE(image));
325 +
326         npe = dev_get_drvdata(dev);
327         if (npe->loaded && (npe->usage > 0)) {
328                 printk(KERN_INFO "Cowardly refusing to reload an Image "
329 @@ -267,8 +272,7 @@
330  
331  static void npe_firmware_probe(struct device *dev)
332  {
333 -#if (defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)) \
334 -       && defined(MODULE)
335 +#ifdef CONFIG_IXP4XX_NPE_FW_LOADER
336         const struct firmware *fw_entry;
337         struct npe_info *npe = dev_get_drvdata(dev);
338         struct dl_image *image;
339 @@ -477,3 +481,4 @@
340  
341  EXPORT_SYMBOL(get_npe_by_id);
342  EXPORT_SYMBOL(return_npe_dev);
343 +EXPORT_SYMBOL(store_npe_image);
344 Index: linux-2.6.20-rc3/include/asm-arm/arch-ixp4xx/platform.h
345 ===================================================================
346 --- linux-2.6.20-rc3.orig/include/asm-arm/arch-ixp4xx/platform.h
347 +++ linux-2.6.20-rc3/include/asm-arm/arch-ixp4xx/platform.h
348 @@ -86,6 +86,21 @@
349         unsigned long scl_pin;
350  };
351  
352 +struct dl_block {
353 +       u32 type;
354 +        u32 offset;
355 +};
356 +
357 +struct dl_image {
358 +       u32 magic;
359 +       u32 id;
360 +       u32 size;
361 +       union {
362 +               u32 data[0];
363 +               struct dl_block block[0];
364 +       } u;
365 +};
366 +
367  struct npe_plat_data {
368         const char *name;
369         int data_size;
370 @@ -105,6 +120,10 @@
371  
372  };
373  
374 +struct npe_ucode_platform_data {
375 +       unsigned char *mtd_partition;
376 +};
377
378  /*
379   * This structure provide a means for the board setup code
380   * to give information to th pata_ixp4xx driver. It is
381 Index: linux-2.6.20-rc3/include/linux/ixp_npe.h
382 ===================================================================
383 --- linux-2.6.20-rc3.orig/include/linux/ixp_npe.h
384 +++ linux-2.6.20-rc3/include/linux/ixp_npe.h
385 @@ -99,6 +99,7 @@
386  
387  extern struct device *get_npe_by_id(int id);
388  extern void return_npe_dev(struct device *dev);
389 +extern int store_npe_image(struct dl_image *image, struct device *dev);
390  
391  /* NPE Messages */
392  extern int