打印
[嵌入式linux]

新手求助

[复制链接]
1710|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
maowa_2005|  楼主 | 2013-12-14 16:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
前几天自己编写了简单的驱动模块,用insmod将生成的.ko模块加载到内核,并创建了设备文件节点,在内核中打印简单的“hello word”,已经成功,但是昨天想在驱动模块中对寄存器进行操作,就尝试编写HSI的驱动,但是在编写驱动模块的时候,先通过调用ioremap(hsi_baseaddr,pagesize)将HSI的物理基地址映射为虚拟地址,pagesize选的是4K,之后就在用虚拟基地址+偏移地址往寄存器中写数据时,写不进去,读出来的总是0,而且如果直接读某个寄存器的非0默认值,读出的也会是0,由于刚开始接触驱动,很多不理解,请教各位高人,我这样写是不是有什么错误啊,为什么会读不到值啊

相关帖子

沙发
qyihan| | 2013-12-14 17:56 | 只看该作者
上代码看看

使用特权

评论回复
板凳
rocdove| | 2013-12-15 22:22 | 只看该作者
很怪异,需要代码,芯片型号,内核版本

使用特权

评论回复
地板
maowa_2005|  楼主 | 2013-12-16 09:20 | 只看该作者
本帖最后由 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);

使用特权

评论回复
5
maowa_2005|  楼主 | 2013-12-16 09:29 | 只看该作者
rocdove 发表于 2013-12-15 22:22
很怪异,需要代码,芯片型号,内核版本

代码已贴上,开发板是imx6q sabrelite(Cortex-A9 MPCORE),内核版本是3.0.35

使用特权

评论回复
6
jermy_lin| | 2013-12-17 16:32 | 只看该作者
又看到了,是你的时钟配置有问题,或者没有进行时钟配置,要操作寄存器前必须获取时钟

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

76

帖子

2

粉丝