Commit 3fd08217 authored by Manohar Vanga's avatar Manohar Vanga

Added wishbone (bus + test drv) and fw generator

Signed-off-by: 's avatarManohar Vanga <manohar.vanga@gmail.com>
parents
all: wb_fw
wb_fw: firmware.o
gcc firmware.o -o wb_fw
clean:
rm -rf wb_fw *.o
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define PRIORITY(flag) ((flag >> 28) & 0xf)
#define CLASS(flag) ((flag >> 16) & 0xfff)
#define VERSION(flag) (flag & 0xffff)
struct wb_id {
uint32_t vendor;
uint16_t device;
uint16_t subdevice;
uint32_t flags;
} __attribute__((aligned(1024)));
int main(int argc, char *argv[])
{
if (argc != 3) {
printf("usage: %s <device-list-file> <fw-file>\n", argv[0]);
return 1;
}
FILE *fin, *fout;
char buf[128];
fin = fopen(argv[1], "r");
if (!fin)
return 1;
fout = fopen(argv[2], "w");
if (!fout) {
fclose(fin);
return 1;
}
struct wb_id id;
int num = 0;
while (fgets(buf, 128, fin) != NULL) {
if (buf[0] == '#')
continue;
int priority, class, version;
sscanf(buf, "%d %d %d %d %d %d\n", &id.vendor, &id.device,
&id.subdevice, &priority, &class, &version);
printf("Device:\n\tVendor: %d\n\tDevice: %d\n\tSubdevice: %d\n\tPriority: %d\n\tClass: %d\n\tVersion: %d\n", id.vendor, id.device, id.subdevice, priority & 0xf, class & 0xfff, version & 0xffff);
fwrite((void *)&id, sizeof(struct wb_id), 1, fout);
num++;
}
memset(&id, 0, sizeof(struct wb_id));
while (num++ < 4096)
fwrite((void *)&id, sizeof(struct wb_id), 1, fout);
fclose(fin);
fclose(fout);
return 0;
}
#Vendor Device Subdevice Priority Class Version
1 2 3 4 5 6
10 11 12 13 14 15
#!/bin/bash
if [ "$#" != "3" ]; then
echo "usage: $0 <driver> <firmware>"
exit 1
fi
DEVNAME=$1
FIRMWARE_FNAME=$2
if [ ! -f /sys/class/firmware/$DEVNAME ]; then
echo "Failed to load firmware (sysfs files missing). Check driver"
exit
fi
if [ -f $FIRMWARE_FNAME ]; then
echo 1 > /sys/class/firmware/$DEVNAME/loading
cat $FIRMWARE_FNAME > /sys/class/firmware/$DEVNAME/data
echo 0 > /sys/class/firmware/$DEVNAME/loading
echo "Firmware loaded"
else
echo -1 > /sys/class/firmware/$DEVNAME/loading
echo "Failed to load firmware. File $FIRMWARE_FNAME not found"
fi
obj-m += wb.o
EXTRA_CFLAGS += -Wall
#KERNEL_DIR=/lib/modules/$(shell uname -r)/build
KERNEL_DIR=/home/mvanga/dev/cern/linux/linux-torvalds
all:
make -C $(KERNEL_DIR) M=$(PWD) modules
clean:
make -C $(KERNEL_DIR) M=$(PWD) clean
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include "wb.h"
#define PFX "wb: "
struct device wb_dev;
struct bus_type wb_bus_type;
static ssize_t show_version(struct device_driver *driver, char *buf)
{
struct wb_driver *wbdrv = to_wb_driver(driver);
sprintf(buf, "%s\n", wbdrv->version);
return strlen(buf);
}
static void wb_dev_release(struct device *dev)
{
printk(KERN_DEBUG PFX "release\n");
}
/*
* Register a Wishbone peripheral on the bus.
*/
int wb_register_device(struct wb_device *wbdev)
{
/* TODO: race condition with devno possible */
static unsigned int devno = 1;
wbdev->dev.bus = &wb_bus_type;
wbdev->dev.parent = &wb_dev;
wbdev->dev.release = wb_dev_release;
dev_set_name(&wbdev->dev, "wb%d", devno++);
return device_register(&wbdev->dev);
}
//EXPORT_SYMBOL(wb_register_device);
/*
* Register a Wishbone driver
*/
int wb_register_driver(struct wb_driver *driver)
{
int ret;
driver->driver.bus = &wb_bus_type;
driver->driver.name = driver->version;
ret = driver_register(&driver->driver);
if (ret)
return ret;
driver->version_attr.attr.name = "version";
// driver->version_attr.attr.owner = driver->owner;
driver->version_attr.attr.mode = S_IRUGO;
driver->version_attr.show = show_version;
driver->version_attr.store = NULL;
return driver_create_file(&driver->driver, &driver->version_attr);
}
EXPORT_SYMBOL(wb_register_driver);
void wb_unregister_driver(struct wb_driver *driver)
{
driver_remove_file(&driver->driver, &driver->version_attr);
driver_unregister(&driver->driver);
}
EXPORT_SYMBOL(wb_unregister_driver);
struct wb_device_id *wb_match_device(struct wb_driver *drv, struct wb_device *dev)
{
struct wb_device_id *ids;
ids = drv->id_table;
if (ids) {
while (ids->vendor || ids->device || ids->subdevice) {
if ((ids->vendor == WBONE_ANY_ID || ids->vendor == dev->vendor) &&
(ids->device == WBONE_ANY_ID || ids->device == dev->device) &&
(ids->subdevice == WBONE_ANY_ID || ids->subdevice == dev->subdevice))
return ids;
}
ids++;
}
return NULL;
}
static int wb_bus_match(struct device *dev, struct device_driver *drv)
{
struct wb_device *wb_dev;
struct wb_driver *wb_drv;
struct wb_device_id *found;
wb_dev = to_wb_device(dev);
wb_drv = to_wb_driver(drv);
found = wb_match_device(wb_drv, wb_dev);
if (found) {
wb_dev->driver = wb_drv;
return 1;
}
return 0;
}
static int wb_bus_probe(struct device *dev)
{
struct wb_driver *wb_drv;
struct wb_device *wb_dev;
wb_dev = to_wb_device(dev);
wb_drv = wb_dev->driver;
if (wb_drv && wb_drv->probe)
return wb_drv->probe(wb_dev);
return 0;
}
static int wb_bus_remove(struct device *dev)
{
struct wb_driver *wb_drv;
struct wb_device *wb_dev;
wb_dev = to_wb_device(dev);
wb_drv = wb_dev->driver;
if (wb_drv && wb_drv->remove)
return wb_drv->remove(wb_dev);
return 0;
}
static void wb_bus_shutdown(struct device *dev)
{
struct wb_driver *wb_drv;
struct wb_device *wb_dev;
wb_dev = to_wb_device(dev);
wb_drv = wb_dev->driver;
if (wb_drv && wb_drv->shutdown)
wb_drv->shutdown(wb_dev);
return;
}
static int wb_bus_suspend(struct device *dev, pm_message_t state)
{
return 0;
}
static int wb_bus_resume(struct device *dev)
{
return 0;
}
struct device wb_dev = {
.init_name = "wb0",
.release = wb_dev_release,
};
struct bus_type wb_bus_type = {
.name = "wb",
.match = wb_bus_match,
.probe = wb_bus_probe,
.remove = wb_bus_remove,
.shutdown = wb_bus_shutdown,
.suspend = wb_bus_suspend,
.resume = wb_bus_resume,
};
int wb_init(void)
{
int ret;
ret = bus_register(&wb_bus_type);
if (ret)
return ret;
ret = device_register(&wb_dev);
if (ret) {
bus_unregister(&wb_bus_type);
return ret;
}
return 0;
}
void wb_exit(void)
{
device_unregister(&wb_dev);
bus_unregister(&wb_bus_type);
}
module_init(wb_init)
module_exit(wb_exit)
MODULE_AUTHOR("Manohar Vanga");
MODULE_DESCRIPTION("Virtual or Vanga bus depending on how cocky I'm feeling");
MODULE_LICENSE("GPL");
#ifndef LINUX_BUS_VBUS_H
#define LINUX_BUS_VBUS_H
#include <linux/device.h>
#include <linux/pm.h>
#include <linux/types.h>
#define WBONE_ANY_ID (~0)
struct wb_device;
struct wb_device_id {
__u32 vendor; /* Vendor or WBONE_ANY_ID */
__u16 device; /* Device ID or WBONE_ANY_ID */
__u16 subdevice; /* Device ID or WBONE_ANY_ID */
};
struct wb_driver {
char *version;
struct module *owner;
struct wb_device_id *id_table;
int (*probe)(struct wb_device *);
int (*remove)(struct wb_device *);
void (*shutdown)(struct wb_device *);
struct dev_pm_ops ops;
struct device_driver driver;
struct driver_attribute version_attr;
};
#define to_wb_driver(drv) container_of(drv, struct wb_driver, driver);
struct wb_device {
char *name;
unsigned int vendor;
unsigned short device;
unsigned short subdevice;
unsigned int flags; /* LSB to MSB: 4 bits priority, 12 bits class,
16 bits version */
struct wb_driver *driver;
struct device dev;
};
#define to_wb_device(dev) container_of(dev, struct wb_device, dev);
//int wb_register_device(struct wb_device *wbdev); /* not public */
int wb_register_driver(struct wb_driver *driver);
void wb_unregister_driver(struct wb_driver *driver);
#endif
obj-m += wbtest.o
#KERNEL_DIR=/lib/modules/$(shell uname -r)/build
KERNEL_DIR=/home/mvanga/dev/cern/linux/linux-torvalds
all:
make -C $(KERNEL_DIR) M=$(PWD) modules
clean:
make -C $(KERNEL_DIR) M=$(PWD) clean
#include "../wb.h"
int wbtest_match(struct device *dev)
{
struct wb_device *wbdev = to_wb_device(dev);
printk("vendor :%d\n", wbdev->vendor);
return 0;
}
struct wb_device_id wbtest_ids[] = {
{ WBONE_ANY_ID, WBONE_ANY_ID, WBONE_ANY_ID },
{ 0, },
};
struct wb_driver wbtest_driver = {
.version = "wbtest",
.owner = THIS_MODULE,
.id_table = wbtest_ids,
};
int wbtest_init(void)
{
int ret;
ret = wb_register_driver(&wbtest_driver);
if (ret < 0)
return ret;
return 0;
}
void wbtest_exit(void)
{
wb_unregister_driver(&wbtest_driver);
}
module_init(wbtest_init);
module_exit(wbtest_exit);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment