初步完善框架
#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/device.h> #include <linux/i2c.h> #include <linux/err.h> #include <linux/clk.h>
  #include "i2c-k1x.h"
  static int spacemit_k1_i2c_xfer(struct i2c_adapter *adapt, struct i2c_msg msgs[], int num) { 	struct spacemit_k1_i2c *i2c = i2c_get_adapdata(adapt);
  	return num; }
  static u32 spacemit_k1_i2c_functionality(struct i2c_adapter *adap) { 	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); }
  static const struct i2c_algorithm spacemit_k1_i2c_algrtm = { 	.master_xfer	= spacemit_k1_i2c_xfer, 	.functionality	= spacemit_k1_i2c_functionality, };
 
  static int spacemit_k1_i2c_parse_dt(struct platform_device *pdev, 				    struct spacemit_k1_i2c *i2c) { 	struct device_node *dnode = pdev->dev.of_node; 	int ret;
  	ret = of_property_read_u32(dnode, "spacemit,adapter-id", &pdev->id); 	if(ret) 		pdev->id = -1; 	 	return 0; }
  static int spacemit_k1_i2c_probe(struct platform_device *pdev) { 	struct spacemit_k1_i2c *i2c; 	int ret = 0;
  	i2c = devm_kzalloc(&pdev->dev, 			sizeof(struct spacemit_k1_i2c), 			GFP_KERNEL); 	 	if (!i2c) { 		ret = -ENOMEM;	 		goto err_ret; 	}
  	i2c->dev = &pdev->dev; 	platform_set_drvdata(pdev, i2c); 	 	ret = spacemit_k1_i2c_parse_dt(pdev, i2c); 	if(ret) 		goto err_ret;	 	 	pr_info("spacemit_k1_i2c_probe function: pdev->id %d\n", pdev->id);
  	i2c->adap.owner 	= THIS_MODULE; 	i2c->adap.algo 		= &spacemit_k1_i2c_algrtm; 	i2c->adap.algo_data 	= i2c; 	i2c->adap.nr 		= pdev->id; 	i2c->adap.dev.parent 	= &pdev->dev; 	i2c->adap.dev.of_node 	= pdev->dev.of_node; 	i2c->adap.retries	= 3; 	strscpy(i2c->adap.name, "spacemit-i2c-adapter", 		sizeof(i2c->adap.name)); 	ret = i2c_add_numbered_adapter(&i2c->adap); 	if(ret) { 		dev_err(i2c->dev, "failed to add i2c adapter\n"); 		goto err_ret; 	}	
  err_ret: 	return ret; }
  static int spacemit_k1_i2c_remove(struct platform_device *pdev) { 	struct spacemit_k1_i2c *i2c; 	 	pr_info("spacemit_k1_i2c_remove\n"); 	 	i2c = platform_get_drvdata(pdev);
  	i2c_del_adapter(&i2c->adap);
  	dev_dbg(i2c->dev, "driver removed\n");
  	return 0; }
  static const struct of_device_id spacemit_k1_i2c_dt_match[] = { 	{ 		.compatible = "spacemit,k1x-i2c", 	}, 	{} };
  MODULE_DEVICE_TABLE(of, spacemit_k1_i2c_dt_match);
  static struct platform_driver spacemit_k1_i2c_driver = { 	.probe  = spacemit_k1_i2c_probe, 	.remove = spacemit_k1_i2c_remove, 	.driver = { 		.name		= "i2c-spacemit-k1x", 		.of_match_table	= spacemit_k1_i2c_dt_match, 	}, };
 
  module_platform_driver(spacemit_k1_i2c_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("i2c driver for Spacemit k1 soc");
   | 
 
这里选择module_platform_driver而不是像vendor版本的写法是因为我们暂时不需要注册重启hook。
k1写法如下:
static int __init spacemit_i2c_init(void) { 	register_restart_handler(&spacemit_i2c_sys_nb); 	return platform_driver_register(&spacemit_i2c_driver); }
  static void __exit spacemit_i2c_exit(void) { 	platform_driver_unregister(&spacemit_i2c_driver); 	unregister_restart_handler(&spacemit_i2c_sys_nb); }
  subsys_initcall(spacemit_i2c_init); module_exit(spacemit_i2c_exit);
   |