/**
 * displayboard_init.c
 *
 * Initialization of GPIO pins on the board hardware.
 * 
 * Copyright (c) 2022 Bigscreen, Inc.
 */

#include <compiler.h>
#include <board.h>
#include <ioport.h>
#include "displayboard.h"

// Redefine board init here
#if defined(__GNUC__)
void board_init(void) WEAK __attribute__((alias("displayboard_system_board_init")));
#elif defined(__ICCARM__)
void board_init(void);
#  pragma weak board_init=system_board_init
#endif

#define ioport_set_port_peripheral_mode(port, masks, mode) \
do {\
	ioport_set_port_mode(port, masks, mode);\
	ioport_disable_port(port, masks);\
} while (0)

void displayboard_system_board_init(void)
{
	WDT->WDT_MR = WDT_MR_WDDIS;
	
	// Enable PIO clocks
	ioport_init();
	
	// Immediately disable power supplies
	ioport_set_pin_dir(PIN_EN_1V, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_EN_1V, false);
	ioport_set_pin_dir(PIN_EN_VOLEDn, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_EN_VOLEDn, false);
	ioport_set_pin_dir(PIN_EN_VOLEDp, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_EN_VOLEDp, false);
	ioport_set_pin_dir(PIN_EN_1V8, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_EN_1V8, false);
	ioport_set_pin_dir(PIN_AUX_USB_EN, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_AUX_USB_EN, false);

	// Fan control
	ioport_set_pin_mode(PIN_FAN_FREQ, PINMODE_FAN_FREQ);
	ioport_disable_pin(PIN_FAN_FREQ); // note: "disable" just means under peripheral control
	ioport_set_pin_mode(PIN_FAN_PWM, PINMODE_FAN_PWM);
	ioport_disable_pin(PIN_FAN_PWM);
	
	// Aux USB Power Control
	ioport_set_pin_dir(PIN_AUX_USB_EN, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_AUX_USB_EN, false);
	ioport_set_pin_dir(PIN_AUX_USB_FAULT, IOPORT_DIR_INPUT);
	ioport_set_pin_mode(PIN_AUX_USB_FAULT, IOPORT_MODE_PULLUP);
	
	// Debugging UART
	#if defined (CONF_BOARD_UART_CONSOLE)
	/* Configure UART pins */
	ioport_set_port_peripheral_mode(PINS_USART3_PORT, PINS_USART3,
	PINS_USART3_FLAGS);
	#endif

	ioport_set_pin_mode(PIN_UART_TX, PINMODE_UART_TX);
	ioport_disable_pin(PIN_UART_TX);
	ioport_set_pin_mode(PIN_UART_RX, PINMODE_UART_RX);
	ioport_disable_pin(PIN_UART_RX);
	
	// Tracking GPIO
	ioport_set_pin_dir(PIN_TRACK_GPIO1, IOPORT_DIR_INPUT);
	ioport_set_pin_dir(PIN_TRACK_GPIO2, IOPORT_DIR_INPUT);
	
	// Power supply enables
	ioport_set_pin_dir(PIN_EN_1V, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_EN_1V, false);
	ioport_set_pin_dir(PIN_EN_VOLEDn, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_EN_VOLEDn, false);
	ioport_set_pin_dir(PIN_EN_VOLEDp, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_EN_VOLEDp, false);
	ioport_set_pin_dir(PIN_EN_1V8, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_EN_1V8, false);
	
	// PDM mic
	ioport_set_pin_mode(PIN_PDM_DAT, PINMODE_PDM_DAT);
	ioport_disable_pin(PIN_PDM_DAT);
	ioport_set_pin_mode(PIN_PDM_CLK, PINMODE_PDM_CLK);
	ioport_disable_pin(PIN_PDM_CLK);
	
	// USB C PD
	ioport_set_pin_dir(PIN_USBCC_EN, IOPORT_DIR_OUTPUT);
	// ioport_set_pin_mode(PIN_USBCC_EN, IOPORT_MODE_OPEN_DRAIN);
	ioport_set_pin_level(PIN_USBCC_EN, HPD_DISABLED); // Start with HPD disabled
	ioport_set_pin_dir(PIN_USBC_ADC_CC1, IOPORT_DIR_INPUT);
	ioport_set_pin_mode(PIN_USBC_ADC_CC1, 0);
	ioport_set_pin_dir(PIN_USBC_ADC_CC2, IOPORT_DIR_INPUT);
	ioport_set_pin_mode(PIN_USBC_ADC_CC2, 0);
	
	// Prox sensor interrupt
	ioport_set_pin_dir(PIN_EXP_IRQ, IOPORT_DIR_INPUT);
	ioport_set_pin_mode(PIN_EXP_IRQ, IOPORT_MODE_PULLUP);
	
	// DDIC 
	// do not enable pullups - DDIC pins are not all 3.3V tolerant
	// outputs must be open drain (external pullup on board)
	ioport_set_pin_dir(PIN_DDIC_GPIO7, IOPORT_DIR_INPUT);
	ioport_set_pin_dir(PIN_DDIC_GPIO4, IOPORT_DIR_INPUT);
	ioport_set_pin_mode(PIN_DDIC_RST, IOPORT_MODE_OPEN_DRAIN);
	ioport_set_pin_dir(PIN_DDIC_RST, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_DDIC_RST, true);
	ioport_set_pin_dir(PIN_DDIC_HPD, IOPORT_DIR_INPUT);
	
	// Temperature sensor
	ioport_set_pin_dir(PIN_TEMP_SENSE, IOPORT_DIR_INPUT);
	
	// DDIC I2C
	ioport_set_pin_mode(PIN_DDIC_I2C_SCL, PINMODE_DDIC_I2C_SCL);
	ioport_disable_pin(PIN_DDIC_I2C_SCL);
	ioport_set_pin_mode(PIN_DDIC_I2C_SDA, PINMODE_DDIC_I2C_SDA);
	ioport_disable_pin(PIN_DDIC_I2C_SDA);
	
	// USB Hub
	// Take control of PB4 and PB5 from the system controller. Default is PB4 = JTAG TDI, PB5 = TDO/TRACESWO
	MATRIX->CCFG_SYSIO |= (1 << 4) + (1 << 5);
	// Now PB4 (hub interrupt) and PB5 (hub reset) can be controlled
	ioport_set_pin_dir(PIN_USBHUB_INT, IOPORT_DIR_INPUT);
	ioport_set_pin_mode(PIN_USBHUB_INT, IOPORT_MODE_PULLUP);
	ioport_set_pin_dir(PIN_USBHUB_RESET, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_USBHUB_RESET, false); // Keep hub in reset
	ioport_set_pin_dir(PIN_USBHUB_CLKEN, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_USBHUB_CLKEN, true);
	
	// Spare GPIO
	ioport_set_pin_dir(PIN_SPARE, IOPORT_DIR_INPUT);
	ioport_set_pin_mode(PIN_SPARE, IOPORT_MODE_PULLUP);
	
	// I2C
	ioport_set_pin_mode(PIN_HUB_I2C_SCL, PINMODE_HUB_I2C_SCL);
	ioport_disable_pin(PIN_HUB_I2C_SCL);
	ioport_set_pin_mode(PIN_HUB_I2C_SDA, PINMODE_HUB_I2C_SCL);
	ioport_disable_pin(PIN_HUB_I2C_SDA);
	
	// OLED reset
	// output must be open drain (external pullup on board) do not enable internal pullup
	ioport_set_pin_mode(PIN_OLED_RESX, IOPORT_MODE_OPEN_DRAIN);
	ioport_set_pin_dir(PIN_OLED_RESX, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_OLED_RESX, true);
	
	
}