tscan1.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * tscan1.c: driver for Technologic Systems TS-CAN1 PC104 boards
  4. *
  5. * Copyright 2010 Andre B. Oliveira
  6. */
  7. /* References:
  8. * - Getting started with TS-CAN1, Technologic Systems, Feb 2022
  9. * https://docs.embeddedts.com/TS-CAN1
  10. */
  11. #include <linux/init.h>
  12. #include <linux/io.h>
  13. #include <linux/ioport.h>
  14. #include <linux/isa.h>
  15. #include <linux/module.h>
  16. #include <linux/netdevice.h>
  17. #include "sja1000.h"
  18. MODULE_DESCRIPTION("Driver for Technologic Systems TS-CAN1 PC104 boards");
  19. MODULE_AUTHOR("Andre B. Oliveira <anbadeol@gmail.com>");
  20. MODULE_LICENSE("GPL");
  21. /* Maximum number of boards (one in each JP1:JP2 setting of IO address) */
  22. #define TSCAN1_MAXDEV 4
  23. /* PLD registers address offsets */
  24. #define TSCAN1_ID1 0
  25. #define TSCAN1_ID2 1
  26. #define TSCAN1_VERSION 2
  27. #define TSCAN1_LED 3
  28. #define TSCAN1_PAGE 4
  29. #define TSCAN1_MODE 5
  30. #define TSCAN1_JUMPERS 6
  31. /* PLD board identifier registers magic values */
  32. #define TSCAN1_ID1_VALUE 0xf6
  33. #define TSCAN1_ID2_VALUE 0xb9
  34. /* PLD mode register SJA1000 IO enable bit */
  35. #define TSCAN1_MODE_ENABLE 0x40
  36. /* PLD jumpers register bits */
  37. #define TSCAN1_JP4 0x10
  38. #define TSCAN1_JP5 0x20
  39. /* PLD IO base addresses start */
  40. #define TSCAN1_PLD_ADDRESS 0x150
  41. /* PLD register space size */
  42. #define TSCAN1_PLD_SIZE 8
  43. /* SJA1000 register space size */
  44. #define TSCAN1_SJA1000_SIZE 32
  45. /* SJA1000 crystal frequency (16MHz) */
  46. #define TSCAN1_SJA1000_XTAL 16000000
  47. /* SJA1000 IO base addresses */
  48. static const unsigned short tscan1_sja1000_addresses[] = {
  49. 0x100, 0x120, 0x180, 0x1a0, 0x200, 0x240, 0x280, 0x320
  50. };
  51. /* Read SJA1000 register */
  52. static u8 tscan1_read(const struct sja1000_priv *priv, int reg)
  53. {
  54. return inb((unsigned long)priv->reg_base + reg);
  55. }
  56. /* Write SJA1000 register */
  57. static void tscan1_write(const struct sja1000_priv *priv, int reg, u8 val)
  58. {
  59. outb(val, (unsigned long)priv->reg_base + reg);
  60. }
  61. /* Probe for a TS-CAN1 board with JP2:JP1 jumper setting ID */
  62. static int tscan1_probe(struct device *dev, unsigned id)
  63. {
  64. struct net_device *netdev;
  65. struct sja1000_priv *priv;
  66. unsigned long pld_base, sja1000_base;
  67. int irq, i;
  68. pld_base = TSCAN1_PLD_ADDRESS + id * TSCAN1_PLD_SIZE;
  69. if (!request_region(pld_base, TSCAN1_PLD_SIZE, dev_name(dev)))
  70. return -EBUSY;
  71. if (inb(pld_base + TSCAN1_ID1) != TSCAN1_ID1_VALUE ||
  72. inb(pld_base + TSCAN1_ID2) != TSCAN1_ID2_VALUE) {
  73. release_region(pld_base, TSCAN1_PLD_SIZE);
  74. return -ENODEV;
  75. }
  76. switch (inb(pld_base + TSCAN1_JUMPERS) & (TSCAN1_JP4 | TSCAN1_JP5)) {
  77. case TSCAN1_JP4:
  78. irq = 6;
  79. break;
  80. case TSCAN1_JP5:
  81. irq = 7;
  82. break;
  83. case TSCAN1_JP4 | TSCAN1_JP5:
  84. irq = 5;
  85. break;
  86. default:
  87. dev_err(dev, "invalid JP4:JP5 setting (no IRQ)\n");
  88. release_region(pld_base, TSCAN1_PLD_SIZE);
  89. return -EINVAL;
  90. }
  91. netdev = alloc_sja1000dev(0);
  92. if (!netdev) {
  93. release_region(pld_base, TSCAN1_PLD_SIZE);
  94. return -ENOMEM;
  95. }
  96. dev_set_drvdata(dev, netdev);
  97. SET_NETDEV_DEV(netdev, dev);
  98. netdev->base_addr = pld_base;
  99. netdev->irq = irq;
  100. priv = netdev_priv(netdev);
  101. priv->read_reg = tscan1_read;
  102. priv->write_reg = tscan1_write;
  103. priv->can.clock.freq = TSCAN1_SJA1000_XTAL / 2;
  104. priv->cdr = CDR_CBP | CDR_CLK_OFF;
  105. priv->ocr = OCR_TX0_PUSHPULL;
  106. /* Select the first SJA1000 IO address that is free and that works */
  107. for (i = 0; i < ARRAY_SIZE(tscan1_sja1000_addresses); i++) {
  108. sja1000_base = tscan1_sja1000_addresses[i];
  109. if (!request_region(sja1000_base, TSCAN1_SJA1000_SIZE,
  110. dev_name(dev)))
  111. continue;
  112. /* Set SJA1000 IO base address and enable it */
  113. outb(TSCAN1_MODE_ENABLE | i, pld_base + TSCAN1_MODE);
  114. priv->reg_base = (void __iomem *)sja1000_base;
  115. if (!register_sja1000dev(netdev)) {
  116. /* SJA1000 probe succeeded; turn LED off and return */
  117. outb(0, pld_base + TSCAN1_LED);
  118. netdev_info(netdev, "TS-CAN1 at 0x%lx 0x%lx irq %d\n",
  119. pld_base, sja1000_base, irq);
  120. return 0;
  121. }
  122. /* SJA1000 probe failed; release and try next address */
  123. outb(0, pld_base + TSCAN1_MODE);
  124. release_region(sja1000_base, TSCAN1_SJA1000_SIZE);
  125. }
  126. dev_err(dev, "failed to assign SJA1000 IO address\n");
  127. dev_set_drvdata(dev, NULL);
  128. free_sja1000dev(netdev);
  129. release_region(pld_base, TSCAN1_PLD_SIZE);
  130. return -ENXIO;
  131. }
  132. static void tscan1_remove(struct device *dev, unsigned id /*unused*/)
  133. {
  134. struct net_device *netdev;
  135. struct sja1000_priv *priv;
  136. unsigned long pld_base, sja1000_base;
  137. netdev = dev_get_drvdata(dev);
  138. unregister_sja1000dev(netdev);
  139. dev_set_drvdata(dev, NULL);
  140. priv = netdev_priv(netdev);
  141. pld_base = netdev->base_addr;
  142. sja1000_base = (unsigned long)priv->reg_base;
  143. outb(0, pld_base + TSCAN1_MODE); /* disable SJA1000 IO space */
  144. release_region(sja1000_base, TSCAN1_SJA1000_SIZE);
  145. release_region(pld_base, TSCAN1_PLD_SIZE);
  146. free_sja1000dev(netdev);
  147. }
  148. static struct isa_driver tscan1_isa_driver = {
  149. .probe = tscan1_probe,
  150. .remove = tscan1_remove,
  151. .driver = {
  152. .name = "tscan1",
  153. },
  154. };
  155. module_isa_driver(tscan1_isa_driver, TSCAN1_MAXDEV);