blob: dc55bde76a0b1be8dd4e4445a724abd251ed08a0 [file] [log] [blame]
/*
* (C) Copyright 2015 Google, Inc.
* All rights reserved.
*
*/
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "common.h"
#include "gpio.h"
#include "../common/io.h"
#define LED_ON_OPTION "on"
#define LED_OFF_OPTION "off"
int enable_gpio_pin_out(int pin, int en) {
uint32_t value;
if (pin < 0 || pin > MAX_GPIO_PIN_NUM) return -1;
if (en < 0 || en > 1) return -1;
read_physical_addr(GPIO_OE, &value);
value &= ~(1 << pin);
value |= en << pin;
write_physical_addr(GPIO_OE, value);
return 0;
}
int is_gpio_pin_out_enabled(int pin) {
uint32_t value;
if (pin < 0 || pin > MAX_GPIO_PIN_NUM) return -1;
read_physical_addr(GPIO_OE, &value);
// 0 - output, 1 - input
if ((value & (1 << pin)) != 0) {
return 0;
} else {
return 1;
}
}
int get_gpio_pin_out_value(int pin) {
uint32_t value;
if (pin < 0 || pin > MAX_GPIO_PIN_NUM) return -1;
read_physical_addr(GPIO_OUT, &value);
return ((value >> pin) & 0x1);
}
int get_gpio_pin_in_value(int pin) {
uint32_t value;
if (pin < 0 || pin > MAX_GPIO_PIN_NUM) return -1;
read_physical_addr(GPIO_IN, &value);
return ((value >> pin) & 0x1);
}
int set_gpio_pin_out_value(int pin, int value) {
if (pin < 0 || pin > MAX_GPIO_PIN_NUM) return -1;
if (value < 0 || value > 1) return -1;
if (value == 0) {
write_physical_addr(GPIO_CLEAR, 1 << pin);
} else {
write_physical_addr(GPIO_SET, 1 << pin);
}
return 0;
}
int get_gpio_mux_value(int pin) {
uint32_t value, reg_addr, addr_offset, byte_offset;
if (pin < 0 || pin > MAX_GPIO_PIN_NUM) return -1;
addr_offset = (pin / GPIO_CNTL_PER_REG) * GPIO_CNTL_PER_REG;
byte_offset = pin - addr_offset;
reg_addr = GPIO_OUT_FUNCTION0 + addr_offset;
read_physical_addr(reg_addr, &value);
return ((value >> (8 * byte_offset)) & 0xFF);
}
int set_gpio_mux_value(int pin, int value) {
uint32_t data, reg_addr, addr_offset, byte_offset;
if (pin < 0 || pin > MAX_GPIO_PIN_NUM) return -1;
if (value < 0 || value > GPIO_CPU_CNTL_MAX_VAL) return -1;
addr_offset = (pin / GPIO_CNTL_PER_REG) * GPIO_CNTL_PER_REG;
byte_offset = pin - addr_offset;
reg_addr = GPIO_OUT_FUNCTION0 + addr_offset;
read_physical_addr(reg_addr, &data);
data &= ~(0xFF << (8 * byte_offset));
data |= value << (8 * byte_offset);
write_physical_addr(reg_addr, data);
return 0;
}
int get_gpio_pin_status(int pin) {
int mux_sel, out_enabled, value;
if (pin < 0 || pin > MAX_GPIO_PIN_NUM) {
printf("%s invalid pin number %d\n", FAIL_TEXT, pin);
return -1;
}
mux_sel = get_gpio_mux_value(pin);
if (mux_sel < 0) {
printf("%s to get MUX select for pin %d\n", FAIL_TEXT, pin);
return -1;
}
out_enabled = is_gpio_pin_out_enabled(pin);
if (out_enabled < 0) {
printf("%s to get pin %d output enable status\n", FAIL_TEXT, pin);
return -1;
}
if (out_enabled == 1) {
value = get_gpio_pin_out_value(pin);
printf("GPIO %d output enabled: value %d mux %d\n", pin, value, mux_sel);
} else {
value = get_gpio_pin_in_value(pin);
printf("GPIO %d input enabled: value %d mux %d\n", pin, value, mux_sel);
}
return 0;
}
int set_gpio_pin(int pin, int value) {
if (pin < 0 || pin > MAX_GPIO_PIN_NUM) {
printf("%s invalid pin number %d (0 to %d)\n", FAIL_TEXT, pin,
MAX_GPIO_PIN_NUM);
return -1;
}
if (value < 0 || value > 1) {
printf("%s invalid pin value %d (0 or 1)\n", FAIL_TEXT, value);
return -1;
}
// Set MUX to CPU control value
if (set_gpio_mux_value(pin, GPIO_CPU_CNTL_VAL) < 0) {
printf("%s to enable pin %d to output\n", FAIL_TEXT, pin);
return -1;
}
if (enable_gpio_pin_out(pin, 0) < 0) {
printf("%s to enable pin %d to output\n", FAIL_TEXT, pin);
return -1;
}
if (set_gpio_pin_out_value(pin, value) < 0) {
printf("%s to set pin %d out register to %d\n", FAIL_TEXT, pin, value);
return -1;
}
printf("GPIO pin %d set to output %d\n", pin, value);
return 0;
}
static void gpio_dump_usage(void) {
printf("gpio_dump\n");
printf("GPIO registerd dump\n");
}
int gpio_dump(int argc, char *argv[]) {
uint32_t oe, in, out, mux0, mux1, mux2, mux3, mux4;
if (argc != 1 || argv == NULL) {
gpio_dump_usage();
return -1;
}
read_physical_addr(GPIO_OE, &oe);
read_physical_addr(GPIO_IN, &in);
read_physical_addr(GPIO_OUT, &out);
read_physical_addr(GPIO_OUT_FUNCTION0, &mux0);
read_physical_addr(GPIO_OUT_FUNCTION1, &mux1);
read_physical_addr(GPIO_OUT_FUNCTION2, &mux2);
read_physical_addr(GPIO_OUT_FUNCTION3, &mux3);
read_physical_addr(GPIO_OUT_FUNCTION4, &mux4);
printf("GPIO OE %08x IN %08X OUT %08X MUX %08X %08X %08X %08X %08X\n", oe, in,
out, mux0, mux1, mux2, mux3, mux4);
return 0;
}
static void gpio_out_usage(void) {
printf("gpio_out <pin (%d-0)> <0|1>\n", MAX_GPIO_PIN_NUM);
printf("Example:\n");
printf("gpio_out 17 1\n");
printf("GPIO pin 17 output 1\n");
}
int gpio_out(int argc, char *argv[]) {
int pin, value;
if (argc != 3) {
gpio_out_usage();
return -1;
}
pin = strtol(argv[1], NULL, 0);
value = strtol(argv[2], NULL, 0);
return set_gpio_pin(pin, value);
}
static void gpio_disable_out_usage(void) {
printf("gpio_disable_out <pin (%d-0)>\n", MAX_GPIO_PIN_NUM);
printf("Example:\n");
printf("gpio_disable_out 27\n");
printf("GPIO pin 27 output disabled\n");
}
int gpio_disable_out(int argc, char *argv[]) {
int pin;
if (argc != 2) {
gpio_disable_out_usage();
return -1;
}
pin = strtol(argv[1], NULL, 0);
if (pin < 0 || pin > MAX_GPIO_PIN_NUM) {
printf("%s invalid pin number %d. Range ( 0 to %d)\n", FAIL_TEXT, pin,
MAX_GPIO_PIN_NUM);
return -1;
}
if (enable_gpio_pin_out(pin, 1) < 0) {
printf("%s disable pin number %d error\n", FAIL_TEXT, pin);
return -1;
}
printf("GPIO pin %d output disabled\n", pin);
return 0;
}
static void gpio_stat_usage(void) {
printf("gpio_stat <pin (%d-0)>\n", MAX_GPIO_PIN_NUM);
printf("Example:\n");
printf("gpio_stat 17\n");
printf("GPIO pin 17 output status\n");
}
int gpio_stat(int argc, char *argv[]) {
int pin;
if (argc != 2) {
gpio_stat_usage();
return -1;
}
pin = strtol(argv[1], NULL, 0);
return get_gpio_pin_status(pin);
}
static void set_red_led_usage(void) {
printf("set_red_led <on/off>\n");
printf("Example:\n");
printf("set_red_led on\n");
printf("Turn on red LED\n");
}
int set_red_led(int argc, char *argv[]) {
if (argc != 2) {
set_red_led_usage();
return -1;
}
if (strcmp(argv[1], LED_ON_OPTION) == 0) {
return set_gpio_pin(GPIO_RED_LED_PIN, 1);
} else if (strcmp(argv[1], LED_OFF_OPTION) == 0) {
return set_gpio_pin(GPIO_RED_LED_PIN, 0);
} else {
set_red_led_usage();
return -1;
}
}
static void set_blue_led_usage(void) {
printf("set_blue_led <on/off>\n");
printf("Example:\n");
printf("set_blue_led on\n");
printf("Turn on blue LED\n");
}
int set_blue_led(int argc, char *argv[]) {
if (argc != 2) {
set_blue_led_usage();
return -1;
}
if (strcmp(argv[1], LED_ON_OPTION) == 0) {
return set_gpio_pin(GPIO_BLUE_LED_PIN, 1);
} else if (strcmp(argv[1], LED_OFF_OPTION) == 0) {
return set_gpio_pin(GPIO_BLUE_LED_PIN, 0);
} else {
set_blue_led_usage();
return -1;
}
}
static void set_led_dim_usage(void) {
printf("set_led_dim <on/off>\n");
printf("Example:\n");
printf("set_led_dim on\n");
printf("dim LED\n");
}
int set_led_dim(int argc, char *argv[]) {
if (argc != 2) {
set_led_dim_usage();
return -1;
}
if (strcmp(argv[1], LED_ON_OPTION) == 0) {
return set_gpio_pin(GPIO_DIM_LED_PIN, 1);
} else if (strcmp(argv[1], LED_OFF_OPTION) == 0) {
return set_gpio_pin(GPIO_DIM_LED_PIN, 0);
} else {
set_led_dim_usage();
return -1;
}
}
static void set_poe_usage(void) {
printf("set_poe <on/off>\n");
printf("Example:\n");
printf("set_poe on\n");
printf("Turn on PoE\n");
}
int set_poe(int argc, char *argv[]) {
if (argc != 2) {
set_poe_usage();
return -1;
}
if (strcmp(argv[1], LED_ON_OPTION) == 0) {
return set_gpio_pin(GPIO_POE_PIN, 0);
} else if (strcmp(argv[1], LED_OFF_OPTION) == 0) {
return set_gpio_pin(GPIO_POE_PIN, 1);
} else {
set_poe_usage();
return -1;
}
}
static void check_reset_button_usage(void) {
printf("check_reset_button\n");
printf("Example:\n");
printf("check_reset_button\n");
printf("Check if the external reset button on or off\n");
}
int check_reset_button(int argc, char *argv[]) {
if (argc != 1 || argv == NULL) {
check_reset_button_usage();
return -1;
}
// Reset button is active low
if (get_gpio_pin_in_value(GPIO_RESET_BUTTON_PIN) > 0) {
printf("Reset button is off\n");
} else {
printf("Reset button is on\n");
}
return 0;
}
static void cpu_reset_usage(void) {
printf("cpu_reset\n");
printf("Example:\n");
printf("cpu_reset\n");
printf("Perform CPU cold reset\n");
}
int cpu_reset(int argc, char *argv[]) {
if (argc != 1 || argv == NULL) {
cpu_reset_usage();
return -1;
}
printf("CPU cold reset ...\n");
sleep(1);
write_physical_addr(RST_RESET, 1 << CPU_COLD_RESET_BIT);
return 0;
}