离写上一篇博文已经又过了一个星期啦,每天忙的几乎没时间写,趁着今天放假,继续写,补充完整。
接着上一节的,调用该驱动的probe函数,下面咱们就看看probe函数做了些啥事?
static int __devinit isa1200_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct isa1200_chip *haptic;
struct isa1200_platform_data *pdata;
const struct i2c_device_id *id)
{
struct isa1200_chip *haptic;
struct isa1200_platform_data *pdata;
/*取出client的平台数据*/
pdata = client->dev.platform_data;
/*如果平台数据的dev_setup不空的话,则调用该函数*/
if (pdata->dev_setup) {
ret = pdata->dev_setup(true);
}
ret = pdata->dev_setup(true);
}
/*分配一个isa1200_chip结构体变量,并赋值*/
haptic = kzalloc(sizeof(struct isa1200_chip), GFP_KERNEL);
haptic->client = client;
haptic->enable = 0;
haptic->pdata = pdata;
haptic->client = client;
haptic->enable = 0;
haptic->pdata = pdata;
/*调用pdata的power_on函数*/
if (pdata->power_on) {
ret = pdata->power_on(1);
}
ret = pdata->power_on(1);
}
/*继续初始化haptic变量*/
spin_lock_init(&haptic->lock);
INIT_WORK(&haptic->work, isa1200_chip_work);
INIT_WORK(&haptic->work, isa1200_chip_work);
hrtimer_init(&haptic->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
haptic->timer.function = isa1200_vib_timer_func;
haptic->timer.function = isa1200_vib_timer_func;
/*register with timed output class*/
haptic->dev.name = pdata->name;
haptic->dev.get_time = isa1200_chip_get_time;
haptic->dev.enable = isa1200_chip_enable;
ret = timed_output_dev_register(&haptic->dev);
haptic->dev.name = pdata->name;
haptic->dev.get_time = isa1200_chip_get_time;
haptic->dev.enable = isa1200_chip_enable;
ret = timed_output_dev_register(&haptic->dev);
/*把初始化好的haptic变量挂到client的驱动数据指针上*/
i2c_set_clientdata(client, haptic);
i2c_set_clientdata(client, haptic);
/*判断gpio是否可用?*/
ret = gpio_is_valid(pdata->hap_en_gpio);
if (ret) {
if (ret) {
/*如果可用,则请求该gpio*/
ret = gpio_request(pdata->hap_en_gpio, "haptic_gpio");
}
ret = gpio_request(pdata->hap_en_gpio, "haptic_gpio");
}
ret = isa1200_setup(client);//设置client
return ret;
}
return ret;
}
下面主要看isa1200_setup(client);看都做了些神马?
static int isa1200_setup(struct i2c_client *client)
{
/*取出刚才设置的client的driver data*/
{
/*取出刚才设置的client的driver data*/
struct isa1200_chip *haptic = i2c_get_clientdata(client);
/*提取pdata里面的值,并进行加工*/
value = (haptic->pdata->smart_en << 3) |
(haptic->pdata->is_erm << 5) |
(haptic->pdata->ext_clk_en << 7);
value = (haptic->pdata->smart_en << 3) |
(haptic->pdata->is_erm << 5) |
(haptic->pdata->ext_clk_en << 7);
/*然后发送到client对应的控制器*/
isa1200_write_reg(client, ISA1200_HCTRL1, value);
/*继续组合值,这都是硬件寄存器相关的,就不细分啦*/
if (haptic->pdata->mode_ctrl == PWM_GEN_MODE) {
temp = haptic->pdata->pwm_fd.pwm_div;
value = ((temp >> 7) - 1);
}
temp = haptic->pdata->pwm_fd.pwm_div;
value = ((temp >> 7) - 1);
}
value |= (haptic->pdata->mode_ctrl << 3) |
(haptic->pdata->overdrive_high << 5) |
(haptic->pdata->overdrive_en << 5) |
(haptic->pdata->chip_en << 7);
(haptic->pdata->overdrive_high << 5) |
(haptic->pdata->overdrive_en << 5) |
(haptic->pdata->chip_en << 7);
/*把上面组合好的值发送到对应的client的寄存器中*/
rc = isa1200_write_reg(client, ISA1200_HCTRL0, value);
}
下面最重要的要出场啦,这也是I2C的核心:
}
下面最重要的要出场啦,这也是I2C的核心:
是啥呢?isa1200_write_reg(client, ISA1200_HCTRL0, value);函数,是怎么通信的呢?
static int isa1200_write_reg(struct i2c_client *client, int reg, u8 value)
{
int ret;
{
int ret;
ret = i2c_smbus_write_byte_data(client, reg, value);
return ret;
}
return ret;
}
继续跟踪:
s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
{
union i2c_smbus_data data;
data.byte = value;
return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
I2C_SMBUS_WRITE, command,
I2C_SMBUS_BYTE_DATA, &data);
}
{
union i2c_smbus_data data;
data.byte = value;
return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
I2C_SMBUS_WRITE, command,
I2C_SMBUS_BYTE_DATA, &data);
}
看了半天还没出来,真是犹抱琵琶半遮面,终于要露脸啦:
s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
char read_write, u8 command, int protocol,
union i2c_smbus_data *data)
{
unsigned long orig_jiffies;
int try;
s32 res;
char read_write, u8 command, int protocol,
union i2c_smbus_data *data)
{
unsigned long orig_jiffies;
int try;
s32 res;
flags &= I2C_M_TEN | I2C_CLIENT_PEC;
if (adapter->algo->smbus_xfer) {
rt_mutex_lock(&adapter->bus_lock);
rt_mutex_lock(&adapter->bus_lock);
/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (res = 0, try = 0; try <= adapter->retries; try++) {
res = adapter->algo->smbus_xfer(adapter, addr, flags,
read_write, command,
protocol, data);//这个是调用总线的算法中得函数
if (res != -EAGAIN)
break;
if (time_after(jiffies,
orig_jiffies + adapter->timeout))
break;
}
rt_mutex_unlock(&adapter->bus_lock);
}
orig_jiffies = jiffies;
for (res = 0, try = 0; try <= adapter->retries; try++) {
res = adapter->algo->smbus_xfer(adapter, addr, flags,
read_write, command,
protocol, data);//这个是调用总线的算法中得函数
if (res != -EAGAIN)
break;
if (time_after(jiffies,
orig_jiffies + adapter->timeout))
break;
}
rt_mutex_unlock(&adapter->bus_lock);
}
return res;
}
}
上面总结下:I2C通信是,cpu调用I2C控制器的传输函数,这个根据控制器的不同要重写该函数,发往对应client的地址。进行通信。
上面说了半天,各个寄存器都设置好啦,马达已经处于就绪状态,但是怎么操作呢,接口呢,貌似一路走来,没有碰到给外部提供的接口,下一篇博文,就要去找找给上层提供的接口