mt_scp_l1c.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2018. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. *
  31. * The following software/firmware and/or related documentation ("MediaTek Software")
  32. * have been modified by MediaTek Inc. All revisions are subject to any receiver\'s
  33. * applicable license agreements with MediaTek Inc.
  34. */
  35. #include <stdint.h>
  36. #include <debug.h>
  37. #include <platform/mt_typedefs.h>
  38. #include <platform/mt_scp.h>
  39. static l1c_status_t l1c_set_size(uint32_t l1c_type, l1c_size_t l1c_size)
  40. {
  41. /* L1C size is invalid */
  42. if (l1c_size >= L1C_SIZE_MAX) {
  43. return L1C_STATUS_ERROR_L1C_SIZE;
  44. }
  45. /* Set L1C size */
  46. L1C_SEL(l1c_type)->L1C_CON &= ~L1C_CON_L1CSIZE_MASK;
  47. L1C_SEL(l1c_type)->L1C_CON |= (l1c_size << L1C_CON_L1CSIZE_OFFSET);
  48. /* When L1C size is 0KB, make sure the L1C is disabled */
  49. if (l1c_size == L1C_SIZE_0KB) {
  50. L1C_SEL(l1c_type)->L1C_CON = 0;
  51. }
  52. dprintf(CRITICAL, "L1C_CON, addr:0x%x, value:0x%x\n",
  53. (unsigned int)&L1C_SEL(l1c_type)->L1C_CON,
  54. L1C_SEL(l1c_type)->L1C_CON);
  55. return L1C_STATUS_OK;
  56. }
  57. static l1c_status_t l1c_region_enable(uint32_t l1c_type, l1c_region_t region)
  58. {
  59. /* Region is invalid */
  60. if (region >= L1C_REGION_MAX) {
  61. return L1C_STATUS_ERROR_REGION;
  62. }
  63. /* The region should be configured before region is enabled */
  64. if (L1C_SEL(l1c_type)->L1C_ENTRY_N[region] & L1C_ENTRY_N_C_MASK) {
  65. L1C_SEL(l1c_type)->L1C_REGION_EN |= (1 << region);
  66. } else {
  67. return L1C_STATUS_ERROR;
  68. }
  69. return L1C_STATUS_OK;
  70. }
  71. static l1c_status_t l1c_region_config(uint32_t l1c_type, l1c_region_t region,
  72. const l1c_region_config_t *region_config)
  73. {
  74. /* Region is invalid */
  75. if (region >= L1C_REGION_MAX) {
  76. return L1C_STATUS_ERROR_REGION;
  77. }
  78. /* Parameter check */
  79. if (region_config == NULL) {
  80. return L1C_STATUS_INVALID_PARAMETER;
  81. }
  82. /* The region address must be 4KB aligned */
  83. if (region_config->l1c_region_address & (MTK_L1C_REGION_SIZE_UNIT - 1)) {
  84. //assert(0);
  85. return L1C_STATUS_ERROR_REGION_ADDRESS;
  86. }
  87. /* The region size must be 4KB aligned */
  88. if (region_config->l1c_region_size & (MTK_L1C_REGION_SIZE_UNIT - 1)) {
  89. //assert(0);
  90. return L1C_STATUS_ERROR_REGION_SIZE;
  91. }
  92. /* Write the region setting to corresponding register */
  93. L1C_SEL(l1c_type)->L1C_ENTRY_N[region] = region_config->l1c_region_address;
  94. L1C_SEL(l1c_type)->L1C_END_ENTRY_N[region] = region_config->l1c_region_address +
  95. region_config->l1c_region_size;
  96. /* Set this bit when region is configured, and this bit will be double checked in l1c_region_enable() function */
  97. L1C_SEL(l1c_type)->L1C_ENTRY_N[region] |= L1C_ENTRY_N_C_MASK;
  98. /* Update the global variable */
  99. return L1C_STATUS_OK;
  100. }
  101. static l1c_status_t l1c_enable(uint32_t l1c_type)
  102. {
  103. /* Enable L1C */
  104. L1C_SEL(l1c_type)->L1C_CON |= L1C_CON_MCEN_MASK | L1C_CON_CNTEN0_MASK | L1C_CON_CNTEN1_MASK;
  105. return L1C_STATUS_OK;
  106. }
  107. static l1c_status_t l1c_invalidate_all_l1c_lines(uint32_t l1c_type)
  108. {
  109. /* Invalidate all L1C lines */
  110. L1C_SEL(l1c_type)->L1C_OP &= ~L1C_OP_OP_MASK;
  111. L1C_SEL(l1c_type)->L1C_OP |= ((L1C_INVALIDATE_ALL_LINES << L1C_OP_OP_OFFSET) | L1C_OP_EN_MASK);
  112. return L1C_STATUS_OK;
  113. }
  114. l1c_status_t l1c_flush_all_l1c_lines(uint32_t l1c_type)
  115. {
  116. /* Flush all L1C lines */
  117. L1C_SEL(l1c_type)->L1C_OP &= ~L1C_OP_OP_MASK;
  118. L1C_SEL(l1c_type)->L1C_OP |= ((L1C_FLUSH_ALL_LINES << L1C_OP_OP_OFFSET) | L1C_OP_EN_MASK);
  119. return L1C_STATUS_OK;
  120. }
  121. static l1c_status_t l1c_init(uint32_t l1c_type)
  122. {
  123. l1c_region_t region;
  124. /* If l1c is enable , flush and invalidate all l1c lines */
  125. if (L1C_SEL(l1c_type)->L1C_CON & L1C_CON_MCEN_MASK) {
  126. L1C_SEL(l1c_type)->L1C_OP &= ~L1C_OP_OP_MASK;
  127. L1C_SEL(l1c_type)->L1C_OP |= ((L1C_FLUSH_ALL_LINES << L1C_OP_OP_OFFSET) | L1C_OP_EN_MASK);
  128. L1C_SEL(l1c_type)->L1C_OP &= ~L1C_OP_OP_MASK;
  129. L1C_SEL(l1c_type)->L1C_OP |= ((L1C_INVALIDATE_ALL_LINES << L1C_OP_OP_OFFSET) | L1C_OP_EN_MASK);
  130. }
  131. /* Set L1C related registers to default value*/
  132. L1C_SEL(l1c_type)->L1C_CON = 0;
  133. L1C_SEL(l1c_type)->L1C_REGION_EN = 0;
  134. /* Set L1C region registers to default value and update the global variable */
  135. for (region = L1C_REGION_0; region < L1C_REGION_MAX; region ++) {
  136. /* Set L1C related registers to default value */
  137. L1C_SEL(l1c_type)->L1C_ENTRY_N[region] = 0;
  138. L1C_SEL(l1c_type)->L1C_END_ENTRY_N[region] = 0;
  139. }
  140. return L1C_STATUS_OK;
  141. }
  142. void scp_l1c_init(unsigned int l1c_icon, unsigned int l1c_dcon)
  143. {
  144. l1c_region_t region, region_number;
  145. uint32_t status = 0;
  146. /* Max region number is 16 */
  147. l1c_region_config_t region_cfg_tbl[] = {
  148. {DRAM_REGION_BASE, DRAM_REGION_LENGTH},
  149. };
  150. dprintf(CRITICAL, "DRAM l1cable region:0x%x~0x%x\n", DRAM_REGION_BASE, DRAM_REGION_BASE + DRAM_REGION_LENGTH);
  151. status |= l1c_init(L1C_IL1C);
  152. status |= l1c_init(L1C_DL1C);
  153. status |= l1c_set_size(L1C_IL1C, L1C_INDEX(l1c_icon));
  154. status |= l1c_set_size(L1C_DL1C, L1C_INDEX(l1c_dcon));
  155. region_number = (l1c_region_t)(sizeof(region_cfg_tbl) / sizeof(region_cfg_tbl[0]));
  156. for (region = L1C_REGION_0; region < region_number; region++) {
  157. status |= l1c_region_config(L1C_IL1C, region, &region_cfg_tbl[region]);
  158. status |= l1c_region_enable(L1C_IL1C, region);
  159. }
  160. for (region = L1C_REGION_0; region < region_number; region++) {
  161. status |= l1c_region_config(L1C_DL1C, region, &region_cfg_tbl[region]);
  162. status |= l1c_region_enable(L1C_DL1C, region);
  163. }
  164. L1C_SEL(L1C_IL1C)->L1C_CON |= (uint32_t)(l1c_icon & L1C_WAY_NUM);
  165. status |= l1c_enable(L1C_IL1C);
  166. status |= l1c_enable(L1C_DL1C);
  167. /* add for l1c sync bug(mips) */
  168. l1c_invalidate_all_l1c_lines(L1C_IL1C);
  169. //l1c_flush_all_l1c_lines(L1C_DL1C);
  170. l1c_invalidate_all_l1c_lines(L1C_DL1C);
  171. dprintf(CRITICAL, "l1c init status: 0x%x\n", status);
  172. }