[RK3399][Android7.1] 加密芯片支持(一)驱动支持

平台 内核版本 安卓版本
RK3399 Linux4.4 Android7.1

Pin Configuration

在这里插入图片描述

Encryption Flow

在这里插入图片描述

i2c驱动

I2C的设备驱动是通过i2c_add_driver(&my_driver)i2c-core注册的

#define DRV_NAME                   "adasplus"

static const struct i2c_device_id hp_SE_id[] = {
    { DRV_NAME, 0 },
    { }
};
    
MODULE_DEVICE_TABLE(i2c, hp_SE_id);

static struct i2c_driver hq_SE_driver = {
    .driver     = {
        .name   = DRV_NAME,
		.of_match_table = of_match_ptr(SE_ids),
    },
    .id_table   = hp_SE_id,
    .probe      = hq_SE_probe,
    .remove     = hq_SE_remove,
    .shutdown   = hq_SE_shutdown,
};

static int __init hq_SE_init(void)
{
    int nRet = 0;
    nRet = i2c_add_driver(&hq_SE_driver);
    if(nRet < 0){
        printk("i2c_add_driver err, ret = %d\n", nRet);
    }
	printk("init ret:%d\n", nRet);
    return nRet;
}

匹配设备和驱动的时候,使用的是of_match_table里的数据和DTB里的compatible数据

static struct of_device_id SE_ids[] = {
    {.compatible = DRV_NAME},
    {}
};

MODULE_DEVICE_TABLE(of, SE_ids);

probe函数在设备驱动注册最后收尾工作,当设备的device和其对应的driver 在总线上完成配对之后,系统就调用总线设备的probe函数完成驱动注册最后工作。

static int hq_SE_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
	printk("probe enter\n");
    int nRet = 0;

    mClient = client;
	

    if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
        nRet = -ENODEV;
        printk("i2c_check_functionality fail\n");
		kfree(client);
        return nRet;
    }
	
	nRet = misc_register(&SE_miscdev);
	if (nRet < 0)
	{
		return nRet;
	}
	
	printk("probe ok\n");
	return 0;
}

miscdevice

static  struct file_operations SE_fops={
	.owner        	 = THIS_MODULE,
	.open    		 = SE_open,
	.read    		 = SE_read,
	.write    		 = SE_write,
	.release     	 = SE_release,
	.unlocked_ioctl  = SE_unlocked_ioctl,
	.compat_ioctl 	 = SE_unlocked_ioctl,
};

static struct miscdevice SE_miscdev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name  = "i2c-se0",
	.fops  = &SE_fops,
};

向上数据交互

static long SE_unlocked_ioctl(struct file *file, unsigned int  cmd, unsigned long arg)
{
	struct SE_DATA data[1];
	if(cmd >= SE_IOC_SIZE)
		return -EINVAL;
	
	switch(cmd)
	{
	case SE_IOC_GET_DATA:
		if (copy_from_user((void*)data,(void __user*)arg, sizeof(struct SE_DATA)))
		{
			printk("copy_from_user error\n");
			return -EFAULT;
		}
		printk("cmd:%s, reg:0x%x, size:%d\n", "SE_IOC_GET_DATA", data->reg, data->size);

		if(hqSE_read_data(mClient, data->reg, data->buff, data->size) != 0)
		{
			printk("read data failed, reg:0x%x, size:%d\n", data->reg, data->size);
			return -EFAULT;
		}

		if (copy_to_user((void __user*)arg, (void*)data, sizeof(struct SE_DATA)))
		{
			printk("copy_to_user error\n");
			return -EFAULT;
		}
	
		break;

	case SE_IOC_SET_DATA:
		if (copy_from_user((void*)data,(void __user*)arg, sizeof(struct SE_DATA)))
		{
			printk("copy_from_user error\n");
			return -EFAULT;
		}

		printk("cmd:%s, reg:0x%x, size:%d\n", "SE_IOC_SET_DATA", data->reg, data->size);

		hqSE_write_data(mClient, data->reg, data->buff, data->size);
		break;

	default:
		printk("cmd:0x%x error\n", cmd);
		break;
	}
	return 0;
}
  • hqSE_write_data
  • hqSE_read_data

hqSE_write_data

static int hqSE_write_data(struct i2c_client *client, const char reg,const  char *data, unsigned char len)
{
	u8  buf[BUFFSIZE+1];
	int rc;
	int ret = 0;
	int i;

	buf[0] = reg;
	printk("write: %x ",buf[0]);

	if (len >= BUFFSIZE+1) {
		printk("%s (%d) : FAILED: buffer size is limitted(BUFFSIZE+1) %d\n", __func__, __LINE__, len);
		dev_err(&client->dev, "hqSE_write_data FAILED: buffer size is limitted(BUFFSIZE+1)\n");
		return -1;
	}

	for( i=0 ; i<len; i++ ) {
		buf[i+1] = data[i];
		printk("%x ",buf[i+1]);
	}
 	 printk(" \n");
	rc = i2c_master_send(client, buf, len+1);

	if (rc != len+1) {
		printk("%s (%d) : FAILED: writing to reg 0x%x\n", __func__, __LINE__, reg);

		ret = -1;
	}

	return ret;
}

hqSE_read_data

static int hqSE_read_data(struct i2c_client *client, const char reg, char *data, unsigned char len)
{
	u8  buf[BUFFSIZE];
	int rc;	
	int i = 0;
	
	if(len > BUFFSIZE)
	{
		printk("len > BUFFSIZE, buffer size is out\n");
		return -1;
	}

	buf[0] = reg;
	printk(" read: %x ",buf[0]);
	rc = i2c_master_recv_(client, buf, len);
	if (rc != len) {
		printk("%s (%d) : FAILED: reading data, rc:%d\n", __func__, __LINE__, rc);
		return -1;
	}	
	
	for(i = 0; i < len; i++){
		data[i] = buf[i] ;
		printk("%x ",data[i]);
	}		
	printk(" \n");
	return 0;
}
int i2c_master_recv_(const struct i2c_client *client, char *buf, int count)
{
	struct i2c_adapter *adap = client->adapter;
	struct i2c_msg msg[2];
	int ret;

	char reg = buf[0] & 0xff;


	msg[0].addr = client->addr;
	msg[0].flags = I2C_M_TEN;
	msg[0].len = 1;
	msg[0].buf = &reg;
	
	msg[1].addr = client->addr;
	//msg[1].flags = client->flags & I2C_M_TEN;
	msg[1].flags = I2C_M_RD;
	msg[1].len = count;
	msg[1].buf = buf;

	ret = i2c_transfer(adap, &msg, 2);

	/*
	 * If everything went ok (i.e. 1 msg received), return #bytes received,
	 * else error code.
	 */
	return (ret == 2) ? count : ret;
}
发布了270 篇原创文章 · 获赞 95 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq_33487044/article/details/104367977