diff --git a/Android/HAL/HalDriver/Android.mk b/Android/HAL/HalDriver/Android.mk new file mode 100644 index 0000000..15a13c8 --- /dev/null +++ b/Android/HAL/HalDriver/Android.mk @@ -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) diff --git a/Android/HAL/HalDriver/demo_hal_driver.c b/Android/HAL/HalDriver/demo_hal_driver.c new file mode 100644 index 0000000..b2b6f35 --- /dev/null +++ b/Android/HAL/HalDriver/demo_hal_driver.c @@ -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 +#include +#include +#include +#include +#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(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; +} diff --git a/Android/HAL/HalDriver/demo_hal_driver.h b/Android/HAL/HalDriver/demo_hal_driver.h new file mode 100644 index 0000000..bed75c8 --- /dev/null +++ b/Android/HAL/HalDriver/demo_hal_driver.h @@ -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 + +__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_ \ No newline at end of file diff --git a/Linux/KernelDriver/4.14/Platform/Makefile b/Linux/KernelDriver/4.14/Platform/Makefile new file mode 100644 index 0000000..02c2579 --- /dev/null +++ b/Linux/KernelDriver/4.14/Platform/Makefile @@ -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 \ No newline at end of file diff --git a/Linux/KernelDriver/4.14/Platform/demo_platform.c b/Linux/KernelDriver/4.14/Platform/demo_platform.c new file mode 100644 index 0000000..76df7cb --- /dev/null +++ b/Linux/KernelDriver/4.14/Platform/demo_platform.c @@ -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 +#include +#include +#include +#include +#include + +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +#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; ichannels; i++) { + enable_irq(miccom->channelx[i].irq); + } +} + +static void miccom_disable_irq_nosync(struct mfis_iccom* miccom) +{ + int i; + + for(i=0; ichannels; 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; ichannels; 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"); \ No newline at end of file