0001
0002
0003
0004 #include <linux/mod_devicetable.h>
0005 #include <linux/module.h>
0006 #include <linux/property.h>
0007 #include <linux/regmap.h>
0008 #include <linux/spi/spi.h>
0009
0010 #include "pinctrl-mcp23s08.h"
0011
0012 #define MCP_MAX_DEV_PER_CS 8
0013
0014
0015
0016
0017
0018
0019
0020 struct mcp23s08_driver_data {
0021 unsigned ngpio;
0022 struct mcp23s08 *mcp[8];
0023 struct mcp23s08 chip[];
0024 };
0025
0026 static int mcp23sxx_spi_write(void *context, const void *data, size_t count)
0027 {
0028 struct mcp23s08 *mcp = context;
0029 struct spi_device *spi = to_spi_device(mcp->dev);
0030 struct spi_message m;
0031 struct spi_transfer t[2] = { { .tx_buf = &mcp->addr, .len = 1, },
0032 { .tx_buf = data, .len = count, }, };
0033
0034 spi_message_init(&m);
0035 spi_message_add_tail(&t[0], &m);
0036 spi_message_add_tail(&t[1], &m);
0037
0038 return spi_sync(spi, &m);
0039 }
0040
0041 static int mcp23sxx_spi_gather_write(void *context,
0042 const void *reg, size_t reg_size,
0043 const void *val, size_t val_size)
0044 {
0045 struct mcp23s08 *mcp = context;
0046 struct spi_device *spi = to_spi_device(mcp->dev);
0047 struct spi_message m;
0048 struct spi_transfer t[3] = { { .tx_buf = &mcp->addr, .len = 1, },
0049 { .tx_buf = reg, .len = reg_size, },
0050 { .tx_buf = val, .len = val_size, }, };
0051
0052 spi_message_init(&m);
0053 spi_message_add_tail(&t[0], &m);
0054 spi_message_add_tail(&t[1], &m);
0055 spi_message_add_tail(&t[2], &m);
0056
0057 return spi_sync(spi, &m);
0058 }
0059
0060 static int mcp23sxx_spi_read(void *context, const void *reg, size_t reg_size,
0061 void *val, size_t val_size)
0062 {
0063 struct mcp23s08 *mcp = context;
0064 struct spi_device *spi = to_spi_device(mcp->dev);
0065 u8 tx[2];
0066
0067 if (reg_size != 1)
0068 return -EINVAL;
0069
0070 tx[0] = mcp->addr | 0x01;
0071 tx[1] = *((u8 *) reg);
0072
0073 return spi_write_then_read(spi, tx, sizeof(tx), val, val_size);
0074 }
0075
0076 static const struct regmap_bus mcp23sxx_spi_regmap = {
0077 .write = mcp23sxx_spi_write,
0078 .gather_write = mcp23sxx_spi_gather_write,
0079 .read = mcp23sxx_spi_read,
0080 };
0081
0082 static int mcp23s08_spi_regmap_init(struct mcp23s08 *mcp, struct device *dev,
0083 unsigned int addr, unsigned int type)
0084 {
0085 const struct regmap_config *config;
0086 struct regmap_config *copy;
0087 const char *name;
0088
0089 switch (type) {
0090 case MCP_TYPE_S08:
0091 mcp->reg_shift = 0;
0092 mcp->chip.ngpio = 8;
0093 mcp->chip.label = devm_kasprintf(dev, GFP_KERNEL, "mcp23s08.%d", addr);
0094
0095 config = &mcp23x08_regmap;
0096 name = devm_kasprintf(dev, GFP_KERNEL, "%d", addr);
0097 break;
0098
0099 case MCP_TYPE_S17:
0100 mcp->reg_shift = 1;
0101 mcp->chip.ngpio = 16;
0102 mcp->chip.label = devm_kasprintf(dev, GFP_KERNEL, "mcp23s17.%d", addr);
0103
0104 config = &mcp23x17_regmap;
0105 name = devm_kasprintf(dev, GFP_KERNEL, "%d", addr);
0106 break;
0107
0108 case MCP_TYPE_S18:
0109 mcp->reg_shift = 1;
0110 mcp->chip.ngpio = 16;
0111 mcp->chip.label = "mcp23s18";
0112
0113 config = &mcp23x17_regmap;
0114 name = config->name;
0115 break;
0116
0117 default:
0118 dev_err(dev, "invalid device type (%d)\n", type);
0119 return -EINVAL;
0120 }
0121
0122 copy = devm_kmemdup(dev, config, sizeof(*config), GFP_KERNEL);
0123 if (!copy)
0124 return -ENOMEM;
0125
0126 copy->name = name;
0127
0128 mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp, copy);
0129 if (IS_ERR(mcp->regmap))
0130 dev_err(dev, "regmap init failed for %s\n", mcp->chip.label);
0131 return PTR_ERR_OR_ZERO(mcp->regmap);
0132 }
0133
0134 static int mcp23s08_probe(struct spi_device *spi)
0135 {
0136 struct device *dev = &spi->dev;
0137 struct mcp23s08_driver_data *data;
0138 unsigned long spi_present_mask;
0139 const void *match;
0140 unsigned int addr;
0141 unsigned int ngpio = 0;
0142 int chips;
0143 int type;
0144 int ret;
0145 u32 v;
0146
0147 match = device_get_match_data(dev);
0148 if (match)
0149 type = (int)(uintptr_t)match;
0150 else
0151 type = spi_get_device_id(spi)->driver_data;
0152
0153 ret = device_property_read_u32(dev, "microchip,spi-present-mask", &v);
0154 if (ret) {
0155 ret = device_property_read_u32(dev, "mcp,spi-present-mask", &v);
0156 if (ret) {
0157 dev_err(dev, "missing spi-present-mask");
0158 return ret;
0159 }
0160 }
0161 spi_present_mask = v;
0162
0163 if (!spi_present_mask || spi_present_mask >= BIT(MCP_MAX_DEV_PER_CS)) {
0164 dev_err(dev, "invalid spi-present-mask");
0165 return -ENODEV;
0166 }
0167
0168 chips = hweight_long(spi_present_mask);
0169
0170 data = devm_kzalloc(dev, struct_size(data, chip, chips), GFP_KERNEL);
0171 if (!data)
0172 return -ENOMEM;
0173
0174 spi_set_drvdata(spi, data);
0175
0176 for_each_set_bit(addr, &spi_present_mask, MCP_MAX_DEV_PER_CS) {
0177 data->mcp[addr] = &data->chip[--chips];
0178 data->mcp[addr]->irq = spi->irq;
0179
0180 ret = mcp23s08_spi_regmap_init(data->mcp[addr], dev, addr, type);
0181 if (ret)
0182 return ret;
0183
0184 data->mcp[addr]->pinctrl_desc.name = devm_kasprintf(dev, GFP_KERNEL,
0185 "mcp23xxx-pinctrl.%d",
0186 addr);
0187 if (!data->mcp[addr]->pinctrl_desc.name)
0188 return -ENOMEM;
0189
0190 ret = mcp23s08_probe_one(data->mcp[addr], dev, 0x40 | (addr << 1), type, -1);
0191 if (ret < 0)
0192 return ret;
0193
0194 ngpio += data->mcp[addr]->chip.ngpio;
0195 }
0196 data->ngpio = ngpio;
0197
0198 return 0;
0199 }
0200
0201 static const struct spi_device_id mcp23s08_ids[] = {
0202 { "mcp23s08", MCP_TYPE_S08 },
0203 { "mcp23s17", MCP_TYPE_S17 },
0204 { "mcp23s18", MCP_TYPE_S18 },
0205 { }
0206 };
0207 MODULE_DEVICE_TABLE(spi, mcp23s08_ids);
0208
0209 static const struct of_device_id mcp23s08_spi_of_match[] = {
0210 {
0211 .compatible = "microchip,mcp23s08",
0212 .data = (void *) MCP_TYPE_S08,
0213 },
0214 {
0215 .compatible = "microchip,mcp23s17",
0216 .data = (void *) MCP_TYPE_S17,
0217 },
0218 {
0219 .compatible = "microchip,mcp23s18",
0220 .data = (void *) MCP_TYPE_S18,
0221 },
0222
0223 {
0224 .compatible = "mcp,mcp23s08",
0225 .data = (void *) MCP_TYPE_S08,
0226 },
0227 {
0228 .compatible = "mcp,mcp23s17",
0229 .data = (void *) MCP_TYPE_S17,
0230 },
0231 { }
0232 };
0233 MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match);
0234
0235 static struct spi_driver mcp23s08_driver = {
0236 .probe = mcp23s08_probe,
0237 .id_table = mcp23s08_ids,
0238 .driver = {
0239 .name = "mcp23s08",
0240 .of_match_table = mcp23s08_spi_of_match,
0241 },
0242 };
0243
0244 static int __init mcp23s08_spi_init(void)
0245 {
0246 return spi_register_driver(&mcp23s08_driver);
0247 }
0248
0249
0250
0251
0252
0253 subsys_initcall(mcp23s08_spi_init);
0254
0255 static void mcp23s08_spi_exit(void)
0256 {
0257 spi_unregister_driver(&mcp23s08_driver);
0258 }
0259 module_exit(mcp23s08_spi_exit);
0260
0261 MODULE_LICENSE("GPL");