bmips_cpu.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
  4. *
  5. * Derived from linux/arch/mips/bcm63xx/cpu.c:
  6. * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
  7. * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
  8. */
  9. #include <common.h>
  10. #include <cpu.h>
  11. #include <dm.h>
  12. #include <errno.h>
  13. #include <asm/io.h>
  14. #define REV_CHIPID_SHIFT 16
  15. #define REV_CHIPID_MASK (0xffff << REV_CHIPID_SHIFT)
  16. #define REV_LONG_CHIPID_SHIFT 12
  17. #define REV_LONG_CHIPID_MASK (0xfffff << REV_LONG_CHIPID_SHIFT)
  18. #define REV_REVID_SHIFT 0
  19. #define REV_REVID_MASK (0xff << REV_REVID_SHIFT)
  20. #define REG_BCM6328_OTP 0x62c
  21. #define BCM6328_TP1_DISABLED BIT(9)
  22. #define REG_BCM6318_STRAP_OVRDBUS 0x900
  23. #define OVRDBUS_6318_FREQ_SHIFT 23
  24. #define OVRDBUS_6318_FREQ_MASK (0x3 << OVRDBUS_6318_FREQ_SHIFT)
  25. #define REG_BCM6328_MISC_STRAPBUS 0x1a40
  26. #define STRAPBUS_6328_FCVO_SHIFT 7
  27. #define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
  28. #define REG_BCM6348_PERF_MIPSPLLCFG 0x34
  29. #define MIPSPLLCFG_6348_M1CPU_SHIFT 6
  30. #define MIPSPLLCFG_6348_M1CPU_MASK (0x7 << MIPSPLLCFG_6348_M1CPU_SHIFT)
  31. #define MIPSPLLCFG_6348_N2_SHIFT 15
  32. #define MIPSPLLCFG_6348_N2_MASK (0x1F << MIPSPLLCFG_6348_N2_SHIFT)
  33. #define MIPSPLLCFG_6348_N1_SHIFT 20
  34. #define MIPSPLLCFG_6348_N1_MASK (0x7 << MIPSPLLCFG_6348_N1_SHIFT)
  35. #define REG_BCM6358_DDR_DMIPSPLLCFG 0x12b8
  36. #define DMIPSPLLCFG_6358_M1_SHIFT 0
  37. #define DMIPSPLLCFG_6358_M1_MASK (0xff << DMIPSPLLCFG_6358_M1_SHIFT)
  38. #define DMIPSPLLCFG_6358_N1_SHIFT 23
  39. #define DMIPSPLLCFG_6358_N1_MASK (0x3f << DMIPSPLLCFG_6358_N1_SHIFT)
  40. #define DMIPSPLLCFG_6358_N2_SHIFT 29
  41. #define DMIPSPLLCFG_6358_N2_MASK (0x7 << DMIPSPLLCFG_6358_N2_SHIFT)
  42. #define REG_BCM6362_MISC_STRAPBUS 0x1814
  43. #define STRAPBUS_6362_FCVO_SHIFT 1
  44. #define STRAPBUS_6362_FCVO_MASK (0x1f << STRAPBUS_6362_FCVO_SHIFT)
  45. #define REG_BCM6368_DDR_DMIPSPLLCFG 0x12a0
  46. #define DMIPSPLLCFG_6368_P1_SHIFT 0
  47. #define DMIPSPLLCFG_6368_P1_MASK (0xf << DMIPSPLLCFG_6368_P1_SHIFT)
  48. #define DMIPSPLLCFG_6368_P2_SHIFT 4
  49. #define DMIPSPLLCFG_6368_P2_MASK (0xf << DMIPSPLLCFG_6368_P2_SHIFT)
  50. #define DMIPSPLLCFG_6368_NDIV_SHIFT 16
  51. #define DMIPSPLLCFG_6368_NDIV_MASK (0x1ff << DMIPSPLLCFG_6368_NDIV_SHIFT)
  52. #define REG_BCM6368_DDR_DMIPSPLLDIV 0x12a4
  53. #define DMIPSPLLDIV_6368_MDIV_SHIFT 0
  54. #define DMIPSPLLDIV_6368_MDIV_MASK (0xff << DMIPSPLLDIV_6368_MDIV_SHIFT)
  55. #define REG_BCM63268_MISC_STRAPBUS 0x1814
  56. #define STRAPBUS_63268_FCVO_SHIFT 21
  57. #define STRAPBUS_63268_FCVO_MASK (0xf << STRAPBUS_63268_FCVO_SHIFT)
  58. #define REG_BCM6838_OTP_BRCMBITS0 0x440
  59. #define VIPER_6838_FREQ_SHIFT 18
  60. #define VIPER_6838_FREQ_MASK (0x7 << VIPER_6838_FREQ_SHIFT)
  61. struct bmips_cpu_priv;
  62. struct bmips_cpu_hw {
  63. int (*get_cpu_desc)(struct bmips_cpu_priv *priv, char *buf, int size);
  64. ulong (*get_cpu_freq)(struct bmips_cpu_priv *);
  65. int (*get_cpu_count)(struct bmips_cpu_priv *);
  66. };
  67. struct bmips_cpu_priv {
  68. void __iomem *regs;
  69. const struct bmips_cpu_hw *hw;
  70. };
  71. /* Specific CPU Ops */
  72. static int bmips_short_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
  73. int size)
  74. {
  75. unsigned short cpu_id;
  76. unsigned char cpu_rev;
  77. u32 val;
  78. val = readl_be(priv->regs);
  79. cpu_id = (val & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
  80. cpu_rev = (val & REV_REVID_MASK) >> REV_REVID_SHIFT;
  81. snprintf(buf, size, "BCM%04X%02X", cpu_id, cpu_rev);
  82. return 0;
  83. }
  84. static int bmips_long_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
  85. int size)
  86. {
  87. unsigned int cpu_id;
  88. unsigned char cpu_rev;
  89. u32 val;
  90. val = readl_be(priv->regs);
  91. cpu_id = (val & REV_LONG_CHIPID_MASK) >> REV_LONG_CHIPID_SHIFT;
  92. cpu_rev = (val & REV_REVID_MASK) >> REV_REVID_SHIFT;
  93. snprintf(buf, size, "BCM%05X%02X", cpu_id, cpu_rev);
  94. return 0;
  95. }
  96. static ulong bcm3380_get_cpu_freq(struct bmips_cpu_priv *priv)
  97. {
  98. return 333000000;
  99. }
  100. static ulong bcm6318_get_cpu_freq(struct bmips_cpu_priv *priv)
  101. {
  102. unsigned int mips_pll_fcvo;
  103. mips_pll_fcvo = readl_be(priv->regs + REG_BCM6318_STRAP_OVRDBUS);
  104. mips_pll_fcvo = (mips_pll_fcvo & OVRDBUS_6318_FREQ_MASK)
  105. >> OVRDBUS_6318_FREQ_SHIFT;
  106. switch (mips_pll_fcvo) {
  107. case 0:
  108. return 166000000;
  109. case 1:
  110. return 400000000;
  111. case 2:
  112. return 250000000;
  113. case 3:
  114. return 333000000;
  115. default:
  116. return 0;
  117. }
  118. }
  119. static ulong bcm6328_get_cpu_freq(struct bmips_cpu_priv *priv)
  120. {
  121. unsigned int mips_pll_fcvo;
  122. mips_pll_fcvo = readl_be(priv->regs + REG_BCM6328_MISC_STRAPBUS);
  123. mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_6328_FCVO_MASK)
  124. >> STRAPBUS_6328_FCVO_SHIFT;
  125. switch (mips_pll_fcvo) {
  126. case 0x12:
  127. case 0x14:
  128. case 0x19:
  129. return 160000000;
  130. case 0x1c:
  131. return 192000000;
  132. case 0x13:
  133. case 0x15:
  134. return 200000000;
  135. case 0x1a:
  136. return 384000000;
  137. case 0x16:
  138. return 400000000;
  139. default:
  140. return 320000000;
  141. }
  142. }
  143. static ulong bcm6338_get_cpu_freq(struct bmips_cpu_priv *priv)
  144. {
  145. return 240000000;
  146. }
  147. static ulong bcm6348_get_cpu_freq(struct bmips_cpu_priv *priv)
  148. {
  149. unsigned int tmp, n1, n2, m1;
  150. tmp = readl_be(priv->regs + REG_BCM6348_PERF_MIPSPLLCFG);
  151. n1 = (tmp & MIPSPLLCFG_6348_N1_MASK) >> MIPSPLLCFG_6348_N1_SHIFT;
  152. n2 = (tmp & MIPSPLLCFG_6348_N2_MASK) >> MIPSPLLCFG_6348_N2_SHIFT;
  153. m1 = (tmp & MIPSPLLCFG_6348_M1CPU_MASK) >> MIPSPLLCFG_6348_M1CPU_SHIFT;
  154. return (16 * 1000000 * (n1 + 1) * (n2 + 2)) / (m1 + 1);
  155. }
  156. static ulong bcm6358_get_cpu_freq(struct bmips_cpu_priv *priv)
  157. {
  158. unsigned int tmp, n1, n2, m1;
  159. tmp = readl_be(priv->regs + REG_BCM6358_DDR_DMIPSPLLCFG);
  160. n1 = (tmp & DMIPSPLLCFG_6358_N1_MASK) >> DMIPSPLLCFG_6358_N1_SHIFT;
  161. n2 = (tmp & DMIPSPLLCFG_6358_N2_MASK) >> DMIPSPLLCFG_6358_N2_SHIFT;
  162. m1 = (tmp & DMIPSPLLCFG_6358_M1_MASK) >> DMIPSPLLCFG_6358_M1_SHIFT;
  163. return (16 * 1000000 * n1 * n2) / m1;
  164. }
  165. static ulong bcm6362_get_cpu_freq(struct bmips_cpu_priv *priv)
  166. {
  167. unsigned int mips_pll_fcvo;
  168. mips_pll_fcvo = readl_be(priv->regs + REG_BCM6362_MISC_STRAPBUS);
  169. mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_6362_FCVO_MASK)
  170. >> STRAPBUS_6362_FCVO_SHIFT;
  171. switch (mips_pll_fcvo) {
  172. case 0x03:
  173. case 0x0b:
  174. case 0x13:
  175. case 0x1b:
  176. return 240000000;
  177. case 0x04:
  178. case 0x0c:
  179. case 0x14:
  180. case 0x1c:
  181. return 160000000;
  182. case 0x05:
  183. case 0x0e:
  184. case 0x16:
  185. case 0x1e:
  186. case 0x1f:
  187. return 400000000;
  188. case 0x06:
  189. return 440000000;
  190. case 0x07:
  191. case 0x17:
  192. return 384000000;
  193. case 0x15:
  194. case 0x1d:
  195. return 200000000;
  196. default:
  197. return 320000000;
  198. }
  199. }
  200. static ulong bcm6368_get_cpu_freq(struct bmips_cpu_priv *priv)
  201. {
  202. unsigned int tmp, p1, p2, ndiv, m1;
  203. tmp = readl_be(priv->regs + REG_BCM6368_DDR_DMIPSPLLCFG);
  204. p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >> DMIPSPLLCFG_6368_P1_SHIFT;
  205. p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >> DMIPSPLLCFG_6368_P2_SHIFT;
  206. ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >>
  207. DMIPSPLLCFG_6368_NDIV_SHIFT;
  208. tmp = readl_be(priv->regs + REG_BCM6368_DDR_DMIPSPLLDIV);
  209. m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >> DMIPSPLLDIV_6368_MDIV_SHIFT;
  210. return (((64 * 1000000) / p1) * p2 * ndiv) / m1;
  211. }
  212. static ulong bcm63268_get_cpu_freq(struct bmips_cpu_priv *priv)
  213. {
  214. unsigned int mips_pll_fcvo;
  215. mips_pll_fcvo = readl_be(priv->regs + REG_BCM63268_MISC_STRAPBUS);
  216. mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_63268_FCVO_MASK)
  217. >> STRAPBUS_63268_FCVO_SHIFT;
  218. switch (mips_pll_fcvo) {
  219. case 0x3:
  220. case 0xe:
  221. return 320000000;
  222. case 0xa:
  223. return 333000000;
  224. case 0x2:
  225. case 0xb:
  226. case 0xf:
  227. return 400000000;
  228. default:
  229. return 0;
  230. }
  231. }
  232. static ulong bcm6838_get_cpu_freq(struct bmips_cpu_priv *priv)
  233. {
  234. unsigned int mips_viper_freq;
  235. mips_viper_freq = readl_be(priv->regs + REG_BCM6838_OTP_BRCMBITS0);
  236. mips_viper_freq = (mips_viper_freq & VIPER_6838_FREQ_MASK)
  237. >> VIPER_6838_FREQ_SHIFT;
  238. switch (mips_viper_freq) {
  239. case 0x0:
  240. return 600000000;
  241. case 0x1:
  242. return 400000000;
  243. case 0x2:
  244. return 240000000;
  245. default:
  246. return 0;
  247. }
  248. }
  249. static int bcm6328_get_cpu_count(struct bmips_cpu_priv *priv)
  250. {
  251. u32 val = readl_be(priv->regs + REG_BCM6328_OTP);
  252. if (val & BCM6328_TP1_DISABLED)
  253. return 1;
  254. else
  255. return 2;
  256. }
  257. static int bcm6345_get_cpu_count(struct bmips_cpu_priv *priv)
  258. {
  259. return 1;
  260. }
  261. static int bcm6358_get_cpu_count(struct bmips_cpu_priv *priv)
  262. {
  263. return 2;
  264. }
  265. static const struct bmips_cpu_hw bmips_cpu_bcm3380 = {
  266. .get_cpu_desc = bmips_short_cpu_desc,
  267. .get_cpu_freq = bcm3380_get_cpu_freq,
  268. .get_cpu_count = bcm6358_get_cpu_count,
  269. };
  270. static const struct bmips_cpu_hw bmips_cpu_bcm6318 = {
  271. .get_cpu_desc = bmips_short_cpu_desc,
  272. .get_cpu_freq = bcm6318_get_cpu_freq,
  273. .get_cpu_count = bcm6345_get_cpu_count,
  274. };
  275. static const struct bmips_cpu_hw bmips_cpu_bcm6328 = {
  276. .get_cpu_desc = bmips_long_cpu_desc,
  277. .get_cpu_freq = bcm6328_get_cpu_freq,
  278. .get_cpu_count = bcm6328_get_cpu_count,
  279. };
  280. static const struct bmips_cpu_hw bmips_cpu_bcm6338 = {
  281. .get_cpu_desc = bmips_short_cpu_desc,
  282. .get_cpu_freq = bcm6338_get_cpu_freq,
  283. .get_cpu_count = bcm6345_get_cpu_count,
  284. };
  285. static const struct bmips_cpu_hw bmips_cpu_bcm6348 = {
  286. .get_cpu_desc = bmips_short_cpu_desc,
  287. .get_cpu_freq = bcm6348_get_cpu_freq,
  288. .get_cpu_count = bcm6345_get_cpu_count,
  289. };
  290. static const struct bmips_cpu_hw bmips_cpu_bcm6358 = {
  291. .get_cpu_desc = bmips_short_cpu_desc,
  292. .get_cpu_freq = bcm6358_get_cpu_freq,
  293. .get_cpu_count = bcm6358_get_cpu_count,
  294. };
  295. static const struct bmips_cpu_hw bmips_cpu_bcm6362 = {
  296. .get_cpu_desc = bmips_short_cpu_desc,
  297. .get_cpu_freq = bcm6362_get_cpu_freq,
  298. .get_cpu_count = bcm6358_get_cpu_count,
  299. };
  300. static const struct bmips_cpu_hw bmips_cpu_bcm6368 = {
  301. .get_cpu_desc = bmips_short_cpu_desc,
  302. .get_cpu_freq = bcm6368_get_cpu_freq,
  303. .get_cpu_count = bcm6358_get_cpu_count,
  304. };
  305. static const struct bmips_cpu_hw bmips_cpu_bcm63268 = {
  306. .get_cpu_desc = bmips_long_cpu_desc,
  307. .get_cpu_freq = bcm63268_get_cpu_freq,
  308. .get_cpu_count = bcm6358_get_cpu_count,
  309. };
  310. static const struct bmips_cpu_hw bmips_cpu_bcm6838 = {
  311. .get_cpu_desc = bmips_short_cpu_desc,
  312. .get_cpu_freq = bcm6838_get_cpu_freq,
  313. .get_cpu_count = bcm6358_get_cpu_count,
  314. };
  315. /* Generic CPU Ops */
  316. static int bmips_cpu_get_desc(struct udevice *dev, char *buf, int size)
  317. {
  318. struct bmips_cpu_priv *priv = dev_get_priv(dev);
  319. const struct bmips_cpu_hw *hw = priv->hw;
  320. return hw->get_cpu_desc(priv, buf, size);
  321. }
  322. static int bmips_cpu_get_info(struct udevice *dev, struct cpu_info *info)
  323. {
  324. struct bmips_cpu_priv *priv = dev_get_priv(dev);
  325. const struct bmips_cpu_hw *hw = priv->hw;
  326. info->cpu_freq = hw->get_cpu_freq(priv);
  327. info->features = BIT(CPU_FEAT_L1_CACHE);
  328. info->features |= BIT(CPU_FEAT_MMU);
  329. info->features |= BIT(CPU_FEAT_DEVICE_ID);
  330. return 0;
  331. }
  332. static int bmips_cpu_get_count(struct udevice *dev)
  333. {
  334. struct bmips_cpu_priv *priv = dev_get_priv(dev);
  335. const struct bmips_cpu_hw *hw = priv->hw;
  336. return hw->get_cpu_count(priv);
  337. }
  338. static int bmips_cpu_get_vendor(struct udevice *dev, char *buf, int size)
  339. {
  340. snprintf(buf, size, "Broadcom");
  341. return 0;
  342. }
  343. static const struct cpu_ops bmips_cpu_ops = {
  344. .get_desc = bmips_cpu_get_desc,
  345. .get_info = bmips_cpu_get_info,
  346. .get_count = bmips_cpu_get_count,
  347. .get_vendor = bmips_cpu_get_vendor,
  348. };
  349. /* BMIPS CPU driver */
  350. int bmips_cpu_bind(struct udevice *dev)
  351. {
  352. struct cpu_platdata *plat = dev_get_parent_platdata(dev);
  353. plat->cpu_id = dev_read_u32_default(dev, "reg", -1);
  354. plat->device_id = read_c0_prid();
  355. return 0;
  356. }
  357. int bmips_cpu_probe(struct udevice *dev)
  358. {
  359. struct bmips_cpu_priv *priv = dev_get_priv(dev);
  360. const struct bmips_cpu_hw *hw =
  361. (const struct bmips_cpu_hw *)dev_get_driver_data(dev);
  362. priv->regs = dev_remap_addr(dev_get_parent(dev));
  363. if (!priv->regs)
  364. return -EINVAL;
  365. priv->hw = hw;
  366. return 0;
  367. }
  368. static const struct udevice_id bmips_cpu_ids[] = {
  369. {
  370. .compatible = "brcm,bcm3380-cpu",
  371. .data = (ulong)&bmips_cpu_bcm3380,
  372. }, {
  373. .compatible = "brcm,bcm6318-cpu",
  374. .data = (ulong)&bmips_cpu_bcm6318,
  375. }, {
  376. .compatible = "brcm,bcm6328-cpu",
  377. .data = (ulong)&bmips_cpu_bcm6328,
  378. }, {
  379. .compatible = "brcm,bcm6338-cpu",
  380. .data = (ulong)&bmips_cpu_bcm6338,
  381. }, {
  382. .compatible = "brcm,bcm6348-cpu",
  383. .data = (ulong)&bmips_cpu_bcm6348,
  384. }, {
  385. .compatible = "brcm,bcm6358-cpu",
  386. .data = (ulong)&bmips_cpu_bcm6358,
  387. }, {
  388. .compatible = "brcm,bcm6362-cpu",
  389. .data = (ulong)&bmips_cpu_bcm6362,
  390. }, {
  391. .compatible = "brcm,bcm6368-cpu",
  392. .data = (ulong)&bmips_cpu_bcm6368,
  393. }, {
  394. .compatible = "brcm,bcm63268-cpu",
  395. .data = (ulong)&bmips_cpu_bcm63268,
  396. }, {
  397. .compatible = "brcm,bcm6838-cpu",
  398. .data = (ulong)&bmips_cpu_bcm6838,
  399. },
  400. { /* sentinel */ }
  401. };
  402. U_BOOT_DRIVER(bmips_cpu_drv) = {
  403. .name = "bmips_cpu",
  404. .id = UCLASS_CPU,
  405. .of_match = bmips_cpu_ids,
  406. .bind = bmips_cpu_bind,
  407. .probe = bmips_cpu_probe,
  408. .priv_auto_alloc_size = sizeof(struct bmips_cpu_priv),
  409. .ops = &bmips_cpu_ops,
  410. .flags = DM_FLAG_PRE_RELOC,
  411. };
  412. #ifdef CONFIG_DISPLAY_CPUINFO
  413. int print_cpuinfo(void)
  414. {
  415. struct cpu_info cpu;
  416. struct udevice *dev;
  417. int err;
  418. char desc[100];
  419. err = uclass_get_device(UCLASS_CPU, 0, &dev);
  420. if (err)
  421. return 0;
  422. err = cpu_get_info(dev, &cpu);
  423. if (err)
  424. return 0;
  425. err = cpu_get_desc(dev, desc, sizeof(desc));
  426. if (err)
  427. return 0;
  428. printf("Chip ID: %s, MIPS: ", desc);
  429. print_freq(cpu.cpu_freq, "\n");
  430. return 0;
  431. }
  432. #endif