#!/bin/sh -e
#
# Activate WIFI on Variscite DART-MX8M-PLUS/VAR-SOM-MX8M-PLUS
#

# GPIO pin to supply WIFI power on DART-MX8M-PLUS
WIFI_PWR_GPIO_DART="gpiochip1 8"

# GPIO pin to supply WIFI power on VAR-SOM-MX8M-PLUS
WIFI_PWR_GPIO_SOM="gpiochip1 19"

# GPIO pin to enable WIFI module on DART-MX8M-PLUS
WIFI_EN_GPIO_DART="gpiochip1 7"

# GPIO pin to enable WIFI module on VAR-SOM-MX8M-PLUS
WIFI_EN_GPIO_SOM="gpiochip1 8"

# GPIO pin to control routing of UART signals
# to BT module or SOM connectoron DART-MX8M-PLUS
BT_BUF_GPIO_DART="gpiochip1 9"

# GPIO pin to control routing of UART signals
# to BT module or SOM connectoron VAR-SOM-MX8M-PLUS
BT_BUF_GPIO_SOM="gpiochip0 4"

# GPIO pin to enable BT module on DART-MX8M-PLUS
BT_EN_GPIO_DART="gpiochip1 6"

# GPIO pin to enable BT module on VAR-SOM-MX8M-PLUS
BT_EN_GPIO_SOM="gpiochip1 9"

# WIFI MMC host
WIFI_MMC_HOST=30b40000.mmc

# Return true if WIFI interface exists
wifi_interface_exists()
{
	for i in $(seq 1 20); do
		if [ -d /sys/class/net/wlan0 ]; then
			return 0
		else
			sleep 1
		fi
	done

	return 1
}

# Bind WIFI device to MMC controller
wifi_mmc_bind()
{
	if [ -e /sys/bus/platform/drivers/sdhci-esdhc-imx/bind ]; then
		echo ${WIFI_MMC_HOST} > /sys/bus/platform/drivers/sdhci-esdhc-imx/bind
	fi
}

# Unbind WIFI device from MMC controller
wifi_mmc_unbind()
{
	if [ -e /sys/bus/platform/drivers/sdhci-esdhc-imx/${WIFI_MMC_HOST} ]; then
		echo ${WIFI_MMC_HOST} > /sys/bus/platform/drivers/sdhci-esdhc-imx/unbind
	fi
}

# Return true if SOM is VAR-SOM-MX8M-PLUS
som_is_var_som_mx8m_plus()
{
	grep -q VAR-SOM-MX8M-PLUS /sys/devices/soc0/machine
}

# Configure VAR-SOM-MX8M-PLUS WIFI/BT pins
config_pins()
{
	if som_is_var_som_mx8m_plus; then
		WIFI_PWR_GPIO=${WIFI_PWR_GPIO_SOM}
		WIFI_EN_GPIO=${WIFI_EN_GPIO_SOM}
		BT_BUF_GPIO=${BT_BUF_GPIO_SOM}
		BT_EN_GPIO=${BT_EN_GPIO_SOM}
	else
		WIFI_PWR_GPIO=${WIFI_PWR_GPIO_DART}
		WIFI_EN_GPIO=${WIFI_EN_GPIO_DART}
		BT_BUF_GPIO=${BT_BUF_GPIO_DART}
		BT_EN_GPIO=${BT_EN_GPIO_DART}
	fi
}

# Power up WIFI chip
wifi_up()
{
	# Unbind WIFI device from MMC controller
	wifi_mmc_unbind

	# WIFI_PWR up
	gpioset ${WIFI_PWR_GPIO}=1
	usleep 10000

	# WLAN_EN up
	gpioset ${WIFI_EN_GPIO}=1

	# BT_EN up
	gpioset ${BT_EN_GPIO}=1

	# BT_BUF up
	gpioset ${BT_BUF_GPIO}=0

	# Wait at least 150ms
	usleep 200000

	# BT_BUF down
	gpioset ${BT_BUF_GPIO}=1

	# BT_EN down
	gpioset ${BT_EN_GPIO}=0

	# Bind WIFI device to MMC controller
	wifi_mmc_bind

	# Load WIFI driver
	modprobe brcmfmac
}

# Power down WIFI chip
wifi_down()
{
	# Unload WIFI driver
	modprobe -r brcmfmac

	# Unbind WIFI device from MMC controller
	wifi_mmc_unbind

	# Configure WIFI/BT pins
	config_pins

	# WIFI_EN down
	gpioset ${WIFI_EN_GPIO}=0

	# BT_BUF down
	gpioset ${BT_BUF_GPIO}=1

	# BT_EN down
	gpioset ${BT_EN_GPIO}=0
	usleep 10000

	# WIFI_PWR down
	gpioset ${WIFI_PWR_GPIO}=0
}

# Return true if SOM has WIFI module assembled
wifi_is_available()
{
	# Read SOM options EEPROM field
	opt=$(i2cget -f -y 0x0 0x52 0x20)

	# Check WIFI bit in SOM options
	if [ $((opt & 0x1)) -eq 1 ]; then
		return 0
	else
		return 1
	fi
}

# Return true if WIFI should be started
wifi_should_not_be_started()
{
	# Do not start WIFI if it is not available
	if ! wifi_is_available; then
		return 0
	fi

	# Do not start WIFI if it is already started
	[ -d /sys/class/net/wlan0 ] && return 0

	return 1
}

# Return true if WIFI should not be stopped
wifi_should_not_be_stopped()
{
	# Do not stop WIFI if it is not available
	if ! wifi_is_available; then
		return 0
	fi

	return 1
}

# Start WIFI hardware
wifi_start()
{
	# Exit if WIFI should not be started
	wifi_should_not_be_started && exit 0

	# Configure WIFI/BT pins
	config_pins

	# Try starting WIFI hardware
	for i in $(seq 1 3); do
		# Up WIFI
		wifi_up

		# Exit if WIFI interface exists
		wifi_interface_exists && exit 0

		# Down WIFI
		wifi_down

		# Wait enough time for discharge
		sleep 5
	done

	exit 1
}

# Stop WIFI hardware
wifi_stop()
{
	# Exit if WIFI should not be stopped
	wifi_should_not_be_stopped && exit 0

	# Down WIFI
	wifi_down
}

###########################
#  Execution starts here  #
###########################
case $1 in
start)
	wifi_start
	;;
stop)
	wifi_stop
	;;
esac

exit 0
