Android Hub 驱动

Makefile

KERNEL_DIR=/home/xxx/workspace/RK3399/soap/new_pro/P88/kernel
CURDIR=`pwd`

ARCH=arm64
CROSS_COMPILE=/home/xxx/workspace/RK3399/soap/new_pro/P88/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
export  ARCH  CROSS_COMPILE

obj-m := husb_ala.o
all:
	make -C $(KERNEL_DIR) M=$(CURDIR) modules

.PHONE:clean cp

clean:
	$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean	

cp:
	sudo  cp  *.ko /home/nfs -rf

 

创建

husb_ala.c

#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>

#define I2C_RETRY_NUMBER        1

struct husb311_ctrl
{
	int gpio;
	int irq;
	struct i2c_client * client;
};

static struct husb311_ctrl * g_husb311_ctrl = NULL;
static DEFINE_MUTEX(i2c_rw_access);

/**/


int husb311_i2c_read(struct i2c_client *client, char *writebuf, int writelen, char *readbuf, int readlen)
{
    int ret = 0;
    int i = 0;

    mutex_lock(&i2c_rw_access);

    if (readlen > 0) {
        if (writelen > 0) {
            struct i2c_msg msgs[] = {
                {
                    .addr = client->addr,
                    .flags = 0,
                    .len = writelen,
                    .buf = writebuf,
                },
                {
                    .addr = client->addr,
                    .flags = I2C_M_RD,
                    .len = readlen,
                    .buf = readbuf,
                },
            };
            for (i = 0; i < I2C_RETRY_NUMBER; i++) {
                ret = i2c_transfer(client->adapter, msgs, 2);
                if (ret < 0) {
                    printk(KERN_ERR "[IIC]: i2c_transfer(write) error, ret=%d ,client->addr=0x%x!!", ret,client->addr);
                } else
                    break;
            }
        } else {
            struct i2c_msg msgs[] = {
                {
                    .addr = client->addr,
                    .flags = I2C_M_RD,
                    .len = readlen,
                    .buf = readbuf,
                },
            };
            for (i = 0; i < I2C_RETRY_NUMBER; i++) {
                ret = i2c_transfer(client->adapter, msgs, 1);
                if (ret < 0) {
                    printk(KERN_ERR "[IIC]: i2c_transfer(read) error, ret=%d!!", ret);
                } else
                    break;
            }
        }
    }

    mutex_unlock(&i2c_rw_access);
    return ret;
}

int husb311_i2c_write(struct i2c_client *client, char *writebuf, int writelen)
{
    int ret = 0;
    int i = 0;

    mutex_lock(&i2c_rw_access);
    if (writelen > 0) {
        struct i2c_msg msgs[] = {
            {
                .addr = client->addr,
                .flags = 0,
                .len = writelen,
                .buf = writebuf,
            },
        };
        for (i = 0; i < I2C_RETRY_NUMBER; i++) {
            ret = i2c_transfer(client->adapter, msgs, 1);
            if (ret < 0) {
                printk(KERN_ERR "%s: i2c_transfer(write) error, ret=%d", __func__, ret);
            } else
                break;
        }
    }
    mutex_unlock(&i2c_rw_access);

    return ret;
}

int husb311_i2c_write_reg(struct i2c_client *client, unsigned char regaddr, unsigned char regvalue)
{
    unsigned char buf[2] = {0};
    buf[0] = regaddr;
    buf[1] = regvalue;
    return husb311_i2c_write(client, buf, sizeof(buf));
}

int husb311_i2c_read_reg(struct i2c_client *client, unsigned char regaddr, unsigned char *regvalue)
{
    return husb311_i2c_read(client, &regaddr, 1, regvalue, 1);
}



/**/


static int husb311_i2c_read_regs(struct i2c_client *client, unsigned char cmd, unsigned char *data, unsigned char data_len)
{
	struct i2c_msg msgs[2];
	int ret = -1;
	unsigned char * buffer = NULL;
	buffer = kzalloc(data_len, GFP_KERNEL);
	if (!buffer)
		return -ENOMEM;
	msgs[0].addr = client->addr;
	msgs[0].flags = client->flags;
	msgs[0].len = 1;
	msgs[0].buf = &cmd;

	msgs[1].addr = client->addr;
	msgs[1].flags = client->flags | I2C_M_RD;
	msgs[1].len = data_len;
	msgs[1].buf = buffer;
	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
	if (ret < 0)
		dev_err(&client->adapter->dev, "i2c read failed\n");
	else
		memcpy(data, buffer, data_len);

	kfree(buffer);
	return ret;
}

