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