| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858 |
- /* Copyright 2018 Canaan Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <math.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include "bsp.h"
- #include "encoding.h"
- #include "string.h"
- #include "sysctl.h"
- #include "uart.h"
- #define SYSCTRL_CLOCK_FREQ_IN0 (26000000UL)
- const uint8_t get_select_pll2[] =
- {
- [SYSCTL_SOURCE_IN0] = 0,
- [SYSCTL_SOURCE_PLL0] = 1,
- [SYSCTL_SOURCE_PLL1] = 2,
- };
- const uint8_t get_source_pll2[] =
- {
- [0] = SYSCTL_SOURCE_IN0,
- [1] = SYSCTL_SOURCE_PLL0,
- [2] = SYSCTL_SOURCE_PLL1,
- };
- const uint8_t get_select_aclk[] =
- {
- [SYSCTL_SOURCE_IN0] = 0,
- [SYSCTL_SOURCE_PLL0] = 1,
- };
- const uint8_t get_source_aclk[] =
- {
- [0] = SYSCTL_SOURCE_IN0,
- [1] = SYSCTL_SOURCE_PLL0,
- };
- volatile sysctl_t *const sysctl = (volatile sysctl_t *)SYSCTL_BASE_ADDR;
- uint32_t sysctl_get_git_id(void)
- {
- return sysctl->git_id.git_id;
- }
- uint32_t sysctl_get_freq(void)
- {
- return sysctl->clk_freq.clk_freq;
- }
- static void sysctl_reset_ctl(sysctl_reset_t reset, uint8_t rst_value)
- {
- switch(reset)
- {
- case SYSCTL_RESET_SOC:
- sysctl->soft_reset.soft_reset = rst_value;
- break;
- case SYSCTL_RESET_ROM:
- sysctl->peri_reset.rom_reset = rst_value;
- break;
- case SYSCTL_RESET_DMA:
- sysctl->peri_reset.dma_reset = rst_value;
- break;
- case SYSCTL_RESET_AI:
- sysctl->peri_reset.ai_reset = rst_value;
- break;
- case SYSCTL_RESET_DVP:
- sysctl->peri_reset.dvp_reset = rst_value;
- break;
- case SYSCTL_RESET_FFT:
- sysctl->peri_reset.fft_reset = rst_value;
- break;
- case SYSCTL_RESET_GPIO:
- sysctl->peri_reset.gpio_reset = rst_value;
- break;
- case SYSCTL_RESET_SPI0:
- sysctl->peri_reset.spi0_reset = rst_value;
- break;
- case SYSCTL_RESET_SPI1:
- sysctl->peri_reset.spi1_reset = rst_value;
- break;
- case SYSCTL_RESET_SPI2:
- sysctl->peri_reset.spi2_reset = rst_value;
- break;
- case SYSCTL_RESET_SPI3:
- sysctl->peri_reset.spi3_reset = rst_value;
- break;
- case SYSCTL_RESET_I2S0:
- sysctl->peri_reset.i2s0_reset = rst_value;
- break;
- case SYSCTL_RESET_I2S1:
- sysctl->peri_reset.i2s1_reset = rst_value;
- break;
- case SYSCTL_RESET_I2S2:
- sysctl->peri_reset.i2s2_reset = rst_value;
- break;
- case SYSCTL_RESET_I2C0:
- sysctl->peri_reset.i2c0_reset = rst_value;
- break;
- case SYSCTL_RESET_I2C1:
- sysctl->peri_reset.i2c1_reset = rst_value;
- break;
- case SYSCTL_RESET_I2C2:
- sysctl->peri_reset.i2c2_reset = rst_value;
- break;
- case SYSCTL_RESET_UART1:
- sysctl->peri_reset.uart1_reset = rst_value;
- break;
- case SYSCTL_RESET_UART2:
- sysctl->peri_reset.uart2_reset = rst_value;
- break;
- case SYSCTL_RESET_UART3:
- sysctl->peri_reset.uart3_reset = rst_value;
- break;
- case SYSCTL_RESET_AES:
- sysctl->peri_reset.aes_reset = rst_value;
- break;
- case SYSCTL_RESET_FPIOA:
- sysctl->peri_reset.fpioa_reset = rst_value;
- break;
- case SYSCTL_RESET_TIMER0:
- sysctl->peri_reset.timer0_reset = rst_value;
- break;
- case SYSCTL_RESET_TIMER1:
- sysctl->peri_reset.timer1_reset = rst_value;
- break;
- case SYSCTL_RESET_TIMER2:
- sysctl->peri_reset.timer2_reset = rst_value;
- break;
- case SYSCTL_RESET_WDT0:
- sysctl->peri_reset.wdt0_reset = rst_value;
- break;
- case SYSCTL_RESET_WDT1:
- sysctl->peri_reset.wdt1_reset = rst_value;
- break;
- case SYSCTL_RESET_SHA:
- sysctl->peri_reset.sha_reset = rst_value;
- break;
- case SYSCTL_RESET_RTC:
- sysctl->peri_reset.rtc_reset = rst_value;
- break;
- default:
- break;
- }
- }
- void sysctl_reset(sysctl_reset_t reset)
- {
- sysctl_reset_ctl(reset, 1);
- usleep(10);
- sysctl_reset_ctl(reset, 0);
- }
- static int sysctl_clock_bus_en(sysctl_clock_t clock, uint8_t en)
- {
- /*
- * The timer is under APB0, to prevent apb0_clk_en1 and apb0_clk_en0
- * on same register, we split it to peripheral and central two
- * registers, to protect CPU close apb0 clock accidentally.
- *
- * The apb0_clk_en0 and apb0_clk_en1 have same function,
- * one of them set, the APB0 clock enable.
- */
- /* The APB clock should carefully disable */
- if(en)
- {
- switch(clock)
- {
- /*
- * These peripheral devices are under APB0
- * GPIO, UART1, UART2, UART3, SPI_SLAVE, I2S0, I2S1,
- * I2S2, I2C0, I2C1, I2C2, FPIOA, SHA256, TIMER0,
- * TIMER1, TIMER2
- */
- case SYSCTL_CLOCK_GPIO:
- case SYSCTL_CLOCK_SPI2:
- case SYSCTL_CLOCK_I2S0:
- case SYSCTL_CLOCK_I2S1:
- case SYSCTL_CLOCK_I2S2:
- case SYSCTL_CLOCK_I2C0:
- case SYSCTL_CLOCK_I2C1:
- case SYSCTL_CLOCK_I2C2:
- case SYSCTL_CLOCK_UART1:
- case SYSCTL_CLOCK_UART2:
- case SYSCTL_CLOCK_UART3:
- case SYSCTL_CLOCK_FPIOA:
- case SYSCTL_CLOCK_TIMER0:
- case SYSCTL_CLOCK_TIMER1:
- case SYSCTL_CLOCK_TIMER2:
- case SYSCTL_CLOCK_SHA:
- sysctl->clk_en_cent.apb0_clk_en = en;
- break;
- /*
- * These peripheral devices are under APB1
- * WDT, AES, OTP, DVP, SYSCTL
- */
- case SYSCTL_CLOCK_AES:
- case SYSCTL_CLOCK_WDT0:
- case SYSCTL_CLOCK_WDT1:
- case SYSCTL_CLOCK_OTP:
- case SYSCTL_CLOCK_RTC:
- sysctl->clk_en_cent.apb1_clk_en = en;
- break;
- /*
- * These peripheral devices are under APB2
- * SPI0, SPI1
- */
- case SYSCTL_CLOCK_SPI0:
- case SYSCTL_CLOCK_SPI1:
- sysctl->clk_en_cent.apb2_clk_en = en;
- break;
- default:
- break;
- }
- }
- return 0;
- }
- static int sysctl_clock_device_en(sysctl_clock_t clock, uint8_t en)
- {
- switch(clock)
- {
- /*
- * These devices are PLL
- */
- case SYSCTL_CLOCK_PLL0:
- sysctl->pll0.pll_out_en0 = en;
- break;
- case SYSCTL_CLOCK_PLL1:
- sysctl->pll1.pll_out_en1 = en;
- break;
- case SYSCTL_CLOCK_PLL2:
- sysctl->pll2.pll_out_en2 = en;
- break;
- /*
- * These devices are CPU, SRAM, APB bus, ROM, DMA, AI
- */
- case SYSCTL_CLOCK_CPU:
- sysctl->clk_en_cent.cpu_clk_en = en;
- break;
- case SYSCTL_CLOCK_SRAM0:
- sysctl->clk_en_cent.sram0_clk_en = en;
- break;
- case SYSCTL_CLOCK_SRAM1:
- sysctl->clk_en_cent.sram1_clk_en = en;
- break;
- case SYSCTL_CLOCK_APB0:
- sysctl->clk_en_cent.apb0_clk_en = en;
- break;
- case SYSCTL_CLOCK_APB1:
- sysctl->clk_en_cent.apb1_clk_en = en;
- break;
- case SYSCTL_CLOCK_APB2:
- sysctl->clk_en_cent.apb2_clk_en = en;
- break;
- case SYSCTL_CLOCK_ROM:
- sysctl->clk_en_peri.rom_clk_en = en;
- break;
- case SYSCTL_CLOCK_DMA:
- sysctl->clk_en_peri.dma_clk_en = en;
- break;
- case SYSCTL_CLOCK_AI:
- sysctl->clk_en_peri.ai_clk_en = en;
- break;
- case SYSCTL_CLOCK_DVP:
- sysctl->clk_en_peri.dvp_clk_en = en;
- break;
- case SYSCTL_CLOCK_FFT:
- sysctl->clk_en_peri.fft_clk_en = en;
- break;
- case SYSCTL_CLOCK_SPI3:
- sysctl->clk_en_peri.spi3_clk_en = en;
- break;
- /*
- * These peripheral devices are under APB0
- * GPIO, UART1, UART2, UART3, SPI_SLAVE, I2S0, I2S1,
- * I2S2, I2C0, I2C1, I2C2, FPIOA, SHA256, TIMER0,
- * TIMER1, TIMER2
- */
- case SYSCTL_CLOCK_GPIO:
- sysctl->clk_en_peri.gpio_clk_en = en;
- break;
- case SYSCTL_CLOCK_SPI2:
- sysctl->clk_en_peri.spi2_clk_en = en;
- break;
- case SYSCTL_CLOCK_I2S0:
- sysctl->clk_en_peri.i2s0_clk_en = en;
- break;
- case SYSCTL_CLOCK_I2S1:
- sysctl->clk_en_peri.i2s1_clk_en = en;
- break;
- case SYSCTL_CLOCK_I2S2:
- sysctl->clk_en_peri.i2s2_clk_en = en;
- break;
- case SYSCTL_CLOCK_I2C0:
- sysctl->clk_en_peri.i2c0_clk_en = en;
- break;
- case SYSCTL_CLOCK_I2C1:
- sysctl->clk_en_peri.i2c1_clk_en = en;
- break;
- case SYSCTL_CLOCK_I2C2:
- sysctl->clk_en_peri.i2c2_clk_en = en;
- break;
- case SYSCTL_CLOCK_UART1:
- sysctl->clk_en_peri.uart1_clk_en = en;
- break;
- case SYSCTL_CLOCK_UART2:
- sysctl->clk_en_peri.uart2_clk_en = en;
- break;
- case SYSCTL_CLOCK_UART3:
- sysctl->clk_en_peri.uart3_clk_en = en;
- break;
- case SYSCTL_CLOCK_FPIOA:
- sysctl->clk_en_peri.fpioa_clk_en = en;
- break;
- case SYSCTL_CLOCK_TIMER0:
- sysctl->clk_en_peri.timer0_clk_en = en;
- break;
- case SYSCTL_CLOCK_TIMER1:
- sysctl->clk_en_peri.timer1_clk_en = en;
- break;
- case SYSCTL_CLOCK_TIMER2:
- sysctl->clk_en_peri.timer2_clk_en = en;
- break;
- case SYSCTL_CLOCK_SHA:
- sysctl->clk_en_peri.sha_clk_en = en;
- break;
- /*
- * These peripheral devices are under APB1
- * WDT, AES, OTP, DVP, SYSCTL
- */
- case SYSCTL_CLOCK_AES:
- sysctl->clk_en_peri.aes_clk_en = en;
- break;
- case SYSCTL_CLOCK_WDT0:
- sysctl->clk_en_peri.wdt0_clk_en = en;
- break;
- case SYSCTL_CLOCK_WDT1:
- sysctl->clk_en_peri.wdt1_clk_en = en;
- break;
- case SYSCTL_CLOCK_OTP:
- sysctl->clk_en_peri.otp_clk_en = en;
- break;
- case SYSCTL_CLOCK_RTC:
- sysctl->clk_en_peri.rtc_clk_en = en;
- break;
- /*
- * These peripheral devices are under APB2
- * SPI0, SPI1
- */
- case SYSCTL_CLOCK_SPI0:
- sysctl->clk_en_peri.spi0_clk_en = en;
- break;
- case SYSCTL_CLOCK_SPI1:
- sysctl->clk_en_peri.spi1_clk_en = en;
- break;
- default:
- break;
- }
- return 0;
- }
- int sysctl_clock_enable(sysctl_clock_t clock)
- {
- if(clock >= SYSCTL_CLOCK_MAX)
- return -1;
- sysctl_clock_bus_en(clock, 1);
- sysctl_clock_device_en(clock, 1);
- return 0;
- }
- int sysctl_clock_disable(sysctl_clock_t clock)
- {
- if(clock >= SYSCTL_CLOCK_MAX)
- return -1;
- sysctl_clock_device_en(clock, 0);
- return 0;
- }
- int sysctl_clock_set_threshold(sysctl_threshold_t which, int threshold)
- {
- int result = 0;
- switch(which)
- {
- /*
- * These threshold is 2 bit width
- */
- case SYSCTL_THRESHOLD_ACLK:
- sysctl->clk_sel0.aclk_divider_sel = (uint8_t)threshold & 0x03;
- break;
- /*
- * These threshold is 3 bit width
- */
- case SYSCTL_THRESHOLD_APB0:
- sysctl->clk_sel0.apb0_clk_sel = (uint8_t)threshold & 0x07;
- break;
- case SYSCTL_THRESHOLD_APB1:
- sysctl->clk_sel0.apb1_clk_sel = (uint8_t)threshold & 0x07;
- break;
- case SYSCTL_THRESHOLD_APB2:
- sysctl->clk_sel0.apb2_clk_sel = (uint8_t)threshold & 0x07;
- break;
- /*
- * These threshold is 4 bit width
- */
- case SYSCTL_THRESHOLD_SRAM0:
- sysctl->clk_th0.sram0_gclk_threshold = (uint8_t)threshold & 0x0F;
- break;
- case SYSCTL_THRESHOLD_SRAM1:
- sysctl->clk_th0.sram1_gclk_threshold = (uint8_t)threshold & 0x0F;
- break;
- case SYSCTL_THRESHOLD_AI:
- sysctl->clk_th0.ai_gclk_threshold = (uint8_t)threshold & 0x0F;
- break;
- case SYSCTL_THRESHOLD_DVP:
- sysctl->clk_th0.dvp_gclk_threshold = (uint8_t)threshold & 0x0F;
- break;
- case SYSCTL_THRESHOLD_ROM:
- sysctl->clk_th0.rom_gclk_threshold = (uint8_t)threshold & 0x0F;
- break;
- /*
- * These threshold is 8 bit width
- */
- case SYSCTL_THRESHOLD_SPI0:
- sysctl->clk_th1.spi0_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_SPI1:
- sysctl->clk_th1.spi1_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_SPI2:
- sysctl->clk_th1.spi2_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_SPI3:
- sysctl->clk_th1.spi3_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_TIMER0:
- sysctl->clk_th2.timer0_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_TIMER1:
- sysctl->clk_th2.timer1_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_TIMER2:
- sysctl->clk_th2.timer2_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_I2S0_M:
- sysctl->clk_th4.i2s0_mclk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_I2S1_M:
- sysctl->clk_th4.i2s1_mclk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_I2S2_M:
- sysctl->clk_th5.i2s2_mclk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_I2C0:
- sysctl->clk_th5.i2c0_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_I2C1:
- sysctl->clk_th5.i2c1_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_I2C2:
- sysctl->clk_th5.i2c2_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_WDT0:
- sysctl->clk_th6.wdt0_clk_threshold = (uint8_t)threshold;
- break;
- case SYSCTL_THRESHOLD_WDT1:
- sysctl->clk_th6.wdt1_clk_threshold = (uint8_t)threshold;
- break;
- /*
- * These threshold is 16 bit width
- */
- case SYSCTL_THRESHOLD_I2S0:
- sysctl->clk_th3.i2s0_clk_threshold = (uint16_t)threshold;
- break;
- case SYSCTL_THRESHOLD_I2S1:
- sysctl->clk_th3.i2s1_clk_threshold = (uint16_t)threshold;
- break;
- case SYSCTL_THRESHOLD_I2S2:
- sysctl->clk_th4.i2s2_clk_threshold = (uint16_t)threshold;
- break;
- default:
- result = -1;
- break;
- }
- return result;
- }
- int sysctl_clock_get_threshold(sysctl_threshold_t which)
- {
- int threshold = 0;
- switch(which)
- {
- /*
- * Select and get threshold value
- */
- case SYSCTL_THRESHOLD_ACLK:
- threshold = (int)sysctl->clk_sel0.aclk_divider_sel;
- break;
- case SYSCTL_THRESHOLD_APB0:
- threshold = (int)sysctl->clk_sel0.apb0_clk_sel;
- break;
- case SYSCTL_THRESHOLD_APB1:
- threshold = (int)sysctl->clk_sel0.apb1_clk_sel;
- break;
- case SYSCTL_THRESHOLD_APB2:
- threshold = (int)sysctl->clk_sel0.apb2_clk_sel;
- break;
- case SYSCTL_THRESHOLD_SRAM0:
- threshold = (int)sysctl->clk_th0.sram0_gclk_threshold;
- break;
- case SYSCTL_THRESHOLD_SRAM1:
- threshold = (int)sysctl->clk_th0.sram1_gclk_threshold;
- break;
- case SYSCTL_THRESHOLD_AI:
- threshold = (int)sysctl->clk_th0.ai_gclk_threshold;
- break;
- case SYSCTL_THRESHOLD_DVP:
- threshold = (int)sysctl->clk_th0.dvp_gclk_threshold;
- break;
- case SYSCTL_THRESHOLD_ROM:
- threshold = (int)sysctl->clk_th0.rom_gclk_threshold;
- break;
- case SYSCTL_THRESHOLD_SPI0:
- threshold = (int)sysctl->clk_th1.spi0_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_SPI1:
- threshold = (int)sysctl->clk_th1.spi1_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_SPI2:
- threshold = (int)sysctl->clk_th1.spi2_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_SPI3:
- threshold = (int)sysctl->clk_th1.spi3_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_TIMER0:
- threshold = (int)sysctl->clk_th2.timer0_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_TIMER1:
- threshold = (int)sysctl->clk_th2.timer1_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_TIMER2:
- threshold = (int)sysctl->clk_th2.timer2_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_I2S0:
- threshold = (int)sysctl->clk_th3.i2s0_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_I2S1:
- threshold = (int)sysctl->clk_th3.i2s1_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_I2S2:
- threshold = (int)sysctl->clk_th4.i2s2_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_I2S0_M:
- threshold = (int)sysctl->clk_th4.i2s0_mclk_threshold;
- break;
- case SYSCTL_THRESHOLD_I2S1_M:
- threshold = (int)sysctl->clk_th4.i2s1_mclk_threshold;
- break;
- case SYSCTL_THRESHOLD_I2S2_M:
- threshold = (int)sysctl->clk_th5.i2s2_mclk_threshold;
- break;
- case SYSCTL_THRESHOLD_I2C0:
- threshold = (int)sysctl->clk_th5.i2c0_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_I2C1:
- threshold = (int)sysctl->clk_th5.i2c1_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_I2C2:
- threshold = (int)sysctl->clk_th5.i2c2_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_WDT0:
- threshold = (int)sysctl->clk_th6.wdt0_clk_threshold;
- break;
- case SYSCTL_THRESHOLD_WDT1:
- threshold = (int)sysctl->clk_th6.wdt1_clk_threshold;
- break;
- default:
- break;
- }
- return threshold;
- }
- int sysctl_clock_set_clock_select(sysctl_clock_select_t which, int select)
- {
- int result = 0;
- switch(which)
- {
- /*
- * These clock select is 1 bit width
- */
- case SYSCTL_CLOCK_SELECT_PLL0_BYPASS:
- sysctl->pll0.pll_bypass0 = select & 0x01;
- break;
- case SYSCTL_CLOCK_SELECT_PLL1_BYPASS:
- sysctl->pll1.pll_bypass1 = select & 0x01;
- break;
- case SYSCTL_CLOCK_SELECT_PLL2_BYPASS:
- sysctl->pll2.pll_bypass2 = select & 0x01;
- break;
- case SYSCTL_CLOCK_SELECT_ACLK:
- sysctl->clk_sel0.aclk_sel = select & 0x01;
- break;
- case SYSCTL_CLOCK_SELECT_SPI3:
- sysctl->clk_sel0.spi3_clk_sel = select & 0x01;
- break;
- case SYSCTL_CLOCK_SELECT_TIMER0:
- sysctl->clk_sel0.timer0_clk_sel = select & 0x01;
- break;
- case SYSCTL_CLOCK_SELECT_TIMER1:
- sysctl->clk_sel0.timer1_clk_sel = select & 0x01;
- break;
- case SYSCTL_CLOCK_SELECT_TIMER2:
- sysctl->clk_sel0.timer2_clk_sel = select & 0x01;
- break;
- case SYSCTL_CLOCK_SELECT_SPI3_SAMPLE:
- sysctl->clk_sel1.spi3_sample_clk_sel = select & 0x01;
- break;
- /*
- * These clock select is 2 bit width
- */
- case SYSCTL_CLOCK_SELECT_PLL2:
- sysctl->pll2.pll_ckin_sel2 = select & 0x03;
- break;
- default:
- result = -1;
- break;
- }
- return result;
- }
- int sysctl_clock_get_clock_select(sysctl_clock_select_t which)
- {
- int clock_select = 0;
- switch(which)
- {
- /*
- * Select and get clock select value
- */
- case SYSCTL_CLOCK_SELECT_PLL0_BYPASS:
- clock_select = (int)sysctl->pll0.pll_bypass0;
- break;
- case SYSCTL_CLOCK_SELECT_PLL1_BYPASS:
- clock_select = (int)sysctl->pll1.pll_bypass1;
- break;
- case SYSCTL_CLOCK_SELECT_PLL2_BYPASS:
- clock_select = (int)sysctl->pll2.pll_bypass2;
- break;
- case SYSCTL_CLOCK_SELECT_PLL2:
- clock_select = (int)sysctl->pll2.pll_ckin_sel2;
- break;
- case SYSCTL_CLOCK_SELECT_ACLK:
- clock_select = (int)sysctl->clk_sel0.aclk_sel;
- break;
- case SYSCTL_CLOCK_SELECT_SPI3:
- clock_select = (int)sysctl->clk_sel0.spi3_clk_sel;
- break;
- case SYSCTL_CLOCK_SELECT_TIMER0:
- clock_select = (int)sysctl->clk_sel0.timer0_clk_sel;
- break;
- case SYSCTL_CLOCK_SELECT_TIMER1:
- clock_select = (int)sysctl->clk_sel0.timer1_clk_sel;
- break;
- case SYSCTL_CLOCK_SELECT_TIMER2:
- clock_select = (int)sysctl->clk_sel0.timer2_clk_sel;
- break;
- case SYSCTL_CLOCK_SELECT_SPI3_SAMPLE:
- clock_select = (int)sysctl->clk_sel1.spi3_sample_clk_sel;
- break;
- default:
- break;
- }
- return clock_select;
- }
- uint32_t sysctl_clock_source_get_freq(sysctl_clock_source_t input)
- {
- uint32_t result;
- switch(input)
- {
- case SYSCTL_SOURCE_IN0:
- result = SYSCTRL_CLOCK_FREQ_IN0;
- break;
- case SYSCTL_SOURCE_PLL0:
- result = sysctl_pll_get_freq(SYSCTL_PLL0);
- break;
- case SYSCTL_SOURCE_PLL1:
- result = sysctl_pll_get_freq(SYSCTL_PLL1);
- break;
- case SYSCTL_SOURCE_PLL2:
- result = sysctl_pll_get_freq(SYSCTL_PLL2);
- break;
- case SYSCTL_SOURCE_ACLK:
- result = sysctl_clock_get_freq(SYSCTL_CLOCK_ACLK);
- break;
- default:
- result = 0;
- break;
- }
- return result;
- }
- static int sysctl_pll_is_lock(sysctl_pll_t pll)
- {
- /*
- * All bit enable means PLL lock
- *
- * struct pll_lock_t
- * {
- * uint8_t overflow : 1;
- * uint8_t rfslip : 1;
- * uint8_t fbslip : 1;
- * };
- *
- */
- if(pll >= SYSCTL_PLL_MAX)
- return 0;
- switch(pll)
- {
- case SYSCTL_PLL0:
- return sysctl->pll_lock.pll_lock0 == 3;
- case SYSCTL_PLL1:
- return sysctl->pll_lock.pll_lock1 & 1;
- case SYSCTL_PLL2:
- return sysctl->pll_lock.pll_lock2 & 1;
- default:
- break;
- }
- return 0;
- }
- static int sysctl_pll_clear_slip(sysctl_pll_t pll)
- {
- if(pll >= SYSCTL_PLL_MAX)
- return -1;
- switch(pll)
- {
- case SYSCTL_PLL0:
- sysctl->pll_lock.pll_slip_clear0 = 1;
- break;
- case SYSCTL_PLL1:
- sysctl->pll_lock.pll_slip_clear1 = 1;
- break;
- case SYSCTL_PLL2:
- sysctl->pll_lock.pll_slip_clear2 = 1;
- break;
- default:
- break;
- }
- return sysctl_pll_is_lock(pll) ? 0 : -1;
- }
- int sysctl_pll_enable(sysctl_pll_t pll)
- {
- /*
- * ---+
- * PWRDN |
- * +-------------------------------------------------------------
- * ^
- * |
- * |
- * t1
- * +------------------+
- * RESET | |
- * ----------+ +-----------------------------------
- * ^ ^ ^
- * |<----- t_rst ---->|<---------- t_lock ---------->|
- * | | |
- * t2 t3 t4
- */
- if(pll >= SYSCTL_PLL_MAX)
- return -1;
- switch(pll)
- {
- case SYSCTL_PLL0:
- /* Do not bypass PLL */
- sysctl->pll0.pll_bypass0 = 0;
- /*
- * Power on the PLL, negtive from PWRDN
- * 0 is power off
- * 1 is power on
- */
- sysctl->pll0.pll_pwrd0 = 1;
- /*
- * Reset trigger of the PLL, connected RESET
- * 0 is free
- * 1 is reset
- */
- sysctl->pll0.pll_reset0 = 0;
- sysctl->pll0.pll_reset0 = 1;
- asm volatile("nop");
- asm volatile("nop");
- sysctl->pll0.pll_reset0 = 0;
- break;
- case SYSCTL_PLL1:
- /* Do not bypass PLL */
- sysctl->pll1.pll_bypass1 = 0;
- /*
- * Power on the PLL, negtive from PWRDN
- * 0 is power off
- * 1 is power on
- */
- sysctl->pll1.pll_pwrd1 = 1;
- /*
- * Reset trigger of the PLL, connected RESET
- * 0 is free
- * 1 is reset
- */
- sysctl->pll1.pll_reset1 = 0;
- sysctl->pll1.pll_reset1 = 1;
- asm volatile("nop");
- asm volatile("nop");
- sysctl->pll1.pll_reset1 = 0;
- break;
- case SYSCTL_PLL2:
- /* Do not bypass PLL */
- sysctl->pll2.pll_bypass2 = 0;
- /*
- * Power on the PLL, negtive from PWRDN
- * 0 is power off
- * 1 is power on
- */
- sysctl->pll2.pll_pwrd2 = 1;
- /*
- * Reset trigger of the PLL, connected RESET
- * 0 is free
- * 1 is reset
- */
- sysctl->pll2.pll_reset2 = 0;
- sysctl->pll2.pll_reset2 = 1;
- asm volatile("nop");
- asm volatile("nop");
- sysctl->pll2.pll_reset2 = 0;
- break;
- default:
- break;
- }
- return 0;
- }
- int sysctl_pll_disable(sysctl_pll_t pll)
- {
- if(pll >= SYSCTL_PLL_MAX)
- return -1;
- switch(pll)
- {
- case SYSCTL_PLL0:
- /* Bypass PLL */
- sysctl->pll0.pll_bypass0 = 1;
- /*
- * Power on the PLL, negtive from PWRDN
- * 0 is power off
- * 1 is power on
- */
- sysctl->pll0.pll_pwrd0 = 0;
- break;
- case SYSCTL_PLL1:
- /* Bypass PLL */
- sysctl->pll1.pll_bypass1 = 1;
- /*
- * Power on the PLL, negtive from PWRDN
- * 0 is power off
- * 1 is power on
- */
- sysctl->pll1.pll_pwrd1 = 0;
- break;
- case SYSCTL_PLL2:
- /* Bypass PLL */
- sysctl->pll2.pll_bypass2 = 1;
- /*
- * Power on the PLL, negtive from PWRDN
- * 0 is power off
- * 1 is power on
- */
- sysctl->pll2.pll_pwrd2 = 0;
- break;
- default:
- break;
- }
- return 0;
- }
- uint32_t sysctl_pll_get_freq(sysctl_pll_t pll)
- {
- uint32_t freq_in = 0, freq_out = 0;
- uint32_t nr = 0, nf = 0, od = 0;
- uint8_t select = 0;
- if(pll >= SYSCTL_PLL_MAX)
- return 0;
- switch(pll)
- {
- case SYSCTL_PLL0:
- freq_in = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- nr = sysctl->pll0.clkr0 + 1;
- nf = sysctl->pll0.clkf0 + 1;
- od = sysctl->pll0.clkod0 + 1;
- break;
- case SYSCTL_PLL1:
- freq_in = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- nr = sysctl->pll1.clkr1 + 1;
- nf = sysctl->pll1.clkf1 + 1;
- od = sysctl->pll1.clkod1 + 1;
- break;
- case SYSCTL_PLL2:
- /*
- * Get input freq accroding select register
- */
- select = sysctl->pll2.pll_ckin_sel2;
- if(select < sizeof(get_source_pll2))
- freq_in = sysctl_clock_source_get_freq(get_source_pll2[select]);
- else
- return 0;
- nr = sysctl->pll2.clkr2 + 1;
- nf = sysctl->pll2.clkf2 + 1;
- od = sysctl->pll2.clkod2 + 1;
- break;
- default:
- break;
- }
- /*
- * Get final PLL output freq
- * FOUT = FIN / NR * NF / OD
- */
- freq_out = (double)freq_in / (double)nr * (double)nf / (double)od;
- return freq_out;
- }
- static uint32_t sysctl_pll_source_set_freq(sysctl_pll_t pll, sysctl_clock_source_t source, uint32_t freq)
- {
- uint32_t freq_in = 0;
- if(pll >= SYSCTL_PLL_MAX)
- return 0;
- if(source >= SYSCTL_SOURCE_MAX)
- return 0;
- switch(pll)
- {
- case SYSCTL_PLL0:
- case SYSCTL_PLL1:
- /*
- * Check input clock source
- */
- if(source != SYSCTL_SOURCE_IN0)
- return 0;
- freq_in = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- /*
- * Check input clock freq
- */
- if(freq_in == 0)
- return 0;
- break;
- case SYSCTL_PLL2:
- /*
- * Check input clock source
- */
- if(source < sizeof(get_select_pll2))
- freq_in = sysctl_clock_source_get_freq(source);
- /*
- * Check input clock freq
- */
- if(freq_in == 0)
- return 0;
- break;
- default:
- return 0;
- }
- /*
- * Begin calculate PLL registers' value
- */
- /* constants */
- const double vco_min = 3.5e+08;
- const double vco_max = 1.75e+09;
- const double ref_min = 1.36719e+07;
- const double ref_max = 1.75e+09;
- const int nr_min = 1;
- const int nr_max = 16;
- const int nf_min = 1;
- const int nf_max = 64;
- const int no_min = 1;
- const int no_max = 16;
- const int nb_min = 1;
- const int nb_max = 64;
- const int max_vco = 1;
- const int ref_rng = 1;
- /* variables */
- int nr = 0;
- int nrx = 0;
- int nf = 0;
- int nfi = 0;
- int no = 0;
- int noe = 0;
- int not = 0;
- int nor = 0;
- int nore = 0;
- int nb = 0;
- int first = 0;
- int firstx = 0;
- int found = 0;
- long long nfx = 0;
- double fin = 0, fout = 0, fvco = 0;
- double val = 0, nval = 0, err = 0, merr = 0, terr = 0;
- int x_nrx = 0, x_no = 0, x_nb = 0;
- long long x_nfx = 0;
- double x_fvco = 0, x_err = 0;
- fin = freq_in;
- fout = freq;
- val = fout / fin;
- terr = 0.5 / ((double)(nf_max / 2));
- first = firstx = 1;
- if(terr != -2)
- {
- first = 0;
- if(terr == 0)
- terr = 1e-16;
- merr = fabs(terr);
- }
- found = 0;
- for(nfi = val; nfi < nf_max; ++nfi)
- {
- nr = rint(((double)nfi) / val);
- if(nr == 0)
- continue;
- if((ref_rng) && (nr < nr_min))
- continue;
- if(fin / ((double)nr) > ref_max)
- continue;
- nrx = nr;
- nf = nfx = nfi;
- nval = ((double)nfx) / ((double)nr);
- if(nf == 0)
- nf = 1;
- err = 1 - nval / val;
- if((first) || (fabs(err) < merr * (1 + 1e-6)) || (fabs(err) < 1e-16))
- {
- not = floor(vco_max / fout);
- for(no = (not > no_max) ? no_max : not; no > no_min; --no)
- {
- if((ref_rng) && ((nr / no) < nr_min))
- continue;
- if((nr % no) == 0)
- break;
- }
- if((nr % no) != 0)
- continue;
- nor = ((not > no_max) ? no_max : not) / no;
- nore = nf_max / nf;
- if(nor > nore)
- nor = nore;
- noe = ceil(vco_min / fout);
- if(!max_vco)
- {
- nore = (noe - 1) / no + 1;
- nor = nore;
- not = 0; /* force next if to fail */
- }
- if((((no * nor) < (not >> 1)) || ((no * nor) < noe)) && ((no * nor) < (nf_max / nf)))
- {
- no = nf_max / nf;
- if(no > no_max)
- no = no_max;
- if(no > not)
- no = not;
- nfx *= no;
- nf *= no;
- if((no > 1) && (!firstx))
- continue;
- /* wait for larger nf in later iterations */
- } else
- {
- nrx /= no;
- nfx *= nor;
- nf *= nor;
- no *= nor;
- if(no > no_max)
- continue;
- if((nor > 1) && (!firstx))
- continue;
- /* wait for larger nf in later iterations */
- }
- nb = nfx;
- if(nb < nb_min)
- nb = nb_min;
- if(nb > nb_max)
- continue;
- fvco = fin / ((double)nrx) * ((double)nfx);
- if(fvco < vco_min)
- continue;
- if(fvco > vco_max)
- continue;
- if(nf < nf_min)
- continue;
- if((ref_rng) && (fin / ((double)nrx) < ref_min))
- continue;
- if((ref_rng) && (nrx > nr_max))
- continue;
- if(!(((firstx) && (terr < 0)) || (fabs(err) < merr * (1 - 1e-6)) || ((max_vco) && (no > x_no))))
- continue;
- if((!firstx) && (terr >= 0) && (nrx > x_nrx))
- continue;
- found = 1;
- x_no = no;
- x_nrx = nrx;
- x_nfx = nfx;
- x_nb = nb;
- x_fvco = fvco;
- x_err = err;
- first = firstx = 0;
- merr = fabs(err);
- if(terr != -1)
- continue;
- }
- }
- if(!found)
- {
- return 0;
- }
- nrx = x_nrx;
- nfx = x_nfx;
- no = x_no;
- nb = x_nb;
- fvco = x_fvco;
- err = x_err;
- if((terr != -2) && (fabs(err) >= terr * (1 - 1e-6)))
- {
- return 0;
- }
- /*
- * Begin write PLL registers' value,
- * Using atomic write method.
- */
- sysctl_pll0_t pll0;
- sysctl_pll1_t pll1;
- sysctl_pll2_t pll2;
- switch(pll)
- {
- case SYSCTL_PLL0:
- /* Read register from bus */
- pll0 = sysctl->pll0;
- /* Set register temporary value */
- pll0.clkr0 = nrx - 1;
- pll0.clkf0 = nfx - 1;
- pll0.clkod0 = no - 1;
- pll0.bwadj0 = nb - 1;
- /* Write register back to bus */
- sysctl->pll0 = pll0;
- break;
- case SYSCTL_PLL1:
- /* Read register from bus */
- pll1 = sysctl->pll1;
- /* Set register temporary value */
- pll1.clkr1 = nrx - 1;
- pll1.clkf1 = nfx - 1;
- pll1.clkod1 = no - 1;
- pll1.bwadj1 = nb - 1;
- /* Write register back to bus */
- sysctl->pll1 = pll1;
- break;
- case SYSCTL_PLL2:
- /* Read register from bus */
- pll2 = sysctl->pll2;
- /* Set register temporary value */
- if(source < sizeof(get_select_pll2))
- pll2.pll_ckin_sel2 = get_select_pll2[source];
- pll2.clkr2 = nrx - 1;
- pll2.clkf2 = nfx - 1;
- pll2.clkod2 = no - 1;
- pll2.bwadj2 = nb - 1;
- /* Write register back to bus */
- sysctl->pll2 = pll2;
- break;
- default:
- return 0;
- }
- return sysctl_pll_get_freq(pll);
- }
- uint32_t sysctl_clock_get_freq(sysctl_clock_t clock)
- {
- uint32_t source = 0;
- uint32_t result = 0;
- switch(clock)
- {
- /*
- * The clock IN0
- */
- case SYSCTL_CLOCK_IN0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- result = source;
- break;
- /*
- * These clock directly under PLL clock domain
- * They are using gated divider.
- */
- case SYSCTL_CLOCK_PLL0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- result = source;
- break;
- case SYSCTL_CLOCK_PLL1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL1);
- result = source;
- break;
- case SYSCTL_CLOCK_PLL2:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL2);
- result = source;
- break;
- /*
- * These clock directly under ACLK clock domain
- */
- case SYSCTL_CLOCK_CPU:
- switch(sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_ACLK))
- {
- case 0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- break;
- case 1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0) /
- (2ULL << sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ACLK));
- break;
- default:
- break;
- }
- result = source;
- break;
- case SYSCTL_CLOCK_DMA:
- switch(sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_ACLK))
- {
- case 0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- break;
- case 1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0) /
- (2ULL << sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ACLK));
- break;
- default:
- break;
- }
- result = source;
- break;
- case SYSCTL_CLOCK_FFT:
- switch(sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_ACLK))
- {
- case 0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- break;
- case 1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0) /
- (2ULL << sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ACLK));
- break;
- default:
- break;
- }
- result = source;
- break;
- case SYSCTL_CLOCK_ACLK:
- switch(sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_ACLK))
- {
- case 0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- break;
- case 1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0) /
- (2ULL << sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ACLK));
- break;
- default:
- break;
- }
- result = source;
- break;
- case SYSCTL_CLOCK_HCLK:
- switch(sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_ACLK))
- {
- case 0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- break;
- case 1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0) /
- (2ULL << sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ACLK));
- break;
- default:
- break;
- }
- result = source;
- break;
- /*
- * These clock under ACLK clock domain.
- * They are using gated divider.
- */
- case SYSCTL_CLOCK_SRAM0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK);
- result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SRAM0) + 1);
- break;
- case SYSCTL_CLOCK_SRAM1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK);
- result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SRAM1) + 1);
- break;
- case SYSCTL_CLOCK_ROM:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK);
- result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_ROM) + 1);
- break;
- case SYSCTL_CLOCK_DVP:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK);
- result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_DVP) + 1);
- break;
- /*
- * These clock under ACLK clock domain.
- * They are using even divider.
- */
- case SYSCTL_CLOCK_APB0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK);
- result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_APB0) + 1);
- break;
- case SYSCTL_CLOCK_APB1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK);
- result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_APB1) + 1);
- break;
- case SYSCTL_CLOCK_APB2:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_ACLK);
- result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_APB2) + 1);
- break;
- /*
- * These clock under AI clock domain.
- * They are using gated divider.
- */
- case SYSCTL_CLOCK_AI:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL1);
- result = source / (sysctl_clock_get_threshold(SYSCTL_THRESHOLD_AI) + 1);
- break;
- /*
- * These clock under I2S clock domain.
- * They are using even divider.
- */
- case SYSCTL_CLOCK_I2S0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL2);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2S0) + 1) * 2);
- break;
- case SYSCTL_CLOCK_I2S1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL2);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2S1) + 1) * 2);
- break;
- case SYSCTL_CLOCK_I2S2:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL2);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2S2) + 1) * 2);
- break;
- /*
- * These clock under WDT clock domain.
- * They are using even divider.
- */
- case SYSCTL_CLOCK_WDT0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_WDT0) + 1) * 2);
- break;
- case SYSCTL_CLOCK_WDT1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_WDT1) + 1) * 2);
- break;
- /*
- * These clock under PLL0 clock domain.
- * They are using even divider.
- */
- case SYSCTL_CLOCK_SPI0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SPI0) + 1) * 2);
- break;
- case SYSCTL_CLOCK_SPI1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SPI1) + 1) * 2);
- break;
- case SYSCTL_CLOCK_SPI2:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SPI2) + 1) * 2);
- break;
- case SYSCTL_CLOCK_I2C0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2C0) + 1) * 2);
- break;
- case SYSCTL_CLOCK_I2C1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2C1) + 1) * 2);
- break;
- case SYSCTL_CLOCK_I2C2:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_I2C2) + 1) * 2);
- break;
- /*
- * These clock under PLL0_SEL clock domain.
- * They are using even divider.
- */
- case SYSCTL_CLOCK_SPI3:
- switch(sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_SPI3))
- {
- case 0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- break;
- case 1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- break;
- default:
- break;
- }
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_SPI3) + 1) * 2);
- break;
- case SYSCTL_CLOCK_TIMER0:
- switch(sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_TIMER0))
- {
- case 0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- break;
- case 1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- break;
- default:
- break;
- }
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_TIMER0) + 1) * 2);
- break;
- case SYSCTL_CLOCK_TIMER1:
- switch(sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_TIMER1))
- {
- case 0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- break;
- case 1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- break;
- default:
- break;
- }
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_TIMER1) + 1) * 2);
- break;
- case SYSCTL_CLOCK_TIMER2:
- switch(sysctl_clock_get_clock_select(SYSCTL_CLOCK_SELECT_TIMER2))
- {
- case 0:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- break;
- case 1:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_PLL0);
- break;
- default:
- break;
- }
- result = source / ((sysctl_clock_get_threshold(SYSCTL_THRESHOLD_TIMER2) + 1) * 2);
- break;
- /*
- * These clock under MISC clock domain.
- * They are using even divider.
- */
- /*
- * These clock under APB0 clock domain.
- * They are using even divider.
- */
- case SYSCTL_CLOCK_GPIO:
- source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0);
- result = source;
- break;
- case SYSCTL_CLOCK_UART1:
- source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0);
- result = source;
- break;
- case SYSCTL_CLOCK_UART2:
- source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0);
- result = source;
- break;
- case SYSCTL_CLOCK_UART3:
- source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0);
- result = source;
- break;
- case SYSCTL_CLOCK_FPIOA:
- source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0);
- result = source;
- break;
- case SYSCTL_CLOCK_SHA:
- source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0);
- result = source;
- break;
- /*
- * These clock under APB1 clock domain.
- * They are using even divider.
- */
- case SYSCTL_CLOCK_AES:
- source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB1);
- result = source;
- break;
- case SYSCTL_CLOCK_OTP:
- source = sysctl_clock_get_freq(SYSCTL_CLOCK_APB1);
- result = source;
- break;
- case SYSCTL_CLOCK_RTC:
- source = sysctl_clock_source_get_freq(SYSCTL_SOURCE_IN0);
- result = source;
- break;
- /*
- * These clock under APB2 clock domain.
- * They are using even divider.
- */
- /*
- * Do nothing.
- */
- default:
- break;
- }
- return result;
- }
- int sysctl_dma_select(sysctl_dma_channel_t channel, sysctl_dma_select_t select)
- {
- sysctl_dma_sel0_t dma_sel0;
- sysctl_dma_sel1_t dma_sel1;
- /* Read register from bus */
- dma_sel0 = sysctl->dma_sel0;
- dma_sel1 = sysctl->dma_sel1;
- switch(channel)
- {
- case SYSCTL_DMA_CHANNEL_0:
- dma_sel0.dma_sel0 = select;
- break;
- case SYSCTL_DMA_CHANNEL_1:
- dma_sel0.dma_sel1 = select;
- break;
- case SYSCTL_DMA_CHANNEL_2:
- dma_sel0.dma_sel2 = select;
- break;
- case SYSCTL_DMA_CHANNEL_3:
- dma_sel0.dma_sel3 = select;
- break;
- case SYSCTL_DMA_CHANNEL_4:
- dma_sel0.dma_sel4 = select;
- break;
- case SYSCTL_DMA_CHANNEL_5:
- dma_sel1.dma_sel5 = select;
- break;
- default:
- return -1;
- }
- /* Write register back to bus */
- sysctl->dma_sel0 = dma_sel0;
- sysctl->dma_sel1 = dma_sel1;
- return 0;
- }
- uint32_t sysctl_pll_fast_enable_pll(void)
- {
- /*
- * Begin write PLL registers' value,
- * Using atomic write method.
- */
- sysctl_pll0_t pll0;
- sysctl_pll1_t pll1;
- sysctl_pll2_t pll2;
- /* Read register from bus */
- pll0 = sysctl->pll0;
- pll1 = sysctl->pll1;
- pll2 = sysctl->pll2;
- /* PLL VCO MAX freq: 1.8GHz */
- /* PLL0: 26M reference clk get 793M output clock */
- pll0.clkr0 = 0;
- pll0.clkf0 = 60;
- pll0.clkod0 = 1;
- pll0.bwadj0 = 60;
- /* PLL1: 26M reference clk get 390M output clock */
- pll1.clkr1 = 0;
- pll1.clkf1 = 59;
- pll1.clkod1 = 3;
- pll1.bwadj1 = 59;
- /* PLL2: 26M reference clk get 390M output clock */
- pll2.clkr2 = 0;
- pll2.clkf2 = 59;
- pll2.clkod2 = 3;
- pll2.bwadj2 = 59;
- /* Write register to bus */
- sysctl->pll0 = pll0;
- sysctl->pll1 = pll1;
- sysctl->pll2 = pll2;
- sysctl_pll_enable(SYSCTL_PLL0);
- sysctl_pll_enable(SYSCTL_PLL1);
- sysctl_pll_enable(SYSCTL_PLL2);
- while(sysctl_pll_is_lock(SYSCTL_PLL0) == 0)
- sysctl_pll_clear_slip(SYSCTL_PLL0);
- while(sysctl_pll_is_lock(SYSCTL_PLL1) == 0)
- sysctl_pll_clear_slip(SYSCTL_PLL1);
- while(sysctl_pll_is_lock(SYSCTL_PLL2) == 0)
- sysctl_pll_clear_slip(SYSCTL_PLL2);
- sysctl_clock_enable(SYSCTL_CLOCK_PLL0);
- sysctl_clock_enable(SYSCTL_CLOCK_PLL1);
- sysctl_clock_enable(SYSCTL_CLOCK_PLL2);
- /* Set ACLK to PLL0 */
- sysctl_clock_set_clock_select(SYSCTL_CLOCK_SELECT_ACLK, SYSCTL_SOURCE_PLL0);
- return 0;
- }
- uint32_t sysctl_set_spi0_dvp_data(uint8_t en)
- {
- sysctl->misc.spi_dvp_data_enable = en;
- return 0;
- }
- void sysctl_set_power_mode(sysctl_power_bank_t power_bank, sysctl_io_power_mode_t io_power_mode)
- {
- if(io_power_mode)
- *((uint32_t *)(&sysctl->power_sel)) |= (1 << power_bank);
- else
- *((uint32_t *)(&sysctl->power_sel)) &= ~(1 << power_bank);
- }
- uint32_t sysctl_pll_set_freq(sysctl_pll_t pll, uint32_t pll_freq)
- {
- if(pll_freq == 0)
- return 0;
- volatile sysctl_general_pll_t *v_pll_t;
- switch(pll)
- {
- case SYSCTL_PLL0:
- v_pll_t = (sysctl_general_pll_t *)(&sysctl->pll0);
- break;
- case SYSCTL_PLL1:
- v_pll_t = (sysctl_general_pll_t *)(&sysctl->pll1);
- break;
- case SYSCTL_PLL2:
- v_pll_t = (sysctl_general_pll_t *)(&sysctl->pll2);
- break;
- default:
- return 0;
- break;
- }
- /* 1. Change CPU CLK to XTAL */
- if(pll == SYSCTL_PLL0)
- sysctl_clock_set_clock_select(SYSCTL_CLOCK_SELECT_ACLK, SYSCTL_SOURCE_IN0);
- /* 2. Disable PLL output */
- v_pll_t->pll_out_en = 0;
- /* 3. Turn off PLL */
- v_pll_t->pll_pwrd = 0;
- /* 4. Set PLL new value */
- uint32_t result;
- if(pll == SYSCTL_PLL2)
- result = sysctl_pll_source_set_freq(pll, v_pll_t->pll_ckin_sel, pll_freq);
- else
- result = sysctl_pll_source_set_freq(pll, SYSCTL_SOURCE_IN0, pll_freq);
- /* 5. Power on PLL */
- v_pll_t->pll_pwrd = 1;
- /* wait >100ns */
- usleep(1);
- /* 6. Reset PLL then Release Reset*/
- v_pll_t->pll_reset = 0;
- v_pll_t->pll_reset = 1;
- /* wait >100ns */
- usleep(1);
- v_pll_t->pll_reset = 0;
- /* 7. Get lock status, wait PLL stable */
- while(sysctl_pll_is_lock(pll) == 0)
- sysctl_pll_clear_slip(pll);
- /* 8. Enable PLL output */
- v_pll_t->pll_out_en = 1;
- /* 9. Change CPU CLK to PLL */
- if(pll == SYSCTL_PLL0)
- {
- sysctl_clock_set_clock_select(SYSCTL_CLOCK_SELECT_ACLK, SYSCTL_SOURCE_PLL0);
- uart_debug_init(-1);
- }
- return result;
- }
- static uint32_t cpu_freq = 390000000;
- uint32_t sysctl_cpu_get_freq(void)
- {
- return cpu_freq;
- }
- uint32_t sysctl_cpu_set_freq(uint32_t freq)
- {
- if(freq == 0)
- return 0;
- cpu_freq = sysctl_pll_set_freq(SYSCTL_PLL0, (sysctl->clk_sel0.aclk_divider_sel + 1) * 2 * freq);
- return cpu_freq;
- }
- void sysctl_enable_irq(void)
- {
- set_csr(mie, MIP_MEIP);
- set_csr(mstatus, MSTATUS_MIE);
- }
- void sysctl_disable_irq(void)
- {
- clear_csr(mie, MIP_MEIP);
- clear_csr(mstatus, MSTATUS_MIE);
- }
- uint64_t sysctl_get_time_us(void)
- {
- uint64_t v_cycle = read_cycle();
- return v_cycle * 1000000 / sysctl_clock_get_freq(SYSCTL_CLOCK_CPU);
- }
- sysctl_reset_enum_status_t sysctl_get_reset_status(void)
- {
- static sysctl_reset_enum_status_t s_reset_status = 0;
- if(s_reset_status != 0)
- {
- return s_reset_status;
- }
- if(sysctl->reset_status.wdt0_reset_sts)
- {
- s_reset_status = SYSCTL_RESET_STATUS_WDT0;
- } else if(sysctl->reset_status.wdt1_reset_sts)
- {
- s_reset_status = SYSCTL_RESET_STATUS_WDT1;
- } else if(sysctl->reset_status.soft_reset_sts)
- {
- s_reset_status = SYSCTL_RESET_STATUS_SOFT;
- } else
- {
- s_reset_status = SYSCTL_RESET_STATUS_HARD;
- }
- sysctl->reset_status.reset_sts_clr = 1;
- return s_reset_status;
- }
|