Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* MCP23S08 I2C GPIO driver */
0003 
0004 #include <linux/i2c.h>
0005 #include <linux/mod_devicetable.h>
0006 #include <linux/module.h>
0007 #include <linux/regmap.h>
0008 
0009 #include "pinctrl-mcp23s08.h"
0010 
0011 static int mcp230xx_probe(struct i2c_client *client, const struct i2c_device_id *id)
0012 {
0013     struct device *dev = &client->dev;
0014     unsigned int type = id->driver_data;
0015     struct mcp23s08 *mcp;
0016     int ret;
0017 
0018     mcp = devm_kzalloc(dev, sizeof(*mcp), GFP_KERNEL);
0019     if (!mcp)
0020         return -ENOMEM;
0021 
0022     switch (type) {
0023     case MCP_TYPE_008:
0024         mcp->regmap = devm_regmap_init_i2c(client, &mcp23x08_regmap);
0025         mcp->reg_shift = 0;
0026         mcp->chip.ngpio = 8;
0027         mcp->chip.label = "mcp23008";
0028         break;
0029 
0030     case MCP_TYPE_017:
0031         mcp->regmap = devm_regmap_init_i2c(client, &mcp23x17_regmap);
0032         mcp->reg_shift = 1;
0033         mcp->chip.ngpio = 16;
0034         mcp->chip.label = "mcp23017";
0035         break;
0036 
0037     case MCP_TYPE_018:
0038         mcp->regmap = devm_regmap_init_i2c(client, &mcp23x17_regmap);
0039         mcp->reg_shift = 1;
0040         mcp->chip.ngpio = 16;
0041         mcp->chip.label = "mcp23018";
0042         break;
0043 
0044     default:
0045         dev_err(dev, "invalid device type (%d)\n", type);
0046         return -EINVAL;
0047     }
0048 
0049     if (IS_ERR(mcp->regmap))
0050         return PTR_ERR(mcp->regmap);
0051 
0052     mcp->irq = client->irq;
0053     mcp->pinctrl_desc.name = "mcp23xxx-pinctrl";
0054 
0055     ret = mcp23s08_probe_one(mcp, dev, client->addr, type, -1);
0056     if (ret)
0057         return ret;
0058 
0059     i2c_set_clientdata(client, mcp);
0060 
0061     return 0;
0062 }
0063 
0064 static const struct i2c_device_id mcp230xx_id[] = {
0065     { "mcp23008", MCP_TYPE_008 },
0066     { "mcp23017", MCP_TYPE_017 },
0067     { "mcp23018", MCP_TYPE_018 },
0068     { }
0069 };
0070 MODULE_DEVICE_TABLE(i2c, mcp230xx_id);
0071 
0072 static const struct of_device_id mcp23s08_i2c_of_match[] = {
0073     {
0074         .compatible = "microchip,mcp23008",
0075         .data = (void *) MCP_TYPE_008,
0076     },
0077     {
0078         .compatible = "microchip,mcp23017",
0079         .data = (void *) MCP_TYPE_017,
0080     },
0081     {
0082         .compatible = "microchip,mcp23018",
0083         .data = (void *) MCP_TYPE_018,
0084     },
0085 /* NOTE: The use of the mcp prefix is deprecated and will be removed. */
0086     {
0087         .compatible = "mcp,mcp23008",
0088         .data = (void *) MCP_TYPE_008,
0089     },
0090     {
0091         .compatible = "mcp,mcp23017",
0092         .data = (void *) MCP_TYPE_017,
0093     },
0094     { }
0095 };
0096 MODULE_DEVICE_TABLE(of, mcp23s08_i2c_of_match);
0097 
0098 static struct i2c_driver mcp230xx_driver = {
0099     .driver = {
0100         .name   = "mcp230xx",
0101         .of_match_table = mcp23s08_i2c_of_match,
0102     },
0103     .probe      = mcp230xx_probe,
0104     .id_table   = mcp230xx_id,
0105 };
0106 
0107 static int __init mcp23s08_i2c_init(void)
0108 {
0109     return i2c_add_driver(&mcp230xx_driver);
0110 }
0111 
0112 /*
0113  * Register after I²C postcore initcall and before
0114  * subsys initcalls that may rely on these GPIOs.
0115  */
0116 subsys_initcall(mcp23s08_i2c_init);
0117 
0118 static void mcp23s08_i2c_exit(void)
0119 {
0120     i2c_del_driver(&mcp230xx_driver);
0121 }
0122 module_exit(mcp23s08_i2c_exit);
0123 
0124 MODULE_LICENSE("GPL");