From 4ba5da1144f1c2730e2d36b775783ffa9f5a1b04 Mon Sep 17 00:00:00 2001 From: "gowtham.r" Date: Thu, 28 Nov 2019 15:00:14 +0530 Subject: [PATCH] adding Adlink IPi SMARC x86/ARM support Signed-off-by: gowtham.r --- README.md | 2 + api/mraa/types.h | 3 + docs/adlink_ipi_arm.md | 38 ++ docs/adlink_ipi_x86.md | 56 ++ include/arm/adlink_ipi.h | 23 + include/x86/intel_adlink_lec_al.h | 30 + src/CMakeLists.txt | 2 + src/arm/adlink_ipi.c | 791 ++++++++++++++++++++++ src/arm/arm.c | 6 + src/x86/adlink-ipi.c | 1046 +++++++++++++++++++++++++++++ src/x86/x86.c | 29 +- 11 files changed, 2025 insertions(+), 1 deletion(-) create mode 100755 docs/adlink_ipi_arm.md create mode 100755 docs/adlink_ipi_x86.md create mode 100755 include/arm/adlink_ipi.h create mode 100755 include/x86/intel_adlink_lec_al.h create mode 100644 src/arm/adlink_ipi.c create mode 100644 src/x86/adlink-ipi.c diff --git a/README.md b/README.md index 840b96d..43e2d2b 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ X86 * [UP Squared](../master/docs/up2.md) * [Intel Joule](../master/docs/joule.md) * [IEI Tank](../master/docs/iei-tank.md) +* [ADLINK IPi-SMARC X86](../master/docs/adlink_ipi_x86.md) ARM --- @@ -44,6 +45,7 @@ ARM * [Beaglebone Black](../master/docs/beaglebone.md) * [phyBOARD-Wega](../master/docs/phyboard-wega.md) * [96Boards](../master/docs/96boards.md) +* [ADLINK IPi-SMARC ARM](../master/docs/adlink_ipi_arm.md) MIPS --- diff --git a/api/mraa/types.h b/api/mraa/types.h index 1498d32..be27bd5 100644 --- a/api/mraa/types.h +++ b/api/mraa/types.h @@ -63,6 +63,9 @@ typedef enum { MRAA_MTK_OMEGA2 = 18, /**< MT7688 based Onion Omega2 board */ MRAA_IEI_TANK = 19, /**< IEI Tank System*/ MRAA_ROCKPI4 = 20, /**< Radxa ROCK PI 4 Models A/B */ + MRAA_ADLINK_IPI = 21, /**< Adlink Industrial PI */ + MRAA_ADLINK_LEC_AL = 22, /**< Adlink LEC-AL*/ + MRAA_ADLINK_LEC_AL_AI = 23, /**< Adlink LEC-AL*/ // USB platform extenders start at 256 MRAA_FTDI_FT4222 = 256, /**< FTDI FT4222 USB to i2c bridge */ diff --git a/docs/adlink_ipi_arm.md b/docs/adlink_ipi_arm.md new file mode 100755 index 0000000..cfb14fe --- /dev/null +++ b/docs/adlink_ipi_arm.md @@ -0,0 +1,38 @@ +ADLINK IPi-SMARC ARM +============ + +Based on Rockchip PX30 with Quad-core ARM Cortex-A35 CPU + +Up to 4GB DDR3L at 1066/1333 MHz, 32 GB eMMC + +4x USB 2.0, 1x USB 2.0 OTG port, 2x 10/100M Ethernet Ports, DSI to HDMI converter board, RTC and a 40-pin I/O header + + + + +## Pin Mapping + +| Linux GPIO (/sys/class/gpio) | Function | MRAA number | MRAA number | Function | Linux GPIO (/sys/class/gpio) | +| :--------------------------: | :-------: | :---------: | :---------: | :-------: | :--------------------------: | +| | 3V3 | 1 | 2 | 5V | | +| | I2C_0 SDA | 3 | 4 | 5V | | +| | I2C_0 SCL | 5 | 6 | GND | | +| 116 | GPIO | 7 | 8 | UART TX | | +| | GND | 9 | 10 | UART RX | | +| 118 | GPIO | 11 | 12 | GPIO | 117 | +| 107 | GPIO | 13 | 14 | GND | | +| 104 | GPIO | 15 | 16 | GPIO | 109 | +| | 3V3 | 17 | 18 | GPIO | 121 | +| | SPI MOSI | 19 | 20 | GND | | +| | SPI MISO | 21 | 22 | GPIO | 122 | +| | SPI SCLK | 23 | 24 | SPI CS0 | | +| | GND | 25 | 26 | SPI CS1 | | +| | I2C_1 SDA | 27 | 28 | I2C_1 SCL | | +| 496 | GPIO/PWM | 29 | 30 | GND | | +| 497 | GPIO/PWM | 31 | 32 | GPIO/PWM | 498 | +| 499 | GPIO/PWM | 33 | 34 | GND | | +| 500 | GPIO/PWM | 35 | 36 | GPIO/PWM | 501 | +| 502 | GPIO/PWM | 37 | 38 | GPIO/PWM | 503 | +| | GND | 39 | 40 | GPIO/PWM | 504 | + + diff --git a/docs/adlink_ipi_x86.md b/docs/adlink_ipi_x86.md new file mode 100755 index 0000000..e1bfd37 --- /dev/null +++ b/docs/adlink_ipi_x86.md @@ -0,0 +1,56 @@ +ADLINK IPi-SMARC x86 +============ + +* ADLINK IPi-SMARC x86 + + Based on Intel(R) AtomĀ® E3900 Series(codename: Apollo Lake) with Movidius chip + + up to 8GB RAM, 64GB eMMC + + 2x USB 2.0, 2x USB 3.0, 1x USB 2.0 OTG port, 1x Gigabit Ethernet port, HDMI display, RTC and a 40-pin I/O header + + + + + +## Pin Mapping + + +| Linux GPIO (/sys/class/gpio) | Function | MRAA number | MRAA number | Function | Linux GPIO (/sys/class/gpio) | +| :--------------------------: | :-------: | :---------: | :---------: | :-------: | :--------------------------: | +| | 3V3 | 1 | 2 | 5V | | +| | I2C_0 SDA | 3 | 4 | 5V | | +| | I2C_0 SCL | 5 | 6 | GND | | +| 255 | GPIO | 7 | 8 | UART TX | | +| | GND | 9 | 10 | UART RX | | +| 256 | GPIO | 11 | 12 | GPIO | 257 | +| 258 | GPIO | 13 | 14 | GND | | +| 259 | GPIO | 15 | 16 | GPIO | 260 | +| | 3V3 | 17 | 18 | GPIO | 261 | +| | n/a | 19 | 20 | GND | | +| | n/a | 21 | 22 | GPIO | 262 | +| | n/a | 23 | 24 | n/a | | +| | GND | 25 | 26 | n/a | | +| | I2C_1 SDA | 27 | 28 | I2C_1 SCL | | +| 234 | GPIO/PWM | 29 | 30 | GND | | +| 235 | GPIO/PWM | 31 | 32 | GPIO/PWM | 236 | +| 237 | GPIO/PWM | 33 | 34 | GND | | +| 238 | GPIO/PWM | 35 | 36 | GPIO/PWM | 239 | +| 240 | GPIO/PWM | 37 | 38 | GPIO/PWM | 241 | +| | GND | 39 | 40 | GPIO/PWM | 242 | + +**Note:** + +* Before installing MRAA on Ubuntu 18.04, please follow up the below instructions to insert the following drivers first and configure I2C devices: + + ``` + $ sudo modprobe i2c_i801 + $ sudo modprobe gpio-pca953x + $ echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-13/new_device + $ echo "sx1509q 0x3e" > /sys/bus/i2c/devices/i2c-1/new_device + ``` + +* Not support SPI interface + + + diff --git a/include/arm/adlink_ipi.h b/include/arm/adlink_ipi.h new file mode 100755 index 0000000..ab3e077 --- /dev/null +++ b/include/arm/adlink_ipi.h @@ -0,0 +1,23 @@ +/* + * Author: Thomas Ingleby + * Author: Santhanakumar A + * Copyright (c) 2014 Intel Corporation. + * Copyright (c) 2019 ADLINK Technology Inc. + * SPDX-License-Identifier: MIT + */ + + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mraa_internal.h" + +mraa_board_t * + mraa_adlink_ipi(); + +#ifdef __cplusplus +} +#endif diff --git a/include/x86/intel_adlink_lec_al.h b/include/x86/intel_adlink_lec_al.h new file mode 100755 index 0000000..1d268dd --- /dev/null +++ b/include/x86/intel_adlink_lec_al.h @@ -0,0 +1,30 @@ +/* + * Author: Author: Gowtham R + * Based on work from: Dan O'Donovan + * Nicola Lunghi + * Copyright (c) 2017 Emutex Ltd. + * Copyright (c) 2014 Intel Corporation. + * Copyright (c) 2019 ADLINK Technology Inc. + * SPDX-License-Identifier: MIT + */ + + + + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mraa_internal.h" + +// +1 as pins are "1 indexed" +#define MRAA_LEC_AL_PINCOUNT (40 + 1) + +mraa_board_t* +mraa_lec_al_board(); + +#ifdef __cplusplus +} +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6f80eab..4fc9134 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,6 +55,7 @@ set (mraa_LIB_X86_SRCS_NOAUTO ${PROJECT_SOURCE_DIR}/src/x86/up2.c ${PROJECT_SOURCE_DIR}/src/x86/intel_joule_expansion.c ${PROJECT_SOURCE_DIR}/src/x86/iei_tank.c + ${PROJECT_SOURCE_DIR}/src/x86/adlink-ipi.c ) message (STATUS "INFO - Adding support for platform ${MRAAPLATFORMFORCE}") @@ -102,6 +103,7 @@ set (mraa_LIB_ARM_SRCS_NOAUTO ${PROJECT_SOURCE_DIR}/src/arm/banana.c ${PROJECT_SOURCE_DIR}/src/arm/de_nano_soc.c ${PROJECT_SOURCE_DIR}/src/arm/rockpi4.c + ${PROJECT_SOURCE_DIR}/src/arm/adlink_ipi.c ) set (mraa_LIB_MIPS_SRCS_NOAUTO diff --git a/src/arm/adlink_ipi.c b/src/arm/adlink_ipi.c new file mode 100644 index 0000000..8b6dc7c --- /dev/null +++ b/src/arm/adlink_ipi.c @@ -0,0 +1,791 @@ +/* + * Author: Thomas Ingleby + * Author: Santhanakumar A + * Copyright (c) 2014 Intel Corporation. + * Copyright (c) 2019 ADLINK Technology Inc. + * SPDX-License-Identifier: MIT + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "arm/adlink_ipi.h" +#include "common.h" + +#define PLATFORM_NAME_ADLINK_IPI "Adlink IPI - PX30" +#define MRAA_ADLINK_IPI_PINCOUNT 41 + +static int platform_detected = 0; + +static const char* serialdev[] = { "/dev/ttyS0", "/dev/ttyS1" }; +static const char* seriallink[] = { "/sys/class/tty/ttyS0", "/sys/class/tty/ttyS1" }; + +static const char* spilink[] = { "/sys/class/spidev/spidev0.0", + "/sys/class/spidev/spidev1.0" }; + +static const char* i2clink[] = { + "/sys/class/i2c-dev/i2c-0", "/sys/class/i2c-dev/i2c-1" }; + +static const char* pwmlink[] = { + "/sys/class/pwm/pwmchip1", "/sys/class/pwm/pwmchip2" }; + +static unsigned char regIon[16] = {0x2A, 0x2D, 0x30, 0x33, 0x36, 0x3B, 0x40, 0x45, 0x4A, 0x4D, 0x50, 0x53, 0x56, 0x5B, 0x60, 0x65}; + +static unsigned int IonValue[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + +static int base2, _fd; + +#define MAX_SIZE 64 +#define SYSFS_PWM "/sys/class/pwm" + +static int sx150x_pwm_init(int); + +static int +mraa_pwm_setup_duty_fp(mraa_pwm_context dev) +{ + char bu[MAX_SIZE]; + snprintf(bu, MAX_SIZE, "/sys/class/pwm/pwmchip%d/pwm%d/duty_cycle", dev->chipid, dev->pin); + + dev->duty_fp = open(bu, O_RDWR); + if (dev->duty_fp == -1) { + return 1; + } + return 0; +} + + +int _tperiod; + +static mraa_result_t pwm_period_replace(mraa_pwm_context dev, int period) +{ + _tperiod = period; + return MRAA_SUCCESS; +} + +static float pwm_read_replace(mraa_pwm_context dev) +{ + unsigned char rx_tx_buf[3] = {0}; + + if(dev->pin < 9) + { + if(_fd == -1) + { + return 0; + } + + rx_tx_buf[0] = regIon[dev->pin]; + if(write(_fd, &(rx_tx_buf[0]), 1) == 1) + { + if(read(_fd, &(rx_tx_buf[1]), 1) == 1) + { + return (rx_tx_buf[1] / 2.55); + } + } + } + return 0; +} + +static mraa_result_t pwm_write_replace(mraa_pwm_context dev, float duty) +{ + unsigned char rx_tx_buf[3] = {0}; + + IonValue[dev->pin] = ((duty /_tperiod) * 255); + + if(dev->pin < 9) + { + if(_fd == -1) + { + return MRAA_ERROR_INVALID_RESOURCE; + } + + rx_tx_buf[0] = regIon[dev->pin]; + rx_tx_buf[1] = IonValue[dev->pin]; + + if(write(_fd, &(rx_tx_buf[0]), 2) != 2) + { + return MRAA_ERROR_NO_RESOURCES; + } + return MRAA_SUCCESS; + } + return MRAA_ERROR_NO_RESOURCES; +} + + +static mraa_result_t pwm_enable_replace(mraa_pwm_context dev, int enable) +{ + int pin = dev->pin; + + if(9 > pin && 0 <= pin) + { + if(_fd != -1) + { + unsigned char rx_tx_buf[3] = {0}; + + if(_fd == -1) + { + return MRAA_ERROR_NO_RESOURCES; + } + + rx_tx_buf[0] = regIon[pin]; + rx_tx_buf[1] = IonValue[pin]; + if(write(_fd, &(rx_tx_buf[0]), 2) != 2) + { + return MRAA_ERROR_NO_RESOURCES; + } + } + else + { + return MRAA_ERROR_NO_RESOURCES; + } + + return MRAA_SUCCESS; + } + return MRAA_ERROR_NO_RESOURCES; +} + +static mraa_result_t pwm_init_raw_replace(mraa_pwm_context dev, int pin) +{ + char buffer[100] = {0}; + int i, fd; + syslog(LOG_WARNING, "pwm_init: pwm%i. chip info %d.", pin, dev->chipid); + + if(dev->chipid == 1 || dev->chipid == 2) + { + dev->advance_func->pwm_period_replace = NULL; + dev->advance_func->pwm_read_replace = NULL; + dev->advance_func->pwm_write_replace = NULL; + dev->advance_func->pwm_enable_replace = NULL; + + char directory[MAX_SIZE]; + snprintf(directory, MAX_SIZE, SYSFS_PWM "/pwmchip%d/pwm%d", dev->chipid, dev->pin); + struct stat dir; + if (stat(directory, &dir) == 0 && S_ISDIR(dir.st_mode)) { + syslog(LOG_NOTICE, "pwm_init: pwm%i already exported, continuing", pin); + dev->owner = 0; // Not Owner + } else { + char buffer[MAX_SIZE]; + snprintf(buffer, MAX_SIZE, "/sys/class/pwm/pwmchip%d/export", dev->chipid); + int export_f = open(buffer, O_WRONLY); + if (export_f == -1) { + syslog(LOG_ERR, "pwm_init: pwm%i. Failed to open export for writing: %s", pin, strerror(errno)); + free(dev); + return MRAA_ERROR_INVALID_RESOURCE; + } + + char out[MAX_SIZE]; + int size = snprintf(out, MAX_SIZE, "%d", dev->pin); + if (write(export_f, out, size * sizeof(char)) == -1) { + syslog(LOG_WARNING, "pwm_init: pwm%i. Failed to write to export! (%s) Potentially already in use.", pin, strerror(errno)); + close(export_f); + free(dev); + return MRAA_ERROR_INVALID_RESOURCE; + } + dev->owner = 1; + mraa_pwm_period_us(dev, 0xFF); + close(export_f); + } + + mraa_pwm_setup_duty_fp(dev); + + return MRAA_SUCCESS; + }else if(dev->chipid == 3) + { + dev->advance_func->pwm_period_replace = pwm_period_replace; + dev->advance_func->pwm_read_replace = pwm_read_replace; + dev->advance_func->pwm_write_replace = pwm_write_replace; + dev->advance_func->pwm_enable_replace = pwm_enable_replace; + + if(pin < 9) + { + if(sx150x_pwm_init(pin)) + { + return MRAA_ERROR_NO_RESOURCES; + } + if((fd = open("/sys/class/gpio/unexport", O_WRONLY)) != -1) + { + i = sprintf(buffer,"%d",base2 + pin); + write(fd, buffer, i); + close(fd); + } + if((fd = open("/sys/class/gpio/export", O_WRONLY)) != -1) + { + i = sprintf(buffer,"%d",base2 + pin); + write(fd, buffer, i); + close(fd); + sprintf(buffer,"/sys/class/gpio/gpio%d/direction",base2 + pin); + if((fd = open(buffer, O_WRONLY)) != -1) + { + write(fd, "out", 3); + close(fd); + sprintf(buffer,"/sys/class/gpio/gpio%d/value",base2 + pin); + if((fd = open(buffer, O_WRONLY)) != -1) + { + write(fd, "0", 1); + close(fd); + } + } + } + else + { + return MRAA_ERROR_NO_RESOURCES; + } + return MRAA_SUCCESS; + } + else + { + return MRAA_ERROR_NO_RESOURCES; + } + } + return MRAA_ERROR_NO_RESOURCES; +} + +//configuring extra registers as pwm for extended gpio +static int sx150x_pwm_init(int pin) +{ + int i; + int add = (pin < 8) ? 1 : 0; + + unsigned char rx_tx_buf[] = {0x0 + add, 0, 0x6 + add, 0, 0xE + add, 0, 0x20 + add, 0, 0x10 + add, 0}; + + if(_fd == -1) + { + return -1; + } + + for(i = 0; i < 9; i += 2) + { + if(write(_fd, &(rx_tx_buf[i]), 1) != 1) + { + return -1; + } + if(read(_fd, &(rx_tx_buf[i + 1]), 1) != 1) + { + return -1; + } + + if((i == 2) || (i == 6)) + rx_tx_buf[i+1] |= (1 << (pin % 8)); + else + rx_tx_buf[i+1] &= ~(1 << (pin % 8)); + + if(write(_fd, &(rx_tx_buf[i]), 2) != 2) + { + return -1; + } + } + + return 0; +} + +static mraa_result_t gpio_init_pre(int pin) +{ + unsigned char rx_tx_buf[3] = {0}; + int fd, i; + char buffer[50] = {0}; + + if((496 + 16) > pin && (496 - 1) < pin) + { + pin = pin - base2; + + int add = (pin < 8) ? 1 : 0; + + if(_fd == -1) + { + return MRAA_ERROR_INVALID_RESOURCE; + } + + rx_tx_buf[0] = regIon[pin]; + rx_tx_buf[1] = -1; + + if(write(_fd, &(rx_tx_buf[0]), 2) != 2) + { + return MRAA_ERROR_NO_RESOURCES; + } + + rx_tx_buf[0] = 0x0 + add; + if(write(_fd, &(rx_tx_buf[0]), 1) == 1) + { + if(read(_fd, &(rx_tx_buf[1]), 1) == 1) + { + rx_tx_buf[1] &= ~(1 < (pin % 8)); + write(_fd, &rx_tx_buf[0], 2); + } + } + + rx_tx_buf[0] = 0x20 + add; + if(write(_fd, &(rx_tx_buf[0]), 1) == 1) + { + if(read(_fd, &(rx_tx_buf[1]), 1) == 1) + { + rx_tx_buf[1] &= ~(1 < (pin % 8)); + write(_fd, &rx_tx_buf[0], 2); + if((fd = open("/sys/class/gpio/unexport", O_WRONLY)) != -1) + { + i = sprintf(buffer,"%d",base2 + pin); + write(fd, buffer, i); + close(fd); + } + return MRAA_SUCCESS; + } + } + return MRAA_ERROR_INVALID_RESOURCE; + } + return MRAA_SUCCESS; +} + + +static int sx150x_init() +{ + char rx_tx_buf[100] = {0}; + int i, bus_num, fd; + + for(i = 0; i < 999; i++) + { + sprintf(rx_tx_buf,"/sys/class/gpio/gpiochip%d/device/name",i); + if((fd = open(rx_tx_buf, O_RDONLY)) != -1) + { + int count = read(fd, rx_tx_buf, 7); + if(count != 0) + { + if(strncmp(rx_tx_buf, "sx1509q", count) == 0) + { + base2 = i; + break; + } + } + close(fd); + } + } + + for(i = 0; i < 999;i++) + { + sprintf(rx_tx_buf,"/sys/bus/i2c/devices/%x-003e/name",i); + if((fd = open(rx_tx_buf, O_RDONLY)) != -1) + { + int count = read(fd, rx_tx_buf, 7); + if(count != 0) + { + if(strncmp(rx_tx_buf, "sx1509q", count) == 0) + { + bus_num = i; + break; + } + } + close(fd); + } + } + + sprintf(rx_tx_buf, "/dev/i2c-%d",bus_num); + if((_fd = open(rx_tx_buf, O_RDWR)) < 0) + { + return -1; + } + + if(ioctl(_fd, I2C_SLAVE_FORCE, 0x3E) < 0) + { + return -1; + } +// configuring clock and misc register for PWM feature + rx_tx_buf[0] = 0x1E; + if(write(_fd, &(rx_tx_buf[0]), 1) == 1) + { + if(read(_fd, &(rx_tx_buf[1]), 1) == 1) + { + rx_tx_buf[1] |= (1 << 6); + rx_tx_buf[1] |= ~(1 << 5); + if(write(_fd, &(rx_tx_buf[0]), 2) != 2) + { + return -1; + } + } + } + else + { + return -1; + } + + rx_tx_buf[0] = 0x1F; + if(write(_fd, &(rx_tx_buf[0]), 1) == 1) + { + if(read(_fd, &(rx_tx_buf[1]), 1) == 1) + { + rx_tx_buf[1] &= ~(1 << 7); + rx_tx_buf[1] &= ~(1 << 3); + rx_tx_buf[1] &= ~((0x7) << 4); + rx_tx_buf[1] |= ((1 & 0x7) << 4); + if(write(_fd, &(rx_tx_buf[0]), 2) == 2) + { + return 0; + } + } + } + + return -1; +} + +mraa_board_t* +mraa_adlink_ipi() +{ + mraa_board_t* b = (mraa_board_t*) calloc(1, sizeof(mraa_board_t)); + if (b == NULL) { + return NULL; + } + + platform_detected = 0; + int i2c0 = -1; + int i2c1 = -1; + int spi0 = -1; + int uart0 = -1; + int pwm0 = -1; + int pwm1 = -1; + + //TODO: Handle different Adlink arm variants eg. IMX6, IMX8M + b->platform_name = PLATFORM_NAME_ADLINK_IPI; + //platform_detected = PLATFORM_PRO; + b->phy_pin_count = MRAA_ADLINK_IPI_PINCOUNT; +/* + if (platform_detected == 0) { + free(b); + syslog(LOG_ERR, "mraa: Could not detect platform"); + return NULL; + } +*/ + int devnum; + for (devnum = 0; devnum < 2; devnum++) { + if (mraa_link_targets(seriallink[devnum], "ff030000")) { + uart0 = devnum; + } + } + + for (devnum = 0; devnum < 2; devnum++) { + if (mraa_link_targets(spilink[devnum], "ff1d0000")) { + spi0 = devnum; + } + } + + for (devnum = 0; devnum < 2; devnum++) { + if (mraa_link_targets(i2clink[devnum], "ff180000")) { + i2c0 = devnum; + } + if (mraa_link_targets(i2clink[devnum], "ff190000")) { + i2c1 = devnum; + } + } + + for (devnum = 0; devnum < 2; devnum++) { + if (mraa_link_targets(pwmlink[devnum], "ff208020")) { + pwm0 = devnum; + } + if (mraa_link_targets(pwmlink[devnum], "ff208030")) { + pwm1 = devnum; + } + } + + b->adv_func = (mraa_adv_func_t*) calloc(1, sizeof(mraa_adv_func_t)); + if (b->adv_func == NULL) { + free(b); + return NULL; + } + + b->pins = (mraa_pininfo_t*) calloc(b->phy_pin_count, sizeof(mraa_pininfo_t)); + if (b->pins == NULL) { + free(b->adv_func); + free(b); + return NULL; + } + + b->pwm_dev_count = 0; + b->pwm_default_period = 500; + b->pwm_max_period = 2147483; + b->pwm_min_period = 1; + + b->adv_func->gpio_init_pre = gpio_init_pre; + + // initializations of pwm functions + b->adv_func->pwm_init_raw_replace = pwm_init_raw_replace; + b->adv_func->pwm_period_replace = pwm_period_replace; + b->adv_func->pwm_read_replace = pwm_read_replace; + b->adv_func->pwm_write_replace = pwm_write_replace; + b->adv_func->pwm_enable_replace = pwm_enable_replace; + + + /* + b->adv_func->spi_init_pre = &mraa_adlink_spi_init_pre; + b->adv_func->i2c_init_pre = &mraa_adlink_i2c_init_pre; + b->adv_func->gpio_mmap_setup = &mraa_adlink_mmap_setup; +*/ + strncpy(b->pins[0].name, "INVALID", MRAA_PIN_NAME_SIZE); + b->pins[0].capabilities = (mraa_pincapabilities_t){ 0, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[1].name, "3V3", MRAA_PIN_NAME_SIZE); + b->pins[1].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[2].name, "5V", MRAA_PIN_NAME_SIZE); + b->pins[2].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[3].name, "I2C1_SDA", MRAA_PIN_NAME_SIZE); // GPIO0_C3 + b->pins[3].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 1, 0, 0 }; + b->pins[3].gpio.pinmap = 19; + + strncpy(b->pins[4].name, "5V", MRAA_PIN_NAME_SIZE); + b->pins[4].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[5].name, "I2C1_SCL", MRAA_PIN_NAME_SIZE); // GPIO0_C2 + b->pins[5].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 1, 0, 0 }; + b->pins[5].gpio.pinmap = 18; + + strncpy(b->pins[6].name, "GND", MRAA_PIN_NAME_SIZE); + b->pins[6].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + if (pwm0 == 0) { + strncpy(b->pins[7].name, "PWM6", MRAA_PIN_NAME_SIZE); // PWM6 + b->pins[7].capabilities = (mraa_pincapabilities_t){ 1, 0, 1, 0, 0, 0, 0, 0 }; + } else { + strncpy(b->pins[7].name, "GPIO3_C4", MRAA_PIN_NAME_SIZE); // GPIO3_C4 + b->pins[7].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + } + b->pins[7].gpio.pinmap = 116; + + b->pins[7].pwm.pinmap = 0; + b->pins[7].pwm.parent_id = 1; + b->pins[7].pwm.mux_total = 0; + b->pwm_dev_count++; + + strncpy(b->pins[8].name, "UART0_TX", MRAA_PIN_NAME_SIZE); // GPIO0_B2 + b->pins[8].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 1 }; + b->pins[8].gpio.pinmap = 10; + + strncpy(b->pins[9].name, "GND", MRAA_PIN_NAME_SIZE); + b->pins[9].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[10].name, "UART0_RX", MRAA_PIN_NAME_SIZE); // GPIO0_B3 + b->pins[10].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 1 }; + b->pins[10].gpio.pinmap = 11; + + strncpy(b->pins[11].name, "GPIO3_C6", MRAA_PIN_NAME_SIZE); // GPIO3_C6 + b->pins[11].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }; + b->pins[11].gpio.pinmap = 118; + + if (pwm1 == 1) { + strncpy(b->pins[12].name, "PWM7", MRAA_PIN_NAME_SIZE); // PWM7 + b->pins[12].capabilities = (mraa_pincapabilities_t){ 1, 0, 1, 0, 0, 0, 0, 0 }; + } else { + strncpy(b->pins[12].name, "GPIO3_C5", MRAA_PIN_NAME_SIZE); // GPIO3_C5 + b->pins[12].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + } + b->pins[12].gpio.pinmap = 117; + + b->pins[12].pwm.pinmap = 0; + b->pins[12].pwm.parent_id = 2; + b->pins[12].pwm.mux_total = 0; + b->pwm_dev_count++; + + strncpy(b->pins[13].name, "GPIO3_B3", MRAA_PIN_NAME_SIZE); // GPIO3_B3 + b->pins[13].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }; + b->pins[13].gpio.pinmap = 107; + + strncpy(b->pins[14].name, "GND", MRAA_PIN_NAME_SIZE); + b->pins[14].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[15].name, "GPIO3_B4", MRAA_PIN_NAME_SIZE); // GPIO3_B4 + b->pins[15].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }; + b->pins[15].gpio.pinmap = 104; + + strncpy(b->pins[16].name, "GPIO3_B5", MRAA_PIN_NAME_SIZE); // GPIO3_B5 + b->pins[16].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }; + b->pins[16].gpio.pinmap = 109; + + strncpy(b->pins[17].name, "3V3", MRAA_PIN_NAME_SIZE); + b->pins[17].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[18].name, "GPIO3_D1", MRAA_PIN_NAME_SIZE); // GPIO3_D1 + b->pins[18].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }; + b->pins[18].gpio.pinmap = 121; + + strncpy(b->pins[19].name, "SPI0_MOSI", MRAA_PIN_NAME_SIZE); // GPIO1_B4 + b->pins[19].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 1, 0, 0, 0 }; + b->pins[19].gpio.pinmap = 44; + + strncpy(b->pins[20].name, "GND", MRAA_PIN_NAME_SIZE); + b->pins[20].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[21].name, "SPI0_MISO", MRAA_PIN_NAME_SIZE); // GPIO1_B5 + b->pins[21].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 1, 0, 0, 0 }; + b->pins[21].gpio.pinmap = 45; + + strncpy(b->pins[22].name, "GPIO3_D2", MRAA_PIN_NAME_SIZE); // GPIO3_D2 + b->pins[22].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }; + b->pins[22].gpio.pinmap = 122; + + strncpy(b->pins[23].name, "SPI0_CLK", MRAA_PIN_NAME_SIZE); // GPIO1_B7 + b->pins[23].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 1, 0, 0, 0 }; + b->pins[23].gpio.pinmap = 47; + + strncpy(b->pins[24].name, "SPI0_CSN", MRAA_PIN_NAME_SIZE); // GPIO1_B6 + b->pins[24].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 1, 0, 0, 0 }; + b->pins[24].gpio.pinmap = 46; + + strncpy(b->pins[25].name, "GND", MRAA_PIN_NAME_SIZE); + b->pins[25].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[26].name, "SPI0_CS1", MRAA_PIN_NAME_SIZE); // NC + b->pins[26].capabilities = (mraa_pincapabilities_t){ 0, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[27].name, "I2C0_SDA", MRAA_PIN_NAME_SIZE); // GPIO0_B1 + b->pins[27].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 1, 0, 0 }; + b->pins[27].gpio.pinmap = 9; + + strncpy(b->pins[28].name, "I2C0_SCL", MRAA_PIN_NAME_SIZE); // GPIO0_B0 + b->pins[28].capabilities = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 1, 0, 0 }; + b->pins[28].gpio.pinmap = 8; + + strncpy(b->pins[29].name, "EGPIO1_0", MRAA_PIN_NAME_SIZE); // Expander GPIO + b->pins[29].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + b->pins[29].gpio.pinmap = 496; + + b->pins[29].pwm.parent_id = 3; + b->pins[29].pwm.pinmap = 0; + b->pwm_dev_count++; + + strncpy(b->pins[30].name, "GND", MRAA_PIN_NAME_SIZE); + b->pins[30].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[31].name, "EGPIO1_1", MRAA_PIN_NAME_SIZE); // Expander GPIO + b->pins[31].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + b->pins[31].gpio.pinmap = 497; + + b->pins[31].pwm.parent_id = 3; + b->pins[31].pwm.pinmap = 1; + b->pwm_dev_count++; + + strncpy(b->pins[32].name, "EGPIO1_2", MRAA_PIN_NAME_SIZE); // Expander GPIO + b->pins[32].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + b->pins[32].gpio.pinmap = 498; + + b->pins[32].pwm.parent_id = 3; + b->pins[32].pwm.pinmap = 2; + b->pwm_dev_count++; + + strncpy(b->pins[33].name, "EGPIO1_3", MRAA_PIN_NAME_SIZE); // Expander GPIO + b->pins[33].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + b->pins[33].gpio.pinmap = 499; + + b->pins[33].pwm.parent_id = 3; + b->pins[33].pwm.pinmap = 3; + b->pwm_dev_count++; + + strncpy(b->pins[34].name, "GND", MRAA_PIN_NAME_SIZE); + b->pins[34].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[35].name, "EGPIO1_4", MRAA_PIN_NAME_SIZE); // Expander GPIO + b->pins[35].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + b->pins[35].gpio.pinmap = 500; + + b->pins[35].pwm.parent_id = 3; + b->pins[35].pwm.pinmap = 4; + b->pwm_dev_count++; + + strncpy(b->pins[36].name, "EGPIO1_5", MRAA_PIN_NAME_SIZE); // Expander GPIO + b->pins[36].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + b->pins[36].gpio.pinmap = 501; + + b->pins[36].pwm.parent_id = 3; + b->pins[36].pwm.pinmap = 5; + b->pwm_dev_count++; + + strncpy(b->pins[37].name, "EGPIO1_6", MRAA_PIN_NAME_SIZE); // Expander GPIO + b->pins[37].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + b->pins[37].gpio.pinmap = 502; + + b->pins[37].pwm.parent_id = 3; + b->pins[37].pwm.pinmap = 6; + b->pwm_dev_count++; + + strncpy(b->pins[38].name, "EGPIO1_7", MRAA_PIN_NAME_SIZE); // Expander GPIO + b->pins[38].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + b->pins[38].gpio.pinmap = 503; + + b->pins[38].pwm.parent_id = 3; + b->pins[38].pwm.pinmap = 7; + b->pwm_dev_count++; + + strncpy(b->pins[39].name, "GND", MRAA_PIN_NAME_SIZE); + b->pins[39].capabilities = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 }; + + strncpy(b->pins[40].name, "EGPIO2_8", MRAA_PIN_NAME_SIZE); // Expander GPIO + b->pins[40].capabilities = (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }; + b->pins[40].gpio.pinmap = 504; + + b->pins[40].pwm.parent_id = 3; + b->pins[40].pwm.pinmap = 8; + b->pwm_dev_count++; + + b->aio_count = 0; + b->adc_raw = 0; + b->adc_supported = 0; + b->gpio_count = 0; + int i; + for (i = 0; i < b->phy_pin_count; i++) { + if (b->pins[i].capabilities.gpio) { + b->gpio_count++; + } + } + + // BUS DEFINITIONS + b->i2c_bus_count = 0; + b->def_i2c_bus = 0; + if (i2c0 >= 0) { + b->def_i2c_bus = b->i2c_bus_count; + b->i2c_bus[b->i2c_bus_count].bus_id = i2c0; + b->i2c_bus[b->i2c_bus_count].sda = 27; + b->i2c_bus[b->i2c_bus_count].scl = 28; + b->i2c_bus_count++; + } + + if (i2c1 >= 0) { + b->def_i2c_bus = b->i2c_bus_count; + b->i2c_bus[b->i2c_bus_count].bus_id = i2c1; + b->i2c_bus[b->i2c_bus_count].sda = 3; + b->i2c_bus[b->i2c_bus_count].scl = 5; + b->i2c_bus_count++; + } + + b->spi_bus_count = 0; + b->def_spi_bus = 0; + if (spi0 >= 0) { + b->spi_bus[b->spi_bus_count].bus_id = spi0; + b->spi_bus[b->spi_bus_count].slave_s = 0; + b->spi_bus[b->spi_bus_count].cs = 24; + b->spi_bus[b->spi_bus_count].mosi = 19; + b->spi_bus[b->spi_bus_count].miso = 21; + b->spi_bus[b->spi_bus_count].sclk = 23; + b->spi_bus_count++; + } + + b->uart_dev_count = 0; + b->def_uart_dev = 0; + + if (uart0 >= 0) { + b->uart_dev[b->uart_dev_count].device_path = (char *)serialdev[uart0]; + b->uart_dev[b->uart_dev_count].rx = 10; + b->uart_dev[b->uart_dev_count].tx = 8; + b->uart_dev_count++; + } + + if(sx150x_init() < 0) + { + _fd = -1; + } + + return b; +} diff --git a/src/arm/arm.c b/src/arm/arm.c index 3d15eb5..b26d953 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -16,6 +16,7 @@ #include "arm/beaglebone.h" #include "arm/phyboard.h" #include "arm/raspberry_pi.h" +#include "arm/adlink_ipi.h" #include "mraa_internal.h" @@ -93,6 +94,8 @@ mraa_arm_platform() platform_type = MRAA_ROCKPI4; else if (mraa_file_contains("/proc/device-tree/compatible", "raspberrypi,")) platform_type = MRAA_RASPBERRY_PI; + else if (mraa_file_contains("/proc/device-tree/model", "ADLINK ARM, LEC-PX30")) + platform_type = MRAA_ADLINK_IPI; } switch (platform_type) { @@ -117,6 +120,9 @@ mraa_arm_platform() case MRAA_DE_NANO_SOC: plat = mraa_de_nano_soc(); break; + case MRAA_ADLINK_IPI: + plat = mraa_adlink_ipi(); + break; default: plat = NULL; syslog(LOG_ERR, "Unknown Platform, currently not supported by MRAA"); diff --git a/src/x86/adlink-ipi.c b/src/x86/adlink-ipi.c new file mode 100644 index 0000000..1c0ee63 --- /dev/null +++ b/src/x86/adlink-ipi.c @@ -0,0 +1,1046 @@ + + /* + * Author: Dan O'Donovan + * Author: Santhanakumar A + + * Copyright (c) 2019 ADLINK Technology Inc. + * SPDX-License-Identifier: MIT + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "linux/gpio.h" +#include "mraa_internal.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "common.h" +#include "gpio.h" +#include "x86/intel_adlink_lec_al.h" +#include "gpio/gpio_chardev.h" + +#define SYSFS_CLASS_GPIO "/sys/class/gpio" + +#define PLATFORM_NAME "LEC-AL" +#define PLATFORM_NAME_AI "LEC-AL AI" + +#define MRAA_LEC_AL_GPIOCOUNT 17 +#define MAX_SIZE 64 +#define POLL_TIMEOUT + +static volatile int base1, base2, _fd; +static volatile long m_period; +static mraa_gpio_context gpio; + + +struct intr_list { + volatile int pin; + unsigned char curr; + char valuepath[50]; + void (*fptr)(void*); + void* args; + struct intr_list *next; +}; + +static unsigned char regIon[16] = {0x2A, 0x2D, 0x30, 0x33, 0x36, 0x3B, 0x40, 0x45, 0x4A, 0x4D, 0x50, 0x53, 0x56, 0x5B, 0x60, 0x65}; + +static struct intr_list *list; +mraa_result_t gpio_intr_init_pre(int pin); +static int sx150x_pwm_init(int pin); + +static mraa_result_t pwm_init_raw_replace(mraa_pwm_context dev, int pin) +{ + char buffer[100] = {0}; + int i, fd; + + if(pin < 9) + { + if(sx150x_pwm_init(pin)) + { + return MRAA_ERROR_NO_RESOURCES; + } + if((fd = open("/sys/class/gpio/export", O_WRONLY)) != -1) + { + i = sprintf(buffer,"%d",base2 + pin); + write(fd, buffer, i); + close(fd); + sprintf(buffer,"/sys/class/gpio/gpio%d/direction",base2 + pin); + if((fd = open(buffer, O_WRONLY)) != -1) + { + write(fd, "out", 3); + close(fd); + sprintf(buffer,"/sys/class/gpio/gpio%d/value",base2 + pin); + if((fd = open(buffer, O_WRONLY)) != -1) + { + write(fd, "0", 1); + close(fd); + } + } + } + else + { + return MRAA_ERROR_NO_RESOURCES; + } + } + return MRAA_SUCCESS; +} + +static mraa_result_t pwm_period_replace(mraa_pwm_context dev, int period) +{ + m_period = period; + return MRAA_SUCCESS; +} + +static float pwm_read_replace(mraa_pwm_context dev) +{ + unsigned char rx_tx_buf[3] = {0}; + + if(dev->pin < 9) + { + if(_fd == -1) + { + return 0; + } + + rx_tx_buf[0] = regIon[dev->pin]; + if(write(_fd, &(rx_tx_buf[0]), 1) == 1) + { + if(read(_fd, &(rx_tx_buf[1]), 1) == 1) + { + return ((rx_tx_buf[1] / 2.55)* 2000); + } + } + } + return 0; +} + +static mraa_result_t pwm_write_replace(mraa_pwm_context dev, float duty) +{ + unsigned char rx_tx_buf[3] = {0}; + + duty = duty / 2000; + + if(dev->pin < 9) + { + duty = duty * 2.55; + if(_fd == -1) + { + return MRAA_ERROR_INVALID_RESOURCE; + } + + rx_tx_buf[0] = regIon[dev->pin]; + rx_tx_buf[1] = duty; + + if(write(_fd, &(rx_tx_buf[0]), 2) != 2) + { + return MRAA_ERROR_NO_RESOURCES; + } + return MRAA_SUCCESS; + } + return MRAA_ERROR_NO_RESOURCES; +} + +static mraa_result_t pwm_enable_replace(mraa_pwm_context dev, int enable) +{ + int pin = dev->pin; + + if(9 > pin && 0 <= pin) + { + if(_fd != -1) + { + unsigned char rx_tx_buf[3] = {0}; + + if(_fd == -1) + { + return MRAA_ERROR_NO_RESOURCES; + } + + rx_tx_buf[0] = regIon[pin]; + rx_tx_buf[1] = 0xFF; + if(write(_fd, &(rx_tx_buf[0]), 2) != 2) + { + return MRAA_ERROR_NO_RESOURCES; + } + } + else + { + return MRAA_ERROR_NO_RESOURCES; + } + + return MRAA_SUCCESS; + } + return MRAA_ERROR_NO_RESOURCES; +} + + static void +gpio_close_event_handles_sysfs(int fds[], int num_fds) +{ + if ((fds == NULL) || (num_fds <= 0)) { + syslog(LOG_CRIT, "failed to close and free sysfs event handles"); + return; + } + + for (int i = 0; i < num_fds; ++i) { + close(fds[i]); + } + + free(fds); +} + + + static mraa_timestamp_t +gpio_get_timestamp_sysfs() +{ + struct timeval time; + gettimeofday(&time, NULL); + + return (time.tv_sec * 1e6 + time.tv_usec); +} + +//clearing all interrupts +void clear_sx1509x_intr(void) +{ + uint8_t rx_tx_buf[10] = {0}; + + rx_tx_buf[0] = 0x18; + rx_tx_buf[1] = 0xFF; + rx_tx_buf[2] = 0xFF; + write(_fd, rx_tx_buf, 3); +} + + +static mraa_result_t gpio_wait_interrupt(int fds[], int num_fds, mraa_gpio_events_t events) +{ + unsigned char c; + struct pollfd pfd[num_fds]; + + pfd[0].fd = fds[0]; + // setup poll on POLLPRI + pfd[0].events = POLLPRI; + + // do an initial read to clear interrupt + lseek(fds[0], 0, SEEK_SET); + read(fds[0], &c, 1); + + clear_sx1509x_intr(); + + // Wait for it forever or until pthread_cancel + // poll is a cancelable point like sleep() + poll(pfd, num_fds, -1); + + clear_sx1509x_intr(); + + if (pfd[0].revents & POLLPRI) { + read(fds[0], &c, 1); + events[0].id = 0; + events[0].timestamp = gpio_get_timestamp_sysfs(); + } else + events[0].id = -1; + + return MRAA_SUCCESS; +} + + static void* +gpio_interrupt_handler(void* arg) +{ + if (arg == NULL) { + syslog(LOG_ERR, "gpio: interrupt_handler: context is invalid"); + return NULL; + } + + mraa_result_t ret; + mraa_gpio_context dev = (mraa_gpio_context) arg; + int idx = 0; + + int *fps = malloc(dev->num_pins * sizeof(int)); + if (!fps) { + syslog(LOG_ERR, "mraa_gpio_interrupt_handler_multiple() malloc error"); + return NULL; + } + + mraa_gpio_context it = dev; + + char bu[MAX_SIZE]; + snprintf(bu, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/value", it->pin); + fps[idx] = open(bu, O_RDONLY); + if (fps[idx] < 0) { + syslog(LOG_ERR, "gpio%i: interrupt_handler: failed to open 'value' : %s", it->pin, + strerror(errno)); + gpio_close_event_handles_sysfs(fps, idx); + return NULL; + } + + idx++; + + for (;;) { + ret = gpio_wait_interrupt(fps, idx, dev->events); + + if (ret == MRAA_SUCCESS && !dev->isr_thread_terminating) { + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + if(dev->isr != NULL) + { + (dev->isr)(dev->isr_args); + } + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + } + } +} + +static void internal_isr(void*args) +{ + struct intr_list *it = list; + int fps; + unsigned char c; + + /* Is this pin on a subplatform? Do nothing... */ + while (it) { + // open gpio value with open(3) + fps = open(it->valuepath, O_RDONLY); + if (fps > 0) { + read(fps, &c, 1); + close(fps); + if(it->curr != c) + { + (it->fptr)(it->args); + it->curr = c; + } + + } + it = it->next; + } +} + +// configuring main interrupt line for sx1509q it will create common isr routine for all gpio's +static mraa_result_t intr_init() +{ + int fd; + char bu[MAX_SIZE]; + int length; + char filepath[MAX_SIZE]; + + gpio = (mraa_gpio_context) calloc(1, sizeof(struct _gpio)); + if (gpio == NULL) { + syslog(LOG_CRIT, "gpio%i: Failed to allocate memory for context", 456); + return MRAA_ERROR_INVALID_RESOURCE; + } + + gpio->advance_func = NULL; + gpio->pin = 434 + 22; + gpio->value_fp = -1; + gpio->isr_value_fp = -1; + + gpio->isr_thread_terminating = 0; + gpio->owner = 1; + + gpio->num_pins = 1; + gpio->next = NULL; + gpio->events = NULL; + + if((fd = open("/sys/class/gpio/export", O_WRONLY)) != -1) + { + write(fd,"456",3); + sprintf(bu,"%d",base1 + 12); + write(fd,bu,3); + close(fd); + } + else + { + return MRAA_ERROR_INVALID_RESOURCE; + } + + sprintf(bu,"/sys/class/gpio/gpio%d/direction",456); + if((fd = open(bu, O_WRONLY)) != -1) + { + write(fd, "in", 2); + close(fd); + } + else + { + return MRAA_ERROR_INVALID_RESOURCE; + } + + sprintf(bu,"/sys/class/gpio/gpio%d/direction",base1 + 12); + if((fd = open(bu, O_WRONLY)) != -1) + { + write(fd, "in", 2); + close(fd); + } + else + { + return MRAA_ERROR_INVALID_RESOURCE; + } + + // we only allow one isr per mraa_gpio_context + if (gpio->thread_id != 0) { + return MRAA_ERROR_NO_RESOURCES; + } + + gpio->events = malloc(gpio->num_pins * sizeof(mraa_gpio_event)); + if (gpio->events == NULL) { + syslog(LOG_ERR, "mraa_gpio_edge_mode() malloc error"); + return MRAA_ERROR_NO_RESOURCES; + } + + gpio->events[0].id = -1; + + snprintf(filepath, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/edge", gpio->pin); + + int edge = open(filepath, O_RDWR); + if (edge == -1) { + syslog(LOG_ERR, "gpio%i: edge_mode: Failed to open 'edge' for writing: %s", gpio->pin, + strerror(errno)); + return MRAA_ERROR_INVALID_RESOURCE; + } + + length = snprintf(bu, sizeof(bu), "both"); + if (write(edge, bu, length * sizeof(char)) == -1) { + syslog(LOG_ERR, "gpio%i: edge_mode: Failed to write to 'edge': %s", gpio->pin, strerror(errno)); + close(edge); + return MRAA_ERROR_UNSPECIFIED; + } + + close(edge); + + gpio->isr = internal_isr; + gpio->isr_args = NULL; + + pthread_create(&gpio->thread_id, NULL, gpio_interrupt_handler, (void*) gpio); + + return MRAA_SUCCESS; +} + +// it will clean the resources, MRAA created by advanced callback functions +static mraa_result_t gpio_close_pre(mraa_gpio_context dev) +{ + struct intr_list *ptr, *last; + ptr = last = list; + char gpio_path[50] = {0}; + int fd, length; + + if(list == NULL) + { + return MRAA_SUCCESS; + } + + while(ptr) + { + if(ptr->pin == dev->pin) + { + break; + } + last = ptr; + ptr = ptr->next; + } + + if(ptr) + { + if(ptr == list) + { + list = ptr->next; + } + else + { + last->next = ptr->next; + } + } + + + if(list == NULL && gpio != NULL) + { + mraa_gpio_isr_exit(gpio); + if((fd = open("/sys/class/gpio/unexport", O_WRONLY)) != -1) + { + length = sprintf(gpio_path,"%d",gpio->pin); + write(fd, gpio_path, length); + length = sprintf(gpio_path,"%d",base1 + 12); + write(fd, gpio_path, length); + close(fd); + } + + free(gpio); + gpio = NULL; + } + + return MRAA_SUCCESS; +} + +//callb ack routine for isr registration +static mraa_result_t gpio_isr_replace(mraa_gpio_context dev, mraa_gpio_edge_t mode, void (*fptr)(void*), void* args) +{ + struct intr_list *node = list; + int fps; + + node = list; + + if(list == NULL) + { + intr_init(); + } + + gpio_intr_init_pre(dev->pin); + + struct intr_list *ptr = list; + + while(ptr) + { + if(ptr->pin == dev->pin) + { + return MRAA_ERROR_NO_RESOURCES; + } + ptr = ptr->next; + } + + list = (struct intr_list*)calloc(1, sizeof(struct intr_list)); + if(list == NULL) + { + return MRAA_ERROR_INVALID_RESOURCE; + } + list->fptr = fptr; + list->args = args; + list->pin = dev->pin; + list->next = node; + + snprintf(list->valuepath, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/value", list->pin); + fps = open(list->valuepath, O_RDONLY); + if (fps > 0) { + read(fps, &(list->curr), 1); + close(fps); + } + + return MRAA_SUCCESS; +} + + +//configuring extra registers as pwm for extended gpio +static int sx150x_pwm_init(int pin) +{ + int i; + int add = (pin < 8) ? 1 : 0; + + unsigned char rx_tx_buf[] = {0x0 + add, 0, 0x6 + add, 0, 0xE + add, 0, 0x20 + add, 0, 0x10 + add, 0}; + + if(_fd == -1) + { + return -1; + } + + + for(i = 0; i < 9; i += 2) + { + if(write(_fd, &(rx_tx_buf[i]), 1) != 1) + { + return -1; + } + if(read(_fd, &(rx_tx_buf[i + 1]), 1) != 1) + { + return -1; + } + + if((i == 2) || (i == 6)) + rx_tx_buf[i+1] |= (1 << (pin % 8)); + else + rx_tx_buf[i+1] &= ~(1 << (pin % 8)); + + if(write(_fd, &(rx_tx_buf[i]), 2) != 2) + { + return -1; + } + } + + return 0; +} + +//configuring extra registers as interrupt for extended gpio +mraa_result_t gpio_intr_init_pre(int pin) +{ + int i; + if(base2 + 17 > pin && (base2 - 1) < pin) + { + pin = (pin - base2); + int index = pin % 8; + + unsigned char rx_tx_buf[] = {0x12, 0, 0, 0x14, 0, 0, 0x16, 0, 0, 0x18, 0, 0}; + + if(_fd == -1) + { + return MRAA_ERROR_NO_RESOURCES; + } + + for(i = 0; i < 10; i+=3) + { + if(write(_fd, &(rx_tx_buf[i]), 1) != 1) + { + return MRAA_ERROR_NO_RESOURCES; + } + if(read(_fd, &(rx_tx_buf[i + 1]), 2) != 2) + { + return MRAA_ERROR_NO_RESOURCES; + } + + + if(rx_tx_buf[i] == 0x12) + { + if(pin < 8) + rx_tx_buf[i + 2] &= ~(1 << index); + else + rx_tx_buf[i + 1] &= ~(1 << index); + } + else + { + if(rx_tx_buf[i] == 0x14 && pin < 8) + { + if(index < 4) + rx_tx_buf[i + 2] |= (3 << ((index % 4) * 2)); + else + rx_tx_buf[i + 1] |= (3 << ((index % 4) * 2)); + } + else if(rx_tx_buf[i] == 0x16) + { + if(index < 4) + rx_tx_buf[i + 2] |= (3 << ((index % 4) * 2)); + else + rx_tx_buf[i + 1] |= (3 << ((index % 4) * 2)); + } + else + { + if(pin < 8) + rx_tx_buf[i + 2] |= (1 << index); + else + rx_tx_buf[i + 1] |= (1 << index); + } + } + + if(write(_fd, &(rx_tx_buf[i]), 3) != 3) + { + return MRAA_ERROR_NO_RESOURCES; + } + } + } + return MRAA_SUCCESS; +} + +static int sx150x_init(int bus_num) +{ + char rx_tx_buf[20] = {0}; + + sprintf(rx_tx_buf, "/dev/i2c-%d",bus_num); + if((_fd = open(rx_tx_buf, O_RDWR)) < 0) + { + return -1; + } + + if(ioctl(_fd, I2C_SLAVE_FORCE, 0x3E) < 0) + { + return -1; + } +/* +// resetting sx1509q + rx_tx_buf[0] = 0x7d; + rx_tx_buf[1] = 0x12; + + if(write(_fd, &(rx_tx_buf[0]), 2) == 2) + { + rx_tx_buf[1] = 0x34; + if(write(_fd, &(rx_tx_buf[0]), 2) != 2) + { + return -1; + } + } +*/ +// configuring clock and misc register for PWM feature + rx_tx_buf[0] = 0x1E; + if(write(_fd, &(rx_tx_buf[0]), 1) == 1) + { + if(read(_fd, &(rx_tx_buf[1]), 1) == 1) + { + rx_tx_buf[1] |= (1 << 6); + rx_tx_buf[1] |= ~(1 << 5); + if(write(_fd, &(rx_tx_buf[0]), 2) != 2) + { + return -1; + } + } + } + else + { + return -1; + } + + rx_tx_buf[0] = 0x1F; + if(write(_fd, &(rx_tx_buf[0]), 1) == 1) + { + if(read(_fd, &(rx_tx_buf[1]), 1) == 1) + { + rx_tx_buf[1] &= ~(1 << 7); + rx_tx_buf[1] &= ~(1 << 3); + rx_tx_buf[1] &= ~((0x7) << 4); + rx_tx_buf[1] |= ((1 & 0x7) << 4); + if(write(_fd, &(rx_tx_buf[0]), 2) == 2) + { + return 0; + } + } + } + + return -1; +} + + +// utility function to setup pin mapping of boards +static mraa_result_t mraa_lec_al_set_pininfo(mraa_board_t* board, int mraa_index, char* name, + mraa_pincapabilities_t caps, int sysfs_pin) +{ + if (mraa_index < board->phy_pin_count) { + mraa_pininfo_t* pin_info = &board->pins[mraa_index]; + strncpy(pin_info->name, name, MRAA_PIN_NAME_SIZE); + pin_info->capabilities = caps; + if (caps.gpio) { + pin_info->gpio.pinmap = sysfs_pin; + pin_info->gpio.mux_total = 0; + } + if (caps.i2c) { + pin_info->i2c.pinmap = 1; + pin_info->i2c.mux_total = 0; + } + + if (caps.uart) { + pin_info->uart.mux_total = 0; + } + if (caps.spi) { + pin_info->spi.mux_total = 0; + } + return MRAA_SUCCESS; + } + return MRAA_ERROR_INVALID_RESOURCE; +} + +static mraa_result_t mraa_lec_al_get_pin_index(mraa_board_t* board, char* name, int* pin_index) +{ + int i; + for (i = 0; i < board->phy_pin_count; ++i) { + if (strncmp(name, board->pins[i].name, MRAA_PIN_NAME_SIZE) == 0) { + *pin_index = i; + return MRAA_SUCCESS; + } + } + + syslog(LOG_CRIT, "lec_al: Failed to find pin name %s", name); + + return MRAA_ERROR_INVALID_RESOURCE; +} + +static mraa_result_t gpio_init_pre(int pin) +{ + unsigned char rx_tx_buf[3] = {0}; + int fd, i; + char buffer[50] = {0}; + + if(pin == base1 + 6) + { + for(i = 0; i < 100; i++) + { + sprintf(buffer, "/sys/class/hwmon/hwmon%d/device/fan1_enable", i); + + if((fd = open(buffer, O_RDWR)) == -1) + { + continue; + } + if((write(fd, "1", 1)) != 1) + { + close(fd); + return MRAA_ERROR_NO_RESOURCES; + } + close(fd); + + } + } + + if(base2 + 17 > pin && (base2 - 1) < pin) + { + pin = pin - base2; + + int add = (pin < 8) ? 1 : 0; + + if(_fd == -1) + { + return MRAA_ERROR_INVALID_RESOURCE; + } + + rx_tx_buf[0] = regIon[pin]; + rx_tx_buf[1] = -1; + + if(write(_fd, &(rx_tx_buf[0]), 2) != 2) + { + return MRAA_ERROR_NO_RESOURCES; + } + + rx_tx_buf[0] = 0x0 + add; + if(write(_fd, &(rx_tx_buf[0]), 1) == 1) + { + if(read(_fd, &(rx_tx_buf[1]), 1) == 1) + { + rx_tx_buf[1] &= ~(1 < (pin % 8)); + write(_fd, &rx_tx_buf[0], 2); + } + } + + rx_tx_buf[0] = 0x20 + add; + if(write(_fd, &(rx_tx_buf[0]), 1) == 1) + { + if(read(_fd, &(rx_tx_buf[1]), 1) == 1) + { + rx_tx_buf[1] &= ~(1 < (pin % 8)); + write(_fd, &rx_tx_buf[0], 2); + if((fd = open("/sys/class/gpio/unexport", O_WRONLY)) != -1) + { + i = sprintf(buffer,"%d",base2 + pin); + write(fd, buffer, i); + close(fd); + } + return MRAA_SUCCESS; + } + } + return MRAA_ERROR_INVALID_RESOURCE; + } + return MRAA_SUCCESS; +} + +mraa_board_t* mraa_lec_al_board() +{ + int i, fd, i2c_bus_num; + char buffer[60] = {0}, *line = NULL; + FILE *fh; + size_t len; + + mraa_board_t* b = (mraa_board_t*) calloc(1, sizeof (mraa_board_t)); + + if (b == NULL) { + return NULL; + } + + if((fh = fopen("/sys/devices/virtual/dmi/id/product_name", "r")) != NULL) { + if (getline(&line, &len, fh) != -1) { + line[strcspn(line, "\r\n")] = 0; + if ((strncasecmp(line, "LEC-ALAI", strlen("LEC-ALAI") + 1) == 0)) { + b->platform_name = PLATFORM_NAME_AI; + } + else + { + b->platform_name = PLATFORM_NAME; + } + } + fclose(fh); + } + + b->phy_pin_count = MRAA_LEC_AL_PINCOUNT; + b->gpio_count = MRAA_LEC_AL_GPIOCOUNT; + b->chardev_capable = 0; + + b->pins = (mraa_pininfo_t*) malloc(sizeof(mraa_pininfo_t) * MRAA_LEC_AL_PINCOUNT); + if (b->pins == NULL) { + goto error; + } + + b->adv_func = (mraa_adv_func_t *) calloc(1, sizeof (mraa_adv_func_t)); + if (b->adv_func == NULL) { + free(b->pins); + goto error; + } + + b->adv_func->gpio_isr_replace = gpio_isr_replace; + b->adv_func->gpio_close_pre = gpio_close_pre; + b->adv_func->gpio_init_pre = gpio_init_pre; + + // initializations of pwm functions + b->adv_func->pwm_init_raw_replace = pwm_init_raw_replace; + b->adv_func->pwm_period_replace = pwm_period_replace; + b->adv_func->pwm_read_replace = pwm_read_replace; + b->adv_func->pwm_write_replace = pwm_write_replace; + b->adv_func->pwm_enable_replace = pwm_enable_replace; + + for(i = 0; i < 999; i++) + { + sprintf(buffer,"/sys/class/gpio/gpiochip%d/device/name",i); + if((fd = open(buffer, O_RDONLY)) != -1) + { + int count = read(fd,buffer,7); + if(count != 0) + { + if(strncmp(buffer, "sx1509q", count) == 0) + { + base2 = i; + } + if(strncmp(buffer, "pca9535", count) == 0) + { + base1 = i; + } + } + close(fd); + } + } + + syslog(LOG_NOTICE, "lec_al: base1 %d base2 %d\n", base1, base2); + + // Configure PWM + b->pwm_dev_count = 0; + b->pwm_default_period = 5000; + b->pwm_max_period = 218453; + b->pwm_min_period = 1; + + mraa_lec_al_set_pininfo(b, 1, "3v3", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 2, "5v", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 3, "I2C0_DAT", (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 1, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 4, "5v", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 5, "I2C0_CK", (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 1, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 6, "GND", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 7, "GPIO04", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, base1 + 4); + mraa_lec_al_set_pininfo(b, 8, "UART_TXD", (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 1 }, -1); + mraa_lec_al_set_pininfo(b, 9, "GND", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 10, "UART_RXD", (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 1 }, -1); + mraa_lec_al_set_pininfo(b, 11, "GPIO05", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, base1 + 6); + mraa_lec_al_set_pininfo(b, 12, "GPIO06", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, base1 + 5); + b->pins[12].pwm.parent_id = 0; + b->pins[12].pwm.pinmap = 9; + b->pwm_dev_count++; + mraa_lec_al_set_pininfo(b, 13, "GPIO07", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, base1 + 7); + mraa_lec_al_set_pininfo(b, 14, "GND", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 15, "GPIO08", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, base1 + 8); + mraa_lec_al_set_pininfo(b, 16, "GPIO09", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, base1 + 9); + mraa_lec_al_set_pininfo(b, 17, "3v3", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 18, "GPIO10", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, base1 + 10); + mraa_lec_al_set_pininfo(b, 19, "SPI_0_MOSI", (mraa_pincapabilities_t){ 1, 0, 0, 0, 1, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 20, "GND", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 21, "SPI_0_MISO", (mraa_pincapabilities_t){ 1, 0, 0, 0, 1, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 22, "GPIO11", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, base1 + 11); + mraa_lec_al_set_pininfo(b, 23, "SPI_0_SCLK", (mraa_pincapabilities_t){ 1, 0, 0, 0, 1, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 24, "SPI_0_CE0", (mraa_pincapabilities_t){ 1, 0, 0, 0, 1, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 25, "GND", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 26, "SPI_0_CE1", (mraa_pincapabilities_t){ 1, 0, 0, 0, 1, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 27, "I2C1_DAT", (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 1, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 28, "I2C1_CK", (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 1, 0, 0 }, -1); + + mraa_lec_al_set_pininfo(b, 29, "GPIO1_0", (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }, base2 + 0); + b->pins[29].pwm.parent_id = 1; + b->pins[29].pwm.pinmap = 0; + b->pwm_dev_count++; + mraa_lec_al_set_pininfo(b, 30, "GND", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 31, "GPIO1_1", (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }, base2 + 1); + b->pins[31].pwm.parent_id = 1; + b->pins[31].pwm.pinmap = 1; + b->pwm_dev_count++; + mraa_lec_al_set_pininfo(b, 32, "GPIO1_2", (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }, base2 + 2); + b->pins[32].pwm.parent_id = 1; + b->pins[32].pwm.pinmap = 2; + b->pwm_dev_count++; + mraa_lec_al_set_pininfo(b, 33, "GPIO1_3", (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }, base2 + 3); + b->pins[33].pwm.parent_id = 1; + b->pins[33].pwm.pinmap = 3; + b->pwm_dev_count++; + mraa_lec_al_set_pininfo(b, 34, "GND", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 35, "GPIO1_4", (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }, base2 + 4); + b->pins[35].pwm.parent_id = 1; + b->pins[35].pwm.pinmap = 4; + b->pwm_dev_count++; + mraa_lec_al_set_pininfo(b, 36, "GPIO1_5", (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }, base2 + 5); + b->pins[36].pwm.parent_id = 1; + b->pins[36].pwm.pinmap = 5; + b->pwm_dev_count++; + mraa_lec_al_set_pininfo(b, 37, "GPIO1_6", (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }, base2 + 6); + b->pins[37].pwm.parent_id = 1; + b->pins[37].pwm.pinmap = 6; + b->pwm_dev_count++; + mraa_lec_al_set_pininfo(b, 38, "GPIO1_7", (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }, base2 + 7); + b->pins[38].pwm.parent_id = 1; + b->pins[38].pwm.pinmap = 7; + b->pwm_dev_count++; + mraa_lec_al_set_pininfo(b, 39, "GND", (mraa_pincapabilities_t){ -1, 0, 0, 0, 0, 0, 0, 0 }, -1); + mraa_lec_al_set_pininfo(b, 40, "GPIO2_8", (mraa_pincapabilities_t){ 1, 1, 1, 0, 0, 0, 0, 0 }, base2 + 8); + b->pins[40].pwm.parent_id = 1; + b->pins[40].pwm.pinmap = 8; + b->pwm_dev_count++; + + + // Configure UART #1 (default) + b->uart_dev_count = 1; + + mraa_lec_al_get_pin_index(b, "UART_RXD", &(b->uart_dev[0].rx)); + mraa_lec_al_get_pin_index(b, "UART_TXD", &(b->uart_dev[0].tx)); + b->uart_dev[0].device_path = "/dev/ttyS4"; + + b->def_uart_dev = 0; + + // Configure SPI #0 CS1 + b->spi_bus_count = 0; + b->spi_bus[b->spi_bus_count].bus_id = 1; + b->spi_bus[b->spi_bus_count].slave_s = 0; + mraa_lec_al_get_pin_index(b, "SPI_0_CE0", &(b->spi_bus[b->spi_bus_count].cs)); + mraa_lec_al_get_pin_index(b, "SPI_0_MOSI", &(b->spi_bus[b->spi_bus_count].mosi)); + mraa_lec_al_get_pin_index(b, "SPI_0_MISO", &(b->spi_bus[b->spi_bus_count].miso)); + mraa_lec_al_get_pin_index(b, "SPI_0_SCLK", &(b->spi_bus[b->spi_bus_count].sclk)); + b->spi_bus_count++; + + b->spi_bus[b->spi_bus_count].bus_id = 1; + b->spi_bus[b->spi_bus_count].slave_s = 1; + mraa_lec_al_get_pin_index(b, "SPI_0_CE1", &(b->spi_bus[b->spi_bus_count].cs)); + mraa_lec_al_get_pin_index(b, "SPI_0_MOSI", &(b->spi_bus[b->spi_bus_count].mosi)); + mraa_lec_al_get_pin_index(b, "SPI_0_MISO", &(b->spi_bus[b->spi_bus_count].miso)); + mraa_lec_al_get_pin_index(b, "SPI_0_SCLK", &(b->spi_bus[b->spi_bus_count].sclk)); + b->spi_bus_count++; + + // Set number of i2c adaptors usable from userspace + b->i2c_bus_count = 0; + b->def_i2c_bus = 0; + + i2c_bus_num = mraa_find_i2c_bus_pci("0000:00", "0000:00:16.1", "i2c_designware.1"); + if (i2c_bus_num != -1) { + if(sx150x_init(i2c_bus_num) < 0) + { + _fd = -1; + } + + b->i2c_bus[0].bus_id = i2c_bus_num; + mraa_lec_al_get_pin_index(b, "I2C1_DAT", (int*) &(b->i2c_bus[1].sda)); + mraa_lec_al_get_pin_index(b, "I2C1_CK", (int*) &(b->i2c_bus[1].scl)); + b->i2c_bus_count++; + } + + i2c_bus_num = mraa_find_i2c_bus_pci("0000:00", "0000:00:1f.1", "."); + if (i2c_bus_num != -1) { + b->i2c_bus[1].bus_id = i2c_bus_num; + mraa_lec_al_get_pin_index(b, "I2C0_DAT", (int*) &(b->i2c_bus[0].sda)); + mraa_lec_al_get_pin_index(b, "I2C0_CK", (int*) &(b->i2c_bus[0].scl)); + b->i2c_bus_count++; + } + + const char* pinctrl_path = "/sys/bus/platform/drivers/broxton-pinctrl"; + int have_pinctrl = access(pinctrl_path, F_OK) != -1; + syslog(LOG_NOTICE, "lec_al: kernel pinctrl driver %savailable", have_pinctrl ? "" : "un"); + + return b; + +error: + syslog(LOG_CRIT, "lec_al: Platform failed to initialise"); + free(b); + close(_fd); + return NULL; +} diff --git a/src/x86/x86.c b/src/x86/x86.c index c61ac88..b064d91 100644 --- a/src/x86/x86.c +++ b/src/x86/x86.c @@ -23,6 +23,7 @@ #include "x86/up2.h" #include "x86/intel_joule_expansion.h" #include "x86/iei_tank.h" +#include "x86/intel_adlink_lec_al.h" mraa_platform_t mraa_x86_platform() @@ -30,10 +31,12 @@ mraa_x86_platform() #ifndef MRAA_PLATFORM_FORCE mraa_platform_t platform_type = MRAA_UNKNOWN_PLATFORM; - char* line = NULL; + char* line = NULL, buffer[20] = {0}; // let getline allocate memory for *line size_t len = 0; FILE* fh = fopen("/sys/devices/virtual/dmi/id/board_name", "r"); + int fd; + if (fh != NULL) { if (getline(&line, &len, fh) != -1) { // Sanitize input by terminating at any of possible end of line chars @@ -89,6 +92,12 @@ mraa_x86_platform() } else if ((strncasecmp(line, "SAF3", strlen("SAF3") + 1) == 0) ) { platform_type = MRAA_IEI_TANK; plat = mraa_iei_tank(); + } else if ((strncasecmp(line, "LEC-ALAI", strlen("LEC-ALAI") + 1) == 0) ) { + platform_type = MRAA_ADLINK_LEC_AL; + plat = mraa_lec_al_board(); + } else if ((strncasecmp(line, "LEC-AL", strlen("LEC-AL") + 1) == 0) ) { + platform_type = MRAA_ADLINK_LEC_AL; + plat = mraa_lec_al_board(); } else { syslog(LOG_ERR, "Platform not supported, not initialising"); platform_type = MRAA_UNKNOWN_PLATFORM; @@ -109,6 +118,24 @@ mraa_x86_platform() fclose(fh); } } + + if( (fd = open("/sys/devices/virtual/dmi/id/product_name", O_RDONLY)) != -1) { + syslog(LOG_ERR, "Checking additional Platform support for LEC-AL iPI"); + if(read(fd, buffer, 10) > 0) { + if ((strncasecmp(buffer, "LEC-ALAI", strlen("LEC-ALAI")) == 0)) { + syslog(LOG_ERR, "LEC-AL AI IPi found. starting MRAA"); + platform_type = MRAA_ADLINK_LEC_AL_AI; + plat = mraa_lec_al_board(); + } + else if ((strncasecmp(buffer, "LEC-AL", strlen("LEC-AL")) == 0)) { + syslog(LOG_ERR, "LEC-AL IPi found. starting MRAA"); + platform_type = MRAA_ADLINK_LEC_AL; + plat = mraa_lec_al_board(); + } + close(fd); + } + } + return platform_type; #else #if defined(xMRAA_INTEL_GALILEO_GEN2)