4、i2c适配器驱动

通常我们会在与I2C适配器所对应的platform_driver的probe() 函数中完成两个工作。

·初始化I2C适配器所使用的硬件资源, 如申请I/O地址、 中断号、 时钟等。

·通过i2c_add_adapter() 添加i2c_adapter的数据结构, 当然这个i2c_adapter数据结构的成员已经被xxx

适配器的相应函数指针所初始化。

static int altr_i2c_probe(struct platform_device *pdev)

{

struct altr_i2c_dev *idev = NULL;

int irq, ret;

idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL);

if (!idev)

return -ENOMEM;

idev->base = devm_platform_ioremap_resource(pdev, 0);

if (IS_ERR(idev->base))

return PTR_ERR(idev->base);

irq = platform_get_irq(pdev, 0);

if (irq < 0)

return irq;

idev->i2c_clk = devm_clk_get(&pdev->dev, NULL);

if (IS_ERR(idev->i2c_clk)) {

dev_err(&pdev->dev, "missing clock\n");

return PTR_ERR(idev->i2c_clk);

}

idev->dev = &pdev->dev;

init_completion(&idev->msg_complete);

mutex_init(&idev->isr_mutex);

ret = device_property_read_u32(idev->dev, "fifo-size",

       &idev->fifo_size);

if (ret) {

dev_err(&pdev->dev, "FIFO size set to default of %d\n",

ALTR_I2C_DFLT_FIFO_SZ);

idev->fifo_size = ALTR_I2C_DFLT_FIFO_SZ;

}

ret = device_property_read_u32(idev->dev, "clock-frequency",

       &idev->bus_clk_rate);

if (ret) {

dev_err(&pdev->dev, "Default to 100kHz\n");

idev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ;        /* default clock rate */

}

if (idev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ) {

dev_err(&pdev->dev, "invalid clock-frequency %d\n",

idev->bus_clk_rate);

return -EINVAL;

}

ret = devm_request_threaded_irq(&pdev->dev, irq, altr_i2c_isr_quick,

altr_i2c_isr, IRQF_ONESHOT,

pdev->name, idev);

if (ret) {

dev_err(&pdev->dev, "failed to claim IRQ %d\n", irq);

return ret;

}

ret = clk_prepare_enable(idev->i2c_clk);

if (ret) {

dev_err(&pdev->dev, "failed to enable clock\n");

return ret;

}

mutex_lock(&idev->isr_mutex);

altr_i2c_init(idev);

mutex_unlock(&idev->isr_mutex);

i2c_set_adapdata(&idev->adapter, idev);

strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name));

idev->adapter.owner = THIS_MODULE;

idev->adapter.algo = &altr_i2c_algo;

idev->adapter.dev.parent = &pdev->dev;

idev->adapter.dev.of_node = pdev->dev.of_node;

platform_set_drvdata(pdev, idev);

ret = i2c_add_adapter(&idev->adapter);

if (ret) {

clk_disable_unprepare(idev->i2c_clk);

return ret;

}

dev_info(&pdev->dev, "Altera SoftIP I2C Probe Complete\n");

return 0;

}

通常我们会在platform_driver的remove() 函数中完成与加载函数相反的工作。

·释放I2C适配器所使用的硬件资源, 如释放I/O地址、 中断号、 时钟等。

·通过i2c_del_adapter() 删除i2c_adapter的数据结构。

static int altr_i2c_remove(struct platform_device *pdev)

{

struct altr_i2c_dev *idev = platform_get_drvdata(pdev);

clk_disable_unprepare(idev->i2c_clk);

i2c_del_adapter(&idev->adapter);

return 0;

}

static const struct of_device_id altr_i2c_of_match[] = {

{ .compatible = "altr,softip-i2c-v1.0" },

{},

};

MODULE_DEVICE_TABLE(of, altr_i2c_of_match);

static struct platform_driver altr_i2c_driver = {

.probe = altr_i2c_probe,

.remove = altr_i2c_remove,

.driver = {

.name = "altera-i2c",

.of_match_table = altr_i2c_of_match,

},

};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值