diff --git a/api/mraa/types.h b/api/mraa/types.h index 00fca5e..8c9a306 100644 --- a/api/mraa/types.h +++ b/api/mraa/types.h @@ -68,6 +68,7 @@ typedef enum { MRAA_ADLINK_LEC_AL_AI = 23, /**< Adlink LEC-AL*/ MRAA_UPXTREME = 24, /**< The UPXTREME Board */ MRAA_INTEL_ILK = 25, /**< Intel Learning Kit */ + MRAA_SIEMENS_IOT2050 = 26, /**< Siemens IOT2050 board */ // USB platform extenders start at 256 MRAA_FTDI_FT4222 = 256, /**< FTDI FT4222 USB to i2c bridge */ diff --git a/api/mraa/types.hpp b/api/mraa/types.hpp index 3429982..6958d4f 100644 --- a/api/mraa/types.hpp +++ b/api/mraa/types.hpp @@ -61,6 +61,7 @@ typedef enum { MTK_OMEGA2 = 18, /**< MT7688 based Onion Omega2 board */ IEI_TANK = 19, /**< IEI Tank System*/ INTEL_UPXTREME = 24, /**< The UPXTREME Board */ + SIEMENS_IOT2050 = 26, /**< Siemens IOT2050 board */ FTDI_FT4222 = 256, /**< FTDI FT4222 USB to i2c bridge */ diff --git a/include/arm/siemens/iot2050.h b/include/arm/siemens/iot2050.h new file mode 100644 index 0000000..0acf0a0 --- /dev/null +++ b/include/arm/siemens/iot2050.h @@ -0,0 +1,40 @@ +/* + * Author: Le Jin + * Copyright (c) Siemens AG, 2019 + * + * 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. + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mraa_internal.h" + +#define PLATFORM_NAME "SIMATIC IOT2050" +#define MRAA_IOT2050_PINCOUNT (20) + +mraa_board_t * + mraa_siemens_iot2050(); + +#ifdef __cplusplus +} +#endif diff --git a/include/arm/siemens/platform.h b/include/arm/siemens/platform.h new file mode 100644 index 0000000..6595f74 --- /dev/null +++ b/include/arm/siemens/platform.h @@ -0,0 +1,97 @@ +/* + * Author: Le Jin + * Copyright (c) Siemens AG, 2019 + * + * 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. + */ +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ +#ifdef __cplusplus +extern "C" { +#endif +#include +#include +#include +typedef struct { + bool (*init)(void); + void (*deinit)(void); + void (*select_func)(uint8_t group, uint16_t pinIndex, uint8_t func); + void (*select_input)(uint8_t group, uint16_t pinIndex); + void (*select_output)(uint8_t group, uint16_t pinIndex); + void (*select_inout)(uint8_t group, uint16_t pinIndex); + void (*select_hiz)(uint8_t group, uint16_t pinIndex); + void (*select_pull_up)(uint8_t group, uint16_t pinIndex); + void (*select_pull_down)(uint8_t group, uint16_t pinIndex); + void (*select_pull_disable)(uint8_t group, uint16_t pinIndex); + uint32_t (*get_raw_reg_value)(uint8_t group, uint16_t pinIndex); + void (*set_raw_reg_value)(uint8_t group, uint16_t pinIndex, uint32_t value); + void (*dump_info)(uint8_t group, uint16_t pinIndex); +} pin_mux_ops_t; + +typedef struct{ + bool initialized; + pin_mux_ops_t ops; +} pin_mux_interface_t; + +#define VOID_INTERFACE_CALL(instance, function) \ +do {\ + if((instance) && ((pin_mux_interface_t *)instance)->ops.function) \ + ((pin_mux_interface_t *)instance)->ops.function(); \ +}while(0) + +#define VOID_INTERFACE_CALL_WITH_ARGS(instance, function, ...) \ +do {\ + if((instance) && ((pin_mux_interface_t *)instance)->ops.function) \ + ((pin_mux_interface_t *)instance)->ops.function(__VA_ARGS__); \ +}while(0) + +#define INTERFACE_CALL_WITH_ARGS(instance, retType, defaultRetValue, function, ...) \ +( \ + { \ + retType ret = defaultRetValue; \ + if((instance) && ((pin_mux_interface_t *)instance)->ops.function) \ + ret = ((pin_mux_interface_t *)instance)->ops.function(__VA_ARGS__); \ + ret; \ + } \ +) + +#ifdef _DEBUG +#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUG_PRINT(...) do{}while(0) +#endif + +void *platfrom_pinmux_get_instance(char *platform); +#define platform_pinmux_release_instance(instance) VOID_INTERFACE_CALL(instance, deinit) +#define platform_pinmux_select_func(instance, ...) VOID_INTERFACE_CALL_WITH_ARGS(instance, select_func, __VA_ARGS__) +#define platform_pinmux_select_input(instance, ...) VOID_INTERFACE_CALL_WITH_ARGS(instance, select_input, __VA_ARGS__) +#define platform_pinmux_select_output(instance, ...) VOID_INTERFACE_CALL_WITH_ARGS(instance, select_output, __VA_ARGS__) +#define platform_pinmux_select_inout(instance, ...) VOID_INTERFACE_CALL_WITH_ARGS(instance, select_inout, __VA_ARGS__) +#define platform_pinmux_select_hiz(instance, ...) VOID_INTERFACE_CALL_WITH_ARGS(instance, select_hiz, __VA_ARGS__) +#define platform_pinmux_select_pull_up(instance, ...) VOID_INTERFACE_CALL_WITH_ARGS(instance, select_pull_up, __VA_ARGS__) +#define platform_pinmux_select_pull_down(instance, ...) VOID_INTERFACE_CALL_WITH_ARGS(instance, select_pull_down, __VA_ARGS__) +#define platform_pinmux_select_pull_disable(instance, ...) VOID_INTERFACE_CALL_WITH_ARGS(instance, select_pull_disable, __VA_ARGS__) +#define platform_pinmux_get_raw_reg_value(instance, ...) INTERFACE_CALL_WITH_ARGS(instance, uint32_t, -1, get_raw_reg_value, __VA_ARGS__) +#define platform_pinmux_set_raw_reg_value(instance, ...) VOID_INTERFACE_CALL_WITH_ARGS(instance, set_raw_reg_value, __VA_ARGS__) +#define platform_pinmux_dump_info(instance, ...) VOID_INTERFACE_CALL_WITH_ARGS(instance, dump_info, __VA_ARGS__) +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/arm/siemens/platform_iot2050.h b/include/arm/siemens/platform_iot2050.h new file mode 100644 index 0000000..e677eb1 --- /dev/null +++ b/include/arm/siemens/platform_iot2050.h @@ -0,0 +1,34 @@ +/* + * Author: Le Jin + * Copyright (c) Siemens AG, 2019 + * + * 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. + */ +#ifndef _PLATFORM_IOT2050_H_ +#define _PLATFORM_IOT2050_H_ +#ifdef __cplusplus +extern "C" { +#endif +#include "arm/siemens/platform.h" +pin_mux_interface_t *iot2050_pinmux_get_instance(void); +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aa983f4..8146eb6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -109,6 +109,9 @@ set (mraa_LIB_ARM_SRCS_NOAUTO ${PROJECT_SOURCE_DIR}/src/arm/de_nano_soc.c ${PROJECT_SOURCE_DIR}/src/arm/rockpi4.c ${PROJECT_SOURCE_DIR}/src/arm/adlink_ipi.c + ${PROJECT_SOURCE_DIR}/src/arm/siemens/iot2050.c + ${PROJECT_SOURCE_DIR}/src/arm/siemens/platform.c + ${PROJECT_SOURCE_DIR}/src/arm/siemens/platform_iot2050.c ) set (mraa_LIB_MIPS_SRCS_NOAUTO diff --git a/src/arm/arm.c b/src/arm/arm.c index df88e7e..0a44d0f 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -17,6 +17,7 @@ #include "arm/phyboard.h" #include "arm/raspberry_pi.h" #include "arm/adlink_ipi.h" +#include "arm/siemens/iot2050.h" #include "mraa_internal.h" @@ -98,6 +99,8 @@ mraa_arm_platform() platform_type = MRAA_RASPBERRY_PI; else if (mraa_file_contains("/proc/device-tree/model", "ADLINK ARM, LEC-PX30")) platform_type = MRAA_ADLINK_IPI; + else if (mraa_file_contains("/proc/device-tree/model", "SIMATIC IOT2050")) + platform_type = MRAA_SIEMENS_IOT2050; } switch (platform_type) { @@ -124,6 +127,8 @@ mraa_arm_platform() break; case MRAA_ADLINK_IPI: plat = mraa_adlink_ipi(); + case MRAA_SIEMENS_IOT2050: + plat = mraa_siemens_iot2050(); break; default: plat = NULL; diff --git a/src/arm/siemens/iot2050.c b/src/arm/siemens/iot2050.c new file mode 100644 index 0000000..2f27475 --- /dev/null +++ b/src/arm/siemens/iot2050.c @@ -0,0 +1,1237 @@ +/* + * Author: Le Jin + * Copyright (c) Siemens AG, 2019 + * + * 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 "common.h" +#include "gpio/gpio_chardev.h" +#include "arm/siemens/iot2050.h" +#include "arm/siemens/platform.h" + +#define PINMUX_GROUP_MAIN (0) +#define PINMUX_GROUP_WAKUP (1) + +typedef struct { + uint8_t group; + uint16_t index; + uint16_t pinmap; + int8_t mode[MAX_MUX_REGISTER_MODE]; +}regmux_info_t; + +static void *pinmux_instance = NULL; +static regmux_info_t pinmux_info[MRAA_IOT2050_PINCOUNT]; +static mraa_gpio_context output_en_pins[MRAA_IOT2050_PINCOUNT]; +static int pull_en_pins[MRAA_IOT2050_PINCOUNT]; + +static inline int +iot2050_locate_phy_pin_by_name(mraa_board_t *board, char *pin_name) +{ + int i; + + if(!pin_name) + return -1; + for(i=0; iphy_pin_count; i++) { + if(!strncmp(board->pins[i].name, pin_name, MRAA_PIN_NAME_SIZE)) { + return i; + } + } + return -1; +} + +static inline regmux_info_t* +iot2050_get_regmux_by_pinmap(int pinmap) +{ + int i; + + for(i=0; i MRAA_IOT2050_PINCOUNT)) + return MRAA_SUCCESS; + if((mode < 0) || (mode >= MAX_MUX_REGISTER_MODE)) { + return MRAA_ERROR_FEATURE_NOT_SUPPORTED; + } + if(mode == MUX_REGISTER_MODE_AIO) { + return MRAA_SUCCESS; + } + mux_mode = info->mode[mode]; + if(mux_mode < 0) { + return MRAA_ERROR_FEATURE_NOT_SUPPORTED; + } + syslog(LOG_DEBUG, "REGMUX[phy_pin %d] group %d index %d mode %d\n", phy_pin, info->group, info->index, mux_mode); + + platform_pinmux_select_func(pinmux_instance, info->group, info->index, mux_mode); + /* Configure as input and output for default */ + platform_pinmux_select_inout(pinmux_instance, info->group, info->index); + return MRAA_SUCCESS; +} + +static mraa_result_t +iot2050_gpio_dir_pre(mraa_gpio_context dev, mraa_gpio_dir_t dir) +{ + int pin = dev->phy_pin; + + if(pin >= 0) { + if(plat->pins[pin].gpio.complex_cap.complex_pin != 1) { + return MRAA_SUCCESS; + } + if(plat->pins[pin].gpio.complex_cap.output_en == 1) { + if(output_en_pins[pin] == NULL) { + output_en_pins[pin] = mraa_gpio_init_raw(plat->pins[pin].gpio.output_enable); + if(output_en_pins[pin]) { + if(mraa_gpio_dir(output_en_pins[pin], MRAA_GPIO_OUT) != MRAA_SUCCESS) { + mraa_gpio_close(output_en_pins[pin]); + output_en_pins[pin] = NULL; + goto failed; + } + } else { + goto failed; + } + } + if(dir == MRAA_GPIO_IN) { + syslog(LOG_DEBUG, "GPIODIR[phy_pin %d] gpio set out en %d to %d\n", pin, plat->pins[pin].gpio.output_enable, !plat->pins[pin].gpio.complex_cap.output_en_high); + if(mraa_gpio_write(output_en_pins[pin], !plat->pins[pin].gpio.complex_cap.output_en_high) != MRAA_SUCCESS) { + goto failed; + } + } else { + syslog(LOG_DEBUG, "GPIODIR[phy_pin %d] gpio set out en %d to %d\n", pin, plat->pins[pin].gpio.output_enable, plat->pins[pin].gpio.complex_cap.output_en_high); + if(mraa_gpio_write(output_en_pins[pin], plat->pins[pin].gpio.complex_cap.output_en_high) != MRAA_SUCCESS) { + goto failed; + } + } + } + } + return MRAA_SUCCESS; +failed: + syslog(LOG_ERR, "iot2050: Error setting gpio direction"); + return MRAA_ERROR_INVALID_RESOURCE; +} + +static mraa_result_t +iot2050_gpio_mode_replace(mraa_gpio_context dev, mraa_gpio_mode_t mode) +{ + regmux_info_t *info; + mraa_gpio_context pull_en_pin; + mraa_result_t ret = MRAA_SUCCESS; + + /* Only support mode change on interface pins */ + if(dev->phy_pin == -1) { + ret = MRAA_ERROR_INVALID_RESOURCE; + goto failed; + } + info = iot2050_get_regmux_by_pinmap(dev->pin); + pull_en_pin = mraa_gpio_init_raw(pull_en_pins[dev->phy_pin]); + if(pull_en_pin == NULL) { + ret = MRAA_ERROR_INVALID_RESOURCE; + goto failed; + } + switch(mode) { + case MRAA_GPIO_PULLUP: + if(mraa_gpio_dir(pull_en_pin, MRAA_GPIO_OUT_HIGH) != MRAA_SUCCESS) { + ret = MRAA_ERROR_INVALID_RESOURCE; + goto failed; + } + if(info) { + platform_pinmux_select_pull_up(pinmux_instance, info->group, info->index); + } + break; + case MRAA_GPIO_PULLDOWN: + if(mraa_gpio_dir(pull_en_pin, MRAA_GPIO_OUT_LOW) != MRAA_SUCCESS) { + ret = MRAA_ERROR_INVALID_RESOURCE; + goto failed; + } + if(info) { + platform_pinmux_select_pull_down(pinmux_instance, info->group, info->index); + } + break; + case MRAA_GPIO_HIZ: + case MRAA_GPIO_STRONG: + if(mraa_gpio_dir(pull_en_pin, MRAA_GPIO_IN) != MRAA_SUCCESS) { + ret = MRAA_ERROR_INVALID_RESOURCE; + goto failed; + } + if(info) { + platform_pinmux_select_pull_disable(pinmux_instance, info->group, info->index); + } + break; + case MRAA_GPIOD_ACTIVE_LOW: + case MRAA_GPIOD_OPEN_DRAIN: + case MRAA_GPIOD_OPEN_SOURCE: + default: + ret = MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; + goto failed; + } + mraa_gpio_close(pull_en_pin); + return ret; +failed: + syslog(LOG_ERR, "iot2050: Error setting gpio mode"); + if(pull_en_pin) { + mraa_gpio_close(pull_en_pin); + } + return ret; +} + +static inline void +iot2050_setup_pins(mraa_board_t *board, int pin_index, char *pin_name, mraa_pincapabilities_t cap, regmux_info_t mux_info) +{ + strncpy(board->pins[pin_index].name, pin_name, MRAA_PIN_NAME_SIZE); + board->pins[pin_index].capabilities = cap; + pinmux_info[pin_index] = mux_info; +} + +static inline void +iot2050_pin_add_gpio(mraa_board_t *board, int pin_index, int chip, int line, + int output_en_pin, int pull_en_pin, mraa_mux_t *pin_mux, int num_pinmux) +{ + int i; + + mraa_pininfo_t *pininfo = &(board->pins[pin_index]); + /*for sysfs*/ + pininfo->gpio.pinmap = pinmux_info[pin_index].pinmap; + pininfo->gpio.mux_total = 0; + /*for gpio chardev*/ + pininfo->gpio.gpio_chip = chip; + pininfo->gpio.gpio_line = line; + for(i=0; igpio.mux[i] = pin_mux[i]; + } + pininfo->gpio.mux_total = num_pinmux; + /*output enable pin*/ + if(output_en_pin != -1) + { + pininfo->gpio.complex_cap = (mraa_pin_cap_complex_t){ 1, 1, 1, 0, 0 }; + pininfo->gpio.output_enable = output_en_pin; + pininfo->gpio.complex_cap.output_en_high = 1; + } + /*pull enabled pin*/ + pull_en_pins[pin_index] = pull_en_pin; + board->gpio_count++; +} + +static inline void +iot2050_pin_add_aio(mraa_board_t *board, int pin_index, int channel, mraa_mux_t *pin_mux, int num_pinmux) +{ + int i; + + mraa_pininfo_t *pininfo = &(board->pins[pin_index]); + pininfo->aio.pinmap = channel; + for(i=0; iaio.mux[i] = pin_mux[i]; + } + pininfo->aio.mux_total = num_pinmux; + board->aio_dev[channel].pin = pin_index; + board->aio_count++; +} + +static inline void +iot2050_pin_add_uart(mraa_board_t *board, int pin_index, int parent_id, mraa_mux_t *pin_mux, int num_pinmux) +{ + int i; + + mraa_pininfo_t *pininfo = &(board->pins[pin_index]); + pininfo->uart.parent_id = parent_id; + for(i=0; iuart.mux[i] = pin_mux[i]; + } + pininfo->uart.mux_total = num_pinmux; +} + +static inline void +iot2050_pin_add_i2c(mraa_board_t *board, int pin_index, int parent_id, mraa_mux_t *pin_mux, int num_pinmux) +{ + int i; + + mraa_pininfo_t *pininfo = &(board->pins[pin_index]); + pininfo->i2c.parent_id = parent_id; + for(i=0; ii2c.mux[i] = pin_mux[i]; + } + pininfo->i2c.mux_total = num_pinmux; +} + +static inline void +iot2050_pin_add_spi(mraa_board_t *board, int pin_index, int parent_id, mraa_mux_t *pin_mux, int num_pinmux) +{ + int i; + + mraa_pininfo_t *pininfo = &(board->pins[pin_index]); + pininfo->spi.parent_id = parent_id; + for(i=0; ispi.mux[i] = pin_mux[i]; + } + pininfo->spi.mux_total = num_pinmux; +} + +static inline void +iot2050_pin_add_pwm(mraa_board_t *board, int pin_index, int parent_id, int pinmap, mraa_mux_t *pin_mux, int num_pinmux) +{ + int i; + + mraa_pininfo_t *pininfo = &(board->pins[pin_index]); + pininfo->pwm.parent_id = parent_id; + pininfo->pwm.pinmap = pinmap; + for(i=0; ipwm.mux[i] = pin_mux[i]; + } + pininfo->pwm.mux_total = num_pinmux; +} + + +static inline void +iot2050_setup_uart(mraa_board_t *board, char *name, char *path, char *rx_pin_name, char *tx_pin_name, char *cts_pin_name, char *rts_pin_name) +{ + board->uart_dev[board->uart_dev_count].name = name; + board->uart_dev[board->uart_dev_count].device_path = path; + board->uart_dev[board->uart_dev_count].tx = iot2050_locate_phy_pin_by_name(board, tx_pin_name); + board->uart_dev[board->uart_dev_count].rx = iot2050_locate_phy_pin_by_name(board, rx_pin_name); + board->uart_dev[board->uart_dev_count].rts = iot2050_locate_phy_pin_by_name(board, rts_pin_name); + board->uart_dev[board->uart_dev_count].cts = iot2050_locate_phy_pin_by_name(board, cts_pin_name); + board->uart_dev_count++; +} + +static inline void +iot2050_setup_i2c(mraa_board_t *board, char *name, int bus_id, char *sda_pin_name, char *scl_pin_name) +{ + board->i2c_bus[board->i2c_bus_count].name = name; + board->i2c_bus[board->i2c_bus_count].bus_id = bus_id; + board->i2c_bus[board->i2c_bus_count].sda = iot2050_locate_phy_pin_by_name(board, sda_pin_name); + board->i2c_bus[board->i2c_bus_count].scl = iot2050_locate_phy_pin_by_name(board, scl_pin_name); + board->i2c_bus_count++; +} + +static inline void +iot2050_setup_spi(mraa_board_t *board, char *name, int bus_id, int cs_id, + char *sclk_pin_name, char *mosi_pin_name, + char *miso_pin_name, char *cs_pin_name) +{ + board->spi_bus[board->spi_bus_count].name = name; + board->spi_bus[board->spi_bus_count].bus_id = bus_id; + board->spi_bus[board->spi_bus_count].slave_s = cs_id; + board->spi_bus[board->spi_bus_count].sclk = iot2050_locate_phy_pin_by_name(board, sclk_pin_name); + board->spi_bus[board->spi_bus_count].mosi = iot2050_locate_phy_pin_by_name(board, mosi_pin_name); + board->spi_bus[board->spi_bus_count].miso = iot2050_locate_phy_pin_by_name(board, miso_pin_name); + board->spi_bus[board->spi_bus_count].cs = iot2050_locate_phy_pin_by_name(board, cs_pin_name); + board->spi_bus_count++; +} + +static inline void +iot2050_setup_pwm(mraa_board_t *board, char *name) +{ + board->pwm_dev[board->pwm_dev_count].name = name; + board->pwm_dev_count++; +} + +static inline void +iot2050_setup_led(mraa_board_t *board, char *name) +{ + board->led_dev[board->led_dev_count].name = name; + board->led_dev_count++; +} + +mraa_board_t* +mraa_siemens_iot2050() +{ + mraa_board_t* b = (mraa_board_t*) calloc(1, sizeof(mraa_board_t)); + mraa_mux_t mux_info[6]; + int pin_index = 0; + unsigned main_gpio0_chip, main_gpio0_base; + unsigned wkup_gpio0_chip, wkup_gpio0_base; + unsigned d4200_gpio_chip, d4200_gpio_base; + unsigned d4201_gpio_chip, d4201_gpio_base; + unsigned d4202_gpio_chip, d4202_gpio_base; + unsigned line_offset; + int res; + + if (mraa_find_gpio_line_by_name("main_gpio0-base", &main_gpio0_chip, &line_offset) < 0 || line_offset != 0) { + goto error; + } + res = mraa_get_chip_base_by_number(main_gpio0_chip); + if (res < 0) { + goto error; + } + main_gpio0_base = res; + + if (mraa_find_gpio_line_by_name("wkup_gpio0-base", &wkup_gpio0_chip, &line_offset) < 0 || line_offset != 0) { + goto error; + } + res = mraa_get_chip_base_by_number(wkup_gpio0_chip); + if (res < 0) { + goto error; + } + wkup_gpio0_base = res; + + /* A0-pull is line 0 in D4200 */ + if (mraa_find_gpio_line_by_name("A0-pull", &d4200_gpio_chip, &line_offset) < 0 || line_offset != 0) { + goto error; + } + res = mraa_get_chip_base_by_number(d4200_gpio_chip); + if (res < 0) { + goto error; + } + d4200_gpio_base = res; + + /* IO0-direction is line 0 in D4201 */ + if (mraa_find_gpio_line_by_name("IO0-direction", &d4201_gpio_chip, &line_offset) < 0 || line_offset != 0) { + goto error; + } + res = mraa_get_chip_base_by_number(d4201_gpio_chip); + if (res < 0) { + goto error; + } + d4201_gpio_base = res; + + /* IO0-pull is line 0 in D4202 */ + if (mraa_find_gpio_line_by_name("IO0-pull", &d4202_gpio_chip, &line_offset) < 0 || line_offset != 0) { + goto error; + } + res = mraa_get_chip_base_by_number(d4202_gpio_chip); + if (res < 0) { + goto error; + } + d4202_gpio_base = res; + + if(b == NULL) { + return NULL; + } + memset(output_en_pins, 0, sizeof(mraa_gpio_context) * MRAA_IOT2050_PINCOUNT); + b->platform_name = PLATFORM_NAME; + b->phy_pin_count = MRAA_IOT2050_PINCOUNT; + b->chardev_capable = 0; + b->adc_raw = 12; + b->adc_supported = 12; + b->pwm_default_period = 1000; /*us*/ + b->pwm_max_period = 939509; + b->pwm_min_period = 1; + b->aio_non_seq = 1; + b->adv_func = (mraa_adv_func_t*) calloc(1, sizeof(mraa_adv_func_t)); + if(b->adv_func == NULL) { + goto error; + } + b->adv_func->gpio_dir_pre = &iot2050_gpio_dir_pre; + b->adv_func->gpio_mode_replace = &iot2050_gpio_mode_replace; + b->adv_func->mux_init_reg = &iot2050_mux_init_reg; + b->pins = (mraa_pininfo_t*) calloc(MRAA_IOT2050_PINCOUNT, sizeof(mraa_pininfo_t)); + if(b->pins == NULL) { + free(b->adv_func); + goto error; + } + pinmux_instance = platfrom_pinmux_get_instance("iot2050"); + /* IO */ + iot2050_setup_pins(b, pin_index, "IO0", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 1}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 17, + wkup_gpio0_base+29, + { + 7, /*GPIO*/ + 4, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + -1 /*PWM*/ + } + }); + + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 29, d4201_gpio_base+0, d4202_gpio_base+0, NULL, 0); + mux_info[0].pin = d4201_gpio_base+0; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_LOW; + mux_info[1].pin = d4202_gpio_base+0; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_uart(b, pin_index, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO1", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 1}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 18, + wkup_gpio0_base+30, + { + 7, /*GPIO*/ + 4, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + -1 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 30, d4201_gpio_base+1, d4202_gpio_base+1, NULL, 0); + mux_info[0].pin = d4201_gpio_base+1; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+1; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_uart(b, pin_index, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO2", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 1}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 19, + wkup_gpio0_base+31, + { + 7, /*GPIO*/ + 4, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + -1 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 31, d4201_gpio_base+2, d4202_gpio_base+2, NULL, 0); + mux_info[0].pin = d4201_gpio_base+2; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_LOW; + mux_info[1].pin = d4202_gpio_base+2; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_uart(b, pin_index, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO3", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 1}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 21, + wkup_gpio0_base+33, + { + 7, /*GPIO*/ + 4, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + -1 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 33, d4201_gpio_base+3, d4202_gpio_base+3, NULL, 0); + mux_info[0].pin = d4201_gpio_base+3; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+3; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_uart(b, pin_index, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO4", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 1, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_MAIN, + 33, + main_gpio0_base+33, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + 5 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, main_gpio0_chip, 33, d4201_gpio_base+4, d4202_gpio_base+4, NULL, 0); + mux_info[0].pin = d4201_gpio_base+4; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+4; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_pwm(b, pin_index, 0, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO5", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 1, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_MAIN, + 35, + main_gpio0_base+35, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + 5 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, main_gpio0_chip, 35, d4201_gpio_base+5, d4202_gpio_base+5, NULL, 0); + mux_info[0].pin = d4201_gpio_base+5; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+5; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_pwm(b, pin_index, 2, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO6", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 1, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_MAIN, + 38, + main_gpio0_base+38, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + 5 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, main_gpio0_chip, 38, d4201_gpio_base+6, d4202_gpio_base+6, NULL, 0); + mux_info[0].pin = d4201_gpio_base+6; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+6; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_pwm(b, pin_index, 4, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO7", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 1, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_MAIN, + 43, + main_gpio0_base+43, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + 5 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, main_gpio0_chip, 43, d4201_gpio_base+7, d4202_gpio_base+7, NULL, 0); + mux_info[0].pin = d4201_gpio_base+7; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+7; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_pwm(b, pin_index, 6, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO8", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 1, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_MAIN, + 48, + main_gpio0_base+48, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + 5 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, main_gpio0_chip, 48, d4201_gpio_base+8, d4202_gpio_base+8, NULL, 0); + mux_info[0].pin = d4201_gpio_base+8; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+8; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_pwm(b, pin_index, 8, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO9", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 1, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_MAIN, + 51, + main_gpio0_base+51, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + 5 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, main_gpio0_chip, 51, d4201_gpio_base+9, d4202_gpio_base+9, NULL, 0); + mux_info[0].pin = d4201_gpio_base+9; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+9; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_pwm(b, pin_index, 10, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO10", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 1, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 39, + wkup_gpio0_base+51, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + 0, /*SPI*/ + -1 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 51, d4201_gpio_base+10, d4202_gpio_base+10, NULL, 0); + mux_info[0].pin = d4201_gpio_base+10; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+10; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_spi(b, pin_index, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO11", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 1, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 37, + wkup_gpio0_base+49, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + 0, /*SPI*/ + -1 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 49, d4201_gpio_base+11, d4202_gpio_base+11, NULL, 0); + mux_info[0].pin = d4201_gpio_base+11; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+11; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_spi(b, pin_index, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO12", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 1, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 38, + wkup_gpio0_base+50, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + 0, /*SPI*/ + -1 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 50, d4201_gpio_base+12, d4202_gpio_base+12, NULL, 0); + mux_info[0].pin = d4201_gpio_base+12; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_LOW; + mux_info[1].pin = d4202_gpio_base+12; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_spi(b, pin_index, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "IO13", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 1, /*spi*/ + 0, /*i2c*/ + 0, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 36, + wkup_gpio0_base+48, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + 0, /*SPI*/ + -1 /*PWM*/ + } + }); + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 48, d4201_gpio_base+13, d4202_gpio_base+13, NULL, 0); + mux_info[0].pin = d4201_gpio_base+13; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_HIGH; + mux_info[1].pin = d4202_gpio_base+13; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + iot2050_pin_add_spi(b, pin_index, 0, mux_info, 2); + pin_index++; + + iot2050_setup_pins(b, pin_index, "A0", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 1, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 33, + wkup_gpio0_base+45, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + -1 /*PWM*/ + } + }); + mux_info[0].pin = d4200_gpio_base+8; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_LOW; + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 45, wkup_gpio0_base+38, d4200_gpio_base+0, mux_info, 1); + // D/A switch + mux_info[0].pin = d4200_gpio_base+8; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_IN; + // muxed GPIO as input + mux_info[1].pin = wkup_gpio0_base+45; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + // output enable as input + mux_info[2].pin = wkup_gpio0_base+38; + mux_info[2].pincmd = PINCMD_SET_DIRECTION; + mux_info[2].value = MRAA_GPIO_OUT_LOW; + // pull enable as input + mux_info[3].pin = d4200_gpio_base+0; + mux_info[3].pincmd = PINCMD_SET_DIRECTION; + mux_info[3].value = MRAA_GPIO_IN; + iot2050_pin_add_aio(b, pin_index, 0, mux_info, 4); + pin_index++; + + iot2050_setup_pins(b, pin_index, "A1", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 1, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 32, + wkup_gpio0_base+44, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + -1 /*PWM*/ + } + }); + mux_info[0].pin = d4200_gpio_base+9; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_LOW; + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 44, wkup_gpio0_base+37, d4200_gpio_base+1, mux_info, 1); + // D/A switch + mux_info[0].pin = d4200_gpio_base+9; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_IN; + // muxed GPIO as input + mux_info[1].pin = wkup_gpio0_base+44; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + // output enable as input + mux_info[2].pin = wkup_gpio0_base+37; + mux_info[2].pincmd = PINCMD_SET_DIRECTION; + mux_info[2].value = MRAA_GPIO_OUT_LOW; + // pull enable as input + mux_info[3].pin = d4200_gpio_base+1; + mux_info[3].pincmd = PINCMD_SET_DIRECTION; + mux_info[3].value = MRAA_GPIO_IN; + iot2050_pin_add_aio(b, pin_index, 1, mux_info, 4); + pin_index++; + + iot2050_setup_pins(b, pin_index, "A2", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 1, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 31, + wkup_gpio0_base+43, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + -1 /*PWM*/ + } + }); + mux_info[0].pin = d4200_gpio_base+10; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_LOW; + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 43, wkup_gpio0_base+36, d4200_gpio_base+2, mux_info, 1); + // D/A switch + mux_info[0].pin = d4200_gpio_base+10; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_IN; + // muxed GPIO as input + mux_info[1].pin = wkup_gpio0_base+43; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + // output enable as input + mux_info[2].pin = wkup_gpio0_base+36; + mux_info[2].pincmd = PINCMD_SET_DIRECTION; + mux_info[2].value = MRAA_GPIO_OUT_LOW; + // pull enable as input + mux_info[3].pin = d4200_gpio_base+2; + mux_info[3].pincmd = PINCMD_SET_DIRECTION; + mux_info[3].value = MRAA_GPIO_IN; + iot2050_pin_add_aio(b, pin_index, 2, mux_info, 4); + pin_index++; + + iot2050_setup_pins(b, pin_index, "A3", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 0, /*i2c*/ + 1, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 27, + wkup_gpio0_base+39, + { + 7, /*GPIO*/ + -1, /*UART*/ + -1, /*I2C*/ + -1, /*SPI*/ + -1 /*PWM*/ + } + }); + mux_info[0].pin = d4200_gpio_base+11; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_LOW; + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 39, wkup_gpio0_base+34, d4200_gpio_base+3, mux_info, 1); + // D/A switch + mux_info[0].pin = d4200_gpio_base+11; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_IN; + // muxed GPIO as input + mux_info[1].pin = wkup_gpio0_base+39; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_IN; + // output enable as input + mux_info[2].pin = wkup_gpio0_base+34; + mux_info[2].pincmd = PINCMD_SET_DIRECTION; + mux_info[2].value = MRAA_GPIO_OUT_LOW; + // pull enable as input + mux_info[3].pin = d4200_gpio_base+3; + mux_info[3].pincmd = PINCMD_SET_DIRECTION; + mux_info[3].value = MRAA_GPIO_IN; + iot2050_pin_add_aio(b, pin_index, 3, mux_info, 4); + pin_index++; + + iot2050_setup_pins(b, pin_index, "A4", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 1, /*i2c*/ + 1, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 30, + wkup_gpio0_base+42, + { + 7, /*GPIO*/ + -1, /*UART*/ + 0, /*I2C*/ + -1, /*SPI*/ + -1 /*PWM*/ + } + }); + mux_info[0].pin = d4200_gpio_base+12; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_LOW; + mux_info[1].pin = wkup_gpio0_base+21; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_OUT_HIGH; + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 42, wkup_gpio0_base+41, d4200_gpio_base+4, mux_info, 2); + // A/D/I switch + mux_info[0].pin = d4200_gpio_base+12; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_IN; + mux_info[1].pin = wkup_gpio0_base+21; + mux_info[1].pincmd = PINCMD_SET_OUT_VALUE; + mux_info[1].value = 0; + // pull enable as input + mux_info[2].pin = d4200_gpio_base+4; + mux_info[2].pincmd = PINCMD_SET_DIRECTION; + mux_info[2].value = MRAA_GPIO_IN; + iot2050_pin_add_i2c(b, pin_index, 0, mux_info, 3); + // A/D/I switch + mux_info[0].pin = d4200_gpio_base+12; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_IN; + mux_info[1].pin = wkup_gpio0_base+21; + mux_info[1].pincmd = PINCMD_SET_OUT_VALUE; + mux_info[1].value = 1; + // muxed GPIO as input + mux_info[2].pin = wkup_gpio0_base+42; + mux_info[2].pincmd = PINCMD_SET_DIRECTION; + mux_info[2].value = MRAA_GPIO_IN; + // output enable as input + mux_info[3].pin = wkup_gpio0_base+41; + mux_info[3].pincmd = PINCMD_SET_DIRECTION; + mux_info[3].value = MRAA_GPIO_OUT_LOW; + // pull enable as input + mux_info[4].pin = d4200_gpio_base+4; + mux_info[4].pincmd = PINCMD_SET_DIRECTION; + mux_info[4].value = MRAA_GPIO_IN; + iot2050_pin_add_aio(b, pin_index, 4, mux_info, 5); + pin_index++; + + iot2050_setup_pins(b, pin_index, "A5", + (mraa_pincapabilities_t) { + 1, /*valid*/ + 1, /*gpio*/ + 0, /*pwm*/ + 0, /*fast gpio*/ + 0, /*spi*/ + 1, /*i2c*/ + 1, /*aio*/ + 0}, /*uart*/ + (regmux_info_t) { + PINMUX_GROUP_WAKUP, + 23, + wkup_gpio0_base+35, + { + 7, /*GPIO*/ + -1, /*UART*/ + 0, /*I2C*/ + -1, /*SPI*/ + -1 /*PWM*/ + } + }); + mux_info[0].pin = d4200_gpio_base+13; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_OUT_LOW; + mux_info[1].pin = wkup_gpio0_base+21; + mux_info[1].pincmd = PINCMD_SET_DIRECTION; + mux_info[1].value = MRAA_GPIO_OUT_HIGH; + iot2050_pin_add_gpio(b, pin_index, wkup_gpio0_chip, 35, d4201_gpio_base+14, d4200_gpio_base+5, mux_info, 2); + // A/D/I switch + mux_info[0].pin = d4200_gpio_base+13; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_IN; + mux_info[1].pin = wkup_gpio0_base+21; + mux_info[1].pincmd = PINCMD_SET_OUT_VALUE; + mux_info[1].value = 0; + // pull enable as input + mux_info[2].pin = d4200_gpio_base+5; + mux_info[2].pincmd = PINCMD_SET_DIRECTION; + mux_info[2].value = MRAA_GPIO_IN; + iot2050_pin_add_i2c(b, pin_index, 0, mux_info, 3); + // A/D/I switch + mux_info[0].pin = d4200_gpio_base+13; + mux_info[0].pincmd = PINCMD_SET_DIRECTION; + mux_info[0].value = MRAA_GPIO_IN; + mux_info[1].pin = wkup_gpio0_base+21; + mux_info[1].pincmd = PINCMD_SET_OUT_VALUE; + mux_info[1].value = 1; + // muxed GPIO as input + mux_info[2].pin = wkup_gpio0_base+35; + mux_info[2].pincmd = PINCMD_SET_DIRECTION; + mux_info[2].value = MRAA_GPIO_IN; + // output enable as input + mux_info[3].pin = d4201_gpio_base+14; + mux_info[3].pincmd = PINCMD_SET_DIRECTION; + mux_info[3].value = MRAA_GPIO_OUT_LOW; + // pull enable as input + mux_info[4].pin = d4200_gpio_base+5; + mux_info[4].pincmd = PINCMD_SET_DIRECTION; + mux_info[4].value = MRAA_GPIO_IN; + iot2050_pin_add_aio(b, pin_index, 5, mux_info, 5); + pin_index++; + + /* UART */ + iot2050_setup_uart(b, "UART0", "/dev/ttyS1", "IO0", "IO1", "IO2", "IO3"); + b->def_uart_dev = 0; + /* I2C */ + iot2050_setup_i2c(b, "I2C0", 4, "A4", "A5"); + b->def_i2c_bus = 0; + /* SPI */ + iot2050_setup_spi(b, "SPI0", 0, 0, "IO13", "IO11", "IO12", "IO10"); + b->def_spi_bus = 0; + /* PWM */ + iot2050_setup_pwm(b, "PWM0"); + iot2050_setup_pwm(b, "PWM1"); + iot2050_setup_pwm(b, "PWM2"); + iot2050_setup_pwm(b, "PWM3"); + iot2050_setup_pwm(b, "PWM4"); + iot2050_setup_pwm(b, "PWM5"); + b->def_pwm_dev = 0; + /* LED */ + iot2050_setup_led(b, "user-led1-green"); + iot2050_setup_led(b, "user-led1-red"); + iot2050_setup_led(b, "user-led2-green"); + iot2050_setup_led(b, "user-led2-red"); + return b; +error: + syslog(LOG_CRIT, "iot2050: Platform failed to initialise"); + free(b); + return NULL; +} diff --git a/src/arm/siemens/platform.c b/src/arm/siemens/platform.c new file mode 100644 index 0000000..faa808a --- /dev/null +++ b/src/arm/siemens/platform.c @@ -0,0 +1,41 @@ +/* + * Author: Le Jin + * Copyright (c) Siemens AG, 2019 + * + * 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 "arm/siemens/platform.h" +#include "arm/siemens/platform_iot2050.h" + +void * +platfrom_pinmux_get_instance(char *platform) +{ + pin_mux_interface_t *instance = NULL; + if(!strcmp(platform, "iot2050")) { + instance = iot2050_pinmux_get_instance(); + } + if((instance) && (instance->initialized == false) && (instance->ops.init)) { + return instance->ops.init()?instance:NULL; + } + else { + return NULL; + } +} diff --git a/src/arm/siemens/platform_iot2050.c b/src/arm/siemens/platform_iot2050.c new file mode 100644 index 0000000..55997db --- /dev/null +++ b/src/arm/siemens/platform_iot2050.c @@ -0,0 +1,367 @@ +/* + * Author: Le Jin + * Copyright (c) Siemens AG, 2019 + * + * 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 "arm/siemens/platform_iot2050.h" + +enum{ + GROUP_MAIN_DOMAIN = 0, + GROUP_WAKUP_DOMAIN, + MAX_GROUP_NUMBER +}; + +typedef struct{ + pin_mux_interface_t super; + int mem_fd; + volatile uint32_t *pin_mux_reg_base[MAX_GROUP_NUMBER]; + volatile void *map_address[MAX_GROUP_NUMBER]; +} iot2050_pin_mux_handler_t; + +static bool iot2050_pinmux_init(void); +static void iot2050_pinmux_deinit(void); +static void iot2050_pinmux_select_func(uint8_t group, uint16_t pin_index, uint8_t func); +static void iot2050_pinmux_select_input(uint8_t group, uint16_t pin_index); +static void iot2050_pinmux_select_output(uint8_t group, uint16_t pin_index); +static void iot2050_pinmux_select_inout(uint8_t group, uint16_t pin_index); +static void iot2050_pinmux_select_hiz(uint8_t group, uint16_t pin_index); +static void iot2050_pinmux_select_pull_up(uint8_t group, uint16_t pin_index); +static void iot2050_pinmux_select_pull_down(uint8_t group, uint16_t pin_index); +static void iot2050_pinmux_select_pull_disable(uint8_t group, uint16_t pin_index); +static uint32_t iot2050_pinmux_get_raw_reg_value(uint8_t group, uint16_t pin_index); +static void iot2050_pinmux_set_raw_reg_value(uint8_t group, uint16_t pin_index, uint32_t value); +static void iot2050_pinmux_dump_info(uint8_t group, uint16_t pin_index); + +#define MAIN_PINMUX_REG_NUM (195) +#define MAIN_PINMUX_REG_LENGTH (MAIN_PINMUX_REG_NUM<<2) +#define MAIN_PINMUX_REG_PHY_BASE_ADDRESS (0x0011c000) + +#define WAKUP_PINMUX_REG_NUM (70) +#define WAKUP_PINMUX_REG_LENGTH (WAKUP_PINMUX_REG_NUM<<2) +#define WAKUP_PINMUX_REG_PHY_BASE_ADDRESS (0x4301c000) + +#define PAGE_SIZE 4096UL +#define PAGE_MASK (PAGE_SIZE - 1) + +#define REG_MUXMODE_POS (0) +#define REG_MUXMODE_MASK (0x0F << REG_MUXMODE_POS) +#define REG_MUXMODE_GET(reg) ((reg & REG_MUXMODE_MASK) >> REG_MUXMODE_POS) +#define REG_MUXMODE(mode) ((mode << REG_MUXMODE_POS) & REG_MUXMODE_MASK) + +#define REG_PULL_ENABLE_POS (16) +#define REG_PULL_ENABLE_MASK (0x01 << REG_PULL_ENABLE_POS) +#define REG_PULL_ENABLE_GET(reg) ((reg & REG_PULL_ENABLE_MASK) >> REG_PULL_ENABLE_POS) +#define REG_PULL_ENABLE (0x00 << REG_PULL_ENABLE_POS) +#define REG_PULL_DISABLE (0x01 << REG_PULL_ENABLE_POS) +#define REG_PULL_IS_ENABLED(reg) (!REG_PULL_ENABLE_GET(reg)) +#define REG_PULL_IS_DISABLED(reg) (!REG_PULL_IS_ENABLED(reg)) + +#define REG_PULL_SELECT_POS (17) +#define REG_PULL_SELECT_MASK (0x01 << REG_PULL_SELECT_POS) +#define REG_PULL_SELECT_GET(reg) ((reg & REG_PULL_SELECT_MASK) >> REG_PULL_SELECT_POS) +#define REG_PULL_UP (0x01 << REG_PULL_SELECT_POS) +#define REG_PULL_DOWN (0x00 << REG_PULL_SELECT_POS) +#define REG_PULL_IS_UP(reg) (REG_PULL_SELECT_GET(reg)) +#define REG_PULL_IS_DOWN(reg) (!REG_PULL_IS_UP(reg)) + +#define REG_INPUT_ENABLE_POS (18) +#define REG_INPUT_ENABLE_MASK (0x01 << REG_INPUT_ENABLE_POS) +#define REG_INPUT_ENABLE_GET(reg) ((reg & REG_INPUT_ENABLE_MASK) >> REG_INPUT_ENABLE_POS) +#define REG_INPUT_ENABLE (0x01 << REG_INPUT_ENABLE_POS) +#define REG_INPUT_DISABLE (0x00 << REG_INPUT_ENABLE_POS) +#define REG_INPUT_IS_ENABLED(reg) (REG_INPUT_ENABLE_GET(reg)) +#define REG_INPUT_IS_DISABLED(reg) (!REG_INPUT_IS_ENABLED(reg)) + +#define REG_OUTPUT_ENABLE_POS (21) +#define REG_OUTPUT_ENABLE_MASK (0x01 << REG_OUTPUT_ENABLE_POS) +#define REG_OUTPUT_ENABLE_GET(reg) ((reg & REG_OUTPUT_ENABLE_MASK) >> REG_OUTPUT_ENABLE_POS) +#define REG_OUTPUT_ENABLE (0x00 << REG_OUTPUT_ENABLE_POS) +#define REG_OUTPUT_DISABLE (0x01 << REG_OUTPUT_ENABLE_POS) +#define REG_OUTPUT_IS_ENABLED(reg) (!REG_OUTPUT_ENABLE_GET(reg)) +#define REG_OUTPUT_IS_DISABLED(reg) (!REG_OUTPUT_IS_ENABLED(reg)) + +#define REG_UPDATE(address, mask, value) (*address = ((*address) & (~mask)) | (value)) +#define GROUP_IS_VALID(group) (group < MAX_GROUP_NUMBER) + +#define PIN_OUTPUT (PULL_DISABLE) +#define PIN_OUTPUT_PULLUP (PULL_UP) +#define PIN_OUTPUT_PULLDOWN 0 +#define PIN_INPUT (INPUT_EN | PULL_DISABLE) +#define PIN_INPUT_PULLUP (INPUT_EN | PULL_UP) +#define PIN_INPUT_PULLDOWN (INPUT_EN) + +static iot2050_pin_mux_handler_t iot2050_pin_mux_handler = { + .super = { + .initialized = false, + .ops = { + .init = iot2050_pinmux_init, + .deinit = iot2050_pinmux_deinit, + .select_func = iot2050_pinmux_select_func, + .select_input = iot2050_pinmux_select_input, + .select_output = iot2050_pinmux_select_output, + .select_inout = iot2050_pinmux_select_inout, + .select_hiz = iot2050_pinmux_select_hiz, + .select_pull_up = iot2050_pinmux_select_pull_up, + .select_pull_down = iot2050_pinmux_select_pull_down, + .select_pull_disable = iot2050_pinmux_select_pull_disable, + .get_raw_reg_value = iot2050_pinmux_get_raw_reg_value, + .set_raw_reg_value = iot2050_pinmux_set_raw_reg_value, + .dump_info = iot2050_pinmux_dump_info + } + }, + .mem_fd = -1, + .map_address[GROUP_MAIN_DOMAIN] = MAP_FAILED, + .map_address[GROUP_WAKUP_DOMAIN] = MAP_FAILED, + .pin_mux_reg_base[GROUP_MAIN_DOMAIN] = MAP_FAILED, + .pin_mux_reg_base[GROUP_WAKUP_DOMAIN] = MAP_FAILED +}; + +pin_mux_interface_t* +iot2050_pinmux_get_instance(void) +{ + return (pin_mux_interface_t *)&iot2050_pin_mux_handler; +} + +static bool +iot2050_pinmux_init(void) +{ + uint32_t pageMask = sysconf(_SC_PAGE_SIZE) - 1; + + /* Open memory */ + DEBUG_PRINT("Open device\n"); + if((iot2050_pin_mux_handler.mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) { + DEBUG_PRINT("Open device: %s\n", strerror(errno)); + goto _FATAL; + } + + /* Map */ + DEBUG_PRINT("Map main mux register base\n"); + iot2050_pin_mux_handler.map_address[GROUP_MAIN_DOMAIN] = mmap(0, MAIN_PINMUX_REG_LENGTH, + PROT_READ | PROT_WRITE, MAP_SHARED, + iot2050_pin_mux_handler.mem_fd, + MAIN_PINMUX_REG_PHY_BASE_ADDRESS & ~pageMask); + if(iot2050_pin_mux_handler.map_address[GROUP_MAIN_DOMAIN] == MAP_FAILED) { + DEBUG_PRINT("Pinmux main domain map failed: %s\n", strerror(errno)); + goto _FATAL; + } + iot2050_pin_mux_handler.pin_mux_reg_base[GROUP_MAIN_DOMAIN] = iot2050_pin_mux_handler.map_address[GROUP_MAIN_DOMAIN] + + (MAIN_PINMUX_REG_PHY_BASE_ADDRESS & pageMask); + DEBUG_PRINT("\tPage address: %p\n", iot2050_pin_mux_handler.map_address[GROUP_MAIN_DOMAIN]); + DEBUG_PRINT("\tIn-page Offset: %x\n", MAIN_PINMUX_REG_PHY_BASE_ADDRESS & pageMask); + DEBUG_PRINT("\tReg address: %p\n", iot2050_pin_mux_handler.pin_mux_reg_base[GROUP_MAIN_DOMAIN]); + DEBUG_PRINT("Map wakup mux register base\n"); + iot2050_pin_mux_handler.map_address[GROUP_WAKUP_DOMAIN] = mmap(0, WAKUP_PINMUX_REG_LENGTH, + PROT_READ | PROT_WRITE, MAP_SHARED, + iot2050_pin_mux_handler.mem_fd, + WAKUP_PINMUX_REG_PHY_BASE_ADDRESS & ~pageMask); + if(iot2050_pin_mux_handler.map_address[GROUP_WAKUP_DOMAIN] == MAP_FAILED) { + DEBUG_PRINT("Pinmux wakup domain map failed: %s\n", strerror(errno)); + goto _FATAL; + } + iot2050_pin_mux_handler.pin_mux_reg_base[GROUP_WAKUP_DOMAIN] = iot2050_pin_mux_handler.map_address[GROUP_WAKUP_DOMAIN] + + (WAKUP_PINMUX_REG_PHY_BASE_ADDRESS & pageMask); + DEBUG_PRINT("\tPage address: %p\n", iot2050_pin_mux_handler.map_address[GROUP_WAKUP_DOMAIN]); + DEBUG_PRINT("\tIn-page Offset: %x\n", WAKUP_PINMUX_REG_PHY_BASE_ADDRESS & pageMask); + DEBUG_PRINT("\tReg address: %p\n", iot2050_pin_mux_handler.pin_mux_reg_base[GROUP_WAKUP_DOMAIN]); + iot2050_pin_mux_handler.super.initialized = true; + return true; +_FATAL: + iot2050_pinmux_deinit(); + return false; +} + +static void +iot2050_pinmux_deinit(void) +{ + if(iot2050_pin_mux_handler.mem_fd > 0) + close(iot2050_pin_mux_handler.mem_fd); + iot2050_pin_mux_handler.mem_fd = -1; + if(iot2050_pin_mux_handler.map_address[GROUP_MAIN_DOMAIN] != MAP_FAILED) + munmap((void *)iot2050_pin_mux_handler.map_address[GROUP_MAIN_DOMAIN], MAIN_PINMUX_REG_LENGTH); + iot2050_pin_mux_handler.map_address[GROUP_MAIN_DOMAIN] = MAP_FAILED; + iot2050_pin_mux_handler.pin_mux_reg_base[GROUP_MAIN_DOMAIN] = MAP_FAILED; + + if(iot2050_pin_mux_handler.map_address[GROUP_WAKUP_DOMAIN] != MAP_FAILED) + munmap((void *)iot2050_pin_mux_handler.map_address[GROUP_WAKUP_DOMAIN], WAKUP_PINMUX_REG_LENGTH); + iot2050_pin_mux_handler.map_address[GROUP_WAKUP_DOMAIN] = MAP_FAILED; + iot2050_pin_mux_handler.pin_mux_reg_base[GROUP_WAKUP_DOMAIN] = MAP_FAILED; + iot2050_pin_mux_handler.super.initialized = false; +} + +static void +iot2050_pinmux_select_func(uint8_t group, uint16_t pin_index, uint8_t func) { + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + REG_UPDATE(reg, REG_MUXMODE_MASK, REG_MUXMODE(func)); + } +} + +static void +iot2050_pinmux_select_input(uint8_t group, uint16_t pin_index) +{ + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + REG_UPDATE(reg, REG_INPUT_ENABLE_MASK, REG_INPUT_ENABLE); + REG_UPDATE(reg, REG_OUTPUT_ENABLE_MASK, REG_OUTPUT_DISABLE); + } +} + +static void +iot2050_pinmux_select_output(uint8_t group, uint16_t pin_index) +{ + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + REG_UPDATE(reg, REG_INPUT_ENABLE_MASK, REG_INPUT_DISABLE); + REG_UPDATE(reg, REG_OUTPUT_ENABLE_MASK, REG_OUTPUT_ENABLE); + } +} + +static void +iot2050_pinmux_select_inout(uint8_t group, uint16_t pin_index) +{ + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + REG_UPDATE(reg, REG_INPUT_ENABLE_MASK, REG_INPUT_ENABLE); + REG_UPDATE(reg, REG_OUTPUT_ENABLE_MASK, REG_OUTPUT_ENABLE); + } +} + +static void +iot2050_pinmux_select_hiz(uint8_t group, uint16_t pin_index) +{ + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + REG_UPDATE(reg, REG_INPUT_ENABLE_MASK, REG_INPUT_DISABLE); + REG_UPDATE(reg, REG_OUTPUT_ENABLE_MASK, REG_OUTPUT_DISABLE); + } +} + + +static void +iot2050_pinmux_select_pull_up(uint8_t group, uint16_t pin_index) +{ + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + REG_UPDATE(reg, REG_PULL_ENABLE_MASK, REG_PULL_ENABLE); + REG_UPDATE(reg, REG_PULL_SELECT_MASK, REG_PULL_UP); + } +} + +static void +iot2050_pinmux_select_pull_down(uint8_t group, uint16_t pin_index) +{ + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + REG_UPDATE(reg, REG_PULL_ENABLE_MASK, REG_PULL_ENABLE); + REG_UPDATE(reg, REG_PULL_SELECT_MASK, REG_PULL_DOWN); + } +} + +static void +iot2050_pinmux_select_pull_disable(uint8_t group, uint16_t pin_index) +{ + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + REG_UPDATE(reg, REG_PULL_ENABLE_MASK, REG_PULL_DISABLE); + } +} + +static uint32_t +iot2050_pinmux_get_raw_reg_value(uint8_t group, uint16_t pin_index) +{ + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + return *reg; + } + return -1; +} + +static void +iot2050_pinmux_set_raw_reg_value(uint8_t group, uint16_t pin_index, uint32_t value) +{ + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + *reg = value; + } +} + +static void +iot2050_pinmux_dump_info(uint8_t group, uint16_t pin_index) +{ + volatile uint32_t *reg; + + if(GROUP_IS_VALID(group)) { + reg = iot2050_pin_mux_handler.pin_mux_reg_base[group] + pin_index; + fprintf(stderr, "PinmuxReg Domain %s, Index %d, Raw 0x%08x\n", + group?"Wakup":"Main", + pin_index, + iot2050_pinmux_get_raw_reg_value(group, pin_index)); + if(REG_INPUT_IS_ENABLED(*reg)) { + fprintf(stderr, "\tInput: enabled\n"); + } + else if(REG_OUTPUT_IS_ENABLED(*reg)) { + fprintf(stderr, "\tOutput: enabled\n"); + } + else { + fprintf(stderr, "\tOutput: Hiz\n"); + } + + if(REG_PULL_IS_ENABLED(*reg)) { + if(REG_PULL_IS_UP(*reg)) { + fprintf(stderr, "\tPull Status: up\n"); + } + else { + fprintf(stderr, "\tPull Status: down\n"); + } + } + else { + fprintf(stderr, "\tPull Status: disabled\n"); + } + fprintf(stderr, "\tMode: %d\n", REG_MUXMODE_GET(*reg)); + } +}