diff --git a/config/boards/helios4.conf b/config/boards/helios4.conf index 0c4189672e..c227c917d9 100644 --- a/config/boards/helios4.conf +++ b/config/boards/helios4.conf @@ -4,13 +4,13 @@ BOARDFAMILY="mvebu" BOOTCONFIG="armada_38x_helios4_config" MODULES="mv_cesa" BUILD_DESKTOP="no" -# -KERNEL_TARGET="next" -CLI_TARGET="" + +KERNEL_TARGET="default,next" +CLI_TARGET="jessie:default,stretch:next" CLI_BETA_TARGET="" # -RECOMMENDED="Debian_jessie_next_nightly:75,Debian_stretch_next_nightly:75" +RECOMMENDED="Debian_jessie_default_nightly:85,Debian_stretch_next_nightly:85" # BOARDRATING="" CHIP="https://kobol.io/helios4" diff --git a/config/kernel/linux-mvebu-default.config b/config/kernel/linux-mvebu-default.config index aaa1d5f0d6..c6adf0977d 100644 --- a/config/kernel/linux-mvebu-default.config +++ b/config/kernel/linux-mvebu-default.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.4.99 Kernel Configuration +# Linux/arm 4.4.110 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -3028,6 +3028,7 @@ CONFIG_SENSORS_LM75=m # CONFIG_SENSORS_NCT7904 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_PMBUS is not set +CONFIG_SENSORS_PWM_FAN=m # CONFIG_SENSORS_SHT15 is not set # CONFIG_SENSORS_SHT21 is not set # CONFIG_SENSORS_SHTC1 is not set @@ -3276,6 +3277,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_TPS51632 is not set # CONFIG_REGULATOR_TPS62360 is not set # CONFIG_REGULATOR_TPS65023 is not set @@ -3373,11 +3375,14 @@ CONFIG_LCD_LMS501KF03=m CONFIG_LCD_HX8357=m CONFIG_BACKLIGHT_CLASS_DEVICE=m CONFIG_BACKLIGHT_GENERIC=m +CONFIG_BACKLIGHT_PWM=m CONFIG_BACKLIGHT_PM8941_WLED=m CONFIG_BACKLIGHT_ADP8860=m CONFIG_BACKLIGHT_ADP8870=m CONFIG_BACKLIGHT_88PM860X=m +CONFIG_BACKLIGHT_LM3630A=m CONFIG_BACKLIGHT_LM3639=m +CONFIG_BACKLIGHT_LP855X=m CONFIG_BACKLIGHT_GPIO=m CONFIG_BACKLIGHT_LV5207LP=m CONFIG_BACKLIGHT_BD6107=m @@ -3849,6 +3854,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_REGULATOR=m # CONFIG_LEDS_BD2802 is not set # CONFIG_LEDS_LT3593 is not set @@ -4220,6 +4226,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_PXA is not set # CONFIG_COMMON_CLK_CDCE706 is not set CONFIG_MVEBU_CLK_COMMON=y @@ -4528,7 +4535,10 @@ CONFIG_IIO_SYSFS_TRIGGER=m # CONFIG_TSYS02D is not set # CONFIG_NTB is not set # CONFIG_VME_BUS is not set -# CONFIG_PWM is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +CONFIG_PWM_FSL_FTM=m +CONFIG_PWM_PCA9685=m CONFIG_IRQCHIP=y CONFIG_ARM_GIC=y CONFIG_ARMADA_370_XP_IRQ=y diff --git a/config/kernel/linux-mvebu-next.config b/config/kernel/linux-mvebu-next.config index d158ac86e1..c3f34740be 100644 --- a/config/kernel/linux-mvebu-next.config +++ b/config/kernel/linux-mvebu-next.config @@ -1887,6 +1887,8 @@ CONFIG_SCSI_LOWLEVEL=y CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_ARCH_WANT_LIBATA_LEDS=y +CONFIG_ATA_LEDS=y CONFIG_SATA_PMP=y # @@ -3614,7 +3616,7 @@ CONFIG_MMC_MVSDIO=y # CONFIG_MMC_SDHCI_XENON is not set # CONFIG_MEMSTICK is not set CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=m +CONFIG_LEDS_CLASS=y # CONFIG_LEDS_CLASS_FLASH is not set CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y @@ -3651,6 +3653,7 @@ CONFIG_LEDS_IS31FL32XX=m # LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) # # CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_SYSCON is not set CONFIG_LEDS_USER=m # diff --git a/config/sources/mvebu-u-boot-clearfog.inc b/config/sources/mvebu-clearfog.inc similarity index 100% rename from config/sources/mvebu-u-boot-clearfog.inc rename to config/sources/mvebu-clearfog.inc diff --git a/config/sources/mvebu-helios4.inc b/config/sources/mvebu-helios4.inc new file mode 100644 index 0000000000..e88826109b --- /dev/null +++ b/config/sources/mvebu-helios4.inc @@ -0,0 +1,33 @@ +case $BRANCH in + default|next) + BOOTSOURCE='https://github.com/helios-4/u-boot-marvell.git' + BOOTBRANCH='branch:u-boot-2013.01-15t1-helios4' + BOOTDIR='u-boot-armada' + BOOTSCRIPT='boot-marvell.cmd:boot.cmd' + + UBOOT_TARGET_MAP="u-boot.mmc;;u-boot.mmc" + + UBOOT_USE_GCC='== 4.9' + UBOOT_COMPILER='arm-linux-gnueabi-' + + BOOTPATCHDIR='u-boot-helios4' + ;; +esac + + +# Helios4 tweak : install and configure fancontrol +family_tweaks_s() +{ + chroot $SDCARD /bin/bash -c "apt-get -y -qq install fancontrol >/dev/null 2>&1" + case $BRANCH in + default) + cp -R $SRC/packages/bsp/helios4/fancontrol_gpio-fan.conf $SDCARD/etc/fancontrol + ;; + + next) + cp -R $SRC/packages/bsp/helios4/fancontrol_pwm-fan.conf $SDCARD/etc/fancontrol + patch $SDCARD/usr/sbin/fancontrol < $SRC/packages/bsp/helios4/fancontrol.patch + ;; + esac +} + diff --git a/config/sources/mvebu-u-boot-helios4.inc b/config/sources/mvebu-u-boot-helios4.inc deleted file mode 100644 index cdf276ede6..0000000000 --- a/config/sources/mvebu-u-boot-helios4.inc +++ /dev/null @@ -1,15 +0,0 @@ -case $BRANCH in - default|next) - BOOTSOURCE='https://github.com/helios-4/u-boot-marvell.git' - BOOTBRANCH='branch:u-boot-2013.01-15t1-helios4' - BOOTDIR='u-boot-armada' - BOOTSCRIPT='boot-marvell.cmd:boot.cmd' - - UBOOT_TARGET_MAP="u-boot.mmc;;u-boot.mmc" - - UBOOT_USE_GCC='== 4.9' - UBOOT_COMPILER='arm-linux-gnueabi-' - - BOOTPATCHDIR='u-boot-helios4' - ;; -esac diff --git a/config/sources/mvebu.conf b/config/sources/mvebu.conf index 810336dc87..e16e0845e9 100644 --- a/config/sources/mvebu.conf +++ b/config/sources/mvebu.conf @@ -1,10 +1,10 @@ HAS_UUID_SUPPORT=yes if [[ $BOARD == helios4 ]]; then - source "${BASH_SOURCE%/*}/mvebu-u-boot-helios4.inc" + source "${BASH_SOURCE%/*}/mvebu-helios4.inc" BOOTENV_FILE='helios4-default.txt' else - source "${BASH_SOURCE%/*}/mvebu-u-boot-clearfog.inc" + source "${BASH_SOURCE%/*}/mvebu-clearfog.inc" BOOTENV_FILE='clearfog-default.txt' fi @@ -57,5 +57,8 @@ write_uboot_platform() family_tweaks() { + # execute specific tweaks function if present + [[ $(type -t family_tweaks_s) == function ]] && family_tweaks_s + chroot $SDCARD /bin/bash -c "apt-get -y -qq remove --auto-remove linux-sound-base alsa-base alsa-utils bluez>/dev/null 2>&1" } diff --git a/packages/bsp/helios4/fancontrol.patch b/packages/bsp/helios4/fancontrol.patch new file mode 100644 index 0000000000..ce9ee76706 --- /dev/null +++ b/packages/bsp/helios4/fancontrol.patch @@ -0,0 +1,12 @@ +@@ -157,9 +157,9 @@ + + function DevicePath() + { +- if [ -h "$1/device" ] ++ if [ -h "$1" ] + then +- readlink -f "$1/device" | sed -e 's/^\/sys\///' ++ readlink -f "$1" | sed -e 's/^\/sys\///;s/\/hwmon\/.*//' + fi + } + diff --git a/packages/bsp/helios4/fancontrol_gpio-fan.conf b/packages/bsp/helios4/fancontrol_gpio-fan.conf new file mode 100644 index 0000000000..556c823c4e --- /dev/null +++ b/packages/bsp/helios4/fancontrol_gpio-fan.conf @@ -0,0 +1,12 @@ +# Helios4 GPIO Fan Control Configuration +# This is a temporary configuration while relying on gpio-fan driver. +# Only low or full speed is supported. +# 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=gpio_fan hwmon1=gpio_fan 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=1 hwmon1/pwm1=1 +MINSTOP=hwmon0/pwm1=0 hwmon1/pwm1=0 diff --git a/packages/bsp/helios4/fancontrol_pwm-fan.conf b/packages/bsp/helios4/fancontrol_pwm-fan.conf new file mode 100644 index 0000000000..9bd9dc181c --- /dev/null +++ b/packages/bsp/helios4/fancontrol_pwm-fan.conf @@ -0,0 +1,11 @@ +# Helios4 PWM Fan Control Configuration +# Temp source : armada_thermal sensor +INTERVAL=10 +DEVPATH=hwmon1=devices/virtual hwmon2=devices/platform/j10-pwm hwmon3=devices/platform/j17-pwm hwmon4=devices/platform/soc/soc:internal-regs/f1011000.i2c/i2c-0/0-004c +DEVNAME=hwmon1=armada_thermal hwmon2=pwmfan hwmon3=pwmfan hwmon4=lm75 +FCTEMPS=hwmon2/pwm1=hwmon1/temp1_input hwmon3/pwm1=hwmon1/temp1_input +MINTEMP=hwmon2/pwm1=55 hwmon3/pwm1=55 +MAXTEMP=hwmon2/pwm1=95 hwmon3/pwm1=95 +MINSTART=hwmon2/pwm1=100 hwmon3/pwm1=100 +MINSTOP=hwmon2/pwm1=50 hwmon3/pwm1=50 + diff --git a/patch/kernel/mvebu-default/90-gpio-mvebu-Add-limited-PWM-support.patch.disabled b/patch/kernel/mvebu-default/90-gpio-mvebu-Add-limited-PWM-support.patch.disabled deleted file mode 100644 index 045c82886e..0000000000 --- a/patch/kernel/mvebu-default/90-gpio-mvebu-Add-limited-PWM-support.patch.disabled +++ /dev/null @@ -1,488 +0,0 @@ -From 65bce3cd01230b283915be86196f5e1318c18dd6 Mon Sep 17 00:00:00 2001 -From: aprayoga -Date: Sun, 3 Sep 2017 15:59:11 +0800 -Subject: gpio: mvebu: Add limited PWM support - -backported from https://patchwork.kernel.org/patch/9681399/ - -* Remove atomic PWM API portion as this is not supported on LK4.4 -and use https://patchwork.ozlabs.org/patch/739591/ instead. ---- - .../devicetree/bindings/gpio/gpio-mvebu.txt | 31 +++ - MAINTAINERS | 2 + - drivers/gpio/gpio-mvebu.c | 309 ++++++++++++++++++++- - 3 files changed, 328 insertions(+), 14 deletions(-) - -diff --git a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt -index 6b76891..b6cdcb2 100644 ---- a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt -+++ b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt -@@ -46,6 +46,23 @@ Optional: - The base of CP0 bank0 should be 20 (after AP-806 pins) the base of CP0 bank1 should be - 52 (after AP-806, and CP0 bank0 pins) - -+Optional properties: -+ -+In order to use the gpio lines in PWM mode, some additional optional -+properties are required. Only Armada 370 and XP support these properties. -+ -+- reg: an additional register set is needed, for the GPIO Blink -+ Counter on/off registers. -+ -+- reg-names: Must contain an entry "pwm" corresponding to the -+ additional register range needed for pwm operation. -+ -+- #pwm-cells: Should be two. The first cell is the pin number. The -+ second cell is reserved for flags and should be set to 0, so it has a -+ known value. It then becomes possible to use it in the future. -+ -+- clocks: Must be a phandle to the clock for the gpio controller. -+ - Example: - - gpio0: gpio@d0018100 { -@@ -59,3 +76,17 @@ Example: - #interrupt-cells = <2>; - interrupts = <16>, <17>, <18>, <19>; - }; -+ -+ gpio1: gpio@18140 { -+ compatible = "marvell,armada-370-xp-gpio"; -+ reg = <0x18140 0x40>, <0x181c8 0x08>; -+ reg-names = "gpio", "pwm"; -+ ngpios = <17>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ #pwm-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ interrupts = <87>, <88>, <89>; -+ clocks = <&coreclk 0>; -+ }; -diff --git a/MAINTAINERS b/MAINTAINERS -index 7008b0d..d272aca 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -8635,6 +8635,8 @@ F: include/linux/pwm.h - F: drivers/pwm/ - F: drivers/video/backlight/pwm_bl.c - F: include/linux/pwm_backlight.h -+F: drivers/gpio/gpio-mvebu.c -+F: Documentation/devicetree/bindings/gpio/gpio-mvebu.txt - - PXA2xx/PXA3xx SUPPORT - M: Daniel Mack -diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c -index ffea532..8775123 100644 ---- a/drivers/gpio/gpio-mvebu.c -+++ b/drivers/gpio/gpio-mvebu.c -@@ -42,29 +42,43 @@ - #include - #include - #include -+#include - #include - #include - #include -+#include -+ -+#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,23 @@ - - #define MVEBU_MAX_GPIO_PER_BANK 32 - -+struct mvebu_pwm { -+ void __iomem *membase; -+ unsigned long clk_rate; -+ struct gpio_desc *gpiod; -+ bool used; -+ unsigned int pin; -+ struct pwm_chip chip; -+ int id; -+ spinlock_t lock; -+ struct mvebu_gpio_chip *mvchip; -+ -+ /* Used to preserve GPIO/PWM registers across suspend/resume */ -+ u32 blink_select; -+ u32 blink_on_duration; -+ u32 blink_off_duration; -+}; -+ - struct mvebu_gpio_chip { - struct gpio_chip chip; - spinlock_t lock; -@@ -84,6 +115,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 +137,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 +222,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_pwm *mvpwm) -+{ -+ return mvpwm->membase + PWM_BLINK_ON_DURATION_OFF; -+} -+ -+static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm) -+{ -+ return mvpwm->membase + PWM_BLINK_OFF_DURATION_OFF; -+} -+ -+/* - * Functions implementing the gpio_chip methods - */ - -@@ -489,6 +543,220 @@ 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; -+ unsigned long flags; -+ int ret = 0; -+ -+ spin_lock_irqsave(&mvpwm->lock, flags); -+ if (mvpwm->gpiod) { -+ ret = -EBUSY; -+ } else { -+ 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; -+ } -+ -+ mvpwm->gpiod = desc; -+ mvpwm->pin = pwm->pwm - mvchip->chip.base; -+ mvpwm->used = true; -+ } -+ -+out: -+ spin_unlock_irqrestore(&mvpwm->lock, flags); -+ return ret; -+} -+ -+static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&mvpwm->lock, flags); -+ gpiod_free(mvpwm->gpiod); -+ mvpwm->used = false; -+ spin_unlock_irqrestore(&mvpwm->lock, flags); -+} -+ -+static int mvebu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwmd, -+ int duty_ns, int period_ns) -+{ -+ struct mvebu_pwm *pwm = to_mvebu_pwm(chip); -+ struct mvebu_gpio_chip *mvchip = pwm->mvchip; -+ unsigned int on, off; -+ unsigned long long val; -+ u32 u; -+ -+ val = (unsigned long long) pwm->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) pwm->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; -+ -+ u = readl_relaxed(mvebu_gpioreg_blink_select(mvchip)); -+ u &= ~(1 << pwm->pin); -+ u |= (pwm->id << pwm->pin); -+ writel_relaxed(u, mvebu_gpioreg_blink_select(mvchip)); -+ -+ writel_relaxed(on, mvebu_pwmreg_blink_on_duration(pwm)); -+ writel_relaxed(off, mvebu_pwmreg_blink_off_duration(pwm)); -+ -+ 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, mvpwm->pin, 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, mvpwm->pin, 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->blink_on_duration = -+ readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); -+ mvpwm->blink_off_duration = -+ readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); -+} -+ -+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->blink_on_duration, -+ mvebu_pwmreg_blink_on_duration(mvpwm)); -+ writel_relaxed(mvpwm->blink_off_duration, -+ mvebu_pwmreg_blink_off_duration(mvpwm)); -+} -+ -+/* -+ * 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; -+ -+ if (!of_device_is_compatible(mvchip->chip.of_node, -+ "marvell,armada-370-xp-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; -+ else if (id == 1) -+ set = U32_MAX; -+ else -+ return -EINVAL; -+ writel_relaxed(set, mvebu_gpioreg_blink_select(mvchip)); -+ mvpwm->id = id; -+ -+ mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL); -+ if (!mvpwm) -+ return -ENOMEM; -+ mvchip->mvpwm = mvpwm; -+ mvpwm->mvchip = mvchip; -+ -+ mvpwm->membase = devm_ioremap_resource(dev, res); -+ if (IS_ERR(mvpwm->membase)) -+ return PTR_ERR(mvpwm->membase); -+ -+ mvpwm->clk_rate = clk_get_rate(mvchip->clk); -+ if (!mvpwm->clk_rate) { -+ dev_err(dev, "failed to get clock rate\n"); -+ return -EINVAL; -+ } -+ -+ mvpwm->chip.dev = dev; -+ mvpwm->chip.ops = &mvebu_pwm_ops; -+ mvpwm->chip.npwm = mvchip->chip.ngpio; -+ -+ spin_lock_init(&mvpwm->lock); -+ -+ return pwmchip_add(&mvpwm->chip); -+} -+ - #ifdef CONFIG_DEBUG_FS - #include - -@@ -561,6 +829,10 @@ static const struct of_device_id mvebu_gpio_of_match[] = { - .data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP, - }, - { -+ .compatible = "marvell,armada-370-xp-gpio", -+ .data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION, -+ }, -+ { - /* sentinel */ - }, - }; -@@ -607,6 +879,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 +925,9 @@ static int mvebu_gpio_resume(struct platform_device *pdev) - BUG(); - } - -+ if (IS_ENABLED(CONFIG_PWM)) -+ mvebu_pwm_resume(mvchip); -+ - return 0; - } - -@@ -661,7 +939,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 +972,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 +1112,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: --- -2.7.4 - diff --git a/patch/kernel/mvebu-default/91-ARM-dts-mvebu-Add-PWM-properties-to-.dtsi-armada-38x.patch.disabled b/patch/kernel/mvebu-default/91-ARM-dts-mvebu-Add-PWM-properties-to-.dtsi-armada-38x.patch.disabled deleted file mode 100644 index e19aa068d1..0000000000 --- a/patch/kernel/mvebu-default/91-ARM-dts-mvebu-Add-PWM-properties-to-.dtsi-armada-38x.patch.disabled +++ /dev/null @@ -1,62 +0,0 @@ -From e85a492b45f49e374f544bbffe8c975b1dabe87f Mon Sep 17 00:00:00 2001 -From: aprayoga -Date: Sun, 3 Sep 2017 16:08:59 +0800 -Subject: ARM: dts: mvebu: Add PWM properties to .dtsi (armada-38x) - -reference: -https://patchwork.kernel.org/patch/9681397/ ---- - arch/arm/boot/dts/armada-38x.dtsi | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi -index a73cbe2..f87204f 100644 ---- a/arch/arm/boot/dts/armada-38x.dtsi -+++ b/arch/arm/boot/dts/armada-38x.dtsi -@@ -345,31 +345,39 @@ - }; - - gpio0: gpio@18100 { -- compatible = "marvell,orion-gpio"; -- reg = <0x18100 0x40>; -+ compatible = "marvell,armada-370-xp-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 = , - , - , - ; -+ clocks = <&coreclk 0>; - }; - - gpio1: gpio@18140 { -- compatible = "marvell,orion-gpio"; -- reg = <0x18140 0x40>; -+ compatible = "marvell,armada-370-xp-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 = , - , - , - ; -+ clocks = <&coreclk 0>; - }; - - system-controller@18200 { --- -2.7.4 - diff --git a/patch/kernel/mvebu-default/93-net-phy-marvell-88e1510_fixed_led_act.patch b/patch/kernel/mvebu-default/93-net-phy-marvell-88e1510_fixed_led_act.patch new file mode 100644 index 0000000000..27312e0cc4 --- /dev/null +++ b/patch/kernel/mvebu-default/93-net-phy-marvell-88e1510_fixed_led_act.patch @@ -0,0 +1,365 @@ +diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c +index 7cfb3f4..8143b07 100644 +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -39,6 +39,8 @@ + #include + + #define MII_MARVELL_PHY_PAGE 22 ++#define MII_MARVELL_COPPER_PAGE 0x00 ++#define MII_MARVELL_FIBER_PAGE 0x01 + + #define MII_M1011_IEVENT 0x13 + #define MII_M1011_IEVENT_CLEAR 0x0000 +@@ -136,6 +138,24 @@ + #define MII_88E1510_PHY_INTERNAL_REG_1 16 + #define MII_88E1510_PHY_INTERNAL_REG_2 17 + #define MII_88E1510_PHY_GENERAL_CTRL_1 20 ++#define MII_88E1510_PHY_GENERAL_CTRL_1_MODE_MASK 0x7 ++#define MII_88E1510_PHY_GENERAL_CTRL_1_MODE_SGMII 0x1 /* SGMII to copper */ ++#define MII_88E1510_PHY_GENERAL_CTRL_1_RESET 0x8000 /* Soft reset */ ++ ++#define LPA_FIBER_1000HALF 0x40 ++#define LPA_FIBER_1000FULL 0x20 ++ ++#define LPA_PAUSE_FIBER 0x180 ++#define LPA_PAUSE_ASYM_FIBER 0x100 ++ ++#define ADVERTISE_FIBER_1000HALF 0x40 ++#define ADVERTISE_FIBER_1000FULL 0x20 ++ ++#define ADVERTISE_PAUSE_FIBER 0x180 ++#define ADVERTISE_PAUSE_ASYM_FIBER 0x100 ++ ++#define REGISTER_LINK_STATUS 0x400 ++#define NB_FIBER_STATS 1 + + MODULE_DESCRIPTION("Marvell PHY driver"); + MODULE_AUTHOR("Andy Fleming"); +@@ -149,8 +169,9 @@ struct marvell_hw_stat { + }; + + static struct marvell_hw_stat marvell_hw_stats[] = { +- { "phy_receive_errors", 0, 21, 16}, ++ { "phy_receive_errors_copper", 0, 21, 16}, + { "phy_idle_errors", 0, 10, 8 }, ++ { "phy_receive_errors_fiber", 1, 21, 16}, + }; + + struct marvell_priv { +@@ -378,7 +399,6 @@ static int m88e1121_config_aneg(struct phy_device *phydev) + return err; + + if (phy_interface_is_rgmii(phydev)) { +- + mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) & + MII_88E1121_PHY_MSCR_DELAY_MASK; + +@@ -406,15 +426,7 @@ static int m88e1121_config_aneg(struct phy_device *phydev) + if (err < 0) + return err; + +- oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); +- +- phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_88E1121_PHY_LED_PAGE); +- phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF); +- phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); +- +- err = genphy_config_aneg(phydev); +- +- return err; ++ return genphy_config_aneg(phydev); + } + + static int m88e1318_config_aneg(struct phy_device *phydev) +@@ -422,6 +434,8 @@ static int m88e1318_config_aneg(struct phy_device *phydev) + int err, oldpage, mscr; + + oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); ++ if (oldpage < 0) ++ return oldpage; + + err = phy_write(phydev, MII_MARVELL_PHY_PAGE, + MII_88E1121_PHY_MSCR_PAGE); +@@ -442,15 +456,122 @@ static int m88e1318_config_aneg(struct phy_device *phydev) + return m88e1121_config_aneg(phydev); + } + ++/** ++ * ethtool_adv_to_fiber_adv_t ++ * @ethadv: the ethtool advertisement settings ++ * ++ * A small helper function that translates ethtool advertisement ++ * settings to phy autonegotiation advertisements for the ++ * MII_ADV register for fiber link. ++ */ ++static inline u32 ethtool_adv_to_fiber_adv_t(u32 ethadv) ++{ ++ u32 result = 0; ++ ++ if (ethadv & ADVERTISED_1000baseT_Half) ++ result |= ADVERTISE_FIBER_1000HALF; ++ if (ethadv & ADVERTISED_1000baseT_Full) ++ result |= ADVERTISE_FIBER_1000FULL; ++ ++ if ((ethadv & ADVERTISE_PAUSE_ASYM) && (ethadv & ADVERTISE_PAUSE_CAP)) ++ result |= LPA_PAUSE_ASYM_FIBER; ++ else if (ethadv & ADVERTISE_PAUSE_CAP) ++ result |= (ADVERTISE_PAUSE_FIBER ++ & (~ADVERTISE_PAUSE_ASYM_FIBER)); ++ ++ return result; ++} ++ ++/** ++ * marvell_config_aneg_fiber - restart auto-negotiation or write BMCR ++ * @phydev: target phy_device struct ++ * ++ * Description: If auto-negotiation is enabled, we configure the ++ * advertising, and then restart auto-negotiation. If it is not ++ * enabled, then we write the BMCR. Adapted for fiber link in ++ * some Marvell's devices. ++ */ ++static int marvell_config_aneg_fiber(struct phy_device *phydev) ++{ ++ int changed = 0; ++ int err; ++ int adv, oldadv; ++ u32 advertise; ++ ++ if (phydev->autoneg != AUTONEG_ENABLE) ++ return genphy_setup_forced(phydev); ++ ++ /* Only allow advertising what this PHY supports */ ++ phydev->advertising &= phydev->supported; ++ advertise = phydev->advertising; ++ ++ /* Setup fiber advertisement */ ++ adv = phy_read(phydev, MII_ADVERTISE); ++ if (adv < 0) ++ return adv; ++ ++ oldadv = adv; ++ adv &= ~(ADVERTISE_FIBER_1000HALF | ADVERTISE_FIBER_1000FULL ++ | LPA_PAUSE_FIBER); ++ adv |= ethtool_adv_to_fiber_adv_t(advertise); ++ ++ if (adv != oldadv) { ++ err = phy_write(phydev, MII_ADVERTISE, adv); ++ if (err < 0) ++ return err; ++ ++ changed = 1; ++ } ++ ++ if (changed == 0) { ++ /* Advertisement hasn't changed, but maybe aneg was never on to ++ * begin with? Or maybe phy was isolated? ++ */ ++ int ctl = phy_read(phydev, MII_BMCR); ++ ++ if (ctl < 0) ++ return ctl; ++ ++ if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE)) ++ changed = 1; /* do restart aneg */ ++ } ++ ++ /* Only restart aneg if we are advertising something different ++ * than we were before. ++ */ ++ if (changed > 0) ++ changed = genphy_restart_aneg(phydev); ++ ++ return changed; ++} ++ + static int m88e1510_config_aneg(struct phy_device *phydev) + { + int err; + ++ err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_MARVELL_COPPER_PAGE); ++ if (err < 0) ++ goto error; ++ ++ /* Configure the copper link first */ + err = m88e1318_config_aneg(phydev); + if (err < 0) +- return err; ++ goto error; + +- return 0; ++ /* Then the fiber link */ ++ err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_MARVELL_FIBER_PAGE); ++ if (err < 0) ++ goto error; ++ ++ err = marvell_config_aneg_fiber(phydev); ++ if (err < 0) ++ goto error; ++ ++ return phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_MARVELL_COPPER_PAGE); ++ ++error: ++ err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_MARVELL_COPPER_PAGE); ++ return err; + } + + static int marvell_config_init(struct phy_device *phydev) +@@ -635,109 +756,65 @@ static int m88e1111_config_init(struct phy_device *phydev) + return phy_write(phydev, MII_BMCR, BMCR_RESET); + } + +-static int m88e1510_phy_writebits(struct phy_device *phydev, +- u8 reg_num, u16 offset, u16 len, u16 data) ++static int m88e1121_config_init(struct phy_device *phydev) + { +- int err; +- int reg; +- u16 mask; ++ int err, oldpage; + +- if ((len + offset) >= 16) +- mask = 0 - (1 << offset); +- else +- mask = (1 << (len + offset)) - (1 << offset); ++ oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); ++ if (oldpage < 0) ++ return oldpage; + +- reg = phy_read(phydev, reg_num); +- if (reg < 0) +- return reg; ++ phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_88E1121_PHY_LED_PAGE); + +- reg &= ~mask; +- reg |= data << offset; ++ /* Default PHY LED config: LED[0] .. Link, LED[1] .. Activity */ ++ err = phy_write(phydev, MII_88E1121_PHY_LED_CTRL, ++ MII_88E1121_PHY_LED_DEF); ++ if (err < 0) ++ return err; + +- err = phy_write(phydev, reg_num, (u16)reg); ++ err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); ++ if (err < 0) ++ return err; + +- return err; ++ /* Set marvell,reg-init configuration from device tree */ ++ return marvell_config_init(phydev); + } + +-/* For Marvell 88E1510/88E1518/88E1512/88E1514, need to fix the Errata in +- * SGMII mode, which is described in Marvell Release Notes Errata Section 3.1. +- * Besides of that, the 88E151X serial PHY should be initialized as legacy +- * Marvell 88E1111 PHY. +- */ + static int m88e1510_config_init(struct phy_device *phydev) + { + int err; ++ int temp; + +- /* As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512 +- * /88E1514 Rev A0, Errata Section 3.1 +- */ ++ /* SGMII-to-Copper mode initialization */ + if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { +- err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x00ff); +- if (err < 0) +- return err; +- +- err = phy_write(phydev, MII_88E1510_PHY_INTERNAL_REG_2, 0x214B); +- if (err < 0) +- return err; +- +- err = phy_write(phydev, MII_88E1510_PHY_INTERNAL_REG_1, 0x2144); +- if (err < 0) +- return err; +- +- err = phy_write(phydev, MII_88E1510_PHY_INTERNAL_REG_2, 0x0C28); +- if (err < 0) +- return err; +- +- err = phy_write(phydev, MII_88E1510_PHY_INTERNAL_REG_1, 0x2146); +- if (err < 0) +- return err; +- +- err = phy_write(phydev, MII_88E1510_PHY_INTERNAL_REG_2, 0xB233); +- if (err < 0) +- return err; +- +- err = phy_write(phydev, MII_88E1510_PHY_INTERNAL_REG_1, 0x214D); +- if (err < 0) +- return err; +- +- err = phy_write(phydev, MII_88E1510_PHY_INTERNAL_REG_2, 0xCC0C); +- if (err < 0) +- return err; +- +- err = phy_write(phydev, MII_88E1510_PHY_INTERNAL_REG_1, 0x2159); +- if (err < 0) +- return err; +- +- err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0); +- if (err < 0) +- return err; +- ++ /* Select page 18 */ + err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 18); + if (err < 0) + return err; + +- /* Write HWCFG_MODE = SGMII to Copper */ +- err = m88e1510_phy_writebits(phydev, +- MII_88E1510_PHY_GENERAL_CTRL_1, +- 0, 3, 1); ++ /* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */ ++ temp = phy_read(phydev, MII_88E1510_PHY_GENERAL_CTRL_1); ++ temp &= ~MII_88E1510_PHY_GENERAL_CTRL_1_MODE_MASK; ++ temp |= MII_88E1510_PHY_GENERAL_CTRL_1_MODE_SGMII; ++ err = phy_write(phydev, MII_88E1510_PHY_GENERAL_CTRL_1, temp); + if (err < 0) + return err; + +- /* Phy reset */ +- err = m88e1510_phy_writebits(phydev, +- MII_88E1510_PHY_GENERAL_CTRL_1, +- 15, 1, 1); ++ /* PHY reset is necessary after changing MODE[2:0] */ ++ temp |= MII_88E1510_PHY_GENERAL_CTRL_1_RESET; ++ err = phy_write(phydev, MII_88E1510_PHY_GENERAL_CTRL_1, temp); + if (err < 0) + return err; + +- err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0); ++ /* Reset page selection */ ++ err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_MARVELL_COPPER_PAGE); + if (err < 0) + return err; + + usleep_range(100, 200); + } + +- return m88e1111_config_init(phydev); ++ return m88e1121_config_init(phydev); + } + + static int m88e1118_config_aneg(struct phy_device *phydev) +@@ -1372,7 +1449,7 @@ static struct phy_driver marvell_drivers[] = { + .phy_id = MARVELL_PHY_ID_88E1510, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1510", +- .features = PHY_GBIT_FEATURES | SUPPORTED_Pause, ++ .features = PHY_GBIT_FEATURES | SUPPORTED_FIBRE | SUPPORTED_Pause, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1510_config_init, + .config_aneg = &m88e1510_config_aneg, +@@ -1391,7 +1468,6 @@ static struct phy_driver marvell_drivers[] = { + .flags = PHY_HAS_INTERRUPT, + .probe = marvell_probe, + .config_init = &marvell_config_init, +- .config_init = &marvell_config_init, + .config_aneg = &m88e1510_config_aneg, + .read_status = &marvell_read_status, + .ack_interrupt = &marvell_ack_interrupt, diff --git a/patch/kernel/mvebu-default/94-01-Enable-ATA-port-LED-trigger.patch b/patch/kernel/mvebu-default/94-01-Enable-ATA-port-LED-trigger.patch new file mode 100644 index 0000000000..6cc27c187e --- /dev/null +++ b/patch/kernel/mvebu-default/94-01-Enable-ATA-port-LED-trigger.patch @@ -0,0 +1,25 @@ +From 9ee6345ef82f7af5f98e17a40e667f8ad6b2fa1b Mon Sep 17 00:00:00 2001 +From: aprayoga +Date: Sun, 3 Sep 2017 18:10:12 +0800 +Subject: Enable ATA port LED trigger + +--- + arch/arm/configs/mvebu_v7_defconfig | 1 + + arch/arm/mach-mvebu/Kconfig | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig +index 053ea9d..aa1f389 100644 +--- a/arch/arm/mach-mvebu/Kconfig ++++ b/arch/arm/mach-mvebu/Kconfig +@@ -52,6 +52,7 @@ config MACH_ARMADA_375 + + config MACH_ARMADA_38X + bool "Marvell Armada 380/385 boards" if ARCH_MULTI_V7 ++ select ARCH_WANT_LIBATA_LEDS + select ARM_ERRATA_720789 + select ARM_ERRATA_753970 + select ARM_GIC +-- +2.7.4 + diff --git a/patch/kernel/mvebu-default/92-libata-add-ledtrig-support.patch b/patch/kernel/mvebu-default/94-01-libata-add-ledtrig-support.patch similarity index 100% rename from patch/kernel/mvebu-default/92-libata-add-ledtrig-support.patch rename to patch/kernel/mvebu-default/94-01-libata-add-ledtrig-support.patch diff --git a/patch/kernel/mvebu-default/95-helios4-device-tree.patch b/patch/kernel/mvebu-default/95-helios4-device-tree.patch index 0a1ec90cc9..fbbc6c2c63 100644 --- a/patch/kernel/mvebu-default/95-helios4-device-tree.patch +++ b/patch/kernel/mvebu-default/95-helios4-device-tree.patch @@ -8,21 +8,20 @@ Subject: Initial device tree - All 7 LED declared as led-gpio - LED1 (system) default to hearbeat - LED7 (USB) triggered by USB Host activity -- GPIO23 (MPP23) declared as GPIO button - SPI NOR flash declared as MTD - Enable IO expander interrupt - Allocate GPIOs for fans --- - arch/arm/boot/dts/armada-388-helios4.dts | 318 ++++++++++++++++++++++++++++++ - 1 file changed, 318 insertions(+) + 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..b7a2122 +index 0000000..19a0256 --- /dev/null +++ b/arch/arm/boot/dts/armada-388-helios4.dts -@@ -0,0 +1,346 @@ +@@ -0,0 +1,318 @@ +/* + * Device Tree file for Helios4 + * based on SolidRun Clearfog revision A1 rev 2.0 (88F6828) @@ -42,7 +41,7 @@ index 0000000..b7a2122 + + memory { + device_type = "memory"; -+ reg = <0x00000000 0x40000000>; /* 1 GB */ ++ reg = <0x00000000 0x80000000>; /* 2 GB */ + }; + + aliases { @@ -92,19 +91,6 @@ index 0000000..b7a2122 + vin-supply = <®_12v>; + }; + -+ gpio-keys { -+ compatible = "gpio-keys"; -+ pinctrl-0 = <&user_button_pins>; -+ pinctrl-names = "default"; -+ -+ button_0 { -+ label = "User Button"; -+ gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; -+ linux,can-disable; -+ linux,code = ; -+ }; -+ }; -+ + system-leds { + compatible = "gpio-leds"; + status-led { @@ -116,7 +102,7 @@ index 0000000..b7a2122 + + fault-led { + label = "helios4:red:fault"; -+ gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; ++ gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + default-state = "keep"; + }; + }; @@ -156,13 +142,17 @@ index 0000000..b7a2122 + }; + + fan1: j10-pwm { -+ compatible = "pwm-fan"; -+ pwms = <&gpio1 9 3000>; ++ 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 4 4500>; ++ compatible = "gpio-fan"; ++ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; ++ gpio-fan,speed-map = < 0 0 ++ 3800 1>; + }; + + usb2_phy: usb2-phy { @@ -178,7 +168,7 @@ index 0000000..b7a2122 + soc { + internal-regs { + i2c@11000 { -+ clock-frequency = <100000>; ++ clock-frequency = <400000>; + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + status = "okay"; @@ -205,7 +195,7 @@ index 0000000..b7a2122 + pinctrl-names = "default"; + pinctrl-0 = <&pca0_pins>; + interrupt-parent = <&gpio0>; -+ interrupts = <18 IRQ_TYPE_EDGE_FALLING>; ++ interrupts = <23 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + @@ -234,8 +224,6 @@ index 0000000..b7a2122 + reg = <0x4c>; + vcc-supply = <®_3p3v>; + }; -+ -+ /* What device at 0x64 ? */ + }; + + i2c@11100 { @@ -281,16 +269,6 @@ index 0000000..b7a2122 + µsom_spi1_cs_pins>; + pinctrl-names = "default"; + status = "okay"; -+ -+ spi-flash@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "w25q32", "jedec,spi-nor"; -+ reg = <0>; /* Chip select 0 */ -+ spi-max-frequency = <104000000>; -+ spi-cpha; -+ status = "okay"; -+ }; + }; + + sdhci@d8000 { @@ -303,13 +281,6 @@ index 0000000..b7a2122 + status = "okay"; + vmmc = <®_3p3v>; + wp-inverted; -+ max-frequency = <50000000>; -+ cap-sd-highspeed; -+ sd-uhs-sdr12; -+ sd-uhs-sdr25; -+ sd-uhs-sdr50; -+ keep-power-in-suspend; -+ wakeup-source; + }; + + usb@58000 { @@ -327,7 +298,11 @@ index 0000000..b7a2122 + }; + + pinctrl@18000 { -+ pca0_pins: pca0_pins { ++ pca0_pins: pca0-pins { ++ marvell,pins = "mpp23"; ++ marvell,function = "gpio"; ++ }; ++ microsom_phy0_int_pins: microsom-phy0-int-pins { + marvell,pins = "mpp18"; + marvell,function = "gpio"; + }; @@ -354,17 +329,13 @@ index 0000000..b7a2122 + }; + helios_fan_pins: helios-fan-pins { + marvell,pins = "mpp41", "mpp43", -+ "mpp36", "mpp25"; ++ "mpp48", "mpp55"; + marvell,function = "gpio"; + }; + microsom_spi1_cs_pins: spi1-cs-pins { + marvell,pins = "mpp59"; + marvell,function = "spi1"; + }; -+ user_button_pins: user-button-pins { -+ marvell,pins = "mpp23"; -+ marvell,function = "gpio"; -+ }; + }; + }; + }; @@ -382,6 +353,6 @@ diff -u a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile armada-388-gp.dtb \ armada-388-rd.dtb --- +-- 2.7.4 diff --git a/patch/kernel/mvebu-next/91-01-libata-add-ledtrig-support.patch b/patch/kernel/mvebu-next/91-01-libata-add-ledtrig-support.patch new file mode 100644 index 0000000000..272964ec11 --- /dev/null +++ b/patch/kernel/mvebu-next/91-01-libata-add-ledtrig-support.patch @@ -0,0 +1,179 @@ +From 5843af891d0dabf9bb80039cfe807d01e9495154 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 12 Dec 2014 13:38:33 +0100 +Subject: libata: add ledtrig support + +This adds a LED trigger for each ATA port indicating disk activity. + +As this is needed only on specific platforms (NAS SoCs and such), +these platforms should define ARCH_WANTS_LIBATA_LEDS if there +are boards with LED(s) intended to indicate ATA disk activity and +need the OS to take care of that. +In that way, if not selected, LED trigger support not will be +included in libata-core and both, codepaths and structures remain +untouched. + +Signed-off-by: Daniel Golle +--- + drivers/ata/Kconfig | 16 ++++++++++++++ + drivers/ata/libata-core.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/libata.h | 7 ++++++ + 3 files changed, 79 insertions(+) + +diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig +index 6aaa3f8..4e24b64 100644 +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -46,6 +46,22 @@ config ATA_VERBOSE_ERROR + + If unsure, say Y. + ++config ARCH_WANT_LIBATA_LEDS ++ bool ++ ++config ATA_LEDS ++ bool "support ATA port LED triggers" ++ depends on ARCH_WANT_LIBATA_LEDS ++ select NEW_LEDS ++ select LEDS_CLASS ++ select LEDS_TRIGGERS ++ default y ++ help ++ This option adds a LED trigger for each registered ATA port. ++ It is used to drive disk activity leds connected via GPIO. ++ ++ If unsure, say N. ++ + config ATA_ACPI + bool "ATA ACPI Support" + depends on ACPI +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index b0b77b6..1400f4d 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -728,6 +728,7 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) + return block; + } + ++ + /** + * ata_build_rw_tf - Build ATA taskfile for given read/write request + * @tf: Target ATA taskfile +@@ -4757,6 +4758,30 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) + } + + /** ++ * ata_led_act - Trigger port activity LED ++ * @ap: indicating port ++ * ++ * Blinks any LEDs registered to the trigger. ++ * Commonly used with leds-gpio on NAS systems with disk activity ++ * indicator LEDs. ++ * ++ * LOCKING: ++ * None. ++ */ ++static inline void ata_led_act(struct ata_port *ap) ++{ ++#if CONFIG_ATA_LEDS ++#define LIBATA_BLINK_DELAY 20 /* ms */ ++ unsigned long led_delay = LIBATA_BLINK_DELAY; ++ ++ if (unlikely(!ap->ledtrig)) ++ return; ++ ++ led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0); ++#endif /* CONFIG_ATA_LEDS */ ++} ++ ++/** + * ata_qc_new_init - Request an available ATA command, and initialize it + * @dev: Device from whom we request an available command structure + * @tag: tag +@@ -4780,6 +4805,9 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag) + if (tag < 0) + return NULL; + } ++#if CONFIG_ATA_LEDS ++ ata_led_act(ap); ++#endif + + qc = __ata_qc_from_tag(ap, tag); + qc->tag = tag; +@@ -5677,6 +5705,9 @@ struct ata_port *ata_port_alloc(struct ata_host *host) + ap->stats.unhandled_irq = 1; + ap->stats.idle_irq = 1; + #endif ++#if CONFIG_ATA_LEDS ++ ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); ++#endif + ata_sff_port_init(ap); + + return ap; +@@ -5698,6 +5729,12 @@ static void ata_host_release(struct device *gendev, void *res) + + kfree(ap->pmp_link); + kfree(ap->slave_link); ++#if CONFIG_ATA_LEDS ++ if (ap->ledtrig) { ++ led_trigger_unregister(ap->ledtrig); ++ kfree(ap->ledtrig); ++ }; ++#endif + kfree(ap); + host->ports[i] = NULL; + } +@@ -6145,6 +6182,25 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) + host->ports[i]->local_port_no = i + 1; + } + ++#if CONFIG_ATA_LEDS ++ /* register LED triggers for all ports */ ++ for (i = 0; i < host->n_ports; i++) { ++ if (unlikely(!host->ports[i]->ledtrig)) ++ continue; ++ ++ snprintf(host->ports[i]->ledtrig_name, ++ sizeof(host->ports[i]->ledtrig_name), "ata%u", ++ host->ports[i]->print_id); ++ ++ host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name; ++ ++ if (led_trigger_register(host->ports[i]->ledtrig)) { ++ kfree(host->ports[i]->ledtrig); ++ host->ports[i]->ledtrig = NULL; ++ } ++ } ++#endif ++ + /* Create associated sysfs transport objects */ + for (i = 0; i < host->n_ports; i++) { + rc = ata_tport_add(host->dev,host->ports[i]); +diff --git a/include/linux/libata.h b/include/linux/libata.h +index b20a275..50eeee3 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + /* + * Define if arch has non-standard setup. This is a _PCI_ standard +@@ -877,6 +878,12 @@ struct ata_port { + #ifdef CONFIG_ATA_ACPI + struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */ + #endif ++ ++#ifdef CONFIG_ATA_LEDS ++ struct led_trigger *ledtrig; ++ char ledtrig_name[8]; ++#endif ++ + /* owned by EH */ + u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned; + }; +-- +2.7.4 + diff --git a/patch/kernel/mvebu-default/93-Enable-ATA-port-LED-trigger.patch b/patch/kernel/mvebu-next/91-02-Enable-ATA-port-LED-trigger.patch similarity index 90% rename from patch/kernel/mvebu-default/93-Enable-ATA-port-LED-trigger.patch rename to patch/kernel/mvebu-next/91-02-Enable-ATA-port-LED-trigger.patch index 2b5952f120..472d9b9946 100644 --- a/patch/kernel/mvebu-default/93-Enable-ATA-port-LED-trigger.patch +++ b/patch/kernel/mvebu-next/91-02-Enable-ATA-port-LED-trigger.patch @@ -24,10 +24,10 @@ diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 053ea9d..aa1f389 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig -@@ -52,6 +52,7 @@ config MACH_ARMADA_375 - +@@ -57,6 +57,7 @@ config MACH_ARMADA_375 config MACH_ARMADA_38X - bool "Marvell Armada 380/385 boards" if ARCH_MULTI_V7 + bool "Marvell Armada 380/385 boards" + depends on ARCH_MULTI_V7 + select ARCH_WANT_LIBATA_LEDS select ARM_ERRATA_720789 select ARM_ERRATA_753970 diff --git a/patch/kernel/mvebu-next/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch b/patch/kernel/mvebu-next/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch new file mode 100644 index 0000000000..bcc3976d0b --- /dev/null +++ b/patch/kernel/mvebu-next/92-mvebu-gpio-remove-hardcoded-timer-assignment.patch @@ -0,0 +1,352 @@ +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index 45c65f8..2ec4a15 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -93,20 +93,41 @@ + + #define MVEBU_MAX_GPIO_PER_BANK 32 + +-struct mvebu_pwm { ++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; +- spinlock_t lock; + 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; +- u32 blink_on_duration; +- u32 blink_off_duration; + }; + ++static struct mvebu_pwmchip *mvebu_pwm_list[MVEBU_PWM_CTRL_MAX]; ++ + struct mvebu_gpio_chip { + struct gpio_chip chip; + struct regmap *regs; +@@ -283,12 +304,12 @@ mvebu_gpio_write_level_mask(struct mvebu_gpio_chip *mvchip, u32 val) + * Functions returning addresses of individual registers for a given + * PWM controller. + */ +-static void __iomem *mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm) ++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_pwm *mvpwm) ++static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwmchip *mvpwm) + { + return mvpwm->membase + PWM_BLINK_OFF_DURATION_OFF; + } +@@ -600,46 +621,80 @@ 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; + unsigned long flags; + int ret = 0; ++ struct mvebu_pwm_chip_drv *chip_data; + +- spin_lock_irqsave(&mvpwm->lock, flags); ++ spin_lock_irqsave(&mvpwm->controller.lock, flags); + +- if (mvpwm->gpiod) { +- ret = -EBUSY; +- } else { +- desc = gpio_to_desc(mvchip->chip.base + pwm->hwpwm); +- if (!desc) { +- ret = -ENODEV; +- goto out; +- } ++ regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, ++ &mvchip->blink_en_reg); ++ if (pwm->chip_data || (mvchip->blink_en_reg & BIT(pwm->hwpwm))) ++ return -EBUSY; + +- ret = gpiod_request(desc, "mvebu-pwm"); +- if (ret) +- goto out; ++ desc = gpio_to_desc(mvchip->chip.base + pwm->hwpwm); ++ if (!desc) { ++ ret = -ENODEV; ++ goto out; ++ } + +- ret = gpiod_direction_output(desc, 0); +- if (ret) { +- gpiod_free(desc); +- goto out; +- } ++ ret = gpiod_request(desc, "mvebu-pwm"); ++ if (ret) ++ goto out; + +- mvpwm->gpiod = desc; ++ 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; ++ ++ regmap_update_bits(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, ++ BIT(pwm->hwpwm), chip_data->ctrl ? BIT(pwm->hwpwm) : 0); ++ ++ chip_data->gpiod = desc; ++ pwm->chip_data = chip_data; ++ ++ regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, ++ &mvpwm->blink_select); + out: +- spin_unlock_irqrestore(&mvpwm->lock, flags); ++ spin_unlock_irqrestore(&mvpwm->controller.lock, flags); + 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->lock, flags); +- gpiod_free(mvpwm->gpiod); +- mvpwm->gpiod = NULL; +- spin_unlock_irqrestore(&mvpwm->lock, 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 void mvebu_pwm_get_state(struct pwm_chip *chip, +@@ -647,17 +702,24 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, + struct pwm_state *state) { + + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); ++ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data; ++ struct mvebu_pwmchip *controller; + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; + unsigned long long val; + unsigned long flags; + u32 u; + +- spin_lock_irqsave(&mvpwm->lock, flags); ++ if (chip_data) ++ controller = mvebu_pwm_list[chip_data->ctrl]; ++ else ++ controller = &mvpwm->controller; ++ ++ spin_lock_irqsave(&controller->lock, flags); + + val = (unsigned long long) +- readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); ++ readl_relaxed(mvebu_pwmreg_blink_on_duration(controller)); + val *= NSEC_PER_SEC; +- do_div(val, mvpwm->clk_rate); ++ do_div(val, controller->clk_rate); + if (val > UINT_MAX) + state->duty_cycle = UINT_MAX; + else if (val) +@@ -666,9 +728,9 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, + state->duty_cycle = 1; + + val = (unsigned long long) +- readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); ++ readl_relaxed(mvebu_pwmreg_blink_off_duration(controller)); + val *= NSEC_PER_SEC; +- do_div(val, mvpwm->clk_rate); ++ do_div(val, controller->clk_rate); + if (val < state->duty_cycle) { + state->period = 1; + } else { +@@ -687,19 +749,21 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, + else + state->enabled = false; + +- spin_unlock_irqrestore(&mvpwm->lock, flags); ++ spin_unlock_irqrestore(&controller->lock, flags); + } + + static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) + { + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); ++ struct mvebu_pwm_chip_drv *chip_data = (struct mvebu_pwm_chip_drv*) pwm->chip_data; ++ struct mvebu_pwmchip *controller = mvebu_pwm_list[chip_data->ctrl]; + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; + unsigned long long val; + unsigned long flags; + unsigned int on, off; + +- val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle; ++ val = (unsigned long long) controller->clk_rate * state->duty_cycle; + do_div(val, NSEC_PER_SEC); + if (val > UINT_MAX) + return -EINVAL; +@@ -708,7 +772,7 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + else + on = 1; + +- val = (unsigned long long) mvpwm->clk_rate * ++ val = (unsigned long long) controller->clk_rate * + (state->period - state->duty_cycle); + do_div(val, NSEC_PER_SEC); + if (val > UINT_MAX) +@@ -718,16 +782,16 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + else + off = 1; + +- spin_lock_irqsave(&mvpwm->lock, flags); ++ spin_lock_irqsave(&controller->lock, flags); + +- writel_relaxed(on, mvebu_pwmreg_blink_on_duration(mvpwm)); +- writel_relaxed(off, mvebu_pwmreg_blink_off_duration(mvpwm)); ++ writel_relaxed(on, mvebu_pwmreg_blink_on_duration(controller)); ++ writel_relaxed(off, mvebu_pwmreg_blink_off_duration(controller)); + if (state->enabled) + mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1); + else + mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 0); + +- spin_unlock_irqrestore(&mvpwm->lock, flags); ++ spin_unlock_irqrestore(&controller->lock, flags); + + return 0; + } +@@ -746,10 +810,10 @@ static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip) + + regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, + &mvpwm->blink_select); +- mvpwm->blink_on_duration = +- readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); +- mvpwm->blink_off_duration = +- readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); ++ 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 __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip) +@@ -758,10 +822,10 @@ static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip) + + regmap_write(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, + mvpwm->blink_select); +- writel_relaxed(mvpwm->blink_on_duration, +- mvebu_pwmreg_blink_on_duration(mvpwm)); +- writel_relaxed(mvpwm->blink_off_duration, +- mvebu_pwmreg_blink_off_duration(mvpwm)); ++ 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)); + } + + static int mvebu_pwm_probe(struct platform_device *pdev, +@@ -772,6 +836,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + 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")) +@@ -794,12 +859,15 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + * 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) ++ if (id == 0) { + set = 0; +- else if (id == 1) ++ ctrl_set = MVEBU_PWM_CTRL_SET_A; ++ } else if (id == 1) { + set = U32_MAX; +- else ++ ctrl_set = MVEBU_PWM_CTRL_SET_B; ++ } else { + return -EINVAL; ++ } + regmap_write(mvchip->regs, + GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset, set); + +@@ -809,15 +877,13 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + mvchip->mvpwm = mvpwm; + mvpwm->mvchip = mvchip; + +- mvpwm->membase = devm_ioremap_resource(dev, res); +- if (IS_ERR(mvpwm->membase)) +- return PTR_ERR(mvpwm->membase); ++ mvpwm->controller.membase = devm_ioremap_resource(dev, res); ++ if (IS_ERR(mvpwm->controller.membase)) ++ return PTR_ERR(mvpwm->controller.membase); + +- mvpwm->clk_rate = clk_get_rate(mvchip->clk); +- if (!mvpwm->clk_rate) { +- dev_err(dev, "failed to get clock rate\n"); ++ 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; +@@ -830,7 +896,9 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + */ + mvpwm->chip.base = -1; + +- spin_lock_init(&mvpwm->lock); ++ spin_lock_init(&mvpwm->controller.lock); ++ mvpwm->default_counter = ctrl_set; ++ mvebu_pwm_list[ctrl_set] = &mvpwm->controller; + + return pwmchip_add(&mvpwm->chip); + } diff --git a/patch/kernel/mvebu-next/93-helios4-device-tree.patch b/patch/kernel/mvebu-next/93-helios4-device-tree.patch new file mode 100644 index 0000000000..ff18c48d86 --- /dev/null +++ b/patch/kernel/mvebu-next/93-helios4-device-tree.patch @@ -0,0 +1,331 @@ + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/armada-388-helios4.dts | 309 +++++++++++++++++++++ + 2 files changed, 310 insertions(+) + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 4b17f35..c6b6038 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -1020,6 +1020,7 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \ + armada-388-clearfog.dtb \ + armada-388-clearfog-base.dtb \ + armada-388-clearfog-pro.dtb \ ++ armada-388-helios4.dtb \ + armada-388-db.dtb \ + armada-388-gp.dtb \ + armada-388-rd.dtb +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..93d0132 +--- /dev/null ++++ b/arch/arm/boot/dts/armada-388-helios4.dts +@@ -0,0 +1,309 @@ ++/* ++ * Device Tree file for Helios4 ++ * based on SolidRun Clearfog revision A1 rev 2.0 (88F6828) ++ * ++ * Copyright (C) 2017 Kobol.io ++ * ++ */ ++ ++/dts-v1/; ++#include "armada-388.dtsi" ++#include "armada-38x-solidrun-microsom.dtsi" ++ ++/ { ++ model = "Helios4"; ++ compatible = "marvell,armada388", ++ "marvell,armada385", "marvell,armada380"; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x00000000 0x80000000>; /* 2 GB */ ++ }; ++ ++ aliases { ++ /* So that mvebu u-boot can update the MAC addresses */ ++ ethernet1 = ð0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ reg_12v: regulator-12v { ++ compatible = "regulator-fixed"; ++ regulator-name = "power_brick_12V"; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ regulator-always-on; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "3P3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ vin-supply = <®_12v>; ++ }; ++ ++ reg_5p0v_hdd: regulator-5v-hdd { ++ compatible = "regulator-fixed"; ++ regulator-name = "5V_HDD"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ vin-supply = <®_12v>; ++ }; ++ ++ reg_5p0v_usb: regulator-5v-usb { ++ compatible = "regulator-fixed"; ++ regulator-name = "USB-PWR"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-boot-on; ++ regulator-always-on; ++ enable-active-high; ++ gpio = <&expander0 6 GPIO_ACTIVE_HIGH>; ++ vin-supply = <®_12v>; ++ }; ++ ++ system-leds { ++ compatible = "gpio-leds"; ++ status-led { ++ label = "helios4:green:status"; ++ gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ default-state = "on"; ++ }; ++ ++ fault-led { ++ label = "helios4:red:fault"; ++ gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; ++ default-state = "keep"; ++ }; ++ }; ++ ++ io-leds { ++ compatible = "gpio-leds"; ++ sata1-led { ++ label = "helios4:green:ata1"; ++ gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "ata1"; ++ default-state = "off"; ++ }; ++ sata2-led { ++ label = "helios4:green:ata2"; ++ gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "ata2"; ++ default-state = "off"; ++ }; ++ sata3-led { ++ label = "helios4:green:ata3"; ++ gpios = <&gpio1 20 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "ata3"; ++ default-state = "off"; ++ }; ++ sata4-led { ++ label = "helios4:green:ata4"; ++ gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "ata4"; ++ default-state = "off"; ++ }; ++ usb-led { ++ label = "helios4:green:usb"; ++ gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "usb-host"; ++ default-state = "off"; ++ }; ++ }; ++ ++ fan1: j10-pwm { ++ compatible = "pwm-fan"; ++ pwms = <&gpio1 9 40000>; /* Target freq:25 kHz */ ++ }; ++ ++ fan2: j17-pwm { ++ compatible = "pwm-fan"; ++ pwms = <&gpio1 23 40000>; /* Target freq:25 kHz */ ++ }; ++ ++ usb2_phy: usb2-phy { ++ compatible = "usb-nop-xceiv"; ++ vbus-regulator = <®_5p0v_usb>; ++ }; ++ ++ usb3_phy: usb3-phy { ++ compatible = "usb-nop-xceiv"; ++ //vbus-regulator = <®_5p0v_usb>; ++ }; ++ ++ soc { ++ internal-regs { ++ sata@a8000 { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ sata0: sata-port@0 { ++ reg = <0>; ++ }; ++ ++ sata1: sata-port@1 { ++ reg = <1>; ++ }; ++ }; ++ ++ sata@e0000 { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ sata2: sata-port@0 { ++ reg = <0>; ++ }; ++ ++ sata3: sata-port@1 { ++ reg = <1>; ++ }; ++ }; ++ ++ sdhci@d8000 { ++ bus-width = <4>; ++ cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; ++ no-1-8-v; ++ pinctrl-0 = <µsom_sdhci_pins ++ &helios_sdhci_cd_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ vmmc = <®_3p3v>; ++ wp-inverted; ++ max-frequency = <50000000>; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ }; ++ ++ usb@58000 { ++ //vcc-supply = <®_5p0v_usb>; ++ usb-phy = <&usb2_phy>; ++ status = "okay"; ++ }; ++ ++ usb3@f0000 { ++ status = "okay"; ++ }; ++ ++ usb3@f8000 { ++ status = "okay"; ++ }; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ clock-frequency = <400000>; ++ pinctrl-0 = <&i2c0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ /* ++ * PCA9655 GPIO expander, up to 1MHz clock. ++ * 0-Board Revision bit 0 # ++ * 1-Board Revision bit 1 # ++ * 5-USB3 overcurrent ++ * 6-USB3 power ++ */ ++ expander0: gpio-expander@20 { ++ /* ++ * This is how it should be: ++ * compatible = "onnn,pca9655", "nxp,pca9555"; ++ * but you can't do this because of the way I2C works. ++ */ ++ compatible = "nxp,pca9555"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ reg = <0x20>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pca0_pins>; ++ interrupt-parent = <&gpio0>; ++ interrupts = <23 IRQ_TYPE_EDGE_FALLING>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ++ board_rev_bit_0 { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_LOW>; ++ input; ++ line-name = "board-rev-0"; ++ }; ++ board_rev_bit_1 { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_LOW>; ++ input; ++ line-name = "board-rev-1"; ++ }; ++ usb3_ilimit { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "usb-overcurrent-status"; ++ }; ++ }; ++ ++ temp_sensor: temp@4c { ++ compatible = "ti,lm75"; ++ reg = <0x4c>; ++ vcc-supply = <®_3p3v>; ++ }; ++}; ++ ++&i2c1 { ++ /* ++ * External I2C Bus for user peripheral ++ */ ++ clock-frequency = <400000>; ++ pinctrl-0 = <&helios_i2c1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ pca0_pins: pca0_pins { ++ marvell,pins = "mpp23"; ++ marvell,function = "gpio"; ++ }; ++ microsom_phy0_int_pins: microsom-phy0-int-pins { ++ marvell,pins = "mpp18"; ++ marvell,function = "gpio"; ++ }; ++ helios_i2c1_pins: i2c1-pins { ++ marvell,pins = "mpp26", "mpp27"; ++ marvell,function = "i2c1"; ++ }; ++ helios_sdhci_cd_pins: helios-sdhci-cd-pins { ++ marvell,pins = "mpp20"; ++ marvell,function = "gpio"; ++ }; ++ helios_led_pins: helios-led-pins { ++ marvell,pins = "mpp24", "mpp25", ++ "mpp49", "mpp50", ++ "mpp52", "mpp53", ++ "mpp54"; ++ marvell,function = "gpio"; ++ }; ++ helios_fan_pins: helios-fan-pins { ++ marvell,pins = "mpp41", "mpp43", ++ "mpp48", "mpp55"; ++ marvell,function = "gpio"; ++ }; ++}; ++ ++&spi1 { ++ status = "okay"; ++ ++ spi-flash@0 { ++ spi-max-frequency = <104000000>; ++ status = "okay"; ++ }; ++}; diff --git a/patch/kernel/mvebu-next/93-helios4-remove-spi-nor-flash.patch b/patch/kernel/mvebu-next/93-helios4-remove-spi-nor-flash.patch new file mode 100644 index 0000000000..eec08df382 --- /dev/null +++ b/patch/kernel/mvebu-next/93-helios4-remove-spi-nor-flash.patch @@ -0,0 +1,17 @@ +diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/armada-388-helios4.dts +index 93d0132..47699bd 100644 +--- a/arch/arm/boot/dts/armada-388-helios4.dts ++++ b/arch/arm/boot/dts/armada-388-helios4.dts +@@ -298,12 +298,3 @@ + marvell,function = "gpio"; + }; + }; +- +-&spi1 { +- status = "okay"; +- +- spi-flash@0 { +- spi-max-frequency = <104000000>; +- status = "okay"; +- }; +-}; diff --git a/patch/kernel/mvebu-next/93-helios4-remove_sd_uhs_option.patch b/patch/kernel/mvebu-next/93-helios4-remove_sd_uhs_option.patch new file mode 100644 index 0000000000..08e364d4ad --- /dev/null +++ b/patch/kernel/mvebu-next/93-helios4-remove_sd_uhs_option.patch @@ -0,0 +1,16 @@ +diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/armada-388-helios4.dts +index 47699bd..4a5e8fc 100644 +--- a/arch/arm/boot/dts/armada-388-helios4.dts ++++ b/arch/arm/boot/dts/armada-388-helios4.dts +@@ -177,11 +177,6 @@ + status = "okay"; + vmmc = <®_3p3v>; + wp-inverted; +- max-frequency = <50000000>; +- cap-sd-highspeed; +- sd-uhs-sdr12; +- sd-uhs-sdr25; +- sd-uhs-sdr50; + }; + + usb@58000 {