Merge remote-tracking branch 'origin/helios4_LK4.4' into helios4
This commit is contained in:
commit
75a40bcfdb
@ -3279,7 +3279,7 @@ CONFIG_REGULATOR_GPIO=m
|
||||
# CONFIG_REGULATOR_MAX8973 is not set
|
||||
# CONFIG_REGULATOR_MT6311 is not set
|
||||
# CONFIG_REGULATOR_PFUZE100 is not set
|
||||
CONFIG_REGULATOR_PWM=m
|
||||
# CONFIG_REGULATOR_PWM is not set
|
||||
# CONFIG_REGULATOR_TPS51632 is not set
|
||||
# CONFIG_REGULATOR_TPS62360 is not set
|
||||
# CONFIG_REGULATOR_TPS65023 is not set
|
||||
@ -3377,14 +3377,14 @@ CONFIG_LCD_LMS501KF03=m
|
||||
CONFIG_LCD_HX8357=m
|
||||
CONFIG_BACKLIGHT_CLASS_DEVICE=m
|
||||
CONFIG_BACKLIGHT_GENERIC=m
|
||||
CONFIG_BACKLIGHT_PWM=m
|
||||
# CONFIG_BACKLIGHT_PWM is not set
|
||||
CONFIG_BACKLIGHT_PM8941_WLED=m
|
||||
CONFIG_BACKLIGHT_ADP8860=m
|
||||
CONFIG_BACKLIGHT_ADP8870=m
|
||||
CONFIG_BACKLIGHT_88PM860X=m
|
||||
CONFIG_BACKLIGHT_LM3630A=m
|
||||
# CONFIG_BACKLIGHT_LM3630A is not set
|
||||
CONFIG_BACKLIGHT_LM3639=m
|
||||
CONFIG_BACKLIGHT_LP855X=m
|
||||
# CONFIG_BACKLIGHT_LP855X is not set
|
||||
CONFIG_BACKLIGHT_GPIO=m
|
||||
CONFIG_BACKLIGHT_LV5207LP=m
|
||||
CONFIG_BACKLIGHT_BD6107=m
|
||||
@ -3856,7 +3856,7 @@ CONFIG_LEDS_GPIO=m
|
||||
# CONFIG_LEDS_PCA955X is not set
|
||||
# CONFIG_LEDS_PCA963X is not set
|
||||
# CONFIG_LEDS_DAC124S085 is not set
|
||||
CONFIG_LEDS_PWM=m
|
||||
# CONFIG_LEDS_PWM is not set
|
||||
CONFIG_LEDS_REGULATOR=m
|
||||
# CONFIG_LEDS_BD2802 is not set
|
||||
# CONFIG_LEDS_LT3593 is not set
|
||||
@ -4228,7 +4228,7 @@ CONFIG_COMMON_CLK_SCPI=m
|
||||
# CONFIG_COMMON_CLK_SI570 is not set
|
||||
# CONFIG_COMMON_CLK_CDCE925 is not set
|
||||
# CONFIG_CLK_QORIQ is not set
|
||||
CONFIG_COMMON_CLK_PWM=m
|
||||
# CONFIG_COMMON_CLK_PWM is not set
|
||||
# CONFIG_COMMON_CLK_PXA is not set
|
||||
# CONFIG_COMMON_CLK_CDCE706 is not set
|
||||
CONFIG_MVEBU_CLK_COMMON=y
|
||||
@ -4539,8 +4539,8 @@ CONFIG_IIO_SYSFS_TRIGGER=m
|
||||
# CONFIG_VME_BUS is not set
|
||||
CONFIG_PWM=y
|
||||
CONFIG_PWM_SYSFS=y
|
||||
CONFIG_PWM_FSL_FTM=m
|
||||
CONFIG_PWM_PCA9685=m
|
||||
# CONFIG_PWM_FSL_FTM is not set
|
||||
# CONFIG_PWM_PCA9685 is not set
|
||||
CONFIG_IRQCHIP=y
|
||||
CONFIG_ARM_GIC=y
|
||||
CONFIG_ARMADA_370_XP_IRQ=y
|
||||
|
||||
@ -19,9 +19,10 @@ esac
|
||||
family_tweaks_s()
|
||||
{
|
||||
chroot $SDCARD /bin/bash -c "apt-get -y -qq install fancontrol >/dev/null 2>&1"
|
||||
cp -R $SRC/packages/bsp/helios4/90-helios4-hwmon.rules $SDCARD/etc/udev/rules.d/
|
||||
case $BRANCH in
|
||||
default)
|
||||
cp -R $SRC/packages/bsp/helios4/fancontrol_gpio-fan.conf $SDCARD/etc/fancontrol
|
||||
cp -R $SRC/packages/bsp/helios4/fancontrol_pwm-fan-LK4.4.conf $SDCARD/etc/fancontrol
|
||||
;;
|
||||
|
||||
next)
|
||||
|
||||
24
packages/bsp/helios4/90-helios4-hwmon.rules
Executable file
24
packages/bsp/helios4/90-helios4-hwmon.rules
Executable file
@ -0,0 +1,24 @@
|
||||
# Helios4 persistent hwmon
|
||||
|
||||
ACTION=="remove", GOTO="helios4_hwmon_end"
|
||||
|
||||
#
|
||||
KERNELS=="j10-pwm", SUBSYSTEMS=="platform", ENV{_HELIOS4_FAN_}="j10", ENV{_IS_HELIOS4_FAN_}="1", ENV{IS_HELIOS4_HWMON}="1"
|
||||
KERNELS=="j17-pwm", SUBSYSTEMS=="platform", ENV{_HELIOS4_FAN_}="j17", ENV{_IS_HELIOS4_FAN_}="1", ENV{IS_HELIOS4_HWMON}="1"
|
||||
KERNELS=="0-004c", SUBSYSTEMS=="i2c", DRIVERS=="lm75", ENV{IS_HELIOS4_HWMON}="1"
|
||||
|
||||
SUBSYSTEM!="hwmon", GOTO="helios4_hwmon_end"
|
||||
|
||||
ENV{HWMON_PATH}="/sys%p"
|
||||
#
|
||||
ATTR{name}=="f1072004mdiomii00", ENV{IS_HELIOS4_HWMON}="1", ENV{HELIOS4_SYMLINK}="/dev/thermal-eth"
|
||||
ATTR{name}=="armada_thermal", ENV{IS_HELIOS4_HWMON}="1", ENV{HELIOS4_SYMLINK}="/dev/thermal-cpu"
|
||||
#
|
||||
ENV{IS_HELIOS4_HWMON}=="1", ATTR{name}=="lm75", ENV{HELIOS4_SYMLINK}="/dev/thermal-board"
|
||||
ENV{_IS_HELIOS4_FAN_}=="1", ENV{HELIOS4_SYMLINK}="/dev/fan-$env{_HELIOS4_FAN_}"
|
||||
|
||||
#
|
||||
ENV{IS_HELIOS4_HWMON}=="1", RUN+="/bin/ln -sf $env{HWMON_PATH} $env{HELIOS4_SYMLINK}"
|
||||
|
||||
LABEL="helios4_hwmon_end"
|
||||
|
||||
10
packages/bsp/helios4/fancontrol_pwm-fan-LK4.4.conf
Normal file
10
packages/bsp/helios4/fancontrol_pwm-fan-LK4.4.conf
Normal file
@ -0,0 +1,10 @@
|
||||
# Helios4 PWM Fan Control Configuration
|
||||
# Temp source : lm75 sensor
|
||||
INTERVAL=10
|
||||
DEVPATH=hwmon0=devices/platform/j10-pwm hwmon1=devices/platform/j17-pwm hwmon2=devices/platform/soc/soc:internal-regs/f1011000.i2c/i2c-0/0-004c
|
||||
DEVNAME=hwmon0=pwmfan hwmon1=pwmfan hwmon2=lm75
|
||||
FCTEMPS=hwmon0/pwm1=hwmon2/temp1_input hwmon1/pwm1=hwmon2/temp1_input
|
||||
MINTEMP=hwmon0/pwm1=45 hwmon1/pwm1=45
|
||||
MAXTEMP=hwmon0/pwm1=65 hwmon1/pwm1=65
|
||||
MINSTART=hwmon0/pwm1=100 hwmon1/pwm1=100
|
||||
MINSTOP=hwmon0/pwm1=50 hwmon1/pwm1=50
|
||||
@ -0,0 +1,523 @@
|
||||
arch/arm/boot/dts/armada-38x.dtsi | 16 +-
|
||||
drivers/gpio/gpio-mvebu.c | 369 +++++++++++++++++++++++++++--
|
||||
2 files changed, 367 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
|
||||
index e4e1546..5894e45 100644
|
||||
--- a/arch/arm/boot/dts/armada-38x.dtsi
|
||||
+++ b/arch/arm/boot/dts/armada-38x.dtsi
|
||||
@@ -339,31 +339,39 @@
|
||||
};
|
||||
|
||||
gpio0: gpio@18100 {
|
||||
- compatible = "marvell,orion-gpio";
|
||||
- reg = <0x18100 0x40>;
|
||||
+ compatible = "marvell,armada-370-gpio",
|
||||
+ "marvell,orion-gpio";
|
||||
+ reg = <0x18100 0x40>, <0x181c0 0x08>;
|
||||
+ reg-names = "gpio", "pwm";
|
||||
ngpios = <32>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
+ #pwm-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&coreclk 0>;
|
||||
};
|
||||
|
||||
gpio1: gpio@18140 {
|
||||
- compatible = "marvell,orion-gpio";
|
||||
- reg = <0x18140 0x40>;
|
||||
+ compatible = "marvell,armada-370-gpio",
|
||||
+ "marvell,orion-gpio";
|
||||
+ reg = <0x18140 0x40>, <0x181c8 0x08>;
|
||||
+ reg-names = "gpio", "pwm";
|
||||
ngpios = <28>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
+ #pwm-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&coreclk 0>;
|
||||
};
|
||||
|
||||
system-controller@18200 {
|
||||
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
|
||||
index ffea532..9fe65f7 100644
|
||||
--- a/drivers/gpio/gpio-mvebu.c
|
||||
+++ b/drivers/gpio/gpio-mvebu.c
|
||||
@@ -42,29 +42,43 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_device.h>
|
||||
+#include <linux/pwm.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include "gpiolib.h"
|
||||
|
||||
/*
|
||||
* GPIO unit register offsets.
|
||||
*/
|
||||
-#define GPIO_OUT_OFF 0x0000
|
||||
-#define GPIO_IO_CONF_OFF 0x0004
|
||||
-#define GPIO_BLINK_EN_OFF 0x0008
|
||||
-#define GPIO_IN_POL_OFF 0x000c
|
||||
-#define GPIO_DATA_IN_OFF 0x0010
|
||||
-#define GPIO_EDGE_CAUSE_OFF 0x0014
|
||||
-#define GPIO_EDGE_MASK_OFF 0x0018
|
||||
-#define GPIO_LEVEL_MASK_OFF 0x001c
|
||||
+#define GPIO_OUT_OFF 0x0000
|
||||
+#define GPIO_IO_CONF_OFF 0x0004
|
||||
+#define GPIO_BLINK_EN_OFF 0x0008
|
||||
+#define GPIO_IN_POL_OFF 0x000c
|
||||
+#define GPIO_DATA_IN_OFF 0x0010
|
||||
+#define GPIO_EDGE_CAUSE_OFF 0x0014
|
||||
+#define GPIO_EDGE_MASK_OFF 0x0018
|
||||
+#define GPIO_LEVEL_MASK_OFF 0x001c
|
||||
+#define GPIO_BLINK_CNT_SELECT_OFF 0x0020
|
||||
+
|
||||
+/*
|
||||
+ * PWM register offsets.
|
||||
+ */
|
||||
+#define PWM_BLINK_ON_DURATION_OFF 0x0
|
||||
+#define PWM_BLINK_OFF_DURATION_OFF 0x4
|
||||
+
|
||||
|
||||
/* The MV78200 has per-CPU registers for edge mask and level mask */
|
||||
#define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18)
|
||||
#define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C)
|
||||
|
||||
-/* The Armada XP has per-CPU registers for interrupt cause, interrupt
|
||||
+/*
|
||||
+ * The Armada XP has per-CPU registers for interrupt cause, interrupt
|
||||
* mask and interrupt level mask. Those are relative to the
|
||||
- * percpu_membase. */
|
||||
+ * percpu_membase.
|
||||
+ */
|
||||
#define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4)
|
||||
#define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4)
|
||||
#define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4)
|
||||
@@ -75,6 +89,41 @@
|
||||
|
||||
#define MVEBU_MAX_GPIO_PER_BANK 32
|
||||
|
||||
+enum mvebu_pwm_ctrl {
|
||||
+ MVEBU_PWM_CTRL_SET_A = 0,
|
||||
+ MVEBU_PWM_CTRL_SET_B,
|
||||
+ MVEBU_PWM_CTRL_MAX
|
||||
+};
|
||||
+
|
||||
+struct mvebu_pwmchip {
|
||||
+ void __iomem *membase;
|
||||
+ unsigned long clk_rate;
|
||||
+ spinlock_t lock;
|
||||
+ bool in_use;
|
||||
+
|
||||
+ /* Used to preserve GPIO/PWM registers across suspend/resume */
|
||||
+ u32 blink_on_duration;
|
||||
+ u32 blink_off_duration;
|
||||
+};
|
||||
+
|
||||
+struct mvebu_pwm_chip_drv {
|
||||
+ enum mvebu_pwm_ctrl ctrl;
|
||||
+ struct gpio_desc *gpiod;
|
||||
+ bool master;
|
||||
+};
|
||||
+
|
||||
+struct mvebu_pwm {
|
||||
+ struct pwm_chip chip;
|
||||
+ struct mvebu_gpio_chip *mvchip;
|
||||
+ struct mvebu_pwmchip controller;
|
||||
+ enum mvebu_pwm_ctrl default_counter;
|
||||
+
|
||||
+ /* Used to preserve GPIO/PWM registers across suspend/resume */
|
||||
+ u32 blink_select;
|
||||
+};
|
||||
+
|
||||
+static struct mvebu_pwmchip *mvebu_pwm_list[MVEBU_PWM_CTRL_MAX];
|
||||
+
|
||||
struct mvebu_gpio_chip {
|
||||
struct gpio_chip chip;
|
||||
spinlock_t lock;
|
||||
@@ -84,6 +133,10 @@ struct mvebu_gpio_chip {
|
||||
struct irq_domain *domain;
|
||||
int soc_variant;
|
||||
|
||||
+ /* Used for PWM support */
|
||||
+ struct clk *clk;
|
||||
+ struct mvebu_pwm *mvpwm;
|
||||
+
|
||||
/* Used to preserve GPIO registers across suspend/resume */
|
||||
u32 out_reg;
|
||||
u32 io_conf_reg;
|
||||
@@ -102,6 +155,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
|
||||
return mvchip->membase + GPIO_OUT_OFF;
|
||||
}
|
||||
|
||||
+static void __iomem *mvebu_gpioreg_blink_select(struct mvebu_gpio_chip *mvchip)
|
||||
+{
|
||||
+ return mvchip->membase + GPIO_BLINK_CNT_SELECT_OFF;
|
||||
+}
|
||||
+
|
||||
static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
|
||||
{
|
||||
return mvchip->membase + GPIO_BLINK_EN_OFF;
|
||||
@@ -182,6 +240,20 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Functions returning addresses of individual registers for a given
|
||||
+ * PWM controller.
|
||||
+ */
|
||||
+static void __iomem *mvebu_pwmreg_blink_on_duration(struct mvebu_pwmchip *mvpwm)
|
||||
+{
|
||||
+ return mvpwm->membase + PWM_BLINK_ON_DURATION_OFF;
|
||||
+}
|
||||
+
|
||||
+static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwmchip *mvpwm)
|
||||
+{
|
||||
+ return mvpwm->membase + PWM_BLINK_OFF_DURATION_OFF;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* Functions implementing the gpio_chip methods
|
||||
*/
|
||||
|
||||
@@ -489,6 +561,262 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Functions implementing the pwm_chip methods
|
||||
+ */
|
||||
+static struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip)
|
||||
+{
|
||||
+ return container_of(chip, struct mvebu_pwm, chip);
|
||||
+}
|
||||
+
|
||||
+static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
+{
|
||||
+ struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
|
||||
+ struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
|
||||
+ struct gpio_desc *desc;
|
||||
+ enum mvebu_pwm_ctrl id;
|
||||
+ int ret = 0;
|
||||
+ struct mvebu_pwm_chip_drv *chip_data;
|
||||
+ u32 u;
|
||||
+
|
||||
+ spin_lock(&mvpwm->controller.lock);
|
||||
+
|
||||
+ mvchip->blink_en_reg = readl_relaxed(mvebu_gpioreg_blink(mvchip));
|
||||
+ if (pwm->chip_data || (mvchip->blink_en_reg & BIT(pwm->hwpwm)))
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ desc = gpio_to_desc(mvchip->chip.base + pwm->hwpwm);
|
||||
+ if (!desc) {
|
||||
+ ret = -ENODEV;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ ret = gpiod_request(desc, "mvebu-pwm");
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+
|
||||
+ ret = gpiod_direction_output(desc, 0);
|
||||
+ if (ret) {
|
||||
+ gpiod_free(desc);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ chip_data = kzalloc(sizeof(struct mvebu_pwm_chip_drv), GFP_KERNEL);
|
||||
+ if (!chip_data) {
|
||||
+ gpiod_free(desc);
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ for (id = MVEBU_PWM_CTRL_SET_A;id < MVEBU_PWM_CTRL_MAX; id++) {
|
||||
+ if (!mvebu_pwm_list[id]->in_use) {
|
||||
+ chip_data->ctrl = id;
|
||||
+ chip_data->master = true;
|
||||
+ mvebu_pwm_list[id]->in_use = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!chip_data->master)
|
||||
+ chip_data->ctrl = mvpwm->default_counter;
|
||||
+
|
||||
+ u = readl_relaxed(mvebu_gpioreg_blink_select(mvchip));
|
||||
+ if (id)
|
||||
+ u |= (1 << pwm->hwpwm);
|
||||
+ else
|
||||
+ u &= ~(1 << pwm->hwpwm);
|
||||
+ writel_relaxed(u, mvebu_gpioreg_blink_select(mvchip));
|
||||
+
|
||||
+ chip_data->gpiod = desc;
|
||||
+ pwm->chip_data = chip_data;
|
||||
+ mvpwm->blink_select = u;
|
||||
+out:
|
||||
+ spin_unlock(&mvpwm->controller.lock);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
+{
|
||||
+ struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
|
||||
+ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&mvpwm->controller.lock, flags);
|
||||
+ if (chip_data->master)
|
||||
+ mvebu_pwm_list[chip_data->ctrl]->in_use = false;
|
||||
+
|
||||
+ gpiod_free(chip_data->gpiod);
|
||||
+ kfree(chip_data);
|
||||
+ pwm->chip_data = NULL;
|
||||
+ spin_unlock_irqrestore(&mvpwm->controller.lock, flags);
|
||||
+}
|
||||
+
|
||||
+static int mvebu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwmd,
|
||||
+ int duty_ns, int period_ns)
|
||||
+{
|
||||
+ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwmd->chip_data;
|
||||
+ struct mvebu_pwmchip *controller = mvebu_pwm_list[chip_data->ctrl];
|
||||
+ unsigned int on, off;
|
||||
+ unsigned long long val;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ val = (unsigned long long) controller->clk_rate * duty_ns;
|
||||
+ do_div(val, NSEC_PER_SEC);
|
||||
+ if (val > UINT_MAX)
|
||||
+ return -EINVAL;
|
||||
+ if (val)
|
||||
+ on = val;
|
||||
+ else
|
||||
+ on = 1;
|
||||
+
|
||||
+ val = (unsigned long long) controller->clk_rate * (period_ns - duty_ns);
|
||||
+ do_div(val, NSEC_PER_SEC);
|
||||
+ if (val > UINT_MAX)
|
||||
+ return -EINVAL;
|
||||
+ if (val)
|
||||
+ off = val;
|
||||
+ else
|
||||
+ off = 1;
|
||||
+
|
||||
+ spin_lock_irqsave(&controller->lock, flags);
|
||||
+ writel_relaxed(on, mvebu_pwmreg_blink_on_duration(controller));
|
||||
+ writel_relaxed(off, mvebu_pwmreg_blink_off_duration(controller));
|
||||
+ spin_unlock_irqrestore(&controller->lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mvebu_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
+{
|
||||
+ struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
|
||||
+ struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
|
||||
+
|
||||
+ mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mvebu_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
+{
|
||||
+ struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
|
||||
+ struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
|
||||
+
|
||||
+ mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 0);
|
||||
+}
|
||||
+
|
||||
+static const struct pwm_ops mvebu_pwm_ops = {
|
||||
+ .request = mvebu_pwm_request,
|
||||
+ .free = mvebu_pwm_free,
|
||||
+ .config = mvebu_pwm_config,
|
||||
+ .enable = mvebu_pwm_enable,
|
||||
+ .disable = mvebu_pwm_disable,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static void mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
|
||||
+{
|
||||
+ struct mvebu_pwm *mvpwm = mvchip->mvpwm;
|
||||
+
|
||||
+ mvpwm->blink_select =
|
||||
+ readl_relaxed(mvebu_gpioreg_blink_select(mvchip));
|
||||
+ mvpwm->controller.blink_on_duration =
|
||||
+ readl_relaxed(mvebu_pwmreg_blink_on_duration(&mvpwm->controller));
|
||||
+ mvpwm->controller.blink_off_duration =
|
||||
+ readl_relaxed(mvebu_pwmreg_blink_off_duration(&mvpwm->controller));
|
||||
+}
|
||||
+
|
||||
+static void mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
|
||||
+{
|
||||
+ struct mvebu_pwm *mvpwm = mvchip->mvpwm;
|
||||
+
|
||||
+ writel_relaxed(mvpwm->blink_select,
|
||||
+ mvebu_gpioreg_blink_select(mvchip));
|
||||
+ writel_relaxed(mvpwm->controller.blink_on_duration,
|
||||
+ mvebu_pwmreg_blink_on_duration(&mvpwm->controller));
|
||||
+ writel_relaxed(mvpwm->controller.blink_off_duration,
|
||||
+ mvebu_pwmreg_blink_off_duration(&mvpwm->controller));
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Armada 370/XP has simple PWM support for gpio lines. Other SoCs
|
||||
+ * don't have this hardware. So if we don't have the necessary
|
||||
+ * resource, it is not an error.
|
||||
+ */
|
||||
+static int mvebu_pwm_probe(struct platform_device *pdev,
|
||||
+ struct mvebu_gpio_chip *mvchip,
|
||||
+ int id)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct mvebu_pwm *mvpwm;
|
||||
+ struct resource *res;
|
||||
+ u32 set;
|
||||
+ enum mvebu_pwm_ctrl ctrl_set;
|
||||
+
|
||||
+ if (!of_device_is_compatible(mvchip->chip.of_node,
|
||||
+ "marvell,armada-370-gpio"))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (IS_ERR(mvchip->clk))
|
||||
+ return PTR_ERR(mvchip->clk);
|
||||
+
|
||||
+ /*
|
||||
+ * There are only two sets of PWM configuration registers for
|
||||
+ * all the GPIO lines on those SoCs which this driver reserves
|
||||
+ * for the first two GPIO chips. So if the resource is missing
|
||||
+ * we can't treat it as an error.
|
||||
+ */
|
||||
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm");
|
||||
+ if (!res)
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Use set A for lines of GPIO chip with id 0, B for GPIO chip
|
||||
+ * with id 1. Don't allow further GPIO chips to be used for PWM.
|
||||
+ */
|
||||
+ if (id == 0) {
|
||||
+ set = 0;
|
||||
+ ctrl_set = MVEBU_PWM_CTRL_SET_A;
|
||||
+ } else if (id == 1) {
|
||||
+ set = U32_MAX;
|
||||
+ ctrl_set = MVEBU_PWM_CTRL_SET_B;
|
||||
+ } else {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ writel_relaxed(set, mvebu_gpioreg_blink_select(mvchip));
|
||||
+
|
||||
+ mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL);
|
||||
+ if (!mvpwm)
|
||||
+ return -ENOMEM;
|
||||
+ mvchip->mvpwm = mvpwm;
|
||||
+ mvpwm->mvchip = mvchip;
|
||||
+
|
||||
+ mvpwm->controller.membase = devm_ioremap_resource(dev, res);
|
||||
+ if (IS_ERR(mvpwm->controller.membase))
|
||||
+ return PTR_ERR(mvpwm->controller.membase);
|
||||
+
|
||||
+ mvpwm->controller.clk_rate = clk_get_rate(mvchip->clk);
|
||||
+ if (!mvpwm->controller.clk_rate)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mvpwm->chip.dev = dev;
|
||||
+ mvpwm->chip.ops = &mvebu_pwm_ops;
|
||||
+ mvpwm->chip.npwm = mvchip->chip.ngpio;
|
||||
+
|
||||
+ /*
|
||||
+ * There may already be some PWM allocated, so we can't force
|
||||
+ * mvpwm->chip.base to a fixed point like mvchip->chip.base.
|
||||
+ * So, we let pwmchip_add() do the numbering and take the next free
|
||||
+ * region.
|
||||
+ */
|
||||
+ mvpwm->chip.base = -1;
|
||||
+
|
||||
+ spin_lock_init(&mvpwm->controller.lock);
|
||||
+ mvpwm->default_counter = ctrl_set;
|
||||
+ mvebu_pwm_list[ctrl_set] = &mvpwm->controller;
|
||||
+
|
||||
+ return pwmchip_add(&mvpwm->chip);
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
@@ -561,6 +889,10 @@ static const struct of_device_id mvebu_gpio_of_match[] = {
|
||||
.data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
|
||||
},
|
||||
{
|
||||
+ .compatible = "marvell,armada-370-gpio",
|
||||
+ .data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
|
||||
+ },
|
||||
+ {
|
||||
/* sentinel */
|
||||
},
|
||||
};
|
||||
@@ -607,6 +939,9 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
BUG();
|
||||
}
|
||||
|
||||
+ if (IS_ENABLED(CONFIG_PWM))
|
||||
+ mvebu_pwm_suspend(mvchip);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -650,6 +985,9 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
|
||||
BUG();
|
||||
}
|
||||
|
||||
+ if (IS_ENABLED(CONFIG_PWM))
|
||||
+ mvebu_pwm_resume(mvchip);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -661,7 +999,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
||||
struct resource *res;
|
||||
struct irq_chip_generic *gc;
|
||||
struct irq_chip_type *ct;
|
||||
- struct clk *clk;
|
||||
unsigned int ngpios;
|
||||
unsigned int gpio_base = -1;
|
||||
int soc_variant;
|
||||
@@ -695,10 +1032,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
||||
return id;
|
||||
}
|
||||
|
||||
- clk = devm_clk_get(&pdev->dev, NULL);
|
||||
+ mvchip->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
/* Not all SoCs require a clock.*/
|
||||
- if (!IS_ERR(clk))
|
||||
- clk_prepare_enable(clk);
|
||||
+ if (!IS_ERR(mvchip->clk))
|
||||
+ clk_prepare_enable(mvchip->clk);
|
||||
|
||||
mvchip->soc_variant = soc_variant;
|
||||
mvchip->chip.label = dev_name(&pdev->dev);
|
||||
@@ -835,6 +1172,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
||||
goto err_generic_chip;
|
||||
}
|
||||
|
||||
+ /* Armada 370/XP has simple PWM support for GPIO lines */
|
||||
+ if (IS_ENABLED(CONFIG_PWM))
|
||||
+ return mvebu_pwm_probe(pdev, mvchip, id);
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_generic_chip:
|
||||
@ -1,27 +1,9 @@
|
||||
From 9fe4b82ed5e62ac82df8294e9e02b4ffab23bb47 Mon Sep 17 00:00:00 2001
|
||||
From: Aditya Prayoga <adit.prayoga@gmail.com>
|
||||
Date: Sun, 19 Mar 2017 17:27:01 +0800
|
||||
Subject: Initial device tree
|
||||
|
||||
- Tested using clearfrog u-boot
|
||||
- Increase SD Card clock to 50 MHz from default 25 MHz
|
||||
- All 7 LED declared as led-gpio
|
||||
- LED1 (system) default to hearbeat
|
||||
- LED7 (USB) triggered by USB Host activity
|
||||
- SPI NOR flash declared as MTD
|
||||
- Enable IO expander interrupt
|
||||
- Allocate GPIOs for fans
|
||||
---
|
||||
arch/arm/boot/dts/armada-388-helios4.dts | 333 +++++++++++++++++++++
|
||||
1 file changed, 329 insertions(+)
|
||||
create mode 100644 arch/arm/boot/dts/armada-388-helios4.dts
|
||||
|
||||
diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/armada-388-helios4.dts
|
||||
new file mode 100644
|
||||
index 0000000..19a0256
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/armada-388-helios4.dts
|
||||
@@ -0,0 +1,318 @@
|
||||
@@ -0,0 +1,314 @@
|
||||
+/*
|
||||
+ * Device Tree file for Helios4
|
||||
+ * based on SolidRun Clearfog revision A1 rev 2.0 (88F6828)
|
||||
@ -142,17 +124,13 @@ index 0000000..19a0256
|
||||
+ };
|
||||
+
|
||||
+ fan1: j10-pwm {
|
||||
+ compatible = "gpio-fan";
|
||||
+ gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
|
||||
+ gpio-fan,speed-map = < 0 0
|
||||
+ 3800 1>;
|
||||
+ compatible = "pwm-fan";
|
||||
+ pwms = <&gpio1 9 3800>;
|
||||
+ };
|
||||
+
|
||||
+ fan2: j17-pwm {
|
||||
+ compatible = "gpio-fan";
|
||||
+ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
|
||||
+ gpio-fan,speed-map = < 0 0
|
||||
+ 3800 1>;
|
||||
+ compatible = "pwm-fan";
|
||||
+ pwms = <&gpio1 23 3800>;
|
||||
+ };
|
||||
+
|
||||
+ usb2_phy: usb2-phy {
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/armada-388-helios4.dts
|
||||
index ec7a5ce..1075535 100644
|
||||
--- a/arch/arm/boot/dts/armada-388-helios4.dts
|
||||
+++ b/arch/arm/boot/dts/armada-388-helios4.dts
|
||||
@@ -131,13 +131,17 @@
|
||||
};
|
||||
|
||||
fan1: j10-pwm {
|
||||
- compatible = "pwm-fan";
|
||||
- pwms = <&gpio1 9 3800>;
|
||||
+ compatible = "gpio-fan";
|
||||
+ gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
|
||||
+ gpio-fan,speed-map = < 0 0
|
||||
+ 3800 1>;
|
||||
};
|
||||
|
||||
fan2: j17-pwm {
|
||||
- compatible = "pwm-fan";
|
||||
- pwms = <&gpio1 23 3800>;
|
||||
+ compatible = "gpio-fan";
|
||||
+ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
|
||||
+ gpio-fan,speed-map = < 0 0
|
||||
+ 3800 1>;
|
||||
};
|
||||
|
||||
usb2_phy: usb2-phy {
|
||||
Loading…
Reference in New Issue
Block a user