0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <linux/bitops.h>
0023 #include <linux/gpio/driver.h>
0024 #include <linux/io.h>
0025 #include <linux/module.h>
0026 #include <linux/platform_device.h>
0027 #include <linux/slab.h>
0028
0029
0030 enum ts5500_blocks { TS5500_DIO1, TS5500_DIO2, TS5500_LCD, TS5600_LCD };
0031
0032 struct ts5500_priv {
0033 const struct ts5500_dio *pinout;
0034 struct gpio_chip gpio_chip;
0035 spinlock_t lock;
0036 bool strap;
0037 u8 hwirq;
0038 };
0039
0040
0041
0042
0043
0044 static bool hex7d_reserved;
0045
0046
0047
0048
0049
0050 struct ts5500_dio {
0051 const u8 value_addr;
0052 const u8 value_mask;
0053 const u8 control_addr;
0054 const u8 control_mask;
0055 const bool no_input;
0056 const bool no_output;
0057 const u8 irq;
0058 };
0059
0060 #define TS5500_DIO_IN_OUT(vaddr, vbit, caddr, cbit) \
0061 { \
0062 .value_addr = vaddr, \
0063 .value_mask = BIT(vbit), \
0064 .control_addr = caddr, \
0065 .control_mask = BIT(cbit), \
0066 }
0067
0068 #define TS5500_DIO_IN(addr, bit) \
0069 { \
0070 .value_addr = addr, \
0071 .value_mask = BIT(bit), \
0072 .no_output = true, \
0073 }
0074
0075 #define TS5500_DIO_IN_IRQ(addr, bit, _irq) \
0076 { \
0077 .value_addr = addr, \
0078 .value_mask = BIT(bit), \
0079 .no_output = true, \
0080 .irq = _irq, \
0081 }
0082
0083 #define TS5500_DIO_OUT(addr, bit) \
0084 { \
0085 .value_addr = addr, \
0086 .value_mask = BIT(bit), \
0087 .no_input = true, \
0088 }
0089
0090
0091
0092
0093
0094
0095 #define TS5500_DIO_GROUP(vaddr, vbitfrom, caddr, cbit) \
0096 TS5500_DIO_IN_OUT(vaddr, vbitfrom + 0, caddr, cbit), \
0097 TS5500_DIO_IN_OUT(vaddr, vbitfrom + 1, caddr, cbit), \
0098 TS5500_DIO_IN_OUT(vaddr, vbitfrom + 2, caddr, cbit), \
0099 TS5500_DIO_IN_OUT(vaddr, vbitfrom + 3, caddr, cbit)
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 static const struct ts5500_dio ts5500_dio1[] = {
0123 TS5500_DIO_GROUP(0x7b, 0, 0x7a, 0),
0124 TS5500_DIO_GROUP(0x7b, 4, 0x7a, 1),
0125 TS5500_DIO_GROUP(0x7c, 0, 0x7a, 5),
0126 TS5500_DIO_IN(0x7c, 4),
0127 TS5500_DIO_IN_IRQ(0x7c, 5, 7),
0128 };
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150 static const struct ts5500_dio ts5500_dio2[] = {
0151 TS5500_DIO_GROUP(0x7e, 0, 0x7d, 0),
0152 TS5500_DIO_GROUP(0x7e, 4, 0x7d, 1),
0153 TS5500_DIO_GROUP(0x7f, 0, 0x7d, 5),
0154 TS5500_DIO_IN_IRQ(0x7f, 4, 6),
0155 };
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176 static const struct ts5500_dio ts5500_lcd[] = {
0177 TS5500_DIO_GROUP(0x72, 0, 0x7d, 2),
0178 TS5500_DIO_GROUP(0x72, 4, 0x7d, 3),
0179 TS5500_DIO_OUT(0x73, 0),
0180 TS5500_DIO_IN(0x73, 6),
0181 TS5500_DIO_IN_IRQ(0x73, 7, 1),
0182 };
0183
0184 static inline void ts5500_set_mask(u8 mask, u8 addr)
0185 {
0186 u8 val = inb(addr);
0187 val |= mask;
0188 outb(val, addr);
0189 }
0190
0191 static inline void ts5500_clear_mask(u8 mask, u8 addr)
0192 {
0193 u8 val = inb(addr);
0194 val &= ~mask;
0195 outb(val, addr);
0196 }
0197
0198 static int ts5500_gpio_input(struct gpio_chip *chip, unsigned offset)
0199 {
0200 struct ts5500_priv *priv = gpiochip_get_data(chip);
0201 const struct ts5500_dio line = priv->pinout[offset];
0202 unsigned long flags;
0203
0204 if (line.no_input)
0205 return -ENXIO;
0206
0207 if (line.no_output)
0208 return 0;
0209
0210 spin_lock_irqsave(&priv->lock, flags);
0211 ts5500_clear_mask(line.control_mask, line.control_addr);
0212 spin_unlock_irqrestore(&priv->lock, flags);
0213
0214 return 0;
0215 }
0216
0217 static int ts5500_gpio_get(struct gpio_chip *chip, unsigned offset)
0218 {
0219 struct ts5500_priv *priv = gpiochip_get_data(chip);
0220 const struct ts5500_dio line = priv->pinout[offset];
0221
0222 return !!(inb(line.value_addr) & line.value_mask);
0223 }
0224
0225 static int ts5500_gpio_output(struct gpio_chip *chip, unsigned offset, int val)
0226 {
0227 struct ts5500_priv *priv = gpiochip_get_data(chip);
0228 const struct ts5500_dio line = priv->pinout[offset];
0229 unsigned long flags;
0230
0231 if (line.no_output)
0232 return -ENXIO;
0233
0234 spin_lock_irqsave(&priv->lock, flags);
0235 if (!line.no_input)
0236 ts5500_set_mask(line.control_mask, line.control_addr);
0237
0238 if (val)
0239 ts5500_set_mask(line.value_mask, line.value_addr);
0240 else
0241 ts5500_clear_mask(line.value_mask, line.value_addr);
0242 spin_unlock_irqrestore(&priv->lock, flags);
0243
0244 return 0;
0245 }
0246
0247 static void ts5500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
0248 {
0249 struct ts5500_priv *priv = gpiochip_get_data(chip);
0250 const struct ts5500_dio line = priv->pinout[offset];
0251 unsigned long flags;
0252
0253 spin_lock_irqsave(&priv->lock, flags);
0254 if (val)
0255 ts5500_set_mask(line.value_mask, line.value_addr);
0256 else
0257 ts5500_clear_mask(line.value_mask, line.value_addr);
0258 spin_unlock_irqrestore(&priv->lock, flags);
0259 }
0260
0261 static int ts5500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
0262 {
0263 struct ts5500_priv *priv = gpiochip_get_data(chip);
0264 const struct ts5500_dio *block = priv->pinout;
0265 const struct ts5500_dio line = block[offset];
0266
0267
0268 if (line.irq)
0269 return line.irq;
0270
0271
0272 if (priv->strap)
0273 return priv->hwirq;
0274
0275 return -ENXIO;
0276 }
0277
0278 static int ts5500_enable_irq(struct ts5500_priv *priv)
0279 {
0280 int ret = 0;
0281 unsigned long flags;
0282
0283 spin_lock_irqsave(&priv->lock, flags);
0284 if (priv->hwirq == 7)
0285 ts5500_set_mask(BIT(7), 0x7a);
0286 else if (priv->hwirq == 6)
0287 ts5500_set_mask(BIT(7), 0x7d);
0288 else if (priv->hwirq == 1)
0289 ts5500_set_mask(BIT(6), 0x7d);
0290 else
0291 ret = -EINVAL;
0292 spin_unlock_irqrestore(&priv->lock, flags);
0293
0294 return ret;
0295 }
0296
0297 static void ts5500_disable_irq(struct ts5500_priv *priv)
0298 {
0299 unsigned long flags;
0300
0301 spin_lock_irqsave(&priv->lock, flags);
0302 if (priv->hwirq == 7)
0303 ts5500_clear_mask(BIT(7), 0x7a);
0304 else if (priv->hwirq == 6)
0305 ts5500_clear_mask(BIT(7), 0x7d);
0306 else if (priv->hwirq == 1)
0307 ts5500_clear_mask(BIT(6), 0x7d);
0308 else
0309 dev_err(priv->gpio_chip.parent, "invalid hwirq %d\n",
0310 priv->hwirq);
0311 spin_unlock_irqrestore(&priv->lock, flags);
0312 }
0313
0314 static int ts5500_dio_probe(struct platform_device *pdev)
0315 {
0316 enum ts5500_blocks block = platform_get_device_id(pdev)->driver_data;
0317 struct device *dev = &pdev->dev;
0318 const char *name = dev_name(dev);
0319 struct ts5500_priv *priv;
0320 unsigned long flags;
0321 int ret;
0322
0323 ret = platform_get_irq(pdev, 0);
0324 if (ret < 0)
0325 return ret;
0326
0327 priv = devm_kzalloc(dev, sizeof(struct ts5500_priv), GFP_KERNEL);
0328 if (!priv)
0329 return -ENOMEM;
0330
0331 platform_set_drvdata(pdev, priv);
0332 priv->hwirq = ret;
0333 spin_lock_init(&priv->lock);
0334
0335 priv->gpio_chip.owner = THIS_MODULE;
0336 priv->gpio_chip.label = name;
0337 priv->gpio_chip.parent = dev;
0338 priv->gpio_chip.direction_input = ts5500_gpio_input;
0339 priv->gpio_chip.direction_output = ts5500_gpio_output;
0340 priv->gpio_chip.get = ts5500_gpio_get;
0341 priv->gpio_chip.set = ts5500_gpio_set;
0342 priv->gpio_chip.to_irq = ts5500_gpio_to_irq;
0343 priv->gpio_chip.base = -1;
0344
0345 switch (block) {
0346 case TS5500_DIO1:
0347 priv->pinout = ts5500_dio1;
0348 priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_dio1);
0349
0350 if (!devm_request_region(dev, 0x7a, 3, name)) {
0351 dev_err(dev, "failed to request %s ports\n", name);
0352 return -EBUSY;
0353 }
0354 break;
0355 case TS5500_DIO2:
0356 priv->pinout = ts5500_dio2;
0357 priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_dio2);
0358
0359 if (!devm_request_region(dev, 0x7e, 2, name)) {
0360 dev_err(dev, "failed to request %s ports\n", name);
0361 return -EBUSY;
0362 }
0363
0364 if (hex7d_reserved)
0365 break;
0366
0367 if (!devm_request_region(dev, 0x7d, 1, name)) {
0368 dev_err(dev, "failed to request %s 7D\n", name);
0369 return -EBUSY;
0370 }
0371
0372 hex7d_reserved = true;
0373 break;
0374 case TS5500_LCD:
0375 case TS5600_LCD:
0376 priv->pinout = ts5500_lcd;
0377 priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_lcd);
0378
0379 if (!devm_request_region(dev, 0x72, 2, name)) {
0380 dev_err(dev, "failed to request %s ports\n", name);
0381 return -EBUSY;
0382 }
0383
0384 if (!hex7d_reserved) {
0385 if (!devm_request_region(dev, 0x7d, 1, name)) {
0386 dev_err(dev, "failed to request %s 7D\n", name);
0387 return -EBUSY;
0388 }
0389
0390 hex7d_reserved = true;
0391 }
0392
0393
0394 spin_lock_irqsave(&priv->lock, flags);
0395 ts5500_clear_mask(BIT(4), 0x7d);
0396 spin_unlock_irqrestore(&priv->lock, flags);
0397 break;
0398 }
0399
0400 ret = devm_gpiochip_add_data(dev, &priv->gpio_chip, priv);
0401 if (ret) {
0402 dev_err(dev, "failed to register the gpio chip\n");
0403 return ret;
0404 }
0405
0406 ret = ts5500_enable_irq(priv);
0407 if (ret) {
0408 dev_err(dev, "invalid interrupt %d\n", priv->hwirq);
0409 return ret;
0410 }
0411
0412 return 0;
0413 }
0414
0415 static int ts5500_dio_remove(struct platform_device *pdev)
0416 {
0417 struct ts5500_priv *priv = platform_get_drvdata(pdev);
0418
0419 ts5500_disable_irq(priv);
0420
0421 return 0;
0422 }
0423
0424 static const struct platform_device_id ts5500_dio_ids[] = {
0425 { "ts5500-dio1", TS5500_DIO1 },
0426 { "ts5500-dio2", TS5500_DIO2 },
0427 { "ts5500-dio-lcd", TS5500_LCD },
0428 { "ts5600-dio-lcd", TS5600_LCD },
0429 { }
0430 };
0431 MODULE_DEVICE_TABLE(platform, ts5500_dio_ids);
0432
0433 static struct platform_driver ts5500_dio_driver = {
0434 .driver = {
0435 .name = "ts5500-dio",
0436 },
0437 .probe = ts5500_dio_probe,
0438 .remove = ts5500_dio_remove,
0439 .id_table = ts5500_dio_ids,
0440 };
0441
0442 module_platform_driver(ts5500_dio_driver);
0443
0444 MODULE_LICENSE("GPL");
0445 MODULE_AUTHOR("Savoir-faire Linux Inc. <kernel@savoirfairelinux.com>");
0446 MODULE_DESCRIPTION("Technologic Systems TS-5500 Digital I/O driver");