增加 demo 代码.
Signed-off-by: rick.chan <chenyang@autoai.com>
This commit is contained in:
parent
fa54c0d6ed
commit
798d67b956
|
@ -0,0 +1,12 @@
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := miccom.default
|
||||||
|
LOCAL_MODULE_RELATIVE_PATH := $(TARGET_OUT_SHARED_LIBRARIIES)/hw
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_PRELINK_MODULE := false
|
||||||
|
LOCAL_SHARED_LIBRARIES := liblog
|
||||||
|
LOCAL_SRC_FILES := miccom.c
|
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
|
@ -0,0 +1,100 @@
|
||||||
|
/**
|
||||||
|
* @file demo_hal_driver.c
|
||||||
|
* @author Rich Chan (cy187lion@sina.com)
|
||||||
|
* @brief
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2020-06-10
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2020
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define LOG_TAG "MiccomStub"
|
||||||
|
|
||||||
|
#include <hard/hardware.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <cutils/log.h>
|
||||||
|
#include <cutils/atomic.h>
|
||||||
|
#include "miccom.h"
|
||||||
|
|
||||||
|
#define DEVICE_NAME "/dev/miccom"
|
||||||
|
#define MODULE_NAME "Miccom"
|
||||||
|
#define MODULE_AUTHOR "cy187lion@sina.com"
|
||||||
|
|
||||||
|
static int miccom_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);
|
||||||
|
static int miccom_device_close(struct hw_device_t* device);
|
||||||
|
static int miccom_set_reg(struct miccom_device_t* dev, char reg, unsigned char num);
|
||||||
|
static int miccom_get_reg(struct miccom_device_t* dev, char* reg, unsigned char num);
|
||||||
|
|
||||||
|
static struct hw_modult_methods_t miccom_module_methods = {
|
||||||
|
.open = miccom_device_open
|
||||||
|
};
|
||||||
|
|
||||||
|
struct miccom_module_t HAL_MODULE_INFO_SYM = {
|
||||||
|
.common = {
|
||||||
|
.tag = HARDWARE_MODULE_TAG,
|
||||||
|
.version_major: 1,
|
||||||
|
.version_minor: 0,
|
||||||
|
.id = MICCOM_HARDWARE_MODULE_ID,
|
||||||
|
.name = MODULE_NAME,
|
||||||
|
.author = MODULE_AUTHOR,
|
||||||
|
.methods = &miccom_module_methods
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int miccom_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device)
|
||||||
|
{
|
||||||
|
struct miccom_device_t* dev;
|
||||||
|
|
||||||
|
dev = (struct hw_device_t*)malloc(sizeof(*dev));
|
||||||
|
if(!dev) {
|
||||||
|
LOGE("Miccom stub: failed to alloc space.");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
memset(dev, 0, sizeof(*dev));
|
||||||
|
|
||||||
|
dev->common.tag = HARDWARE_DEVICE_TAG;
|
||||||
|
dev->common.version = 0;
|
||||||
|
dev->common.module = const_cast<hw_module_t *>(module);
|
||||||
|
dev->common.close = miccom_device_close;
|
||||||
|
dev->set_reg = miccom_set_reg;
|
||||||
|
dev->get_reg = miccom_get_reg;
|
||||||
|
|
||||||
|
if(dev->fd = open(DEVICE_NAME, O_RDWR) == -1) {
|
||||||
|
LOGE("Miccom stub: failed to open "DEVICE_NAME" -- %s.", strerror(errno));
|
||||||
|
free(dev);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*device = &(dev->common);
|
||||||
|
LOGI("Miccom stub: Open "DEVICE_NAME" successfully.");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int miccom_device_close(struct hw_device_t* device)
|
||||||
|
{
|
||||||
|
struct miccom_device_t* dev = (struct miccom_device_t*)device;
|
||||||
|
|
||||||
|
if(dev) {
|
||||||
|
close(dev->fd);
|
||||||
|
free(dev);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int miccom_set_reg(struct miccom_device_t* dev, char reg, unsigned char num)
|
||||||
|
{
|
||||||
|
LOGI("Miccom stub: set value %d to device reg.", reg);
|
||||||
|
// write(dev->fd, ®, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int miccom_get_reg(struct miccom_device_t* dev, char* reg, unsigned char num)
|
||||||
|
{
|
||||||
|
if(!reg) {
|
||||||
|
LOGE("Miccom stub: error reg pointer.");
|
||||||
|
}
|
||||||
|
// read(dev->fd, reg, num);
|
||||||
|
LOGI("Miccom stub: get value %d from device reg.", *reg);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* @file demo_hal_driver.h
|
||||||
|
* @author Rich Chan (cy187lion@sina.com)
|
||||||
|
* @brief
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2020-06-10
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2020
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _ANDROID_DEMO_HAL_DRIVER_INTERFACE_H_
|
||||||
|
#define _ANDROID_DEMO_HAL_DRIVER_INTERFACE_H_
|
||||||
|
|
||||||
|
#include <hardware/hardware.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MICCOM_HARDWARE_MODULE_ID "miccom"
|
||||||
|
|
||||||
|
struct miccom_module_t {
|
||||||
|
struct hw_modult_t common;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct miccom_device_t {
|
||||||
|
struct hw_device_t common;
|
||||||
|
int fd;
|
||||||
|
int (*set_reg)(struct miccom_device_t* dev, char reg, unsigned char num);
|
||||||
|
int (*get_reg)(struct miccom_device_t* dev, char* reg, unsigned char num);
|
||||||
|
}
|
||||||
|
|
||||||
|
_END_DECLS
|
||||||
|
|
||||||
|
#endif // _ANDROID_DEMO_HAL_DRIVER_INTERFACE_H_
|
|
@ -0,0 +1,14 @@
|
||||||
|
obj-m:= \
|
||||||
|
demoplatform.o
|
||||||
|
|
||||||
|
demoplatform-objs:= \
|
||||||
|
demo_platform.o
|
||||||
|
|
||||||
|
EXTRA_CFLAGS += \
|
||||||
|
-I$(PWD)
|
||||||
|
|
||||||
|
all:
|
||||||
|
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
|
@ -0,0 +1,242 @@
|
||||||
|
/**
|
||||||
|
* @file demo_platform.c
|
||||||
|
* @author Rich Chan (cy187lion@sina.com)
|
||||||
|
* @brief
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2020-06-10
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2020
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/of_irq.h>
|
||||||
|
#include <linux/miscdevice.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
|
// #include <linux/init.h>
|
||||||
|
// #include <linux/sched.h>
|
||||||
|
// #include <linux/jiffies.h>
|
||||||
|
// #include <linux/slab.h>
|
||||||
|
// #include <linux/ioport.h>
|
||||||
|
// #include <linux/errno.h>
|
||||||
|
// #include <linux/uaccess.h>
|
||||||
|
// #include <linux/spinlock.h>
|
||||||
|
// #include <linux/semaphore.h>
|
||||||
|
// #include <linux/mutex.h>
|
||||||
|
// #include <linux/wait.h>
|
||||||
|
// #include <linux/kdev_t.h>
|
||||||
|
// #include <linux/fs.h>
|
||||||
|
// #include <linux/aer.h>
|
||||||
|
// #include <linux/idr.h>
|
||||||
|
// #include <linux/of_address.h>
|
||||||
|
|
||||||
|
#define MFIS_ICCOM_NAME "miccom"
|
||||||
|
|
||||||
|
struct mfis_cta
|
||||||
|
{
|
||||||
|
void __iomem *mmio;
|
||||||
|
uint32_t cta_addr;
|
||||||
|
uint32_t cta_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mfis_channel
|
||||||
|
{
|
||||||
|
int irq;
|
||||||
|
struct mfis_cta tx;
|
||||||
|
struct mfis_cta rx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mfis_iccom
|
||||||
|
{
|
||||||
|
void __iomem *mmio;
|
||||||
|
uint32_t size;
|
||||||
|
struct miscdevice mis;
|
||||||
|
uint32_t channels;
|
||||||
|
struct mfis_channel channelx[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define to_miccom(priv) container_of((priv), struct mfis_iccom, mis)
|
||||||
|
|
||||||
|
static int miccom_open(struct inode *inode, struct file* filp)
|
||||||
|
{
|
||||||
|
struct mfis_iccom *miccom = to_miccom(filp->private_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int miccom_release(struct inode *inode, struct file* filp)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t miccom_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset)
|
||||||
|
{
|
||||||
|
const char __user *p = buffer;
|
||||||
|
return p-buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t miccom_write(struct file *filp, const char __user *buffer, size_t count, loff_t *offset)
|
||||||
|
{
|
||||||
|
const char __user *p = buffer;
|
||||||
|
return p-buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long miccom_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct mfis_iccom *miccom = to_miccom(filp->private_data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t miccom_isr(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
disable_irq_nosync(irq);
|
||||||
|
printk(KERN_EMERG"[mfis drv:miccom_isr]IRQ=%d.\n", irq);
|
||||||
|
enable_irq(irq);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct file_operations miccom_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = miccom_open,
|
||||||
|
.release = miccom_release,
|
||||||
|
.read = miccom_read,
|
||||||
|
.write = miccom_write,
|
||||||
|
.unlocked_ioctl = miccom_ioctl,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void miccom_enable_irq(struct mfis_iccom* miccom)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<miccom->channels; i++) {
|
||||||
|
enable_irq(miccom->channelx[i].irq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void miccom_disable_irq_nosync(struct mfis_iccom* miccom)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<miccom->channels; i++) {
|
||||||
|
disable_irq_nosync(miccom->channelx[i].irq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int miccom_remap_cta(struct device *dev, struct device_node *node, struct mfis_iccom* miccom)
|
||||||
|
{
|
||||||
|
int32_t len;
|
||||||
|
int i = 0;
|
||||||
|
const __be32 *property;
|
||||||
|
struct device_node *child_np = of_get_next_available_child(node, NULL);
|
||||||
|
int32_t rirq;
|
||||||
|
|
||||||
|
while(child_np) {
|
||||||
|
struct mfis_cta *tx = &miccom->channelx[i].tx;
|
||||||
|
struct mfis_cta *rx = &miccom->channelx[i].rx;
|
||||||
|
|
||||||
|
miccom->channelx[i].irq = of_irq_get(child_np, 0);
|
||||||
|
printk(KERN_EMERG"[mfis drv:remap_cta]IRQ=%d.\n", miccom->channelx[i].irq);
|
||||||
|
|
||||||
|
property = of_get_property(child_np, "mfis,cta-memory", &len);
|
||||||
|
tx->cta_addr = be32_to_cpup(property+1);
|
||||||
|
tx->cta_size = be32_to_cpup(property+3);
|
||||||
|
rx->cta_addr = be32_to_cpup(property+5);
|
||||||
|
rx->cta_size = be32_to_cpup(property+7);
|
||||||
|
// printk(KERN_EMERG"[mfis drv:remap_cta]tx cta_addr=%#x, cta_size=%d.\n", tx->cta_addr, tx->cta_size);
|
||||||
|
// printk(KERN_EMERG"[mfis drv:remap_cta]rx cta_addr=%#x, cta_size=%d.\n", rx->cta_addr, rx->cta_size);
|
||||||
|
|
||||||
|
devm_request_mem_region(dev, (uintptr_t)tx->cta_addr, tx->cta_size, child_np->name);
|
||||||
|
devm_request_mem_region(dev, (uintptr_t)rx->cta_addr, rx->cta_size, child_np->name);
|
||||||
|
|
||||||
|
tx->mmio = devm_ioremap_nocache(dev, (uintptr_t)tx->cta_addr, tx->cta_size);
|
||||||
|
rx->mmio = devm_ioremap_nocache(dev, (uintptr_t)rx->cta_addr, rx->cta_size);
|
||||||
|
// printk(KERN_EMERG"[mfis drv:remap_cta]tx->mmio=%p, rx->mmio=%p.\n", tx->mmio, rx->mmio);
|
||||||
|
rirq = request_irq(miccom->channelx[i].irq, miccom_isr,
|
||||||
|
IRQF_PROBE_SHARED, child_np->name,
|
||||||
|
(void*)miccom);
|
||||||
|
if (rirq != 0) {
|
||||||
|
dev_err(dev, "[mfis drv:remap_cta]Same IRQ registered.\n");
|
||||||
|
return -ENODEV;
|
||||||
|
} else {
|
||||||
|
disable_irq_nosync(miccom->channelx[i].irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
child_np = of_get_next_available_child(node, child_np);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int miccom_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct mfis_iccom* miccom;
|
||||||
|
uint32_t channels;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct device_node *node = dev_of_node(dev);
|
||||||
|
struct miscdevice *miscdev;
|
||||||
|
struct resource *io;
|
||||||
|
|
||||||
|
// printk(KERN_EMERG"[mfis drv:probe]Enter.\n");
|
||||||
|
of_property_read_u32(node, "mfis,channels", &channels);
|
||||||
|
// printk(KERN_EMERG"[mfis drv:probe]channels=%d.\n", channels);
|
||||||
|
miccom = kzalloc(sizeof(struct mfis_iccom)+channels*sizeof(struct mfis_channel), GFP_KERNEL);
|
||||||
|
miccom->channels = channels;
|
||||||
|
|
||||||
|
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
miccom->mmio = devm_ioremap_resource(dev, io);
|
||||||
|
// printk(KERN_EMERG"[mfis drv:probe]IORMEM start=%#llx, mmio=%p.\n", io->start, miccom->mmio);
|
||||||
|
|
||||||
|
miccom_remap_cta(dev, node, miccom);
|
||||||
|
|
||||||
|
miscdev = &miccom->mis;
|
||||||
|
miscdev->minor = MISC_DYNAMIC_MINOR;
|
||||||
|
miscdev->name = MFIS_ICCOM_NAME;
|
||||||
|
miscdev->fops = &miccom_fops;
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, miccom);
|
||||||
|
misc_register(miscdev);
|
||||||
|
|
||||||
|
// TODO: Juest for test.
|
||||||
|
miccom_enable_irq(miccom);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int miccom_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
struct mfis_iccom* miccom;
|
||||||
|
|
||||||
|
miccom = platform_get_drvdata(pdev);
|
||||||
|
for(i=0; i<miccom->channels; i++) {
|
||||||
|
free_irq(miccom->channelx[i].irq, (void*)miccom);
|
||||||
|
}
|
||||||
|
misc_deregister(&miccom->mis);
|
||||||
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
kfree(miccom);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id miccom_match[] = {
|
||||||
|
{ .compatible = "autoai,mfis-iccom", },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, miccom_match);
|
||||||
|
|
||||||
|
static struct platform_driver mfis_driver = {
|
||||||
|
.probe = miccom_probe,
|
||||||
|
.remove = miccom_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "mfis",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = miccom_match,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(mfis_driver)
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Rich Chan");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_DESCRIPTION("mfis driver");
|
||||||
|
MODULE_VERSION("1.0.0");
|
Loading…
Reference in New Issue