Commit 987ce2e8 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

updated to create devices in sysfs

parent 23812050
...@@ -47,9 +47,44 @@ ...@@ -47,9 +47,44 @@
#include "x393_macro.h" #include "x393_macro.h"
//#include "x393_helpers.h" //#include "x393_helpers.h"
static const char * const circbuf_devs[] = {
DEV393_DEVNAME(DEV393_CIRCBUF0),
DEV393_DEVNAME(DEV393_CIRCBUF1),
DEV393_DEVNAME(DEV393_CIRCBUF2),
DEV393_DEVNAME(DEV393_CIRCBUF3),
DEV393_DEVNAME(DEV393_JPEGHEAD0),
DEV393_DEVNAME(DEV393_JPEGHEAD1),
DEV393_DEVNAME(DEV393_JPEGHEAD2),
DEV393_DEVNAME(DEV393_JPEGHEAD3),
DEV393_DEVNAME(DEV393_HUFFMAN0),
DEV393_DEVNAME(DEV393_HUFFMAN1),
DEV393_DEVNAME(DEV393_HUFFMAN2),
DEV393_DEVNAME(DEV393_HUFFMAN3)
};
static const int circbuf_major = DEV393_MAJOR(DEV393_CIRCBUF0);
static const int circbuf_minor[] = {
DEV393_MINOR(DEV393_CIRCBUF0),
DEV393_MINOR(DEV393_CIRCBUF1),
DEV393_MINOR(DEV393_CIRCBUF2),
DEV393_MINOR(DEV393_CIRCBUF3),
DEV393_MINOR(DEV393_JPEGHEAD0),
DEV393_MINOR(DEV393_JPEGHEAD1),
DEV393_MINOR(DEV393_JPEGHEAD2),
DEV393_MINOR(DEV393_JPEGHEAD3),
DEV393_MINOR(DEV393_HUFFMAN0),
DEV393_MINOR(DEV393_HUFFMAN1),
DEV393_MINOR(DEV393_HUFFMAN2),
DEV393_MINOR(DEV393_HUFFMAN3)
};
/** @brief Driver name displayed in system logs */ /** @brief Driver name displayed in system logs */
//#define CIRCBUF_DRIVER_NAME "circbuf driver" //#define CIRCBUF_DRIVER_NAME "circbuf driver"
/** device class */
static struct class *circbuf_dev_class;
/** @brief Wait queue for the processes waiting for a new frame to appear in the circular buffer. Each channel has /** @brief Wait queue for the processes waiting for a new frame to appear in the circular buffer. Each channel has
* its own instance of wait queue to prevent race conditions when one channel wakes up the queue while the other * its own instance of wait queue to prevent race conditions when one channel wakes up the queue while the other
* channel is processing interrupt and moved its write pointer, but has not finished all other functions yet. * channel is processing interrupt and moved its write pointer, but has not finished all other functions yet.
...@@ -866,47 +901,69 @@ static struct file_operations circbuf_fops = { ...@@ -866,47 +901,69 @@ static struct file_operations circbuf_fops = {
*/ */
static int circbuf_all_init(struct platform_device *pdev) static int circbuf_all_init(struct platform_device *pdev)
{ {
int res, i; int res, i;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct of_device_id *match; const struct of_device_id *match;
// char device for sensor port
/* sanity check */ struct device *chrdev;
match = of_match_device(elphel393_circbuf_of_match, dev);
if (!match)
return -EINVAL;
dev_dbg(dev, "registering character device with name 'circbuf_operations'");
res = register_chrdev(DEV393_MAJOR(DEV393_CIRCBUF0), "circbuf_operations", &circbuf_fops);
if(res < 0) {
dev_err(dev, "couldn't get a major number %d.\n", DEV393_MAJOR(DEV393_CIRCBUF0));
return res;
}
dev_info(dev, "registered MAJOR: %d\n", DEV393_MAJOR(DEV393_CIRCBUF0));
res = jpeghead_init(pdev); /* sanity check */
if (res < 0) { match = of_match_device(elphel393_circbuf_of_match, dev);
dev_err(dev, "unable to initialize jpeghead module\n"); if (!match)
return res; return -EINVAL;
}
res = image_acq_init(pdev); dev_dbg(dev, "registering character device with name 'circbuf_operations'");
if (res < 0) { res = register_chrdev(DEV393_MAJOR(DEV393_CIRCBUF0), "circbuf_operations", &circbuf_fops);
dev_err(dev, "unable to initialize sensor_common module\n"); if(res < 0) {
return res; dev_err(dev, "couldn't get a major number %d.\n", DEV393_MAJOR(DEV393_CIRCBUF0));
} return res;
res = init_ccam_dma_buf_ptr(pdev); }
if (res < 0) { dev_info(dev, "registered MAJOR: %d\n", DEV393_MAJOR(DEV393_CIRCBUF0));
dev_err(dev, "ERROR allocating coherent DMA buffer\n");
return -ENOMEM;
}
dev_dbg(dev, "initialize circbuf wait queue\n"); // create device class
for (i = 0; i < SENSOR_PORTS; i++) circbuf_dev_class = class_create(THIS_MODULE, DEV393_NAME(DEV393_CIRCBUF0));
init_waitqueue_head(&circbuf_wait_queue[i]); if (IS_ERR(circbuf_dev_class)) {
dev_dbg(dev, "initialize Huffman tables with default data\n"); pr_err("Cannot create \"%s\" class", DEV393_NAME(DEV393_CIRCBUF0));
return PTR_ERR(circbuf_dev_class);
}
// create devices
for (i=0;i<(sizeof(circbuf_minor)/sizeof(int));i++){
chrdev = device_create(
circbuf_dev_class,
&pdev->dev,
MKDEV(circbuf_major, circbuf_minor[i]),
NULL,
"%s",circbuf_devs[i]);
if(IS_ERR(chrdev)){
pr_err("Failed to create a device (circbuf, %d). Error code: %ld\n",i,PTR_ERR(chrdev));
}
}
g_dev_ptr = dev; res = jpeghead_init(pdev);
if (res < 0) {
dev_err(dev, "unable to initialize jpeghead module\n");
return res;
}
res = image_acq_init(pdev);
if (res < 0) {
dev_err(dev, "unable to initialize sensor_common module\n");
return res;
}
res = init_ccam_dma_buf_ptr(pdev);
if (res < 0) {
dev_err(dev, "ERROR allocating coherent DMA buffer\n");
return -ENOMEM;
}
return 0; dev_dbg(dev, "initialize circbuf wait queue\n");
for (i = 0; i < SENSOR_PORTS; i++)
init_waitqueue_head(&circbuf_wait_queue[i]);
dev_dbg(dev, "initialize Huffman tables with default data\n");
g_dev_ptr = dev;
return 0;
} }
/** /**
...@@ -916,8 +973,13 @@ static int circbuf_all_init(struct platform_device *pdev) ...@@ -916,8 +973,13 @@ static int circbuf_all_init(struct platform_device *pdev)
*/ */
static int circbuf_remove(struct platform_device *pdev) static int circbuf_remove(struct platform_device *pdev)
{ {
int i;
for (i=0;i<(sizeof(circbuf_minor)/sizeof(int));i++){
device_destroy(
circbuf_dev_class,
MKDEV(circbuf_major, circbuf_minor[i]));
}
unregister_chrdev(DEV393_MAJOR(DEV393_CIRCBUF0), "circbuf_operations"); unregister_chrdev(DEV393_MAJOR(DEV393_CIRCBUF0), "circbuf_operations");
return 0; return 0;
} }
......
...@@ -164,6 +164,32 @@ static int xi2c_initialized=0; // configure GPIO puins access at first command; ...@@ -164,6 +164,32 @@ static int xi2c_initialized=0; // configure GPIO puins access at first command;
static int i2c_hardware_on=0; // shadow register for FPFA I2C controller static int i2c_hardware_on=0; // shadow register for FPFA I2C controller
#endif #endif
static const char * const xi2c_devs[]={
DEV393_DEVNAME(DEV393_I2C_CTRL),
DEV393_DEVNAME(DEV393_I2C_8_AINC),
DEV393_DEVNAME(DEV393_I2C_16_AINC),
DEV393_DEVNAME(DEV393_I2C1_8_AINC),
DEV393_DEVNAME(DEV393_I2C1_16_AINC),
DEV393_DEVNAME(DEV393_I2C_RAW),
DEV393_DEVNAME(DEV393_I2C1_RAW),
DEV393_DEVNAME(DEV393_I2C_ENABLE)
};
static const int xi2c_major = DEV393_MAJOR(DEV393_I2C_CTRL);
static const int xi2c_minor[]={
DEV393_MINOR(DEV393_I2C_CTRL),
DEV393_MINOR(DEV393_I2C_8_AINC),
DEV393_MINOR(DEV393_I2C_16_AINC),
DEV393_MINOR(DEV393_I2C1_8_AINC),
DEV393_MINOR(DEV393_I2C1_16_AINC),
DEV393_MINOR(DEV393_I2C_RAW),
DEV393_MINOR(DEV393_I2C1_RAW),
DEV393_MINOR(DEV393_I2C_ENABLE)
};
/** @brief Global device class for sysfs */
static struct class *xi2c_dev_class;
//void i2c_disable(int n); //void i2c_disable(int n);
//void i2c_dir_out(int n); //void i2c_dir_out(int n);
...@@ -1360,6 +1386,8 @@ int xi2c_init(struct platform_device *pdev) ...@@ -1360,6 +1386,8 @@ int xi2c_init(struct platform_device *pdev)
{ {
int i,res; int i,res;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
// char device for sensor port
struct device *chrdev;
elphel393_ext_i2c_sysfs_register(pdev); elphel393_ext_i2c_sysfs_register(pdev);
dev_info(dev, DEV393_NAME(DEV393_I2C_CTRL)": registered sysfs\n"); dev_info(dev, DEV393_NAME(DEV393_I2C_CTRL)": registered sysfs\n");
...@@ -1373,6 +1401,26 @@ int xi2c_init(struct platform_device *pdev) ...@@ -1373,6 +1401,26 @@ int xi2c_init(struct platform_device *pdev)
printk(X3X3_I2C_DRIVER_NAME" - %d, %d channels\n",DEV393_MAJOR(DEV393_I2C_CTRL),X3X3_I2C_CHANNELS); printk(X3X3_I2C_DRIVER_NAME" - %d, %d channels\n",DEV393_MAJOR(DEV393_I2C_CTRL),X3X3_I2C_CHANNELS);
// thisminor =0; // thisminor =0;
// create device class
xi2c_dev_class = class_create(THIS_MODULE, DEV393_NAME(DEV393_I2C_CTRL));
if (IS_ERR(xi2c_dev_class)) {
pr_err("Cannot create \"%s\" class", DEV393_NAME(DEV393_I2C_CTRL));
return PTR_ERR(xi2c_dev_class);
}
//create devices
for (i=0;i<(sizeof(xi2c_minor)/sizeof(int));i++){
chrdev = device_create(
xi2c_dev_class,
&pdev->dev,
MKDEV(xi2c_major, xi2c_minor[i]),
NULL,
"%s",xi2c_devs[i]);
if(IS_ERR(chrdev)){
pr_err("Failed to create a device (xi2c %d). Error code: %ld\n",i,PTR_ERR(chrdev));
}
}
elphel393_xi2c_init_of(pdev); elphel393_xi2c_init_of(pdev);
bitdelays[0].scl_high=2; //! SCL high: bitdelays[0].scl_high=2; //! SCL high:
...@@ -1474,6 +1522,12 @@ int xi2c_init(struct platform_device *pdev) ...@@ -1474,6 +1522,12 @@ int xi2c_init(struct platform_device *pdev)
int xi2c_remove(struct platform_device *pdev) int xi2c_remove(struct platform_device *pdev)
{ {
int i;
for (i=0;i<(sizeof(xi2c_minor)/sizeof(int));i++){
device_destroy(
xi2c_dev_class,
MKDEV(xi2c_major, xi2c_minor[i]));
}
unregister_chrdev(DEV393_MAJOR(DEV393_I2C_CTRL), DEV393_NAME(DEV393_I2C_CTRL)); unregister_chrdev(DEV393_MAJOR(DEV393_I2C_CTRL), DEV393_NAME(DEV393_I2C_CTRL));
return 0; return 0;
} }
......
...@@ -15,9 +15,8 @@ ...@@ -15,9 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//#define DEBUG
//copied from cxi2c.c - TODO:remove unneeded //copied from cxi2c.c - TODO:remove unneeded
#include <linux/module.h> #include <linux/module.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -72,6 +71,40 @@ ...@@ -72,6 +71,40 @@
#define X3X3_EXIF_DRIVER_DESCRIPTION "Elphel (R) model 393 Exif device driver" #define X3X3_EXIF_DRIVER_DESCRIPTION "Elphel (R) model 393 Exif device driver"
static const char * const exif393_devs[]={
DEV393_DEVNAME(DEV393_EXIF_TEMPLATE),
DEV393_DEVNAME(DEV393_EXIF_METADIR),
DEV393_DEVNAME(DEV393_EXIF_TIME),
DEV393_DEVNAME(DEV393_EXIF0),
DEV393_DEVNAME(DEV393_EXIF1),
DEV393_DEVNAME(DEV393_EXIF2),
DEV393_DEVNAME(DEV393_EXIF3),
DEV393_DEVNAME(DEV393_EXIF_META0),
DEV393_DEVNAME(DEV393_EXIF_META1),
DEV393_DEVNAME(DEV393_EXIF_META2),
DEV393_DEVNAME(DEV393_EXIF_META3)
};
static const int exif393_major = DEV393_MAJOR(DEV393_EXIF_TEMPLATE);
static const int exif393_minor[]={
DEV393_MINOR(DEV393_EXIF_TEMPLATE),
DEV393_MINOR(DEV393_EXIF_METADIR),
DEV393_MINOR(DEV393_EXIF_TIME),
DEV393_MINOR(DEV393_EXIF0),
DEV393_MINOR(DEV393_EXIF1),
DEV393_MINOR(DEV393_EXIF2),
DEV393_MINOR(DEV393_EXIF3),
DEV393_MINOR(DEV393_EXIF_META0),
DEV393_MINOR(DEV393_EXIF_META1),
DEV393_MINOR(DEV393_EXIF_META2),
DEV393_MINOR(DEV393_EXIF_META3)
};
/** @brief Global device class for sysfs */
static struct class *exif393_dev_class;
/** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */ /** @brief Global pointer to basic device structure. This pointer is used in debugfs output functions */
static struct device *g_devfp_ptr = NULL; static struct device *g_devfp_ptr = NULL;
...@@ -795,17 +828,56 @@ EXPORT_SYMBOL_GPL(exif_get_data); ...@@ -795,17 +828,56 @@ EXPORT_SYMBOL_GPL(exif_get_data);
//!++++++++++++++++++++++++++++++++++++ _init() ++++++++++++++++++++++++++++++++++++++++++++++++++++++ //!++++++++++++++++++++++++++++++++++++ _init() ++++++++++++++++++++++++++++++++++++++++++++++++++++++
static int __init exif_init(void) { static int __init exif_init(void) {
int res; int res, i;
res = register_chrdev(DEV393_MAJOR(DEV393_EXIF0), "Exif", &exif_fops); struct device *chrdev;
//res = register_chrdev(DEV393_MAJOR(DEV393_EXIF0), "Exif", &exif_fops);
res = register_chrdev(DEV393_MAJOR(DEV393_EXIF0), DEV393_NAME(DEV393_EXIF0), &exif_fops);
if(res < 0) { if(res < 0) {
dev_err(g_devfp_ptr,"\nexif_init: couldn't get a major number %d.\n",DEV393_MAJOR(DEV393_EXIF0)); dev_err(g_devfp_ptr,"\nexif_init: couldn't get a major number %d.\n",DEV393_MAJOR(DEV393_EXIF0));
return res; return res;
} }
dev_dbg(g_devfp_ptr,DEV393_NAME(DEV393_EXIF0)" - %d\n",DEV393_MAJOR(DEV393_EXIF0)); dev_dbg(g_devfp_ptr,DEV393_NAME(DEV393_EXIF0)" - %d\n",DEV393_MAJOR(DEV393_EXIF0));
// create device class
exif393_dev_class = class_create(THIS_MODULE, DEV393_NAME(DEV393_EXIF0));
if (IS_ERR(exif393_dev_class)) {
dev_err(g_devfp_ptr,"Cannot create \"%s\" class\n",DEV393_NAME(DEV393_EXIF0));
return PTR_ERR(exif393_dev_class);
}
//create devices
for (i=0;i<(sizeof(exif393_minor)/sizeof(int));i++){
chrdev = device_create(
exif393_dev_class,
NULL,
MKDEV(exif393_major, exif393_minor[i]),
NULL,
"%s",exif393_devs[i]);
if(IS_ERR(chrdev)){
dev_err(g_devfp_ptr,"Failed to create a device (exif393, %d). Error code: %ld\n",i,PTR_ERR(chrdev));
}
}
return 0; return 0;
} }
static void __exit exif_exit(void)
{
int i;
for (i=0;i<(sizeof(exif393_minor)/sizeof(int));i++){
device_destroy(
exif393_dev_class,
MKDEV(exif393_major, exif393_minor[i]));
}
unregister_chrdev(DEV393_MAJOR(DEV393_JTAGS_CONF0), DEV393_NAME(DEV393_JTAGS_CONF0));
dev_dbg(NULL, "unregistering driver");
}
module_exit(exif_exit);
module_init(exif_init); module_init(exif_init);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>."); MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(X3X3_EXIF_DRIVER_DESCRIPTION); MODULE_DESCRIPTION(X3X3_EXIF_DRIVER_DESCRIPTION);
...@@ -118,6 +118,37 @@ port C 353: ...@@ -118,6 +118,37 @@ port C 353:
#define JTAG_MODE_EXTEST 5 // JTAG channel boundary scan - EXTEST (the first operation after open is read) #define JTAG_MODE_EXTEST 5 // JTAG channel boundary scan - EXTEST (the first operation after open is read)
#define JTAG_MODE_RAW 6 // JTAG raw command mode #define JTAG_MODE_RAW 6 // JTAG raw command mode
static const char * const fpgajtag_devs[]={
DEV393_DEVNAME(DEV393_JTAG_RESET),
//DEV393_DEVNAME(DEV393_JTAG_RAW), // create link in udev rule
DEV393_DEVNAME(DEV393_JTAGS_CONF0),
DEV393_DEVNAME(DEV393_JTAGS_CONF1),
DEV393_DEVNAME(DEV393_JTAGS_CONF2),
DEV393_DEVNAME(DEV393_JTAGS_CONF3),
DEV393_DEVNAME(DEV393_JTAGS_BSCAN0),
DEV393_DEVNAME(DEV393_JTAGS_BSCAN1),
DEV393_DEVNAME(DEV393_JTAGS_BSCAN2),
DEV393_DEVNAME(DEV393_JTAGS_BSCAN3)
};
static const int fpgajtag_major = DEV393_MAJOR(DEV393_JTAG_RESET);
static const int fpgajtag_minor[]={
DEV393_MINOR(DEV393_JTAG_RESET),
//DEV393_MINOR(DEV393_JTAG_RAW),
DEV393_MINOR(DEV393_JTAGS_CONF0),
DEV393_MINOR(DEV393_JTAGS_CONF1),
DEV393_MINOR(DEV393_JTAGS_CONF2),
DEV393_MINOR(DEV393_JTAGS_CONF3),
DEV393_MINOR(DEV393_JTAGS_BSCAN0),
DEV393_MINOR(DEV393_JTAGS_BSCAN1),
DEV393_MINOR(DEV393_JTAGS_BSCAN2),
DEV393_MINOR(DEV393_JTAGS_BSCAN3)
};
/** @brief Global device class for sysfs */
static struct class *fpgajtag_dev_class;
// configuration and raw minors use whole buffer, ID and boundary can be opened at the same time // configuration and raw minors use whole buffer, ID and boundary can be opened at the same time
struct JTAG_channel_t { struct JTAG_channel_t {
int mode; // 0..5 -JTAG_MODE_CLOSED...JTAG_MODE_EXTEST int mode; // 0..5 -JTAG_MODE_CLOSED...JTAG_MODE_EXTEST
...@@ -1392,12 +1423,35 @@ int JTAG_EXTEST (int chn, unsigned char * buf, int len) { ...@@ -1392,12 +1423,35 @@ int JTAG_EXTEST (int chn, unsigned char * buf, int len) {
static int __init fpga_jtag_init(void) { static int __init fpga_jtag_init(void) {
int i,res; int i,res;
struct device *chrdev;
res = register_chrdev(DEV393_MAJOR(DEV393_JTAGS_CONF0), fpga_jtag_name, &fpga_jtag_fops); res = register_chrdev(DEV393_MAJOR(DEV393_JTAGS_CONF0), fpga_jtag_name, &fpga_jtag_fops);
if(res < 0) { if(res < 0) {
dev_err(NULL,"\nfpga_jtag_init: couldn't get a major number %d.\n",DEV393_MAJOR(DEV393_JTAGS_CONF0)); dev_err(NULL,"\nfpga_jtag_init: couldn't get a major number %d.\n",DEV393_MAJOR(DEV393_JTAGS_CONF0));
return res; return res;
} }
dev_dbg(NULL,DEV393_NAME(DEV393_JTAGS_CONF0)" - %d\n",DEV393_MAJOR(DEV393_JTAGS_CONF0)); dev_dbg(NULL,DEV393_NAME(DEV393_JTAGS_CONF0)" - %d\n",DEV393_MAJOR(DEV393_JTAGS_CONF0));
// create device class
fpgajtag_dev_class = class_create(THIS_MODULE, DEV393_NAME(DEV393_JTAGS_CONF0));
if (IS_ERR(fpgajtag_dev_class)) {
pr_err("Cannot create \"%s\" class", DEV393_NAME(DEV393_EXIF0));
return PTR_ERR(fpgajtag_dev_class);
}
//create devices
for (i=0;i<(sizeof(fpgajtag_minor)/sizeof(int));i++){
chrdev = device_create(
fpgajtag_dev_class,
NULL,
MKDEV(fpgajtag_major, fpgajtag_minor[i]),
NULL,
"%s",fpgajtag_devs[i]);
if(IS_ERR(chrdev)){
pr_err("Failed to create a device (fpgajtag, %d). Error code: %ld\n",i,PTR_ERR(chrdev));
}
}
for (i=0;i<=FPGA_JTAG_MAXMINOR;i++) minors[i]=0; for (i=0;i<=FPGA_JTAG_MAXMINOR;i++) minors[i]=0;
initPortC(); initPortC();
...@@ -1411,6 +1465,12 @@ static int __init fpga_jtag_init(void) { ...@@ -1411,6 +1465,12 @@ static int __init fpga_jtag_init(void) {
static void __exit fpga_jtag_exit(void) static void __exit fpga_jtag_exit(void)
{ {
int i;
for (i=0;i<(sizeof(fpgajtag_minor)/sizeof(int));i++){
device_destroy(
fpgajtag_dev_class,
MKDEV(fpgajtag_major, fpgajtag_minor[i]));
}
unregister_chrdev(DEV393_MAJOR(DEV393_JTAGS_CONF0), DEV393_NAME(DEV393_JTAGS_CONF0)); unregister_chrdev(DEV393_MAJOR(DEV393_JTAGS_CONF0), DEV393_NAME(DEV393_JTAGS_CONF0));
dev_dbg(NULL, "unregistering driver"); dev_dbg(NULL, "unregistering driver");
} }
......
...@@ -163,12 +163,7 @@ static const char * const framepars_name[] = { ...@@ -163,12 +163,7 @@ static const char * const framepars_name[] = {
* devices major - is one number * devices major - is one number
* TODO: switch to dynamic major and get rid of this * TODO: switch to dynamic major and get rid of this
*/ */
static const int framepars_major[] = { static const int framepars_major = DEV393_MAJOR(DEV393_FRAMEPARS0);
DEV393_MAJOR(DEV393_FRAMEPARS0),
DEV393_MAJOR(DEV393_FRAMEPARS1),
DEV393_MAJOR(DEV393_FRAMEPARS2),
DEV393_MAJOR(DEV393_FRAMEPARS3)
};
/** /**
* devices minors - basically base+i - can be a single number * devices minors - basically base+i - can be a single number
...@@ -2156,16 +2151,16 @@ int framepars_init(struct platform_device *pdev) ...@@ -2156,16 +2151,16 @@ int framepars_init(struct platform_device *pdev)
int res; int res;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
// const struct of_device_id *match; // const struct of_device_id *match;
int sensor_port; int i;
// char device for sensor port // char device for sensor port
struct device *chrdev; struct device *chrdev;
for (sensor_port = 0; sensor_port < SENSOR_PORTS; sensor_port++) { for (i = 0; i < SENSOR_PORTS; i++) {
init_framepars_ptr(sensor_port); init_framepars_ptr(i);
initGlobalPars(sensor_port); // sets default debug if enabled - not anymore. Add here? initGlobalPars(i); // sets default debug if enabled - not anymore. Add here?
initMultiPars(sensor_port); // just clear - needs to be called again when sensor is recognized initMultiPars(i); // just clear - needs to be called again when sensor is recognized
frameParsInitialized[sensor_port] = 0; frameParsInitialized[i] = 0;
} }
// register character device // register character device
...@@ -2186,22 +2181,22 @@ int framepars_init(struct platform_device *pdev) ...@@ -2186,22 +2181,22 @@ int framepars_init(struct platform_device *pdev)
return PTR_ERR(framepars_dev_class); return PTR_ERR(framepars_dev_class);
} }
for (sensor_port = 0; sensor_port < SENSOR_PORTS; sensor_port++) { for (i = 0; i < (sizeof(framepars_minor)/sizeof(int)); i++) {
pr_debug("Trying to create device with major-minor: %d-%d, name: %s\n",framepars_major[sensor_port],framepars_minor[sensor_port],framepars_name[sensor_port]); pr_debug("Creating device with major-minor: %d-%d, name: %s\n",framepars_major,framepars_minor[i],framepars_name[i]);
chrdev = device_create( chrdev = device_create(
framepars_dev_class, framepars_dev_class,
&pdev->dev, &pdev->dev,
MKDEV(framepars_major[sensor_port], framepars_minor[sensor_port]), MKDEV(framepars_major, framepars_minor[i]),
NULL, NULL,
"%s", framepars_name[sensor_port]); "%s", framepars_name[i]);
if(IS_ERR(chrdev)){ if(IS_ERR(chrdev)){
pr_err("Failed to create a device. Error code: %d\n",PTR_ERR(chrdev)); pr_err("Failed to create a device. Error code: %ld\n",PTR_ERR(chrdev));
} }
} }
for (sensor_port = 0; sensor_port < SENSOR_PORTS; sensor_port++) { for (i = 0; i < SENSOR_PORTS; i++) {
init_waitqueue_head(&aframepars_wait_queue[sensor_port]); init_waitqueue_head(&aframepars_wait_queue[i]);
} }
dev_info(dev, DEV393_NAME(DEV393_FRAMEPARS0)": registered sysfs\n"); dev_info(dev, DEV393_NAME(DEV393_FRAMEPARS0)": registered sysfs\n");
...@@ -2213,12 +2208,12 @@ int framepars_init(struct platform_device *pdev) ...@@ -2213,12 +2208,12 @@ int framepars_init(struct platform_device *pdev)
int framepars_remove(struct platform_device *pdev) int framepars_remove(struct platform_device *pdev)
{ {
int sensor_port; int i;
for (sensor_port = 0; sensor_port < SENSOR_PORTS; sensor_port++) { for (i = 0; i < (sizeof(framepars_minor)/sizeof(int)); i++) {
device_destroy( device_destroy(
framepars_dev_class, framepars_dev_class,
MKDEV(framepars_major[sensor_port],framepars_minor[sensor_port])); MKDEV(framepars_major,framepars_minor[i]));
} }
unregister_chrdev(DEV393_MAJOR(DEV393_FRAMEPARS0), DEV393_NAME(DEV393_FRAMEPARS0)); unregister_chrdev(DEV393_MAJOR(DEV393_FRAMEPARS0), DEV393_NAME(DEV393_FRAMEPARS0));
......
...@@ -184,7 +184,12 @@ static DEFINE_SPINLOCK(gamma_lock); ///< Non port-specific lock ...@@ -184,7 +184,12 @@ static DEFINE_SPINLOCK(gamma_lock); ///< Non port-specific lock
#endif #endif
static const char * const gamma_dev = DEV393_DEVNAME(DEV393_GAMMA);
static const int gamma_major = DEV393_MAJOR(DEV393_GAMMA);
static const int gamma_minor = DEV393_MINOR(DEV393_GAMMA);
/** @brief Global device class for sysfs */
static struct class *gamma_dev_class;
static struct gamma_stuct_t gammas[GAMMA_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE))); static struct gamma_stuct_t gammas[GAMMA_CACHE_NUMBER] __attribute__ ((aligned (PAGE_SIZE)));
struct gamma_stuct_t * gammas_p; // to use with mmap struct gamma_stuct_t * gammas_p; // to use with mmap
...@@ -1000,6 +1005,8 @@ static int gammas_init(struct platform_device *pdev) { ...@@ -1000,6 +1005,8 @@ static int gammas_init(struct platform_device *pdev) {
int res; int res;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct of_device_id *match; // not yet used const struct of_device_id *match; // not yet used
struct device *chrdev;
dev_info(dev,"Starting "DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA)); dev_info(dev,"Starting "DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA));
init_gammas(); init_gammas();
// MDF10(printk("set_gamma_table (0, GAMMA_SCLALE_1, NULL, 0, 0)\n"); udelay (ELPHEL_DEBUG_DELAY)); // MDF10(printk("set_gamma_table (0, GAMMA_SCLALE_1, NULL, 0, 0)\n"); udelay (ELPHEL_DEBUG_DELAY));
...@@ -1013,11 +1020,32 @@ static int gammas_init(struct platform_device *pdev) { ...@@ -1013,11 +1020,32 @@ static int gammas_init(struct platform_device *pdev) {
} }
// init_waitqueue_head(&gammas_wait_queue); // init_waitqueue_head(&gammas_wait_queue);
dev_info(dev, DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA)); dev_info(dev, DEV393_NAME(DEV393_GAMMA)" - %d \n",DEV393_MAJOR(DEV393_GAMMA));
// create device class
gamma_dev_class = class_create(THIS_MODULE, DEV393_NAME(DEV393_GAMMA));
if (IS_ERR(gamma_dev_class)) {
pr_err("Cannot create \"%s\" class", DEV393_NAME(DEV393_GAMMA));
return PTR_ERR(gamma_dev_class);
}
// create device
chrdev = device_create(
gamma_dev_class,
&pdev->dev,
MKDEV(gamma_major, gamma_minor),
NULL,
"%s",gamma_dev);
if(IS_ERR(chrdev)){
pr_err("Failed to create a device (gamma). Error code: %ld\n",PTR_ERR(chrdev));
}
g_dev_ptr = dev; // to use for debug print g_dev_ptr = dev; // to use for debug print
return 0; return 0;
} }
int gammas_remove(struct platform_device *pdev) int gammas_remove(struct platform_device *pdev)
{ {
device_destroy(gamma_dev_class, MKDEV(gamma_major, gamma_minor));
unregister_chrdev(DEV393_MAJOR(DEV393_GAMMA), DEV393_NAME(DEV393_GAMMA)); unregister_chrdev(DEV393_MAJOR(DEV393_GAMMA), DEV393_NAME(DEV393_GAMMA));
return 0; return 0;
......
...@@ -147,6 +147,9 @@ dma_addr_t fpga_hist_phys; // physical address of the start of the received hi ...@@ -147,6 +147,9 @@ dma_addr_t fpga_hist_phys; // physical address of the start of the received hi
#define X3X3_HISTOGRAMS_DRIVER_DESCRIPTION "Elphel (R) Model 353 Histograms device driver" #define X3X3_HISTOGRAMS_DRIVER_DESCRIPTION "Elphel (R) Model 353 Histograms device driver"
/** device class */
static struct class *histograms_dev_class;
/** for each port and possible sensor subchannel provides index in combine histogram data */ /** for each port and possible sensor subchannel provides index in combine histogram data */
int histograms_map[SENSOR_PORTS][MAX_SENSORS]; int histograms_map[SENSOR_PORTS][MAX_SENSORS];
...@@ -839,6 +842,9 @@ int histograms_init(struct platform_device *pdev) { ...@@ -839,6 +842,9 @@ int histograms_init(struct platform_device *pdev) {
int res,i; int res,i;
int sz, pages; int sz, pages;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
// char device for histograms
struct device *chrdev;
// const struct of_device_id *match; // not yet used // const struct of_device_id *match; // not yet used
// init_histograms(); // Not now??? Need to have list of channels // init_histograms(); // Not now??? Need to have list of channels
// Do it later, from the user space // Do it later, from the user space
...@@ -847,6 +853,25 @@ int histograms_init(struct platform_device *pdev) { ...@@ -847,6 +853,25 @@ int histograms_init(struct platform_device *pdev) {
dev_err(dev, "histograms_init: couldn't get a major number %d.\n", DEV393_MAJOR(DEV393_HISTOGRAM)); dev_err(dev, "histograms_init: couldn't get a major number %d.\n", DEV393_MAJOR(DEV393_HISTOGRAM));
return res; return res;
} }
// new in 4.9:
histograms_dev_class = class_create(THIS_MODULE, DEV393_NAME(DEV393_HISTOGRAM));
if (IS_ERR(histograms_dev_class)) {
pr_err("Cannot create \"%s\" class", DEV393_NAME(DEV393_HISTOGRAM));
return PTR_ERR(histograms_dev_class);
}
chrdev = device_create(
histograms_dev_class,
&pdev->dev,
MKDEV(DEV393_MAJOR(DEV393_HISTOGRAM), DEV393_MINOR(DEV393_HISTOGRAM)),
NULL,
"%s", DEV393_DEVNAME(DEV393_HISTOGRAM));
if(IS_ERR(chrdev)){
pr_err("Failed to create a device. Error code: %ld\n",PTR_ERR(chrdev));
}
// init_waitqueue_head(&histograms_wait_queue); // init_waitqueue_head(&histograms_wait_queue);
for (i = 0; i < SENSOR_PORTS; i++) { for (i = 0; i < SENSOR_PORTS; i++) {
init_waitqueue_head(&ahist_y_wait_queue[i]); // wait queue for the G1 histogram (used as Y) init_waitqueue_head(&ahist_y_wait_queue[i]); // wait queue for the G1 histogram (used as Y)
...@@ -869,8 +894,8 @@ int histograms_init(struct platform_device *pdev) { ...@@ -869,8 +894,8 @@ int histograms_init(struct platform_device *pdev) {
} }
int histograms_remove(struct platform_device *pdev) int histograms_remove(struct platform_device *pdev)
{ {
device_destroy(histograms_dev_class,MKDEV(DEV393_MAJOR(DEV393_HISTOGRAM), DEV393_MINOR(DEV393_HISTOGRAM)));
unregister_chrdev(DEV393_MAJOR(DEV393_HISTOGRAM), DEV393_NAME(DEV393_HISTOGRAM)); unregister_chrdev(DEV393_MAJOR(DEV393_HISTOGRAM), DEV393_NAME(DEV393_HISTOGRAM));
return 0; return 0;
} }
static const struct of_device_id elphel393_histograms_of_match[] = { static const struct of_device_id elphel393_histograms_of_match[] = {
......
...@@ -317,7 +317,20 @@ static struct device *g_dev_ptr; ///< Global pointer to basic device structure. ...@@ -317,7 +317,20 @@ static struct device *g_dev_ptr; ///< Global pointer to basic device structure.
wait_queue_head_t logger_wait_queue; wait_queue_head_t logger_wait_queue;
#endif #endif
static const char * const imu_devs[]={
DEV393_DEVNAME(DEV393_LOGGER),
DEV393_DEVNAME(DEV393_LOGGER_CTRL)
};
static const int imu_major = DEV393_MAJOR(DEV393_LOGGER);
static const int imu_minor[]={
DEV393_MINOR(DEV393_LOGGER),
DEV393_MINOR(DEV393_LOGGER_CTRL)
};
/** @brief Global device class for sysfs */
static struct class *imu_dev_class;
int logger_dma_ctrl(int cmd); int logger_dma_ctrl(int cmd);
int logger_init_fpga(int force); int logger_init_fpga(int force);
...@@ -970,12 +983,14 @@ static irqreturn_t logger_irq_handler(int irq, ///< [in] interrupt number ...@@ -970,12 +983,14 @@ static irqreturn_t logger_irq_handler(int irq, ///< [in] interrupt number
static int logger_init(struct platform_device *pdev) static int logger_init(struct platform_device *pdev)
{ {
unsigned int irq; unsigned int irq;
int res; int res, i;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct of_device_id *match; const struct of_device_id *match;
const char *logger_irq_names[4] = {"mult_saxi_0", "mult_saxi_1", "mult_saxi_2", "mult_saxi_3"}; const char *logger_irq_names[4] = {"mult_saxi_0", "mult_saxi_1", "mult_saxi_2", "mult_saxi_3"};
g_dev_ptr = dev; // char device for sensor port
struct device *chrdev;
g_dev_ptr = dev;
/* sanity check */ /* sanity check */
match = of_match_device(elphel393_logger_of_match, dev); match = of_match_device(elphel393_logger_of_match, dev);
...@@ -989,6 +1004,27 @@ static int logger_init(struct platform_device *pdev) ...@@ -989,6 +1004,27 @@ static int logger_init(struct platform_device *pdev)
return res; return res;
} }
dev_info(dev,DEV393_NAME(DEV393_LOGGER)"- %d\n",DEV393_MAJOR(DEV393_LOGGER)); dev_info(dev,DEV393_NAME(DEV393_LOGGER)"- %d\n",DEV393_MAJOR(DEV393_LOGGER));
// create device class
imu_dev_class = class_create(THIS_MODULE, DEV393_NAME(DEV393_LOGGER));
if (IS_ERR(imu_dev_class)) {
pr_err("Cannot create \"%s\" class", DEV393_NAME(DEV393_LOGGER));
return PTR_ERR(imu_dev_class);
}
// create devices
for (i=0;i<(sizeof(imu_minor)/sizeof(int));i++){
chrdev = device_create(
imu_dev_class,
&pdev->dev,
MKDEV(imu_major, imu_minor[i]),
NULL,
"%s",imu_devs[i]);
if(IS_ERR(chrdev)){
pr_err("Failed to create a device (imu_log). Error code: %ld\n",PTR_ERR(chrdev));
}
}
// Setup memory buffer from CMA // Setup memory buffer from CMA
logger_buffer = (u32 *) pElphel_buf->logger_vaddr; // must be page-aligned! logger_buffer = (u32 *) pElphel_buf->logger_vaddr; // must be page-aligned!
logger_size = pElphel_buf->logger_size << PAGE_SHIFT; logger_size = pElphel_buf->logger_size << PAGE_SHIFT;
...@@ -1271,13 +1307,17 @@ int x313_setDMA1Buffer(void) { ...@@ -1271,13 +1307,17 @@ int x313_setDMA1Buffer(void) {
/** IMU/GPS logger driver remove function */ /** IMU/GPS logger driver remove function */
static int logger_remove(struct platform_device *pdev) ///< [in] pointer to @e platform_device structure static int logger_remove(struct platform_device *pdev) ///< [in] pointer to @e platform_device structure
///< @return always 0 ///< @return always 0
{ {
int i;
for (i=0;i<(sizeof(imu_minor)/sizeof(int));i++){
device_destroy(
imu_dev_class,
MKDEV(imu_major, imu_minor[i]));
}
unregister_chrdev(DEV393_MAJOR(DEV393_LOGGER), DEV393_NAME(DEV393_LOGGER)); unregister_chrdev(DEV393_MAJOR(DEV393_LOGGER), DEV393_NAME(DEV393_LOGGER));
return 0; return 0;
} }
......
...@@ -70,6 +70,13 @@ static char * klog393_buf = NULL; ...@@ -70,6 +70,13 @@ static char * klog393_buf = NULL;
const char klogger393_of_prop_bufsize_name[] = "klogger-393,buffer_size"; const char klogger393_of_prop_bufsize_name[] = "klogger-393,buffer_size";
const static u32 max_string_len = PAGE_SIZE; ///< maximal string length const static u32 max_string_len = PAGE_SIZE; ///< maximal string length
static const char * const klogger_dev = DEV393_DEVNAME(DEV393_KLOGGER);
static const int klogger_major = DEV393_MAJOR(DEV393_KLOGGER);
static const int klogger_minor = DEV393_MINOR(DEV393_KLOGGER);
/** @brief Global device class for sysfs */
static struct class *klogger_dev_class;
int klogger393_open(struct inode *inode, struct file *filp); int klogger393_open(struct inode *inode, struct file *filp);
int klogger393_release(struct inode *inode, struct file *filp); int klogger393_release(struct inode *inode, struct file *filp);
loff_t klogger393_llseek(struct file * file, loff_t offset, int orig); loff_t klogger393_llseek(struct file * file, loff_t offset, int orig);
...@@ -370,6 +377,8 @@ int klogger_393_probe(struct platform_device *pdev) ...@@ -370,6 +377,8 @@ int klogger_393_probe(struct platform_device *pdev)
const char * config_string; const char * config_string;
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
const __be32 *bufsize_be; const __be32 *bufsize_be;
// char device for sensor port
struct device *chrdev;
g_dev_ptr = dev; g_dev_ptr = dev;
buffer_wp = 0; buffer_wp = 0;
...@@ -427,14 +436,29 @@ int klogger_393_probe(struct platform_device *pdev) ...@@ -427,14 +436,29 @@ int klogger_393_probe(struct platform_device *pdev)
return res; return res;
} }
// create device class
klogger_dev_class = class_create(THIS_MODULE, DEV393_NAME(DEV393_KLOGGER));
if (IS_ERR(klogger_dev_class)) {
pr_err("Cannot create \"%s\" class", DEV393_NAME(DEV393_KLOGGER));
return PTR_ERR(klogger_dev_class);
}
// create device
chrdev = device_create(
klogger_dev_class,
&pdev->dev,
MKDEV(klogger_major, klogger_minor),
NULL,
"%s",klogger_dev);
if(IS_ERR(chrdev)){
pr_err("Failed to create a device (klogger). Error code: %ld\n",PTR_ERR(chrdev));
}
} else { } else {
dev_warn(dev,"%s: No entry for "DEV393_NAME(DEV393_KLOGGER)", in Device Tree, logger is disabled\n", __func__); dev_warn(dev,"%s: No entry for "DEV393_NAME(DEV393_KLOGGER)", in Device Tree, logger is disabled\n", __func__);
} }
res = klogger_393_sysfs_register(pdev); res = klogger_393_sysfs_register(pdev);
dev_info(dev, DEV393_NAME(DEV393_KLOGGER)": registered sysfs, result = %d\n", res); dev_info(dev, DEV393_NAME(DEV393_KLOGGER)": registered sysfs, result = %d\n", res);
return 0; return 0;
...@@ -446,6 +470,8 @@ int klogger_393_remove(struct platform_device *pdev) ...@@ -446,6 +470,8 @@ int klogger_393_remove(struct platform_device *pdev)
// devm_kfree(&pdev->dev, klog393_buf); // actually not needed // devm_kfree(&pdev->dev, klog393_buf); // actually not needed
} }
device_destroy(klogger_dev_class, MKDEV(klogger_major, klogger_minor));
unregister_chrdev(DEV393_MAJOR(DEV393_KLOGGER), DEV393_NAME(DEV393_KLOGGER)); unregister_chrdev(DEV393_MAJOR(DEV393_KLOGGER), DEV393_NAME(DEV393_KLOGGER));
return 0; return 0;
} }
......
...@@ -42,6 +42,21 @@ static struct device *g_dev_ptr; ///< Global pointer to basic device structure. ...@@ -42,6 +42,21 @@ static struct device *g_dev_ptr; ///< Global pointer to basic device structure.
wait_queue_head_t videomem_wait_queue; wait_queue_head_t videomem_wait_queue;
static DEFINE_SPINLOCK(lock); // for read-modify-write channel enable static DEFINE_SPINLOCK(lock); // for read-modify-write channel enable
static const char * const videomem_devs[]={
DEV393_DEVNAME(DEV393_VIDEOMEM_RAW),
DEV393_DEVNAME(DEV393_IMAGE_RAW)
};
static const int videomem_major = DEV393_MAJOR(DEV393_VIDEOMEM_RAW);
static const int videomem_minor[]={
DEV393_MINOR(DEV393_VIDEOMEM_RAW),
DEV393_MINOR(DEV393_IMAGE_RAW)
};
/** @brief Global device class for sysfs */
static struct class *videomem_dev_class;
static struct elphel_video_buf_t buffer_settings = { ///< some default settings, same as in DT static struct elphel_video_buf_t buffer_settings = { ///< some default settings, same as in DT
.frame_start = {0x00000000, 0x08000000, 0x10000000, 0x08000000}, /* Frame starts (in bytes) */ .frame_start = {0x00000000, 0x08000000, 0x10000000, 0x08000000}, /* Frame starts (in bytes) */
.frame_full_width = { 8192, 8192, 8192, 8192}, /* Frame full widths (in bytes). 1 memory page is 2048 bytes (128 bursts) */ .frame_full_width = { 8192, 8192, 8192, 8192}, /* Frame full widths (in bytes). 1 memory page is 2048 bytes (128 bursts) */
...@@ -551,11 +566,13 @@ static int elphel393_videomem_sysfs_register(struct platform_device *pdev) ...@@ -551,11 +566,13 @@ static int elphel393_videomem_sysfs_register(struct platform_device *pdev)
static int videomem_probe(struct platform_device *pdev) static int videomem_probe(struct platform_device *pdev)
{ {
unsigned int irq; unsigned int irq;
int res; int res, i;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct of_device_id *match; const struct of_device_id *match;
// const __be32 *bufsize_be; // const __be32 *bufsize_be;
struct device_node *node; struct device_node *node;
// char device for sensor port
struct device *chrdev;
elphel393_videomem_sysfs_register(pdev); elphel393_videomem_sysfs_register(pdev);
...@@ -599,6 +616,27 @@ static int videomem_probe(struct platform_device *pdev) ...@@ -599,6 +616,27 @@ static int videomem_probe(struct platform_device *pdev)
dev_err(dev, "\videomem_probe: couldn't get a major number %d.\n ",DEV393_MAJOR(DEV393_VIDEOMEM_RAW)); dev_err(dev, "\videomem_probe: couldn't get a major number %d.\n ",DEV393_MAJOR(DEV393_VIDEOMEM_RAW));
return res; return res;
} }
// create device class
videomem_dev_class = class_create(THIS_MODULE, DEV393_NAME(DEV393_VIDEOMEM_RAW));
if (IS_ERR(videomem_dev_class)) {
pr_err("Cannot create \"%s\" class", DEV393_NAME(DEV393_VIDEOMEM_RAW));
return PTR_ERR(videomem_dev_class);
}
// create devices
for (i=0;i<(sizeof(videomem_minor)/sizeof(int));i++){
chrdev = device_create(
videomem_dev_class,
&pdev->dev,
MKDEV(videomem_major, videomem_minor[i]),
NULL,
"%s",videomem_devs[i]);
if(IS_ERR(chrdev)){
pr_err("Failed to create a device (videomem %d). Error code: %ld\n",i,PTR_ERR(chrdev));
}
}
// Setup interrupt // Setup interrupt
irq = platform_get_irq_byname(pdev, "membridge_irq"); irq = platform_get_irq_byname(pdev, "membridge_irq");
...@@ -620,6 +658,12 @@ static int videomem_probe(struct platform_device *pdev) ...@@ -620,6 +658,12 @@ static int videomem_probe(struct platform_device *pdev)
static int videomem_remove(struct platform_device *pdev) ///< [in] pointer to @e platform_device structure static int videomem_remove(struct platform_device *pdev) ///< [in] pointer to @e platform_device structure
///< @return always 0 ///< @return always 0
{ {
int i;
for (i=0;i<(sizeof(videomem_minor)/sizeof(int));i++){
device_destroy(
videomem_dev_class,
MKDEV(videomem_major, videomem_minor[i]));
}
unregister_chrdev(DEV393_MAJOR(DEV393_VIDEOMEM_RAW), DEV393_NAME(DEV393_VIDEOMEM_RAW)); unregister_chrdev(DEV393_MAJOR(DEV393_VIDEOMEM_RAW), DEV393_NAME(DEV393_VIDEOMEM_RAW));
return 0; return 0;
......
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