Skip to content
Snippets Groups Projects
Verified Commit 060a392d authored by Moritz Lammerich's avatar Moritz Lammerich
Browse files

get basic device enumeration + module loading working

parent 96e86e33
Branches
No related tags found
No related merge requests found
obj-m := zt_flink_axi.o zt_flink_bus.o
obj-m := zt_flink_axi.o zt_flink_bus.o zt_flink_info.o
zt_flink_axi-objs := axi.o
zt_flink_bus-objs := bus.o
zt_flink_info-objs := drivers/info.o
SRC := $(shell pwd)
......
......@@ -94,17 +94,13 @@ static int __init
zt_flink_axi_init(void)
{
pr_info("ZT Flink AXI init\n");
int ret = platform_driver_register(&zt_flink_axi_driver);
if (ret < 0) {
pr_err("ZT Flink AXI failed to register platform driver: %d\n", -ret);
return ret;
}
ret = platform_device_register(&zt_flink_axi_device);
if (ret < 0) {
pr_err("ZT Flink AXI failed to register device: %d\n", -ret);
platform_driver_unregister(&zt_flink_axi_driver);
return ret;
}
pr_info("ZT Flink AXI initialized successfully\n");
return 0;
}
......
#include <linux/err.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device/bus.h>
#include <linux/device/driver.h>
#include <linux/fs.h>
#include "linux/dev_printk.h"
#include "linux/device.h"
#include "linux/export.h"
#include "linux/gfp_types.h"
#include "linux/kobject.h"
#include "linux/list.h"
#include "linux/printk.h"
#include "zt-flink.h"
static dev_t zt_flink_device_type;
static struct class* zt_flink_class;
int zt_flink_device_match(struct device* dev, struct device_driver* drv);
int zt_flink_device_probe(struct device* dev);
void zt_flink_device_remove(struct device* dev);
void zt_flink_device_shutdown(struct device* dev);
int zt_flink_uevent(const struct device* dev, struct kobj_uevent_env* env);
struct bus_type zt_flink_bus_type
= {
......@@ -24,12 +32,14 @@ struct bus_type zt_flink_bus_type
.probe = zt_flink_device_probe,
.remove = zt_flink_device_remove,
.shutdown = zt_flink_device_shutdown,
.uevent = zt_flink_uevent,
};
static LIST_HEAD(zt_flink_controller_list);
int zt_flink_driver_register(struct zt_flink_driver* driver)
{
pr_info("ZT Flink registering driver %s for id %d", driver->name, driver->id);
driver->driver.bus = &zt_flink_bus_type;
return driver_register(&driver->driver);
}
......@@ -44,6 +54,11 @@ EXPORT_SYMBOL(zt_flink_driver_unregister);
int zt_flink_device_register(struct zt_flink_device* device)
{
device->dev.bus = &zt_flink_bus_type;
int ret = dev_set_name(&device->dev, "zt-flink%d", device->id);
if (ret < 0) {
dev_err(&device->dev, "failed to set name: %d", ret);
return ret;
}
return device_register(&device->dev);
}
EXPORT_SYMBOL(zt_flink_device_register);
......@@ -65,24 +80,59 @@ struct zt_flink_device* zt_flink_device_alloc(struct device* dev, uint32_t id)
}
EXPORT_SYMBOL(zt_flink_device_alloc);
struct zt_flink_controller* zt_flink_controller_alloc(struct device* dev)
struct zt_flink_controller* zt_flink_controller_alloc(struct device* parent_dev)
{
if (!dev)
static int current_dev = 0;
dev_info(parent_dev, "current flink controller index: %d\n", current_dev);
if (!parent_dev) {
pr_err("zt-flink failed to allocate controller: no parent device\n");
return NULL;
struct zt_flink_controller* controller = devm_kzalloc(dev, sizeof(struct zt_flink_controller), GFP_KERNEL);
if (!controller)
}
struct zt_flink_controller* controller = devm_kzalloc(parent_dev, sizeof(struct zt_flink_controller), GFP_KERNEL);
if (!controller) {
dev_err(parent_dev, "failed to allocate controller\n");
return NULL;
}
int ret = alloc_chrdev_region(&zt_flink_device_type, current_dev, 1, "zt-flink");
if (ret < 0) {
pr_err("zt-flink-axi failed to allocate chardev region: %d", ret);
return ret;
}
device_initialize(&controller->dev);
controller->dev.parent = dev;
controller->dev.bus = &zt_flink_bus_type;
controller->cdev.owner = THIS_MODULE;
controller->dev.parent = parent_dev;
controller->dev.class = zt_flink_class;
controller->dev.devt = zt_flink_device_type;
ret = dev_set_name(&controller->dev, "zt-flink-controller%d", current_dev);
if (ret < 0)
dev_err(parent_dev, "failed to set device name: %d\n", ret);
++current_dev;
return controller;
}
EXPORT_SYMBOL(zt_flink_controller_alloc);
static void zt_flink_discover_devices(struct zt_flink_controller* controller)
{
dev_info(&controller->dev, "discovering devices\n");
struct zt_flink_device* ztd = zt_flink_device_alloc(&controller->dev, 0);
if (!ztd) {
dev_err(&controller->dev, "failed to allocate device\n");
}
dev_info(&controller->dev, "allocated device\n");
int ret = zt_flink_device_register(ztd);
dev_info(&controller->dev, "zt_flink_device_register returned %d", ret);
}
int zt_flink_controller_register(struct zt_flink_controller* controller)
{
device_add(&controller->dev);
int ret = device_add(&controller->dev);
if (ret < 0) {
dev_err(&controller->dev, "failed to add device: %d\n", ret);
cdev_del(&controller->cdev);
return ret;
}
list_add_tail(&controller->list, &zt_flink_controller_list);
zt_flink_discover_devices(controller);
return 0;
}
EXPORT_SYMBOL(zt_flink_controller_register);
......@@ -91,33 +141,61 @@ int zt_flink_device_match(struct device* dev, struct device_driver* drv)
{
struct zt_flink_device* zt_flink_dev = to_zt_flink_device(dev);
struct zt_flink_driver* zt_flink_drv = to_zt_flink_driver(drv);
if (zt_flink_dev->id == zt_flink_drv->id)
dev_info(dev, "matching IDs: %d (dev) vs %d (drv)\n", zt_flink_dev->id, zt_flink_drv->id);
if (zt_flink_dev->id == zt_flink_drv->id) {
dev_info(dev, "driver match\n");
return 1;
else
} else {
dev_info(dev, "driver mismatch\n");
return 0;
}
}
int zt_flink_device_probe(struct device* dev)
{
dev_info(dev, "probing\n");
return 0;
}
void zt_flink_device_remove(struct device* dev)
{
dev_info(dev, "removing\n");
}
void zt_flink_device_shutdown(struct device* dev)
{
dev_info(dev, "shutdown\n");
}
int zt_flink_uevent(const struct device* dev, struct kobj_uevent_env* env)
{
struct zt_flink_device* ztd = to_zt_flink_device(dev);
if (add_uevent_var(env, "MODALIAS=flink:%d", ztd->id)) {
dev_err(dev, "Failed to add uevent_var: ENOMEM\n");
return -ENOMEM;
}
return 0;
}
static int __init zt_flink_init(void)
{
zt_flink_class = class_create("zt-flink-class");
int status = bus_register(&zt_flink_bus_type);
if (status < 0)
return status;
return 0;
}
static void __exit zt_flink_exit(void)
{
class_destroy(zt_flink_class);
unregister_chrdev_region(zt_flink_device_type, 1);
}
postcore_initcall(zt_flink_init);
module_exit(zt_flink_exit);
MODULE_LICENSE("Dual MIT/GPL");
#include "../zt-flink.h"
#include "linux/dev_printk.h"
#include "linux/device/driver.h"
#include "linux/module.h"
MODULE_ALIAS("flink:0");
int zt_flink_info_probe(struct zt_flink_device* device);
int zt_flink_info_remove(struct zt_flink_device* device);
static struct zt_flink_driver zt_flink_info_driver = {
.id = 0,
.name = "info",
.driver = {
.name = KBUILD_MODNAME,
.owner = THIS_MODULE,
},
};
int zt_flink_info_probe(struct zt_flink_device* device)
{
dev_info(&device->dev, "probing info\n");
return 0;
}
int zt_flink_info_remove(struct zt_flink_device* device)
{
dev_info(&device->dev, "removing info\n");
return 0;
}
static int zt_flink_info_init(void)
{
pr_info("ZT Flink info init\n");
int ret = zt_flink_driver_register(&zt_flink_info_driver);
if (ret < 0)
pr_err("ZT Flink info failed to register driver: %d\n", -ret);
else
pr_info("ZT Flink info registered driver\n");
return ret;
}
static void zt_flink_info_exit(void)
{
pr_info("ZT Flink info exit\n");
}
MODULE_LICENSE("Dual MIT/GPL");
module_init(zt_flink_info_init);
module_exit(zt_flink_info_exit);
......@@ -2,6 +2,7 @@
#define ZT_FLINK_H_
#include "linux/types.h"
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/device/driver.h>
#include <linux/mod_devicetable.h>
......@@ -16,6 +17,7 @@ struct zt_flink_device {
struct zt_flink_controller {
char name[32];
struct device dev;
struct cdev cdev;
struct list_head list;
uint32_t (*read_register)(uint32_t address, void* private_data);
void (*write_register)(uint32_t address, uint32_t value, void* private_data);
......@@ -23,7 +25,7 @@ struct zt_flink_controller {
void* private_data;
};
struct zt_flink_device_id {
struct ztflink_device_id {
uint32_t id;
kernel_ulong_t driver_data;
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment