/* * Copyright (C) 2018 Marcus Comstedt * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include static void Fx3GpifPibIsr(void) __attribute__ ((isr ("IRQ"))); static void Fx3GpifPibIsr(void) { uint32_t req = Fx3ReadReg32(FX3_PIB_INTR) & Fx3ReadReg32(FX3_PIB_INTR_MASK); Fx3WriteReg32(FX3_PIB_INTR, req); Fx3UartTxString("Fx3GpifPibIsr\n"); if (req & FX3_PIB_INTR_GPIF_ERR) { Fx3UartTxString(" GPIF ERROR\n"); /* Pause on error */ Fx3SetReg32(FX3_GPIF_WAVEFORM_CTRL_STAT, FX3_GPIF_WAVEFORM_CTRL_STAT_PAUSE); } if (req & FX3_PIB_INTR_GPIF_INTERRUPT) { Fx3UartTxString(" GPIF\n"); uint32_t gpif_req = Fx3ReadReg32(FX3_GPIF_INTR) & Fx3ReadReg32(FX3_GPIF_INTR_MASK); Fx3WriteReg32(FX3_GPIF_INTR, gpif_req); if (gpif_req & FX3_GPIF_INTR_GPIF_INTR) Fx3UartTxString(" INTR\n"); if (gpif_req & FX3_GPIF_INTR_GPIF_DONE) Fx3UartTxString(" DONE\n"); } Fx3WriteReg32(FX3_VIC_ADDRESS, 0); } void Fx3GpifStart(uint8_t state, uint8_t alpha) { Fx3WriteReg32(FX3_GPIF_INTR, Fx3ReadReg32(FX3_GPIF_INTR)); Fx3WriteReg32(FX3_GPIF_INTR_MASK, FX3_GPIF_INTR_MASK_GPIF_INTR | FX3_GPIF_INTR_MASK_GPIF_DONE); Fx3SetField32(FX3_GPIF_WAVEFORM_CTRL_STAT, ALPHA_INIT, alpha); Fx3SetReg32(FX3_GPIF_WAVEFORM_CTRL_STAT, FX3_GPIF_WAVEFORM_CTRL_STAT_WAVEFORM_VALID); Fx3WriteReg32(FX3_GPIF_WAVEFORM_SWITCH, (Fx3ReadReg32(FX3_GPIF_WAVEFORM_SWITCH) & ~(FX3_GPIF_WAVEFORM_SWITCH_DESTINATION_STATE_SHIFT | FX3_GPIF_WAVEFORM_SWITCH_TERMINAL_STATE_MASK | FX3_GPIF_WAVEFORM_SWITCH_SWITCH_NOW | FX3_GPIF_WAVEFORM_SWITCH_WAVEFORM_SWITCH)) | (state << FX3_GPIF_WAVEFORM_SWITCH_DESTINATION_STATE_SHIFT)); Fx3SetReg32(FX3_GPIF_WAVEFORM_SWITCH, FX3_GPIF_WAVEFORM_SWITCH_SWITCH_NOW | FX3_GPIF_WAVEFORM_SWITCH_WAVEFORM_SWITCH); } void Fx3GpifStop(void) { Fx3SetReg32(FX3_GPIF_WAVEFORM_CTRL_STAT, FX3_GPIF_WAVEFORM_CTRL_STAT_PAUSE); Fx3UtilDelayUs(10); Fx3WriteReg32(FX3_GPIF_WAVEFORM_CTRL_STAT, 0); } void Fx3GpifInvalidate(void) { unsigned i; Fx3WriteReg32(FX3_GPIF_CONFIG, 0x220); for (i=0; i<256; i++) { Fx3WriteReg32(FX3_GPIF_LEFT_WAVEFORM + i*16 + 8, 0); Fx3WriteReg32(FX3_GPIF_RIGHT_WAVEFORM + i*16 + 8, 0); } for (i=0; i<4; i++) Fx3WriteReg32(FX3_GPIF_THREAD_CONFIG + i*4, 0); } static void Fx3GpifConfigureCommon(const uint16_t *functions, uint16_t num_functions, const uint32_t *registers, uint16_t num_registers) { unsigned i; if (functions && num_functions) { if (num_functions > 32) num_functions = 32; for(i=0; istate[0]); Fx3WriteReg32(FX3_GPIF_LEFT_WAVEFORM + pos*16 + 4, left->state[1]); Fx3WriteReg32(FX3_GPIF_LEFT_WAVEFORM + pos*16 + 8, left->state[2]); Fx3WriteReg32(FX3_GPIF_RIGHT_WAVEFORM + pos*16 + 0, right->state[0]); Fx3WriteReg32(FX3_GPIF_RIGHT_WAVEFORM + pos*16 + 4, right->state[1]); Fx3WriteReg32(FX3_GPIF_RIGHT_WAVEFORM + pos*16 + 8, right->state[2]); } } Fx3GpifConfigureCommon(functions, num_functions, ®isters->config, sizeof(*registers)/sizeof(uint32_t)); } void Fx3GpifConfigureCompat(const Fx3GpifWaveformCompat_t *waveforms, const uint8_t *waveform_select, uint16_t num_waveforms, const uint16_t *functions, uint16_t num_functions, const uint32_t *registers, uint16_t num_registers) { unsigned i; if (waveforms && num_waveforms) { for(i=0; ileft[0]); Fx3WriteReg32(FX3_GPIF_LEFT_WAVEFORM + i*16 + 4, w->left[1]); Fx3WriteReg32(FX3_GPIF_LEFT_WAVEFORM + i*16 + 8, w->left[2]); Fx3WriteReg32(FX3_GPIF_RIGHT_WAVEFORM + i*16 + 0, w->right[0]); Fx3WriteReg32(FX3_GPIF_RIGHT_WAVEFORM + i*16 + 4, w->right[1]); Fx3WriteReg32(FX3_GPIF_RIGHT_WAVEFORM + i*16 + 8, w->right[2]); } } Fx3GpifConfigureCommon(functions, num_functions, registers, num_registers); } void Fx3GpifPibStart(uint16_t clock_divisor_x2) { Fx3WriteReg32(FX3_GCTL_PIB_CORE_CLK, (((clock_divisor_x2 >> 1)-1) << FX3_GCTL_PIB_CORE_CLK_DIV_SHIFT) | (3UL << FX3_GCTL_PIB_CORE_CLK_SRC_SHIFT)); if (clock_divisor_x2 & 1) Fx3SetReg32(FX3_GCTL_PIB_CORE_CLK, FX3_GCTL_PIB_CORE_CLK_HALFDIV); Fx3SetReg32(FX3_GCTL_PIB_CORE_CLK, FX3_GCTL_PIB_CORE_CLK_CLK_EN); Fx3WriteReg32(FX3_PIB_POWER, 0); Fx3UtilDelayUs(10); Fx3SetReg32(FX3_PIB_POWER, FX3_PIB_POWER_RESETN); while(!(Fx3ReadReg32(FX3_PIB_POWER) & FX3_PIB_POWER_ACTIVE)) ; Fx3ClearReg32(FX3_PIB_DLL_CTRL, FX3_PIB_DLL_CTRL_ENABLE); Fx3UtilDelayUs(1); Fx3WriteReg32(FX3_PIB_DLL_CTRL, (clock_divisor_x2<11? FX3_PIB_DLL_CTRL_HIGH_FREQ : 0UL) | FX3_PIB_DLL_CTRL_ENABLE); Fx3UtilDelayUs(1); Fx3ClearReg32(FX3_PIB_DLL_CTRL, FX3_PIB_DLL_CTRL_DLL_RESET_N); Fx3UtilDelayUs(1); Fx3SetReg32(FX3_PIB_DLL_CTRL, FX3_PIB_DLL_CTRL_DLL_RESET_N); Fx3UtilDelayUs(1); while(!(Fx3ReadReg32(FX3_PIB_DLL_CTRL) & FX3_PIB_DLL_CTRL_DLL_STAT)) ; Fx3WriteReg32(FX3_VIC_VEC_ADDRESS + (FX3_IRQ_GPIF_CORE<<2), Fx3GpifPibIsr); Fx3WriteReg32(FX3_PIB_INTR, Fx3ReadReg32(FX3_PIB_INTR)); Fx3WriteReg32(FX3_PIB_INTR_MASK, FX3_PIB_INTR_MASK_GPIF_ERR | FX3_PIB_INTR_MASK_GPIF_INTERRUPT); Fx3WriteReg32(FX3_VIC_INT_ENABLE, (1UL << FX3_IRQ_GPIF_CORE)); } void Fx3GpifPibStop(void) { Fx3WriteReg32(FX3_PIB_INTR_MASK, 0UL); Fx3WriteReg32(FX3_VIC_INT_CLEAR, (1UL << FX3_IRQ_GPIF_CORE)); Fx3WriteReg32(FX3_PIB_INTR_MASK, 0UL); Fx3WriteReg32(FX3_PIB_INTR, ~0UL); Fx3WriteReg32(FX3_PIB_POWER, 0UL); Fx3UtilDelayUs(10); Fx3ClearReg32(FX3_GCTL_PIB_CORE_CLK, FX3_GCTL_PIB_CORE_CLK_CLK_EN); } Fx3GpifStat_t Fx3GpifGetStat(uint8_t *current_state) { uint32_t stat = Fx3ReadReg32(FX3_GPIF_WAVEFORM_CTRL_STAT); if (current_state) *current_state = (stat & FX3_GPIF_WAVEFORM_CTRL_STAT_CURRENT_STATE_MASK) >> FX3_GPIF_WAVEFORM_CTRL_STAT_CURRENT_STATE_SHIFT; return (stat & FX3_GPIF_WAVEFORM_CTRL_STAT_GPIF_STAT_MASK) >> FX3_GPIF_WAVEFORM_CTRL_STAT_GPIF_STAT_SHIFT; }