1 /*
2  * ===========================================================================================
3  *
4  *       Filename:  hal_eise.c
5  *
6  *    Description:  hal impl. of eise.
7  *
8  *        Version:  Melis3.0
9  *         Create:  2020-01-08 14:20:56
10  *       Revision:  none
11  *       Compiler:
12  *
13  *         Author:  ganqiuye(ganqiuye@allwinnertech.com)
14  *   Organization:  SWC-MPD
15  *  Last Modified:  2020-04-02 17:33:33
16  *
17  * ===========================================================================================
18  */
19 
20 
21 #include <interrupt.h>
22 #include <hal_queue.h>
23 #include <sunxi_hal_common.h>
24 #include "sunxi_hal_eise.h"
25 #include <init.h>
26 #include <hal_clk.h>
27 #include <interrupt.h>
28 #include <log.h>
29 #define eise_err(x, arg...) printf("[EISE_ERR] (%s, %d)"x"\n", __func__, __LINE__, ##arg)
30 #define eise_warn(x, arg...) printf("[EISE_WARN] (%s, %d)"x"\n", __func__, __LINE__, ##arg)
31 #define eise_print(x, arg...) printf("[EISE] (%s, %d)"x"\n", __func__, __LINE__, ##arg)
32 #define eise_debug(x, arg...) printf("[EISE_DEBUG] (%s, %d)"x"\n", __func__, __LINE__, ##arg)
33 
34 typedef enum
35 {
36     EISE_WRITE_REGISTER = 0x100,
37     EISE_READ_REGISTER,
38     ENABLE_EISE,
39     DISABLE_EISE,
40     WAIT_EISE_FINISH,
41     SET_EISE_FREQ
42 } hal_eise_transfer_cmd_t;
43 
44 
45 #define EISE_CLK_HIGH_WATER  (700)
46 #define EISE_CLK_LOW_WATER   (300)
47 #define EISE_DEFAULT_RATE    (432000000)
48 #define EISE_INTERRUPT_ID    (58)
49 #define EISE_BASE_ADDR       (0x02300000)
50 #define CCMU_BASE_ADDR       (0x03001000)
51 
52 static hal_eise_t sHalEise;
53 
eise_interrupt(int irq,void * dev_id)54 static irqreturn_t eise_interrupt(int irq, void* dev_id)
55 {
56     int irq_status;
57     hal_eise_t* pHe = &sHalEise;
58     hal_writel(0x00, pHe->eise_base_addr + EISE_INTERRUPT_EN);
59 
60     irq_status = hal_readl(pHe->eise_base_addr + EISE_INTERRUPT_STATUS);
61     if (0x00 != (irq_status & 0x07))
62     {
63         hal_sem_post(pHe->hal_sem);
64     }
65 /*
66     if (0x01 != (irq_status & 0x01))
67     {
68         pHe->err_cnt++;
69     }
70 
71     pHe->interrupt_times++;
72 */
73     return IRQ_HANDLED;
74 }
75 
eise_hal_init(int32_t dev)76 static int32_t eise_hal_init(int32_t dev)
77 {
78     hal_eise_t* pHe = &sHalEise;
79     pHe->irq_id = EISE_INTERRUPT_ID;
80     pHe->eise_base_addr = EISE_BASE_ADDR;
81     pHe->ccmu_base_addr = CCMU_BASE_ADDR;
82     pHe->pclk = HAL_CLK_PLL_PERI0;
83     pHe->mclk = HAL_CLK_PERIPH_EISE;
84     hal_clk_set_parent(pHe->mclk, pHe->pclk);
85     pHe->hal_sem = hal_sem_create(0);
86     if (pHe->hal_sem == NULL)
87     {
88         eise_err("creating hal semaphore failed\n");
89         return SUNXI_HAL_ERROR;
90     }
91     int ret = request_irq(pHe->irq_id, (irq_handler_t)eise_interrupt, 0, "sunxi_eise", NULL);
92     if (ret < 0) {
93         eise_err("Request EISE Irq error! return %d\n", ret);
94         return SUNXI_HAL_ERROR;
95     } else {
96         //eise_print("Request EISE Irq success! irq_id = %d, return %d\n", pHe->irq_id, ret);
97     }
98     enable_irq(pHe->irq_id);
99     return SUNXI_HAL_OK;
100 }
101 
eise_hal_uninit(int32_t dev)102 static int32_t eise_hal_uninit(int32_t dev)
103 {
104     hal_eise_t* pHe = &sHalEise;
105     hal_clock_disable(pHe->mclk);
106     free_irq(pHe->irq_id, NULL);
107     eise_print("EISE device has been removed!\n");
108     return 0;
109 }
110 
eise_hal_write(int32_t dev,const char * data,uint32_t num)111 static int32_t eise_hal_write(int32_t dev, const char *data, uint32_t num)
112 {
113     return 0;
114 }
115 
eise_hal_read(int32_t dev,int * data,uint32_t size)116 static int32_t eise_hal_read(int32_t dev, int *data, uint32_t size)
117 {
118     return 0;
119 }
120 
eise_hal_ctl(int32_t dev,uint32_t cmd,void * arg)121 static int32_t eise_hal_ctl(int32_t dev, uint32_t cmd, void* arg)
122 {
123     hal_eise_t* pHe = &sHalEise;
124     struct eise_register reg;
125     long  ret = 0;
126     int hal_sem_ret;
127     unsigned int rData = 0x5a5a5a5a;
128     memcpy(&reg, arg, sizeof(struct eise_register));
129     switch (cmd) {
130         case EISE_WRITE_REGISTER:
131             hal_writel(reg.value, pHe->eise_base_addr + reg.addr);
132             return 0;
133         case EISE_READ_REGISTER:
134             rData = hal_readl(pHe->eise_base_addr + reg.addr);
135             return rData;
136         case ENABLE_EISE:
137             if (hal_clock_enable(pHe->mclk))
138                 eise_err("[SYS] enable eise_moduleclk failed!\n");
139             break;
140         case DISABLE_EISE:
141             hal_clock_disable(pHe->mclk);
142             break;
143         case WAIT_EISE_FINISH:
144             hal_sem_ret = hal_sem_timedwait(pHe->hal_sem, reg.value);//1 tick = 10ms
145             if (hal_sem_ret < 0)
146                 eise_print("[SYS] wait_event_timeout!\n");
147             break;
148         case SET_EISE_FREQ:
149         {
150             unsigned int arg_rate = reg.value;
151             if (arg_rate >= EISE_CLK_LOW_WATER &&
152                 arg_rate <= EISE_CLK_HIGH_WATER) {
153                 if (!hal_clk_set_rate(pHe->mclk, arg_rate*1000000)) {
154                     //eise_err("set clock failed!\n");
155                 }
156                 else
157                 {
158                     //eise_print("set clock success!");
159                 }
160             }
161             //ret = hal_clk_get_rate(pHe->mclk);
162             //eise_print("eise real_fre=%ld\n", ret);
163             break;
164         }
165         default:
166         {
167             eise_warn("[SYS] do not supprot this ioctrl now!\n");
168             break;
169         }
170     }
171 
172     return 0;
173 }
174 
175 const sunxi_hal_driver_eise_t sunxi_hal_eise_driver =
176 {
177     .initialize   = eise_hal_init,
178     .uninitialize = eise_hal_uninit,
179     .send         = eise_hal_write,
180     .receive      = eise_hal_read,
181     .control      = eise_hal_ctl,
182 };
183 
eise_driver_init(void)184 int eise_driver_init(void)
185 {
186     __log("eise hal driver init");
187     return 0;
188 }
189 
190 //late_initcall(eise_driver_init);
191