blob: 3dbf781ef4fd63ee0f23bdb75a4f421b83b1a5de [file] [log] [blame]
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +08001/*
2 * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7#include <stdio.h>
8#include <FreeRTOS.h>
bangzheng.liu4d71f922022-09-29 16:12:20 +08009#include "interrupt_control_pic.h"
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080010#include "common.h"
11#include "register.h"
12
13void pic_set_threshold(uint32_t threshold)
14{
xiaohu.huang38262102022-05-06 22:21:48 +080015 volatile uint32_t *threshold_ptr = (uint32_t *)(PIC_CTRL_ADDR + PIC_THRESHOLD_OFFSET);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080016
xiaohu.huang38262102022-05-06 22:21:48 +080017 *threshold_ptr = threshold;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080018}
19
20void pic_enable_interrupt(uint32_t source)
21{
xiaohu.huang38262102022-05-06 22:21:48 +080022 volatile uint32_t *current_ptr =
23 (volatile uint32_t *)(PIC_CTRL_ADDR + PIC_ENABLE_OFFSET +
24 ((source >> 3) & (~0x3)) // Source number divide 32 and then
25 // multip 4 (bytes)
26 );
27 uint32_t current = *current_ptr;
28
29 current = current | (1 << (source & 0x1f)); // Only check the least 5 bits
30 *current_ptr = current;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080031}
32
xiaohu.huang38262102022-05-06 22:21:48 +080033void pic_disable_interrupt(uint32_t source)
34{
35 volatile uint32_t *current_ptr =
36 (volatile uint32_t *)(PIC_CTRL_ADDR + PIC_ENABLE_OFFSET +
37 ((source >> 3) & (~0x3)) // Source number divide 32 and then
38 // multip 4 (bytes)
39 );
40 uint32_t current = *current_ptr;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080041
xiaohu.huang38262102022-05-06 22:21:48 +080042 current = current & ~((1 << (source & 0x1f))); // Only check the least 5 bits
43 *current_ptr = current;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080044}
45
xiaohu.huang38262102022-05-06 22:21:48 +080046void pic_set_priority(uint32_t source, uint32_t priority)
47{
48 if (PIC_NUM_PRIORITIES > 0) {
49 // Each priority reg occupy a word, so multiple 2
50 volatile uint32_t *priority_ptr =
51 (volatile uint32_t *)(PIC_CTRL_ADDR + PIC_PRIORITY_OFFSET +
52 (source
53 << PIC_PRIORITY_SHIFT_PER_SOURCE));
54 *priority_ptr = priority;
55 }
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080056}
57
xiaohu.huang38262102022-05-06 22:21:48 +080058uint32_t pic_claim_interrupt(void)
59{
60 volatile uint32_t *claim_addr = (volatile uint32_t *)(PIC_CTRL_ADDR + PIC_CLAIM_OFFSET);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080061
xiaohu.huang38262102022-05-06 22:21:48 +080062 return *claim_addr;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080063}
64
xiaohu.huang38262102022-05-06 22:21:48 +080065uint32_t pic_check_eip(void)
66{
67 volatile uint32_t *eip_addr = (volatile uint32_t *)(PIC_CTRL_ADDR + PIC_EIP_OFFSET);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080068
xiaohu.huang38262102022-05-06 22:21:48 +080069 return *eip_addr;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080070}
71
xiaohu.huang38262102022-05-06 22:21:48 +080072void pic_complete_interrupt(uint32_t source)
73{
74 volatile uint32_t *claim_addr = (volatile uint32_t *)(PIC_CTRL_ADDR + PIC_CLAIM_OFFSET);
75 *claim_addr = source;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080076}
77
78void DefaultInterruptHandler(void)
79{
80}
81
xiaohu.huang38262102022-05-06 22:21:48 +080082int RegisterIrq(uint32_t int_num, uint32_t int_priority, function_ptr_t handler)
83{
84 pic_interrupt_handlers[int_num] = handler;
85 pic_set_priority(int_num, int_priority);
86 // pic_enable_interrupt (int_num);
87 return 0;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080088}
89
90int UnRegisterIrq(uint32_t int_num)
91{
xiaohu.huang38262102022-05-06 22:21:48 +080092 pic_interrupt_handlers[int_num] = DefaultInterruptHandler;
93 pic_set_priority(int_num, 0);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080094
xiaohu.huang38262102022-05-06 22:21:48 +080095 return 0;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080096}
97
98int EnableIrq(uint32_t ulIrq)
99{
xiaohu.huang38262102022-05-06 22:21:48 +0800100 UBaseType_t uxSavedInterruptStatus;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800101
xiaohu.huang38262102022-05-06 22:21:48 +0800102 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
103 pic_enable_interrupt(ulIrq);
104 portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
105 return 0;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800106}
107
108int DisableIrq(uint32_t ulIrq)
109{
xiaohu.huang38262102022-05-06 22:21:48 +0800110 UBaseType_t uxSavedInterruptStatus;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800111
xiaohu.huang38262102022-05-06 22:21:48 +0800112 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
113 pic_disable_interrupt(ulIrq);
114 portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
115 return 0;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800116}
117
118int SetIrqPriority(uint32_t ulIrq, uint32_t ulPri)
119{
xiaohu.huang38262102022-05-06 22:21:48 +0800120 pic_set_priority(ulIrq, ulPri);
121 return 0;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800122}
123
124static unsigned int irq_setting[IRQ_EN_REG_NUM];
125/*N205 does not support clear pending irq.*
126 *Need use work around to clear pending: *
127 *1. disable irq (MIE) *
128 *2. store and disable current enable irq *
129 *3. enable target irq *
130 *4. claim and complete target irq *
131 *5. disable target irq *
132 *6. restore current irq enable setting *
133 *7. enable irq (MIE)
xiaohu.huang38262102022-05-06 22:21:48 +0800134 */
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800135int ClearPendingIrq(uint32_t ulIrq)
136{
137 unsigned int i;
xiaohu.huang38262102022-05-06 22:21:48 +0800138 volatile uint32_t *current_ptr;
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800139 unsigned long irq_status;
140
141 irq_status = interrupt_status_get();
bangzheng.liu27822a82022-09-29 16:34:05 +0800142 if (irq_status & 0x1)
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800143 interrupt_disable();
144
xiaohu.huang38262102022-05-06 22:21:48 +0800145 for (i = 0; i < IRQ_EN_REG_NUM; i++) {
146 current_ptr = (volatile uint32_t *)(PIC_CTRL_ADDR + PIC_ENABLE_OFFSET + i * 4);
147 irq_setting[i] = REG32(current_ptr);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800148 REG32(current_ptr) = 0;
149 }
150 pic_enable_interrupt(ulIrq);
151 i = pic_claim_interrupt();
bangzheng.liu27822a82022-09-29 16:34:05 +0800152 pic_complete_interrupt(i);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800153 pic_disable_interrupt(ulIrq);
154
xiaohu.huang38262102022-05-06 22:21:48 +0800155 for (i = 0; i < IRQ_EN_REG_NUM; i++) {
156 current_ptr = (volatile uint32_t *)(PIC_CTRL_ADDR + PIC_ENABLE_OFFSET + i * 4);
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800157 REG32(current_ptr) = irq_setting[i];
158 }
159
bangzheng.liu27822a82022-09-29 16:34:05 +0800160 if (irq_status & 0x1)
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +0800161 interrupt_enable();
162
163 return 0;
164}