static int husb311_i2c_write_regs(struct i2c_client *client, unsigned char cmd, unsigned char *data, unsigned char data_len)
{
	struct i2c_msg msgs[1];
	unsigned char *buffer;
	int ret = 0;
	buffer = kzalloc(data_len + 1, GFP_KERNEL);
	if (!buffer)
		return -ENOMEM;
	buffer[0] = cmd;
	memcpy(buffer + 1, data, data_len);
	msgs[0].addr = client->addr;
	msgs[0].flags = client->flags;
	msgs[0].len = data_len + 1;
	msgs[0].buf = buffer;
	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
	if (ret < 0)
		dev_err(&client->adapter->dev, "i2c write failed\n");

	kfree(buffer);
	return ret;
}

static int husb311_i2c_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value)
{
	unsigned char buf[2] = {'\0'};
	buf[0] = value;
	buf[1] = '\0';
	return husb311_i2c_write_regs(client, reg, buf, 1);
}

static unsigned char husb311_i2c_read_reg(struct i2c_client *client, unsigned char reg)
{
	int ret = -1;
	unsigned char buf[2] = {'\0'};
	ret = husb311_i2c_read_regs(client, reg, buf, 1);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_i2c_read_regs 0x%x fail\n", reg);
		return -1;
	}
	return buf[0];
}


static int husb311_init(struct i2c_client * client)
{
	int ret = -1;
	//unsigned char value = 0;
	//unsigned char i = 0;
	ret = husb311_i2c_write_reg(client, 0xA0, 0x1);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_i2c_write_reg 0xA0 fail\n");
		return -1;
	}

	for (;;)
	{
		ret = husb311_i2c_read_reg(client, 0x1E, &value);
		if (ret)
		{
			printk(KERN_ERR "time out!!!\n");
			return -1;
		}
		if (!(value & (1 << 6)) || (i > 20))
		{
			break;
		}
		msleep(100);
		i++;
	}
	if (i > 20)
	{
		printk(KERN_ERR "time out!!!\n");
		return -1;
	}
	ret = husb311_i2c_write_reg(client, 0x10, 0xff);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_i2c_write_reg 0x10 fail\n");
		return -1;
	}
	ret = husb311_i2c_write_reg(client, 0x11, 0xff);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_i2c_write_reg 0x11 fail\n");
		return -1;
	}
	ret = husb311_i2c_write_reg(client, 0x12, 0x1);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_i2c_write_reg 0x12 fail\n");
		return -1;
	}	
	ret = husb311_i2c_write_reg(client, 0x13, 0x0);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_i2c_write_reg 0x13 fail\n");
		return -1;
	}	
	ret = husb311_i2c_write_reg(client, 0x14, 0x0);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_i2c_write_reg 0x14 fail\n");
		return -1;
	}	
	ret = husb311_i2c_write_reg(client, 0x90, 0x2);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_i2c_write_reg 0x90 fail\n");
		return -1;
	}	
	ret = husb311_i2c_write_reg(client, 0x9f, 0x0);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_i2c_write_reg 0x9f fail\n");
		return -1;
	}
	ret = husb311_i2c_write_reg(client, 0x1a, 0xa);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_i2c_write_reg 0x1a fail\n");
		return -1;
	}

	return 0;
}

