aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJanne Grunau <janne-gh@jannau.net>2020-05-03 17:24:42 +0200
committerGitHub <noreply@github.com>2020-05-03 11:24:42 -0400
commit0aa78ec76ed4efac9698eda06e11758c70c65876 (patch)
tree2628fa2406687384e9d6c5d100fe71f9b3da5b82
parentdb732e58db52e27d6095d69fec4db5d69871e88e (diff)
downloadkutter-0aa78ec76ed4efac9698eda06e11758c70c65876.tar.gz
kutter-0aa78ec76ed4efac9698eda06e11758c70c65876.tar.xz
kutter-0aa78ec76ed4efac9698eda06e11758c70c65876.zip
linux: Adapt servo0 channels for beagleboard kernel 4.14.108-ti (#2746)
The beagleboard TI kernel 4.14 and 4.19 contain a commit which change the device names ("pwm: Create device class for pwm channels") from pwmN to pwm-${chip}:N. This commit was never merged into the upstream kernel. Decrease the number of pwm channels to a more reasonable 16. Increase the number of pwm chips to 8 since the replicape servo pwm outputs are on pwmchip4. Update replicape code to detect appropriate channel. Signed-off-by: Janne Grunau <janne-gh@jannau.net>
-rw-r--r--klippy/extras/replicape.py20
-rw-r--r--src/linux/hard_pwm.c41
2 files changed, 46 insertions, 15 deletions
diff --git a/klippy/extras/replicape.py b/klippy/extras/replicape.py
index 6817a051..5938502e 100644
--- a/klippy/extras/replicape.py
+++ b/klippy/extras/replicape.py
@@ -108,16 +108,30 @@ class ReplicapeDACEnable:
self.pwm.set_pwm(print_time, 0.)
SERVO_PINS = {
- "servo0": ("pwmchip0/pwm0", "gpio0_30", "gpio1_18"), # P9_11, P9_14
- "servo1": ("pwmchip0/pwm1", "gpio3_17", "gpio1_19"), # P9_28, P9_16
+ "servo0": ("/pwm0", "gpio0_30", "gpio1_18"), # P9_11, P9_14
+ "servo1": ("/pwm1", "gpio3_17", "gpio1_19"), # P9_28, P9_16
}
class servo_pwm:
def __init__(self, replicape, pin_params):
config_name = pin_params['pin']
+ pwmchip = 'pwmchip0'
+ if not replicape.host_mcu.is_fileoutput():
+ try:
+ # Determine the pwmchip number for the servo channels
+ # /sys/devices/platform/ocp/48302000.epwmss/48302200.pwm/pwm
+ # should be stable on the beagle bone black.
+ # It contains only a "pwmchipX" directory. The entry in
+ # /sys/class/pwm/ used by the Linux MCU should be a symlink
+ # to this directory.
+ pwmdev = os.listdir(
+ '/sys/devices/platform/ocp/48302000.epwmss/48302200.pwm/pwm/')
+ pwmchip = [pc for pc in pwmdev if pc.startswith('pwmchip')][0]
+ except:
+ raise pins.error("Replicape unable to determine pwmchip")
pwm_pin, resv1, resv2 = SERVO_PINS[config_name]
pin_params = dict(pin_params)
- pin_params['pin'] = pwm_pin
+ pin_params['pin'] = pwmchip + pwm_pin
# Setup actual pwm pin using linux hardware pwm on host
self.mcu_pwm = replicape.host_mcu.setup_pin("pwm", pin_params)
self.get_mcu = self.mcu_pwm.get_mcu
diff --git a/src/linux/hard_pwm.c b/src/linux/hard_pwm.c
index 25bfb2e7..f14b844b 100644
--- a/src/linux/hard_pwm.c
+++ b/src/linux/hard_pwm.c
@@ -10,6 +10,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <errno.h> // errno, ENOENT
#include "gpio.h" // struct gpio_pwm
#include "internal.h" // NSECS_PER_TICK
@@ -20,16 +21,21 @@
DECL_CONSTANT("PWM_MAX", MAX_PWM);
#define HARD_PWM_START (1<<16)
-#define HARD_PWM(chip, pin) (((chip)<<8) + (pin) + HARD_PWM_START)
-#define HARD_PWM_TO_CHIP(hard_pwm) (((hard_pwm) - HARD_PWM_START) >> 8)
-#define HARD_PWM_TO_PIN(hard_pwm) (((hard_pwm) - HARD_PWM_START) & 0xff)
+#define HARD_PWM(chip, pin) (((chip)<<4) + (pin) + HARD_PWM_START)
+#define HARD_PWM_TO_CHIP(hard_pwm) (((hard_pwm) - HARD_PWM_START) >> 4)
+#define HARD_PWM_TO_PIN(hard_pwm) (((hard_pwm) - HARD_PWM_START) & 0xf)
-DECL_ENUMERATION_RANGE("pin", "pwmchip0/pwm0", HARD_PWM(0, 0), 256);
-DECL_ENUMERATION_RANGE("pin", "pwmchip1/pwm0", HARD_PWM(1, 0), 256);
-DECL_ENUMERATION_RANGE("pin", "pwmchip2/pwm0", HARD_PWM(2, 0), 256);
-DECL_ENUMERATION_RANGE("pin", "pwmchip3/pwm0", HARD_PWM(3, 0), 256);
+DECL_ENUMERATION_RANGE("pin", "pwmchip0/pwm0", HARD_PWM(0, 0), 16);
+DECL_ENUMERATION_RANGE("pin", "pwmchip1/pwm0", HARD_PWM(1, 0), 16);
+DECL_ENUMERATION_RANGE("pin", "pwmchip2/pwm0", HARD_PWM(2, 0), 16);
+DECL_ENUMERATION_RANGE("pin", "pwmchip3/pwm0", HARD_PWM(3, 0), 16);
+DECL_ENUMERATION_RANGE("pin", "pwmchip4/pwm0", HARD_PWM(4, 0), 16);
+DECL_ENUMERATION_RANGE("pin", "pwmchip5/pwm0", HARD_PWM(5, 0), 16);
+DECL_ENUMERATION_RANGE("pin", "pwmchip6/pwm0", HARD_PWM(6, 0), 16);
+DECL_ENUMERATION_RANGE("pin", "pwmchip7/pwm0", HARD_PWM(7, 0), 16);
#define PWM_PATH "/sys/class/pwm/pwmchip%u/pwm%u/%s"
+#define PWM_PATH_BB "/sys/class/pwm/pwm-%u:%u/%s"
struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint16_t val)
{
@@ -37,15 +43,26 @@ struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint16_t val)
char scratch[16];
uint8_t chip_id = HARD_PWM_TO_CHIP(pin);
uint8_t pwm_id = HARD_PWM_TO_PIN(pin);
+ const char * pwm_path = PWM_PATH;
struct gpio_pwm g = {};
g.period = cycle_time * NSECS_PER_TICK;
// configure period/cycle time. Always in nanoseconds
- snprintf(filename, sizeof(filename), PWM_PATH, chip_id, pwm_id, "period");
+ snprintf(filename, sizeof(filename), pwm_path, chip_id, pwm_id, "period");
int fd = open(filename, O_WRONLY|O_CLOEXEC);
- if (fd == -1) {
- report_errno("pwm period", fd);
+ if (fd == -1 && errno == ENOENT) {
+ // upstream pwm control file does not exists try BeagleBoard scheme
+ pwm_path = PWM_PATH_BB;
+ snprintf(filename, sizeof(filename), pwm_path, chip_id, pwm_id,
+ "period");
+ fd = open(filename, O_WRONLY|O_CLOEXEC);
+ if (fd == -1) {
+ report_errno("pwm " PWM_PATH_BB "period for pin", pin);
+ goto fail;
+ }
+ } else if (fd == -1) {
+ report_errno("pwm " PWM_PATH "period for pin", pin);
goto fail;
}
snprintf(scratch, sizeof(scratch), "%u", cycle_time * NSECS_PER_TICK);
@@ -53,7 +70,7 @@ struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint16_t val)
close(fd);
// write duty cycle
- snprintf(filename, sizeof(filename), PWM_PATH, chip_id, pwm_id,
+ snprintf(filename, sizeof(filename), pwm_path, chip_id, pwm_id,
"duty_cycle");
fd = open(filename, O_WRONLY|O_CLOEXEC);
if (fd == -1) {
@@ -65,7 +82,7 @@ struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint16_t val)
gpio_pwm_write(g, val);
// enable PWM
- snprintf(filename, sizeof(filename), PWM_PATH, chip_id, pwm_id, "enable");
+ snprintf(filename, sizeof(filename), pwm_path, chip_id, pwm_id, "enable");
fd = open(filename, O_WRONLY|O_CLOEXEC);
if (fd == -1) {
close(g.fd);