idtcps.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * IDT CPS RapidIO switches support
  4. *
  5. * Copyright 2009-2010 Integrated Device Technology, Inc.
  6. * Alexandre Bounine <[email protected]>
  7. */
  8. #include <linux/rio.h>
  9. #include <linux/rio_drv.h>
  10. #include <linux/rio_ids.h>
  11. #include <linux/module.h>
  12. #include "../rio.h"
  13. #define CPS_DEFAULT_ROUTE 0xde
  14. #define CPS_NO_ROUTE 0xdf
  15. #define IDTCPS_RIO_DOMAIN 0xf20020
  16. static int
  17. idtcps_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
  18. u16 table, u16 route_destid, u8 route_port)
  19. {
  20. u32 result;
  21. if (route_port == RIO_INVALID_ROUTE)
  22. route_port = CPS_DEFAULT_ROUTE;
  23. if (table == RIO_GLOBAL_TABLE) {
  24. rio_mport_write_config_32(mport, destid, hopcount,
  25. RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
  26. rio_mport_read_config_32(mport, destid, hopcount,
  27. RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
  28. result = (0xffffff00 & result) | (u32)route_port;
  29. rio_mport_write_config_32(mport, destid, hopcount,
  30. RIO_STD_RTE_CONF_PORT_SEL_CSR, result);
  31. }
  32. return 0;
  33. }
  34. static int
  35. idtcps_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
  36. u16 table, u16 route_destid, u8 *route_port)
  37. {
  38. u32 result;
  39. if (table == RIO_GLOBAL_TABLE) {
  40. rio_mport_write_config_32(mport, destid, hopcount,
  41. RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
  42. rio_mport_read_config_32(mport, destid, hopcount,
  43. RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
  44. if (CPS_DEFAULT_ROUTE == (u8)result ||
  45. CPS_NO_ROUTE == (u8)result)
  46. *route_port = RIO_INVALID_ROUTE;
  47. else
  48. *route_port = (u8)result;
  49. }
  50. return 0;
  51. }
  52. static int
  53. idtcps_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
  54. u16 table)
  55. {
  56. u32 i;
  57. if (table == RIO_GLOBAL_TABLE) {
  58. for (i = 0x80000000; i <= 0x800000ff;) {
  59. rio_mport_write_config_32(mport, destid, hopcount,
  60. RIO_STD_RTE_CONF_DESTID_SEL_CSR, i);
  61. rio_mport_write_config_32(mport, destid, hopcount,
  62. RIO_STD_RTE_CONF_PORT_SEL_CSR,
  63. (CPS_DEFAULT_ROUTE << 24) |
  64. (CPS_DEFAULT_ROUTE << 16) |
  65. (CPS_DEFAULT_ROUTE << 8) | CPS_DEFAULT_ROUTE);
  66. i += 4;
  67. }
  68. }
  69. return 0;
  70. }
  71. static int
  72. idtcps_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
  73. u8 sw_domain)
  74. {
  75. /*
  76. * Switch domain configuration operates only at global level
  77. */
  78. rio_mport_write_config_32(mport, destid, hopcount,
  79. IDTCPS_RIO_DOMAIN, (u32)sw_domain);
  80. return 0;
  81. }
  82. static int
  83. idtcps_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
  84. u8 *sw_domain)
  85. {
  86. u32 regval;
  87. /*
  88. * Switch domain configuration operates only at global level
  89. */
  90. rio_mport_read_config_32(mport, destid, hopcount,
  91. IDTCPS_RIO_DOMAIN, &regval);
  92. *sw_domain = (u8)(regval & 0xff);
  93. return 0;
  94. }
  95. static struct rio_switch_ops idtcps_switch_ops = {
  96. .owner = THIS_MODULE,
  97. .add_entry = idtcps_route_add_entry,
  98. .get_entry = idtcps_route_get_entry,
  99. .clr_table = idtcps_route_clr_table,
  100. .set_domain = idtcps_set_domain,
  101. .get_domain = idtcps_get_domain,
  102. .em_init = NULL,
  103. .em_handle = NULL,
  104. };
  105. static int idtcps_probe(struct rio_dev *rdev, const struct rio_device_id *id)
  106. {
  107. pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
  108. spin_lock(&rdev->rswitch->lock);
  109. if (rdev->rswitch->ops) {
  110. spin_unlock(&rdev->rswitch->lock);
  111. return -EINVAL;
  112. }
  113. rdev->rswitch->ops = &idtcps_switch_ops;
  114. if (rdev->do_enum) {
  115. /* set TVAL = ~50us */
  116. rio_write_config_32(rdev,
  117. rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
  118. /* Ensure that default routing is disabled on startup */
  119. rio_write_config_32(rdev,
  120. RIO_STD_RTE_DEFAULT_PORT, CPS_NO_ROUTE);
  121. }
  122. spin_unlock(&rdev->rswitch->lock);
  123. return 0;
  124. }
  125. static void idtcps_remove(struct rio_dev *rdev)
  126. {
  127. pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
  128. spin_lock(&rdev->rswitch->lock);
  129. if (rdev->rswitch->ops != &idtcps_switch_ops) {
  130. spin_unlock(&rdev->rswitch->lock);
  131. return;
  132. }
  133. rdev->rswitch->ops = NULL;
  134. spin_unlock(&rdev->rswitch->lock);
  135. }
  136. static const struct rio_device_id idtcps_id_table[] = {
  137. {RIO_DEVICE(RIO_DID_IDTCPS6Q, RIO_VID_IDT)},
  138. {RIO_DEVICE(RIO_DID_IDTCPS8, RIO_VID_IDT)},
  139. {RIO_DEVICE(RIO_DID_IDTCPS10Q, RIO_VID_IDT)},
  140. {RIO_DEVICE(RIO_DID_IDTCPS12, RIO_VID_IDT)},
  141. {RIO_DEVICE(RIO_DID_IDTCPS16, RIO_VID_IDT)},
  142. {RIO_DEVICE(RIO_DID_IDT70K200, RIO_VID_IDT)},
  143. { 0, } /* terminate list */
  144. };
  145. static struct rio_driver idtcps_driver = {
  146. .name = "idtcps",
  147. .id_table = idtcps_id_table,
  148. .probe = idtcps_probe,
  149. .remove = idtcps_remove,
  150. };
  151. static int __init idtcps_init(void)
  152. {
  153. return rio_register_driver(&idtcps_driver);
  154. }
  155. static void __exit idtcps_exit(void)
  156. {
  157. rio_unregister_driver(&idtcps_driver);
  158. }
  159. device_initcall(idtcps_init);
  160. module_exit(idtcps_exit);
  161. MODULE_DESCRIPTION("IDT CPS Gen.1 Serial RapidIO switch family driver");
  162. MODULE_AUTHOR("Integrated Device Technology, Inc.");
  163. MODULE_LICENSE("GPL");