增加 demo 代码.

Signed-off-by: rick.chan <chenyang@autoai.com>
This commit is contained in:
rick.chan 2020-06-10 14:11:05 +08:00
parent fa54c0d6ed
commit 798d67b956
5 changed files with 401 additions and 0 deletions

View File

@ -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)

View File

@ -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, &reg, 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;
}

View File

@ -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_

View File

@ -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

View File

@ -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");