blob: 5cfdc4e2e19733af66e05bad5134268612531d00 [file] [log] [blame]
/*----------------------------------------------------------------------------*/
//
//
// WiringPi ODROID-M1S Board Control file (ROCKCHIP 64Bits Platform)
//
//
/*----------------------------------------------------------------------------*/
/*******************************************************************************
Copyright (C) 2023 Steve Jeong <steve@how2flow.net>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <asm/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
/*----------------------------------------------------------------------------*/
#include "softPwm.h"
#include "softTone.h"
/*----------------------------------------------------------------------------*/
#include "wiringPi.h"
#include "odroidm1.h"
#if !defined(DEVMEM)
#include <gpiod.h>
/*----------------------------------------------------------------------------*/
// libgpiod define
/*----------------------------------------------------------------------------*/
static struct gpiod_chip *chip;
static struct gpiod_line *gpiod;
#endif
/*----------------------------------------------------------------------------*/
// wiringPi gpio map define
/*----------------------------------------------------------------------------*/
static const int pinToGpio[64] = {
// wiringPi number to native gpio number
16, 71, // 0 | 1 : GPIO0_C0, GPIO2_A7
17, 18, // 2 | 3 : GPIO0_C1, GPIO0_C2
77, 78, // 4 | 5 : GPIO2_B5, GPIO2_B6
72, 14, // 6 | 7 : GPIO2_B0, GPIO0_B6
110,109, // 8 | 9 : GPIO3_B6, GPIO3_B5
97, 73, // 10 | 11 : GPIO3_A1, GPIO2_B1
113,114, // 12 | 13 : GPIO3_C1, GPIO3_C2
115, 68, // 14 | 15 : GPIO3_C3, GPIO2_A4
67, -1, // 16 | 17 : GPIO2_A3
-1, -1, // 18 | 19 :
-1, 80, // 20 | 21 : , GPIO2_C0
79, 13, // 22 | 23 : GPIO2_B7, GPIO0_B5
69, -1, // 24 | 25 : GPIO2_A5,
74, 70, // 26 | 27 : GPIO2_B2, GPIO2_A6
-1, -1, // 28 | 29 :
12, 11, // 30 | 31 : GPIO0_B4, GPIO0_B3
// EXT_PINS:
116, 117, 107, 108, // 32...35
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// 36...49
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 50...63
};
static const int phyToGpio[64] = {
// physical header pin number to native gpio number
-1, // 0
-1, -1, // 1 | 2 : 3.3V, 5.0V
110, -1, // 3 | 4 : GPIO3_B6, 5.0V
109, -1, // 5 | 6 : GPIO3_B5, GND
14, 68, // 7 | 8 : GPIO0_B6, GPIO2_A4
-1, 67, // 9 | 10 : GND, GPIO2_A3
16, 71, // 11 | 12 : GPIO0_C0, GPIO2_A7
17, -1, // 13 | 14 : GPIO0_C1, GND
18 , 77, // 15 | 16 : GPIO0_C2, GPIO2_B5
-1, 78, // 17 | 18 : 3.3V, GPIO2_B6
113, -1, // 19 | 20 : GPIO3_C1, GND
114, 72, // 21 | 22 : GPIO3_C2, GPIO2_B0
115, 97, // 23 | 24 : GPIO3_C3, GPIO3_A1
-1, 73, // 25 | 26 : GND, GPIO2_B1
12, 11, // 27 | 28 : GPIO0_B4, GPIO0_B3
80, -1, // 29 | 30 : GPIO2_C0, GND
79, 74, // 31 | 32 : GPIO2_B7, GPIO2_B2
13, -1, // 33 | 34 : GPIO0_B5, GND
69, 70, // 35 | 36 : GPIO2_A5, GPIO2_A6
-1, -1, // 37 | 38 : ADC.AIN1, 1.8V REF
-1, -1, // 39 | 40 : GND, ADC.AIN0
// Not used
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 41...50
// EXT_PINS
116, 117, 107, 108, // 51...54
// Not used
-1, -1, -1, -1, -1, -1, -1, -1, -1 // 55...63
};
static const char *pinToPwm[64] = {
// wiringPi number to pwm group number
"None", "None", // 0 | 1 : GPIO0_C0, GPIO2_A7
"None", "fdd70030", // 2 | 3 : GPIO0_C1, GPIO0_C2(PWM3)
"None", "None", // 4 | 5 : GPIO2_B5, GPIO2_B6
"None", "fdd70020", // 6 | 7 : GPIO2_B0, GPIO0_B6(PWM2)
"None", "None", // 8 | 9 : GPIO3_B6, GPIO3_B5
"None", "None", // 10 | 11 : GPIO3_A1, GPIO2_B1
"None", "None", // 12 | 13 : GPIO3_C1, GPIO3_C2
"None", "None", // 14 | 15 : GPIO3_C3, GPIO2_A4
"None", "None", // 16 | 17 : GPIO2_A3
"None", "None", // 18 | 19 :
"None", "None", // 20 | 21 : , GPIO2_C0
"None", "fdd70010", // 22 | 23 : GPIO2_B7, GPIO0_B5(PWM1)
"None", "None", // 24 | 25 : GPIO2_A5,
"None", "None", // 26 | 27 : GPIO2_B2, GPIO2_A6
"None", "None", // 28 | 29 :
"None", "None", // 30 | 31 : GPIO0_B4, GPIO0_B3
// Padding:
"None","None","None","None","None","None","None","None","None","None","None","None","None","None","None","None", // 32...47
"None","None","None","None","None","None","None","None","None","None","None","None","None","None","None","None" // 48...63
};
static const int pinToPwmNum[64] = {
// wiringPi number to pwm pin number
-1, -1, // 0 | 1 : GPIO0_C0, GPIO2_A7
-1, 2, // 2 | 3 : GPIO0_C1, GPIO0_C2(PWM3)
-1, -1, // 4 | 5 : GPIO2_B5, GPIO2_B6
-1, 1, // 6 | 7 : GPIO2_B0, GPIO0_B6(PWM2)
-1, -1, // 8 | 9 : GPIO3_B6, GPIO3_B5
-1, -1, // 10 | 11 : GPIO3_A1, GPIO2_B1
-1, -1, // 12 | 13 : GPIO3_C1, GPIO3_C2
-1, -1, // 14 | 15 : GPIO3_C3, GPIO2_A4
-1, -1, // 16 | 17 : GPIO2_A3
-1, -1, // 18 | 19 :
-1, -1, // 20 | 21 : , GPIO2_C0
-1, 0, // 22 | 23 : GPIO2_B7, GPIO0_B5(PWM1)
-1, -1, // 24 | 25 : GPIO2_A5,
-1, -1, // 26 | 27 : GPIO2_B2, GPIO2_A6
-1, -1, // 28 | 29 :
-1, -1, // 30 | 31 : GPIO0_B4, GPIO0_B3
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32...47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 48...63
};
static char pwmPinPath[10][(BLOCK_SIZE)] = {
"","",
"",
// Padding:
"None","None","None",
"None","None","None","None"
};
static char setupedPwmPinPath[10][BLOCK_SIZE] = {
"None","None",
"None","None",
"None","None",
"None","None",
"None","None"
};
/*----------------------------------------------------------------------------*/
//
// Global variable define
//
/*----------------------------------------------------------------------------*/
/* ADC file descriptor */
static int adcFds[2];
/* GPIO mmap control. Actual GPIO bank number. */
static volatile uint32_t *gpio[5];
/* GRF(General Register Files) base addresses to control GPIO modes */
static volatile uint32_t *grf[2];
/* CRU(Clock & Reset Unit) base addresses to control CLK mode */
static volatile uint32_t *cru[2];
/* wiringPi Global library */
static struct libodroid *lib = NULL;
/* pwm sysnode */
static DIR *pwm;
static struct dirent *pwmchip;
/* pwm params */
static char sysPwmPath[(BLOCK_SIZE / 4)];
static char pwmExport[(BLOCK_SIZE / 16)];
static char pwmUnexport[(BLOCK_SIZE / 16)];
static char pwmPeriod[(BLOCK_SIZE / 16)];
static char pwmDuty[(BLOCK_SIZE / 16)];
static unsigned int pwmClock;
static unsigned int pwmRange;
/*----------------------------------------------------------------------------*/
// Function prototype define
/*----------------------------------------------------------------------------*/
static int gpioToShiftRegBy32 (int pin);
static int gpioToShiftRegBy16 (int pin);
static void setClkState (int bank, int state);
static int setIomuxMode (int pin, int mode);
/*----------------------------------------------------------------------------*/
// Function of pwm define
/*----------------------------------------------------------------------------*/
static int pinToSysPwmPath (int pin);
static int pwmSetup (int pin);
static int pwmRelease (int pin);
/*----------------------------------------------------------------------------*/
// wiringPi core function
/*----------------------------------------------------------------------------*/
static int _getModeToGpio (int mode, int pin);
static int _pinMode (int pin, int mode);
static int _getDrive (int pin);
static int _setDrive (int pin, int value);
static int _getAlt (int pin);
static int _getPUPD (int pin);
static int _pullUpDnControl (int pin, int pud);
static int _digitalRead (int pin);
static int _digitalWrite (int pin, int value);
static int _pwmWrite (int pin, int value);
static int _analogRead (int pin);
static int _digitalWriteByte (const unsigned int value);
static unsigned int _digitalReadByte (void);
static void _pwmSetRange (unsigned int range);
static void _pwmSetClock (int divisor);
#if !defined(DEVMEM)
/*----------------------------------------------------------------------------*/
// libgpiod core function
/*----------------------------------------------------------------------------*/
static int _pinMode_gpiod (int pin, int mode);
static int _digitalRead_gpiod (int pin);
static int _digitalWrite_gpiod (int pin, int value);
static int _digitalWriteByte_gpiod (const unsigned int value);
static unsigned int _digitalReadByte_gpiod (void);
#endif
/*----------------------------------------------------------------------------*/
// board init function
/*----------------------------------------------------------------------------*/
static void init_gpio_mmap (void);
static void init_adc_fds (void);
void init_odroidm1s (struct libodroid *libwiring);
/*----------------------------------------------------------------------------*/
//
// for the offset to the GPIO bit
//
/*----------------------------------------------------------------------------*/
static int gpioToShiftRegBy32 (int pin)
{
return pin % 32;
}
/*----------------------------------------------------------------------------*/
//
// for the offset to the GPIO bit
//
/*----------------------------------------------------------------------------*/
static int gpioToShiftRegBy16 (int pin)
{
return pin % 16;
}
/*----------------------------------------------------------------------------*/
//
// config pwm sys path. "/sys/class/pwm/pwmchip?"
//
/*----------------------------------------------------------------------------*/
static int pinToSysPwmPath (int pin)
{
const char *pwmGroup;
char pwmLinkSrc[(BLOCK_SIZE / 8)];
char pwmPath[(BLOCK_SIZE / 8)];
int sz_link;
memset(pwmLinkSrc, 0, sizeof(pwmLinkSrc));
memset(pwmPath, 0, sizeof(pwmPath));
pwmGroup = pinToPwm[pin];
pwm = opendir("/sys/class/pwm");
if (pwm == NULL) {
printf("need to set device: pwm\n");
return -1;
}
while (1) {
pwmchip = readdir(pwm);
if (pwmchip == NULL) {
break;
}
if (strlen(pwmchip->d_name) <= 2)
continue;
sprintf(pwmPath, "%s/%s", "/sys/class/pwm", pwmchip->d_name);
sz_link = readlink(pwmPath, pwmLinkSrc, sizeof(pwmLinkSrc));
if (sz_link < 0) {
perror("Read symbolic link fail");
return sz_link;
}
if (strstr(pwmLinkSrc, pwmGroup) != NULL) {
strncpy(sysPwmPath, pwmPath, (sizeof(sysPwmPath) - 1));
break;
}
}
closedir(pwm);
return 0;
}
static int pwmSetup (int pin) {
char cmd[(BLOCK_SIZE * 2)];
int pwmPin, ret;
memset(cmd, 0, sizeof(cmd));
memset(pwmExport, 0, sizeof(pwmExport));
if ((ret = pinToSysPwmPath(pin)) < 0) {
perror("set pwm dtb overlays");
return ret;
}
if (strstr(sysPwmPath, "pwmchip") == NULL) {
printf("config pwm dtb overlays\n");
return -1;
}
pwmPin = pinToPwmNum[pin];
pwmClock = (M1_PWM_INTERNAL_CLK / 2);
sprintf(pwmExport, "%d", 0);
sprintf(pwmPinPath[pwmPin], "%s/pwm%d", sysPwmPath, 0);
strncpy(setupedPwmPinPath[pwmPin], pwmPinPath[pwmPin], (BLOCK_SIZE - 1));
#ifdef ANDROID
sprintf(cmd, "su -s sh -c %s %s", SYS_ACCESS_SCRIPT, pwmPinPath[pwmPin]);
#else
sprintf(cmd, "sudo sh %s %s", SYS_ACCESS_SCRIPT, pwmPinPath[pwmPin]);
#endif
inputToSysNode(sysPwmPath, "export", pwmExport);
system(cmd);
printf("PWM/pin%d: Don't change to gpio mode with overlay registered.\n", pin);
return 0;
}
static int pwmRelease (int pin) {
int pwmPin, ret;
if ((ret = pinToSysPwmPath(pin)) < 0) {
return ret;
}
if (strstr(sysPwmPath, "pwmchip") == NULL) {
return -1;
}
pwmPin = pinToPwmNum[pin];
sprintf(pwmUnexport, "%d", (pwmPin % 2));
sprintf(pwmPinPath[pwmPin], "%s/pwm%d", sysPwmPath, (pwmPin % 2));
if ((pwm = opendir(pwmPinPath[pwmPin])) != NULL) {
inputToSysNode(pwmPinPath[pwmPin], "enable", "0");
inputToSysNode(sysPwmPath, "unexport", pwmUnexport);
closedir(pwm);
}
return 0;
}
/*----------------------------------------------------------------------------*/
static int _getModeToGpio (int mode, int pin)
{
if (pin > 255)
return msg(MSG_ERR, "%s : Invalid pin number %d\n", __func__, pin);
switch (mode) {
/* Native gpio number */
case MODE_GPIO:
return pin;
/* Native gpio number for sysfs */
case MODE_GPIO_SYS:
return lib->sysFds[pin] != -1 ? pin : -1;
/* wiringPi number */
case MODE_PINS:
return pin < 64 ? pinToGpio[pin] : -1;
/* header pin number */
case MODE_PHYS:
return pin < 64 ? phyToGpio[pin] : -1;
default :
msg(MSG_WARN, "%s : Unknown Mode %d\n", __func__, mode);
return -1;
}
}
/*----------------------------------------------------------------------------*/
//
// set GPIO clock state
//
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static void setClkState (int bank, int state)
{
uint32_t data, regOffset;
uint8_t gpioPclkShift;
gpioPclkShift = (bank == 0 ? M1_PMU_CRU_GPIO_PCLK_BIT : (bank * M1_CRU_GPIO_PCLK_BIT));
regOffset = M1_PMU_CRU_GPIO_CLK_OFFSET;
// Once the final address/data of the register is determined, 'bank' is determined to be zero or not.
bank = (bank != 0);
data = *(cru[bank] + regOffset);
data &= ~(1 << gpioPclkShift);
data |= (state << gpioPclkShift);
data |= (1 << (gpioPclkShift + 16)); // write_mask
*(cru[bank] + regOffset) = data;
}
/*----------------------------------------------------------------------------*/
//
// set IOMUX mode
//
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int setIomuxMode (int pin, int mode)
{
uint32_t data, regOffset;
uint8_t bank, group, bankOffset, groupOffset;
if (lib->mode == MODE_GPIO_SYS)
return -1;
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE);
bankOffset = (pin - (bank * GPIO_SIZE));
group = (bankOffset / 8); // A or B or C or D
groupOffset = (pin % 8);
regOffset = (bank == 0 ? 0 : bank-1) * 0x8 + group * 0x2;
regOffset += (groupOffset / 4 == 0) ? 0x0 : 0x1;
regOffset += (bank == 0 ? M1_PMU_GRF_IOMUX_OFFSET : M1_SYS_GRF_IOMUX_OFFSET);
// Once the final address/data of the register is determined, 'bank' is determined to be zero or not.
bank = (bank != 0);
data = *(grf[bank] + regOffset);
// Common IOMUX Funtion 1 : GPIO (3'h0)
switch (mode) {
case M1_FUNC_GPIO: // Common IOMUX Function 1_GPIO (3'h0)
data &= ~(0x7 << ((groupOffset % 4) * 4)); // ~0x07 = 3'h0
data |= (0x7 << ((groupOffset % 4) * 4 + 16)); // write_mask
*(grf[bank] + regOffset) = data;
break;
default:
break;
}
return 0;
}
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _pinMode (int pin, int mode)
{
uint32_t data, regOffset;
uint8_t bank, bankOffset;
int origPin;
origPin = pin;
if (lib->mode == MODE_GPIO_SYS)
return -1;
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE);
bankOffset = (pin - (bank * GPIO_SIZE));
regOffset = (bankOffset / 16 == 0 ? M1_GPIO_DIR_OFFSET : M1_GPIO_DIR_OFFSET + 0x1);
pwmRelease(origPin);
softPwmStop(origPin);
softToneStop(origPin);
setClkState(bank, M1_CLK_ENABLE);
setIomuxMode(origPin, M1_FUNC_GPIO);
data = *(gpio[bank] + regOffset);
switch (mode) {
case INPUT:
case INPUT_PULLUP:
case INPUT_PULLDOWN:
_pullUpDnControl(origPin, mode);
__attribute__((fallthrough));
case OUTPUT:
mode = (mode == OUTPUT);
data &= ~(1 << gpioToShiftRegBy16(pin));
data |=(mode << gpioToShiftRegBy16(pin));
data |= (1 << (gpioToShiftRegBy16(pin) + 16)); // write_mask
*(gpio[bank] + regOffset) = data;
break;
case SOFT_PWM_OUTPUT:
softPwmCreate(origPin, 0, 100);
break;
case SOFT_TONE_OUTPUT:
softToneCreate(origPin);
break;
case PWM_OUTPUT:
pwmSetup(origPin);
break;
default:
msg(MSG_WARN, "%s : Unknown Mode %d\n", __func__, mode);
break;
}
return 0;
}
#if !defined(DEVMEM)
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _pinMode_gpiod (int pin, int mode)
{
uint8_t bank, bankOffset;
int origPin, ret;
origPin = pin;
if (lib->mode == MODE_GPIO_SYS)
return -1;
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE);
bankOffset = (pin - (bank * GPIO_SIZE));
pwmRelease(origPin);
softPwmStop(origPin);
softToneStop(origPin);
chip = gpiod_chip_open_by_number(bank);
if (!chip) {
return -1;
}
gpiod = gpiod_chip_get_line(chip, bankOffset);
if (!gpiod) {
printf("gpio get error\n");
gpiod_chip_close(chip);
return -1;
}
switch (mode) {
case INPUT:
case INPUT_PULLUP:
case INPUT_PULLDOWN:
ret = gpiod_line_request_input(gpiod, CONSUMER);
if (ret < 0) {
printf("gpiod request error\n");
gpiod_line_release(gpiod);
}
_pullUpDnControl(origPin, mode);
break;
case OUTPUT:
ret = gpiod_line_request_output(gpiod, CONSUMER, 0);
if (ret < 0) {
printf("gpiod request error\n");
gpiod_line_release(gpiod);
}
break;
case SOFT_PWM_OUTPUT:
softPwmCreate(origPin, 0, 100);
break;
case SOFT_TONE_OUTPUT:
softToneCreate(origPin);
break;
default:
msg(MSG_WARN, "%s : Unknown Mode %d\n", __func__, mode);
return -1;
}
gpiod_line_release(gpiod);
gpiod_chip_close(chip);
return 0;
}
#endif
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _getDrive(int pin)
{
uint32_t data, regOffset;
uint8_t bank, group, bankOffset, groupOffset;
int value = 0;
if (lib->mode == MODE_GPIO_SYS)
return -1;
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE);
bankOffset = (pin - (bank * GPIO_SIZE));
group = (bankOffset / 8);
groupOffset = (pin % 8);
regOffset = (bank == 0 ? M1_PMU_GRF_DS_OFFSET : M1_SYS_GRF_DS_OFFSET + ((bank - 1) * 0x10));
regOffset += (group * 0x4);
regOffset += ((groupOffset / 2) * 0x1);
// Once the final address/data of the register is determined, 'bank' is determined to be zero or not.
bank = (bank != 0);
data = *(grf[bank] + regOffset);
data &= 0x3f3f; //reset reserved bits
data = (groupOffset % 2 == 0 ? data & 0x3f : data >> 8);
switch (data) {
case DS_LEVEL_0:
value = 0;
break;
case DS_LEVEL_1:
value = 1;
break;
case DS_LEVEL_2:
value = 2;
break;
case DS_LEVEL_3:
value = 3;
break;
case DS_LEVEL_4:
value = 4;
break;
case DS_LEVEL_5:
value = 5;
break;
default:
value = -1;
break;
}
return value;
}
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _setDrive(int pin, int value)
{
uint32_t data, regOffset;
uint8_t bank, group, bankOffset, groupOffset;
if (lib->mode == MODE_GPIO_SYS)
return -1;
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE);
bankOffset = (pin - (bank * GPIO_SIZE));
group = (bankOffset / 8);
groupOffset = (pin % 8);
regOffset = (bank == 0 ? M1_PMU_GRF_DS_OFFSET : M1_SYS_GRF_DS_OFFSET + ((bank - 1) * 0x10));
regOffset += (group * 0x4);
regOffset += ((groupOffset / 2) * 0x1);
// Once the final address/data of the register is determined, 'bank' is determined to be zero or not.
bank = (bank != 0);
data = *(grf[bank] + regOffset);
data |= (0x3f3f << 16);
data &= ~(groupOffset % 2 == 0 ? 0x3f << 0 : 0x3f << 8);
switch (value) {
case 0:
data |= (groupOffset % 2 == 0 ? DS_LEVEL_0 : (DS_LEVEL_0 << 8));
break;
case 1:
data |= (groupOffset % 2 == 0 ? DS_LEVEL_1 : (DS_LEVEL_1 << 8));
break;
case 2:
data |= (groupOffset % 2 == 0 ? DS_LEVEL_2 : (DS_LEVEL_2 << 8));
break;
case 3:
data |= (groupOffset % 2 == 0 ? DS_LEVEL_3 : (DS_LEVEL_3 << 8));
break;
case 4:
data |= (groupOffset % 2 == 0 ? DS_LEVEL_4 : (DS_LEVEL_4 << 8));
break;
case 5:
data |= (groupOffset % 2 == 0 ? DS_LEVEL_5 : (DS_LEVEL_5 << 8));
break;
default:
break;
}
*(grf[bank] + regOffset) = data;
return 0;
}
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _getAlt (int pin)
{
// TODO: Working confirmed
uint32_t regOffset;
uint16_t ret = 0;
uint8_t bank, group, bankOffset, groupOffset, shift;
if (lib->mode == MODE_GPIO_SYS)
return -1;
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE); // GPIO0, GPIO1, ...
bankOffset = (pin - (bank * GPIO_SIZE));
group = (bankOffset / 8); // GPIO0_A, GPIO0_B, ...
groupOffset = (pin % 8);
// Move to the proper IOMUX register regardless of whether it is L, H.
regOffset = 0x8 * (bank == 0 ? 0x0 : bank - 1) + 0x2 * group;
// Check where the register this pin located in
regOffset += (groupOffset / 4 == 0) ? 0x0 : 0x1;
// The shift to move to the target pin at the register
shift = groupOffset % 4 * 4;
regOffset += (bank == 0 ? M1_PMU_GRF_IOMUX_OFFSET : M1_SYS_GRF_IOMUX_OFFSET);
ret = (*(grf[(bank != 0)] + regOffset) >> shift) & 0x7;
// If it is ALT0 (GPIO mode), check it's direction
// Add regOffset 0x4 to go to H register
// when the bit group is in the high two-bytes of the word size
if (ret == 0) {
if (bankOffset / 16 == 0)
regOffset = M1_GPIO_DIR_OFFSET;
else
regOffset = (M1_GPIO_DIR_OFFSET + 0x1);
ret = !!(*(gpio[bank] + regOffset) & (1 << gpioToShiftRegBy16(bankOffset)));
}
else {
// If it is alternative mode, add number 2 to fit into
// the alts[] array for "gpio readall" command
// Because the read number directly indicates the number of alt function
ret += 2;
}
return ret;
}
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _getPUPD (int pin)
{
uint32_t regOffset, pupd;
uint8_t bank, group, bankOffset, groupOffset;
if (lib->mode == MODE_GPIO_SYS)
return -1;
if ((pin = _getModeToGpio(lib->mode,pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE);
bankOffset = (pin - (bank * GPIO_SIZE));
group = (bankOffset / 8);
groupOffset = (pin % 8);
pupd = 0x00;
pupd = (0x3 << (groupOffset * 2));
regOffset = (bank == 0 ? M1_PMU_GRF_PUPD_OFFSET + (group * 0x1) : M1_SYS_GRF_PUPD_OFFSET + (group * 0x1) + ((bank - 1) * 0x4));
// Once the final address/data of the register is determined, 'bank' is determined to be zero or not.
bank = (bank != 0);
pupd &= *(grf[bank] + regOffset);
pupd = (pupd >> groupOffset * 2);
return pupd;
}
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _pullUpDnControl (int pin, int pud)
{
uint32_t data, regOffset;
uint8_t bank, group, bankOffset, groupOffset;
if (lib->mode == MODE_GPIO_SYS)
return -1;
if ((pin = _getModeToGpio(lib->mode, pin)) < 0) //exit
return -1;
bank = (pin / GPIO_SIZE);
bankOffset = (pin - (bank * GPIO_SIZE));
group = (bankOffset / 8);
groupOffset = (pin % 8);
regOffset = (bank == 0) ? M1_PMU_GRF_PUPD_OFFSET + (group * 0x1) : M1_SYS_GRF_PUPD_OFFSET + (group * 0x1) + ((bank - 1) * 0x4);
// Once the final address/data of the register is determined, 'bank' is determined to be zero or not.
bank = (bank != 0);
data = *(grf[bank] + regOffset);
data &= ~(0x3 << (groupOffset * 2));
switch (pud) {
case PUD_UP:
data |= (0x1 << (groupOffset * 2));
break;
case PUD_DOWN:
data |= (0x2 << (groupOffset * 2));
break;
case PUD_OFF:
break;
default:
/* No message */
break;
}
data |= (0x3 << ((groupOffset * 2) + 16)); // write_mask
*(grf[bank] + regOffset) = data;
return 0;
}
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _digitalRead (int pin)
{
uint8_t bank;
int ret;
char c;
if (lib->mode == MODE_GPIO_SYS) {
if (lib->sysFds[pin] == -1)
return -1;
lseek(lib->sysFds[pin], 0L, SEEK_SET);
if (read(lib->sysFds[pin], &c, 1) < 0) {
msg(MSG_WARN, "%s: Failed with reading from sysfs GPIO node. \n", __func__);
return -1;
}
return (c == '0') ? LOW : HIGH;
}
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE);
ret = *(gpio[bank] + M1_GPIO_GET_OFFSET) & (1 << gpioToShiftRegBy32(pin)) ? HIGH : LOW;
return ret;
}
#if !defined(DEVMEM)
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _digitalRead_gpiod (int pin)
{
uint8_t bank, bankOffset;
int ret;
char c;
if (lib->mode == MODE_GPIO_SYS) {
if (lib->sysFds[pin] == -1)
return -1;
lseek(lib->sysFds[pin], 0L, SEEK_SET);
if (read(lib->sysFds[pin], &c, 1) < 0) {
msg(MSG_WARN, "%s: Failed with reading from sysfs GPIO node. \n", __func__);
return -1;
}
return (c == '0') ? LOW : HIGH;
}
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE);
bankOffset = (pin - (bank * GPIO_SIZE));
chip = gpiod_chip_open_by_number(bank);
if (!chip) {
printf("chip open error\n");
return -1;
}
gpiod = gpiod_chip_get_line(chip,bankOffset);
if (!gpiod) {
printf("gpiod get error\n");
gpiod_chip_close(chip);
}
ret = gpiod_line_get_value(gpiod);
if (ret < 0) {
printf("gpiod get error\n");
gpiod_line_release(gpiod);
}
gpiod_line_release(gpiod);
gpiod_chip_close(chip);
return ret;
}
#endif
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _digitalWrite (int pin, int value)
{
uint32_t data, regOffset;
uint8_t bank, bankOffset;
if (lib->mode == MODE_GPIO_SYS) {
if (lib->sysFds[pin] != -1) {
if (value == LOW) {
if (write (lib->sysFds[pin], "0\n", 2) < 0)
msg(MSG_ERR,
"%s : %s\nEdit direction file to output mode for\n\t/sys/class/gpio/gpio%d/direction\n",
__func__, strerror(errno), pin + M1_GPIO_PIN_BASE);
} else {
if (write (lib->sysFds[pin], "1\n", 2) < 0)
msg(MSG_ERR,
"%s : %s\nEdit direction file to output mode for\n\t/sys/class/gpio/gpio%d/direction\n",
__func__, strerror(errno), pin + M1_GPIO_PIN_BASE);
}
}
return -1;
}
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE);
bankOffset = (pin - (bank * GPIO_SIZE));
regOffset = (bankOffset / 16 == 0 ? M1_GPIO_SET_OFFSET : M1_GPIO_SET_OFFSET + 0x01);
data = *(gpio[bank] + regOffset);
data &= ~(1 << gpioToShiftRegBy16(pin));
data |= (value << gpioToShiftRegBy16(pin));
data |= (1 << (gpioToShiftRegBy16(pin) + 16)); // write_mask
*(gpio[bank] + regOffset) = data;
return 0;
}
#if !defined(DEVMEM)
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _digitalWrite_gpiod (int pin, int value)
{
uint8_t bank,bankOffset;
int ret;
if (lib->mode == MODE_GPIO_SYS) {
if (lib->sysFds[pin] != -1) {
if (value == LOW) {
if (write (lib->sysFds[pin], "0\n", 2) < 0)
msg(MSG_ERR,
"%s : %s\nEdit direction file to output mode for\n\t/sys/class/gpio/gpio%d/direction\n",
__func__, strerror(errno), pin + M1_GPIO_PIN_BASE);
} else {
if (write (lib->sysFds[pin], "1\n", 2) < 0)
msg(MSG_ERR,
"%s : %s\nEdit direction file to output mode for\n\t/sys/class/gpio/gpio%d/direction\n",
__func__, strerror(errno), pin + M1_GPIO_PIN_BASE);
}
}
return -1;
}
if ((pin = _getModeToGpio(lib->mode, pin)) < 0)
return -1;
bank = (pin / GPIO_SIZE);
bankOffset = (pin - (bank * GPIO_SIZE));
chip = gpiod_chip_open_by_number(bank);
if (!chip) {
printf("chip open error\n");
return -1;
}
gpiod = gpiod_chip_get_line(chip, bankOffset);
if (!gpiod) {
printf("gpiod get error\n");
gpiod_chip_close(chip);
}
switch (value) {
case LOW:
ret = gpiod_line_set_value(gpiod, 0);
if (ret < 0) {
printf("gpiod set error\n");
gpiod_line_release(gpiod);
}
break;
case HIGH:
ret = gpiod_line_set_value(gpiod, 1);
if (ret < 0) {
printf("gpiod set error\n");
gpiod_line_release(gpiod);
}
break;
default:
break;
}
gpiod_line_release(gpiod);
gpiod_chip_close(chip);
return 0;
}
#endif
__attribute__ ((unused))static int _pwmWrite (int pin, int value)
{
unsigned int duty;
int pwmPin;
memset(pwmDuty, 0, sizeof(pwmDuty));
if (lib->mode == MODE_GPIO_SYS)
return -1;
if (((unsigned int)value > pwmRange) || (pwmRange <= 0)) {
printf("warn : pwm range value is greater than or equal pwmWrite's\n");
return -1;
}
pwmPin = pinToPwmNum[pin];
duty = ((value * 100) / pwmRange);
sprintf(pwmDuty, "%d", ((atoi(pwmPeriod) * duty) / 100));
inputToSysNode(pwmPinPath[pwmPin], "duty_cycle", pwmDuty);
return 0;
}
/*----------------------------------------------------------------------------*/
static int _analogRead (int pin)
{
char value[5] = {0, };
if (lib->mode == MODE_GPIO_SYS)
return -1;
/* wiringPi ADC number = pin 25, pin 29 */
switch (pin) {
#if defined(ARDUINO)
/* To work with physical analog channel numbering */
case 1: case 25:
pin = 0;
break;
case 0: case 29:
pin = 1;
break;
#else
case 0: case 25:
pin = 0;
break;
case 1: case 29:
pin = 1;
break;
#endif
default:
return 0;
}
if (adcFds [pin] == -1)
return 0;
lseek(adcFds [pin], 0L, SEEK_SET);
if (read(adcFds [pin], &value[0], 4) < 0) {
msg(MSG_WARN, "%s: Error occurs when it reads from ADC file descriptor. \n", __func__);
return -1;
}
return atoi(value);
}
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _digitalWriteByte (const unsigned int value)
{
union reg_bitfield gpio0;
union reg_bitfield gpio3;
if (lib->mode == MODE_GPIO_SYS) {
return -1;
}
setClkState(GPIO_SIZE * 0, M1_CLK_ENABLE);
setClkState(GPIO_SIZE * 3, M1_CLK_ENABLE);
/* Read data register */
gpio0.wvalue = *(gpio[0] + M1_GPIO_GET_OFFSET);
gpio3.wvalue = *(gpio[3] + M1_GPIO_GET_OFFSET);
/* Wiring PI GPIO0 = M1 GPIO0_C.0 */
gpio0.bits.bit16 = ((value & 0x01) >> 0);
/* Wiring PI GPIO1 = M1 GPIO3_D.0 */
gpio3.bits.bit24 = ((value & 0x02) >> 1);
/* Wiring PI GPIO2 = M1 GPIO0_C.1 */
gpio0.bits.bit17 = ((value & 0x04) >> 2);
/* Wiring PI GPIO3 = M1 GPIO3_B.2 */
gpio3.bits.bit10 = ((value & 0x08) >> 3);
/* Wiring PI GPIO4 = M1 GPIO3_C.6 */
gpio3.bits.bit22 = ((value & 0x10) >> 4);
/* Wiring PI GPIO5 = M1 GPIO3_C.7 */
gpio3.bits.bit23 = ((value & 0x20) >> 5);
/* Wiring PI GPIO6 = M1 GPIO3_D.1 */
gpio3.bits.bit25 = ((value & 0x40) >> 6);
/* Wiring PI GPIO7 = M1 GPIO0_B.6 */
gpio0.bits.bit14 = ((value & 0x80) >> 7);
/* Update data register */
*(gpio[0] + (M1_GPIO_SET_OFFSET + 0x1)) = (WRITE_BYTE_MASK_GPIO0_H | (gpio0.wvalue >> 16));
*(gpio[0] + M1_GPIO_SET_OFFSET) = (WRITE_BYTE_MASK_GPIO0_L | (gpio0.wvalue & 0xffff));
*(gpio[3] + (M1_GPIO_SET_OFFSET + 0x1)) = (WRITE_BYTE_MASK_GPIO3_H | (gpio3.wvalue >> 16));
*(gpio[3] + M1_GPIO_SET_OFFSET) = (WRITE_BYTE_MASK_GPIO3_L | (gpio3.wvalue & 0xffff));
return 0;
}
#if !defined(DEVMEM)
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static int _digitalWriteByte_gpiod (const unsigned int value)
{
static struct gpiod_chip *chip[2];
static struct gpiod_line *gpiodLines[8];
uint32_t unit=0x0;
int ret;
if (lib->mode == MODE_GPIO_SYS) {
return -1;
}
chip[0] = gpiod_chip_open_by_number(0);
chip[1] = gpiod_chip_open_by_number(3);
//gpiod get lines
/* Wiring PI GPIO0 = M1 GPIO0_C.0 */
gpiodLines[0] = gpiod_chip_get_line(chip[0], 16);
/* Wiring PI GPIO1 = M1 GPIO3_D.0 */
gpiodLines[1] = gpiod_chip_get_line(chip[1], 24);
/* Wiring PI GPIO2 = M1 GPIO0_C.1 */
gpiodLines[2] = gpiod_chip_get_line(chip[0], 17);
/* Wiring PI GPIO3 = M1 GPIO3_B.2 */
gpiodLines[3] = gpiod_chip_get_line(chip[1], 10);
/* Wiring PI GPIO4 = M1 GPIO3_C.6 */
gpiodLines[4] = gpiod_chip_get_line(chip[1], 22);
/* Wiring PI GPIO5 = M1 GPIO3_C.7 */
gpiodLines[5] = gpiod_chip_get_line(chip[1], 23);
/* Wiring PI GPIO6 = M1 GPIO3_D.1 */
gpiodLines[6] = gpiod_chip_get_line(chip[1], 25);
/* Wiring PI GPIO7 = M1 GPIO0_B.6 */
gpiodLines[7] = gpiod_chip_get_line(chip[0], 14);
for (int i = 0; i < 8; i++) {
if (!gpiodLines[i]) {
printf("gpiod get error pin:%d\n",i);
for (int j = 0; j < 2; j++)
gpiod_chip_close(chip[j]);
}
}
for (int i = 0; i < 8; i++) {
unit = (1 << i);
ret = gpiod_line_request_output(gpiodLines[i],CONSUMER,0);
if (ret < 0) {
printf("gpiod request error pin:%d\n" , i);
gpiod_line_release(gpiodLines[i]);
}
ret = gpiod_line_set_value(gpiodLines[i],((value & unit) >> i));
if (ret < 0) {
printf("gpiod set error pin:%d\n" , i);
gpiod_line_release(gpiodLines[i]);
}
}
for (int i = 0; i < 8; i++)
gpiod_line_release(gpiodLines[i]);
for (int i = 0; i < 2; i++)
gpiod_chip_close(chip[i]);
return 0;
}
#endif
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static unsigned int _digitalReadByte (void)
{
union reg_bitfield gpio0;
union reg_bitfield gpio3;
unsigned int value = 0;
if (lib->mode == MODE_GPIO_SYS) {
return -1;
}
setClkState(GPIO_SIZE * 0, M1_CLK_ENABLE);
setClkState(GPIO_SIZE * 3, M1_CLK_ENABLE);
/* Read data register */
gpio0.wvalue = *(gpio[0] + M1_GPIO_GET_OFFSET);
gpio3.wvalue = *(gpio[3] + M1_GPIO_GET_OFFSET);
/* Wiring PI GPIO0 = M1 GPIO0_C.0 */
if (gpio0.bits.bit16)
value |= 0x01;
/* Wiring PI GPIO1 = M1 GPIO3_D.0 */
if (gpio3.bits.bit24)
value |= 0x02;
/* Wiring PI GPIO2 = M1 GPIO0_C.1 */
if (gpio0.bits.bit17)
value |= 0x04;
/* Wiring PI GPIO3 = M1 GPIO3_B.2 */
if (gpio3.bits.bit10)
value |= 0x08;
/* Wiring PI GPIO4 = M1 GPIO3_C.6 */
if (gpio3.bits.bit22)
value |= 0x10;
/* Wiring PI GPIO5 = M1 GPIO3_C.7 */
if (gpio3.bits.bit23)
value |= 0x20;
/* Wiring PI GPIO6 = M1 GPIO3_D.1 */
if (gpio3.bits.bit25)
value |= 0x40;
/* Wiring PI GPIO7 = M1 GPIO0_B.6 */
if (gpio0.bits.bit14)
value |= 0x80;
return value;
}
#if !defined(DEVMEM)
/*----------------------------------------------------------------------------*/
__attribute__ ((unused))static unsigned int _digitalReadByte_gpiod (void)
{
static struct gpiod_chip *chip[2];
static struct gpiod_line *gpiodLines[8];
unsigned int value = 0;
uint32_t unit = 0x0;
int ret;
if (lib->mode == MODE_GPIO_SYS) {
return -1;
}
chip[0] = gpiod_chip_open_by_number(0);
chip[1] = gpiod_chip_open_by_number(3);
//gpiod get lines
/* Wiring PI GPIO0 = M1 GPIO0_C.0 */
gpiodLines[0] = gpiod_chip_get_line(chip[0], 16);
/* Wiring PI GPIO1 = M1 GPIO3_D.0 */
gpiodLines[1] = gpiod_chip_get_line(chip[1], 24);
/* Wiring PI GPIO2 = M1 GPIO0_C.1 */
gpiodLines[2] = gpiod_chip_get_line(chip[0], 17);
/* Wiring PI GPIO3 = M1 GPIO3_B.2 */
gpiodLines[3] = gpiod_chip_get_line(chip[1], 10);
/* Wiring PI GPIO4 = M1 GPIO3_C.6 */
gpiodLines[4] = gpiod_chip_get_line(chip[1], 22);
/* Wiring PI GPIO5 = M1 GPIO3_C.7 */
gpiodLines[5] = gpiod_chip_get_line(chip[1], 23);
/* Wiring PI GPIO6 = M1 GPIO3_D.1 */
gpiodLines[6] = gpiod_chip_get_line(chip[1], 25);
/* Wiring PI GPIO7 = M1 GPIO0_B.6 */
gpiodLines[7] = gpiod_chip_get_line(chip[0], 14);
for (int i = 0; i < 8; i++) {
if (!gpiodLines[i]) {
printf("gpiod get error pin:%d\n",i);
for (int j = 0; j < 2; j++)
gpiod_chip_close(chip[j]);
}
}
for (int i = 0; i < 8; i++) {
unit = (1 << i);
ret = gpiod_line_request_input(gpiodLines[i],CONSUMER);
if (ret < 0) {
printf("gpiod request error pin:%d\n",i);
gpiod_line_release(gpiodLines[i]);
}
ret = gpiod_line_get_value(gpiodLines[i]);
if (ret)
value |= unit;
}
for (int i = 0; i < 8; i++)
gpiod_line_release(gpiodLines[i]);
for (int i = 0; i < 2; i++)
gpiod_chip_close(chip[i]);
return value;
}
#endif
/*----------------------------------------------------------------------------*/
// PWM signal ___-----------___________---------------_______-----_
// <--value--> <----value---->
// <-------range--------><-------range-------->
// PWM frequency == (PWM clock) / range
/*----------------------------------------------------------------------------*/
static void _pwmSetRange (unsigned int range)
{
unsigned int freq, period;
memset(pwmPeriod, 0, sizeof(pwmPeriod));
if (lib->mode == MODE_GPIO_SYS)
return;
if (pwmClock < 2) {
printf("error : pwm freq: %dMHz / (pwmSetClock's value) >= 2\n",
(M1_PWM_INTERNAL_CLK / 2000000));
return;
}
pwmRange = range;
if ((pwmRange < 1) || (pwmRange >= pwmClock)) {
printf("error : invalid value. ( < pwm freq)\n");
return;
}
freq = (pwmClock / pwmRange);
period = (1000000000 / freq); // period: s to ns.
sprintf(pwmPeriod, "%d", period);
for (int i = 0; i < 10; i++) {
if (strstr(setupedPwmPinPath[i], "None") != NULL)
continue;
inputToSysNode(setupedPwmPinPath[i], "period", pwmPeriod);
inputToSysNode(setupedPwmPinPath[i], "polarity", "normal");
inputToSysNode(setupedPwmPinPath[i], "enable", "1");
}
}
/*----------------------------------------------------------------------------*/
// Internal clock: 12MHz
// PWM clock == (Internal clock) / divisor
// PWM frequency == (PWM clock) / range
/*----------------------------------------------------------------------------*/
static void _pwmSetClock (int divisor)
{
if (pwmClock > 0)
pwmClock = (pwmClock / divisor);
else {
printf("error : pwm mode error\n");
return;
}
}
/*----------------------------------------------------------------------------*/
static void init_gpio_mmap (void)
{
int fd = -1;
void *mapped_cru[2], *mapped_grf[2], *mapped_gpio[5];
/* GPIO mmap setup */
if (!getuid()) {
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0)
msg (MSG_ERR,
"wiringPiSetup: Unable to open /dev/mem: %s\n",
strerror (errno));
} else {
if (access("/dev/gpiomem",0) == 0) {
if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0)
msg (MSG_ERR,
"wiringPiSetup: Unable to open /dev/gpiomem: %s\n",
strerror (errno));
setUsingGpiomem(TRUE);
} else
msg (MSG_ERR,
"wiringPiSetup: /dev/gpiomem doesn't exist. Please try again with sudo.\n");
}
if (fd < 0) {
msg(MSG_ERR, "wiringPiSetup: Cannot open memory area for GPIO use. \n");
} else {
mapped_cru[0] = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, M1_PMU_CRU_BASE);
mapped_cru[1] = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, M1_CRU_BASE);
mapped_grf[0] = mmap(0, M1_GRF_BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, M1_PMU_GRF_BASE);
mapped_grf[1] = mmap(0, M1_GRF_BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, M1_SYS_GRF_BASE);
mapped_gpio[0] = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, M1_GPIO_0_BASE);
mapped_gpio[1] = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, M1_GPIO_1_BASE);
mapped_gpio[2] = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, M1_GPIO_2_BASE);
mapped_gpio[4] = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, M1_GPIO_4_BASE);
mapped_gpio[3] = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, M1_GPIO_3_BASE);
if ((mapped_cru[0] == MAP_FAILED) || (mapped_cru[1] == MAP_FAILED)) {
msg (MSG_ERR,"wiringPiSetup: mmap (CRU) failed: %s\n",strerror (errno));
} else {
cru[0] = (uint32_t *) mapped_cru[0];
cru[1] = (uint32_t *) mapped_cru[1];
}
if ((mapped_grf[0] == MAP_FAILED) || (mapped_grf[1] == MAP_FAILED)) {
msg (MSG_ERR,"wiringPiSetup: mmap (GRF) failed: %s\n",strerror (errno));
} else {
grf[0] = (uint32_t *) mapped_grf[0];
grf[1] = (uint32_t *) mapped_grf[1];
}
if ((mapped_gpio[0] == MAP_FAILED) ||
(mapped_gpio[1] == MAP_FAILED) ||
(mapped_gpio[2] == MAP_FAILED) ||
(mapped_gpio[3] == MAP_FAILED) ||
(mapped_gpio[4] == MAP_FAILED)) {
msg (MSG_ERR,
"wiringPiSetup: mmap (GPIO) failed: %s\n",
strerror (errno));
} else {
gpio[0] = (uint32_t *) mapped_gpio[0];
gpio[1] = (uint32_t *) mapped_gpio[1];
gpio[2] = (uint32_t *) mapped_gpio[2];
gpio[3] = (uint32_t *) mapped_gpio[3];
gpio[4] = (uint32_t *) mapped_gpio[4];
}
}
}
/*----------------------------------------------------------------------------*/
static void init_adc_fds (void)
{
const char *AIN0_NODE, *AIN1_NODE;
AIN0_NODE = "/sys/devices/platform/fe720000.saradc/iio:device0/in_voltage3_raw";
AIN1_NODE = "/sys/devices/platform/fe720000.saradc/iio:device0/in_voltage2_raw";
adcFds[0] = open(AIN0_NODE, O_RDONLY);
adcFds[1] = open(AIN1_NODE, O_RDONLY);
}
/*----------------------------------------------------------------------------*/
void init_odroidm1s (struct libodroid *libwiring)
{
init_gpio_mmap();
init_adc_fds();
#if defined(DEVMEM)
/* wiringPi Core function initialize */
libwiring->getModeToGpio = _getModeToGpio;
libwiring->pinMode = _pinMode;
libwiring->getAlt = _getAlt;
libwiring->getPUPD = _getPUPD;
libwiring->pullUpDnControl = _pullUpDnControl;
libwiring->getDrive = _getDrive;
libwiring->setDrive = _setDrive;
libwiring->digitalRead = _digitalRead;
libwiring->digitalWrite = _digitalWrite;
libwiring->analogRead = _analogRead;
libwiring->digitalWriteByte = _digitalWriteByte;
libwiring->digitalReadByte = _digitalReadByte;
libwiring->pwmWrite = _pwmWrite;
libwiring->pwmSetRange = _pwmSetRange;
libwiring->pwmSetClock = _pwmSetClock;
#else
/* wiringPi-libgpiod Core function initialize */
libwiring->getModeToGpio = _getModeToGpio;
libwiring->pinMode = _pinMode_gpiod;
libwiring->getAlt = _getAlt;
libwiring->getPUPD = _getPUPD;
libwiring->pullUpDnControl = _pullUpDnControl;
libwiring->getDrive = _getDrive;
libwiring->setDrive = _setDrive;
libwiring->digitalRead = _digitalRead_gpiod;
libwiring->digitalWrite = _digitalWrite_gpiod;
libwiring->analogRead = _analogRead;
libwiring->digitalWriteByte = _digitalWriteByte_gpiod;
libwiring->digitalReadByte = _digitalReadByte_gpiod;
#endif
/* specify pin base number */
libwiring->pinBase = M1_GPIO_PIN_BASE;
/* global variable setup */
lib = libwiring;
}
/*----------------------------------------------------------------------------*/