From 4e480f036845103950fd0a1559d38073a09fdc75 Mon Sep 17 00:00:00 2001 From: efargas Date: Tue, 15 Sep 2015 21:01:17 +0200 Subject: [PATCH 1/3] PWM period control Applied patch from https://github.com/avterekhov/bb-pwm/, tested and working on 3.8.13 branch --- drivers/pwm/pwm-tiehrpwm.c | 44 ++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index af6f1625d255f..836592debd0c5 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -225,6 +225,7 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, unsigned long period_cycles, duty_cycles; unsigned short ps_divval, tb_divval; int i, cmp_reg; + struct pwm_device *pwm_alter; /* In case period changes */ if (period_ns > NSEC_PER_SEC) return -ERANGE; @@ -244,26 +245,41 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, duty_cycles = (unsigned long)c; } + /* * Period values should be same for multiple PWM channels as IP uses - * same period register for multiple channels. + * same period register for multiple channels. Check if there is any with + * a different period. */ - for (i = 0; i < NUM_PWM_CHANNEL; i++) { - if (pc->period_cycles[i] && - (pc->period_cycles[i] != period_cycles)) { - /* - * Allow channel to reconfigure period if no other - * channels being configured. - */ - if (i == pwm->hwpwm) + if (pc->period_cycles[pwm->hwpwm] != period_cycles) { + for (i = 0; i < NUM_PWM_CHANNEL; i++) { + if (pc->period_cycles[i]) { + pwm_alter = &chip->pwms[i]; + if (pwm_alter->duty > period_ns) { + dev_err(chip->dev, "Duty is larger than period"); + return -EINVAL; + } + } + } + if (!pc->period_cycles[pwm->hwpwm]) + pc->period_cycles[pwm->hwpwm] = period_cycles; + for (i = 0; i < NUM_PWM_CHANNEL; i++) { + if (pc->period_cycles[i]) + pc->period_cycles[i] = period_cycles; + } + for (i = 0; i < NUM_PWM_CHANNEL; i++) { + if (i == pwm->hwpwm) /* No need to run for itself */ continue; - - dev_err(chip->dev, "Period value conflicts with channel %d\n", - i); - return -EINVAL; + if (pc->period_cycles[i]) { + pwm_alter = &chip->pwms[i]; + if (ehrpwm_pwm_config(chip, pwm_alter, pwm_alter->duty, period_ns)) { + dev_err(chip->dev, "Something went seriously wrong"); + return -EINVAL; + } + pwm_alter->period = period_ns; + } } } - pc->period_cycles[pwm->hwpwm] = period_cycles; /* Configure clock prescaler to support Low frequency PWM wave */ From 02fe86e7078caf74fd3e8f135e3497df2b57e1c2 Mon Sep 17 00:00:00 2001 From: efargas Date: Tue, 15 Sep 2015 21:04:42 +0200 Subject: [PATCH 2/3] PWM period control Applied patch from https://github.com/avterekhov/bb-pwm/ testes and workin on 3.8.13 branch --- drivers/pwm/pwm_test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm_test.c b/drivers/pwm/pwm_test.c index 9c07880c547bf..7b5005220f58e 100644 --- a/drivers/pwm/pwm_test.c +++ b/drivers/pwm/pwm_test.c @@ -41,7 +41,7 @@ static ssize_t pwm_test_show_duty(struct device *dev, struct device_attribute *attr, char *buf) { struct pwm_test *pwm_test = dev_get_drvdata(dev); - + pwm_test->duty = pwm_test->pwm->duty; return sprintf(buf, "%d\n", pwm_test->duty); } @@ -65,7 +65,7 @@ static ssize_t pwm_test_store_duty(struct device *dev, return rc; } - pwm_test->duty = duty; + pwm_test->duty = pwm_test->pwm->duty; return count; } @@ -74,7 +74,7 @@ static ssize_t pwm_test_show_period(struct device *dev, struct device_attribute *attr, char *buf) { struct pwm_test *pwm_test = dev_get_drvdata(dev); - + pwm_test->period = pwm_test->pwm->period; return sprintf(buf, "%d\n", pwm_test->period); } @@ -102,7 +102,7 @@ static ssize_t pwm_test_store_period(struct device *dev, return rc; } - pwm_test->period = period; + pwm_test->period = pwm_test->pwm->period; return count; } From 4b82759831dd401350ffaa6f4f969a278941e0f4 Mon Sep 17 00:00:00 2001 From: efargas Date: Tue, 15 Sep 2015 22:44:07 +0200 Subject: [PATCH 3/3] Updated defines to fully work with BeagleBone DTS EXAMPLE /dts-v1/; /plugin/; / { compatible = "ti,beaglebone", "ti,beaglebone-black"; /* identification */ part-number = "BB-PCA9555-20"; version = "00A0"; /* state the resources this cape uses */ exclusive-use = /* the pin header uses */ "P8.8", /* pca9555 irq: gpio2_3 */ /* the hardware ip uses */ "gpio2_3"; fragment@0 { target = <&am33xx_pinmux>; __overlay__ { pca9555_irq_pin: pinmux_pca9555_irq_pin { pinctrl-single,pins = < 0x094 0x37 /* gpmc_oen_ren.gpio2_3 INPUT | PULLUP | MODE7 */ >; }; }; }; fragment@1 { target = <&i2c2>; __overlay__ { #address-cells = <1>; #size-cells = <0>; pca9555: pca9555@20 { compatible = "nxp,pca9555"; reg = <0x20>; pinctrl-0 = <&pca9555_irq_pin>; interrupt-parent = <&gpio3>; interrupts = <3 0x2>; irg-gpio = <&gpio3 3 2>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; status = "okay"; }; }; }; }; --- drivers/gpio/gpio-pca953x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index cc102d25ee249..24fee5d16fa02 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -24,6 +24,10 @@ #include #endif +#define CONFIG_OF_GPIO 1 +#define CONFIG_GPIO_PCA953X_IRQ 1 +#define CONFIG_ARM 1 + #define PCA953X_INPUT 0 #define PCA953X_OUTPUT 1 #define PCA953X_INVERT 2