File indexing completed on 2025-05-11 08:22:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <bsp.h>
0029 #include <bsp/bootcard.h>
0030 #include <bsp/fatal.h>
0031 #include <bsp/fdt.h>
0032 #include <bsp/irq-generic.h>
0033 #include <bsp/linker-symbols.h>
0034 #include <dev/clock/arm-generic-timer.h>
0035 #include <libcpu/arm-cp15.h>
0036 #include <arm/freescale/imx/imx6ul_ccmreg.h>
0037
0038 #include <libfdt.h>
0039
0040 #define MAGIC_IRQ_OFFSET 32
0041
0042 void *imx_get_reg_of_node(const void *fdt, int node)
0043 {
0044 int len;
0045 const uint32_t *val;
0046
0047 val = fdt_getprop(fdt, node, "reg", &len);
0048 if (val == NULL || len < 4) {
0049 return NULL;
0050 }
0051
0052 return (void *) fdt32_to_cpu(val[0]);
0053 }
0054
0055 rtems_vector_number imx_get_irq_of_node(
0056 const void *fdt,
0057 int node,
0058 size_t index
0059 )
0060 {
0061 int len;
0062 const uint32_t *val;
0063
0064 val = fdt_getprop(fdt, node, "interrupts", &len);
0065 if (val == NULL || len < (int) ((index + 1) * 12)) {
0066 return BSP_INTERRUPT_VECTOR_INVALID;
0067 }
0068
0069 return fdt32_to_cpu(val[index * 3 + 1]) + MAGIC_IRQ_OFFSET;
0070 }
0071
0072 uint32_t bsp_fdt_map_intr(const uint32_t *intr, size_t icells)
0073 {
0074 return intr[1] + MAGIC_IRQ_OFFSET;
0075 }
0076
0077 static bool imx_is_imx6(const void *fdt)
0078 {
0079
0080
0081
0082
0083
0084
0085
0086 int node;
0087
0088 node = fdt_node_offset_by_compatible(fdt, -1, "fsl,imx6ul");
0089 if (node >= 0) {
0090 return true;
0091 }
0092
0093 node = fdt_node_offset_by_compatible(fdt, -1, "fsl,imx6ull");
0094 if (node >= 0) {
0095 return true;
0096 }
0097
0098 return false;
0099 }
0100
0101 #define SYSCNT_CNTCR (0x0)
0102 #define SYSCNT_CNTCR_ENABLE (1 << 0)
0103 #define SYSCNT_CNTCR_HDBG (1 << 1)
0104 #define SYSCNT_CNTCR_FCREQ(n) (1 << (8 + (n)))
0105 #define SYSCNT_CNTFID(n) (0x20 + 4 * (n))
0106
0107 static uint32_t imx_syscnt_enable_and_return_frequency(const void *fdt)
0108 {
0109 uint32_t freq;
0110 volatile void *syscnt_base;
0111
0112
0113 if (imx_is_imx6(fdt)) {
0114 syscnt_base = (void *)0x021dc000;
0115 } else {
0116 syscnt_base = (void *)0x306c0000;
0117 }
0118
0119 freq = *(uint32_t *)(syscnt_base + SYSCNT_CNTFID(0));
0120
0121 arm_cp15_set_counter_frequency(freq);
0122
0123 *(uint32_t *)(syscnt_base + SYSCNT_CNTCR) =
0124 SYSCNT_CNTCR_ENABLE |
0125 SYSCNT_CNTCR_HDBG |
0126 SYSCNT_CNTCR_FCREQ(0);
0127
0128 return freq;
0129 }
0130
0131 void arm_generic_timer_get_config(
0132 uint32_t *frequency,
0133 uint32_t *irq
0134 )
0135 {
0136 const void *fdt;
0137 int node;
0138 int len;
0139 const uint32_t *val;
0140
0141 fdt = bsp_fdt_get();
0142 node = fdt_path_offset(fdt, "/timer");
0143
0144 val = fdt_getprop(fdt, node, "clock-frequency", &len);
0145 if (val != NULL && len >= 4) {
0146 *frequency = fdt32_to_cpu(val[0]);
0147 } else {
0148
0149
0150
0151
0152 *frequency = imx_syscnt_enable_and_return_frequency(fdt);
0153 }
0154
0155
0156 *irq = imx_get_irq_of_node(fdt, node, 0) - 16;
0157 }
0158
0159 uintptr_t imx_gic_dist_base;
0160
0161 static void imx_find_gic(const void *fdt)
0162 {
0163 int node;
0164
0165 node = fdt_path_offset(fdt, "/interrupt-controller");
0166 if (node < 0) {
0167 node = fdt_path_offset(fdt, "/soc/interrupt-controller");
0168 }
0169 imx_gic_dist_base = (uintptr_t) imx_get_reg_of_node(fdt, node);
0170
0171 #if defined(RTEMS_SMP)
0172
0173
0174
0175
0176
0177 rtems_cache_flush_multiple_data_lines(
0178 &imx_gic_dist_base,
0179 sizeof(imx_gic_dist_base)
0180 );
0181 #endif
0182 }
0183
0184 static void imx_ccm_enable_eth2_clk(void)
0185 {
0186 const void *fdt = bsp_fdt_get();
0187
0188 if (imx_is_imx6(fdt)) {
0189 int node;
0190 volatile imx6ul_ccm_analog *ccm_analog = NULL;
0191
0192 node = fdt_node_offset_by_compatible(fdt, -1, "fsl,imx6ul-anatop");
0193 if (node >= 0) {
0194 ccm_analog = imx_get_reg_of_node(fdt, node);
0195 }
0196 if (ccm_analog != NULL) {
0197 ccm_analog->pll_enet_set = IMX6UL_CCM_ANALOG_PLL_ENET_ENET2_125M_EN;
0198 }
0199 }
0200 }
0201
0202 void bsp_start(void)
0203 {
0204 imx_find_gic(bsp_fdt_get());
0205 bsp_interrupt_initialize();
0206 rtems_cache_coherent_add_area(
0207 bsp_section_nocacheheap_begin,
0208 (uintptr_t) bsp_section_nocacheheap_size
0209 );
0210 imx_ccm_enable_eth2_clk();
0211 }