本帖最后由 maowa_2005 于 2013-12-16 09:27 编辑
qyihan 发表于 2013-12-14 17:56
上代码看看
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <asm/io.h>
#include "hsi_imx.h"
#include <asm/io.h> /* readl writel ioremap */
#include <mach/iomux-mx6q.h>
#include <mach/clock.h>
#include <linux/ioport.h> /* request_mem_region */
MODULE_LICENSE("GPL");
#define DEV_NAME "hsi"
#define SZ_4K 0x00001000
#define MX6Q_IOMUX_BASE_ADDR 0x020e0000
#define MX6_IO_ADDRESS(x) (void __force __iomem *)((x)+ 0xF2000000)
void *hsi_base_addr;
static int hsi_open(struct inode *inode, struct file *filp);
static ssize_t hsi_read(struct file *filp, char *buf, size_t len, loff_t *off);
static ssize_t hsi_write(struct file *filp, char *buf, size_t len, loff_t *off);
extern int hsi_initialize(void);
extern int hsi_tx(unsigned int value,unsigned int count);
extern long hsi_rx(unsigned int count);
//extern void mxc_iomux_v3_init(void __iomem *iomux_v3_base);
extern struct clk *clk_get(struct device *dev, const char *con_id);
extern int clk_enable(struct clk *clk);
void clear_clockgate(void)
{
unsigned int clk_en = ((readl(hsi_base_addr + MIPI_HSI_CTRL))&0xbfffffff);
writel(clk_en, hsi_base_addr + MIPI_HSI_CTRL);
printk(KERN_NOTICE"\nclk_en = %x \n", (readl(hsi_base_addr + MIPI_HSI_CTRL)&0x40000000)>>30);
}
void setup_hsi(void)
{
// mxc_iomux_v3_init(MX6_IO_ADDRESS(MX6Q_IOMUX_BASE_ADDR));
/* hsi */
mxc_iomux_v3_setup_pad(MX6Q_PAD_RGMII_TD0__MIPI_HSI_CTRL_TX_READY);
mxc_iomux_v3_setup_pad(MX6Q_PAD_RGMII_TD1__MIPI_HSI_CTRL_RX_FLAG);
mxc_iomux_v3_setup_pad(MX6Q_PAD_RGMII_TD2__MIPI_HSI_CTRL_RX_DATA);
mxc_iomux_v3_setup_pad(MX6Q_PAD_RGMII_TD3__MIPI_HSI_CTRL_RX_WAKE);
mxc_iomux_v3_setup_pad(MX6Q_PAD_RGMII_RD0__MIPI_HSI_CTRL_RX_READY);
mxc_iomux_v3_setup_pad(MX6Q_PAD_RGMII_RD1__MIPI_HSI_CTRL_TX_FLAG);
mxc_iomux_v3_setup_pad(MX6Q_PAD_RGMII_RD2__MIPI_HSI_CTRL_TX_DATA);
mxc_iomux_v3_setup_pad(MX6Q_PAD_RGMII_RD3__MIPI_HSI_CTRL_TX_WAKE);
}
int hsi_initialize(void)
{
printk(KERN_NOTICE"\n*******enter hsi_initialize()******\n");
/* setup hsi iomux */
setup_hsi();
clear_clockgate();
unsigned int hsi_ctrl_reg = 0x09000003;
unsigned int hsi_id_bit_reg = 0x00000044;
writel(hsi_ctrl_reg, hsi_base_addr + MIPI_HSI_CTRL); //??????????????????
writel(hsi_id_bit_reg, hsi_base_addr + MIPI_HSI_ID_BIT);//??????????????????
printk(KERN_NOTICE"\nhsi_ctrl_reg = %x \n", readl(hsi_base_addr + MIPI_HSI_CTRL));//???????????????
printk(KERN_NOTICE"\nhsi_id_bit_reg %x \n", readl(hsi_base_addr + MIPI_HSI_ID_BIT));
/*TX channel 0_en = 1, wakeup = 1, trans_mode = 1(frame) */
unsigned int hsi_tx_conf_reg = 0x00010003;
writel(hsi_tx_conf_reg, hsi_base_addr + MIPI_HSI_TX_CONF);
printk(KERN_NOTICE"\nhsi_tx_conf_reg %x\n", readl(hsi_base_addr + MIPI_HSI_TX_CONF));
/*RX channel 0_en = 1, wakeup = 1, rec_mode = 1(frame) data_flow = 00 (synchronized data flow) */
unsigned int hsi_rx_conf_reg = 0x0001000c;
writel(hsi_rx_conf_reg, hsi_base_addr + MIPI_HSI_RX_CONF);
printk(KERN_NOTICE"\nhsi_rx_conf_reg %x\n", readl(hsi_base_addr + MIPI_HSI_RX_CONF));
while(1)
{
unsigned int reg = ((readl(hsi_base_addr + MIPI_HSI_TX_FIFO_STAT))&0x3);
if (reg == 0 || reg == 1)
{
printk(KERN_NOTICE"\nTx channel 0 fifo is not full!\n");
break;
}
}
writel(0,hsi_base_addr + MIPI_HSI_TX_CH0_DP );
return 0;
}
int hsi_tx(unsigned int value,unsigned int count)
{
unsigned int i ;
unsigned int reg;
for (i = 1; i <= count; i++)
{
reg = ((readl(hsi_base_addr + MIPI_HSI_TX_FIFO_STAT))&0x3);
if (reg == 0 || reg == 1)
{
printk(KERN_NOTICE"\nTx channel 0 fifo is not full!\n");
writel((value + i -1), hsi_base_addr + MIPI_HSI_TX_CH0_DP);
printk(KERN_NOTICE"\ntx count = %x \n",i);
/**check tx/rx fifo status**/
printk(KERN_NOTICE"\nMIPI_HSI_TX_FIFO_STAT 0x02208210 = %x\n", readl(hsi_base_addr + MIPI_HSI_TX_FIFO_STAT));
printk(KERN_NOTICE"\nMIPI_HSI_RX_FIFO_STAT 0x02208214 = %x\n", readl(hsi_base_addr + MIPI_HSI_RX_FIFO_STAT));
/* check irq/err_irq status */
//printk(KERN_NOTICE"\nirqstat 02208030 = %x \n",readl(hsi_base_addr + MIPI_HSI_IRQSTAT));
//printk(KERN_NOTICE"\nerr_irqstat 022080d0 = %x \n",readl(hsi_base_addr + MIPI_HSI_ERR_IRQSTAT));
}
else
{ i--;
printk(KERN_NOTICE"\nTx channel 0 fifo = %x , full!!\n",reg);
return -1;
}
}
return 0;
}
long hsi_rx(unsigned int count)
{
unsigned int reg;
unsigned int i;
for ( i = 1; i <= count; i++ )
{
reg = ((readl(hsi_base_addr + MIPI_HSI_RX_FIFO_STAT))&0x3);
if (reg == 0 || reg == 2)
{
printk(KERN_NOTICE"\nRx channel 0 fifo is not empty!\n");
reg = readl(hsi_base_addr + MIPI_HSI_RX_CH0_DP);
printk(KERN_NOTICE"\nRx count = %x \n",i);
printk(KERN_NOTICE"\nThe recieved data%x is %x \n\n ", i, reg);
/**check tx/rx fifo status**/
printk(KERN_NOTICE"\nMIPI_HSI_TX_FIFO_STAT 0x02208210 = %x\n", readl(hsi_base_addr + MIPI_HSI_TX_FIFO_STAT));
printk(KERN_NOTICE"\nMIPI_HSI_RX_FIFO_STAT 0x02208214 = %x\n", readl(hsi_base_addr + MIPI_HSI_RX_FIFO_STAT));
}
else
{ i--;
printk(KERN_NOTICE"\nRx channel 0 fifo is empty!!\n");
return -1;
}
}
return reg;
}
struct hsi_dev_t {
struct cdev cdev;
unsigned int hsi_data;
}hsi_dev;
static int hsi_major = 0;
static int hsi_minor = 0;
struct hsi_dev_t *hsi_devp;
struct file_operations hsi_fops = {
.owner = THIS_MODULE,
.open = hsi_open,
.read = hsi_read,
.write = hsi_write,
};
static int hsi_open(struct inode *inode, struct file *filp)
{
struct hsi_dev_t *dev;
dev = container_of(inode->i_cdev, struct hsi_dev_t, cdev);
filp->private_data = dev;
if(!request_mem_region(HSI_BASE_ADDR, SZ_4K, "hsi")){
printk("##request_mem_region failed \n");
}
hsi_base_addr = ioremap(HSI_BASE_ADDR, SZ_4K);
printk("##hsi_phy_base_addr = %x ", HSI_BASE_ADDR);
printk("##hsi_virtual_base_addr = %x ", hsi_base_addr);
hsi_initialize();
return 0;
}
static ssize_t hsi_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
struct hsi_dev_t *dev = filp->private_data;
unsigned int count = 1;
long reg = hsi_rx(count);
if (reg < 0)
{
printk("\nhsi_read fail\n");
return -1;
}else {
dev->hsi_data = (unsigned int)reg;
}
if (copy_to_user(buf, &(dev->hsi_data),sizeof(unsigned int)))
return -EFAULT;
return sizeof(unsigned int);
}
static ssize_t hsi_write(struct file *filp, char *buf, size_t len, loff_t *off)
{
struct hsi_dev_t *dev = filp->private_data;
if (copy_from_user(&dev->hsi_data, buf, sizeof(unsigned int)))
return -EFAULT;
unsigned int count = 1;
int reg = hsi_tx(dev->hsi_data, count);
if (reg < 0)
{
printk("\nhsi_write fail\n");
return -1;
}else{
printk("\nhsi_write success\n");
}
}
static int __init hsi_init(void)
{
dev_t hsi_devno;
int ret;
if (hsi_major) {
hsi_devno = MKDEV(hsi_major, hsi_minor);
ret = register_chrdev_region(hsi_devno,1,DEV_NAME);
}else {
ret = alloc_chrdev_region(&hsi_devno, hsi_minor, 1, DEV_NAME);
hsi_major = MAJOR(hsi_devno);
}
hsi_devp = (struct hsi_dev_t *)kmalloc(sizeof(struct hsi_dev_t), GFP_KERNEL);
memset(hsi_devp, 0, sizeof(struct hsi_dev_t));
cdev_init(&hsi_devp->cdev, &hsi_fops);
hsi_devp->cdev.owner = THIS_MODULE;
hsi_devp->cdev.ops = &hsi_fops;
ret = cdev_add(&hsi_devp->cdev, hsi_devno, 1);
return 0;
}
static int __exit hsi_exit(void)
{
cdev_del(&hsi_devp->cdev);
kfree(hsi_devp);
unregister_chrdev_region(MKDEV(hsi_major, hsi_minor), 1);
iounmap(hsi_base_addr);
release_mem_region(HSI_BASE_ADDR, SZ_4K);
return 0;
}
module_init(hsi_init);
module_exit(hsi_exit);
|