Skip to content

Commit

Permalink
add pwm api for milkv duo
Browse files Browse the repository at this point in the history
  • Loading branch information
carbonfix committed May 28, 2024
1 parent c511029 commit 5221879
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/platform/milkv/duo.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ void milkv_duoInit(void) {

milkv_duo->setup = &milkv_duoSetup;
milkv_duo->validGPIO = &milkv_duoValidGPIO;

milkv_duo->pwmSetPeriod = milkv_duo->soc->socSetPWMPeriod;
milkv_duo->pwmSetDuty = milkv_duo->soc->socSetPWMDuty;
milkv_duo->pwmSetPolarity = milkv_duo->soc->socSetPWMPolarity;
milkv_duo->pwmEnable = milkv_duo->soc->socEnablePWM;
}
4 changes: 4 additions & 0 deletions src/platform/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ void platform_register(struct platform_t **platform, char *name) {
(*platform)->waitForInterrupt = NULL;
(*platform)->isr = NULL;
(*platform)->selectableFd = NULL;
(*platform)->pwmSetPeriod = NULL;
(*platform)->pwmSetDuty = NULL;
(*platform)->pwmSetPolarity = NULL;
(*platform)->pwmEnable = NULL;
(*platform)->validGPIO = NULL;
(*platform)->gc = NULL;

Expand Down
5 changes: 4 additions & 1 deletion src/platform/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ typedef struct platform_t {
int (*waitForInterrupt)(int, int);
int (*isr)(int, enum isr_mode_t);
int (*selectableFd)(int);

int (*pwmSetPeriod)(int, long);
int (*pwmSetDuty)(int, long);
int (*pwmSetPolarity)(int, int);
int (*pwmEnable)(int, int);
int (*validGPIO)(int);
int (*gc)(void);

Expand Down
5 changes: 5 additions & 0 deletions src/soc/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ typedef struct soc_t {
void (*setIRQ)(int *, size_t size);
char *(*getPinName)(int);

int (*socSetPWMPeriod)(int, long);
int (*socSetPWMDuty)(int, long);
int (*socSetPWMPolarity)(int, int);
int (*socEnablePWM)(int, int);

int (*validGPIO)(int);
int (*selectableFd)(int);
int (*gc)(void);
Expand Down
224 changes: 224 additions & 0 deletions src/soc/sophgo/cv180x.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@

#define CV180X_GPIO_GROUP_COUNT 4

static int pin_pwm[12][2] = {
{2, 10}, // GP2 -> PWM10
{3, 11}, // GP3 -> PWM11
{4, 5}, // GP4 -> PWM5
{5, 6}, // GP5 -> PWM6
{6, 9}, // GP6 -> PWM9
{7, 8}, // GP7 -> PWM8
{8, 7}, // GP8 -> PWM7
{9, 4}, // GP9 -> PWM4
{12, 4}, // GP12 -> PWM4
{13, 5} // GP13 -> PWM5
};

struct soc_t *cv180x = NULL;

static struct layout_t {
Expand Down Expand Up @@ -415,6 +428,212 @@ static int cv180xSelectableFd(int i) {
return pin->fd;
}

int cv180x_sysfs_pwm_set_long(struct soc_t *soc, char *path, long value) {
char out[16];
int fd = 0;
if((fd = open(path, O_WRONLY)) <= 0) {
wiringXLog(LOG_ERR, "The %s %s cannot open %s for PWM (%s)", soc->brand, soc->chip, path, strerror(errno));
return -1;
}
int l = snprintf(out, 16, "%ld", value);
if (write(fd, out, l) != l) {
wiringXLog(LOG_ERR, "The %s %s failed to write to %s for PWM (%s)", soc->brand, soc->chip, path, strerror(errno));
close(fd);
return -1;
}
close(fd);

return 0;
}

int cv180x_sysfs_pwm_set_string(struct soc_t *soc, char *path, char *str) {
int fd = 0;
if ((fd = open(path, O_WRONLY)) <= 0) {
wiringXLog(LOG_ERR, "The %s %s cannot open %s for PWM (%s)", soc->brand, soc->chip, path, strerror(errno));
return -1;
}
int l = strlen(str);
if (write(fd, str, l) != l) {
wiringXLog(LOG_ERR, "The %s %s failed to write to %s for PWM (%s)", soc->brand, soc->chip, path, strerror(errno));
close(fd);
return -1;
}
close(fd);

return 0;
}

/*
index | 0 1 2 3
----------+-------------------------
pwmchip0 -> pwm0, pwm1, pwm2, pwm3
pwmchip4 -> pwm4, pwm5, pwm6, pwm7
pwmchip8 -> pwm8, pwm9, pwm10,pwm11
pwmchip12 -> pwm12,pwm13,pwm14,pwm15
*/
static int cv180x_get_pwm(int pin, int *chip, int *index) {
int i;
int found = 0;
int pwm;

for (i = 0; i < 12; i++) {
if (pin == pin_pwm[i][0]) {
found = 1;
pwm = pin_pwm[i][1];
break;
}
}

if (found == 0) {
wiringXLog(LOG_ERR, "GP%d is not a PWM pin", pin);
return -1;
}

if (pwm < 4 || pwm > 11) {
wiringXLog(LOG_ERR, "pwm %d not supported", pwm);
return -1;
}

//wiringXLog(LOG_INFO, "GP%d is PWM%d", pin, pwm);

*chip = (pwm / 4) * 4;
*index = pwm % 4;

return pwm;
}

static int cv180xSetPWMPeriod(int pin, long period) {
int chip = 0;
int index = 0;
char path[PATH_MAX];
int pwm = cv180x_get_pwm(pin, &chip, &index);

if (pwm < 0) {
wiringXLog(LOG_ERR, "[%s:%d] get pwm for pin(%d) failed!", __func__, __LINE__, pin);
return -1;
}

memset(path, 0, sizeof(path));

//wiringXLog(LOG_INFO, "[%s:%d], GP%d/PWM%d(chip:%d,index:%d), period: %ld", __func__, __LINE__, pin, pwm, chip, index, period);

sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d", chip, index);
if ((soc_sysfs_check_gpio(cv180x, path)) == -1) {
sprintf(path, "/sys/class/pwm/pwmchip%d/export", chip);
if (soc_sysfs_gpio_export(cv180x, path, index) == -1) {
return -1;
}
}

sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d/period", chip, index);
if (cv180x_sysfs_pwm_set_long(cv180x, path, period) == -1) {
return -1;
}

return 0;
}

static int cv180xSetPWMDuty(int pin, long duty_cycle) {
int chip = 0;
int index = 0;
char path[PATH_MAX];
int pwm = cv180x_get_pwm(pin, &chip, &index);

if (pwm < 0) {
wiringXLog(LOG_ERR, "[%s:%d] get pwm for pin(%d) failed!", __func__, __LINE__, pin);
return -1;
}

//wiringXLog(LOG_INFO, "[%s:%d], GP%d/PWM%d(chip:%d,index:%d), duty_cycle: %ld", __func__, __LINE__, pin, pwm, chip, index, duty_cycle);

sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d", chip, index);
if ((soc_sysfs_check_gpio(cv180x, path)) == -1) {
sprintf(path, "/sys/class/pwm/pwmchip%d/export", chip);
if (soc_sysfs_gpio_export(cv180x, path, index) == -1) {
return -1;
}
}

sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d/duty_cycle", chip, index);
if (cv180x_sysfs_pwm_set_long(cv180x, path, duty_cycle) == -1) {
return -1;
}

return 0;
}

/*
0 - normal
1 - inversed
*/
static int cv180xSetPWMPolarity(int pin, int polarity) {
int chip = 0;
int index = 0;
char path[PATH_MAX];
char polarity_str[16];
int pwm = cv180x_get_pwm(pin, &chip, &index);

if (pwm < 0) {
wiringXLog(LOG_ERR, "[%s:%d] get pwm for pin(%d) failed!", __func__, __LINE__, pin);
return -1;
}

memset(path, 0, sizeof(path));

//wiringXLog(LOG_INFO, "[%s:%d], GP%d/PWM%d(chip:%d,index:%d), polarity: %ld", __func__, __LINE__, pin, pwm, chip, index, polarity);

sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d", chip, index);
if ((soc_sysfs_check_gpio(cv180x, path)) == -1) {
sprintf(path, "/sys/class/pwm/pwmchip%d/export", chip);
if(soc_sysfs_gpio_export(cv180x, path, index) == -1) {
return -1;
}
}

sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d/polarity", chip, index);

if (polarity == 0) {
sprintf(polarity_str, "normal");
} else {
sprintf(polarity_str, "inversed");
}

if (cv180x_sysfs_pwm_set_string(cv180x, path, polarity_str) == -1) {
return -1;
}

return 0;
}

static int cv180xEnablePWM(int pin, int enable) {
int chip = 0;
int index = 0;
char path[PATH_MAX];
int pwm = cv180x_get_pwm(pin, &chip, &index);

if (pwm < 0) {
wiringXLog(LOG_ERR, "[%s:%d] get pwm for pin(%d) failed!", __func__, __LINE__, pin);
return -1;
}

//wiringXLog(LOG_INFO, "[%s:%d], GP%d/PWM%d(chip:%d,index:%d), enable: %ld", __func__, __LINE__, pin, pwm, chip, index, enable);

sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d", chip, index);
if ((soc_sysfs_check_gpio(cv180x, path)) == -1) {
sprintf(path, "/sys/class/pwm/pwmchip%d/export", chip);
if (soc_sysfs_gpio_export(cv180x, path, index) == -1) {
return -1;
}
}

sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d/enable", chip, index);
if (cv180x_sysfs_pwm_set_long(cv180x, path, enable) == -1) {
return -1;
}

return 0;
}

void cv180xInit(void) {
soc_register(&cv180x, "Sophgo", "CV180X");

Expand All @@ -435,4 +654,9 @@ void cv180xInit(void) {
cv180x->setIRQ = &cv180xSetIRQ;
cv180x->isr = &cv180xISR;
cv180x->waitForInterrupt = &cv180xWaitForInterrupt;

cv180x->socSetPWMPeriod = &cv180xSetPWMPeriod;
cv180x->socSetPWMDuty = &cv180xSetPWMDuty;
cv180x->socSetPWMPolarity = &cv180xSetPWMPolarity;
cv180x->socEnablePWM = &cv180xEnablePWM;
}
44 changes: 44 additions & 0 deletions src/wiringx.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,50 @@ EXPORT int wiringXSerialGetChar(int fd) {
}
}

EXPORT int wiringXPWMSetPeriod(int pin, long period) {
if (platform == NULL) {
wiringXLog(LOG_ERR, "wiringX has not been properly setup (no platform has been selected)");
return -1;
} else if (platform->pwmSetPeriod == NULL) {
wiringXLog(LOG_ERR, "The %s does not support the pwmSetPeriod functionality", platform->name[namenr]);
return -1;
}
return platform->pwmSetPeriod(pin, period);
}

EXPORT int wiringXPWMSetDuty(int pin, long duty_cycle) {
if (platform == NULL) {
wiringXLog(LOG_ERR, "wiringX has not been properly setup (no platform has been selected)");
return -1;
} else if (platform->pwmSetDuty == NULL) {
wiringXLog(LOG_ERR, "The %s does not support the pwmSetDuty functionality", platform->name[namenr]);
return -1;
}
return platform->pwmSetDuty(pin, duty_cycle);
}

EXPORT int wiringXPWMSetPolarity(int pin, int polarity) {
if (platform == NULL) {
wiringXLog(LOG_ERR, "wiringX has not been properly setup (no platform has been selected)");
return -1;
} else if (platform->pwmSetPolarity == NULL) {
wiringXLog(LOG_ERR, "The %s does not support the pwmSetPolarity functionality", platform->name[namenr]);
return -1;
}
return platform->pwmSetPolarity(pin, polarity);
}

EXPORT int wiringXPWMEnable(int pin, int enable) {
if (platform == NULL) {
wiringXLog(LOG_ERR, "wiringX has not been properly setup (no platform has been selected)");
return -1;
} else if (platform->pwmEnable == NULL) {
wiringXLog(LOG_ERR, "The %s does not support the pwmEnable functionality", platform->name[namenr]);
return -1;
}
return platform->pwmEnable(pin, enable);
}

EXPORT int wiringXSelectableFd(int gpio) {
if(platform == NULL) {
wiringXLog(LOG_ERR, "wiringX has not been properly setup (no platform has been selected)");
Expand Down
5 changes: 5 additions & 0 deletions src/wiringx.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ void wiringXSerialPrintf(int, const char *, ...);
int wiringXSerialDataAvail(int);
int wiringXSerialGetChar(int);

int wiringXPWMSetPeriod(int, long);
int wiringXPWMSetDuty(int, long);
int wiringXPWMSetPolarity(int, int);
int wiringXPWMEnable(int, int);

char *wiringXPlatform(void);
int wiringXValidGPIO(int);
int wiringXSelectableFd(int);
Expand Down

0 comments on commit 5221879

Please sign in to comment.