source: azure_iot_hub_riscv/trunk/asp_baseplatform/pdic/k210/device.c@ 453

Last change on this file since 453 was 453, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 33.1 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
7 * Graduate School of Information Science, Nagoya Univ., JAPAN
8 * Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
9 *
10 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
11 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
12 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
13 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15 * スコード中に含まれていること.
16 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
18 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
19 * の無保証規定を掲載すること.
20 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
21 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
22 * と.
23 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
24 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
25 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
26 * 報告すること.
27 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
28 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
29 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
30 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
31 * 免責すること.
32 *
33 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
34 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
35 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
36 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
37 * の責任を負わない.
38 *
39 * @(#) $Id$
40 */
41/*
42 * K210用デバイスドライバ
43 */
44#include "kernel_impl.h"
45#include <t_syslog.h>
46#include <t_stdlib.h>
47#include <sil.h>
48#include <target_syssvc.h>
49#include "kernel_cfg.h"
50#include "device.h"
51
52
53Inline uint64_t
54sil_rel_mem(const uint64_t *mem)
55{
56 uint64_t data;
57
58 data = *((const volatile uint64_t *) mem);
59 return(data);
60}
61
62Inline void
63sil_wrl_mem(uint64_t *mem, uint64_t data)
64{
65 *((volatile uint64_t *) mem) = data;
66}
67
68/*
69 * SIL関数のマクロ定義
70 */
71#define sil_orw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) | (b))
72#define sil_andw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
73#define sil_modw_mem(a, b, c) sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
74#define sil_orl_mem(a, b) sil_wrl_mem((a), sil_rel_mem(a) | (b))
75#define sil_andl_mem(a, b) sil_wrl_mem((a), sil_rel_mem(a) & ~(b))
76#define sil_modl_mem(a, b, c) sil_wrl_mem((a), (sil_rel_mem(a) & (~b)) | (c))
77
78/*
79 * サービスコールのエラーのログ出力
80 */
81Inline void
82svc_perror(const char *file, int_t line, const char *expr, ER ercd)
83{
84 if (ercd < 0) {
85 t_perror(LOG_ERROR, file, line, expr, ercd);
86 }
87}
88
89#define SVC_PERROR(expr) svc_perror(__FILE__, __LINE__, #expr, (expr))
90
91
92/*
93 * GPIOモードの内部定義
94 */
95#define GPIO_MODE 0x00000001
96#define GPIO_MODE_IT 0x00010000
97#define RISING_EDGE 0x00100000
98#define FALLING_EDGE 0x00200000
99#define HIGH_LEVEL 0x00400000
100#define LOW_LEVEL 0x00800000
101#define GPIO_OUTPUT_TYPE 0x00000010
102
103#define GPIO_ID 0
104#define GPIOHS_ID 1
105
106#ifndef NON_INT_GPIOHS_IO
107#define NON_INT_GPIOHS_IO 4
108#endif
109
110typedef struct {
111 uint8_t maxpin;
112 uint8_t funcbase;
113 uint16_t diroff;
114 uint16_t outoff;
115 uint16_t inoff;
116} gpio_pcb_type;
117
118static const gpio_pcb_type pcb_table[2] = {
119 {GPIO_MAX_PINNO, FUNC_GPIO0,
120 TOFF_GPIO_DIRECTION, TOFF_GPIO_DATA_OUTOUT, TOFF_GPIO_DATA_INPUT},
121 {GPIOHS_MAX_PINNO, FUNC_GPIOHS0,
122 TOFF_GPIOHS_OUTPUT_EN, TOFF_GPIOHS_OUTPUT_VAL, TOFF_GPIOHS_INPUT_VAL}
123};
124
125int8_t arduino_gpio_table[ARDUINO_GPIO_PORT];
126
127/*
128 * GPIOの種別IDを取り出す
129 */
130static int gpio_get_no(unsigned long base)
131{
132 if(base == TADR_GPIO_BASE)
133 return 0;
134 else if(base == TADR_GPIOHS_BASE)
135 return 1;
136 else
137 return -1;
138}
139
140/*
141 * GPIOの初期設定関数
142 */
143void
144gpio_setup(unsigned long base, GPIO_Init_t *init, uint32_t pin)
145{
146 const gpio_pcb_type *pt;
147 uint32_t dir, io_number, off;
148 uint8_t ch_sel;
149 int no = gpio_get_no(base);
150
151 if(no < 0 || init == NULL)
152 return;
153
154 pt = &pcb_table[no];
155 if(pin >= pt->maxpin || init->pull >= GPIO_PULLMAX)
156 return;
157 dir = init->mode & GPIO_MODE;
158
159 for(io_number = 0, off = TOFF_FPIOA_IO ; io_number < FPIOA_NUM_IO ; io_number++, off += 4){
160 ch_sel = sil_rew_mem((uint32_t *)(TADR_FPIOA_BASE+off)) & FPIOA_CH_SEL;
161 if(ch_sel == (pt->funcbase + pin))
162 break;
163 }
164 if(io_number >= FPIOA_NUM_IO)
165 return;
166
167 switch(init->pull){
168 case GPIO_NOPULL:
169 sil_andw_mem((uint32_t *)(TADR_FPIOA_BASE+off), (FPIOA_PU | FPIOA_PD));
170 break;
171 case GPIO_PULLDOWN:
172 sil_andw_mem((uint32_t *)(TADR_FPIOA_BASE+off), FPIOA_PU);
173 sil_orw_mem((uint32_t *)(TADR_FPIOA_BASE+off), FPIOA_PD);
174 break;
175 case GPIO_PULLUP:
176 sil_orw_mem((uint32_t *)(TADR_FPIOA_BASE+off), FPIOA_PU);
177 sil_andw_mem((uint32_t *)(TADR_FPIOA_BASE+off), FPIOA_PD);
178 break;
179 default:
180 break;
181 }
182
183 if(no == GPIO_ID){ /* GPIO */
184 sil_modw_mem((uint32_t *)(base+TOFF_GPIO_DIRECTION), (1<<pin), (dir<<pin));
185 }
186 else{ /* GPIOHS */
187 uint32_t off, off_d;
188 off = dir ? TOFF_GPIOHS_OUTPUT_EN : TOFF_GPIOHS_INPUT_EN;
189 off_d = !dir ? TOFF_GPIOHS_OUTPUT_EN : TOFF_GPIOHS_INPUT_EN;
190 sil_andw_mem((uint32_t *)(base+off_d), 1<<pin);
191 sil_orw_mem((uint32_t *)(base+off), 1<<pin);
192
193 sil_andw_mem((uint32_t *)(base+TOFF_GPIOHS_RISE_IE), (1<<pin));
194 sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_RISE_IP), (1<<pin));
195 sil_andw_mem((uint32_t *)(base+TOFF_GPIOHS_FALL_IE), (1<<pin));
196 sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_FALL_IP), (1<<pin));
197 sil_andw_mem((uint32_t *)(base+TOFF_GPIOHS_LOW_IE), (1<<pin));
198 sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_LOW_IP), (1<<pin));
199 sil_andw_mem((uint32_t *)(base+TOFF_GPIOHS_HIGH_IE), (1<<pin));
200 sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_HIGH_IP), (1<<pin));
201 if((init->mode & GPIO_MODE_IT) != 0){
202 if((init->mode & FALLING_EDGE) != 0)
203 sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_FALL_IE), (1<<pin));
204 if((init->mode & RISING_EDGE) != 0)
205 sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_RISE_IE), (1<<pin));
206 if((init->mode & LOW_LEVEL) != 0)
207 sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_LOW_IE), (1<<pin));
208 if((init->mode & HIGH_LEVEL) != 0)
209 sil_orw_mem((uint32_t *)(base+TOFF_GPIOHS_HIGH_IE), (1<<pin));
210 }
211 }
212}
213
214/*
215 * GPIOピン設定
216 */
217void
218gpio_set_pin(unsigned long base, uint8_t pin, uint8_t value)
219{
220 const gpio_pcb_type *pt;
221 int no = gpio_get_no(base);
222 uint32_t dir;
223
224 if(no < 0)
225 return;
226 pt = &pcb_table[no];
227 if(pin >= pt->maxpin)
228 return;
229 dir = (sil_rew_mem((uint32_t *)(base+pt->diroff)) >> pin) & 1;
230 if(dir == 0)
231 return;
232 value &= 1;
233 sil_modw_mem((uint32_t *)(base+pt->outoff), (1<<pin), (value<<pin));
234}
235
236/*
237 * GPIOピンデータ取得
238 */
239uint8_t
240gpio_get_pin(unsigned long base, uint8_t pin)
241{
242 const gpio_pcb_type *pt;
243 int no = gpio_get_no(base);
244 uint32_t dir, off;
245
246 if(no < 0)
247 return 0;
248 pt = &pcb_table[no];
249 if(pin >= pt->maxpin)
250 return 0;
251 dir = (sil_rew_mem((uint32_t *)(base+pt->diroff)) >> pin) & 1;
252 off = dir ? pt->outoff : pt->inoff;
253 return (sil_rew_mem((uint32_t *)(base+off)) >> pin) & 1;
254}
255
256/*
257 * GPIOHSの空きファンクション番号を返す
258 */
259int
260gpio_get_gpiohno(uint8_t fpio_pin, bool_t intreq)
261{
262#if NON_INT_GPIOHS_IO > 0
263 static uint8_t io0 = 0;
264#endif
265 static uint8_t io1 = NON_INT_GPIOHS_IO;
266 int io = -1;
267
268 if(arduino_gpio_table[fpio_pin] >= 0)
269 return (int)arduino_gpio_table[fpio_pin];
270#if NON_INT_GPIOHS_IO > 0
271 else if(intreq && io0 < (NON_INT_GPIOHS_IO-1)){
272 io = (int)io0++;
273 arduino_gpio_table[fpio_pin] = io;
274 }
275#endif
276 else{
277 if(io1 <= (FUNC_GPIOHS31-FUNC_GPIOHS0)){
278 io = (int)io1++;
279 arduino_gpio_table[fpio_pin] = io;
280 }
281 }
282 return io;
283}
284
285
286/*
287 * DMACの設定関数
288 */
289#define DMAC_COM_INTVALUE (DMAC_COM_INTSTATUS_SLVIF_DEC_ERR | DMAC_COM_INTSTATUS_SLVIF_WR2RO_ERR |\
290 DMAC_COM_INTSTATUS_SLVIF_RD2WO_ERR | DMAC_COM_INTSTATUS_SLVIF_WRONHOLD_ERR |\
291 DMAC_COM_INTSTATUS_SLVIF_UNDEFREG_ERR)
292
293#define DMAC_CH_CFG_DEFAULT (DMACCH_CFG_SRC_MULTBLKTYPE | DMACCH_CFG_DST_MULTBLKTYPE |\
294 DMACCH_CFG_TT_FC | DMACCH_CFG_HS_SEL_SRC | DMACCH_CFG_HS_SEL_DST |\
295 DMACCH_CFG_SRC_PER | DMACCH_CFG_DST_PER)
296
297#define DMAC_CH_CTL_SRC (DMACCH_CTL_SMS | DMACCH_CTL_SINC | DMACCH_CTL_SRC_TR_WIDTH | DMACCH_CTL_SRC_MSIZE)
298#define DMAC_CH_CTL_DST (DMACCH_CTL_DMS | DMACCH_CTL_DINC | DMACCH_CTL_DST_TR_WIDTH | DMACCH_CTL_DST_MSIZE)
299#define DMAC_CH_CTL_DEFAULT (DMAC_CH_CTL_SRC | DMAC_CH_CTL_DST)
300
301#define DMAC_CH_INT_ERROR (DMACCH_ENABLE_SRC_DEC_ERR_INSTAT | DMACCH_ENABLE_DST_DEC_ERR_INSTAT |\
302 DMACCH_ENABLE_SRC_SLV_ERR_INSTAT | DMACCH_ENABLE_DST_SLV_ERR_INSTAT)
303#define DMAC_CH_INT_DEFAULT (DMACCH_ENABLE_DMA_TFR_DONE_INTSTAT | DMACCH_ENABLE_SRC_TRANSCOMP_INTSTAT |\
304 DMACCH_ENABLE_DST_TRANSCOMP_INSTAT | DMAC_CH_INT_ERROR)
305
306#define DMAC_CHANNEL_ENABLE (DMAC_CHEN_CH1_EN | DMAC_CHEN_CH2_EN | DMAC_CHEN_CH3_EN |\
307 DMAC_CHEN_CH4_EN | DMAC_CHEN_CH5_EN | DMAC_CHEN_CH6_EN)
308
309static DMA_Handle_t *pDmaHandler[NUM_DMA_CHANNEL];
310
311/*
312 * DMACの初期化
313 */
314static void
315dmac_init(void)
316{
317 uint64_t tmp;
318
319 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), SYSCTL_CLK_EN_PERI_DMA_CLK_EN);
320
321 /*
322 * DMACリセット
323 */
324 sil_orl_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_RESET), DMAC_RESET_RST);
325 while((sil_rel_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_RESET)) & DMAC_RESET_RST) != 0);
326
327 /*
328 * COMMON割込みクリア
329 */
330 sil_wrl_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_COM_INTCLEAR), DMAC_COM_INTVALUE);
331
332 /*
333 * DMAC無効化
334 */
335 sil_wrl_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_CFG), 0);
336 while(sil_rel_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_CFG)) != 0);
337
338 /*
339 * チャネル無効化
340 */
341 tmp = sil_rel_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_CHEN));
342 tmp &= ~DMAC_CHANNEL_ENABLE;
343 sil_wrl_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_CHEN), tmp);
344
345 /*
346 * DMAC有効化
347 */
348 sil_wrl_mem((uint64_t *)(TADR_DMAC_BASE+TOFF_DMAC_CFG), (DMAC_CFG_DMAC_EN | DMAC_CFG_INT_EN));
349}
350
351/*
352 * チャンネルCFG/CTLレジスタ設定
353 */
354static void
355dma_config(DMA_Handle_t *hdma)
356{
357 uint64_t cfg, ctl;
358
359 /* DMA-CFGレジスタ設定 */
360 cfg = sil_rel_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_CFG));
361 cfg &= ~(DMAC_CH_CFG_DEFAULT | DMACCH_CFG_SRC_HWHS_POL | DMACCH_CFG_DST_HWHS_POL | DMACCH_CFG_CH_PRIOR);
362 cfg |= (hdma->Init.SrcMultBlock << 0) | (hdma->Init.DrcMultBlock << 2);
363 cfg |= (uint64_t)hdma->Init.Direction << 32;
364 cfg |= ((uint64_t)hdma->Init.SrcHandShake << 35) | ((uint64_t)hdma->Init.DrcHandShake << 36);
365 cfg |= ((uint64_t)hdma->Init.SrcHwhsPol << 37) | ((uint64_t)hdma->Init.DrcHwhsPol << 38);
366 cfg |= ((uint64_t)hdma->chnum << 39) | ((uint64_t)hdma->chnum << 44);
367 cfg |= (uint64_t)hdma->Init.Priority << 49;
368 sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_CFG), cfg);
369
370 /* DMA-CTLレジスタ設定 */
371 ctl = sil_rel_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_CTL));
372 ctl &= ~(DMAC_CH_CTL_DEFAULT | DMACCH_CTL_IOC_BLKTFR);
373 ctl |= (hdma->Init.SrcMaster << 0) | (hdma->Init.DstMaster << 2);
374 ctl |= (hdma->Init.SrcInc << 4) | (hdma->Init.DstInc << 6);
375 ctl |= (hdma->Init.SrcTransWidth << 8) | (hdma->Init.DstTransWidth << 11);
376 ctl |= (hdma->Init.SrcBurstSize << 14) | (hdma->Init.DstBurstSize << 18);
377 ctl |= (uint64_t)hdma->Init.IocBlkTrans << 58;
378 sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_CTL), ctl);
379}
380
381/*
382 * CHANNEL DMA初期化関数
383 * parameter1 hdma: DMAハンドラへのポインタ
384 * return ER値
385 */
386ER
387dma_init(DMA_Handle_t *hdma)
388{
389 /* パラメータチェック */
390 if(hdma == NULL || hdma->chnum >= NUM_DMA_CHANNEL)
391 return E_PAR;
392 if(pDmaHandler[hdma->chnum] != NULL)
393 return E_OBJ;
394
395 hdma->base = TADR_DMAC_BASE;
396 hdma->cbase = hdma->base + TOFF_DMAC_CHANNEL + hdma->chnum * DMAC_CHANNEL_WINDOW_SIZE;
397 select_dma_channel(hdma->chnum, hdma->Init.Request);
398 pDmaHandler[hdma->chnum] = hdma;
399
400 /* DMA-CFG/CTLレジスタ設定 */
401 dma_config(hdma);
402
403 /* エラー状態をクリア */
404 hdma->status = DMA_STATUS_READY;
405 hdma->ErrorCode = DMA_ERROR_NONE;
406 return E_OK;
407}
408
409/*
410 * チャネルDMA終了関数
411 * parameter1 hdma: DMAハンドラへのポインタ
412 * return ER値
413 */
414ER
415dma_deinit(DMA_Handle_t *hdma)
416{
417 /* パラメータチェック */
418 if(hdma == NULL || hdma->chnum >= NUM_DMA_CHANNEL)
419 return E_PAR;
420
421 /*
422 * チャンネルの無効化
423 */
424 dma_end(hdma);
425 pDmaHandler[hdma->chnum] = NULL;
426
427 /* エラー状態をクリア */
428 hdma->ErrorCode = DMA_ERROR_NONE;
429 return E_OK;
430}
431
432/*
433 * CHANNEL DMAリセット関数
434 * parameter1 hdma: DMAハンドラへのポインタ
435 * return ER値
436 */
437ER
438dma_reset(DMA_Handle_t *hdma)
439{
440 uint32_t tick = 0;
441
442 /* パラメータチェック */
443 if(hdma == NULL || hdma->chnum >= NUM_DMA_CHANNEL)
444 return E_PAR;
445
446 while((sil_rel_mem((uint64_t *)(hdma->base+TOFF_DMAC_CHEN)) & (1 << hdma->chnum)) != 0){
447 dly_tsk(1);
448 if(tick++ >= DMA_TRS_TIMEOUT)
449 return E_TMOUT;
450 }
451
452 /* DMA-CFGレジスタ設定 */
453 dma_config(hdma);
454 return E_OK;
455}
456
457/*
458 * チャネルDMA開始関数
459 * parameter1 hdma: DMAハンドラへのポインタ
460 * parameter2 SrcAddress: ソースアドレス
461 * parameter3 DstAddress: デスティネーションアドレス
462 * parameter4 DataLength: 転送長
463 * return ER値
464 */
465ER
466dma_start(DMA_Handle_t *hdma, uintptr_t SrcAddress, uintptr_t DstAddress, uint32_t DataLength)
467{
468 uint64_t tmp;
469
470 /* パラメータチェック */
471 if(hdma == NULL || hdma->chnum >= NUM_DMA_CHANNEL)
472 return E_PAR;
473
474 hdma->status = DMA_STATUS_BUSY;
475 hdma->ErrorCode = DMA_ERROR_NONE;
476
477 /*
478 * 割込み要因クリア
479 */
480 sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_INTCLEAR), 0xFFFFFFFF);
481
482 /*
483 * 転送設定
484 */
485 sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_SAR), (uint64_t)SrcAddress);
486 sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_DAR), (uint64_t)DstAddress);
487 sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_BLOCK_TS), DataLength - 1);
488
489 /*
490 * DMAC有効化
491 */
492 sil_wrl_mem((uint64_t *)(hdma->base+TOFF_DMAC_CFG), (DMAC_CFG_DMAC_EN | DMAC_CFG_INT_EN));
493 sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_INTSTATUS_EN), DMAC_CH_INT_DEFAULT);
494
495 /* DMA開始 */
496 tmp = sil_rel_mem((uint64_t *)(hdma->base+TOFF_DMAC_CHEN));
497 tmp |= (DMAC_CHEN_CH1_EN | DMAC_CHEN_CH1_EN_WE) << hdma->chnum;
498 sil_wrl_mem((uint64_t *)(hdma->base+TOFF_DMAC_CHEN), tmp);
499 return E_OK;
500}
501
502/*
503 * チャネルDMA停止関数
504 * parameter1 hdma : DMAハンドラへのポインタ
505 * return ER値
506 */
507ER
508dma_end(DMA_Handle_t *hdma)
509{
510 uint64_t tmp;
511
512 if(hdma == NULL || hdma->chnum >= NUM_DMA_CHANNEL)
513 return E_PAR;
514
515 /* DMA停止 */
516 tmp = sil_rel_mem((uint64_t *)(hdma->base+TOFF_DMAC_CHEN));
517 tmp &= ~DMAC_CHEN_CH1_EN << hdma->chnum;
518 tmp |= DMAC_CHEN_CH1_EN_WE << hdma->chnum;
519 sil_wrl_mem((uint64_t *)(hdma->base+TOFF_DMAC_CHEN), tmp);
520
521 hdma->status = DMA_STATUS_READY;
522 return E_OK;
523}
524
525/*
526 * チャネルDMA割込み処理関数
527 * parameter1 hdma: DMAハンドラへのポインタ
528 */
529void
530dma_inthandler(DMA_Handle_t *hdma)
531{
532 uint64_t intstatus, intstatus_en;
533
534 intstatus = sil_rel_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_INTSTATUS));
535 intstatus_en = sil_rel_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_INTSTATUS_EN));
536 syslog_2(LOG_DEBUG, "dma_inthandler instatus[%08x][%08x]", (int)intstatus, (int)intstatus_en);
537 if((intstatus & intstatus_en & DMACCH_ENABLE_DMA_TFR_DONE_INTSTAT) != 0){
538 hdma->status = DMA_STATUS_READY_TRN1;
539 if(hdma->xfercallback != NULL)
540 hdma->xfercallback(hdma);
541 }
542 else if((intstatus & intstatus_en & DMACCH_ENABLE_SRC_TRANSCOMP_INTSTAT) != 0){
543 hdma->status = DMA_STATUS_READY_TRN2;
544 if(hdma->xfercallback != NULL)
545 hdma->xfercallback(hdma);
546 }
547 else if((intstatus & intstatus_en & DMACCH_ENABLE_DST_TRANSCOMP_INSTAT) != 0){
548 hdma->status = DMA_STATUS_READY_TRN3;
549 if(hdma->xfercallback != NULL)
550 hdma->xfercallback(hdma);
551 }
552 if((intstatus & intstatus_en & DMAC_CH_INT_ERROR) != 0){
553 hdma->ErrorCode |= intstatus & intstatus_en & DMAC_CH_INT_ERROR;
554 if(hdma->errorcallback != NULL)
555 hdma->errorcallback(hdma);
556 }
557 sil_wrl_mem((uint64_t *)(hdma->cbase+TOFF_DMAC_CH_INTCLEAR), intstatus);
558}
559
560/*
561 * チャネルDMA 割込みサービスルーチン
562 */
563void
564channel_dmac_isr(intptr_t exinf)
565{
566 dma_inthandler(pDmaHandler[(uint32_t)exinf]);
567}
568
569ER
570select_dma_channel(uint8_t channel, uint8_t select)
571{
572 uint32_t dma_sel;
573
574 if(select >= NUM_DMA_SELECT)
575 return E_PAR;
576 if(channel < DMA_CHANNEL5){
577 dma_sel = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_DMA_SEL0));
578 dma_sel &= ~(0x3F << (channel * 6));
579 dma_sel |= select << (channel * 6);
580 sil_wrw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_DMA_SEL0), dma_sel);
581 return E_OK;
582 }
583 else if(channel == DMA_CHANNEL5){
584 dma_sel = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_DMA_SEL1));
585 dma_sel &= ~0x3F;
586 dma_sel |= select;
587 sil_wrw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_DMA_SEL1), dma_sel);
588 return E_OK;
589 }
590 else
591 return E_PAR;
592}
593
594
595/*
596 * WDOGドライバ
597 */
598/*
599 * SPIOポートIDから管理ブロックを取り出すためのマクロ
600 */
601#define INDEX_WDOG(wdogid) ((uint_t)((wdogid) - 1))
602
603typedef struct {
604 unsigned long base;
605 uint32_t reset;
606 uint32_t threshold;
607 uint32_t thshift;
608 uint32_t bus_en;
609 uint32_t peri_en;
610} WDT_PortControlBlock;
611
612static const WDT_PortControlBlock wdt_table[2] = {
613 {TADR_WDT0_BASE, SYSCTL_PERI_RESET_WDT0_RESET, SYSCTL_CLK_TH6_WD0_CLK_THHD,
614 0, SYSCTL_CLK_EN_CENT_APB1_CLK_EN, SYSCTL_CLK_EN_PERI_WDT0_CLK_EN},
615 {TADR_WDT1_BASE, SYSCTL_PERI_RESET_WDT1_RESET, SYSCTL_CLK_TH6_WD1_CLK_THHD,
616 8, SYSCTL_CLK_EN_CENT_APB1_CLK_EN, SYSCTL_CLK_EN_PERI_WDT1_CLK_EN}
617};
618
619static WDT_Handle_t WdtHandle[NUM_WDOGPORT];
620
621
622/*
623 * WDT無効化
624 */
625static void
626wdt_disable(WDT_Handle_t *hwdt)
627{
628 sil_wrw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CRR), WDT_CRR_MASK);
629 sil_andw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CR), WDT_CR_ENABLE);
630}
631
632/*
633 * WINDOW WATCH-DOG初期化
634 * parameter1 port: WDOGポート番号
635 * return WDTハンドラへのポインタ
636 */
637WDT_Handle_t *
638wdt_init(ID port)
639{
640 const WDT_PortControlBlock *pcb;
641 WDT_Handle_t *hwdt;
642 uint8_t no;
643 uint32_t source = SYSCTRL_CLOCK_FREQ_IN0;
644 uint32_t threshold;
645
646 if(port < WDOG1_PORTID || port >= NUM_WDOGPORT)
647 return NULL;
648
649 no = INDEX_WDOG(port);
650 pcb = &wdt_table[no];
651 hwdt = &WdtHandle[no];
652
653 hwdt->base = pcb->base;
654 hwdt->wdtno = no;
655 hwdt->callback = NULL;
656
657 /*
658 * WDTリセット
659 */
660 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PERI_RESET), pcb->reset);
661 sil_dly_nse(10*1000);
662 sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PERI_RESET), pcb->reset);
663
664 /*
665 * WDT初期化
666 */
667 sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH6), pcb->threshold);
668 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), pcb->bus_en);
669 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), pcb->peri_en);
670
671 sil_modw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CR), WDT_CR_RMOD_MASK, WDT_CR_RMOD_INTERRUPT);
672
673 threshold = sil_rew_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_TH6)) & pcb->threshold;
674 threshold >>= pcb->thshift;
675
676 hwdt->pclk = source / ((threshold + 1) * 2);
677
678 wdt_disable(hwdt);
679 return hwdt;
680}
681
682/*
683 * WINDOW WATCH-DOG終了設定
684 * parameter1 hwdt: WDOGハンドラ
685 * return ERコード
686 */
687ER
688wdt_deinit(WDT_Handle_t *hwdt)
689{
690 const WDT_PortControlBlock *pcb;
691
692 if(hwdt == NULL)
693 return E_PAR;
694 pcb = &wdt_table[hwdt->wdtno];
695 wdt_disable(hwdt);
696 sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), pcb->peri_en);
697 hwdt->base = 0;
698 return E_OK;
699}
700
701/*
702 * WDOGタイマー開始
703 * parameter1 hwdt: WDOGハンドラ
704 * parameter2 mode: タイムアウトモード
705 * parameter3 tmout: タイムアウト時間(ms)
706 * return ERコード
707 */
708ER_UINT
709wdt_start(WDT_Handle_t *hwdt, uint32_t mode, uint32_t timeout_ms)
710{
711 uint8_t m_top;
712 uint64_t clk;
713 uint32_t torr;
714
715 if(hwdt == NULL)
716 return E_PAR;
717 clk = ((uint64_t)timeout_ms * hwdt->pclk / 1000) >> 16;
718 for(m_top = 0, clk >>=1 ; m_top < 16 && clk > 0 ; m_top++){
719 clk >>= 1;
720 }
721 if(m_top > 0xf)
722 m_top = 0xf;
723
724 sil_modw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CR), WDT_CR_RMOD_MASK, mode);
725
726 /*
727 * WDTタイムアウト設定
728 */
729 torr = (m_top << 4) | m_top;
730 sil_wrw_mem((uint32_t *)(hwdt->base+TOFF_WDT_TORR), torr);
731
732 /*
733 * WDT有効化
734 */
735 sil_wrw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CRR), WDT_CRR_MASK);
736 sil_orw_mem((uint32_t *)(hwdt->base+TOFF_WDT_CR), WDT_CR_ENABLE);
737 return (1UL << (m_top + 16 + 1)) * 1000UL / hwdt->pclk;
738}
739
740/*
741 * WDOGタイマー停止
742 * parameter1 hwdt: WDOGハンドラ
743 * return ERコード
744 */
745ER
746wdt_stop(WDT_Handle_t *hwdt)
747{
748 if(hwdt == NULL)
749 return E_PAR;
750 wdt_disable(hwdt);
751 return E_OK;
752}
753
754/*
755 * WDOG割込サービスコール
756 */
757void
758wdog_isr(intptr_t exinf)
759{
760 WDT_Handle_t *hwdt = &WdtHandle[INDEX_WDOG(exinf)];
761 uint32_t eoi;
762
763 eoi = sil_rew_mem((uint32_t *)(hwdt->base+TOFF_WDT_EOI));
764 sil_wrw_mem((uint32_t *)(hwdt->base+TOFF_WDT_EOI), eoi);
765 if(hwdt->callback != NULL)
766 hwdt->callback(hwdt);
767}
768
769
770/*
771 * RTCデバイス
772 */
773
774#define RTC_MASK_VALUE (RTC_RCTL_TIMER_MASK | RTC_RCTL_ALARAM_MASK |\
775 RTC_RCTL_INT_CNT_MASK | RTC_RCTL_INT_REG_MASK)
776
777static const int days[2][13] = {
778 {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
779 {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}};
780
781
782uint8_t rtc_timer_mode;
783static void (*tick_func)(int);
784static void (*alarm_func)(int);
785
786Inline bool_t
787rtc_in_range(int value, int min, int max)
788{
789 return ((value >= min) && (value <= max));
790}
791
792static int
793rtc_get_wday(int year, int month, int day)
794{
795 /* Magic method to get weekday */
796 int weekday = (day += month < 3 ? year-- : year - 2, 23 * month / 9 + day + 4 + year / 4 - year / 100 + year / 400) % 7;
797 return weekday;
798}
799
800static int
801rtc_year_is_leap(int year)
802{
803 return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
804}
805
806static int
807rtc_get_yday(int year, int month, int day)
808{
809 int leap = rtc_year_is_leap(year);
810
811 return days[leap][month] + day;
812}
813
814/*
815 * RTCプロテクション設定
816 */
817static void
818rtc_protect_set(int enable)
819{
820 if(enable){
821 sil_andw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_REGISTER_CTRL), RTC_MASK_VALUE);
822 }
823 else{
824 sil_orw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_REGISTER_CTRL), RTC_MASK_VALUE);
825 }
826}
827
828ER
829rtc_timer_set_mode(uint8_t timer_mode)
830{
831 uint32_t regctl = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_REGISTER_CTRL));
832 unsigned long freq = (unsigned long)SYS_CLOCK / 26000000;
833 unsigned long start_cycle;
834
835 switch(timer_mode){
836 case RTC_TIMER_RUNNING:
837 regctl |= RTC_RCTL_READ_ENABLE;
838 regctl &= ~RTC_RCTL_WRITE_ENABLE;
839 break;
840 case RTC_TIMER_SETTING:
841 regctl &= ~RTC_RCTL_READ_ENABLE;
842 regctl |= RTC_RCTL_WRITE_ENABLE;
843 break;
844 case RTC_TIMER_PAUSE:
845 default:
846 regctl &= ~(RTC_RCTL_READ_ENABLE | RTC_RCTL_WRITE_ENABLE);
847 break;
848 }
849
850 /* Wait for 1/26000000 s to sync data */
851 start_cycle = read_csr(mcycle);
852 while((read_csr(mcycle) - start_cycle) < freq){
853 continue;
854 }
855
856 sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_REGISTER_CTRL), regctl);
857 rtc_timer_mode = timer_mode;
858 return E_OK;
859}
860
861/*
862 * RTC初期化関数
863 */
864void rtc_init(intptr_t exinf)
865{
866 /* Reset RTC */
867 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PERI_RESET), SYSCTL_PERI_RESET_RTC_RESET);
868 sil_dly_nse(10*1000);
869 sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_PERI_RESET), SYSCTL_PERI_RESET_RTC_RESET);
870
871 /* Enable RTC */
872 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB1_CLK_EN);
873 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_CLK_EN_PERI), SYSCTL_CLK_EN_PERI_RTC_CLK_EN);
874
875 /* Unprotect RTC */
876 rtc_protect_set(0);
877 rtc_timer_set_mode(RTC_TIMER_SETTING);
878 /* Set RTC clock frequency */
879 sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INITIAL_COUNT), SYSCTRL_CLOCK_FREQ_IN0);
880
881 sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_COURRNT_COUNT), 1);
882 /* Set RTC mode to timer running mode */
883 rtc_timer_set_mode(RTC_TIMER_RUNNING);
884
885 tick_func = NULL;
886 alarm_func = NULL;
887}
888
889/*
890 * RTCの時刻設定関数
891 *
892 * 時刻の設定はPONIXのtm構造体を使用する
893 * PONIXのインクルードがない場合を考慮し、同一項目のtm2をドライバとして定義する。
894 */
895ER
896rtc_set_time(struct tm2 *pt)
897{
898 uint32_t tm_wday = rtc_get_wday(pt->tm_year + 1900, pt->tm_mon, pt->tm_mday);
899 uint32_t extend = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_EXTENDED));
900 int human_year = pt->tm_year + 1900;
901 int rtc_year = human_year % 100;
902 int rtc_century = human_year / 100;
903
904 if(!rtc_in_range(pt->tm_sec, 0, 59))
905 return E_PAR;
906 if(!rtc_in_range(pt->tm_min, 0, 59))
907 return E_PAR;
908 if(!rtc_in_range(pt->tm_hour, 0, 23))
909 return E_PAR;
910 if(!rtc_in_range(pt->tm_mday, 1, 31))
911 return E_PAR;
912 if(!rtc_in_range(pt->tm_mon, 1, 12))
913 return E_PAR;
914 if(!rtc_in_range(rtc_year, 0, 99) || !rtc_in_range(rtc_century, 0, 31))
915 return E_PAR;
916
917 /*
918 * RTC日時をセットアップ
919 */
920 rtc_timer_set_mode(RTC_TIMER_SETTING);
921 sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_DATE),
922 tm_wday | (pt->tm_mday << 8) | (pt->tm_mon << 16) | (rtc_year << 20));
923 sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_TIME),
924 (pt->tm_sec << 10) | (pt->tm_min << 16) | (pt->tm_hour << 24));
925 extend &= ~RTC_EXTENDED_CENTURY;
926 extend |= rtc_century;
927 sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_EXTENDED), extend);
928 rtc_timer_set_mode(RTC_TIMER_RUNNING);
929 return E_OK;
930}
931
932/*
933 * RTCの時刻取り出し関数
934 *
935 * 時刻の設定はPONIXのtm構造体を使用する
936 * PONIXのインクルードがない場合を考慮し、同一項目のtm2をドライバとして定義する。
937 */
938ER rtc_get_time(struct tm2 *pt)
939{
940 uint32_t date = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_DATE));
941 uint32_t time = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_TIME));
942 uint32_t century = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_EXTENDED)) & RTC_EXTENDED_CENTURY;
943
944 if(rtc_timer_mode != RTC_TIMER_RUNNING)
945 return E_OBJ;
946
947 pt->tm_sec = (time & RTC_TIME_SECOND) >> 10; /* 0-60, follow C99 */
948 pt->tm_min = (time & RTC_TIME_MINUTE) >> 16; /* 0-59 */
949 pt->tm_hour = (time & RTC_TIME_HOUR) >> 24; /* 0-23 */
950 pt->tm_mday = (date & RTC_DATE_DAY) >> 8; /* 1-31 */
951 pt->tm_mon = (date & RTC_DATE_MONTH) >> 16; /* 1-12 */
952 pt->tm_year = (((date & RTC_DATE_YEAR) >> 20) % 100) + (century * 100) - 1900;
953 pt->tm_wday = date & RTC_DATE_WEEK; /* 0-6 */
954 pt->tm_yday = rtc_get_yday(pt->tm_year + 1900, pt->tm_mon + 1, pt->tm_mday) % 366; /* 0-365 */
955 pt->tm_isdst = 0;
956 return E_OK;
957}
958
959/*
960 * RTC TICK割込み設定
961 */
962ER_UINT
963rtc_intmode(int8_t mode, void *func)
964{
965 uint32_t intctl = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INTERRUPT_CTRL));
966 uint_t cmode;
967 if(mode >= 0){
968 rtc_timer_set_mode(RTC_TIMER_SETTING);
969 if(func == NULL){
970 if(alarm_func == NULL)
971 intctl &= ~RTC_INT_TICK_ENABLE;
972 tick_func = NULL;
973 }
974 else{
975 intctl &= ~RTC_INT_TICK_INT_MODE;
976 intctl |= ((mode & 3) << 2) | RTC_INT_TICK_ENABLE;
977 tick_func = (void (*)(int))func;
978 }
979 sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INTERRUPT_CTRL), intctl);
980 rtc_timer_set_mode(RTC_TIMER_RUNNING);
981 }
982 cmode = ((intctl & RTC_INT_TICK_ENABLE) ^ 1) << 2;
983 cmode |= (intctl & RTC_INT_TICK_INT_MODE) >> 2;
984 return cmode;
985}
986
987/*
988 * RTCアラーム設定
989 * parameter1 : parm: Pointer to Alarm structure
990 * parameter2 : ptm: Pointer to struct tm2
991 * return ERコード
992 */
993ER
994rtc_setalarm(RTC_Alarm_t *parm, struct tm2 *ptm)
995{
996 uint32_t intctl = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INTERRUPT_CTRL));
997 int human_year = ptm->tm_year + 1900;
998 int rtc_year = human_year % 100;
999 int rtc_century = human_year / 100;
1000 uint32_t alarmmask;
1001
1002 if(parm == NULL || ptm == NULL)
1003 return E_PAR;
1004 alarmmask = parm->alarmmask & RTC_INT_ARARM_C_MASK;
1005 if(alarmmask != 0 && parm->callback == NULL)
1006 return E_PAR;
1007
1008 if(!rtc_in_range(ptm->tm_sec, 0, 59)){
1009 if((alarmmask & RTC_ALARM_SECOND) != 0)
1010 return E_PAR;
1011 ptm->tm_sec = 0;
1012 }
1013 if(!rtc_in_range(ptm->tm_min, 0, 59)){
1014 if((alarmmask & RTC_ALARM_MINUTE) != 0)
1015 return E_PAR;
1016 ptm->tm_min = 0;
1017 }
1018 if(!rtc_in_range(ptm->tm_hour, 0, 23)){
1019 if((alarmmask & RTC_ALARM_HOUR) != 0)
1020 return E_PAR;
1021 ptm->tm_hour = 0;
1022 }
1023 if(!rtc_in_range(ptm->tm_mday, 1, 31)){
1024 if((alarmmask & RTC_ALARM_DAY) != 0)
1025 return E_PAR;
1026 ptm->tm_mday = 1;
1027 }
1028 if(rtc_in_range(ptm->tm_wday, 0, 6)){
1029 if((alarmmask & RTC_ALARM_WEEK) != 0)
1030 return E_PAR;
1031 ptm->tm_wday = 0;
1032 }
1033 if(!rtc_in_range(ptm->tm_mon, 1, 12)){
1034 if((alarmmask & RTC_ALARM_MONTH) != 0)
1035 return E_PAR;
1036 ptm->tm_mon = 1;
1037 }
1038 if(!rtc_in_range(rtc_year, 0, 99) || !rtc_in_range(rtc_century, 0, 31)){
1039 if((alarmmask & RTC_ALARM_YEAR) != 0)
1040 return E_PAR;
1041 ptm->tm_year = 0;
1042 }
1043
1044 /*
1045 * RTC日時、割込みをセットアップ
1046 */
1047 rtc_timer_set_mode(RTC_TIMER_SETTING);
1048 sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_ALARM_DATE),
1049 ptm->tm_wday | (ptm->tm_mday << 8) | (ptm->tm_mon << 16) | (rtc_year << 20));
1050 sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_ALARM_TIME),
1051 (ptm->tm_sec << 10) | (ptm->tm_min << 16) | (ptm->tm_hour << 24));
1052
1053 if(tick_func == NULL)
1054 intctl &= ~RTC_INT_TICK_ENABLE;
1055 intctl &= ~(RTC_INT_ALARM_ENABLE | RTC_INT_ARARM_C_MASK);
1056 alarm_func = NULL;
1057 if(alarmmask != 0){
1058 intctl |= alarmmask | RTC_INT_TICK_ENABLE | RTC_INT_ALARM_ENABLE;
1059 alarm_func = (void (*)(int))parm->callback;
1060 }
1061 sil_wrw_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INTERRUPT_CTRL), intctl);
1062 rtc_timer_set_mode(RTC_TIMER_RUNNING);
1063 return E_OK;
1064}
1065
1066/*
1067 * RTC割込みハンドラ
1068 */
1069void
1070rtc_int_handler(void)
1071{
1072 uint32_t intctl = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_INTERRUPT_CTRL));
1073 uint32_t cdate = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_DATE));
1074 uint32_t ctime = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_RTC_TIME));
1075
1076 if((intctl & RTC_INT_TICK_ENABLE) != 0 && tick_func != NULL){
1077 int mode = (intctl & RTC_INT_TICK_INT_MODE) >> 2;
1078 bool_t tickact = true;
1079 switch(mode){
1080 case RTC_INT_MINUTE:
1081 if((ctime & RTC_TIME_SECOND) != 0)
1082 tickact = false;
1083 break;
1084 case RTC_INT_HOUR:
1085 if((ctime & (RTC_TIME_SECOND | RTC_TIME_MINUTE)) != 0)
1086 tickact = false;
1087 break;
1088 default:
1089 break;
1090 }
1091 if(tickact)
1092 tick_func(mode);
1093 }
1094
1095 if((intctl & RTC_INT_ALARM_ENABLE) != 0 && alarm_func != NULL){
1096 uint32_t adate = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_ALARM_DATE));
1097 uint32_t atime = sil_rew_mem((uint32_t *)(TADR_RTC_BASE+TOFF_ALARM_TIME));
1098 uint32_t tdate = cdate;
1099 uint32_t ttime = ctime;
1100
1101 if((intctl & RTC_ALARM_YEAR) == 0){
1102 tdate &= ~RTC_DATE_YEAR;
1103 adate &= ~RTC_ALARM_DATE_YEAR;
1104 }
1105 if((intctl & RTC_ALARM_MONTH) == 0){
1106 tdate &= ~RTC_DATE_MONTH;
1107 adate &= ~RTC_ALARM_DATE_MONTH;
1108 }
1109 if((intctl & RTC_ALARM_DAY) == 0){
1110 tdate &= ~RTC_DATE_DAY;
1111 adate &= ~RTC_ALARM_DATE_DAY;
1112 }
1113 if((intctl & RTC_ALARM_WEEK) == 0){
1114 tdate &= ~RTC_DATE_WEEK;
1115 adate &= ~RTC_ALARM_DATE_WEEK;
1116 }
1117 if((intctl & RTC_ALARM_HOUR) == 0){
1118 ttime &= ~RTC_TIME_HOUR;
1119 atime &= ~RTC_ALARM_TIME_HOUR;
1120 }
1121 if((intctl & RTC_ALARM_MINUTE) == 0){
1122 ttime &= ~RTC_TIME_MINUTE;
1123 atime &= ~RTC_ALARM_TIME_MINUTE;
1124 }
1125 if((intctl & RTC_ALARM_SECOND) == 0){
1126 ttime &= ~RTC_TIME_SECOND;
1127 atime &= ~RTC_ALARM_TIME_SECOND;
1128 }
1129 if(tdate == adate && ttime == atime)
1130 alarm_func(intctl);
1131 }
1132}
1133
1134
1135/*
1136 * デバイス初期化
1137 */
1138void
1139device_init(intptr_t exinf)
1140{
1141 unsigned long sbase = TADR_SYSCTL_BASE;
1142 uint32_t i;
1143
1144 /*
1145 * GPIOクロック設定
1146 */
1147 sil_orw_mem((uint32_t *)(sbase+TOFF_SYSCTL_CLK_EN_CENT), SYSCTL_CLK_EN_CENT_APB0_CLK_EN);
1148 sil_orw_mem((uint32_t *)(sbase+TOFF_SYSCTL_CLK_EN_PERI), SYSCTL_CLK_EN_PERI_GPIO_CLK_EN);
1149
1150 /*
1151 * Arduino用GPIOテーブル初期化
1152 */
1153 for(i = 0 ; i < ARDUINO_GPIO_PORT ; i++){
1154 arduino_gpio_table[i] = -1;
1155 }
1156
1157 /*
1158 * DMAC初期化
1159 */
1160 dmac_init();
1161}
1162
1163/*
1164 * SPI0-DVPモード設定
1165 * parameter1 en: 有効(1)、無効(0)
1166 * return ERコード
1167 */
1168ER
1169select_spi0_dvp_mode(uint8_t en)
1170{
1171 if(en == 0){
1172 sil_andw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_MISC), SYSCTL_MISC_SPI_DVP_DATA_ENABLE);
1173 return E_OK;
1174 }
1175 else if(en == 1){
1176 sil_orw_mem((uint32_t *)(TADR_SYSCTL_BASE+TOFF_SYSCTL_MISC), SYSCTL_MISC_SPI_DVP_DATA_ENABLE);
1177 return E_OK;
1178 }
1179 else
1180 return E_PAR;
1181}
1182
Note: See TracBrowser for help on using the repository browser.