jacking/bsp/gpif.c

221 lines
7.9 KiB
C
Raw Permalink Normal View History

2022-01-21 04:15:36 +00:00
/*
* 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 <bsp/gpif.h>
#include <bsp/regaccess.h>
#include <bsp/irq.h>
#include <bsp/util.h>
#include <bsp/uart.h>
#include <rdb/gctl.h>
#include <rdb/pib.h>
#include <rdb/vic.h>
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; i<num_functions; i++) {
Fx3WriteReg32(FX3_GPIF_FUNCTION + i*4, functions[i]);
}
}
if (registers && num_registers) {
for(i=num_registers; i--; )
Fx3WriteReg32(FX3_GPIF_CONFIG + i*4, registers[i]);
}
}
void Fx3GpifConfigure(const Fx3GpifWaveform_t *waveforms,
uint16_t num_waveforms,
const uint16_t *functions, uint16_t num_functions,
const Fx3GpifRegisters_t *registers)
{
unsigned i;
if (waveforms && num_waveforms) {
for(i=0; i<num_waveforms; i++) {
const Fx3GpifWaveform_t *left = &waveforms[waveforms[i].left];
const Fx3GpifWaveform_t *right = &waveforms[waveforms[i].right];
unsigned pos = waveforms[i].state[0] & FX3_GPIF_LEFT_WAVEFORM_NEXT_STATE_MASK;
Fx3WriteReg32(FX3_GPIF_LEFT_WAVEFORM + pos*16 + 0, left->state[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, &registers->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; i<num_waveforms; i++) {
const Fx3GpifWaveformCompat_t *w =
&waveforms[waveform_select? waveform_select[i]:i];
Fx3WriteReg32(FX3_GPIF_LEFT_WAVEFORM + i*16 + 0, w->left[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;
}