brcmstb_gisb.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2014-2021 Broadcom
  4. */
  5. #include <linux/init.h>
  6. #include <linux/types.h>
  7. #include <linux/module.h>
  8. #include <linux/panic_notifier.h>
  9. #include <linux/platform_device.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/sysfs.h>
  12. #include <linux/io.h>
  13. #include <linux/string.h>
  14. #include <linux/device.h>
  15. #include <linux/list.h>
  16. #include <linux/of.h>
  17. #include <linux/bitops.h>
  18. #include <linux/pm.h>
  19. #include <linux/kernel.h>
  20. #include <linux/kdebug.h>
  21. #include <linux/notifier.h>
  22. #ifdef CONFIG_MIPS
  23. #include <asm/traps.h>
  24. #endif
  25. #define ARB_ERR_CAP_CLEAR (1 << 0)
  26. #define ARB_ERR_CAP_STATUS_TIMEOUT (1 << 12)
  27. #define ARB_ERR_CAP_STATUS_TEA (1 << 11)
  28. #define ARB_ERR_CAP_STATUS_WRITE (1 << 1)
  29. #define ARB_ERR_CAP_STATUS_VALID (1 << 0)
  30. #define ARB_BP_CAP_CLEAR (1 << 0)
  31. #define ARB_BP_CAP_STATUS_PROT_SHIFT 14
  32. #define ARB_BP_CAP_STATUS_TYPE (1 << 13)
  33. #define ARB_BP_CAP_STATUS_RSP_SHIFT 10
  34. #define ARB_BP_CAP_STATUS_MASK GENMASK(1, 0)
  35. #define ARB_BP_CAP_STATUS_BS_SHIFT 2
  36. #define ARB_BP_CAP_STATUS_WRITE (1 << 1)
  37. #define ARB_BP_CAP_STATUS_VALID (1 << 0)
  38. enum {
  39. ARB_TIMER,
  40. ARB_BP_CAP_CLR,
  41. ARB_BP_CAP_HI_ADDR,
  42. ARB_BP_CAP_ADDR,
  43. ARB_BP_CAP_STATUS,
  44. ARB_BP_CAP_MASTER,
  45. ARB_ERR_CAP_CLR,
  46. ARB_ERR_CAP_HI_ADDR,
  47. ARB_ERR_CAP_ADDR,
  48. ARB_ERR_CAP_STATUS,
  49. ARB_ERR_CAP_MASTER,
  50. };
  51. static const int gisb_offsets_bcm7038[] = {
  52. [ARB_TIMER] = 0x00c,
  53. [ARB_BP_CAP_CLR] = 0x014,
  54. [ARB_BP_CAP_HI_ADDR] = -1,
  55. [ARB_BP_CAP_ADDR] = 0x0b8,
  56. [ARB_BP_CAP_STATUS] = 0x0c0,
  57. [ARB_BP_CAP_MASTER] = -1,
  58. [ARB_ERR_CAP_CLR] = 0x0c4,
  59. [ARB_ERR_CAP_HI_ADDR] = -1,
  60. [ARB_ERR_CAP_ADDR] = 0x0c8,
  61. [ARB_ERR_CAP_STATUS] = 0x0d0,
  62. [ARB_ERR_CAP_MASTER] = -1,
  63. };
  64. static const int gisb_offsets_bcm7278[] = {
  65. [ARB_TIMER] = 0x008,
  66. [ARB_BP_CAP_CLR] = 0x01c,
  67. [ARB_BP_CAP_HI_ADDR] = -1,
  68. [ARB_BP_CAP_ADDR] = 0x220,
  69. [ARB_BP_CAP_STATUS] = 0x230,
  70. [ARB_BP_CAP_MASTER] = 0x234,
  71. [ARB_ERR_CAP_CLR] = 0x7f8,
  72. [ARB_ERR_CAP_HI_ADDR] = -1,
  73. [ARB_ERR_CAP_ADDR] = 0x7e0,
  74. [ARB_ERR_CAP_STATUS] = 0x7f0,
  75. [ARB_ERR_CAP_MASTER] = 0x7f4,
  76. };
  77. static const int gisb_offsets_bcm7400[] = {
  78. [ARB_TIMER] = 0x00c,
  79. [ARB_BP_CAP_CLR] = 0x014,
  80. [ARB_BP_CAP_HI_ADDR] = -1,
  81. [ARB_BP_CAP_ADDR] = 0x0b8,
  82. [ARB_BP_CAP_STATUS] = 0x0c0,
  83. [ARB_BP_CAP_MASTER] = 0x0c4,
  84. [ARB_ERR_CAP_CLR] = 0x0c8,
  85. [ARB_ERR_CAP_HI_ADDR] = -1,
  86. [ARB_ERR_CAP_ADDR] = 0x0cc,
  87. [ARB_ERR_CAP_STATUS] = 0x0d4,
  88. [ARB_ERR_CAP_MASTER] = 0x0d8,
  89. };
  90. static const int gisb_offsets_bcm74165[] = {
  91. [ARB_TIMER] = 0x008,
  92. [ARB_BP_CAP_CLR] = 0x044,
  93. [ARB_BP_CAP_HI_ADDR] = -1,
  94. [ARB_BP_CAP_ADDR] = 0x048,
  95. [ARB_BP_CAP_STATUS] = 0x058,
  96. [ARB_BP_CAP_MASTER] = 0x05c,
  97. [ARB_ERR_CAP_CLR] = 0x038,
  98. [ARB_ERR_CAP_HI_ADDR] = -1,
  99. [ARB_ERR_CAP_ADDR] = 0x020,
  100. [ARB_ERR_CAP_STATUS] = 0x030,
  101. [ARB_ERR_CAP_MASTER] = 0x034,
  102. };
  103. static const int gisb_offsets_bcm7435[] = {
  104. [ARB_TIMER] = 0x00c,
  105. [ARB_BP_CAP_CLR] = 0x014,
  106. [ARB_BP_CAP_HI_ADDR] = -1,
  107. [ARB_BP_CAP_ADDR] = 0x158,
  108. [ARB_BP_CAP_STATUS] = 0x160,
  109. [ARB_BP_CAP_MASTER] = 0x164,
  110. [ARB_ERR_CAP_CLR] = 0x168,
  111. [ARB_ERR_CAP_HI_ADDR] = -1,
  112. [ARB_ERR_CAP_ADDR] = 0x16c,
  113. [ARB_ERR_CAP_STATUS] = 0x174,
  114. [ARB_ERR_CAP_MASTER] = 0x178,
  115. };
  116. static const int gisb_offsets_bcm7445[] = {
  117. [ARB_TIMER] = 0x008,
  118. [ARB_BP_CAP_CLR] = 0x010,
  119. [ARB_BP_CAP_HI_ADDR] = -1,
  120. [ARB_BP_CAP_ADDR] = 0x1d8,
  121. [ARB_BP_CAP_STATUS] = 0x1e0,
  122. [ARB_BP_CAP_MASTER] = 0x1e4,
  123. [ARB_ERR_CAP_CLR] = 0x7e4,
  124. [ARB_ERR_CAP_HI_ADDR] = 0x7e8,
  125. [ARB_ERR_CAP_ADDR] = 0x7ec,
  126. [ARB_ERR_CAP_STATUS] = 0x7f4,
  127. [ARB_ERR_CAP_MASTER] = 0x7f8,
  128. };
  129. struct brcmstb_gisb_arb_device {
  130. void __iomem *base;
  131. const int *gisb_offsets;
  132. bool big_endian;
  133. struct mutex lock;
  134. struct list_head next;
  135. u32 valid_mask;
  136. const char *master_names[sizeof(u32) * BITS_PER_BYTE];
  137. u32 saved_timeout;
  138. };
  139. static LIST_HEAD(brcmstb_gisb_arb_device_list);
  140. static u32 gisb_read(struct brcmstb_gisb_arb_device *gdev, int reg)
  141. {
  142. int offset = gdev->gisb_offsets[reg];
  143. if (offset < 0) {
  144. /* return 1 if the hardware doesn't have ARB_ERR_CAP_MASTER */
  145. if (reg == ARB_ERR_CAP_MASTER)
  146. return 1;
  147. else
  148. return 0;
  149. }
  150. if (gdev->big_endian)
  151. return ioread32be(gdev->base + offset);
  152. else
  153. return ioread32(gdev->base + offset);
  154. }
  155. static u64 gisb_read_address(struct brcmstb_gisb_arb_device *gdev)
  156. {
  157. u64 value;
  158. value = gisb_read(gdev, ARB_ERR_CAP_ADDR);
  159. value |= (u64)gisb_read(gdev, ARB_ERR_CAP_HI_ADDR) << 32;
  160. return value;
  161. }
  162. static u64 gisb_read_bp_address(struct brcmstb_gisb_arb_device *gdev)
  163. {
  164. u64 value;
  165. value = gisb_read(gdev, ARB_BP_CAP_ADDR);
  166. value |= (u64)gisb_read(gdev, ARB_BP_CAP_HI_ADDR) << 32;
  167. return value;
  168. }
  169. static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
  170. {
  171. int offset = gdev->gisb_offsets[reg];
  172. if (offset == -1)
  173. return;
  174. if (gdev->big_endian)
  175. iowrite32be(val, gdev->base + offset);
  176. else
  177. iowrite32(val, gdev->base + offset);
  178. }
  179. static ssize_t gisb_arb_get_timeout(struct device *dev,
  180. struct device_attribute *attr,
  181. char *buf)
  182. {
  183. struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
  184. u32 timeout;
  185. mutex_lock(&gdev->lock);
  186. timeout = gisb_read(gdev, ARB_TIMER);
  187. mutex_unlock(&gdev->lock);
  188. return sprintf(buf, "%d", timeout);
  189. }
  190. static ssize_t gisb_arb_set_timeout(struct device *dev,
  191. struct device_attribute *attr,
  192. const char *buf, size_t count)
  193. {
  194. struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
  195. int val, ret;
  196. ret = kstrtoint(buf, 10, &val);
  197. if (ret < 0)
  198. return ret;
  199. if (val == 0 || val >= 0xffffffff)
  200. return -EINVAL;
  201. mutex_lock(&gdev->lock);
  202. gisb_write(gdev, val, ARB_TIMER);
  203. mutex_unlock(&gdev->lock);
  204. return count;
  205. }
  206. static const char *
  207. brcmstb_gisb_master_to_str(struct brcmstb_gisb_arb_device *gdev,
  208. u32 masters)
  209. {
  210. u32 mask = gdev->valid_mask & masters;
  211. if (hweight_long(mask) != 1)
  212. return NULL;
  213. return gdev->master_names[ffs(mask) - 1];
  214. }
  215. static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev,
  216. const char *reason)
  217. {
  218. u32 cap_status;
  219. u64 arb_addr;
  220. u32 master;
  221. const char *m_name;
  222. char m_fmt[11];
  223. cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS);
  224. /* Invalid captured address, bail out */
  225. if (!(cap_status & ARB_ERR_CAP_STATUS_VALID))
  226. return 1;
  227. /* Read the address and master */
  228. arb_addr = gisb_read_address(gdev);
  229. master = gisb_read(gdev, ARB_ERR_CAP_MASTER);
  230. m_name = brcmstb_gisb_master_to_str(gdev, master);
  231. if (!m_name) {
  232. snprintf(m_fmt, sizeof(m_fmt), "0x%08x", master);
  233. m_name = m_fmt;
  234. }
  235. pr_crit("GISB: %s at 0x%llx [%c %s], core: %s\n",
  236. reason, arb_addr,
  237. cap_status & ARB_ERR_CAP_STATUS_WRITE ? 'W' : 'R',
  238. cap_status & ARB_ERR_CAP_STATUS_TIMEOUT ? "timeout" : "",
  239. m_name);
  240. /* clear the GISB error */
  241. gisb_write(gdev, ARB_ERR_CAP_CLEAR, ARB_ERR_CAP_CLR);
  242. return 0;
  243. }
  244. #ifdef CONFIG_MIPS
  245. static int brcmstb_bus_error_handler(struct pt_regs *regs, int is_fixup)
  246. {
  247. int ret = 0;
  248. struct brcmstb_gisb_arb_device *gdev;
  249. u32 cap_status;
  250. list_for_each_entry(gdev, &brcmstb_gisb_arb_device_list, next) {
  251. cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS);
  252. /* Invalid captured address, bail out */
  253. if (!(cap_status & ARB_ERR_CAP_STATUS_VALID)) {
  254. is_fixup = 1;
  255. goto out;
  256. }
  257. ret |= brcmstb_gisb_arb_decode_addr(gdev, "bus error");
  258. }
  259. out:
  260. return is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
  261. }
  262. #endif
  263. static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id)
  264. {
  265. brcmstb_gisb_arb_decode_addr(dev_id, "timeout");
  266. return IRQ_HANDLED;
  267. }
  268. static irqreturn_t brcmstb_gisb_tea_handler(int irq, void *dev_id)
  269. {
  270. brcmstb_gisb_arb_decode_addr(dev_id, "target abort");
  271. return IRQ_HANDLED;
  272. }
  273. static irqreturn_t brcmstb_gisb_bp_handler(int irq, void *dev_id)
  274. {
  275. struct brcmstb_gisb_arb_device *gdev = dev_id;
  276. const char *m_name;
  277. u32 bp_status;
  278. u64 arb_addr;
  279. u32 master;
  280. char m_fmt[11];
  281. bp_status = gisb_read(gdev, ARB_BP_CAP_STATUS);
  282. /* Invalid captured address, bail out */
  283. if (!(bp_status & ARB_BP_CAP_STATUS_VALID))
  284. return IRQ_HANDLED;
  285. /* Read the address and master */
  286. arb_addr = gisb_read_bp_address(gdev);
  287. master = gisb_read(gdev, ARB_BP_CAP_MASTER);
  288. m_name = brcmstb_gisb_master_to_str(gdev, master);
  289. if (!m_name) {
  290. snprintf(m_fmt, sizeof(m_fmt), "0x%08x", master);
  291. m_name = m_fmt;
  292. }
  293. pr_crit("GISB: breakpoint at 0x%llx [%c], core: %s\n",
  294. arb_addr, bp_status & ARB_BP_CAP_STATUS_WRITE ? 'W' : 'R',
  295. m_name);
  296. /* clear the GISB error */
  297. gisb_write(gdev, ARB_ERR_CAP_CLEAR, ARB_ERR_CAP_CLR);
  298. return IRQ_HANDLED;
  299. }
  300. /*
  301. * Dump out gisb errors on die or panic.
  302. */
  303. static int dump_gisb_error(struct notifier_block *self, unsigned long v,
  304. void *p);
  305. static struct notifier_block gisb_die_notifier = {
  306. .notifier_call = dump_gisb_error,
  307. };
  308. static struct notifier_block gisb_panic_notifier = {
  309. .notifier_call = dump_gisb_error,
  310. };
  311. static int dump_gisb_error(struct notifier_block *self, unsigned long v,
  312. void *p)
  313. {
  314. struct brcmstb_gisb_arb_device *gdev;
  315. const char *reason = "panic";
  316. if (self == &gisb_die_notifier)
  317. reason = "die";
  318. /* iterate over each GISB arb registered handlers */
  319. list_for_each_entry(gdev, &brcmstb_gisb_arb_device_list, next)
  320. brcmstb_gisb_arb_decode_addr(gdev, reason);
  321. return NOTIFY_DONE;
  322. }
  323. static DEVICE_ATTR(gisb_arb_timeout, S_IWUSR | S_IRUGO,
  324. gisb_arb_get_timeout, gisb_arb_set_timeout);
  325. static struct attribute *gisb_arb_sysfs_attrs[] = {
  326. &dev_attr_gisb_arb_timeout.attr,
  327. NULL,
  328. };
  329. static struct attribute_group gisb_arb_sysfs_attr_group = {
  330. .attrs = gisb_arb_sysfs_attrs,
  331. };
  332. static const struct of_device_id brcmstb_gisb_arb_of_match[] = {
  333. { .compatible = "brcm,gisb-arb", .data = gisb_offsets_bcm7445 },
  334. { .compatible = "brcm,bcm7445-gisb-arb", .data = gisb_offsets_bcm7445 },
  335. { .compatible = "brcm,bcm7435-gisb-arb", .data = gisb_offsets_bcm7435 },
  336. { .compatible = "brcm,bcm7400-gisb-arb", .data = gisb_offsets_bcm7400 },
  337. { .compatible = "brcm,bcm7278-gisb-arb", .data = gisb_offsets_bcm7278 },
  338. { .compatible = "brcm,bcm7038-gisb-arb", .data = gisb_offsets_bcm7038 },
  339. { .compatible = "brcm,bcm74165-gisb-arb", .data = gisb_offsets_bcm74165 },
  340. { },
  341. };
  342. MODULE_DEVICE_TABLE(of, brcmstb_gisb_arb_of_match);
  343. static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
  344. {
  345. struct device_node *dn = pdev->dev.of_node;
  346. struct brcmstb_gisb_arb_device *gdev;
  347. const struct of_device_id *of_id;
  348. int err, timeout_irq, tea_irq, bp_irq;
  349. unsigned int num_masters, j = 0;
  350. int i, first, last;
  351. timeout_irq = platform_get_irq(pdev, 0);
  352. tea_irq = platform_get_irq(pdev, 1);
  353. bp_irq = platform_get_irq(pdev, 2);
  354. gdev = devm_kzalloc(&pdev->dev, sizeof(*gdev), GFP_KERNEL);
  355. if (!gdev)
  356. return -ENOMEM;
  357. mutex_init(&gdev->lock);
  358. INIT_LIST_HEAD(&gdev->next);
  359. gdev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
  360. if (IS_ERR(gdev->base))
  361. return PTR_ERR(gdev->base);
  362. of_id = of_match_node(brcmstb_gisb_arb_of_match, dn);
  363. if (!of_id) {
  364. pr_err("failed to look up compatible string\n");
  365. return -EINVAL;
  366. }
  367. gdev->gisb_offsets = of_id->data;
  368. gdev->big_endian = of_device_is_big_endian(dn);
  369. err = devm_request_irq(&pdev->dev, timeout_irq,
  370. brcmstb_gisb_timeout_handler, 0, pdev->name,
  371. gdev);
  372. if (err < 0)
  373. return err;
  374. err = devm_request_irq(&pdev->dev, tea_irq,
  375. brcmstb_gisb_tea_handler, 0, pdev->name,
  376. gdev);
  377. if (err < 0)
  378. return err;
  379. /* Interrupt is optional */
  380. if (bp_irq > 0) {
  381. err = devm_request_irq(&pdev->dev, bp_irq,
  382. brcmstb_gisb_bp_handler, 0, pdev->name,
  383. gdev);
  384. if (err < 0)
  385. return err;
  386. }
  387. /* If we do not have a valid mask, assume all masters are enabled */
  388. if (of_property_read_u32(dn, "brcm,gisb-arb-master-mask",
  389. &gdev->valid_mask))
  390. gdev->valid_mask = 0xffffffff;
  391. /* Proceed with reading the litteral names if we agree on the
  392. * number of masters
  393. */
  394. num_masters = of_property_count_strings(dn,
  395. "brcm,gisb-arb-master-names");
  396. if (hweight_long(gdev->valid_mask) == num_masters) {
  397. first = ffs(gdev->valid_mask) - 1;
  398. last = fls(gdev->valid_mask) - 1;
  399. for (i = first; i < last; i++) {
  400. if (!(gdev->valid_mask & BIT(i)))
  401. continue;
  402. of_property_read_string_index(dn,
  403. "brcm,gisb-arb-master-names", j,
  404. &gdev->master_names[i]);
  405. j++;
  406. }
  407. }
  408. err = sysfs_create_group(&pdev->dev.kobj, &gisb_arb_sysfs_attr_group);
  409. if (err)
  410. return err;
  411. platform_set_drvdata(pdev, gdev);
  412. list_add_tail(&gdev->next, &brcmstb_gisb_arb_device_list);
  413. #ifdef CONFIG_MIPS
  414. mips_set_be_handler(brcmstb_bus_error_handler);
  415. #endif
  416. if (list_is_singular(&brcmstb_gisb_arb_device_list)) {
  417. register_die_notifier(&gisb_die_notifier);
  418. atomic_notifier_chain_register(&panic_notifier_list,
  419. &gisb_panic_notifier);
  420. }
  421. dev_info(&pdev->dev, "registered irqs: %d, %d\n",
  422. timeout_irq, tea_irq);
  423. return 0;
  424. }
  425. #ifdef CONFIG_PM_SLEEP
  426. static int brcmstb_gisb_arb_suspend(struct device *dev)
  427. {
  428. struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
  429. gdev->saved_timeout = gisb_read(gdev, ARB_TIMER);
  430. return 0;
  431. }
  432. /* Make sure we provide the same timeout value that was configured before, and
  433. * do this before the GISB timeout interrupt handler has any chance to run.
  434. */
  435. static int brcmstb_gisb_arb_resume_noirq(struct device *dev)
  436. {
  437. struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
  438. gisb_write(gdev, gdev->saved_timeout, ARB_TIMER);
  439. return 0;
  440. }
  441. #else
  442. #define brcmstb_gisb_arb_suspend NULL
  443. #define brcmstb_gisb_arb_resume_noirq NULL
  444. #endif
  445. static const struct dev_pm_ops brcmstb_gisb_arb_pm_ops = {
  446. .suspend = brcmstb_gisb_arb_suspend,
  447. .resume_noirq = brcmstb_gisb_arb_resume_noirq,
  448. };
  449. static struct platform_driver brcmstb_gisb_arb_driver = {
  450. .driver = {
  451. .name = "brcm-gisb-arb",
  452. .of_match_table = brcmstb_gisb_arb_of_match,
  453. .pm = &brcmstb_gisb_arb_pm_ops,
  454. },
  455. };
  456. static int __init brcm_gisb_driver_init(void)
  457. {
  458. return platform_driver_probe(&brcmstb_gisb_arb_driver,
  459. brcmstb_gisb_arb_probe);
  460. }
  461. module_init(brcm_gisb_driver_init);
  462. MODULE_AUTHOR("Broadcom");
  463. MODULE_DESCRIPTION("Broadcom STB GISB arbiter driver");
  464. MODULE_LICENSE("GPL v2");