sbi_platform.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2019 Western Digital Corporation or its affiliates.
  5. *
  6. * Authors:
  7. * Anup Patel <anup.patel@wdc.com>
  8. */
  9. #ifndef __SBI_PLATFORM_H__
  10. #define __SBI_PLATFORM_H__
  11. /** Offset of name in struct sbi_platform */
  12. #define SBI_PLATFORM_NAME_OFFSET (0x0)
  13. /** Offset of features in struct sbi_platform */
  14. #define SBI_PLATFORM_FEATURES_OFFSET (0x40)
  15. /** Offset of hart_count in struct sbi_platform */
  16. #define SBI_PLATFORM_HART_COUNT_OFFSET (0x48)
  17. /** Offset of hart_stack_size in struct sbi_platform */
  18. #define SBI_PLATFORM_HART_STACK_SIZE_OFFSET (0x4c)
  19. #ifndef __ASSEMBLY__
  20. #include <sbi/sbi_scratch.h>
  21. /** Possible feature flags of a platform */
  22. enum sbi_platform_features {
  23. /** Platform has timer value */
  24. SBI_PLATFORM_HAS_TIMER_VALUE = (1 << 0),
  25. /** Platform has HART hotplug support */
  26. SBI_PLATFORM_HAS_HART_HOTPLUG = (1 << 1),
  27. /** Platform has PMP support */
  28. SBI_PLATFORM_HAS_PMP = (1 << 2),
  29. /** Platform has S-mode counter enable */
  30. SBI_PLATFORM_HAS_SCOUNTEREN = (1 << 3),
  31. /** Platform has M-mode counter enable */
  32. SBI_PLATFORM_HAS_MCOUNTEREN = (1 << 4),
  33. /** Platform has fault delegation support */
  34. SBI_PLATFORM_HAS_MFAULTS_DELEGATION = (1 << 5),
  35. };
  36. /** Default feature set for a platform */
  37. #define SBI_PLATFORM_DEFAULT_FEATURES \
  38. (SBI_PLATFORM_HAS_TIMER_VALUE | SBI_PLATFORM_HAS_PMP | \
  39. SBI_PLATFORM_HAS_SCOUNTEREN | SBI_PLATFORM_HAS_MCOUNTEREN | \
  40. SBI_PLATFORM_HAS_MFAULTS_DELEGATION)
  41. /** Representation of a platform */
  42. struct sbi_platform {
  43. /** Name of the platform */
  44. char name[64];
  45. /** Supported features */
  46. u64 features;
  47. /** Total number of HARTs */
  48. u32 hart_count;
  49. /** Per-HART stack size for exception/interrupt handling */
  50. u32 hart_stack_size;
  51. /** Mask representing the set of disabled HARTs */
  52. u64 disabled_hart_mask;
  53. /** Platform early initialization */
  54. int (*early_init)(bool cold_boot);
  55. /** Platform final initialization */
  56. int (*final_init)(bool cold_boot);
  57. /** Get number of PMP regions for given HART */
  58. u32 (*pmp_region_count)(u32 hartid);
  59. /**
  60. * Get PMP regions details (namely: protection, base address,
  61. * and size) for given HART
  62. */
  63. int (*pmp_region_info)(u32 hartid, u32 index, ulong *prot, ulong *addr,
  64. ulong *log2size);
  65. /** Write a character to the platform console output */
  66. void (*console_putc)(char ch);
  67. /** Read a character from the platform console input */
  68. int (*console_getc)(void);
  69. /** Initialize the platform console */
  70. int (*console_init)(void);
  71. /** Initialize the platform interrupt controller for current HART */
  72. int (*irqchip_init)(bool cold_boot);
  73. /** Send IPI to a target HART */
  74. void (*ipi_send)(u32 target_hart);
  75. /** Wait for target HART to acknowledge IPI */
  76. void (*ipi_sync)(u32 target_hart);
  77. /** Clear IPI for a target HART */
  78. void (*ipi_clear)(u32 target_hart);
  79. /** Initialize IPI for current HART */
  80. int (*ipi_init)(bool cold_boot);
  81. /** Get platform timer value */
  82. u64 (*timer_value)(void);
  83. /** Start platform timer event for current HART */
  84. void (*timer_event_start)(u64 next_event);
  85. /** Stop platform timer event for current HART */
  86. void (*timer_event_stop)(void);
  87. /** Initialize platform timer for current HART */
  88. int (*timer_init)(bool cold_boot);
  89. /** Reboot the platform */
  90. int (*system_reboot)(u32 type);
  91. /** Shutdown or poweroff the platform */
  92. int (*system_shutdown)(u32 type);
  93. } __packed;
  94. /** Get pointer to sbi_platform for sbi_scratch pointer */
  95. #define sbi_platform_ptr(__s) \
  96. ((const struct sbi_platform *)((__s)->platform_addr))
  97. /** Get pointer to sbi_platform for current HART */
  98. #define sbi_platform_thishart_ptr() \
  99. ((const struct sbi_platform *)(sbi_scratch_thishart_ptr() \
  100. ->platform_addr))
  101. /** Check whether the platform supports timer value */
  102. #define sbi_platform_has_timer_value(__p) \
  103. ((__p)->features & SBI_PLATFORM_HAS_TIMER_VALUE)
  104. /** Check whether the platform supports HART hotplug */
  105. #define sbi_platform_has_hart_hotplug(__p) \
  106. ((__p)->features & SBI_PLATFORM_HAS_HART_HOTPLUG)
  107. /** Check whether the platform has PMP support */
  108. #define sbi_platform_has_pmp(__p) ((__p)->features & SBI_PLATFORM_HAS_PMP)
  109. /** Check whether the platform supports scounteren CSR */
  110. #define sbi_platform_has_scounteren(__p) \
  111. ((__p)->features & SBI_PLATFORM_HAS_SCOUNTEREN)
  112. /** Check whether the platform supports mcounteren CSR */
  113. #define sbi_platform_has_mcounteren(__p) \
  114. ((__p)->features & SBI_PLATFORM_HAS_MCOUNTEREN)
  115. /** Check whether the platform supports fault delegation */
  116. #define sbi_platform_has_mfaults_delegation(__p) \
  117. ((__p)->features & SBI_PLATFORM_HAS_MFAULTS_DELEGATION)
  118. /**
  119. * Get name of the platform
  120. *
  121. * @param plat pointer to struct sbi_platform
  122. *
  123. * @return pointer to platform name on success and NULL on failure
  124. */
  125. static inline const char *sbi_platform_name(const struct sbi_platform *plat)
  126. {
  127. if (plat)
  128. return plat->name;
  129. return NULL;
  130. }
  131. /**
  132. * Check whether the given HART is disabled
  133. *
  134. * @param plat pointer to struct sbi_platform
  135. * @param hartid HART ID
  136. *
  137. * @return TRUE if HART is disabled and FALSE otherwise
  138. */
  139. static inline bool sbi_platform_hart_disabled(const struct sbi_platform *plat,
  140. u32 hartid)
  141. {
  142. if (plat && (plat->disabled_hart_mask & (1 << hartid)))
  143. return TRUE;
  144. return FALSE;
  145. }
  146. /**
  147. * Get total number of HARTs supported by the platform
  148. *
  149. * @param plat pointer to struct sbi_platform
  150. *
  151. * @return total number of HARTs
  152. */
  153. static inline u32 sbi_platform_hart_count(const struct sbi_platform *plat)
  154. {
  155. if (plat)
  156. return plat->hart_count;
  157. return 0;
  158. }
  159. /**
  160. * Get per-HART stack size for exception/interrupt handling
  161. *
  162. * @param plat pointer to struct sbi_platform
  163. *
  164. * @return stack size in bytes
  165. */
  166. static inline u32 sbi_platform_hart_stack_size(const struct sbi_platform *plat)
  167. {
  168. if (plat)
  169. return plat->hart_stack_size;
  170. return 0;
  171. }
  172. /**
  173. * Early initialization for current HART
  174. *
  175. * @param plat pointer to struct sbi_platform
  176. * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE)
  177. *
  178. * @return 0 on success and negative error code on failure
  179. */
  180. static inline int sbi_platform_early_init(const struct sbi_platform *plat,
  181. bool cold_boot)
  182. {
  183. if (plat && plat->early_init)
  184. return plat->early_init(cold_boot);
  185. return 0;
  186. }
  187. /**
  188. * Final initialization for current HART
  189. *
  190. * @param plat pointer to struct sbi_platform
  191. * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE)
  192. *
  193. * @return 0 on success and negative error code on failure
  194. */
  195. static inline int sbi_platform_final_init(const struct sbi_platform *plat,
  196. bool cold_boot)
  197. {
  198. if (plat && plat->final_init)
  199. return plat->final_init(cold_boot);
  200. return 0;
  201. }
  202. /**
  203. * Get the number of PMP regions of a HART
  204. *
  205. * @param plat pointer to struct sbi_platform
  206. * @param hartid HART ID
  207. *
  208. * @return number of PMP regions
  209. */
  210. static inline u32 sbi_platform_pmp_region_count(const struct sbi_platform *plat,
  211. u32 hartid)
  212. {
  213. if (plat && plat->pmp_region_count)
  214. return plat->pmp_region_count(hartid);
  215. return 0;
  216. }
  217. /**
  218. * Get PMP regions details (namely: protection, base address,
  219. * and size) of a HART
  220. *
  221. * @param plat pointer to struct sbi_platform
  222. * @param hartid HART ID
  223. * @param index index of PMP region for which we want details
  224. * @param prot output pointer for PMP region protection
  225. * @param addr output pointer for PMP region base address
  226. * @param log2size output pointer for log-of-2 PMP region size
  227. *
  228. * @return 0 on success and negative error code on failure
  229. */
  230. static inline int sbi_platform_pmp_region_info(const struct sbi_platform *plat,
  231. u32 hartid, u32 index,
  232. ulong *prot, ulong *addr,
  233. ulong *log2size)
  234. {
  235. if (plat && plat->pmp_region_info)
  236. return plat->pmp_region_info(hartid, index, prot, addr,
  237. log2size);
  238. return 0;
  239. }
  240. /**
  241. * Write a character to the platform console output
  242. *
  243. * @param plat pointer to struct sbi_platform
  244. * @param ch character to write
  245. */
  246. static inline void sbi_platform_console_putc(const struct sbi_platform *plat,
  247. char ch)
  248. {
  249. if (plat && plat->console_putc)
  250. plat->console_putc(ch);
  251. }
  252. /**
  253. * Read a character from the platform console input
  254. *
  255. * @param plat pointer to struct sbi_platform
  256. *
  257. * @return character read from console input
  258. */
  259. static inline int sbi_platform_console_getc(const struct sbi_platform *plat)
  260. {
  261. if (plat && plat->console_getc)
  262. return plat->console_getc();
  263. return -1;
  264. }
  265. /**
  266. * Initialize the platform console
  267. *
  268. * @param plat pointer to struct sbi_platform
  269. *
  270. * @return 0 on success and negative error code on failure
  271. */
  272. static inline int sbi_platform_console_init(const struct sbi_platform *plat)
  273. {
  274. if (plat && plat->console_init)
  275. return plat->console_init();
  276. return 0;
  277. }
  278. /**
  279. * Initialize the platform interrupt controller for current HART
  280. *
  281. * @param plat pointer to struct sbi_platform
  282. * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE)
  283. *
  284. * @return 0 on success and negative error code on failure
  285. */
  286. static inline int sbi_platform_irqchip_init(const struct sbi_platform *plat,
  287. bool cold_boot)
  288. {
  289. if (plat && plat->irqchip_init)
  290. return plat->irqchip_init(cold_boot);
  291. return 0;
  292. }
  293. /**
  294. * Send IPI to a target HART
  295. *
  296. * @param plat pointer to struct sbi_platform
  297. * @param target_hart HART ID of IPI target
  298. */
  299. static inline void sbi_platform_ipi_send(const struct sbi_platform *plat,
  300. u32 target_hart)
  301. {
  302. if (plat && plat->ipi_send)
  303. plat->ipi_send(target_hart);
  304. }
  305. /**
  306. * Wait for target HART to acknowledge IPI
  307. *
  308. * @param plat pointer to struct sbi_platform
  309. * @param target_hart HART ID of IPI target
  310. */
  311. static inline void sbi_platform_ipi_sync(const struct sbi_platform *plat,
  312. u32 target_hart)
  313. {
  314. if (plat && plat->ipi_sync)
  315. plat->ipi_sync(target_hart);
  316. }
  317. /**
  318. * Clear IPI for a target HART
  319. *
  320. * @param plat pointer to struct sbi_platform
  321. * @param target_hart HART ID of IPI target
  322. */
  323. static inline void sbi_platform_ipi_clear(const struct sbi_platform *plat,
  324. u32 target_hart)
  325. {
  326. if (plat && plat->ipi_clear)
  327. plat->ipi_clear(target_hart);
  328. }
  329. /**
  330. * Initialize the platform IPI support for current HART
  331. *
  332. * @param plat pointer to struct sbi_platform
  333. * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE)
  334. *
  335. * @return 0 on success and negative error code on failure
  336. */
  337. static inline int sbi_platform_ipi_init(const struct sbi_platform *plat,
  338. bool cold_boot)
  339. {
  340. if (plat && plat->ipi_init)
  341. return plat->ipi_init(cold_boot);
  342. return 0;
  343. }
  344. /**
  345. * Get platform timer value
  346. *
  347. * @param plat pointer to struct sbi_platform
  348. *
  349. * @return 64bit timer value
  350. */
  351. static inline u64 sbi_platform_timer_value(const struct sbi_platform *plat)
  352. {
  353. if (plat && plat->timer_value)
  354. return plat->timer_value();
  355. return 0;
  356. }
  357. /**
  358. * Start platform timer event for current HART
  359. *
  360. * @param plat pointer to struct struct sbi_platform
  361. * @param next_event timer value when timer event will happen
  362. */
  363. static inline void
  364. sbi_platform_timer_event_start(const struct sbi_platform *plat, u64 next_event)
  365. {
  366. if (plat && plat->timer_event_start)
  367. plat->timer_event_start(next_event);
  368. }
  369. /**
  370. * Stop platform timer event for current HART
  371. *
  372. * @param plat pointer to struct sbi_platform
  373. */
  374. static inline void
  375. sbi_platform_timer_event_stop(const struct sbi_platform *plat)
  376. {
  377. if (plat && plat->timer_event_stop)
  378. plat->timer_event_stop();
  379. }
  380. /**
  381. * Initialize the platform timer for current HART
  382. *
  383. * @param plat pointer to struct sbi_platform
  384. * @param cold_boot whether cold boot (TRUE) or warm_boot (FALSE)
  385. *
  386. * @return 0 on success and negative error code on failure
  387. */
  388. static inline int sbi_platform_timer_init(const struct sbi_platform *plat,
  389. bool cold_boot)
  390. {
  391. if (plat && plat->timer_init)
  392. return plat->timer_init(cold_boot);
  393. return 0;
  394. }
  395. /**
  396. * Reboot the platform
  397. *
  398. * @param plat pointer to struct sbi_platform
  399. * @param type type of reboot
  400. *
  401. * @return 0 on success and negative error code on failure
  402. */
  403. static inline int sbi_platform_system_reboot(const struct sbi_platform *plat,
  404. u32 type)
  405. {
  406. if (plat && plat->system_reboot)
  407. return plat->system_reboot(type);
  408. return 0;
  409. }
  410. /**
  411. * Shutdown or poweroff the platform
  412. *
  413. * @param plat pointer to struct sbi_platform
  414. * @param type type of shutdown or poweroff
  415. *
  416. * @return 0 on success and negative error code on failure
  417. */
  418. static inline int sbi_platform_system_shutdown(const struct sbi_platform *plat,
  419. u32 type)
  420. {
  421. if (plat && plat->system_shutdown)
  422. return plat->system_shutdown(type);
  423. return 0;
  424. }
  425. #endif
  426. #endif