2007-05-23 22:48:34 +03:00
|
|
|
---
|
|
|
|
drivers/net/ixp4xx/Kconfig | 10 +
|
|
|
|
drivers/net/ixp4xx/Makefile | 1
|
|
|
|
drivers/net/ixp4xx/npe_ucode.c | 185 +++++++++++++++++++++++++++++++++
|
|
|
|
drivers/net/ixp4xx/ucode_dl.c | 43 ++++---
|
|
|
|
include/asm-arm/arch-ixp4xx/platform.h | 19 +++
|
|
|
|
include/linux/ixp_npe.h | 1
|
|
|
|
6 files changed, 239 insertions(+), 20 deletions(-)
|
|
|
|
|
|
|
|
Index: linux-2.6.20-rc3/drivers/net/ixp4xx/Kconfig
|
|
|
|
===================================================================
|
|
|
|
--- linux-2.6.20-rc3.orig/drivers/net/ixp4xx/Kconfig
|
|
|
|
+++ linux-2.6.20-rc3/drivers/net/ixp4xx/Kconfig
|
|
|
|
@@ -11,6 +11,7 @@
|
2006-12-18 03:57:04 +02:00
|
|
|
tristate "IXP4xx NPE support"
|
|
|
|
depends on ARCH_IXP4XX
|
|
|
|
depends on NET_ETHERNET
|
|
|
|
+ select CRC16
|
|
|
|
help
|
|
|
|
The IXP4XX NPE driver supports the 3 CPU co-processors called
|
|
|
|
"Network Processing Engines" (NPE). It adds support fo downloading
|
2007-05-23 22:48:34 +03:00
|
|
|
@@ -18,7 +19,7 @@
|
2006-12-18 03:57:04 +02:00
|
|
|
More about this at: Documentation/networking/ixp4xx/README.
|
|
|
|
You can either use this OR the Intel Access Library (IAL)
|
|
|
|
|
|
|
|
-config IXP4XX_FW_LOAD
|
|
|
|
+config IXP4XX_NPE_FW_LOAD
|
|
|
|
bool "Use Firmware hotplug for Microcode download"
|
|
|
|
depends on IXP4XX_NPE
|
|
|
|
select HOTPLUG
|
2007-05-23 22:48:34 +03:00
|
|
|
@@ -28,6 +29,13 @@
|
2006-12-18 03:57:04 +02:00
|
|
|
/usr/lib/hotplug/firmware/NPE-[ABC]
|
|
|
|
see Documentation/firmware_class/hotplug-script
|
|
|
|
|
|
|
|
+config IXP4XX_NPE_FW_MTD
|
|
|
|
+ bool "Load firmware from an mtd partition"
|
|
|
|
+ depends on IXP4XX_NPE && MTD_IXP4XX
|
|
|
|
+ help
|
|
|
|
+ With this option, the driver will search for
|
|
|
|
+ the firmware into an MTD partition.
|
|
|
|
+
|
|
|
|
config IXP4XX_MAC
|
|
|
|
tristate "IXP4xx MAC support"
|
|
|
|
depends on IXP4XX_NPE
|
2007-05-23 22:48:34 +03:00
|
|
|
Index: linux-2.6.20-rc3/drivers/net/ixp4xx/Makefile
|
|
|
|
===================================================================
|
|
|
|
--- linux-2.6.20-rc3.orig/drivers/net/ixp4xx/Makefile
|
|
|
|
+++ linux-2.6.20-rc3/drivers/net/ixp4xx/Makefile
|
2007-03-04 01:12:34 +02:00
|
|
|
@@ -1,5 +1,6 @@
|
2006-12-18 03:57:04 +02:00
|
|
|
obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o
|
|
|
|
obj-$(CONFIG_IXP4XX_NPE) += ixp4xx_npe.o
|
|
|
|
+obj-$(CONFIG_IXP4XX_NPE_FW_MTD) += npe_ucode.o
|
2007-03-04 01:12:34 +02:00
|
|
|
obj-$(CONFIG_IXP4XX_MAC) += ixp4xx_mac.o
|
|
|
|
obj-$(CONFIG_IXP4XX_CRYPTO) += ixp4xx_crypto.o
|
2006-12-18 03:57:04 +02:00
|
|
|
|
2007-05-23 22:48:34 +03:00
|
|
|
Index: linux-2.6.20-rc3/drivers/net/ixp4xx/npe_ucode.c
|
|
|
|
===================================================================
|
|
|
|
--- /dev/null
|
|
|
|
+++ linux-2.6.20-rc3/drivers/net/ixp4xx/npe_ucode.c
|
2006-12-18 03:57:04 +02:00
|
|
|
@@ -0,0 +1,185 @@
|
|
|
|
+/*
|
|
|
|
+ * Provide an NPE platform device for microcode handling
|
|
|
|
+ *
|
|
|
|
+ * Copyright (C) 2006 Christian Hohnstaedt <chohnstaedt@innominate.com>
|
|
|
|
+ *
|
|
|
|
+ * This file is released under the GPLv2
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include <linux/kernel.h>
|
|
|
|
+#include <linux/platform_device.h>
|
|
|
|
+#include <linux/init.h>
|
|
|
|
+#include <linux/slab.h>
|
|
|
|
+#include <linux/firmware.h>
|
|
|
|
+#include <linux/mtd/mtd.h>
|
|
|
|
+
|
|
|
|
+#include <linux/ixp_npe.h>
|
|
|
|
+
|
|
|
|
+#define DL_MAGIC 0xfeedf00d
|
|
|
|
+#define DL_MAGIC_SWAP 0x0df0edfe
|
|
|
|
+
|
|
|
|
+#define IMG_SIZE(image) (((image)->size * sizeof(u32)) + \
|
|
|
|
+ sizeof(struct dl_image))
|
|
|
|
+
|
|
|
|
+#define IMG_REV_MAJOR(id) (((id) >> 8) & 0x0f)
|
|
|
|
+#define IMG_REV_MINOR(id) ((id) & 0x0f)
|
|
|
|
+#define IMG_FUNC(id) (((id) >> 16) & 0xff)
|
|
|
|
+#define IMG_NPE(id) (((id) >> 24) & 0x0f)
|
|
|
|
+#define IMG_IXP(id) (((id) >> 28) & 0x0f)
|
|
|
|
+
|
|
|
|
+static struct platform_driver ixp4xx_npe_ucode_driver;
|
|
|
|
+static unsigned char *partition_name = NULL;
|
|
|
|
+
|
|
|
|
+static void print_image_info(u32 id, u32 offset, u32 size)
|
|
|
|
+{
|
|
|
|
+ unsigned char idx;
|
|
|
|
+ const char *names[] = { "IXP425", "IXP465", "unknown" };
|
|
|
|
+
|
|
|
|
+ idx = IMG_IXP(id) < 2 ? IMG_IXP(id) : 2;
|
|
|
|
+
|
|
|
|
+ printk(KERN_INFO "npe: found at 0x%x, %s/NPE-%c func: %02x, rev: %x.%x, "
|
|
|
|
+ "size: %5d, id: %08x\n", offset, names[idx], IMG_NPE(id) + 'A',
|
|
|
|
+ IMG_FUNC(id), IMG_REV_MAJOR(id), IMG_REV_MINOR(id), size, id);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void npe_swap_image(struct dl_image *image)
|
|
|
|
+{
|
|
|
|
+ unsigned int i;
|
|
|
|
+
|
|
|
|
+ image->magic = swab32(image->magic);
|
|
|
|
+ image->id = swab32(image->id);
|
|
|
|
+ image->size = swab32(image->size);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < image->size; i++)
|
|
|
|
+ image->u.data[i] = swab32(image->u.data[i]);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void npe_find_microcode(struct mtd_info *mtd)
|
|
|
|
+{
|
|
|
|
+ u32 buf;
|
|
|
|
+ u32 magic = htonl(DL_MAGIC);
|
|
|
|
+ u32 id, size;
|
|
|
|
+ size_t retlen;
|
|
|
|
+ int err;
|
|
|
|
+ unsigned int offset = 0;
|
|
|
|
+
|
|
|
|
+ printk("npe: searching for firmware...\n");
|
|
|
|
+
|
|
|
|
+ while (offset < mtd->size) {
|
|
|
|
+
|
|
|
|
+ err = mtd->read(mtd, offset, 4, &retlen, (u_char *) &buf);
|
|
|
|
+ offset += retlen;
|
|
|
|
+
|
|
|
|
+ if (buf != magic)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ err = mtd->read(mtd, offset, 4, &retlen, (u_char *) &id);
|
|
|
|
+ offset += retlen;
|
|
|
|
+
|
|
|
|
+ if (id == magic)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ id = ntohl(id);
|
|
|
|
+
|
|
|
|
+ err = mtd->read(mtd, offset, 4, &retlen, (u_char *) &size);
|
|
|
|
+ offset += retlen;
|
|
|
|
+
|
|
|
|
+ size = (ntohl(size) * 4) + 12;
|
|
|
|
+
|
|
|
|
+ print_image_info(id, offset - 12, size);
|
|
|
|
+
|
|
|
|
+ if (size < 24000 && ( IMG_FUNC(id) == 0x01 || IMG_FUNC(id) == 0x00) ) { // XXX fix size/detection
|
|
|
|
+
|
|
|
|
+ struct dl_image *image = kmalloc(size, GFP_KERNEL);
|
|
|
|
+
|
|
|
|
+ /* we are going to load it, rewind offset */
|
|
|
|
+ offset -= 12;
|
|
|
|
+
|
|
|
|
+ if (image) {
|
|
|
|
+ err = mtd->read(mtd, offset, size, &retlen, (u_char *) image);
|
|
|
|
+
|
|
|
|
+ if (err == 0 && retlen == size) {
|
|
|
|
+ if (image->magic == DL_MAGIC_SWAP)
|
|
|
|
+ npe_swap_image(image);
|
|
|
|
+
|
|
|
|
+ store_npe_image(image, NULL);
|
|
|
|
+ } else {
|
|
|
|
+ printk(KERN_ERR "unable to read firmware\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ kfree(image);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ offset += size;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void npe_flash_add(struct mtd_info *mtd)
|
|
|
|
+{
|
|
|
|
+ if (partition_name == NULL)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (strcmp(mtd->name, partition_name) == 0) {
|
|
|
|
+ npe_find_microcode(mtd);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void npe_flash_remove(struct mtd_info *mtd) {
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct mtd_notifier npe_flash_notifier = {
|
|
|
|
+ .add = npe_flash_add,
|
|
|
|
+ .remove = npe_flash_remove,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static int npe_ucode_probe(struct platform_device *pdev)
|
|
|
|
+{
|
|
|
|
+ struct npe_ucode_platform_data *data = pdev->dev.platform_data;
|
|
|
|
+
|
|
|
|
+ if (partition_name)
|
|
|
|
+ return -EEXIST;
|
|
|
|
+
|
|
|
|
+ if (data && data->mtd_partition) {
|
|
|
|
+ partition_name = data->mtd_partition;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return -EINVAL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int npe_ucode_remove(struct platform_device *pdev)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct platform_driver ixp4xx_npe_ucode_driver = {
|
|
|
|
+ .driver = {
|
|
|
|
+ .name = "ixp4xx_npe_ucode",
|
|
|
|
+ .owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .probe = npe_ucode_probe,
|
|
|
|
+ .remove = npe_ucode_remove,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static int __init npe_ucode_init(void)
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = platform_driver_register(&ixp4xx_npe_ucode_driver);
|
|
|
|
+ register_mtd_user(&npe_flash_notifier);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void __exit npe_ucode_exit(void)
|
|
|
|
+{
|
|
|
|
+ unregister_mtd_user(&npe_flash_notifier);
|
|
|
|
+ platform_driver_unregister(&ixp4xx_npe_ucode_driver);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+module_init(npe_ucode_init);
|
|
|
|
+module_exit(npe_ucode_exit);
|
|
|
|
+
|
|
|
|
+MODULE_LICENSE("GPL");
|
|
|
|
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
|
2007-05-23 22:48:34 +03:00
|
|
|
Index: linux-2.6.20-rc3/drivers/net/ixp4xx/ucode_dl.c
|
|
|
|
===================================================================
|
|
|
|
--- linux-2.6.20-rc3.orig/drivers/net/ixp4xx/ucode_dl.c
|
|
|
|
+++ linux-2.6.20-rc3/drivers/net/ixp4xx/ucode_dl.c
|
2006-12-18 03:57:04 +02:00
|
|
|
@@ -16,6 +16,7 @@
|
|
|
|
#include <linux/firmware.h>
|
|
|
|
#include <linux/dma-mapping.h>
|
|
|
|
#include <linux/byteorder/swab.h>
|
|
|
|
+#include <linux/crc16.h>
|
|
|
|
#include <asm/uaccess.h>
|
|
|
|
#include <asm/io.h>
|
|
|
|
|
2007-03-04 01:12:34 +02:00
|
|
|
@@ -26,6 +27,12 @@
|
|
|
|
#define DL_MAGIC 0xfeedf00d
|
|
|
|
#define DL_MAGIC_SWAP 0x0df0edfe
|
2006-12-18 03:57:04 +02:00
|
|
|
|
|
|
|
+#define IMG_REV_MAJOR(id) (((id) >> 8) & 0x0f)
|
|
|
|
+#define IMG_REV_MINOR(id) ((id) & 0x0f)
|
|
|
|
+#define IMG_FUNC(id) (((id) >> 16) & 0xff)
|
|
|
|
+#define IMG_NPE(id) (((id) >> 24) & 0x0f)
|
|
|
|
+#define IMG_IXP(id) (((id) >> 28) & 0x0f)
|
|
|
|
+
|
2007-03-04 01:12:34 +02:00
|
|
|
#define EOF_BLOCK 0xf
|
|
|
|
#define IMG_SIZE(image) (((image)->size * sizeof(u32)) + \
|
|
|
|
sizeof(struct dl_image))
|
2007-05-23 22:48:34 +03:00
|
|
|
@@ -38,21 +45,6 @@
|
2006-12-18 03:57:04 +02:00
|
|
|
data,
|
|
|
|
};
|
|
|
|
|
|
|
|
-struct dl_block {
|
|
|
|
- u32 type;
|
|
|
|
- u32 offset;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-struct dl_image {
|
|
|
|
- u32 magic;
|
|
|
|
- u32 id;
|
|
|
|
- u32 size;
|
|
|
|
- union {
|
|
|
|
- u32 data[0];
|
|
|
|
- struct dl_block block[0];
|
|
|
|
- } u;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
struct dl_codeblock {
|
|
|
|
u32 npe_addr;
|
|
|
|
u32 size;
|
2007-05-23 22:48:34 +03:00
|
|
|
@@ -127,20 +119,33 @@
|
2007-03-04 01:12:34 +02:00
|
|
|
return 0;
|
2006-12-18 03:57:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
-static int store_npe_image(struct dl_image *image, struct device *dev)
|
|
|
|
+int store_npe_image(struct dl_image *image, struct device *dev)
|
|
|
|
{
|
|
|
|
struct dl_block *blk;
|
|
|
|
struct dl_codeblock *cb;
|
|
|
|
struct npe_info *npe;
|
2007-03-04 01:12:34 +02:00
|
|
|
int ret=0;
|
2006-12-18 03:57:04 +02:00
|
|
|
+ u16 crc;
|
|
|
|
|
|
|
|
if (!dev) {
|
|
|
|
- dev = get_npe_by_id( (image->id >> 24) & 0xf);
|
|
|
|
+ dev = get_npe_by_id(IMG_NPE(image->id));
|
2007-03-04 01:12:34 +02:00
|
|
|
return_npe_dev(dev);
|
2006-12-18 03:57:04 +02:00
|
|
|
}
|
|
|
|
if (!dev)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ if (image->size > 24000) { // XXX fix max size
|
|
|
|
+ printk(KERN_ERR "npe: firmware too large\n");
|
|
|
|
+ return -EFBIG;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (IMG_REV_MAJOR(image->id) != 2) {
|
|
|
|
+ printk(KERN_ERR "npe: only revision 2 is supported at this time\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ crc = crc16(0, (u8 *) image, IMG_SIZE(image));
|
|
|
|
+
|
|
|
|
npe = dev_get_drvdata(dev);
|
2007-03-04 01:12:34 +02:00
|
|
|
if (npe->loaded && (npe->usage > 0)) {
|
2006-12-18 03:57:04 +02:00
|
|
|
printk(KERN_INFO "Cowardly refusing to reload an Image "
|
2007-05-23 22:48:34 +03:00
|
|
|
@@ -267,8 +272,7 @@
|
2006-12-18 03:57:04 +02:00
|
|
|
|
|
|
|
static void npe_firmware_probe(struct device *dev)
|
|
|
|
{
|
|
|
|
-#if (defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)) \
|
|
|
|
- && defined(MODULE)
|
|
|
|
+#ifdef CONFIG_IXP4XX_NPE_FW_LOADER
|
|
|
|
const struct firmware *fw_entry;
|
|
|
|
struct npe_info *npe = dev_get_drvdata(dev);
|
|
|
|
struct dl_image *image;
|
2007-05-23 22:48:34 +03:00
|
|
|
@@ -477,3 +481,4 @@
|
2006-12-18 03:57:04 +02:00
|
|
|
|
|
|
|
EXPORT_SYMBOL(get_npe_by_id);
|
2007-03-04 01:12:34 +02:00
|
|
|
EXPORT_SYMBOL(return_npe_dev);
|
2006-12-18 03:57:04 +02:00
|
|
|
+EXPORT_SYMBOL(store_npe_image);
|
2007-05-23 22:48:34 +03:00
|
|
|
Index: linux-2.6.20-rc3/include/asm-arm/arch-ixp4xx/platform.h
|
|
|
|
===================================================================
|
|
|
|
--- linux-2.6.20-rc3.orig/include/asm-arm/arch-ixp4xx/platform.h
|
|
|
|
+++ linux-2.6.20-rc3/include/asm-arm/arch-ixp4xx/platform.h
|
|
|
|
@@ -86,6 +86,21 @@
|
|
|
|
unsigned long scl_pin;
|
|
|
|
};
|
2006-12-18 03:57:04 +02:00
|
|
|
|
|
|
|
+struct dl_block {
|
|
|
|
+ u32 type;
|
|
|
|
+ u32 offset;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+struct dl_image {
|
|
|
|
+ u32 magic;
|
|
|
|
+ u32 id;
|
|
|
|
+ u32 size;
|
|
|
|
+ union {
|
|
|
|
+ u32 data[0];
|
|
|
|
+ struct dl_block block[0];
|
|
|
|
+ } u;
|
|
|
|
+};
|
2007-03-04 01:12:34 +02:00
|
|
|
+
|
2006-12-18 03:57:04 +02:00
|
|
|
struct npe_plat_data {
|
|
|
|
const char *name;
|
|
|
|
int data_size;
|
2007-05-23 22:48:34 +03:00
|
|
|
@@ -105,6 +120,10 @@
|
2007-03-04 01:12:34 +02:00
|
|
|
|
2006-12-18 03:57:04 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
+struct npe_ucode_platform_data {
|
|
|
|
+ unsigned char *mtd_partition;
|
|
|
|
+};
|
2007-03-04 01:12:34 +02:00
|
|
|
+
|
|
|
|
/*
|
2007-05-23 22:48:34 +03:00
|
|
|
* This structure provide a means for the board setup code
|
|
|
|
* to give information to th pata_ixp4xx driver. It is
|
|
|
|
Index: linux-2.6.20-rc3/include/linux/ixp_npe.h
|
|
|
|
===================================================================
|
|
|
|
--- linux-2.6.20-rc3.orig/include/linux/ixp_npe.h
|
|
|
|
+++ linux-2.6.20-rc3/include/linux/ixp_npe.h
|
|
|
|
@@ -99,6 +99,7 @@
|
2006-12-18 03:57:04 +02:00
|
|
|
|
|
|
|
extern struct device *get_npe_by_id(int id);
|
2007-03-04 01:12:34 +02:00
|
|
|
extern void return_npe_dev(struct device *dev);
|
2006-12-18 03:57:04 +02:00
|
|
|
+extern int store_npe_image(struct dl_image *image, struct device *dev);
|
|
|
|
|
|
|
|
/* NPE Messages */
|
|
|
|
extern int
|