static void husb311_func(struct work_struct * work)
{
	unsigned char value = 0;
	int ret = husb311_i2c_read_reg(g_husb311_ctrl->client, 0x10, &value);
	if (ret)
	{
		printk(KERN_ERR "husb311_i2c_write_reg 0x10 fail\n");
		return;
	}
	if (value &(1 << 0))
	{
		ret = husb311_i2c_read_reg(g_husb311_ctrl->client, 0x1d, &value);
		if (ret)
		{
			printk(KERN_ERR "husb311_i2c_write_reg 0x1d fail\n");
			return;
		}
		if ((value & (0x3 << 2)) && ((value & (0x3 << 0))==0x0))
		{
			printk(KERN_ERR "CC2 is connect!!!");
		}
		if ((value & (0x3 << 0)) && ((value & (0x3 << 2))==0x0))
		{
			printk(KERN_ERR "CC1 is connect!!!");

		}
		husb311_i2c_write_reg(g_husb311_ctrl->client, 0x10, 0xff);
		husb311_i2c_write_reg(g_husb311_ctrl->client, 0x11, 0xff);
	}
	enable_irq(g_husb311_ctrl->irq);
}
static DECLARE_WORK(husb311_work, husb311_func);

static irqreturn_t husb311_irq_handler(int irq, void *dev_id)
{
	printk(KERN_ERR "------------husb311_irq_handler-------------\n");
	schedule_work(&husb311_work);
	disable_irq(g_husb311_ctrl->irq);
	return IRQ_HANDLED;
}

static int husb311_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	int ret = -1;
	enum of_gpio_flags irq_flags;
	struct device_node * np = client->dev.of_node;
	printk(KERN_ERR "------------enter probe function-------------\n");
	g_husb311_ctrl = kzalloc(sizeof(struct husb311_ctrl), GFP_KERNEL);
	if (!g_husb311_ctrl)
	{
		printk(KERN_ERR "kzalloc fail\n");
		return -ENOMEM;
	}
	g_husb311_ctrl->client = client;
	g_husb311_ctrl->gpio = of_get_named_gpio_flags(np, "int-n-gpios", 0, (enum of_gpio_flags*)&irq_flags);
	if (g_husb311_ctrl->gpio < 0)
	{
		printk(KERN_ERR "of_get_named_gpio_flags fail\n");
		goto gpio_err;
	}

	printk(KERN_ERR "gpio:%d\n", g_husb311_ctrl->gpio);

	ret = gpio_request(g_husb311_ctrl->gpio, "husb311 irq gpio");
	if (ret < 0)
	{
		printk(KERN_ERR "gpio_request fail\n");
		goto gpio_request_err;
	}
	g_husb311_ctrl->irq = gpio_to_irq(g_husb311_ctrl->gpio);
	if (g_husb311_ctrl->irq < 0)
	{
		printk(KERN_ERR "gpio_to_irq fail\n");
		goto to_irq_err;
	}

	printk(KERN_ERR "irq:%d\n", g_husb311_ctrl->irq);

	ret = request_irq(g_husb311_ctrl->irq, husb311_irq_handler, irq_flags,
	"husb311_irq", NULL);

	printk(KERN_ERR "request_irq return:%d\n", ret);
	if (ret != 0)
	{
		printk(KERN_ERR "request_irq fail\n");
		goto request_irq_err;
	}

	/* init */
	ret = husb311_init(client);
	if (ret < 0)
	{
		printk(KERN_ERR "husb311_init fail\n");
		goto husb311_init_err;
	}
	return 0;

husb311_init_err:
	free_irq(g_husb311_ctrl->irq, NULL);
request_irq_err:
to_irq_err:
	gpio_free(g_husb311_ctrl->gpio);
gpio_request_err:
gpio_err:
	return -1;
}

static int husb311_remove(struct i2c_client *client)
{
	free_irq(g_husb311_ctrl->irq, NULL);
	gpio_free(g_husb311_ctrl->gpio);
	return 0;
}

static const struct of_device_id husb311_of_match[] = {
	{ .compatible = "husb311" },
	{ },
};

static const struct i2c_device_id husb30x[] = {
	{ "husb311", 0 },
	{}
};
MODULE_DEVICE_TABLE(i2c, husb30x);

static struct i2c_driver husb311_i2c_driver = {
	.driver = {
		.name = "husb311",
		.of_match_table = husb311_of_match,
	},
	.probe    = husb311_probe,
	.remove   = husb311_remove,
	.id_table = husb30x,
};

module_i2c_driver(husb311_i2c_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("linqi");
MODULE_DESCRIPTION("husb311 usb cc driver");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值