mvebu: new subtarget cortex A53
This commit introduces new subtarget for Marvell EBU Armada Cortex A53 processor based devices. The first device is Globalscale ESPRESSObin. Some hardware specs: SoC: Marvell Armada 3700LP (88F3720) dual core ARM Cortex A53 processor up to 1.2GHz RAM: 512MB, 1GB or 2GB DDR3 Storage: SATA interface µSD card slot with footprint for an optional 4GB EMMC 4MB SPI NOR flash for bootloader Ethernet: Topaz Networking Switch (88E6341) with 3x GbE ports Connectors: USB 3.0 USB 2.0 µUSB port connected to PL2303SA (USB to serial bridge controller) for UART access Expansion: 2x 46-pin GPIO headers for accessories and shields with I2C, GPIOs, PWM, UART, SPI, MMC, etc MiniPCIe slot Misc: Reset button, JTAG interface Currently booting only from µSD card is supported. The boards depending on date of dispatch can come with various U-Boot versions. For the newest version 2017.03-armada-17.10 no manual intervention should be needed to boot OpenWrt image. For the older ones it's necessary to modify default U-Boot environment: 1. Interrupt boot process to run U-Boot command line, 2. Run following commands: (for version 2017.03-armada-17.06 and 2017.03-armada-17.08) setenv bootcmd "load mmc 0:1 0x4d00000 boot.scr; source 0x4d00000" saveenv (for version 2015.01-armada-17.02 and 2015.01-armada-17.04) setenv bootargs "console=ttyMV0,115200 root=/dev/mmcblk0p2 rw rootwait" setenv bootcmd "ext4load mmc 0:1 ${fdt_addr} armada-3720-espressobin.dtb; ext4load mmc 0:1 ${kernel_addr} Image; booti ${kernel_addr} - ${fdt_addr}" saveenv 3. Poweroff, insert SD card with OpenWrt image, boot and enjoy. Signed-off-by: Tomasz Maciej Nowak <tomek_n@o2.pl>
This commit is contained in:
parent
be3da900cd
commit
584d7c53bd
26 changed files with 1806 additions and 6 deletions
|
@ -7,9 +7,9 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
BOARD:=mvebu
|
||||
BOARDNAME:=Marvell Armada 37x/38x/XP
|
||||
BOARDNAME:=Marvell EBU Armada
|
||||
FEATURES:=fpu usb pci pcie gpio nand squashfs ramdisk
|
||||
SUBTARGETS:=cortexa9
|
||||
SUBTARGETS:=cortexa9 cortexa53
|
||||
MAINTAINER:=Imre Kaloz <kaloz@openwrt.org>
|
||||
|
||||
KERNEL_PATCHVER:=4.14
|
||||
|
|
|
@ -42,6 +42,9 @@ armada-388-clearfog-*)
|
|||
armada-xp-gp)
|
||||
ucidef_set_interface_lan "eth0 eth1 eth2 eth3"
|
||||
;;
|
||||
globalscale,espressobin)
|
||||
ucidef_set_interfaces_lan_wan "lan0 lan1" "wan"
|
||||
;;
|
||||
*)
|
||||
ucidef_set_interface_lan "eth0"
|
||||
;;
|
||||
|
|
|
@ -17,6 +17,9 @@ mvebu_board_detect() {
|
|||
*"Marvell Armada 370 Evaluation Board")
|
||||
name="armada-370-db"
|
||||
;;
|
||||
*"Globalscale Marvell ESPRESSOBin Board")
|
||||
name="globalscale,espressobin"
|
||||
;;
|
||||
*"Globalscale Mirabox")
|
||||
name="mirabox"
|
||||
;;
|
||||
|
|
|
@ -16,7 +16,7 @@ platform_do_upgrade() {
|
|||
armada-385-linksys-caiman|armada-385-linksys-cobra|armada-385-linksys-rango|armada-385-linksys-shelby|armada-xp-linksys-mamba)
|
||||
platform_do_upgrade_linksys "$ARGV"
|
||||
;;
|
||||
armada-385-turris-omnia|armada-388-clearfog-base|armada-388-clearfog-pro)
|
||||
armada-385-turris-omnia|armada-388-clearfog-base|armada-388-clearfog-pro|globalscale,espressobin)
|
||||
platform_do_upgrade_sdcard "$ARGV"
|
||||
;;
|
||||
*)
|
||||
|
@ -29,7 +29,7 @@ platform_copy_config() {
|
|||
armada-385-linksys-caiman|armada-385-linksys-cobra|armada-385-linksys-rango|armada-385-linksys-shelby|armada-xp-linksys-mamba)
|
||||
platform_copy_config_linksys
|
||||
;;
|
||||
armada-385-turris-omnia|armada-388-clearfog-base|armada-388-clearfog-pro)
|
||||
armada-385-turris-omnia|armada-388-clearfog-base|armada-388-clearfog-pro|globalscale,espressobin)
|
||||
platform_copy_config_sdcard "$ARGV"
|
||||
;;
|
||||
esac
|
||||
|
|
|
@ -39,6 +39,7 @@ CONFIG_ARMADA_38X_CLK=y
|
|||
CONFIG_ARMADA_THERMAL=y
|
||||
CONFIG_ARMADA_XP_CLK=y
|
||||
CONFIG_ARM_APPENDED_DTB=y
|
||||
# CONFIG_ARM_ARMADA_37XX_CPUFREQ is not set
|
||||
CONFIG_ARM_ATAG_DTB_COMPAT=y
|
||||
# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
|
||||
CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
|
||||
|
|
112
target/linux/mvebu/cortexa53/config-default
Normal file
112
target/linux/mvebu/cortexa53/config-default
Normal file
|
@ -0,0 +1,112 @@
|
|||
CONFIG_64BIT=y
|
||||
# CONFIG_ACPI is not set
|
||||
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
|
||||
CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
|
||||
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
|
||||
CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
|
||||
CONFIG_ARCH_HAS_KCOV=y
|
||||
CONFIG_ARCH_MMAP_RND_BITS=18
|
||||
CONFIG_ARCH_MMAP_RND_BITS_MAX=24
|
||||
CONFIG_ARCH_MMAP_RND_BITS_MIN=18
|
||||
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11
|
||||
# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set
|
||||
# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set
|
||||
CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
|
||||
CONFIG_ARCH_PROC_KCORE_TEXT=y
|
||||
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
|
||||
CONFIG_ARCH_SPARSEMEM_ENABLE=y
|
||||
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
|
||||
CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
|
||||
CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
|
||||
CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
|
||||
CONFIG_ARCH_WANT_FRAME_POINTERS=y
|
||||
CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
|
||||
CONFIG_ARM64=y
|
||||
# CONFIG_ARM64_16K_PAGES is not set
|
||||
CONFIG_ARM64_4K_PAGES=y
|
||||
# CONFIG_ARM64_64K_PAGES is not set
|
||||
CONFIG_ARM64_CONT_SHIFT=4
|
||||
# CONFIG_ARM64_CRYPTO is not set
|
||||
# CONFIG_ARM64_HW_AFDBM is not set
|
||||
# CONFIG_ARM64_LSE_ATOMICS is not set
|
||||
CONFIG_ARM64_PAGE_SHIFT=12
|
||||
# CONFIG_ARM64_PAN is not set
|
||||
# CONFIG_ARM64_PMEM is not set
|
||||
# CONFIG_ARM64_PTDUMP_CORE is not set
|
||||
# CONFIG_ARM64_PTDUMP_DEBUGFS is not set
|
||||
# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set
|
||||
# CONFIG_ARM64_SW_TTBR0_PAN is not set
|
||||
# CONFIG_ARM64_UAO is not set
|
||||
CONFIG_ARM64_VA_BITS=39
|
||||
CONFIG_ARM64_VA_BITS_39=y
|
||||
# CONFIG_ARM64_VA_BITS_48 is not set
|
||||
# CONFIG_ARM64_VHE is not set
|
||||
CONFIG_ARMADA_37XX_CLK=y
|
||||
CONFIG_ARMADA_AP806_SYSCON=y
|
||||
CONFIG_ARMADA_CP110_SYSCON=y
|
||||
CONFIG_ARM_AMBA=y
|
||||
CONFIG_ARM_ARCH_TIMER=y
|
||||
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
|
||||
CONFIG_ARM_ARMADA_37XX_CPUFREQ=y
|
||||
CONFIG_ARM_GIC_V2M=y
|
||||
CONFIG_ARM_GIC_V3=y
|
||||
CONFIG_ARM_GIC_V3_ITS=y
|
||||
# CONFIG_ARM_PL172_MPMC is not set
|
||||
CONFIG_ARM_PSCI_FW=y
|
||||
# CONFIG_ARM_SP805_WATCHDOG is not set
|
||||
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
|
||||
# CONFIG_COMPAT is not set
|
||||
# CONFIG_DEBUG_ALIGN_RODATA is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
|
||||
CONFIG_GENERIC_CSUM=y
|
||||
CONFIG_GENERIC_IRQ_MIGRATION=y
|
||||
CONFIG_GENERIC_PINCONF=y
|
||||
CONFIG_GENERIC_TIME_VSYSCALL=y
|
||||
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
|
||||
CONFIG_HAVE_ARCH_HUGE_VMAP=y
|
||||
CONFIG_HAVE_ARCH_KASAN=y
|
||||
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
|
||||
CONFIG_HAVE_ARCH_VMAP_STACK=y
|
||||
CONFIG_HAVE_CMPXCHG_DOUBLE=y
|
||||
CONFIG_HAVE_CMPXCHG_LOCAL=y
|
||||
CONFIG_HAVE_DEBUG_BUGVERBOSE=y
|
||||
CONFIG_HAVE_GENERIC_GUP=y
|
||||
CONFIG_HAVE_MEMORY_PRESENT=y
|
||||
CONFIG_HAVE_PATA_PLATFORM=y
|
||||
CONFIG_HAVE_RCU_TABLE_FREE=y
|
||||
# CONFIG_HUGETLBFS is not set
|
||||
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
|
||||
CONFIG_MFD_SYSCON=y
|
||||
CONFIG_MMC_SDHCI_XENON=y
|
||||
CONFIG_MODULES_USE_ELF_RELA=y
|
||||
CONFIG_MVEBU_GICP=y
|
||||
CONFIG_MVEBU_ICU=y
|
||||
CONFIG_MVEBU_ODMI=y
|
||||
CONFIG_MVEBU_PIC=y
|
||||
CONFIG_NEED_SG_DMA_LENGTH=y
|
||||
# CONFIG_NUMA is not set
|
||||
CONFIG_PARTITION_PERCPU=y
|
||||
CONFIG_PCI_AARDVARK=y
|
||||
CONFIG_PCI_BUS_ADDR_T_64BIT=y
|
||||
CONFIG_PGTABLE_LEVELS=3
|
||||
CONFIG_PHYS_ADDR_T_64BIT=y
|
||||
CONFIG_PINCTRL_ARMADA_37XX=y
|
||||
CONFIG_PINCTRL_ARMADA_AP806=y
|
||||
CONFIG_PINCTRL_ARMADA_CP110=y
|
||||
CONFIG_POWER_RESET=y
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
# CONFIG_RANDOMIZE_BASE is not set
|
||||
CONFIG_REGULATOR_GPIO=y
|
||||
# CONFIG_SERIAL_AMBA_PL011 is not set
|
||||
CONFIG_SPARSEMEM=y
|
||||
CONFIG_SPARSEMEM_EXTREME=y
|
||||
CONFIG_SPARSEMEM_MANUAL=y
|
||||
CONFIG_SPARSEMEM_VMEMMAP=y
|
||||
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
|
||||
CONFIG_SPI_ARMADA_3700=y
|
||||
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
||||
CONFIG_SYS_SUPPORTS_HUGETLBFS=y
|
||||
CONFIG_THREAD_INFO_IN_TASK=y
|
||||
CONFIG_VMAP_STACK=y
|
15
target/linux/mvebu/cortexa53/target.mk
Normal file
15
target/linux/mvebu/cortexa53/target.mk
Normal file
|
@ -0,0 +1,15 @@
|
|||
#
|
||||
# Copyright (C) 2017 Hauke Mehrtens
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
ARCH:=aarch64
|
||||
BOARDNAME:=Marvell Armada 3700LP (ARM64)
|
||||
CPU_TYPE:=cortex-a53
|
||||
FEATURES+=ext4
|
||||
|
||||
KERNELNAME:=Image dtbs
|
|
@ -27,17 +27,28 @@ endef
|
|||
|
||||
define Build/boot-scr
|
||||
rm -f $@-boot.scr
|
||||
mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d $(DEVICE_NAME).bootscript $@-boot.scr
|
||||
sed -e 's#@ROOT@#$(SIGNATURE)#g' \
|
||||
$(DEVICE_NAME).bootscript > $@-new.bootscript
|
||||
mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d $@-new.bootscript $@-boot.scr
|
||||
endef
|
||||
|
||||
define Build/boot-img
|
||||
rm -f $@.boot
|
||||
mkfs.fat -C $@.boot 16384
|
||||
$(foreach dts,$(DEVICE_DTS), mcopy -i $@.boot $(DTS_DIR)/$(dts).dtb ::$(dts).dtb;)
|
||||
mcopy -i $@.boot $(IMAGE_KERNEL) ::zImage
|
||||
mcopy -i $@.boot $(IMAGE_KERNEL) ::$(KERNEL_NAME)
|
||||
-mcopy -i $@.boot $@-boot.scr ::boot.scr
|
||||
endef
|
||||
|
||||
define Build/boot-img-ext4
|
||||
rm -fR $@.boot
|
||||
mkdir -p $@.boot
|
||||
$(foreach dts,$(DEVICE_DTS), $(CP) $(DTS_DIR)/$(dts).dtb $@.boot;)
|
||||
$(CP) $(IMAGE_KERNEL) $@.boot/$(KERNEL_NAME)
|
||||
-$(CP) $@-boot.scr $@.boot/boot.scr
|
||||
make_ext4fs -J -l 16384K $@.bootimg $@.boot
|
||||
endef
|
||||
|
||||
define Build/sdcard-img
|
||||
if [ -n "$(UBOOT)" ]; then UBOOT="$(STAGING_DIR_IMAGE)/$(UBOOT)"; fi; \
|
||||
ROOTFS_SIZE=$$(( $(CONFIG_TARGET_ROOTFS_PARTSIZE) * 1024 * 2 )); \
|
||||
|
@ -48,6 +59,16 @@ define Build/sdcard-img
|
|||
83 $$ROOTFS_SIZE $(IMAGE_ROOTFS)
|
||||
endef
|
||||
|
||||
define Build/sdcard-img-ext4
|
||||
if [ -n "$(UBOOT)" ]; then UBOOT="$(STAGING_DIR_IMAGE)/$(UBOOT)"; fi; \
|
||||
ROOTFS_SIZE=$$(( $(CONFIG_TARGET_ROOTFS_PARTSIZE) * 1024 * 2 )); \
|
||||
SIGNATURE="$(SIGNATURE)" \
|
||||
./gen_mvebu_sdcard_img.sh $@ \
|
||||
$$UBOOT \
|
||||
83 32768 $@.bootimg \
|
||||
83 $$ROOTFS_SIZE $(IMAGE_ROOTFS)
|
||||
endef
|
||||
|
||||
define Build/omnia-medkit-initramfs
|
||||
$(TAR) -c -T /dev/null -f $@
|
||||
rm -rf $(dir $(IMAGE_KERNEL))boot
|
||||
|
@ -101,5 +122,6 @@ define Device/NAND-512K
|
|||
endef
|
||||
|
||||
include cortex-a9.mk
|
||||
include cortex-a53.mk
|
||||
|
||||
$(eval $(call BuildImage))
|
||||
|
|
16
target/linux/mvebu/image/cortex-a53.mk
Normal file
16
target/linux/mvebu/image/cortex-a53.mk
Normal file
|
@ -0,0 +1,16 @@
|
|||
ifeq ($(SUBTARGET),cortexa53)
|
||||
|
||||
define Device/globalscale-espressobin
|
||||
KERNEL_NAME := Image
|
||||
KERNEL := kernel-bin
|
||||
DEVICE_TITLE := ESPRESSObin (Marvell Armada 3700 Community Board)
|
||||
DEVICE_PACKAGES := e2fsprogs ethtool mkf2fs kmod-fs-vfat kmod-usb2 kmod-usb3 kmod-usb-storage
|
||||
IMAGES := sdcard.img.gz
|
||||
IMAGE/sdcard.img.gz := boot-scr | boot-img-ext4 | sdcard-img-ext4 | gzip | append-metadata
|
||||
DEVICE_DTS := armada-3720-espressobin
|
||||
DTS_DIR := $(DTS_DIR)/marvell
|
||||
SUPPORTED_DEVICES := globalscale,espressobin
|
||||
endef
|
||||
TARGET_DEVICES += globalscale-espressobin
|
||||
|
||||
endif
|
10
target/linux/mvebu/image/globalscale-espressobin.bootscript
Normal file
10
target/linux/mvebu/image/globalscale-espressobin.bootscript
Normal file
|
@ -0,0 +1,10 @@
|
|||
setenv bootargs "root=PARTUUID=@ROOT@-02 rw rootwait"
|
||||
|
||||
if test -n "${console}"; then
|
||||
setenv bootargs "${bootargs} ${console}"
|
||||
fi
|
||||
|
||||
load mmc 0:1 ${fdt_addr} armada-3720-espressobin.dtb
|
||||
load mmc 0:1 ${kernel_addr} Image
|
||||
|
||||
booti ${kernel_addr} - ${fdt_addr}
|
|
@ -0,0 +1,78 @@
|
|||
From adf4e289dd7f801c3fe12e0e6b491e11e548cd3d Mon Sep 17 00:00:00 2001
|
||||
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Date: Thu, 30 Nov 2017 14:40:27 +0100
|
||||
Subject: clk: mvebu: armada-37xx-periph: cosmetic changes
|
||||
|
||||
This patches fixes few cosmetic issues such as alignment, blank lines
|
||||
and required space.
|
||||
|
||||
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
|
||||
---
|
||||
drivers/clk/mvebu/armada-37xx-periph.c | 17 +++++++++--------
|
||||
1 file changed, 9 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
@@ -79,6 +79,7 @@ static const struct clk_div_table clk_ta
|
||||
{ .val = 1, .div = 4, },
|
||||
{ .val = 0, .div = 0, }, /* last entry */
|
||||
};
|
||||
+
|
||||
static const struct clk_ops clk_double_div_ops;
|
||||
|
||||
#define PERIPH_GATE(_name, _bit) \
|
||||
@@ -217,7 +218,7 @@ PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL
|
||||
PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19);
|
||||
PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6);
|
||||
|
||||
-static struct clk_periph_data data_nb[] ={
|
||||
+static struct clk_periph_data data_nb[] = {
|
||||
REF_CLK_FULL_DD(mmc),
|
||||
REF_CLK_FULL_DD(sata_host),
|
||||
REF_CLK_FULL_DD(sec_at),
|
||||
@@ -281,7 +282,7 @@ static unsigned int get_div(void __iomem
|
||||
}
|
||||
|
||||
static unsigned long clk_double_div_recalc_rate(struct clk_hw *hw,
|
||||
- unsigned long parent_rate)
|
||||
+ unsigned long parent_rate)
|
||||
{
|
||||
struct clk_double_div *double_div = to_clk_double_div(hw);
|
||||
unsigned int div;
|
||||
@@ -303,6 +304,7 @@ static const struct of_device_id armada_
|
||||
.data = data_sb, },
|
||||
{ }
|
||||
};
|
||||
+
|
||||
static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
|
||||
void __iomem *reg, spinlock_t *lock,
|
||||
struct device *dev, struct clk_hw **hw)
|
||||
@@ -355,9 +357,9 @@ static int armada_3700_add_composite_clk
|
||||
}
|
||||
|
||||
*hw = clk_hw_register_composite(dev, data->name, data->parent_names,
|
||||
- data->num_parents, mux_hw,
|
||||
- mux_ops, rate_hw, rate_ops,
|
||||
- gate_hw, gate_ops, CLK_IGNORE_UNUSED);
|
||||
+ data->num_parents, mux_hw,
|
||||
+ mux_ops, rate_hw, rate_ops,
|
||||
+ gate_hw, gate_ops, CLK_IGNORE_UNUSED);
|
||||
|
||||
if (IS_ERR(*hw))
|
||||
return PTR_ERR(*hw);
|
||||
@@ -406,12 +408,11 @@ static int armada_3700_periph_clock_prob
|
||||
if (armada_3700_add_composite_clk(&data[i], reg,
|
||||
&driver_data->lock, dev, hw))
|
||||
dev_err(dev, "Can't register periph clock %s\n",
|
||||
- data[i].name);
|
||||
-
|
||||
+ data[i].name);
|
||||
}
|
||||
|
||||
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
|
||||
- driver_data->hw_data);
|
||||
+ driver_data->hw_data);
|
||||
if (ret) {
|
||||
for (i = 0; i < num_periph; i++)
|
||||
clk_hw_unregister(driver_data->hw_data->hws[i]);
|
|
@ -0,0 +1,178 @@
|
|||
From 9818a7a4fd10f72537cdf2a5ec3402f2c245ea24 Mon Sep 17 00:00:00 2001
|
||||
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Date: Thu, 30 Nov 2017 14:40:28 +0100
|
||||
Subject: clk: mvebu: armada-37xx-periph: prepare cpu clk to be
|
||||
used with DVFS
|
||||
|
||||
When DVFS will be enabled then the cpu clk will use a different set of
|
||||
register at run time. That means that we won't be able to use the common
|
||||
callback and need to use our own ones.
|
||||
|
||||
This patch prepares this change by switching on our own set of callbacks
|
||||
without modifying the behavior of the clocks.
|
||||
|
||||
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
|
||||
---
|
||||
drivers/clk/mvebu/armada-37xx-periph.c | 82 ++++++++++++++++++++++++++++++----
|
||||
1 file changed, 73 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
@@ -46,7 +46,17 @@ struct clk_double_div {
|
||||
u8 shift2;
|
||||
};
|
||||
|
||||
+struct clk_pm_cpu {
|
||||
+ struct clk_hw hw;
|
||||
+ void __iomem *reg_mux;
|
||||
+ u8 shift_mux;
|
||||
+ u32 mask_mux;
|
||||
+ void __iomem *reg_div;
|
||||
+ u8 shift_div;
|
||||
+};
|
||||
+
|
||||
#define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
|
||||
+#define to_clk_pm_cpu(_hw) container_of(_hw, struct clk_pm_cpu, hw)
|
||||
|
||||
struct clk_periph_data {
|
||||
const char *name;
|
||||
@@ -55,6 +65,7 @@ struct clk_periph_data {
|
||||
struct clk_hw *mux_hw;
|
||||
struct clk_hw *rate_hw;
|
||||
struct clk_hw *gate_hw;
|
||||
+ struct clk_hw *muxrate_hw;
|
||||
bool is_double_div;
|
||||
};
|
||||
|
||||
@@ -81,6 +92,7 @@ static const struct clk_div_table clk_ta
|
||||
};
|
||||
|
||||
static const struct clk_ops clk_double_div_ops;
|
||||
+static const struct clk_ops clk_pm_cpu_ops;
|
||||
|
||||
#define PERIPH_GATE(_name, _bit) \
|
||||
struct clk_gate gate_##_name = { \
|
||||
@@ -122,6 +134,18 @@ struct clk_divider rate_##_name = { \
|
||||
} \
|
||||
};
|
||||
|
||||
+#define PERIPH_PM_CPU(_name, _shift1, _reg, _shift2) \
|
||||
+struct clk_pm_cpu muxrate_##_name = { \
|
||||
+ .reg_mux = (void *)TBG_SEL, \
|
||||
+ .mask_mux = 3, \
|
||||
+ .shift_mux = _shift1, \
|
||||
+ .reg_div = (void *)_reg, \
|
||||
+ .shift_div = _shift2, \
|
||||
+ .hw.init = &(struct clk_init_data){ \
|
||||
+ .ops = &clk_pm_cpu_ops, \
|
||||
+ } \
|
||||
+};
|
||||
+
|
||||
#define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\
|
||||
static PERIPH_GATE(_name, _bit); \
|
||||
static PERIPH_MUX(_name, _shift); \
|
||||
@@ -136,10 +160,6 @@ static PERIPH_DIV(_name, _reg, _shift1,
|
||||
static PERIPH_GATE(_name, _bit); \
|
||||
static PERIPH_DIV(_name, _reg, _shift, _table);
|
||||
|
||||
-#define PERIPH_CLK_MUX_DIV(_name, _shift, _reg, _shift_div, _table) \
|
||||
-static PERIPH_MUX(_name, _shift); \
|
||||
-static PERIPH_DIV(_name, _reg, _shift_div, _table);
|
||||
-
|
||||
#define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\
|
||||
static PERIPH_MUX(_name, _shift); \
|
||||
static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2);
|
||||
@@ -180,13 +200,12 @@ static PERIPH_DOUBLEDIV(_name, _reg1, _r
|
||||
.rate_hw = &rate_##_name.hw, \
|
||||
}
|
||||
|
||||
-#define REF_CLK_MUX_DIV(_name) \
|
||||
+#define REF_CLK_PM_CPU(_name) \
|
||||
{ .name = #_name, \
|
||||
.parent_names = (const char *[]){ "TBG-A-P", \
|
||||
"TBG-B-P", "TBG-A-S", "TBG-B-S"}, \
|
||||
.num_parents = 4, \
|
||||
- .mux_hw = &mux_##_name.hw, \
|
||||
- .rate_hw = &rate_##_name.hw, \
|
||||
+ .muxrate_hw = &muxrate_##_name.hw, \
|
||||
}
|
||||
|
||||
#define REF_CLK_MUX_DD(_name) \
|
||||
@@ -216,7 +235,7 @@ PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV
|
||||
PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6);
|
||||
PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6);
|
||||
PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19);
|
||||
-PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6);
|
||||
+static PERIPH_PM_CPU(cpu, 22, DIV_SEL0, 28);
|
||||
|
||||
static struct clk_periph_data data_nb[] = {
|
||||
REF_CLK_FULL_DD(mmc),
|
||||
@@ -235,7 +254,7 @@ static struct clk_periph_data data_nb[]
|
||||
REF_CLK_FULL(trace),
|
||||
REF_CLK_FULL(counter),
|
||||
REF_CLK_FULL_DD(eip97),
|
||||
- REF_CLK_MUX_DIV(cpu),
|
||||
+ REF_CLK_PM_CPU(cpu),
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -297,6 +316,37 @@ static const struct clk_ops clk_double_d
|
||||
.recalc_rate = clk_double_div_recalc_rate,
|
||||
};
|
||||
|
||||
+static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
|
||||
+ int num_parents = clk_hw_get_num_parents(hw);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
|
||||
+ val &= pm_cpu->mask_mux;
|
||||
+
|
||||
+ if (val >= num_parents)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
+static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
|
||||
+ unsigned int div;
|
||||
+
|
||||
+ div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
|
||||
+
|
||||
+ return DIV_ROUND_UP_ULL((u64)parent_rate, div);
|
||||
+}
|
||||
+
|
||||
+static const struct clk_ops clk_pm_cpu_ops = {
|
||||
+ .get_parent = clk_pm_cpu_get_parent,
|
||||
+ .recalc_rate = clk_pm_cpu_recalc_rate,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id armada_3700_periph_clock_of_match[] = {
|
||||
{ .compatible = "marvell,armada-3700-periph-clock-nb",
|
||||
.data = data_nb, },
|
||||
@@ -356,6 +406,20 @@ static int armada_3700_add_composite_clk
|
||||
}
|
||||
}
|
||||
|
||||
+ if (data->muxrate_hw) {
|
||||
+ struct clk_pm_cpu *pmcpu_clk;
|
||||
+ struct clk_hw *muxrate_hw = data->muxrate_hw;
|
||||
+
|
||||
+ pmcpu_clk = to_clk_pm_cpu(muxrate_hw);
|
||||
+ pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux;
|
||||
+ pmcpu_clk->reg_div = reg + (u64)pmcpu_clk->reg_div;
|
||||
+
|
||||
+ mux_hw = muxrate_hw;
|
||||
+ rate_hw = muxrate_hw;
|
||||
+ mux_ops = muxrate_hw->init->ops;
|
||||
+ rate_ops = muxrate_hw->init->ops;
|
||||
+ }
|
||||
+
|
||||
*hw = clk_hw_register_composite(dev, data->name, data->parent_names,
|
||||
data->num_parents, mux_hw,
|
||||
mux_ops, rate_hw, rate_ops,
|
|
@ -0,0 +1,315 @@
|
|||
From 2089dc33ea0e3917465929d4020fbff3d6dbf7f4 Mon Sep 17 00:00:00 2001
|
||||
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Date: Thu, 30 Nov 2017 14:40:29 +0100
|
||||
Subject: clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks
|
||||
|
||||
When DVFS is enabled the CPU clock setting is done using an other set of
|
||||
registers.
|
||||
|
||||
These Power Management registers are exposed through a syscon as they
|
||||
will also be used by other drivers such as the cpufreq.
|
||||
|
||||
This patch add the possibility to modify the CPU frequency using the
|
||||
associate load level matching the target frequency. Then all the
|
||||
frequency switch is handle by the hardware.
|
||||
|
||||
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
[sboyd@codeaurora.org: Grow a local variable for regmap pointer
|
||||
to keep lines shorter]
|
||||
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
|
||||
---
|
||||
drivers/clk/mvebu/armada-37xx-periph.c | 221 ++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 217 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
+++ b/drivers/clk/mvebu/armada-37xx-periph.c
|
||||
@@ -21,9 +21,11 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define TBG_SEL 0x0
|
||||
@@ -33,6 +35,26 @@
|
||||
#define CLK_SEL 0x10
|
||||
#define CLK_DIS 0x14
|
||||
|
||||
+#define LOAD_LEVEL_NR 4
|
||||
+
|
||||
+#define ARMADA_37XX_NB_L0L1 0x18
|
||||
+#define ARMADA_37XX_NB_L2L3 0x1C
|
||||
+#define ARMADA_37XX_NB_TBG_DIV_OFF 13
|
||||
+#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
|
||||
+#define ARMADA_37XX_NB_CLK_SEL_OFF 11
|
||||
+#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
|
||||
+#define ARMADA_37XX_NB_TBG_SEL_OFF 9
|
||||
+#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
|
||||
+#define ARMADA_37XX_NB_CONFIG_SHIFT 16
|
||||
+#define ARMADA_37XX_NB_DYN_MOD 0x24
|
||||
+#define ARMADA_37XX_NB_DFS_EN 31
|
||||
+#define ARMADA_37XX_NB_CPU_LOAD 0x30
|
||||
+#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
|
||||
+#define ARMADA_37XX_DVFS_LOAD_0 0
|
||||
+#define ARMADA_37XX_DVFS_LOAD_1 1
|
||||
+#define ARMADA_37XX_DVFS_LOAD_2 2
|
||||
+#define ARMADA_37XX_DVFS_LOAD_3 3
|
||||
+
|
||||
struct clk_periph_driver_data {
|
||||
struct clk_hw_onecell_data *hw_data;
|
||||
spinlock_t lock;
|
||||
@@ -53,6 +75,7 @@ struct clk_pm_cpu {
|
||||
u32 mask_mux;
|
||||
void __iomem *reg_div;
|
||||
u8 shift_div;
|
||||
+ struct regmap *nb_pm_base;
|
||||
};
|
||||
|
||||
#define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
|
||||
@@ -316,14 +339,94 @@ static const struct clk_ops clk_double_d
|
||||
.recalc_rate = clk_double_div_recalc_rate,
|
||||
};
|
||||
|
||||
+static void armada_3700_pm_dvfs_update_regs(unsigned int load_level,
|
||||
+ unsigned int *reg,
|
||||
+ unsigned int *offset)
|
||||
+{
|
||||
+ if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
|
||||
+ *reg = ARMADA_37XX_NB_L0L1;
|
||||
+ else
|
||||
+ *reg = ARMADA_37XX_NB_L2L3;
|
||||
+
|
||||
+ if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
|
||||
+ load_level == ARMADA_37XX_DVFS_LOAD_2)
|
||||
+ *offset += ARMADA_37XX_NB_CONFIG_SHIFT;
|
||||
+}
|
||||
+
|
||||
+static bool armada_3700_pm_dvfs_is_enabled(struct regmap *base)
|
||||
+{
|
||||
+ unsigned int val, reg = ARMADA_37XX_NB_DYN_MOD;
|
||||
+
|
||||
+ if (IS_ERR(base))
|
||||
+ return false;
|
||||
+
|
||||
+ regmap_read(base, reg, &val);
|
||||
+
|
||||
+ return !!(val & BIT(ARMADA_37XX_NB_DFS_EN));
|
||||
+}
|
||||
+
|
||||
+static unsigned int armada_3700_pm_dvfs_get_cpu_div(struct regmap *base)
|
||||
+{
|
||||
+ unsigned int reg = ARMADA_37XX_NB_CPU_LOAD;
|
||||
+ unsigned int offset = ARMADA_37XX_NB_TBG_DIV_OFF;
|
||||
+ unsigned int load_level, div;
|
||||
+
|
||||
+ /*
|
||||
+ * This function is always called after the function
|
||||
+ * armada_3700_pm_dvfs_is_enabled, so no need to check again
|
||||
+ * if the base is valid.
|
||||
+ */
|
||||
+ regmap_read(base, reg, &load_level);
|
||||
+
|
||||
+ /*
|
||||
+ * The register and the offset inside this register accessed to
|
||||
+ * read the current divider depend on the load level
|
||||
+ */
|
||||
+ load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
|
||||
+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset);
|
||||
+
|
||||
+ regmap_read(base, reg, &div);
|
||||
+
|
||||
+ return (div >> offset) & ARMADA_37XX_NB_TBG_DIV_MASK;
|
||||
+}
|
||||
+
|
||||
+static unsigned int armada_3700_pm_dvfs_get_cpu_parent(struct regmap *base)
|
||||
+{
|
||||
+ unsigned int reg = ARMADA_37XX_NB_CPU_LOAD;
|
||||
+ unsigned int offset = ARMADA_37XX_NB_TBG_SEL_OFF;
|
||||
+ unsigned int load_level, sel;
|
||||
+
|
||||
+ /*
|
||||
+ * This function is always called after the function
|
||||
+ * armada_3700_pm_dvfs_is_enabled, so no need to check again
|
||||
+ * if the base is valid
|
||||
+ */
|
||||
+ regmap_read(base, reg, &load_level);
|
||||
+
|
||||
+ /*
|
||||
+ * The register and the offset inside this register accessed to
|
||||
+ * read the current divider depend on the load level
|
||||
+ */
|
||||
+ load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
|
||||
+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset);
|
||||
+
|
||||
+ regmap_read(base, reg, &sel);
|
||||
+
|
||||
+ return (sel >> offset) & ARMADA_37XX_NB_TBG_SEL_MASK;
|
||||
+}
|
||||
+
|
||||
static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
|
||||
int num_parents = clk_hw_get_num_parents(hw);
|
||||
u32 val;
|
||||
|
||||
- val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
|
||||
- val &= pm_cpu->mask_mux;
|
||||
+ if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) {
|
||||
+ val = armada_3700_pm_dvfs_get_cpu_parent(pm_cpu->nb_pm_base);
|
||||
+ } else {
|
||||
+ val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
|
||||
+ val &= pm_cpu->mask_mux;
|
||||
+ }
|
||||
|
||||
if (val >= num_parents)
|
||||
return -EINVAL;
|
||||
@@ -331,19 +434,124 @@ static u8 clk_pm_cpu_get_parent(struct c
|
||||
return val;
|
||||
}
|
||||
|
||||
+static int clk_pm_cpu_set_parent(struct clk_hw *hw, u8 index)
|
||||
+{
|
||||
+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
|
||||
+ struct regmap *base = pm_cpu->nb_pm_base;
|
||||
+ int load_level;
|
||||
+
|
||||
+ /*
|
||||
+ * We set the clock parent only if the DVFS is available but
|
||||
+ * not enabled.
|
||||
+ */
|
||||
+ if (IS_ERR(base) || armada_3700_pm_dvfs_is_enabled(base))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Set the parent clock for all the load level */
|
||||
+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
|
||||
+ unsigned int reg, mask, val,
|
||||
+ offset = ARMADA_37XX_NB_TBG_SEL_OFF;
|
||||
+
|
||||
+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset);
|
||||
+
|
||||
+ val = index << offset;
|
||||
+ mask = ARMADA_37XX_NB_TBG_SEL_MASK << offset;
|
||||
+ regmap_update_bits(base, reg, mask, val);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
|
||||
unsigned int div;
|
||||
|
||||
- div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
|
||||
-
|
||||
+ if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base))
|
||||
+ div = armada_3700_pm_dvfs_get_cpu_div(pm_cpu->nb_pm_base);
|
||||
+ else
|
||||
+ div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
|
||||
return DIV_ROUND_UP_ULL((u64)parent_rate, div);
|
||||
}
|
||||
|
||||
+static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
+ unsigned long *parent_rate)
|
||||
+{
|
||||
+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
|
||||
+ struct regmap *base = pm_cpu->nb_pm_base;
|
||||
+ unsigned int div = *parent_rate / rate;
|
||||
+ unsigned int load_level;
|
||||
+ /* only available when DVFS is enabled */
|
||||
+ if (!armada_3700_pm_dvfs_is_enabled(base))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
|
||||
+ unsigned int reg, val, offset = ARMADA_37XX_NB_TBG_DIV_OFF;
|
||||
+
|
||||
+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset);
|
||||
+
|
||||
+ regmap_read(base, reg, &val);
|
||||
+
|
||||
+ val >>= offset;
|
||||
+ val &= ARMADA_37XX_NB_TBG_DIV_MASK;
|
||||
+ if (val == div)
|
||||
+ /*
|
||||
+ * We found a load level matching the target
|
||||
+ * divider, switch to this load level and
|
||||
+ * return.
|
||||
+ */
|
||||
+ return *parent_rate / div;
|
||||
+ }
|
||||
+
|
||||
+ /* We didn't find any valid divider */
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
|
||||
+ struct regmap *base = pm_cpu->nb_pm_base;
|
||||
+ unsigned int div = parent_rate / rate;
|
||||
+ unsigned int load_level;
|
||||
+
|
||||
+ /* only available when DVFS is enabled */
|
||||
+ if (!armada_3700_pm_dvfs_is_enabled(base))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
|
||||
+ unsigned int reg, mask, val,
|
||||
+ offset = ARMADA_37XX_NB_TBG_DIV_OFF;
|
||||
+
|
||||
+ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset);
|
||||
+
|
||||
+ regmap_read(base, reg, &val);
|
||||
+ val >>= offset;
|
||||
+ val &= ARMADA_37XX_NB_TBG_DIV_MASK;
|
||||
+
|
||||
+ if (val == div) {
|
||||
+ /*
|
||||
+ * We found a load level matching the target
|
||||
+ * divider, switch to this load level and
|
||||
+ * return.
|
||||
+ */
|
||||
+ reg = ARMADA_37XX_NB_CPU_LOAD;
|
||||
+ mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
|
||||
+ regmap_update_bits(base, reg, mask, load_level);
|
||||
+
|
||||
+ return rate;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* We didn't find any valid divider */
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
static const struct clk_ops clk_pm_cpu_ops = {
|
||||
.get_parent = clk_pm_cpu_get_parent,
|
||||
+ .set_parent = clk_pm_cpu_set_parent,
|
||||
+ .round_rate = clk_pm_cpu_round_rate,
|
||||
+ .set_rate = clk_pm_cpu_set_rate,
|
||||
.recalc_rate = clk_pm_cpu_recalc_rate,
|
||||
};
|
||||
|
||||
@@ -409,6 +617,7 @@ static int armada_3700_add_composite_clk
|
||||
if (data->muxrate_hw) {
|
||||
struct clk_pm_cpu *pmcpu_clk;
|
||||
struct clk_hw *muxrate_hw = data->muxrate_hw;
|
||||
+ struct regmap *map;
|
||||
|
||||
pmcpu_clk = to_clk_pm_cpu(muxrate_hw);
|
||||
pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux;
|
||||
@@ -418,6 +627,10 @@ static int armada_3700_add_composite_clk
|
||||
rate_hw = muxrate_hw;
|
||||
mux_ops = muxrate_hw->init->ops;
|
||||
rate_ops = muxrate_hw->init->ops;
|
||||
+
|
||||
+ map = syscon_regmap_lookup_by_compatible(
|
||||
+ "marvell,armada-3700-nb-pm");
|
||||
+ pmcpu_clk->nb_pm_base = map;
|
||||
}
|
||||
|
||||
*hw = clk_hw_register_composite(dev, data->name, data->parent_names,
|
|
@ -0,0 +1,297 @@
|
|||
From 92ce45fb875d7c3e021cc454482fe0687ff54f29 Mon Sep 17 00:00:00 2001
|
||||
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Date: Thu, 14 Dec 2017 16:00:05 +0100
|
||||
Subject: cpufreq: Add DVFS support for Armada 37xx
|
||||
|
||||
This patch adds DVFS support for the Armada 37xx SoCs
|
||||
|
||||
There are up to four CPU frequency loads for Armada 37xx controlled by
|
||||
the hardware.
|
||||
|
||||
This driver associates the CPU load level to a frequency, then the
|
||||
hardware will switch while selecting a load level.
|
||||
|
||||
The hardware also can associate a voltage for each level (AVS support)
|
||||
but it is not yet supported
|
||||
|
||||
Tested-by: Andre Heider <a.heider@gmail.com>
|
||||
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
---
|
||||
drivers/cpufreq/Kconfig.arm | 7 +
|
||||
drivers/cpufreq/Makefile | 1 +
|
||||
drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 249 insertions(+)
|
||||
create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
|
||||
|
||||
--- a/drivers/cpufreq/Kconfig.arm
|
||||
+++ b/drivers/cpufreq/Kconfig.arm
|
||||
@@ -2,6 +2,13 @@
|
||||
# ARM CPU Frequency scaling drivers
|
||||
#
|
||||
|
||||
+config ARM_ARMADA_37XX_CPUFREQ
|
||||
+ tristate "Armada 37xx CPUFreq support"
|
||||
+ depends on ARCH_MVEBU
|
||||
+ help
|
||||
+ This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
|
||||
+ The Armada 37xx PMU supports 4 frequency and VDD levels.
|
||||
+
|
||||
# big LITTLE core layer and glue drivers
|
||||
config ARM_BIG_LITTLE_CPUFREQ
|
||||
tristate "Generic ARM big LITTLE CPUfreq driver"
|
||||
--- a/drivers/cpufreq/Makefile
|
||||
+++ b/drivers/cpufreq/Makefile
|
||||
@@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) +=
|
||||
# LITTLE drivers, so that it is probed last.
|
||||
obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
|
||||
|
||||
+obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
|
||||
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
|
||||
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
|
||||
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/cpufreq/armada-37xx-cpufreq.c
|
||||
@@ -0,0 +1,241 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * CPU frequency scaling support for Armada 37xx platform.
|
||||
+ *
|
||||
+ * Copyright (C) 2017 Marvell
|
||||
+ *
|
||||
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/cpu.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/of_irq.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pm_opp.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+/* Power management in North Bridge register set */
|
||||
+#define ARMADA_37XX_NB_L0L1 0x18
|
||||
+#define ARMADA_37XX_NB_L2L3 0x1C
|
||||
+#define ARMADA_37XX_NB_TBG_DIV_OFF 13
|
||||
+#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
|
||||
+#define ARMADA_37XX_NB_CLK_SEL_OFF 11
|
||||
+#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
|
||||
+#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1
|
||||
+#define ARMADA_37XX_NB_TBG_SEL_OFF 9
|
||||
+#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
|
||||
+#define ARMADA_37XX_NB_VDD_SEL_OFF 6
|
||||
+#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3
|
||||
+#define ARMADA_37XX_NB_CONFIG_SHIFT 16
|
||||
+#define ARMADA_37XX_NB_DYN_MOD 0x24
|
||||
+#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26)
|
||||
+#define ARMADA_37XX_NB_TBG_EN BIT(28)
|
||||
+#define ARMADA_37XX_NB_DIV_EN BIT(29)
|
||||
+#define ARMADA_37XX_NB_VDD_EN BIT(30)
|
||||
+#define ARMADA_37XX_NB_DFS_EN BIT(31)
|
||||
+#define ARMADA_37XX_NB_CPU_LOAD 0x30
|
||||
+#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
|
||||
+#define ARMADA_37XX_DVFS_LOAD_0 0
|
||||
+#define ARMADA_37XX_DVFS_LOAD_1 1
|
||||
+#define ARMADA_37XX_DVFS_LOAD_2 2
|
||||
+#define ARMADA_37XX_DVFS_LOAD_3 3
|
||||
+
|
||||
+/*
|
||||
+ * On Armada 37xx the Power management manages 4 level of CPU load,
|
||||
+ * each level can be associated with a CPU clock source, a CPU
|
||||
+ * divider, a VDD level, etc...
|
||||
+ */
|
||||
+#define LOAD_LEVEL_NR 4
|
||||
+
|
||||
+struct armada_37xx_dvfs {
|
||||
+ u32 cpu_freq_max;
|
||||
+ u8 divider[LOAD_LEVEL_NR];
|
||||
+};
|
||||
+
|
||||
+static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
|
||||
+ {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
|
||||
+ {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
|
||||
+ {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} },
|
||||
+ {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} },
|
||||
+};
|
||||
+
|
||||
+static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
|
||||
+ if (freq == armada_37xx_dvfs[i].cpu_freq_max)
|
||||
+ return &armada_37xx_dvfs[i];
|
||||
+ }
|
||||
+
|
||||
+ pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Setup the four level managed by the hardware. Once the four level
|
||||
+ * will be configured then the DVFS will be enabled.
|
||||
+ */
|
||||
+static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
|
||||
+ struct clk *clk, u8 *divider)
|
||||
+{
|
||||
+ int load_lvl;
|
||||
+ struct clk *parent;
|
||||
+
|
||||
+ for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {
|
||||
+ unsigned int reg, mask, val, offset = 0;
|
||||
+
|
||||
+ if (load_lvl <= ARMADA_37XX_DVFS_LOAD_1)
|
||||
+ reg = ARMADA_37XX_NB_L0L1;
|
||||
+ else
|
||||
+ reg = ARMADA_37XX_NB_L2L3;
|
||||
+
|
||||
+ if (load_lvl == ARMADA_37XX_DVFS_LOAD_0 ||
|
||||
+ load_lvl == ARMADA_37XX_DVFS_LOAD_2)
|
||||
+ offset += ARMADA_37XX_NB_CONFIG_SHIFT;
|
||||
+
|
||||
+ /* Set cpu clock source, for all the level we use TBG */
|
||||
+ val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
|
||||
+ mask = (ARMADA_37XX_NB_CLK_SEL_MASK
|
||||
+ << ARMADA_37XX_NB_CLK_SEL_OFF);
|
||||
+
|
||||
+ /*
|
||||
+ * Set cpu divider based on the pre-computed array in
|
||||
+ * order to have balanced step.
|
||||
+ */
|
||||
+ val |= divider[load_lvl] << ARMADA_37XX_NB_TBG_DIV_OFF;
|
||||
+ mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
|
||||
+ << ARMADA_37XX_NB_TBG_DIV_OFF);
|
||||
+
|
||||
+ /* Set VDD divider which is actually the load level. */
|
||||
+ val |= load_lvl << ARMADA_37XX_NB_VDD_SEL_OFF;
|
||||
+ mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
|
||||
+ << ARMADA_37XX_NB_VDD_SEL_OFF);
|
||||
+
|
||||
+ val <<= offset;
|
||||
+ mask <<= offset;
|
||||
+
|
||||
+ regmap_update_bits(base, reg, mask, val);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Set cpu clock source, for all the level we keep the same
|
||||
+ * clock source that the one already configured. For this one
|
||||
+ * we need to use the clock framework
|
||||
+ */
|
||||
+ parent = clk_get_parent(clk);
|
||||
+ clk_set_parent(clk, parent);
|
||||
+}
|
||||
+
|
||||
+static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
|
||||
+{
|
||||
+ unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
|
||||
+ mask = ARMADA_37XX_NB_DFS_EN;
|
||||
+
|
||||
+ regmap_update_bits(base, reg, mask, 0);
|
||||
+}
|
||||
+
|
||||
+static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
|
||||
+{
|
||||
+ unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
|
||||
+ mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
|
||||
+
|
||||
+ /* Start with the highest load (0) */
|
||||
+ val = ARMADA_37XX_DVFS_LOAD_0;
|
||||
+ regmap_update_bits(base, reg, mask, val);
|
||||
+
|
||||
+ /* Now enable DVFS for the CPUs */
|
||||
+ reg = ARMADA_37XX_NB_DYN_MOD;
|
||||
+ mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
|
||||
+ ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
|
||||
+ ARMADA_37XX_NB_DFS_EN;
|
||||
+
|
||||
+ regmap_update_bits(base, reg, mask, mask);
|
||||
+}
|
||||
+
|
||||
+static int __init armada37xx_cpufreq_driver_init(void)
|
||||
+{
|
||||
+ struct armada_37xx_dvfs *dvfs;
|
||||
+ struct platform_device *pdev;
|
||||
+ unsigned int cur_frequency;
|
||||
+ struct regmap *nb_pm_base;
|
||||
+ struct device *cpu_dev;
|
||||
+ int load_lvl, ret;
|
||||
+ struct clk *clk;
|
||||
+
|
||||
+ nb_pm_base =
|
||||
+ syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
|
||||
+
|
||||
+ if (IS_ERR(nb_pm_base))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ /* Before doing any configuration on the DVFS first, disable it */
|
||||
+ armada37xx_cpufreq_disable_dvfs(nb_pm_base);
|
||||
+
|
||||
+ /*
|
||||
+ * On CPU 0 register the operating points supported (which are
|
||||
+ * the nominal CPU frequency and full integer divisions of
|
||||
+ * it).
|
||||
+ */
|
||||
+ cpu_dev = get_cpu_device(0);
|
||||
+ if (!cpu_dev) {
|
||||
+ dev_err(cpu_dev, "Cannot get CPU\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ clk = clk_get(cpu_dev, 0);
|
||||
+ if (IS_ERR(clk)) {
|
||||
+ dev_err(cpu_dev, "Cannot get clock for CPU0\n");
|
||||
+ return PTR_ERR(clk);
|
||||
+ }
|
||||
+
|
||||
+ /* Get nominal (current) CPU frequency */
|
||||
+ cur_frequency = clk_get_rate(clk);
|
||||
+ if (!cur_frequency) {
|
||||
+ dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
|
||||
+ if (!dvfs)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
|
||||
+
|
||||
+ for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
|
||||
+ load_lvl++) {
|
||||
+ unsigned long freq = cur_frequency / dvfs->divider[load_lvl];
|
||||
+
|
||||
+ ret = dev_pm_opp_add(cpu_dev, freq, 0);
|
||||
+ if (ret) {
|
||||
+ /* clean-up the already added opp before leaving */
|
||||
+ while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {
|
||||
+ freq = cur_frequency / dvfs->divider[load_lvl];
|
||||
+ dev_pm_opp_remove(cpu_dev, freq);
|
||||
+ }
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Now that everything is setup, enable the DVFS at hardware level */
|
||||
+ armada37xx_cpufreq_enable_dvfs(nb_pm_base);
|
||||
+
|
||||
+ pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
|
||||
+
|
||||
+ return PTR_ERR_OR_ZERO(pdev);
|
||||
+}
|
||||
+/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
|
||||
+late_initcall(armada37xx_cpufreq_driver_init);
|
||||
+
|
||||
+MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
|
||||
+MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
|
||||
+MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,70 @@
|
|||
From dd7aa8d4b53b3484ba31ba56f3ff1be7deb38530 Mon Sep 17 00:00:00 2001
|
||||
From: Maxime Chevallier <maxime.chevallier@smile.fr>
|
||||
Date: Tue, 10 Oct 2017 10:43:18 +0200
|
||||
Subject: spi: a3700: Change SPI mode before asserting chip-select
|
||||
|
||||
The spi device mode should be configured in the controller before the
|
||||
chip-select is asserted, so that a clock polarity configuration change
|
||||
is not interpreted as a clock tick by the device.
|
||||
|
||||
This patch moves the mode setting to the 'prepare_message' function
|
||||
instead of the 'transfer_one' function.
|
||||
|
||||
By doing so, this patch also removes redundant code in
|
||||
a3700_spi_clock_set.
|
||||
|
||||
This was tested on EspressoBin board, with spidev.
|
||||
|
||||
Signed-off-by: Maxime Chevallier <maxime.chevallier@smile.fr>
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-armada-3700.c | 17 ++++-------------
|
||||
1 file changed, 4 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-armada-3700.c
|
||||
+++ b/drivers/spi/spi-armada-3700.c
|
||||
@@ -214,7 +214,7 @@ static void a3700_spi_mode_set(struct a3
|
||||
}
|
||||
|
||||
static void a3700_spi_clock_set(struct a3700_spi *a3700_spi,
|
||||
- unsigned int speed_hz, u16 mode)
|
||||
+ unsigned int speed_hz)
|
||||
{
|
||||
u32 val;
|
||||
u32 prescale;
|
||||
@@ -239,17 +239,6 @@ static void a3700_spi_clock_set(struct a
|
||||
val |= A3700_SPI_CLK_CAPT_EDGE;
|
||||
spireg_write(a3700_spi, A3700_SPI_IF_TIME_REG, val);
|
||||
}
|
||||
-
|
||||
- val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG);
|
||||
- val &= ~(A3700_SPI_CLK_POL | A3700_SPI_CLK_PHA);
|
||||
-
|
||||
- if (mode & SPI_CPOL)
|
||||
- val |= A3700_SPI_CLK_POL;
|
||||
-
|
||||
- if (mode & SPI_CPHA)
|
||||
- val |= A3700_SPI_CLK_PHA;
|
||||
-
|
||||
- spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val);
|
||||
}
|
||||
|
||||
static void a3700_spi_bytelen_set(struct a3700_spi *a3700_spi, unsigned int len)
|
||||
@@ -431,7 +420,7 @@ static void a3700_spi_transfer_setup(str
|
||||
|
||||
a3700_spi = spi_master_get_devdata(spi->master);
|
||||
|
||||
- a3700_spi_clock_set(a3700_spi, xfer->speed_hz, spi->mode);
|
||||
+ a3700_spi_clock_set(a3700_spi, xfer->speed_hz);
|
||||
|
||||
byte_len = xfer->bits_per_word >> 3;
|
||||
|
||||
@@ -592,6 +581,8 @@ static int a3700_spi_prepare_message(str
|
||||
|
||||
a3700_spi_bytelen_set(a3700_spi, 4);
|
||||
|
||||
+ a3700_spi_mode_set(a3700_spi, spi->mode);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
From c737abc193d16e62e23e2fb585b8b7398ab380d8 Mon Sep 17 00:00:00 2001
|
||||
From: allen yan <yanwei@marvell.com>
|
||||
Date: Thu, 7 Sep 2017 15:04:53 +0200
|
||||
Subject: arm64: dts: marvell: Fix A37xx UART0 register size
|
||||
|
||||
Armada-37xx UART0 registers are 0x200 bytes wide. Right next to them are
|
||||
the UART1 registers that should not be declared in this node.
|
||||
|
||||
Update the example in DT bindings document accordingly.
|
||||
|
||||
Signed-off-by: allen yan <yanwei@marvell.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
|
||||
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
---
|
||||
Documentation/devicetree/bindings/serial/mvebu-uart.txt | 2 +-
|
||||
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/serial/mvebu-uart.txt
|
||||
+++ b/Documentation/devicetree/bindings/serial/mvebu-uart.txt
|
||||
@@ -8,6 +8,6 @@ Required properties:
|
||||
Example:
|
||||
serial@12000 {
|
||||
compatible = "marvell,armada-3700-uart";
|
||||
- reg = <0x12000 0x400>;
|
||||
+ reg = <0x12000 0x200>;
|
||||
interrupts = <43>;
|
||||
};
|
||||
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
||||
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
||||
@@ -134,7 +134,7 @@
|
||||
|
||||
uart0: serial@12000 {
|
||||
compatible = "marvell,armada-3700-uart";
|
||||
- reg = <0x12000 0x400>;
|
||||
+ reg = <0x12000 0x200>;
|
||||
interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
From 2ff0d0b5bb397c3dc5c9b97bd0f20948f0b77740 Mon Sep 17 00:00:00 2001
|
||||
From: Miquel Raynal <miquel.raynal@free-electrons.com>
|
||||
Date: Fri, 13 Oct 2017 11:01:57 +0200
|
||||
Subject: arm64: dts: marvell: armada-37xx: add UART clock
|
||||
|
||||
Add the missing clock property to armada-3700 UART node.
|
||||
|
||||
This clock will be used to derive the prescaler value to comply with
|
||||
the requested baudrate.
|
||||
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
|
||||
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
---
|
||||
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
||||
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
||||
@@ -135,6 +135,7 @@
|
||||
uart0: serial@12000 {
|
||||
compatible = "marvell,armada-3700-uart";
|
||||
reg = <0x12000 0x200>;
|
||||
+ clocks = <&xtalclk>;
|
||||
interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
|
@ -0,0 +1,48 @@
|
|||
From e8d66e7927b2a15310df0eb44a67d120ea147a59 Mon Sep 17 00:00:00 2001
|
||||
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
Date: Thu, 14 Dec 2017 16:00:06 +0100
|
||||
Subject: arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq
|
||||
support
|
||||
|
||||
In order to be able to use cpu freq, we need to associate a clock to each
|
||||
CPU and to expose the power management registers.
|
||||
|
||||
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
|
||||
---
|
||||
arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 +
|
||||
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 7 +++++++
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/marvell/armada-372x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/marvell/armada-372x.dtsi
|
||||
@@ -56,6 +56,7 @@
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a53","arm,armv8";
|
||||
reg = <0x1>;
|
||||
+ clocks = <&nb_periph_clk 16>;
|
||||
enable-method = "psci";
|
||||
};
|
||||
};
|
||||
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
||||
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
||||
@@ -64,6 +64,7 @@
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a53", "arm,armv8";
|
||||
reg = <0>;
|
||||
+ clocks = <&nb_periph_clk 16>;
|
||||
enable-method = "psci";
|
||||
};
|
||||
};
|
||||
@@ -219,6 +220,12 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ nb_pm: syscon@14000 {
|
||||
+ compatible = "marvell,armada-3700-nb-pm",
|
||||
+ "syscon";
|
||||
+ reg = <0x14000 0x60>;
|
||||
+ };
|
||||
+
|
||||
pinctrl_sb: pinctrl@18800 {
|
||||
compatible = "marvell,armada3710-sb-pinctrl",
|
||||
"syscon", "simple-mfd";
|
|
@ -0,0 +1,20 @@
|
|||
From be893f672e340b56ca60f2f6c32fdd713a5852f5 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Mihelich <kevin@archlinuxarm.org>
|
||||
Date: Tue, 4 Jul 2017 19:25:28 -0600
|
||||
Subject: arm64: dts: marvell: armada37xx: Add eth0 alias
|
||||
|
||||
Signed-off-by: Kevin Mihelich <kevin@archlinuxarm.org>
|
||||
---
|
||||
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
||||
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
||||
@@ -54,6 +54,7 @@
|
||||
#size-cells = <2>;
|
||||
|
||||
aliases {
|
||||
+ ethernet0 = ð0;
|
||||
serial0 = &uart0;
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
|
||||
+++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
|
||||
@@ -111,6 +111,26 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+&spi0 {
|
||||
+ status = "okay";
|
||||
+
|
||||
+ w25q32dw@0 {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+ compatible = "jedec,spi-nor";
|
||||
+ reg = <0>;
|
||||
+ spi-max-frequency = <104000000>;
|
||||
+ m25,fast-read;
|
||||
+
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&spi_quad_pins>;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&i2c0 {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
&mdio {
|
||||
switch0: switch0@1 {
|
||||
compatible = "marvell,mv88e6085";
|
|
@ -0,0 +1,66 @@
|
|||
From patchwork Thu Sep 28 12:58:32 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [v2, 1/7] PCI: aardvark: fix logic in PCI configuration read/write
|
||||
functions
|
||||
X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
X-Patchwork-Id: 819586
|
||||
Message-Id: <20170928125838.11887-2-thomas.petazzoni@free-electrons.com>
|
||||
To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
|
||||
Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
|
||||
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
|
||||
<gregory.clement@free-electrons.com>,
|
||||
Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
|
||||
Yehuda Yitschak <yehuday@marvell.com>,
|
||||
linux-arm-kernel@lists.infradead.org, Antoine Tenart
|
||||
<antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
|
||||
<miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>,
|
||||
stable@vger.kernel.org, Thomas Petazzoni
|
||||
<thomas.petazzoni@free-electrons.com>
|
||||
Date: Thu, 28 Sep 2017 14:58:32 +0200
|
||||
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
List-Id: <linux-pci.vger.kernel.org>
|
||||
|
||||
From: Victor Gu <xigu@marvell.com>
|
||||
|
||||
The PCI configuration space read/write functions were special casing
|
||||
the situation where PCI_SLOT(devfn) != 0, and returned
|
||||
PCIBIOS_DEVICE_NOT_FOUND in this case.
|
||||
|
||||
However, will this is what is intended for the root bus, it is not
|
||||
intended for the child busses, as it prevents discovering devices with
|
||||
PCI_SLOT(x) != 0. Therefore, we return PCIBIOS_DEVICE_NOT_FOUND only
|
||||
if we're on the root bus.
|
||||
|
||||
Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Victor Gu <xigu@marvell.com>
|
||||
Reviewed-by: Wilson Ding <dingwei@marvell.com>
|
||||
Reviewed-by: Nadav Haklai <nadavh@marvell.com>
|
||||
[Thomas: tweak commit log.]
|
||||
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
---
|
||||
drivers/pci/host/pci-aardvark.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/host/pci-aardvark.c
|
||||
+++ b/drivers/pci/host/pci-aardvark.c
|
||||
@@ -440,7 +440,7 @@ static int advk_pcie_rd_conf(struct pci_
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
- if (PCI_SLOT(devfn) != 0) {
|
||||
+ if ((bus->number == pcie->root_bus_nr) && (PCI_SLOT(devfn) != 0)) {
|
||||
*val = 0xffffffff;
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
@@ -494,7 +494,7 @@ static int advk_pcie_wr_conf(struct pci_
|
||||
int offset;
|
||||
int ret;
|
||||
|
||||
- if (PCI_SLOT(devfn) != 0)
|
||||
+ if ((bus->number == pcie->root_bus_nr) && (PCI_SLOT(devfn) != 0))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
if (where % size)
|
|
@ -0,0 +1,53 @@
|
|||
From patchwork Thu Sep 28 12:58:33 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [v2,
|
||||
2/7] PCI: aardvark: set PIO_ADDR_LS correctly in advk_pcie_rd_conf()
|
||||
X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
X-Patchwork-Id: 819589
|
||||
Message-Id: <20170928125838.11887-3-thomas.petazzoni@free-electrons.com>
|
||||
To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
|
||||
Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
|
||||
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
|
||||
<gregory.clement@free-electrons.com>,
|
||||
Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
|
||||
Yehuda Yitschak <yehuday@marvell.com>,
|
||||
linux-arm-kernel@lists.infradead.org, Antoine Tenart
|
||||
<antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
|
||||
<miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>,
|
||||
stable@vger.kernel.org, Thomas Petazzoni
|
||||
<thomas.petazzoni@free-electrons.com>
|
||||
Date: Thu, 28 Sep 2017 14:58:33 +0200
|
||||
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
List-Id: <linux-pci.vger.kernel.org>
|
||||
|
||||
From: Victor Gu <xigu@marvell.com>
|
||||
|
||||
When setting the PIO_ADDR_LS register during a configuration read, we
|
||||
were properly passing the device number, function number and register
|
||||
number, but not the bus number, causing issues when reading the
|
||||
configuration of PCIe devices.
|
||||
|
||||
Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Victor Gu <xigu@marvell.com>
|
||||
Reviewed-by: Wilson Ding <dingwei@marvell.com>
|
||||
Reviewed-by: Nadav Haklai <nadavh@marvell.com>
|
||||
[Thomas: tweak commit log.]
|
||||
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
---
|
||||
drivers/pci/host/pci-aardvark.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/pci/host/pci-aardvark.c
|
||||
+++ b/drivers/pci/host/pci-aardvark.c
|
||||
@@ -459,7 +459,7 @@ static int advk_pcie_rd_conf(struct pci_
|
||||
advk_writel(pcie, reg, PIO_CTRL);
|
||||
|
||||
/* Program the address registers */
|
||||
- reg = PCIE_BDF(devfn) | PCIE_CONF_REG(where);
|
||||
+ reg = PCIE_CONF_ADDR(bus->number, devfn, where);
|
||||
advk_writel(pcie, reg, PIO_ADDR_LS);
|
||||
advk_writel(pcie, 0, PIO_ADDR_MS);
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
From patchwork Thu Sep 28 12:58:34 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [v2,
|
||||
3/7] PCI: aardvark: set host and device to the same MAX payload size
|
||||
X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
X-Patchwork-Id: 819587
|
||||
Message-Id: <20170928125838.11887-4-thomas.petazzoni@free-electrons.com>
|
||||
To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
|
||||
Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
|
||||
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
|
||||
<gregory.clement@free-electrons.com>,
|
||||
Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
|
||||
Yehuda Yitschak <yehuday@marvell.com>,
|
||||
linux-arm-kernel@lists.infradead.org, Antoine Tenart
|
||||
<antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
|
||||
<miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>,
|
||||
Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
Date: Thu, 28 Sep 2017 14:58:34 +0200
|
||||
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
List-Id: <linux-pci.vger.kernel.org>
|
||||
|
||||
From: Victor Gu <xigu@marvell.com>
|
||||
|
||||
Since the Aardvark does not implement a PCIe root bus, the Linux PCIe
|
||||
subsystem will not align the MAX payload size between the host and the
|
||||
device. This patch ensures that the host and device have the same MAX
|
||||
payload size, fixing a number of problems with various PCIe devices.
|
||||
|
||||
This is part of fixing bug
|
||||
https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
|
||||
reported as the user to be important to get a Intel 7260 mini-PCIe
|
||||
WiFi card working.
|
||||
|
||||
Fixes: Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
|
||||
Signed-off-by: Victor Gu <xigu@marvell.com>
|
||||
Reviewed-by: Evan Wang <xswang@marvell.com>
|
||||
Reviewed-by: Nadav Haklai <nadavh@marvell.com>
|
||||
[Thomas: tweak commit log.]
|
||||
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
---
|
||||
drivers/pci/host/pci-aardvark.c | 60 ++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 59 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/pci/host/pci-aardvark.c
|
||||
+++ b/drivers/pci/host/pci-aardvark.c
|
||||
@@ -30,8 +30,10 @@
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_REG 0xc8
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE (0 << 4)
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT 5
|
||||
+#define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ 0x2
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE (0 << 11)
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT 12
|
||||
+#define PCIE_CORE_MPS_UNIT_BYTE 128
|
||||
#define PCIE_CORE_LINK_CTRL_STAT_REG 0xd0
|
||||
#define PCIE_CORE_LINK_L0S_ENTRY BIT(0)
|
||||
#define PCIE_CORE_LINK_TRAINING BIT(5)
|
||||
@@ -297,7 +299,8 @@ static void advk_pcie_setup_hw(struct ad
|
||||
|
||||
/* Set PCIe Device Control and Status 1 PF0 register */
|
||||
reg = PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE |
|
||||
- (7 << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
|
||||
+ (PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ <<
|
||||
+ PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
|
||||
PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE |
|
||||
PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT;
|
||||
advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG);
|
||||
@@ -879,6 +882,58 @@ out_release_res:
|
||||
return err;
|
||||
}
|
||||
|
||||
+static int advk_pcie_find_smpss(struct pci_dev *dev, void *data)
|
||||
+{
|
||||
+ u8 *smpss = data;
|
||||
+
|
||||
+ if (!dev)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!pci_is_pcie(dev))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (*smpss > dev->pcie_mpss)
|
||||
+ *smpss = dev->pcie_mpss;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int advk_pcie_bus_configure_mps(struct pci_dev *dev, void *data)
|
||||
+{
|
||||
+ int mps;
|
||||
+
|
||||
+ if (!dev)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!pci_is_pcie(dev))
|
||||
+ return 0;
|
||||
+
|
||||
+ mps = PCIE_CORE_MPS_UNIT_BYTE << *(u8 *)data;
|
||||
+ pcie_set_mps(dev, mps);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void advk_pcie_configure_mps(struct pci_bus *bus, struct advk_pcie *pcie)
|
||||
+{
|
||||
+ u8 smpss = PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ;
|
||||
+ u32 reg;
|
||||
+
|
||||
+ /* Find the minimal supported MAX payload size */
|
||||
+ advk_pcie_find_smpss(bus->self, &smpss);
|
||||
+ pci_walk_bus(bus, advk_pcie_find_smpss, &smpss);
|
||||
+
|
||||
+ /* Configure RC MAX payload size */
|
||||
+ reg = advk_readl(pcie, PCIE_CORE_DEV_CTRL_STATS_REG);
|
||||
+ reg &= ~PCI_EXP_DEVCTL_PAYLOAD;
|
||||
+ reg |= smpss << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT;
|
||||
+ advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG);
|
||||
+
|
||||
+ /* Configure device MAX payload size */
|
||||
+ advk_pcie_bus_configure_mps(bus->self, &smpss);
|
||||
+ pci_walk_bus(bus, advk_pcie_bus_configure_mps, &smpss);
|
||||
+}
|
||||
+
|
||||
static int advk_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -952,6 +1007,9 @@ static int advk_pcie_probe(struct platfo
|
||||
list_for_each_entry(child, &bus->children, node)
|
||||
pcie_bus_configure_settings(child);
|
||||
|
||||
+ /* Configure the MAX pay load size */
|
||||
+ advk_pcie_configure_mps(bus, pcie);
|
||||
+
|
||||
pci_bus_add_devices(bus);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
From patchwork Thu Sep 28 12:58:35 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [v2,
|
||||
4/7] PCI: aardvark: use isr1 instead of isr0 interrupt in legacy irq
|
||||
mode
|
||||
X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
X-Patchwork-Id: 819592
|
||||
Message-Id: <20170928125838.11887-5-thomas.petazzoni@free-electrons.com>
|
||||
To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
|
||||
Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
|
||||
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
|
||||
<gregory.clement@free-electrons.com>,
|
||||
Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
|
||||
Yehuda Yitschak <yehuday@marvell.com>,
|
||||
linux-arm-kernel@lists.infradead.org, Antoine Tenart
|
||||
<antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
|
||||
<miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>,
|
||||
Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
Date: Thu, 28 Sep 2017 14:58:35 +0200
|
||||
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
List-Id: <linux-pci.vger.kernel.org>
|
||||
|
||||
From: Victor Gu <xigu@marvell.com>
|
||||
|
||||
The Aardvark has two interrupts sets:
|
||||
|
||||
- first set is bit[23:16] of PCIe ISR 0 register(RD0074840h)
|
||||
|
||||
- second set is bit[11:8] of PCIe ISR 1 register(RD0074848h)
|
||||
|
||||
Only one set should be used, while another set should be masked.
|
||||
|
||||
The second set, ISR1, is more advanced, the Legacy INT_X status bit is
|
||||
asserted once Assert_INTX message is received, and de-asserted after
|
||||
Deassert_INTX message is received. Therefore, it matches what the
|
||||
driver is currently doing in the ->irq_mask() and ->irq_unmask()
|
||||
functions. The ISR0 requires additional work to deassert the
|
||||
interrupt, which the driver doesn't do currently.
|
||||
|
||||
This commit resolves a number of issues with legacy interrupts.
|
||||
|
||||
This is part of fixing bug
|
||||
https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
|
||||
reported as the user to be important to get a Intel 7260 mini-PCIe
|
||||
WiFi card working.
|
||||
|
||||
Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
|
||||
Signed-off-by: Victor Gu <xigu@marvell.com>
|
||||
Reviewed-by: Evan Wang <xswang@marvell.com>
|
||||
Reviewed-by: Nadav Haklai <nadavh@marvell.com>
|
||||
[Thomas: tweak commit log.]
|
||||
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
---
|
||||
drivers/pci/host/pci-aardvark.c | 41 ++++++++++++++++++++++++-----------------
|
||||
1 file changed, 24 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/drivers/pci/host/pci-aardvark.c
|
||||
+++ b/drivers/pci/host/pci-aardvark.c
|
||||
@@ -105,7 +105,8 @@
|
||||
#define PCIE_ISR1_MASK_REG (CONTROL_BASE_ADDR + 0x4C)
|
||||
#define PCIE_ISR1_POWER_STATE_CHANGE BIT(4)
|
||||
#define PCIE_ISR1_FLUSH BIT(5)
|
||||
-#define PCIE_ISR1_ALL_MASK GENMASK(5, 4)
|
||||
+#define PCIE_ISR1_INTX_ASSERT(val) BIT(8 + (val))
|
||||
+#define PCIE_ISR1_ALL_MASK GENMASK(11, 4)
|
||||
#define PCIE_MSI_ADDR_LOW_REG (CONTROL_BASE_ADDR + 0x50)
|
||||
#define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54)
|
||||
#define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58)
|
||||
@@ -615,9 +616,9 @@ static void advk_pcie_irq_mask(struct ir
|
||||
irq_hw_number_t hwirq = irqd_to_hwirq(d);
|
||||
u32 mask;
|
||||
|
||||
- mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
|
||||
- mask |= PCIE_ISR0_INTX_ASSERT(hwirq);
|
||||
- advk_writel(pcie, mask, PCIE_ISR0_MASK_REG);
|
||||
+ mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
|
||||
+ mask |= PCIE_ISR1_INTX_ASSERT(hwirq);
|
||||
+ advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
|
||||
}
|
||||
|
||||
static void advk_pcie_irq_unmask(struct irq_data *d)
|
||||
@@ -626,9 +627,9 @@ static void advk_pcie_irq_unmask(struct
|
||||
irq_hw_number_t hwirq = irqd_to_hwirq(d);
|
||||
u32 mask;
|
||||
|
||||
- mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
|
||||
- mask &= ~PCIE_ISR0_INTX_ASSERT(hwirq);
|
||||
- advk_writel(pcie, mask, PCIE_ISR0_MASK_REG);
|
||||
+ mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
|
||||
+ mask &= ~PCIE_ISR1_INTX_ASSERT(hwirq);
|
||||
+ advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
|
||||
}
|
||||
|
||||
static int advk_pcie_irq_map(struct irq_domain *h,
|
||||
@@ -771,29 +772,35 @@ static void advk_pcie_handle_msi(struct
|
||||
|
||||
static void advk_pcie_handle_int(struct advk_pcie *pcie)
|
||||
{
|
||||
- u32 val, mask, status;
|
||||
+ u32 isr0_val, isr0_mask, isr0_status;
|
||||
+ u32 isr1_val, isr1_mask, isr1_status;
|
||||
int i, virq;
|
||||
|
||||
- val = advk_readl(pcie, PCIE_ISR0_REG);
|
||||
- mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
|
||||
- status = val & ((~mask) & PCIE_ISR0_ALL_MASK);
|
||||
-
|
||||
- if (!status) {
|
||||
- advk_writel(pcie, val, PCIE_ISR0_REG);
|
||||
+ isr0_val = advk_readl(pcie, PCIE_ISR0_REG);
|
||||
+ isr0_mask = advk_readl(pcie, PCIE_ISR0_MASK_REG);
|
||||
+ isr0_status = isr0_val & ((~isr0_mask) & PCIE_ISR0_ALL_MASK);
|
||||
+
|
||||
+ isr1_val = advk_readl(pcie, PCIE_ISR1_REG);
|
||||
+ isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
|
||||
+ isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
|
||||
+
|
||||
+ if (!isr0_status && !isr1_status) {
|
||||
+ advk_writel(pcie, isr0_val, PCIE_ISR0_REG);
|
||||
+ advk_writel(pcie, isr1_val, PCIE_ISR1_REG);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process MSI interrupts */
|
||||
- if (status & PCIE_ISR0_MSI_INT_PENDING)
|
||||
+ if (isr0_status & PCIE_ISR0_MSI_INT_PENDING)
|
||||
advk_pcie_handle_msi(pcie);
|
||||
|
||||
/* Process legacy interrupts */
|
||||
for (i = 0; i < PCI_NUM_INTX; i++) {
|
||||
- if (!(status & PCIE_ISR0_INTX_ASSERT(i)))
|
||||
+ if (!(isr1_status & PCIE_ISR1_INTX_ASSERT(i)))
|
||||
continue;
|
||||
|
||||
- advk_writel(pcie, PCIE_ISR0_INTX_ASSERT(i),
|
||||
- PCIE_ISR0_REG);
|
||||
+ advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i),
|
||||
+ PCIE_ISR1_REG);
|
||||
|
||||
virq = irq_find_mapping(pcie->irq_domain, i);
|
||||
generic_handle_irq(virq);
|
|
@ -0,0 +1,55 @@
|
|||
From patchwork Thu Sep 28 12:58:36 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [v2,5/7] PCI: aardvark: disable LOS state by default
|
||||
X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
X-Patchwork-Id: 819590
|
||||
Message-Id: <20170928125838.11887-6-thomas.petazzoni@free-electrons.com>
|
||||
To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
|
||||
Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
|
||||
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
|
||||
<gregory.clement@free-electrons.com>,
|
||||
Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
|
||||
Yehuda Yitschak <yehuday@marvell.com>,
|
||||
linux-arm-kernel@lists.infradead.org, Antoine Tenart
|
||||
<antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
|
||||
<miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>,
|
||||
Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
Date: Thu, 28 Sep 2017 14:58:36 +0200
|
||||
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
List-Id: <linux-pci.vger.kernel.org>
|
||||
|
||||
From: Victor Gu <xigu@marvell.com>
|
||||
|
||||
Some PCIe devices do not support LOS, and will cause timeouts if the
|
||||
root complex forces the LOS state. This patch disables the LOS state
|
||||
by default.
|
||||
|
||||
This is part of fixing bug
|
||||
https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
|
||||
reported as the user to be important to get a Intel 7260 mini-PCIe
|
||||
WiFi card working.
|
||||
|
||||
Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
|
||||
Signed-off-by: Victor Gu <xigu@marvell.com>
|
||||
Reviewed-by: Evan Wang <xswang@marvell.com>
|
||||
Reviewed-by: Nadav Haklai <nadavh@marvell.com>
|
||||
[Thomas: tweak commit log.]
|
||||
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
---
|
||||
drivers/pci/host/pci-aardvark.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/host/pci-aardvark.c
|
||||
+++ b/drivers/pci/host/pci-aardvark.c
|
||||
@@ -368,8 +368,7 @@ static void advk_pcie_setup_hw(struct ad
|
||||
|
||||
advk_pcie_wait_for_link(pcie);
|
||||
|
||||
- reg = PCIE_CORE_LINK_L0S_ENTRY |
|
||||
- (1 << PCIE_CORE_LINK_WIDTH_SHIFT);
|
||||
+ reg = (1 << PCIE_CORE_LINK_WIDTH_SHIFT);
|
||||
advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
|
||||
|
||||
reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
|
|
@ -0,0 +1,63 @@
|
|||
From patchwork Thu Sep 28 12:58:37 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [v2,6/7] PCI: aardvark: fix PCIe max read request size setting
|
||||
X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
X-Patchwork-Id: 819591
|
||||
Message-Id: <20170928125838.11887-7-thomas.petazzoni@free-electrons.com>
|
||||
To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
|
||||
Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
|
||||
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
|
||||
<gregory.clement@free-electrons.com>,
|
||||
Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
|
||||
Yehuda Yitschak <yehuday@marvell.com>,
|
||||
linux-arm-kernel@lists.infradead.org, Antoine Tenart
|
||||
<antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
|
||||
<miquel.raynal@free-electrons.com>, Evan Wang <xswang@marvell.com>,
|
||||
Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
Date: Thu, 28 Sep 2017 14:58:37 +0200
|
||||
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
List-Id: <linux-pci.vger.kernel.org>
|
||||
|
||||
From: Evan Wang <xswang@marvell.com>
|
||||
|
||||
There is an obvious typo issue in the definition of the PCIe maximum
|
||||
read request size: a bit shift is directly used as a value, while it
|
||||
should be used to shift the correct value.
|
||||
|
||||
This is part of fixing bug
|
||||
https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
|
||||
reported as the user to be important to get a Intel 7260 mini-PCIe
|
||||
WiFi card working.
|
||||
|
||||
Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
|
||||
Signed-off-by: Evan Wang <xswang@marvell.com>
|
||||
Reviewed-by: Victor Gu <xigu@marvell.com>
|
||||
Reviewed-by: Nadav Haklai <nadavh@marvell.com>
|
||||
[Thomas: tweak commit log.]
|
||||
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
---
|
||||
drivers/pci/host/pci-aardvark.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/pci/host/pci-aardvark.c
|
||||
+++ b/drivers/pci/host/pci-aardvark.c
|
||||
@@ -33,6 +33,7 @@
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ 0x2
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE (0 << 11)
|
||||
#define PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT 12
|
||||
+#define PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ 0x2
|
||||
#define PCIE_CORE_MPS_UNIT_BYTE 128
|
||||
#define PCIE_CORE_LINK_CTRL_STAT_REG 0xd0
|
||||
#define PCIE_CORE_LINK_L0S_ENTRY BIT(0)
|
||||
@@ -303,7 +304,8 @@ static void advk_pcie_setup_hw(struct ad
|
||||
(PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ <<
|
||||
PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
|
||||
PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE |
|
||||
- PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT;
|
||||
+ (PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ <<
|
||||
+ PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT);
|
||||
advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG);
|
||||
|
||||
/* Program PCIe Control 2 to disable strict ordering */
|
Loading…
Reference in a new issue