diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 11:02:18 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 11:02:18 -0700 |
commit | fcba914542082b272f31c8e4c40000b88ed3208d (patch) | |
tree | fb28069bf571d93420daafd501b4e97f221d526c /arch/arm | |
parent | a8c4b90e670be3b01e9395c7310639c8109fc77e (diff) | |
parent | 5c5f0421a8eea5bdaba9b9313c5bb4833aeb39cd (diff) |
Merge tag 'soc-for-linus-3' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform updates (part 3) from Arnd Bergmann:
"This is the third and smallest of the SoC specific updates. Changes
include:
- SMP support for the Xilinx zynq platform
- Smaller imx changes
- LPAE support for mvebu
- Moving the orion5x, kirkwood, dove and mvebu platforms to a common
"mbus" driver for their internal devices.
It would be good to get feedback on the location of the "mbus" driver.
Since this is used on multiple platforms may potentially get shared
with other architectures (powerpc and arm64), it was moved to
drivers/bus/. We expect other similar drivers to get moved to the
same place in order to avoid creating more top-level directories under
drivers/ or cluttering up the messy drivers/misc/ even more."
* tag 'soc-for-linus-3' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (50 commits)
ARM: imx: reset_controller may be disabled
ARM: mvebu: Align the internal registers virtual base to support LPAE
ARM: mvebu: Limit the DMA zone when LPAE is selected
arm: plat-orion: remove addr-map code
arm: mach-mv78xx0: convert to use the mvebu-mbus driver
arm: mach-orion5x: convert to use mvebu-mbus driver
arm: mach-dove: convert to use mvebu-mbus driver
arm: mach-kirkwood: convert to use mvebu-mbus driver
arm: mach-mvebu: convert to use mvebu-mbus driver
ARM i.MX53: set CLK_SET_RATE_PARENT flag on the tve_ext_sel clock
ARM i.MX53: tve_di clock is not part of the CCM, but of TVE
ARM i.MX53: make tve_ext_sel propagate rate change to PLL
ARM i.MX53: Remove unused tve_gate clkdev entry
ARM i.MX5: Remove tve_sel clock from i.MX53 clock tree
ARM: i.MX5: Add PATA and SRTC clocks
ARM: imx: do not bring up unavailable cores
ARM: imx: add initial imx6dl support
ARM: imx1: mm: add call to mxc_device_init
ARM: imx_v4_v5_defconfig: Add CONFIG_GPIO_SYSFS
ARM: imx_v6_v7_defconfig: Select CONFIG_PERF_EVENTS
...
Diffstat (limited to 'arch/arm')
85 files changed, 1274 insertions, 995 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5c56fa8824e9..18bef301d6e6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -498,6 +498,7 @@ config ARCH_DOVE select PINCTRL_DOVE select PLAT_ORION_LEGACY select USB_ARCH_HAS_EHCI + select MVEBU_MBUS help Support for the Marvell Dove SoC 88AP510 @@ -511,6 +512,7 @@ config ARCH_KIRKWOOD select PINCTRL select PINCTRL_KIRKWOOD select PLAT_ORION_LEGACY + select MVEBU_MBUS help Support for the following Marvell Kirkwood series SoCs: 88F6180, 88F6192 and 88F6281. @@ -522,6 +524,7 @@ config ARCH_MV78XX0 select GENERIC_CLOCKEVENTS select PCI select PLAT_ORION_LEGACY + select MVEBU_MBUS help Support for the following Marvell MV78xx0 series SoCs: MV781x0, MV782x0. @@ -534,6 +537,7 @@ config ARCH_ORION5X select GENERIC_CLOCKEVENTS select PCI select PLAT_ORION_LEGACY + select MVEBU_MBUS help Support for the following Marvell Orion 5x series SoCs: Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182), diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index f57a6ba26e04..1d41908d5cda 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -245,11 +245,11 @@ choice on i.MX53. config DEBUG_IMX6Q_UART - bool "i.MX6Q Debug UART" + bool "i.MX6Q/DL Debug UART" depends on SOC_IMX6Q help Say Y here if you want kernel low-level debugging support - on i.MX6Q. + on i.MX6Q/DL. config DEBUG_MMP_UART2 bool "Kernel low-level debugging message via MMP UART2" diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi index 758c4ea90344..9693f796bcfe 100644 --- a/arch/arm/boot/dts/armada-370-xp.dtsi +++ b/arch/arm/boot/dts/armada-370-xp.dtsi @@ -73,11 +73,6 @@ clocks = <&coreclk 2>; }; - addr-decoding@d0020000 { - compatible = "marvell,armada-addr-decoding-controller"; - reg = <0xd0020000 0x258>; - }; - sata@d00a0000 { compatible = "marvell,orion-sata"; reg = <0xd00a0000 0x2400>; diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi index 748fc347ed18..14fb2e609bab 100644 --- a/arch/arm/boot/dts/zynq-7000.dtsi +++ b/arch/arm/boot/dts/zynq-7000.dtsi @@ -136,5 +136,12 @@ clock-names = "cpu_1x"; clock-ranges; }; + scutimer: scutimer@f8f00600 { + interrupt-parent = <&intc>; + interrupts = < 1 13 0x301 >; + compatible = "arm,cortex-a9-twd-timer"; + reg = < 0xf8f00600 0x20 >; + clocks = <&cpu_clk 1>; + } ; }; }; diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig index 02c657af4005..f07a847b00c9 100644 --- a/arch/arm/configs/imx_v4_v5_defconfig +++ b/arch/arm/configs/imx_v4_v5_defconfig @@ -109,6 +109,7 @@ CONFIG_I2C_IMX=y CONFIG_SPI=y CONFIG_SPI_IMX=y CONFIG_SPI_SPIDEV=y +CONFIG_GPIO_SYSFS=y CONFIG_W1=y CONFIG_W1_MASTER_MXC=y CONFIG_W1_SLAVE_THERM=y diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 088d6c11a0fa..6ec010f248b5 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -9,6 +9,7 @@ CONFIG_CGROUPS=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y # CONFIG_SLUB_DEBUG is not set # CONFIG_COMPAT_BRK is not set CONFIG_MODULES=y diff --git a/arch/arm/include/debug/mvebu.S b/arch/arm/include/debug/mvebu.S index 865c6d02b332..df191afa3be1 100644 --- a/arch/arm/include/debug/mvebu.S +++ b/arch/arm/include/debug/mvebu.S @@ -12,7 +12,7 @@ */ #define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000 -#define ARMADA_370_XP_REGS_VIRT_BASE 0xfeb00000 +#define ARMADA_370_XP_REGS_VIRT_BASE 0xfec00000 .macro addruart, rp, rv, tmp ldr \rp, =ARMADA_370_XP_REGS_PHYS_BASE diff --git a/arch/arm/mach-dove/Makefile b/arch/arm/mach-dove/Makefile index 3f0a858fb597..4d9d2ffc4535 100644 --- a/arch/arm/mach-dove/Makefile +++ b/arch/arm/mach-dove/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o irq.o +obj-y += common.o irq.o obj-$(CONFIG_DOVE_LEGACY) += mpp.o obj-$(CONFIG_PCI) += pcie.o obj-$(CONFIG_MACH_DOVE_DB) += dove-db-setup.o diff --git a/arch/arm/mach-dove/addr-map.c b/arch/arm/mach-dove/addr-map.c deleted file mode 100644 index 2a06c0163418..000000000000 --- a/arch/arm/mach-dove/addr-map.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * arch/arm/mach-dove/addr-map.c - * - * Address map functions for Marvell Dove 88AP510 SoC - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <asm/mach/arch.h> -#include <asm/setup.h> -#include <mach/dove.h> -#include <plat/addr-map.h> -#include "common.h" - -/* - * Generic Address Decode Windows bit settings - */ -#define TARGET_DDR 0x0 -#define TARGET_BOOTROM 0x1 -#define TARGET_CESA 0x3 -#define TARGET_PCIE0 0x4 -#define TARGET_PCIE1 0x8 -#define TARGET_SCRATCHPAD 0xd - -#define ATTR_CESA 0x01 -#define ATTR_BOOTROM 0xfd -#define ATTR_DEV_SPI0_ROM 0xfe -#define ATTR_DEV_SPI1_ROM 0xfb -#define ATTR_PCIE_IO 0xe0 -#define ATTR_PCIE_MEM 0xe8 -#define ATTR_SCRATCHPAD 0x0 - -static inline void __iomem *ddr_map_sc(int i) -{ - return (void __iomem *)(DOVE_MC_VIRT_BASE + 0x100 + ((i) << 4)); -} - -/* - * Description of the windows needed by the platform code - */ -static struct __initdata orion_addr_map_cfg addr_map_cfg = { - .num_wins = 8, - .remappable_wins = 4, - .bridge_virt_base = BRIDGE_VIRT_BASE, -}; - -static const struct __initdata orion_addr_map_info addr_map_info[] = { - /* - * Windows for PCIe IO+MEM space. - */ - { 0, DOVE_PCIE0_IO_PHYS_BASE, DOVE_PCIE0_IO_SIZE, - TARGET_PCIE0, ATTR_PCIE_IO, DOVE_PCIE0_IO_BUS_BASE - }, - { 1, DOVE_PCIE1_IO_PHYS_BASE, DOVE_PCIE1_IO_SIZE, - TARGET_PCIE1, ATTR_PCIE_IO, DOVE_PCIE1_IO_BUS_BASE - }, - { 2, DOVE_PCIE0_MEM_PHYS_BASE, DOVE_PCIE0_MEM_SIZE, - TARGET_PCIE0, ATTR_PCIE_MEM, -1 - }, - { 3, DOVE_PCIE1_MEM_PHYS_BASE, DOVE_PCIE1_MEM_SIZE, - TARGET_PCIE1, ATTR_PCIE_MEM, -1 - }, - /* - * Window for CESA engine. - */ - { 4, DOVE_CESA_PHYS_BASE, DOVE_CESA_SIZE, - TARGET_CESA, ATTR_CESA, -1 - }, - /* - * Window to the BootROM for Standby and Sleep Resume - */ - { 5, DOVE_BOOTROM_PHYS_BASE, DOVE_BOOTROM_SIZE, - TARGET_BOOTROM, ATTR_BOOTROM, -1 - }, - /* - * Window to the PMU Scratch Pad space - */ - { 6, DOVE_SCRATCHPAD_PHYS_BASE, DOVE_SCRATCHPAD_SIZE, - TARGET_SCRATCHPAD, ATTR_SCRATCHPAD, -1 - }, - /* End marker */ - { -1, 0, 0, 0, 0, 0 } -}; - -void __init dove_setup_cpu_mbus(void) -{ - int i; - int cs; - - /* - * Disable, clear and configure windows. - */ - orion_config_wins(&addr_map_cfg, addr_map_info); - - /* - * Setup MBUS dram target info. - */ - orion_mbus_dram_info.mbus_dram_target_id = TARGET_DDR; - - for (i = 0, cs = 0; i < 2; i++) { - u32 map = readl(ddr_map_sc(i)); - - /* - * Chip select enabled? - */ - if (map & 1) { - struct mbus_dram_window *w; - - w = &orion_mbus_dram_info.cs[cs++]; - w->cs_index = i; - w->mbus_attr = 0; /* CS address decoding done inside */ - /* the DDR controller, no need to */ - /* provide attributes */ - w->base = map & 0xff800000; - w->size = 0x100000 << (((map & 0x000f0000) >> 16) - 4); - } - } - orion_mbus_dram_info.num_cs = cs; -} diff --git a/arch/arm/mach-dove/board-dt.c b/arch/arm/mach-dove/board-dt.c index fbde1dd67113..0b142803b2e1 100644 --- a/arch/arm/mach-dove/board-dt.c +++ b/arch/arm/mach-dove/board-dt.c @@ -64,7 +64,7 @@ static void __init dove_dt_init(void) #ifdef CONFIG_CACHE_TAUROS2 tauros2_init(0); #endif - dove_setup_cpu_mbus(); + dove_setup_cpu_wins(); /* Setup root of clk tree */ dove_of_clk_init(); diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index c6b3b2bb50e7..e2b5da031f96 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -224,6 +224,9 @@ void __init dove_i2c_init(void) void __init dove_init_early(void) { orion_time_set_base(TIMER_VIRT_BASE); + mvebu_mbus_init("marvell,dove-mbus", + BRIDGE_WINS_BASE, BRIDGE_WINS_SZ, + DOVE_MC_WINS_BASE, DOVE_MC_WINS_SZ); } static int __init dove_find_tclk(void) @@ -326,6 +329,40 @@ void __init dove_sdio1_init(void) platform_device_register(&dove_sdio1); } +void __init dove_setup_cpu_wins(void) +{ + /* + * The PCIe windows will no longer be statically allocated + * here once Dove is migrated to the pci-mvebu driver. + */ + mvebu_mbus_add_window_remap_flags("pcie0.0", + DOVE_PCIE0_IO_PHYS_BASE, + DOVE_PCIE0_IO_SIZE, + DOVE_PCIE0_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pcie1.0", + DOVE_PCIE1_IO_PHYS_BASE, + DOVE_PCIE1_IO_SIZE, + DOVE_PCIE1_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pcie0.0", + DOVE_PCIE0_MEM_PHYS_BASE, + DOVE_PCIE0_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window_remap_flags("pcie1.0", + DOVE_PCIE1_MEM_PHYS_BASE, + DOVE_PCIE1_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window("cesa", DOVE_CESA_PHYS_BASE, + DOVE_CESA_SIZE); + mvebu_mbus_add_window("bootrom", DOVE_BOOTROM_PHYS_BASE, + DOVE_BOOTROM_SIZE); + mvebu_mbus_add_window("scratchpad", DOVE_SCRATCHPAD_PHYS_BASE, + DOVE_SCRATCHPAD_SIZE); +} + void __init dove_init(void) { pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n", @@ -334,7 +371,7 @@ void __init dove_init(void) #ifdef CONFIG_CACHE_TAUROS2 tauros2_init(0); #endif - dove_setup_cpu_mbus(); + dove_setup_cpu_wins(); /* Setup root of clk tree */ dove_clk_init(); diff --git a/arch/arm/mach-dove/common.h b/arch/arm/mach-dove/common.h index ee59fba4c6d1..e86347928b67 100644 --- a/arch/arm/mach-dove/common.h +++ b/arch/arm/mach-dove/common.h @@ -23,7 +23,7 @@ void dove_map_io(void); void dove_init(void); void dove_init_early(void); void dove_init_irq(void); -void dove_setup_cpu_mbus(void); +void dove_setup_cpu_wins(void); void dove_ge00_init(struct mv643xx_eth_platform_data *eth_data); void dove_sata_init(struct mv_sata_platform_data *sata_data); #ifdef CONFIG_PCI diff --git a/arch/arm/mach-dove/include/mach/dove.h b/arch/arm/mach-dove/include/mach/dove.h index 661725e3115a..0c4b35f4ee5b 100644 --- a/arch/arm/mach-dove/include/mach/dove.h +++ b/arch/arm/mach-dove/include/mach/dove.h @@ -77,6 +77,8 @@ /* North-South Bridge */ #define BRIDGE_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0x20000) #define BRIDGE_PHYS_BASE (DOVE_SB_REGS_PHYS_BASE + 0x20000) +#define BRIDGE_WINS_BASE (BRIDGE_PHYS_BASE) +#define BRIDGE_WINS_SZ (0x80) /* Cryptographic Engine */ #define DOVE_CRYPT_PHYS_BASE (DOVE_SB_REGS_PHYS_BASE + 0x30000) @@ -168,6 +170,9 @@ #define DOVE_SSP_CLOCK_ENABLE (1 << 1) #define DOVE_SSP_BPB_CLOCK_SRC_SSP (1 << 11) /* Memory Controller */ +#define DOVE_MC_PHYS_BASE (DOVE_NB_REGS_PHYS_BASE + 0x00000) +#define DOVE_MC_WINS_BASE (DOVE_MC_PHYS_BASE + 0x100) +#define DOVE_MC_WINS_SZ (0x8) #define DOVE_MC_VIRT_BASE (DOVE_NB_REGS_VIRT_BASE + 0x00000) /* LCD Controller */ diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 2ebc97e16b91..78f795d73cb6 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -65,6 +65,9 @@ config IRAM_ALLOC bool select GENERIC_ALLOCATOR +config HAVE_IMX_ANATOP + bool + config HAVE_IMX_GPC bool @@ -73,6 +76,7 @@ config HAVE_IMX_MMDC config HAVE_IMX_SRC def_bool y if SMP + select ARCH_HAS_RESET_CONTROLLER config IMX_HAVE_IOMUX_V1 bool @@ -115,6 +119,8 @@ config SOC_IMX25 config SOC_IMX27 bool + select ARCH_HAS_CPUFREQ + select ARCH_HAS_OPP select COMMON_CLK select CPU_ARM926T select IMX_HAVE_IOMUX_V1 @@ -142,6 +148,7 @@ config SOC_IMX35 config SOC_IMX5 bool select ARCH_HAS_CPUFREQ + select ARCH_HAS_OPP select ARCH_MXC_IOMUX_V3 select COMMON_CLK select CPU_V7 @@ -783,7 +790,7 @@ config SOC_IMX53 This enables support for Freescale i.MX53 processor. config SOC_IMX6Q - bool "i.MX6 Quad support" + bool "i.MX6 Quad/DualLite support" select ARCH_HAS_CPUFREQ select ARCH_HAS_OPP select ARM_CPU_SUSPEND if PM @@ -796,6 +803,7 @@ config SOC_IMX6Q select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if LOCAL_TIMERS select HAVE_CAN_FLEXCAN if CAN + select HAVE_IMX_ANATOP select HAVE_IMX_GPC select HAVE_IMX_MMDC select HAVE_IMX_SRC diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index fbe60a145344..930958973f81 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -91,6 +91,7 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX35SD) += mach-cpuimx35.o obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o +obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o obj-$(CONFIG_HAVE_IMX_SRC) += src.o diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c new file mode 100644 index 000000000000..0cfa07dd9aa4 --- /dev/null +++ b/arch/arm/mach-imx/anatop.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/err.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> +#include "common.h" + +#define REG_SET 0x4 +#define REG_CLR 0x8 + +#define ANADIG_REG_2P5 0x130 +#define ANADIG_REG_CORE 0x140 +#define ANADIG_ANA_MISC0 0x150 +#define ANADIG_USB1_CHRG_DETECT 0x1b0 +#define ANADIG_USB2_CHRG_DETECT 0x210 +#define ANADIG_DIGPROG 0x260 + +#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000 +#define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000 +#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG 0x1000 +#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000 +#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000 + +static struct regmap *anatop; + +static void imx_anatop_enable_weak2p5(bool enable) +{ + u32 reg, val; + + regmap_read(anatop, ANADIG_ANA_MISC0, &val); + + /* can only be enabled when stop_mode_config is clear. */ + reg = ANADIG_REG_2P5; + reg += (enable && (val & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) ? + REG_SET : REG_CLR; + regmap_write(anatop, reg, BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG); +} + +static void imx_anatop_enable_fet_odrive(bool enable) +{ + regmap_write(anatop, ANADIG_REG_CORE + (enable ? REG_SET : REG_CLR), + BM_ANADIG_REG_CORE_FET_ODRIVE); +} + +void imx_anatop_pre_suspend(void) +{ + imx_anatop_enable_weak2p5(true); + imx_anatop_enable_fet_odrive(true); +} + +void imx_anatop_post_resume(void) +{ + imx_anatop_enable_fet_odrive(false); + imx_anatop_enable_weak2p5(false); +} + +void imx_anatop_usb_chrg_detect_disable(void) +{ + regmap_write(anatop, ANADIG_USB1_CHRG_DETECT, + BM_ANADIG_USB_CHRG_DETECT_EN_B + | BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B); + regmap_write(anatop, ANADIG_USB2_CHRG_DETECT, + BM_ANADIG_USB_CHRG_DETECT_EN_B | + BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B); +} + +u32 imx_anatop_get_digprog(void) +{ + struct device_node *np; + void __iomem *anatop_base; + static u32 digprog; + + if (digprog) + return digprog; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop"); + anatop_base = of_iomap(np, 0); + WARN_ON(!anatop_base); + digprog = readl_relaxed(anatop_base + ANADIG_DIGPROG); + + return digprog; +} + +void __init imx_anatop_init(void) +{ + anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop"); + if (IS_ERR(anatop)) { + pr_err("%s: failed to find imx6q-anatop regmap!\n", __func__); + return; + } +} diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index 2bc623b414c1..6fc486b6a3c6 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c @@ -45,16 +45,40 @@ static const char *mx53_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", " static const char *mx53_ldb_di1_sel[] = { "pll3_sw", "pll4_sw", }; static const char *mx51_tve_ext_sel[] = { "osc", "ckih1", }; static const char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", }; -static const char *tve_sel[] = { "tve_pred", "tve_ext_sel", }; +static const char *mx51_tve_sel[] = { "tve_pred", "tve_ext_sel", }; static const char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", }; +static const char *gpu3d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" }; +static const char *gpu2d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" }; static const char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", }; static const char *mx53_can_sel[] = { "ipg", "ckih1", "ckih2", "lp_apm", }; +static const char *mx53_cko1_sel[] = { + "cpu_podf", "pll1_sw", "pll2_sw", "pll3_sw", + "emi_slow_podf", "pll4_sw", "nfc_podf", "dummy", + "di_pred", "dummy", "dummy", "ahb", + "ipg", "per_root", "ckil", "dummy",}; +static const char *mx53_cko2_sel[] = { + "dummy"/* dptc_core */, "dummy"/* dptc_perich */, + "dummy", "esdhc_a_podf", + "usboh3_podf", "dummy"/* wrck_clk_root */, + "ecspi_podf", "dummy"/* pll1_ref_clk */, + "esdhc_b_podf", "dummy"/* ddr_clk_root */, + "dummy"/* arm_axi_clk_root */, "dummy"/* usb_phy_out */, + "vpu_sel", "ipu_sel", + "osc", "ckih1", + "dummy", "esdhc_c_sel", + "ssi1_root_podf", "ssi2_root_podf", + "dummy", "dummy", + "dummy"/* lpsr_clk_root */, "dummy"/* pgc_clk_root */, + "dummy"/* tve_out */, "usb_phy_sel", + "tve_sel", "lp_apm", + "uart_root", "dummy"/* spdif0_clk_root */, + "dummy", "dummy", }; enum imx5_clks { dummy, ckil, osc, ckih1, ckih2, ahb, ipg, axi_a, axi_b, uart_pred, uart_root, esdhc_a_pred, esdhc_b_pred, esdhc_c_s, esdhc_d_s, emi_sel, emi_slow_podf, nfc_podf, ecspi_pred, ecspi_podf, usboh3_pred, - usboh3_podf, usb_phy_pred, usb_phy_podf, cpu_podf, di_pred, tve_di, + usboh3_podf, usb_phy_pred, usb_phy_podf, cpu_podf, di_pred, tve_di_unused, tve_s, uart1_ipg_gate, uart1_per_gate, uart2_ipg_gate, uart2_per_gate, uart3_ipg_gate, uart3_per_gate, i2c1_gate, i2c2_gate, gpt_ipg_gate, pwm1_ipg_gate, pwm1_hf_gate, pwm2_ipg_gate, pwm2_hf_gate, @@ -83,7 +107,10 @@ enum imx5_clks { ssi2_root_gate, ssi3_root_gate, ssi_ext1_gate, ssi_ext2_gate, epit1_ipg_gate, epit1_hf_gate, epit2_ipg_gate, epit2_hf_gate, can_sel, can1_serial_gate, can1_ipg_gate, - owire_gate, + owire_gate, gpu3d_s, gpu2d_s, gpu3d_gate, gpu2d_gate, garb_gate, + cko1_sel, cko1_podf, cko1, + cko2_sel, cko2_podf, cko2, + srtc_gate, pata_gate, clk_max }; @@ -160,8 +187,6 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str)); clk[cpu_podf] = imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3); clk[di_pred] = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3); - clk[tve_di] = imx_clk_fixed("tve_di", 65000000); /* FIXME */ - clk[tve_s] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, tve_sel, ARRAY_SIZE(tve_sel)); clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30); clk[uart1_ipg_gate] = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6); clk[uart1_per_gate] = imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8); @@ -200,6 +225,11 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk[nfc_gate] = imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20); clk[ipu_di0_gate] = imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10); clk[ipu_di1_gate] = imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12); + clk[gpu3d_s] = imx_clk_mux("gpu3d_sel", MXC_CCM_CBCMR, 4, 2, gpu3d_sel, ARRAY_SIZE(gpu3d_sel)); + clk[gpu2d_s] = imx_clk_mux("gpu2d_sel", MXC_CCM_CBCMR, 16, 2, gpu2d_sel, ARRAY_SIZE(gpu2d_sel)); + clk[gpu3d_gate] = imx_clk_gate2("gpu3d_gate", "gpu3d_sel", MXC_CCM_CCGR5, 2); + clk[garb_gate] = imx_clk_gate2("garb_gate", "axi_a", MXC_CCM_CCGR5, 4); + clk[gpu2d_gate] = imx_clk_gate2("gpu2d_gate", "gpu2d_sel", MXC_CCM_CCGR6, 14); clk[vpu_s] = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel)); clk[vpu_gate] = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6); clk[vpu_reference_gate] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8); @@ -235,6 +265,8 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk[epit2_ipg_gate] = imx_clk_gate2("epit2_ipg_gate", "ipg", MXC_CCM_CCGR2, 6); clk[epit2_hf_gate] = imx_clk_gate2("epit2_hf_gate", "per_root", MXC_CCM_CCGR2, 8); clk[owire_gate] = imx_clk_gate2("owire_gate", "per_root", MXC_CCM_CCGR2, 22); + clk[srtc_gate] = imx_clk_gate2("srtc_gate", "per_root", MXC_CCM_CCGR4, 28); + clk[pata_gate] = imx_clk_gate2("pata_gate", "ipg", MXC_CCM_CCGR4, 0); for (i = 0; i < ARRAY_SIZE(clk); i++) if (IS_ERR(clk[i])) @@ -286,7 +318,6 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.0"); clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.1"); clk_register_clkdev(clk[dummy], NULL, "imx-keypad"); - clk_register_clkdev(clk[tve_gate], NULL, "imx-tve.0"); clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0"); clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL); clk_register_clkdev(clk[epit1_ipg_gate], "ipg", "imx-epit.0"); @@ -331,8 +362,10 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel)); clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel)); - clk[tve_ext_sel] = imx_clk_mux("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, - mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel)); + clk[tve_ext_sel] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, + mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT); + clk[tve_s] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, + mx51_tve_sel, ARRAY_SIZE(mx51_tve_sel)); clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30); clk[tve_pred] = imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3); clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); @@ -420,23 +453,23 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, clk[pll3_sw] = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE); clk[pll4_sw] = imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE); - clk[ldb_di1_sel] = imx_clk_mux("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1, - mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel)); clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); - clk[ldb_di1_div] = imx_clk_divider("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1); + clk[ldb_di1_div] = imx_clk_divider_flags("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1, 0); + clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1, + mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel), CLK_SET_RATE_PARENT); clk[di_pll4_podf] = imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3); - clk[ldb_di0_sel] = imx_clk_mux("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1, - mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel)); clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); - clk[ldb_di0_div] = imx_clk_divider("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1); + clk[ldb_di0_div] = imx_clk_divider_flags("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1, 0); + clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1, + mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT); clk[ldb_di0_gate] = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28); clk[ldb_di1_gate] = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30); clk[ipu_di0_sel] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel)); clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel)); - clk[tve_ext_sel] = imx_clk_mux("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, - mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel)); + clk[tve_ext_sel] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, + mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT); clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30); clk[tve_pred] = imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3); clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); @@ -453,6 +486,16 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6); clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22); + clk[cko1_sel] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4, + mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel)); + clk[cko1_podf] = imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3); + clk[cko1] = imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7); + + clk[cko2_sel] = imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5, + mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel)); + clk[cko2_podf] = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3); + clk[cko2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24); + for (i = 0; i < ARRAY_SIZE(clk); i++) if (IS_ERR(clk[i])) pr_err("i.MX53 clk %d: register failed with %ld\n", diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index d38e54f5b6d7..151259003086 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011-2013 Freescale Semiconductor, Inc. * Copyright 2011 Linaro Ltd. * * The code contained herein is licensed under the GNU General Public @@ -14,6 +14,7 @@ #include <linux/types.h> #include <linux/clk.h> #include <linux/clkdev.h> +#include <linux/delay.h> #include <linux/err.h> #include <linux/io.h> #include <linux/of.h> @@ -22,6 +23,12 @@ #include "clk.h" #include "common.h" +#include "hardware.h" + +#define CCR 0x0 +#define BM_CCR_WB_COUNT (0x7 << 16) +#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21) +#define BM_CCR_RBC_EN (0x1 << 27) #define CCGR0 0x68 #define CCGR1 0x6c @@ -67,6 +74,67 @@ void imx6q_set_chicken_bit(void) writel_relaxed(val, ccm_base + CGPR); } +static void imx6q_enable_rbc(bool enable) +{ + u32 val; + static bool last_rbc_mode; + + if (last_rbc_mode == enable) + return; + /* + * need to mask all interrupts in GPC before + * operating RBC configurations + */ + imx_gpc_mask_all(); + + /* configure RBC enable bit */ + val = readl_relaxed(ccm_base + CCR); + val &= ~BM_CCR_RBC_EN; + val |= enable ? BM_CCR_RBC_EN : 0; + writel_relaxed(val, ccm_base + CCR); + + /* configure RBC count */ + val = readl_relaxed(ccm_base + CCR); + val &= ~BM_CCR_RBC_BYPASS_COUNT; + val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0; + writel(val, ccm_base + CCR); + + /* + * need to delay at least 2 cycles of CKIL(32K) + * due to hardware design requirement, which is + * ~61us, here we use 65us for safe + */ + udelay(65); + + /* restore GPC interrupt mask settings */ + imx_gpc_restore_all(); + + last_rbc_mode = enable; +} + +static void imx6q_enable_wb(bool enable) +{ + u32 val; + static bool last_wb_mode; + + if (last_wb_mode == enable) + return; + + /* configure well bias enable bit */ + val = readl_relaxed(ccm_base + CLPCR); + val &= ~BM_CLPCR_WB_PER_AT_LPM; + val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0; + writel_relaxed(val, ccm_base + CLPCR); + + /* configure well bias count */ + val = readl_relaxed(ccm_base + CCR); + val &= ~BM_CCR_WB_COUNT; + val |= enable ? BM_CCR_WB_COUNT : 0; + writel_relaxed(val, ccm_base + CCR); + + last_wb_mode = enable; +} + int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) { u32 val = readl_relaxed(ccm_base + CLPCR); @@ -74,6 +142,8 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) val &= ~BM_CLPCR_LPM; switch (mode) { case WAIT_CLOCKED: + imx6q_enable_wb(false); + imx6q_enable_rbc(false); break; case WAIT_UNCLOCKED: val |= 0x1 << BP_CLPCR_LPM; @@ -92,6 +162,8 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) val |= 0x3 << BP_CLPCR_STBY_COUNT; val |= BM_CLPCR_VSTBY; val |= BM_CLPCR_SBYOS; + imx6q_enable_wb(true); + imx6q_enable_rbc(true); break; default: return -EINVAL; @@ -109,29 +181,29 @@ static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", }; static const char *periph_sels[] = { "periph_pre", "periph_clk2", }; static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", }; static const char *axi_sels[] = { "periph", "pll2_pfd2_396m", "pll3_pfd1_540m", }; -static const char *audio_sels[] = { "pll4_audio", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", }; +static const char *audio_sels[] = { "pll4_post_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", }; static const char *gpu_axi_sels[] = { "axi", "ahb", }; static const char *gpu2d_core_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", }; static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", }; static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", }; static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", }; static const char *ldb_di_sels[] = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", }; -static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", }; +static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", }; static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; static const char *ipu2_di0_sels[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; static const char *ipu2_di1_sels[] = { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; static const char *hsi_tx_sels[] = { "pll3_120m", "pll2_pfd2_396m", }; static const char *pcie_axi_sels[] = { "axi", "ahb", }; -static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio", }; +static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_post_div", }; static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", }; static const char *emi_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", }; static const char *vdo_axi_sels[] = { "axi", "ahb", }; static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", }; -static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video", +static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div", "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0", - "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio", }; + "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_post_div", }; enum mx6q_clks { dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m, @@ -165,7 +237,7 @@ enum mx6q_clks { pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg, ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate, - usbphy2_gate, clk_max + usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, clk_max }; static struct clk *clk[clk_max]; @@ -182,6 +254,21 @@ static struct clk_div_table clk_enet_ref_table[] = { { .val = 3, .div = 4, }, }; +static struct clk_div_table post_div_table[] = { + { .val = 2, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 0, .div = 4, }, + { } +}; + +static struct clk_div_table video_div_table[] = { + { .val = 0, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 2, .div = 1, }, + { .val = 3, .div = 4, }, + { } +}; + int __init mx6q_clocks_init(void) { struct device_node *np; @@ -208,6 +295,14 @@ int __init mx6q_clocks_init(void) base = of_iomap(np, 0); WARN_ON(!base); + /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */ + if (cpu_is_imx6q() && imx6q_revision() == IMX_CHIP_REVISION_1_0) { + post_div_table[1].div = 1; + post_div_table[2].div = 1; + video_div_table[1].div = 1; + video_div_table[2].div = 1; + }; + /* type name parent_name base div_mask */ clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f); clk[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1); @@ -260,6 +355,10 @@ int __init mx6q_clocks_init(void) clk[pll3_60m] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2); + clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock); + clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock); + clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock); + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm"); base = of_iomap(np, 0); WARN_ON(!base); @@ -283,8 +382,8 @@ int __init mx6q_clocks_init(void) clk[gpu3d_shader_sel] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels)); clk[ipu1_sel] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); - clk[ldb_di0_sel] = imx_clk_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels)); - clk[ldb_di1_sel] = imx_clk_mux("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels)); + clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); + clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); @@ -332,9 +431,9 @@ int __init mx6q_clocks_init(void) clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3); clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3); clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); - clk[ldb_di0_podf] = imx_clk_divider("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1); + clk[ldb_di0_podf] = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0); clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); - clk[ldb_di1_podf] = imx_clk_divider("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1); + clk[ldb_di1_podf] = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0); clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3); clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3); clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3); @@ -448,6 +547,11 @@ int __init mx6q_clocks_init(void) clk_register_clkdev(clk[cko1], "cko1", NULL); clk_register_clkdev(clk[arm], NULL, "cpu0"); + if (imx6q_revision() != IMX_CHIP_REVISION_1_0) { + clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]); + clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]); + } + /* * The gpmi needs 100MHz frequency in the EDO/Sync mode, * We can not get the 100MHz from the pll2_pfd0_352m. diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 9d1f3b99d1d3..d9d9d9c66dff 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -59,6 +59,14 @@ static inline struct clk *imx_clk_divider(const char *name, const char *parent, reg, shift, width, 0, &imx_ccm_lock); } +static inline struct clk *imx_clk_divider_flags(const char *name, + const char *parent, void __iomem *reg, u8 shift, u8 width, + unsigned long flags) +{ + return clk_register_divider(NULL, name, parent, flags, + reg, shift, width, 0, &imx_ccm_lock); +} + static inline struct clk *imx_clk_gate(const char *name, const char *parent, void __iomem *reg, u8 shift) { @@ -73,6 +81,15 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg, width, 0, &imx_ccm_lock); } +static inline struct clk *imx_clk_mux_flags(const char *name, + void __iomem *reg, u8 shift, u8 width, const char **parents, + int num_parents, unsigned long flags) +{ + return clk_register_mux(NULL, name, parents, num_parents, + flags, reg, shift, width, 0, + &imx_ccm_lock); +} + static inline struct clk *imx_clk_fixed_factor(const char *name, const char *parent, unsigned int mult, unsigned int div) { diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 9fea2522d7a3..4cba7dbb079f 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -74,6 +74,7 @@ extern void mxc_set_cpu_type(unsigned int type); extern void mxc_restart(char, const char *); extern void mxc_arch_reset_init(void __iomem *); extern int mx53_revision(void); +extern int imx6q_revision(void); extern int mx53_display_revision(void); extern void imx_set_aips(void __iomem *); extern int mxc_device_init(void); @@ -128,6 +129,13 @@ extern void imx_src_prepare_restart(void); extern void imx_gpc_init(void); extern void imx_gpc_pre_suspend(void); extern void imx_gpc_post_resume(void); +extern void imx_gpc_mask_all(void); +extern void imx_gpc_restore_all(void); +extern void imx_anatop_init(void); +extern void imx_anatop_pre_suspend(void); +extern void imx_anatop_post_resume(void); +extern void imx_anatop_usb_chrg_detect_disable(void); +extern u32 imx_anatop_get_digprog(void); extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); extern void imx6q_set_chicken_bit(void); diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index 02b61cdf39b9..44a65e9ff1fc 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011-2013 Freescale Semiconductor, Inc. * Copyright 2011 Linaro Ltd. * * The code contained herein is licensed under the GNU General Public @@ -69,6 +69,27 @@ static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on) return 0; } +void imx_gpc_mask_all(void) +{ + void __iomem *reg_imr1 = gpc_base + GPC_IMR1; + int i; + + for (i = 0; i < IMR_NUM; i++) { + gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); + writel_relaxed(~0, reg_imr1 + i * 4); + } + +} + +void imx_gpc_restore_all(void) +{ + void __iomem *reg_imr1 = gpc_base + GPC_IMR1; + int i; + + for (i = 0; i < IMR_NUM; i++) + writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4); +} + static void imx_gpc_irq_unmask(struct irq_data *d) { void __iomem *reg; diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 99502eeefdf7..5536fd81379a 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011-2013 Freescale Semiconductor, Inc. * Copyright 2011 Linaro Ltd. * * The code contained herein is licensed under the GNU General Public @@ -38,38 +38,32 @@ #include "cpuidle.h" #include "hardware.h" -#define IMX6Q_ANALOG_DIGPROG 0x260 +static u32 chip_revision; -static int imx6q_revision(void) +int imx6q_revision(void) { - struct device_node *np; - void __iomem *base; - static u32 rev; - - if (!rev) { - np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop"); - if (!np) - return IMX_CHIP_REVISION_UNKNOWN; - base = of_iomap(np, 0); - if (!base) { - of_node_put(np); - return IMX_CHIP_REVISION_UNKNOWN; - } - rev = readl_relaxed(base + IMX6Q_ANALOG_DIGPROG); - iounmap(base); - of_node_put(np); - } + return chip_revision; +} + +static void __init imx6q_init_revision(void) +{ + u32 rev = imx_anatop_get_digprog(); switch (rev & 0xff) { case 0: - return IMX_CHIP_REVISION_1_0; + chip_revision = IMX_CHIP_REVISION_1_0; + break; case 1: - return IMX_CHIP_REVISION_1_1; + chip_revision = IMX_CHIP_REVISION_1_1; + break; case 2: - return IMX_CHIP_REVISION_1_2; + chip_revision = IMX_CHIP_REVISION_1_2; + break; default: - return IMX_CHIP_REVISION_UNKNOWN; + chip_revision = IMX_CHIP_REVISION_UNKNOWN; } + + mxc_set_cpu_type(rev >> 16 & 0xff); } static void imx6q_restart(char mode, const char *cmd) @@ -164,29 +158,7 @@ static void __init imx6q_1588_init(void) } static void __init imx6q_usb_init(void) { - struct regmap *anatop; - -#define HW_ANADIG_USB1_CHRG_DETECT 0x000001b0 -#define HW_ANADIG_USB2_CHRG_DETECT 0x00000210 - -#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x00100000 -#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x00080000 - - anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop"); - if (!IS_ERR(anatop)) { - /* - * The external charger detector needs to be disabled, - * or the signal at DP will be poor - */ - regmap_write(anatop, HW_ANADIG_USB1_CHRG_DETECT, - BM_ANADIG_USB_CHRG_DETECT_EN_B - | BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B); - regmap_write(anatop, HW_ANADIG_USB2_CHRG_DETECT, - BM_ANADIG_USB_CHRG_DETECT_EN_B | - BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B); - } else { - pr_warn("failed to find fsl,imx6q-anatop regmap\n"); - } + imx_anatop_usb_chrg_detect_disable(); } static void __init imx6q_init_machine(void) @@ -196,6 +168,7 @@ static void __init imx6q_init_machine(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + imx_anatop_init(); imx6q_pm_init(); imx6q_usb_init(); imx6q_1588_init(); @@ -282,6 +255,7 @@ static void __init imx6q_map_io(void) static void __init imx6q_init_irq(void) { + imx6q_init_revision(); l2x0_of_init(0, ~0UL); imx_src_init(); imx_gpc_init(); @@ -292,15 +266,17 @@ static void __init imx6q_timer_init(void) { mx6q_clocks_init(); clocksource_of_init(); - imx_print_silicon_rev("i.MX6Q", imx6q_revision()); + imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q", + imx6q_revision()); } static const char *imx6q_dt_compat[] __initdata = { + "fsl,imx6dl", "fsl,imx6q", NULL, }; -DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)") +DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)") .smp = smp_ops(imx_smp_ops), .map_io = imx6q_map_io, .init_irq = imx6q_init_irq, diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c index 7a146671e65a..3c609c52d3eb 100644 --- a/arch/arm/mach-imx/mm-imx1.c +++ b/arch/arm/mach-imx/mm-imx1.c @@ -51,6 +51,8 @@ void __init mx1_init_irq(void) void __init imx1_soc_init(void) { + mxc_device_init(); + mxc_register_gpio("imx1-gpio", 0, MX1_GPIO1_BASE_ADDR, SZ_256, MX1_GPIO_INT_PORTA, 0); mxc_register_gpio("imx1-gpio", 1, MX1_GPIO2_BASE_ADDR, SZ_256, diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h index 7dce17a9fe6c..8629e5be7ecd 100644 --- a/arch/arm/mach-imx/mxc.h +++ b/arch/arm/mach-imx/mxc.h @@ -34,6 +34,8 @@ #define MXC_CPU_MX35 35 #define MXC_CPU_MX51 51 #define MXC_CPU_MX53 53 +#define MXC_CPU_IMX6DL 0x61 +#define MXC_CPU_IMX6Q 0x63 #define IMX_CHIP_REVISION_1_0 0x10 #define IMX_CHIP_REVISION_1_1 0x11 @@ -150,6 +152,15 @@ extern unsigned int __mxc_cpu_type; #endif #ifndef __ASSEMBLY__ +static inline bool cpu_is_imx6dl(void) +{ + return __mxc_cpu_type == MXC_CPU_IMX6DL; +} + +static inline bool cpu_is_imx6q(void) +{ + return __mxc_cpu_type == MXC_CPU_IMX6Q; +} struct cpu_op { u32 cpu_rate; diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index 77e9a25ed0f6..4a69305db65e 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c @@ -68,8 +68,8 @@ static void __init imx_smp_init_cpus(void) ncores = scu_get_core_count(scu_base); - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); + for (i = ncores; i < NR_CPUS; i++) + set_cpu_possible(i, false); } void imx_smp_prepare(void) diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c index 5faba7a3c95f..204942749e21 100644 --- a/arch/arm/mach-imx/pm-imx6q.c +++ b/arch/arm/mach-imx/pm-imx6q.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011-2013 Freescale Semiconductor, Inc. * Copyright 2011 Linaro Ltd. * * The code contained herein is licensed under the GNU General Public @@ -34,10 +34,12 @@ static int imx6q_pm_enter(suspend_state_t state) case PM_SUSPEND_MEM: imx6q_set_lpm(STOP_POWER_OFF); imx_gpc_pre_suspend(); + imx_anatop_pre_suspend(); imx_set_cpu_jump(0, v7_cpu_resume); /* Zzz ... */ cpu_suspend(0, imx6q_suspend_finish); imx_smp_prepare(); + imx_anatop_post_resume(); imx_gpc_post_resume(); imx6q_set_lpm(WAIT_CLOCKED); break; diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c index 97d086889481..10a6b1a8c5ac 100644 --- a/arch/arm/mach-imx/src.c +++ b/arch/arm/mach-imx/src.c @@ -14,6 +14,7 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/reset-controller.h> #include <linux/smp.h> #include <asm/smp_plat.h> #include "common.h" @@ -21,10 +22,65 @@ #define SRC_SCR 0x000 #define SRC_GPR1 0x020 #define BP_SRC_SCR_WARM_RESET_ENABLE 0 +#define BP_SRC_SCR_SW_GPU_RST 1 +#define BP_SRC_SCR_SW_VPU_RST 2 +#define BP_SRC_SCR_SW_IPU1_RST 3 +#define BP_SRC_SCR_SW_OPEN_VG_RST 4 +#define BP_SRC_SCR_SW_IPU2_RST 12 #define BP_SRC_SCR_CORE1_RST 14 #define BP_SRC_SCR_CORE1_ENABLE 22 static void __iomem *src_base; +static DEFINE_SPINLOCK(scr_lock); + +static const int sw_reset_bits[5] = { + BP_SRC_SCR_SW_GPU_RST, + BP_SRC_SCR_SW_VPU_RST, + BP_SRC_SCR_SW_IPU1_RST, + BP_SRC_SCR_SW_OPEN_VG_RST, + BP_SRC_SCR_SW_IPU2_RST +}; + +static int imx_src_reset_module(struct reset_controller_dev *rcdev, + unsigned long sw_reset_idx) +{ + unsigned long timeout; + unsigned long flags; + int bit; + u32 val; + + if (!src_base) + return -ENODEV; + + if (sw_reset_idx >= ARRAY_SIZE(sw_reset_bits)) + return -EINVAL; + + bit = 1 << sw_reset_bits[sw_reset_idx]; + + spin_lock_irqsave(&scr_lock, flags); + val = readl_relaxed(src_base + SRC_SCR); + val |= bit; + writel_relaxed(val, src_base + SRC_SCR); + spin_unlock_irqrestore(&scr_lock, flags); + + timeout = jiffies + msecs_to_jiffies(1000); + while (readl(src_base + SRC_SCR) & bit) { + if (time_after(jiffies, timeout)) + return -ETIME; + cpu_relax(); + } + + return 0; +} + +static struct reset_control_ops imx_src_ops = { + .reset = imx_src_reset_module, +}; + +static struct reset_controller_dev imx_reset_controller = { + .ops = &imx_src_ops, + .nr_resets = ARRAY_SIZE(sw_reset_bits), +}; void imx_enable_cpu(int cpu, bool enable) { @@ -32,9 +88,11 @@ void imx_enable_cpu(int cpu, bool enable) cpu = cpu_logical_map(cpu); mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1); + spin_lock(&scr_lock); val = readl_relaxed(src_base + SRC_SCR); val = enable ? val | mask : val & ~mask; writel_relaxed(val, src_base + SRC_SCR); + spin_unlock(&scr_lock); } void imx_set_cpu_jump(int cpu, void *jump_addr) @@ -61,9 +119,11 @@ void imx_src_prepare_restart(void) u32 val; /* clear enable bits of secondary cores */ + spin_lock(&scr_lock); val = readl_relaxed(src_base + SRC_SCR); val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE); writel_relaxed(val, src_base + SRC_SCR); + spin_unlock(&scr_lock); /* clear persistent entry register of primary core */ writel_relaxed(0, src_base + SRC_GPR1); @@ -80,11 +140,17 @@ void __init imx_src_init(void) src_base = of_iomap(np, 0); WARN_ON(!src_base); + imx_reset_controller.of_node = np; + if (IS_ENABLED(CONFIG_RESET_CONTROLLER)) + reset_controller_register(&imx_reset_controller); + /* * force warm reset sources to generate cold reset * for a more reliable restart */ + spin_lock(&scr_lock); val = readl_relaxed(src_base + SRC_SCR); val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE); writel_relaxed(val, src_base + SRC_SCR); + spin_unlock(&scr_lock); } diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index cdbca328a412..e1f3735d3415 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o irq.o pcie.o mpp.o +obj-y += common.o irq.o pcie.o mpp.o obj-$(CONFIG_MACH_D2NET_V2) += d2net_v2-setup.o lacie_v2-common.o obj-$(CONFIG_MACH_DB88F6281_BP) += db88f6281-bp-setup.o diff --git a/arch/arm/mach-kirkwood/addr-map.c b/arch/arm/mach-kirkwood/addr-map.c deleted file mode 100644 index 8f0d162a1e1d..000000000000 --- a/arch/arm/mach-kirkwood/addr-map.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * arch/arm/mach-kirkwood/addr-map.c - * - * Address map functions for Marvell Kirkwood SoCs - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <mach/hardware.h> -#include <plat/addr-map.h> -#include "common.h" - -/* - * Generic Address Decode Windows bit settings - */ -#define TARGET_DEV_BUS 1 -#define TARGET_SRAM 3 -#define TARGET_PCIE 4 -#define ATTR_DEV_SPI_ROM 0x1e -#define ATTR_DEV_BOOT 0x1d -#define ATTR_DEV_NAND 0x2f -#define ATTR_DEV_CS3 0x37 -#define ATTR_DEV_CS2 0x3b -#define ATTR_DEV_CS1 0x3d -#define ATTR_DEV_CS0 0x3e -#define ATTR_PCIE_IO 0xe0 -#define ATTR_PCIE_MEM 0xe8 -#define ATTR_PCIE1_IO 0xd0 -#define ATTR_PCIE1_MEM 0xd8 -#define ATTR_SRAM 0x01 - -/* - * Description of the windows needed by the platform code - */ -static struct __initdata orion_addr_map_cfg addr_map_cfg = { - .num_wins = 8, - .remappable_wins = 4, - .bridge_virt_base = BRIDGE_VIRT_BASE, -}; - -static const struct __initdata orion_addr_map_info addr_map_info[] = { - /* - * Windows for PCIe IO+MEM space. - */ - { 0, KIRKWOOD_PCIE_IO_PHYS_BASE, KIRKWOOD_PCIE_IO_SIZE, - TARGET_PCIE, ATTR_PCIE_IO, KIRKWOOD_PCIE_IO_BUS_BASE - }, - { 1, KIRKWOOD_PCIE_MEM_PHYS_BASE, KIRKWOOD_PCIE_MEM_SIZE, - TARGET_PCIE, ATTR_PCIE_MEM, KIRKWOOD_PCIE_MEM_BUS_BASE - }, - { 2, KIRKWOOD_PCIE1_IO_PHYS_BASE, KIRKWOOD_PCIE1_IO_SIZE, - TARGET_PCIE, ATTR_PCIE1_IO, KIRKWOOD_PCIE1_IO_BUS_BASE - }, - { 3, KIRKWOOD_PCIE1_MEM_PHYS_BASE, KIRKWOOD_PCIE1_MEM_SIZE, - TARGET_PCIE, ATTR_PCIE1_MEM, KIRKWOOD_PCIE1_MEM_BUS_BASE - }, - /* - * Window for NAND controller. - */ - { 4, KIRKWOOD_NAND_MEM_PHYS_BASE, KIRKWOOD_NAND_MEM_SIZE, - TARGET_DEV_BUS, ATTR_DEV_NAND, -1 - }, - /* - * Window for SRAM. - */ - { 5, KIRKWOOD_SRAM_PHYS_BASE, KIRKWOOD_SRAM_SIZE, - TARGET_SRAM, ATTR_SRAM, -1 - }, - /* End marker */ - { -1, 0, 0, 0, 0, 0 } -}; - -void __init kirkwood_setup_cpu_mbus(void) -{ - /* - * Disable, clear and configure windows. - */ - orion_config_wins(&addr_map_cfg, addr_map_info); - - /* - * Setup MBUS dram target info. - */ - orion_setup_cpu_mbus_target(&addr_map_cfg, - (void __iomem *) DDR_WINDOW_CPU_BASE); -} diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c index 7904758e771f..e9647b80cb59 100644 --- a/arch/arm/mach-kirkwood/board-dt.c +++ b/arch/arm/mach-kirkwood/board-dt.c @@ -93,7 +93,7 @@ static void __init kirkwood_dt_init(void) */ writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG); - kirkwood_setup_cpu_mbus(); + kirkwood_setup_wins(); kirkwood_l2_init(); diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index 49792a0cd2d3..c2cae69e6d2b 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -33,7 +33,6 @@ #include <linux/platform_data/usb-ehci-orion.h> #include <plat/common.h> #include <plat/time.h> -#include <plat/addr-map.h> #include <linux/platform_data/dma-mv_xor.h> #include "common.h" @@ -535,6 +534,9 @@ void __init kirkwood_init_early(void) * the allocations won't fail. */ init_dma_coherent_pool_size(SZ_1M); + mvebu_mbus_init("marvell,kirkwood-mbus", + BRIDGE_WINS_BASE, BRIDGE_WINS_SZ, + DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ); } int kirkwood_tclk; @@ -650,6 +652,38 @@ char * __init kirkwood_id(void) } } +void __init kirkwood_setup_wins(void) +{ + /* + * The PCIe windows will no longer be statically allocated + * here once Kirkwood is migrated to the pci-mvebu driver. + */ + mvebu_mbus_add_window_remap_flags("pcie0.0", + KIRKWOOD_PCIE_IO_PHYS_BASE, + KIRKWOOD_PCIE_IO_SIZE, + KIRKWOOD_PCIE_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pcie0.0", + KIRKWOOD_PCIE_MEM_PHYS_BASE, + KIRKWOOD_PCIE_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window_remap_flags("pcie1.0", + KIRKWOOD_PCIE1_IO_PHYS_BASE, + KIRKWOOD_PCIE1_IO_SIZE, + KIRKWOOD_PCIE1_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pcie1.0", + KIRKWOOD_PCIE1_MEM_PHYS_BASE, + KIRKWOOD_PCIE1_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window("nand", KIRKWOOD_NAND_MEM_PHYS_BASE, + KIRKWOOD_NAND_MEM_SIZE); + mvebu_mbus_add_window("sram", KIRKWOOD_SRAM_PHYS_BASE, + KIRKWOOD_SRAM_SIZE); +} + void __init kirkwood_l2_init(void) { #ifdef CONFIG_CACHE_FEROCEON_L2 @@ -675,7 +709,7 @@ void __init kirkwood_init(void) */ writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG); - kirkwood_setup_cpu_mbus(); + kirkwood_setup_wins(); kirkwood_l2_init(); diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h index 3147be2f34da..21da3b1ebd7b 100644 --- a/arch/arm/mach-kirkwood/common.h +++ b/arch/arm/mach-kirkwood/common.h @@ -30,7 +30,7 @@ void kirkwood_init(void); void kirkwood_init_early(void); void kirkwood_init_irq(void); -void kirkwood_setup_cpu_mbus(void); +void kirkwood_setup_wins(void); void kirkwood_enable_pcie(void); void kirkwood_pcie_id(u32 *dev, u32 *rev); diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index a05563a31c95..92976cef3910 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -60,8 +60,9 @@ * Register Map */ #define DDR_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x00000) -#define DDR_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x00000) -#define DDR_WINDOW_CPU_BASE (DDR_VIRT_BASE + 0x1500) +#define DDR_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x00000) +#define DDR_WINDOW_CPU_BASE (DDR_PHYS_BASE + 0x1500) +#define DDR_WINDOW_CPU_SZ (0x20) #define DDR_OPERATION_BASE (DDR_PHYS_BASE + 0x1418) #define DEV_BUS_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x10000) @@ -80,6 +81,8 @@ #define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x20000) #define BRIDGE_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x20000) +#define BRIDGE_WINS_BASE (BRIDGE_PHYS_BASE) +#define BRIDGE_WINS_SZ (0x80) #define CRYPTO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x30000) diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c index d96ad4c09972..7f43e6c2f8c0 100644 --- a/arch/arm/mach-kirkwood/pcie.c +++ b/arch/arm/mach-kirkwood/pcie.c @@ -17,7 +17,6 @@ #include <asm/mach/pci.h> #include <plat/pcie.h> #include <mach/bridge-regs.h> -#include <plat/addr-map.h> #include "common.h" static void kirkwood_enable_pcie_clk(const char *port) diff --git a/arch/arm/mach-mv78xx0/Makefile b/arch/arm/mach-mv78xx0/Makefile index 67a13f9bfe64..7cd04634d302 100644 --- a/arch/arm/mach-mv78xx0/Makefile +++ b/arch/arm/mach-mv78xx0/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o mpp.o irq.o pcie.o +obj-y += common.o mpp.o irq.o pcie.o obj-$(CONFIG_MACH_DB78X00_BP) += db78x00-bp-setup.o obj-$(CONFIG_MACH_RD78X00_MASA) += rd78x00-masa-setup.o obj-$(CONFIG_MACH_TERASTATION_WXL) += buffalo-wxl-setup.o diff --git a/arch/arm/mach-mv78xx0/addr-map.c b/arch/arm/mach-mv78xx0/addr-map.c deleted file mode 100644 index 26e9876b50e9..000000000000 --- a/arch/arm/mach-mv78xx0/addr-map.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * arch/arm/mach-mv78xx0/addr-map.c - * - * Address map functions for Marvell MV78xx0 SoCs - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <plat/addr-map.h> -#include <mach/mv78xx0.h> -#include "common.h" - -/* - * Generic Address Decode Windows bit settings - */ -#define TARGET_DEV_BUS 1 -#define TARGET_PCIE0 4 -#define TARGET_PCIE1 8 -#define TARGET_PCIE(i) ((i) ? TARGET_PCIE1 : TARGET_PCIE0) -#define ATTR_DEV_SPI_ROM 0x1f -#define ATTR_DEV_BOOT 0x2f -#define ATTR_DEV_CS3 0x37 -#define ATTR_DEV_CS2 0x3b -#define ATTR_DEV_CS1 0x3d -#define ATTR_DEV_CS0 0x3e -#define ATTR_PCIE_IO(l) (0xf0 & ~(0x10 << (l))) -#define ATTR_PCIE_MEM(l) (0xf8 & ~(0x10 << (l))) - -/* - * CPU Address Decode Windows registers - */ -#define WIN0_OFF(n) (BRIDGE_VIRT_BASE + 0x0000 + ((n) << 4)) -#define WIN8_OFF(n) (BRIDGE_VIRT_BASE + 0x0900 + (((n) - 8) << 4)) - -static void __init __iomem *win_cfg_base(const struct orion_addr_map_cfg *cfg, int win) -{ - /* - * Find the control register base address for this window. - * - * BRIDGE_VIRT_BASE points to the right (CPU0's or CPU1's) - * MBUS bridge depending on which CPU core we're running on, - * so we don't need to take that into account here. - */ - - return (win < 8) ? WIN0_OFF(win) : WIN8_OFF(win); -} - -/* - * Description of the windows needed by the platform code - */ -static struct orion_addr_map_cfg addr_map_cfg __initdata = { - .num_wins = 14, - .remappable_wins = 8, - .win_cfg_base = win_cfg_base, -}; - -void __init mv78xx0_setup_cpu_mbus(void) -{ - /* - * Disable, clear and configure windows. - */ - orion_config_wins(&addr_map_cfg, NULL); - - /* - * Setup MBUS dram target info. - */ - if (mv78xx0_core_index() == 0) - orion_setup_cpu_mbus_target(&addr_map_cfg, - (void __iomem *) DDR_WINDOW_CPU0_BASE); - else - orion_setup_cpu_mbus_target(&addr_map_cfg, - (void __iomem *) DDR_WINDOW_CPU1_BASE); -} - -void __init mv78xx0_setup_pcie_io_win(int window, u32 base, u32 size, - int maj, int min) -{ - orion_setup_cpu_win(&addr_map_cfg, window, base, size, - TARGET_PCIE(maj), ATTR_PCIE_IO(min), 0); -} - -void __init mv78xx0_setup_pcie_mem_win(int window, u32 base, u32 size, - int maj, int min) -{ - orion_setup_cpu_win(&addr_map_cfg, window, base, size, - TARGET_PCIE(maj), ATTR_PCIE_MEM(min), -1); -} diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c index 0efa14498ebc..749a7f8c4992 100644 --- a/arch/arm/mach-mv78xx0/common.c +++ b/arch/arm/mach-mv78xx0/common.c @@ -334,6 +334,14 @@ void __init mv78xx0_uart3_init(void) void __init mv78xx0_init_early(void) { orion_time_set_base(TIMER_VIRT_BASE); + if (mv78xx0_core_index() == 0) + mvebu_mbus_init("marvell,mv78xx0-mbus", + BRIDGE_WINS_CPU0_BASE, BRIDGE_WINS_SZ, + DDR_WINDOW_CPU0_BASE, DDR_WINDOW_CPU_SZ); + else + mvebu_mbus_init("marvell,mv78xx0-mbus", + BRIDGE_WINS_CPU1_BASE, BRIDGE_WINS_SZ, + DDR_WINDOW_CPU1_BASE, DDR_WINDOW_CPU_SZ); } void __init_refok mv78xx0_timer_init(void) @@ -397,8 +405,6 @@ void __init mv78xx0_init(void) printk("HCLK = %dMHz, ", (hclk + 499999) / 1000000); printk("TCLK = %dMHz\n", (get_tclk() + 499999) / 1000000); - mv78xx0_setup_cpu_mbus(); - #ifdef CONFIG_CACHE_FEROCEON_L2 feroceon_l2_init(is_l2_writethrough()); #endif diff --git a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h index 46200a183cf2..723748d8ba7d 100644 --- a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h +++ b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h @@ -60,13 +60,18 @@ */ #define BRIDGE_VIRT_BASE (MV78XX0_CORE_REGS_VIRT_BASE) #define BRIDGE_PHYS_BASE (MV78XX0_CORE_REGS_PHYS_BASE) +#define BRIDGE_WINS_CPU0_BASE (MV78XX0_CORE0_REGS_PHYS_BASE) +#define BRIDGE_WINS_CPU1_BASE (MV78XX0_CORE1_REGS_PHYS_BASE) +#define BRIDGE_WINS_SZ (0xA000) /* * Register Map */ #define DDR_VIRT_BASE (MV78XX0_REGS_VIRT_BASE + 0x00000) -#define DDR_WINDOW_CPU0_BASE (DDR_VIRT_BASE + 0x1500) -#define DDR_WINDOW_CPU1_BASE (DDR_VIRT_BASE + 0x1570) +#define DDR_PHYS_BASE (MV78XX0_REGS_PHYS_BASE + 0x00000) +#define DDR_WINDOW_CPU0_BASE (DDR_PHYS_BASE + 0x1500) +#define DDR_WINDOW_CPU1_BASE (DDR_PHYS_BASE + 0x1570) +#define DDR_WINDOW_CPU_SZ (0x20) #define DEV_BUS_PHYS_BASE (MV78XX0_REGS_PHYS_BASE + 0x10000) #define DEV_BUS_VIRT_BASE (MV78XX0_REGS_VIRT_BASE + 0x10000) diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c index ee8c0b51df2c..dc26a654c496 100644 --- a/arch/arm/mach-mv78xx0/pcie.c +++ b/arch/arm/mach-mv78xx0/pcie.c @@ -10,11 +10,11 @@ #include <linux/kernel.h> #include <linux/pci.h> +#include <linux/mbus.h> #include <video/vga.h> #include <asm/irq.h> #include <asm/mach/pci.h> #include <plat/pcie.h> -#include <plat/addr-map.h> #include <mach/mv78xx0.h> #include "common.h" @@ -54,7 +54,6 @@ static void __init mv78xx0_pcie_preinit(void) int i; u32 size_each; u32 start; - int win = 0; pcie_io_space.name = "PCIe I/O Space"; pcie_io_space.start = MV78XX0_PCIE_IO_PHYS_BASE(0); @@ -72,6 +71,7 @@ static void __init mv78xx0_pcie_preinit(void) start = MV78XX0_PCIE_MEM_PHYS_BASE; for (i = 0; i < num_pcie_ports; i++) { struct pcie_port *pp = pcie_port + i; + char winname[MVEBU_MBUS_MAX_WINNAME_SZ]; snprintf(pp->mem_space_name, sizeof(pp->mem_space_name), "PCIe %d.%d MEM", pp->maj, pp->min); @@ -85,12 +85,17 @@ static void __init mv78xx0_pcie_preinit(void) if (request_resource(&iomem_resource, &pp->res)) panic("can't allocate PCIe MEM sub-space"); - mv78xx0_setup_pcie_mem_win(win + i + 8, pp->res.start, - resource_size(&pp->res), - pp->maj, pp->min); - - mv78xx0_setup_pcie_io_win(win + i, i * SZ_64K, SZ_64K, - pp->maj, pp->min); + snprintf(winname, sizeof(winname), "pcie%d.%d", + pp->maj, pp->min); + + mvebu_mbus_add_window_remap_flags(winname, + pp->res.start, + resource_size(&pp->res), + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window_remap_flags(winname, + i * SZ_64K, SZ_64K, + 0, MVEBU_MBUS_PCI_IO); } } diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 440b13ef1fed..e11acbb0a46d 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -13,6 +13,8 @@ config ARCH_MVEBU select MVEBU_CLK_CORE select MVEBU_CLK_CPU select MVEBU_CLK_GATING + select MVEBU_MBUS + select ZONE_DMA if ARM_LPAE if ARCH_MVEBU diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index da93bcbc74c1..ba769e082ad4 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -5,6 +5,6 @@ AFLAGS_coherency_ll.o := -Wa,-march=armv7-a obj-y += system-controller.o obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o -obj-$(CONFIG_ARCH_MVEBU) += addr-map.o coherency.o coherency_ll.o pmsu.o irq-armada-370-xp.o +obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o irq-armada-370-xp.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-mvebu/addr-map.c b/arch/arm/mach-mvebu/addr-map.c deleted file mode 100644 index ab9b3bd4fef5..000000000000 --- a/arch/arm/mach-mvebu/addr-map.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Address map functions for Marvell 370 / XP SoCs - * - * Copyright (C) 2012 Marvell - * - * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <plat/addr-map.h> - -/* - * Generic Address Decode Windows bit settings - */ -#define ARMADA_XP_TARGET_DEV_BUS 1 -#define ARMADA_XP_ATTR_DEV_BOOTROM 0x1D -#define ARMADA_XP_TARGET_ETH1 3 -#define ARMADA_XP_TARGET_PCIE_0_2 4 -#define ARMADA_XP_TARGET_ETH0 7 -#define ARMADA_XP_TARGET_PCIE_1_3 8 - -#define ARMADA_370_TARGET_DEV_BUS 1 -#define ARMADA_370_ATTR_DEV_BOOTROM 0x1D -#define ARMADA_370_TARGET_PCIE_0 4 -#define ARMADA_370_TARGET_PCIE_1 8 - -#define ARMADA_WINDOW_8_PLUS_OFFSET 0x90 -#define ARMADA_SDRAM_ADDR_DECODING_OFFSET 0x180 - -static const struct __initdata orion_addr_map_info -armada_xp_addr_map_info[] = { - /* - * Window for the BootROM, needed for SMP on Armada XP - */ - { 0, 0xfff00000, SZ_1M, ARMADA_XP_TARGET_DEV_BUS, - ARMADA_XP_ATTR_DEV_BOOTROM, -1 }, - /* End marker */ - { -1, 0, 0, 0, 0, 0 }, -}; - -static const struct __initdata orion_addr_map_info -armada_370_addr_map_info[] = { - /* End marker */ - { -1, 0, 0, 0, 0, 0 }, -}; - -static struct of_device_id of_addr_decoding_controller_table[] = { - { .compatible = "marvell,armada-addr-decoding-controller" }, - { /* end of list */ }, -}; - -static void __iomem * -armada_cfg_base(const struct orion_addr_map_cfg *cfg, int win) -{ - unsigned int offset; - - /* The register layout is a bit annoying and the below code - * tries to cope with it. - * - At offset 0x0, there are the registers for the first 8 - * windows, with 4 registers of 32 bits per window (ctrl, - * base, remap low, remap high) - * - Then at offset 0x80, there is a hole of 0x10 bytes for - * the internal registers base address and internal units - * sync barrier register. - * - Then at offset 0x90, there the registers for 12 - * windows, with only 2 registers of 32 bits per window - * (ctrl, base). - */ - if (win < 8) - offset = (win << 4); - else - offset = ARMADA_WINDOW_8_PLUS_OFFSET + ((win - 8) << 3); - - return cfg->bridge_virt_base + offset; -} - -static struct __initdata orion_addr_map_cfg addr_map_cfg = { - .num_wins = 20, - .remappable_wins = 8, - .win_cfg_base = armada_cfg_base, -}; - -static int __init armada_setup_cpu_mbus(void) -{ - struct device_node *np; - void __iomem *mbus_unit_addr_decoding_base; - void __iomem *sdram_addr_decoding_base; - - np = of_find_matching_node(NULL, of_addr_decoding_controller_table); - if (!np) - return -ENODEV; - - mbus_unit_addr_decoding_base = of_iomap(np, 0); - BUG_ON(!mbus_unit_addr_decoding_base); - - sdram_addr_decoding_base = - mbus_unit_addr_decoding_base + - ARMADA_SDRAM_ADDR_DECODING_OFFSET; - - addr_map_cfg.bridge_virt_base = mbus_unit_addr_decoding_base; - - if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric")) - addr_map_cfg.hw_io_coherency = 1; - - /* - * Disable, clear and configure windows. - */ - if (of_machine_is_compatible("marvell,armadaxp")) - orion_config_wins(&addr_map_cfg, armada_xp_addr_map_info); - else if (of_machine_is_compatible("marvell,armada370")) - orion_config_wins(&addr_map_cfg, armada_370_addr_map_info); - else { - pr_err("Unsupported SoC\n"); - return -EINVAL; - } - - /* - * Setup MBUS dram target info. - */ - orion_setup_cpu_mbus_target(&addr_map_cfg, - sdram_addr_decoding_base); - return 0; -} - -/* Using a early_initcall is needed so that this initialization gets - * done before the SMP initialization, which requires the BootROM to - * be remapped. */ -early_initcall(armada_setup_cpu_mbus); diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c index a5ea616d6d12..12d3655830d1 100644 --- a/arch/arm/mach-mvebu/armada-370-xp.c +++ b/arch/arm/mach-mvebu/armada-370-xp.c @@ -19,6 +19,7 @@ #include <linux/time-armada-370-xp.h> #include <linux/clk/mvebu.h> #include <linux/dma-mapping.h> +#include <linux/mbus.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> @@ -48,12 +49,29 @@ void __init armada_370_xp_timer_and_clk_init(void) void __init armada_370_xp_init_early(void) { + char *mbus_soc_name; + /* * Some Armada 370/XP devices allocate their coherent buffers * from atomic context. Increase size of atomic coherent pool * to make sure such the allocations won't fail. */ init_dma_coherent_pool_size(SZ_1M); + + /* + * This initialization will be replaced by a DT-based + * initialization once the mvebu-mbus driver gains DT support. + */ + if (of_machine_is_compatible("marvell,armada370")) + mbus_soc_name = "marvell,armada370-mbus"; + else + mbus_soc_name = "marvell,armadaxp-mbus"; + + mvebu_mbus_init(mbus_soc_name, + ARMADA_370_XP_MBUS_WINS_BASE, + ARMADA_370_XP_MBUS_WINS_SIZE, + ARMADA_370_XP_SDRAM_WINS_BASE, + ARMADA_370_XP_SDRAM_WINS_SIZE); } static void __init armada_370_xp_dt_init(void) diff --git a/arch/arm/mach-mvebu/armada-370-xp.h b/arch/arm/mach-mvebu/armada-370-xp.h index c6a7d74fddfe..2070e1b4f342 100644 --- a/arch/arm/mach-mvebu/armada-370-xp.h +++ b/arch/arm/mach-mvebu/armada-370-xp.h @@ -16,9 +16,15 @@ #define __MACH_ARMADA_370_XP_H #define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000 -#define ARMADA_370_XP_REGS_VIRT_BASE IOMEM(0xfeb00000) +#define ARMADA_370_XP_REGS_VIRT_BASE IOMEM(0xfec00000) #define ARMADA_370_XP_REGS_SIZE SZ_1M +/* These defines can go away once mvebu-mbus has a DT binding */ +#define ARMADA_370_XP_MBUS_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20000) +#define ARMADA_370_XP_MBUS_WINS_SIZE 0x100 +#define ARMADA_370_XP_SDRAM_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20180) +#define ARMADA_370_XP_SDRAM_WINS_SIZE 0x20 + #ifdef CONFIG_SMP #include <linux/cpumask.h> diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index fe16aaf7c19c..875ea748391c 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -21,6 +21,7 @@ #include <linux/smp.h> #include <linux/clk.h> #include <linux/of.h> +#include <linux/mbus.h> #include <asm/cacheflush.h> #include <asm/smp_plat.h> #include "common.h" @@ -109,6 +110,7 @@ void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) set_secondary_cpus_clock(); flush_cache_all(); set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); + mvebu_mbus_add_window("bootrom", 0xfff00000, SZ_1M); } struct smp_operations armada_xp_smp_ops __initdata = { diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile index 9e809a7c05c0..45da805fb236 100644 --- a/arch/arm/mach-orion5x/Makefile +++ b/arch/arm/mach-orion5x/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o pci.o irq.o mpp.o +obj-y += common.o pci.o irq.o mpp.o obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c deleted file mode 100644 index b5efc0fd31cb..000000000000 --- a/arch/arm/mach-orion5x/addr-map.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * arch/arm/mach-orion5x/addr-map.c - * - * Address map functions for Marvell Orion 5x SoCs - * - * Maintainer: Tzachi Perelstein <tzachi@marvell.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <mach/hardware.h> -#include <plat/addr-map.h> -#include "common.h" - -/* - * The Orion has fully programmable address map. There's a separate address - * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIe, USB, - * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own - * address decode windows that allow it to access any of the Orion resources. - * - * CPU address decoding -- - * Linux assumes that it is the boot loader that already setup the access to - * DDR and internal registers. - * Setup access to PCI and PCIe IO/MEM space is issued by this file. - * Setup access to various devices located on the device bus interface (e.g. - * flashes, RTC, etc) should be issued by machine-setup.c according to - * specific board population (by using orion5x_setup_*_win()). - * - * Non-CPU Masters address decoding -- - * Unlike the CPU, we setup the access from Orion's master interfaces to DDR - * banks only (the typical use case). - * Setup access for each master to DDR is issued by platform device setup. - */ - -/* - * Generic Address Decode Windows bit settings - */ -#define TARGET_DEV_BUS 1 -#define TARGET_PCI 3 -#define TARGET_PCIE 4 -#define TARGET_SRAM 9 -#define ATTR_PCIE_MEM 0x59 -#define ATTR_PCIE_IO 0x51 -#define ATTR_PCIE_WA 0x79 -#define ATTR_PCI_MEM 0x59 -#define ATTR_PCI_IO 0x51 -#define ATTR_DEV_CS0 0x1e -#define ATTR_DEV_CS1 0x1d -#define ATTR_DEV_CS2 0x1b -#define ATTR_DEV_BOOT 0xf -#define ATTR_SRAM 0x0 - -static int __initdata win_alloc_count; - -static int __init cpu_win_can_remap(const struct orion_addr_map_cfg *cfg, - const int win) -{ - u32 dev, rev; - - orion5x_pcie_id(&dev, &rev); - if ((dev == MV88F5281_DEV_ID && win < 4) - || (dev == MV88F5182_DEV_ID && win < 2) - || (dev == MV88F5181_DEV_ID && win < 2) - || (dev == MV88F6183_DEV_ID && win < 4)) - return 1; - - return 0; -} - -/* - * Description of the windows needed by the platform code - */ -static struct orion_addr_map_cfg addr_map_cfg __initdata = { - .num_wins = 8, - .cpu_win_can_remap = cpu_win_can_remap, - .bridge_virt_base = ORION5X_BRIDGE_VIRT_BASE, -}; - -static const struct __initdata orion_addr_map_info addr_map_info[] = { - /* - * Setup windows for PCI+PCIe IO+MEM space. - */ - { 0, ORION5X_PCIE_IO_PHYS_BASE, ORION5X_PCIE_IO_SIZE, - TARGET_PCIE, ATTR_PCIE_IO, ORION5X_PCIE_IO_BUS_BASE - }, - { 1, ORION5X_PCI_IO_PHYS_BASE, ORION5X_PCI_IO_SIZE, - TARGET_PCI, ATTR_PCI_IO, ORION5X_PCI_IO_BUS_BASE - }, - { 2, ORION5X_PCIE_MEM_PHYS_BASE, ORION5X_PCIE_MEM_SIZE, - TARGET_PCIE, ATTR_PCIE_MEM, -1 - }, - { 3, ORION5X_PCI_MEM_PHYS_BASE, ORION5X_PCI_MEM_SIZE, - TARGET_PCI, ATTR_PCI_MEM, -1 - }, - /* End marker */ - { -1, 0, 0, 0, 0, 0 } -}; - -void __init orion5x_setup_cpu_mbus_bridge(void) -{ - /* - * Disable, clear and configure windows. - */ - orion_config_wins(&addr_map_cfg, addr_map_info); - win_alloc_count = 4; - - /* - * Setup MBUS dram target info. - */ - orion_setup_cpu_mbus_target(&addr_map_cfg, - (void __iomem *) ORION5X_DDR_WINDOW_CPU_BASE); -} - -void __init orion5x_setup_dev_boot_win(u32 base, u32 size) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size, - TARGET_DEV_BUS, ATTR_DEV_BOOT, -1); -} - -void __init orion5x_setup_dev0_win(u32 base, u32 size) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size, - TARGET_DEV_BUS, ATTR_DEV_CS0, -1); -} - -void __init orion5x_setup_dev1_win(u32 base, u32 size) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size, - TARGET_DEV_BUS, ATTR_DEV_CS1, -1); -} - -void __init orion5x_setup_dev2_win(u32 base, u32 size) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size, - TARGET_DEV_BUS, ATTR_DEV_CS2, -1); -} - -void __init orion5x_setup_pcie_wa_win(u32 base, u32 size) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size, - TARGET_PCIE, ATTR_PCIE_WA, -1); -} - -void __init orion5x_setup_sram_win(void) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, - ORION5X_SRAM_PHYS_BASE, ORION5X_SRAM_SIZE, - TARGET_SRAM, ATTR_SRAM, -1); -} diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c index 94fbb815680c..b91002ca92f3 100644 --- a/arch/arm/mach-orion5x/board-dt.c +++ b/arch/arm/mach-orion5x/board-dt.c @@ -42,7 +42,7 @@ static void __init orion5x_dt_init(void) /* * Setup Orion address map */ - orion5x_setup_cpu_mbus_bridge(); + orion5x_setup_wins(); /* Setup root of clk tree */ clk_init(); diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 2075bf8e3d90..b97fd672e89d 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -35,7 +35,6 @@ #include <linux/platform_data/usb-ehci-orion.h> #include <plat/time.h> #include <plat/common.h> -#include <plat/addr-map.h> #include "common.h" /***************************************************************************** @@ -175,7 +174,8 @@ void __init orion5x_xor_init(void) ****************************************************************************/ static void __init orion5x_crypto_init(void) { - orion5x_setup_sram_win(); + mvebu_mbus_add_window("sram", ORION5X_SRAM_PHYS_BASE, + ORION5X_SRAM_SIZE); orion_crypto_init(ORION5X_CRYPTO_PHYS_BASE, ORION5X_SRAM_PHYS_BASE, SZ_8K, IRQ_ORION5X_CESA); } @@ -194,6 +194,9 @@ void __init orion5x_wdt_init(void) ****************************************************************************/ void __init orion5x_init_early(void) { + u32 rev, dev; + const char *mbus_soc_name; + orion_time_set_base(TIMER_VIRT_BASE); /* @@ -202,6 +205,46 @@ void __init orion5x_init_early(void) * the allocations won't fail. */ init_dma_coherent_pool_size(SZ_1M); + + /* Initialize the MBUS driver */ + orion5x_pcie_id(&dev, &rev); + if (dev == MV88F5281_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f5281-mbus"; + else if (dev == MV88F5182_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f5182-mbus"; + else if (dev == MV88F5181_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f5181-mbus"; + else if (dev == MV88F6183_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f6183-mbus"; + else + mbus_soc_name = NULL; + mvebu_mbus_init(mbus_soc_name, ORION5X_BRIDGE_WINS_BASE, + ORION5X_BRIDGE_WINS_SZ, + ORION5X_DDR_WINS_BASE, ORION5X_DDR_WINS_SZ); +} + +void orion5x_setup_wins(void) +{ + /* + * The PCIe windows will no longer be statically allocated + * here once Orion5x is migrated to the pci-mvebu driver. + */ + mvebu_mbus_add_window_remap_flags("pcie0.0", ORION5X_PCIE_IO_PHYS_BASE, + ORION5X_PCIE_IO_SIZE, + ORION5X_PCIE_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pcie0.0", ORION5X_PCIE_MEM_PHYS_BASE, + ORION5X_PCIE_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window_remap_flags("pci0.0", ORION5X_PCI_IO_PHYS_BASE, + ORION5X_PCI_IO_SIZE, + ORION5X_PCI_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pci0.0", ORION5X_PCI_MEM_PHYS_BASE, + ORION5X_PCI_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); } int orion5x_tclk; @@ -283,7 +326,7 @@ void __init orion5x_init(void) /* * Setup Orion address map */ - orion5x_setup_cpu_mbus_bridge(); + orion5x_setup_wins(); /* Setup root of clk tree */ clk_init(); diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index e60345760283..cdaa01f3d186 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -17,18 +17,7 @@ void clk_init(void); extern int orion5x_tclk; extern void orion5x_timer_init(void); -/* - * Enumerations and functions for Orion windows mapping. Used by Orion core - * functions to map its interfaces and by the machine-setup to map its on- - * board devices. Details in /mach-orion/addr-map.c - */ -void orion5x_setup_cpu_mbus_bridge(void); -void orion5x_setup_dev_boot_win(u32 base, u32 size); -void orion5x_setup_dev0_win(u32 base, u32 size); -void orion5x_setup_dev1_win(u32 base, u32 size); -void orion5x_setup_dev2_win(u32 base, u32 size); -void orion5x_setup_pcie_wa_win(u32 base, u32 size); -void orion5x_setup_sram_win(void); +void orion5x_setup_wins(void); void orion5x_ehci0_init(void); void orion5x_ehci1_init(void); diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c index 57d0af74874d..16c88bbabc98 100644 --- a/arch/arm/mach-orion5x/d2net-setup.c +++ b/arch/arm/mach-orion5x/d2net-setup.c @@ -317,8 +317,8 @@ static void __init d2net_init(void) d2net_sata_power_init(); orion5x_sata_init(&d2net_sata_data); - orion5x_setup_dev_boot_win(D2NET_NOR_BOOT_BASE, - D2NET_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", D2NET_NOR_BOOT_BASE, + D2NET_NOR_BOOT_SIZE); platform_device_register(&d2net_nor_flash); platform_device_register(&d2net_gpio_buttons); diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c index 76665640087b..4e1263da38bb 100644 --- a/arch/arm/mach-orion5x/db88f5281-setup.c +++ b/arch/arm/mach-orion5x/db88f5281-setup.c @@ -340,16 +340,19 @@ static void __init db88f5281_init(void) orion5x_uart0_init(); orion5x_uart1_init(); - orion5x_setup_dev_boot_win(DB88F5281_NOR_BOOT_BASE, - DB88F5281_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", DB88F5281_NOR_BOOT_BASE, + DB88F5281_NOR_BOOT_SIZE); platform_device_register(&db88f5281_boot_flash); - orion5x_setup_dev0_win(DB88F5281_7SEG_BASE, DB88F5281_7SEG_SIZE); + mvebu_mbus_add_window("devbus-cs0", DB88F5281_7SEG_BASE, + DB88F5281_7SEG_SIZE); - orion5x_setup_dev1_win(DB88F5281_NOR_BASE, DB88F5281_NOR_SIZE); + mvebu_mbus_add_window("devbus-cs1", DB88F5281_NOR_BASE, + DB88F5281_NOR_SIZE); platform_device_register(&db88f5281_nor_flash); - orion5x_setup_dev2_win(DB88F5281_NAND_BASE, DB88F5281_NAND_SIZE); + mvebu_mbus_add_window("devbus-cs2", DB88F5281_NAND_BASE, + DB88F5281_NAND_SIZE); platform_device_register(&db88f5281_nand_flash); i2c_register_board_info(0, &db88f5281_i2c_rtc, 1); diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index 6eb1732757fd..9e6baf581ed3 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -611,7 +611,8 @@ static void __init dns323_init(void) /* setup flash mapping * CS3 holds a 8 MB Spansion S29GL064M90TFIR4 */ - orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", DNS323_NOR_BOOT_BASE, + DNS323_NOR_BOOT_SIZE); platform_device_register(&dns323_nor_flash); /* Sort out LEDs, Buttons and i2c devices */ diff --git a/arch/arm/mach-orion5x/edmini_v2-setup.c b/arch/arm/mach-orion5x/edmini_v2-setup.c index d675e727803d..147615510dd0 100644 --- a/arch/arm/mach-orion5x/edmini_v2-setup.c +++ b/arch/arm/mach-orion5x/edmini_v2-setup.c @@ -154,8 +154,8 @@ void __init edmini_v2_init(void) orion5x_ehci0_init(); orion5x_eth_init(&edmini_v2_eth_data); - orion5x_setup_dev_boot_win(EDMINI_V2_NOR_BOOT_BASE, - EDMINI_V2_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", EDMINI_V2_NOR_BOOT_BASE, + EDMINI_V2_NOR_BOOT_SIZE); platform_device_register(&edmini_v2_nor_flash); pr_notice("edmini_v2: USB device port, flash write and power-off " diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h index d265f5484a8e..b78ff3248868 100644 --- a/arch/arm/mach-orion5x/include/mach/orion5x.h +++ b/arch/arm/mach-orion5x/include/mach/orion5x.h @@ -66,8 +66,10 @@ * Orion Registers Map ******************************************************************************/ +#define ORION5X_DDR_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x00000) +#define ORION5X_DDR_WINS_BASE (ORION5X_DDR_PHYS_BASE + 0x1500) +#define ORION5X_DDR_WINS_SZ (0x10) #define ORION5X_DDR_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x00000) -#define ORION5X_DDR_WINDOW_CPU_BASE (ORION5X_DDR_VIRT_BASE + 0x1500) #define ORION5X_DEV_BUS_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x10000) #define ORION5X_DEV_BUS_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x10000) #define ORION5X_DEV_BUS_REG(x) (ORION5X_DEV_BUS_VIRT_BASE + (x)) @@ -81,6 +83,8 @@ #define ORION5X_BRIDGE_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x20000) #define ORION5X_BRIDGE_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x20000) +#define ORION5X_BRIDGE_WINS_BASE (ORION5X_BRIDGE_PHYS_BASE) +#define ORION5X_BRIDGE_WINS_SZ (0x80) #define ORION5X_PCI_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x30000) diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c index b98403526218..aae10e4a917c 100644 --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -359,13 +359,13 @@ static void __init kurobox_pro_init(void) orion5x_uart1_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(KUROBOX_PRO_NOR_BOOT_BASE, - KUROBOX_PRO_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", KUROBOX_PRO_NOR_BOOT_BASE, + KUROBOX_PRO_NOR_BOOT_SIZE); platform_device_register(&kurobox_pro_nor_flash); if (machine_is_kurobox_pro()) { - orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE, - KUROBOX_PRO_NAND_SIZE); + mvebu_mbus_add_window("devbus-cs0", KUROBOX_PRO_NAND_BASE, + KUROBOX_PRO_NAND_SIZE); platform_device_register(&kurobox_pro_nand_flash); } diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c index 044da5b6a6ae..24f4e14e5893 100644 --- a/arch/arm/mach-orion5x/ls-chl-setup.c +++ b/arch/arm/mach-orion5x/ls-chl-setup.c @@ -294,8 +294,8 @@ static void __init lschl_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(LSCHL_NOR_BOOT_BASE, - LSCHL_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", LSCHL_NOR_BOOT_BASE, + LSCHL_NOR_BOOT_SIZE); platform_device_register(&lschl_nor_flash); platform_device_register(&lschl_leds); diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c index d49f93423f52..fc653bb41e78 100644 --- a/arch/arm/mach-orion5x/ls_hgl-setup.c +++ b/arch/arm/mach-orion5x/ls_hgl-setup.c @@ -243,8 +243,8 @@ static void __init ls_hgl_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(LS_HGL_NOR_BOOT_BASE, - LS_HGL_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", LS_HGL_NOR_BOOT_BASE, + LS_HGL_NOR_BOOT_SIZE); platform_device_register(&ls_hgl_nor_flash); platform_device_register(&ls_hgl_button_device); diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c index 8e3965c6c0fe..18e66e617dc2 100644 --- a/arch/arm/mach-orion5x/lsmini-setup.c +++ b/arch/arm/mach-orion5x/lsmini-setup.c @@ -244,8 +244,8 @@ static void __init lsmini_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(LSMINI_NOR_BOOT_BASE, - LSMINI_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", LSMINI_NOR_BOOT_BASE, + LSMINI_NOR_BOOT_SIZE); platform_device_register(&lsmini_nor_flash); platform_device_register(&lsmini_button_device); diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c index 0ec94a1f2b16..827acbafc9dc 100644 --- a/arch/arm/mach-orion5x/mss2-setup.c +++ b/arch/arm/mach-orion5x/mss2-setup.c @@ -241,7 +241,8 @@ static void __init mss2_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(MSS2_NOR_BOOT_BASE, MSS2_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", MSS2_NOR_BOOT_BASE, + MSS2_NOR_BOOT_SIZE); platform_device_register(&mss2_nor_flash); platform_device_register(&mss2_button_device); diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c index 18143f2a9093..92600ae2b4b6 100644 --- a/arch/arm/mach-orion5x/mv2120-setup.c +++ b/arch/arm/mach-orion5x/mv2120-setup.c @@ -204,7 +204,8 @@ static void __init mv2120_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(MV2120_NOR_BOOT_BASE, MV2120_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", MV2120_NOR_BOOT_BASE, + MV2120_NOR_BOOT_SIZE); platform_device_register(&mv2120_nor_flash); platform_device_register(&mv2120_button_device); diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c index 282e503b003e..dd0641a0d074 100644 --- a/arch/arm/mach-orion5x/net2big-setup.c +++ b/arch/arm/mach-orion5x/net2big-setup.c @@ -397,8 +397,8 @@ static void __init net2big_init(void) net2big_sata_power_init(); orion5x_sata_init(&net2big_sata_data); - orion5x_setup_dev_boot_win(NET2BIG_NOR_BOOT_BASE, - NET2BIG_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", NET2BIG_NOR_BOOT_BASE, + NET2BIG_NOR_BOOT_SIZE); platform_device_register(&net2big_nor_flash); platform_device_register(&net2big_gpio_buttons); diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c index 973db98a3c27..503368023bb1 100644 --- a/arch/arm/mach-orion5x/pci.c +++ b/arch/arm/mach-orion5x/pci.c @@ -157,8 +157,11 @@ static int __init pcie_setup(struct pci_sys_data *sys) if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) { printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config " "read transaction workaround\n"); - orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE, - ORION5X_PCIE_WA_SIZE); + mvebu_mbus_add_window_remap_flags("pcie0.0", + ORION5X_PCIE_WA_PHYS_BASE, + ORION5X_PCIE_WA_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_WA); pcie_ops.read = pcie_rd_conf_wa; } diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c index d6e72f672afb..1c4498bf650a 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c @@ -123,8 +123,8 @@ static void __init rd88f5181l_fxo_init(void) orion5x_eth_switch_init(&rd88f5181l_fxo_switch_plat_data, NO_IRQ); orion5x_uart0_init(); - orion5x_setup_dev_boot_win(RD88F5181L_FXO_NOR_BOOT_BASE, - RD88F5181L_FXO_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", RD88F5181L_FXO_NOR_BOOT_BASE, + RD88F5181L_FXO_NOR_BOOT_SIZE); platform_device_register(&rd88f5181l_fxo_nor_boot_flash); } diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c index c8b7913310e5..adabe34c4fc6 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c @@ -130,8 +130,8 @@ static void __init rd88f5181l_ge_init(void) orion5x_i2c_init(); orion5x_uart0_init(); - orion5x_setup_dev_boot_win(RD88F5181L_GE_NOR_BOOT_BASE, - RD88F5181L_GE_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", RD88F5181L_GE_NOR_BOOT_BASE, + RD88F5181L_GE_NOR_BOOT_SIZE); platform_device_register(&rd88f5181l_ge_nor_boot_flash); i2c_register_board_info(0, &rd88f5181l_ge_i2c_rtc, 1); diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c index f9e156725d7c..66e77ec91532 100644 --- a/arch/arm/mach-orion5x/rd88f5182-setup.c +++ b/arch/arm/mach-orion5x/rd88f5182-setup.c @@ -264,10 +264,11 @@ static void __init rd88f5182_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(RD88F5182_NOR_BOOT_BASE, - RD88F5182_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", RD88F5182_NOR_BOOT_BASE, + RD88F5182_NOR_BOOT_SIZE); - orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE); + mvebu_mbus_add_window("devbus-cs1", RD88F5182_NOR_BASE, + RD88F5182_NOR_SIZE); platform_device_register(&rd88f5182_nor_flash); platform_device_register(&rd88f5182_gpio_leds); diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c index acc0877ec1c9..a0bfa53e7556 100644 --- a/arch/arm/mach-orion5x/terastation_pro2-setup.c +++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c @@ -329,8 +329,8 @@ static void __init tsp2_init(void) /* * Configure peripherals. */ - orion5x_setup_dev_boot_win(TSP2_NOR_BOOT_BASE, - TSP2_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", TSP2_NOR_BOOT_BASE, + TSP2_NOR_BOOT_SIZE); platform_device_register(&tsp2_nor_flash); orion5x_ehci0_init(); diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c index 9c17f0c2b488..80174f0f168e 100644 --- a/arch/arm/mach-orion5x/ts209-setup.c +++ b/arch/arm/mach-orion5x/ts209-setup.c @@ -286,8 +286,8 @@ static void __init qnap_ts209_init(void) /* * Configure peripherals. */ - orion5x_setup_dev_boot_win(QNAP_TS209_NOR_BOOT_BASE, - QNAP_TS209_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", QNAP_TS209_NOR_BOOT_BASE, + QNAP_TS209_NOR_BOOT_SIZE); platform_device_register(&qnap_ts209_nor_flash); orion5x_ehci0_init(); diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c index 8cc5ab6c503e..92592790d6da 100644 --- a/arch/arm/mach-orion5x/ts409-setup.c +++ b/arch/arm/mach-orion5x/ts409-setup.c @@ -277,8 +277,8 @@ static void __init qnap_ts409_init(void) /* * Configure peripherals. */ - orion5x_setup_dev_boot_win(QNAP_TS409_NOR_BOOT_BASE, - QNAP_TS409_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", QNAP_TS409_NOR_BOOT_BASE, + QNAP_TS409_NOR_BOOT_SIZE); platform_device_register(&qnap_ts409_nor_flash); orion5x_ehci0_init(); diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c index 66552ca7e05d..6b84863c018d 100644 --- a/arch/arm/mach-orion5x/wnr854t-setup.c +++ b/arch/arm/mach-orion5x/wnr854t-setup.c @@ -127,8 +127,8 @@ static void __init wnr854t_init(void) orion5x_eth_switch_init(&wnr854t_switch_plat_data, NO_IRQ); orion5x_uart0_init(); - orion5x_setup_dev_boot_win(WNR854T_NOR_BOOT_BASE, - WNR854T_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", WNR854T_NOR_BOOT_BASE, + WNR854T_NOR_BOOT_SIZE); platform_device_register(&wnr854t_nor_flash); } diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c index 2c5408e2e689..fae684bc54f2 100644 --- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c +++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c @@ -213,8 +213,8 @@ static void __init wrt350n_v2_init(void) orion5x_eth_switch_init(&wrt350n_v2_switch_plat_data, NO_IRQ); orion5x_uart0_init(); - orion5x_setup_dev_boot_win(WRT350N_V2_NOR_BOOT_BASE, - WRT350N_V2_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", WRT350N_V2_NOR_BOOT_BASE, + WRT350N_V2_NOR_BOOT_SIZE); platform_device_register(&wrt350n_v2_nor_flash); platform_device_register(&wrt350n_v2_leds); platform_device_register(&wrt350n_v2_button_device); diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c index 7d86bfbb5b06..31d5cd4d9787 100644 --- a/arch/arm/mach-shmobile/clock-r8a7779.c +++ b/arch/arm/mach-shmobile/clock-r8a7779.c @@ -26,6 +26,25 @@ #include <mach/clock.h> #include <mach/common.h> +/* + * MD1 = 1 MD1 = 0 + * (PLLA = 1500) (PLLA = 1600) + * (MHz) (MHz) + *------------------------------------------------+-------------------- + * clkz 1000 (2/3) 800 (1/2) + * clkzs 250 (1/6) 200 (1/8) + * clki 750 (1/2) 800 (1/2) + * clks 250 (1/6) 200 (1/8) + * clks1 125 (1/12) 100 (1/16) + * clks3 187.5 (1/8) 200 (1/8) + * clks4 93.7 (1/16) 100 (1/16) + * clkp 62.5 (1/24) 50 (1/32) + * clkg 62.5 (1/24) 66.6 (1/24) + * clkb, CLKOUT + * (MD2 = 0) 62.5 (1/24) 66.6 (1/24) + * (MD2 = 1) 41.6 (1/36) 50 (1/32) +*/ + #define MD(nr) BIT(nr) #define FRQMR IOMEM(0xffc80014) @@ -93,7 +112,7 @@ static struct clk *main_clks[] = { }; enum { MSTP323, MSTP322, MSTP321, MSTP320, - MSTP115, + MSTP115, MSTP114, MSTP103, MSTP101, MSTP100, MSTP030, MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, @@ -107,6 +126,7 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */ [MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */ [MSTP115] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 15, 0), /* SATA */ + [MSTP114] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 14, 0), /* Ether */ [MSTP103] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 3, 0), /* DU */ [MSTP101] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 1, 0), /* USB2 */ [MSTP100] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 0, 0), /* USB0/1 */ @@ -143,6 +163,7 @@ static struct clk_lookup lookups[] = { /* MSTP32 clocks */ CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */ CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */ + CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP114]), /* Ether */ CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */ CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */ CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h index 945299ed1638..188b295938a5 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7779.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h @@ -3,6 +3,7 @@ #include <linux/sh_clk.h> #include <linux/pm_domain.h> +#include <linux/sh_eth.h> struct platform_device; @@ -31,6 +32,7 @@ extern void r8a7779_earlytimer_init(void); extern void r8a7779_add_early_devices(void); extern void r8a7779_add_standard_devices(void); extern void r8a7779_add_standard_devices_dt(void); +extern void r8a7779_add_ether_device(struct sh_eth_plat_data *pdata); extern void r8a7779_clock_init(void); extern void r8a7779_pinmux_init(void); extern void r8a7779_pm_init(void); diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index a460ba3dedcb..b0b394842ea5 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -1,8 +1,9 @@ /* * r8a7779 processor support * - * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2011, 2013 Renesas Solutions Corp. * Copyright (C) 2011 Magnus Damm + * Copyright (C) 2013 Cogent Embedded, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -393,6 +394,18 @@ static struct platform_device sata_device = { }, }; +/* Ether */ +static struct resource ether_resources[] = { + { + .start = 0xfde00000, + .end = 0xfde003ff, + .flags = IORESOURCE_MEM, + }, { + .start = gic_iid(0xb4), + .flags = IORESOURCE_IRQ, + }, +}; + static struct platform_device *r8a7779_devices_dt[] __initdata = { &scif0_device, &scif1_device, @@ -428,6 +441,14 @@ void __init r8a7779_add_standard_devices(void) ARRAY_SIZE(r8a7779_late_devices)); } +void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata) +{ + platform_device_register_resndata(&platform_bus, "sh_eth", -1, + ether_resources, + ARRAY_SIZE(ether_resources), + pdata, sizeof(*pdata)); +} + /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ void __init __weak r8a7779_register_twd(void) { } diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index cf3226b041f5..c1d61f281e68 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -10,6 +10,7 @@ config ARCH_ZYNQ select ICST select MIGHT_HAVE_CACHE_L2X0 select USE_OF + select HAVE_SMP select SPARSE_IRQ select CADENCE_TTC_TIMER help diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile index 320faedeb484..1b25d92ebf22 100644 --- a/arch/arm/mach-zynq/Makefile +++ b/arch/arm/mach-zynq/Makefile @@ -3,4 +3,8 @@ # # Common support -obj-y := common.o +obj-y := common.o slcr.o +CFLAGS_REMOVE_hotplug.o =-march=armv6k +CFLAGS_hotplug.o =-Wa,-march=armv7-a -mcpu=cortex-a9 +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 68e0907de5d0..5bfe7035b73d 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -33,20 +33,23 @@ #include <asm/mach-types.h> #include <asm/page.h> #include <asm/pgtable.h> +#include <asm/smp_scu.h> #include <asm/hardware/cache-l2x0.h> #include "common.h" +void __iomem *zynq_scu_base; + static struct of_device_id zynq_of_bus_ids[] __initdata = { { .compatible = "simple-bus", }, {} }; /** - * xilinx_init_machine() - System specific initialization, intended to be - * called from board specific initialization. + * zynq_init_machine - System specific initialization, intended to be + * called from board specific initialization. */ -static void __init xilinx_init_machine(void) +static void __init zynq_init_machine(void) { /* * 64KB way size, 8-way associativity, parity disabled @@ -56,50 +59,56 @@ static void __init xilinx_init_machine(void) of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL); } -#define SCU_PERIPH_PHYS 0xF8F00000 -#define SCU_PERIPH_SIZE SZ_8K -#define SCU_PERIPH_VIRT (VMALLOC_END - SCU_PERIPH_SIZE) +static void __init zynq_timer_init(void) +{ + zynq_slcr_init(); + clocksource_of_init(); +} -static struct map_desc scu_desc __initdata = { - .virtual = SCU_PERIPH_VIRT, - .pfn = __phys_to_pfn(SCU_PERIPH_PHYS), - .length = SCU_PERIPH_SIZE, - .type = MT_DEVICE, +static struct map_desc zynq_cortex_a9_scu_map __initdata = { + .length = SZ_256, + .type = MT_DEVICE, }; -static void __init xilinx_zynq_timer_init(void) +static void __init zynq_scu_map_io(void) { - struct device_node *np; - void __iomem *slcr; - - np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr"); - slcr = of_iomap(np, 0); - WARN_ON(!slcr); + unsigned long base; - xilinx_zynq_clocks_init(slcr); - - clocksource_of_init(); + base = scu_a9_get_base(); + zynq_cortex_a9_scu_map.pfn = __phys_to_pfn(base); + /* Expected address is in vmalloc area that's why simple assign here */ + zynq_cortex_a9_scu_map.virtual = base; + iotable_init(&zynq_cortex_a9_scu_map, 1); + zynq_scu_base = (void __iomem *)base; + BUG_ON(!zynq_scu_base); } /** - * xilinx_map_io() - Create memory mappings needed for early I/O. + * zynq_map_io - Create memory mappings needed for early I/O. */ -static void __init xilinx_map_io(void) +static void __init zynq_map_io(void) { debug_ll_io_init(); - iotable_init(&scu_desc, 1); + zynq_scu_map_io(); +} + +static void zynq_system_reset(char mode, const char *cmd) +{ + zynq_slcr_system_reset(); } -static const char *xilinx_dt_match[] = { +static const char * const zynq_dt_match[] = { "xlnx,zynq-zc702", "xlnx,zynq-7000", NULL }; MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") - .map_io = xilinx_map_io, + .smp = smp_ops(zynq_smp_ops), + .map_io = zynq_map_io, .init_irq = irqchip_init, - .init_machine = xilinx_init_machine, - .init_time = xilinx_zynq_timer_init, - .dt_compat = xilinx_dt_match, + .init_machine = zynq_init_machine, + .init_time = zynq_timer_init, + .dt_compat = zynq_dt_match, + .restart = zynq_system_reset, MACHINE_END diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index 5050bb10bb12..fbbd0e21c404 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -17,4 +17,24 @@ #ifndef __MACH_ZYNQ_COMMON_H__ #define __MACH_ZYNQ_COMMON_H__ +extern int zynq_slcr_init(void); +extern void zynq_slcr_system_reset(void); +extern void zynq_slcr_cpu_stop(int cpu); +extern void zynq_slcr_cpu_start(int cpu); + +#ifdef CONFIG_SMP +extern void secondary_startup(void); +extern char zynq_secondary_trampoline; +extern char zynq_secondary_trampoline_jump; +extern char zynq_secondary_trampoline_end; +extern int __cpuinit zynq_cpun_start(u32 address, int cpu); +extern struct smp_operations zynq_smp_ops __initdata; +#endif + +extern void __iomem *zynq_slcr_base; +extern void __iomem *zynq_scu_base; + +/* Hotplug */ +extern void zynq_platform_cpu_die(unsigned int cpu); + #endif diff --git a/arch/arm/mach-zynq/headsmp.S b/arch/arm/mach-zynq/headsmp.S new file mode 100644 index 000000000000..d183cd234a9b --- /dev/null +++ b/arch/arm/mach-zynq/headsmp.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Steffen Trumtrar <s.trumtrar@pengutronix.de> + * Copyright (c) 2012-2013 Xilinx + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/linkage.h> +#include <linux/init.h> + + __CPUINIT + +ENTRY(zynq_secondary_trampoline) + ldr r0, [pc] + bx r0 +.globl zynq_secondary_trampoline_jump +zynq_secondary_trampoline_jump: + /* Space for jumping address */ + .word /* cpu 1 */ +.globl zynq_secondary_trampoline_end +zynq_secondary_trampoline_end: + +ENDPROC(zynq_secondary_trampoline) diff --git a/arch/arm/mach-zynq/hotplug.c b/arch/arm/mach-zynq/hotplug.c new file mode 100644 index 000000000000..c89672bd1de2 --- /dev/null +++ b/arch/arm/mach-zynq/hotplug.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012-2013 Xilinx + * + * based on linux/arch/arm/mach-realview/hotplug.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/smp.h> + +#include <asm/cacheflush.h> +#include <asm/cp15.h> +#include "common.h" + +static inline void zynq_cpu_enter_lowpower(void) +{ + unsigned int v; + + flush_cache_all(); + asm volatile( + " mcr p15, 0, %1, c7, c5, 0\n" + " dsb\n" + /* + * Turn off coherency + */ + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, #0x40\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, %2\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0), "Ir" (CR_C) + : "cc"); +} + +static inline void zynq_cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile( + " mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, #0x40\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : "Ir" (CR_C) + : "cc"); +} + +static inline void zynq_platform_do_lowpower(unsigned int cpu, int *spurious) +{ + /* + * there is no power-control hardware on this platform, so all + * we can do is put the core into WFI; this is safe as the calling + * code will have already disabled interrupts + */ + for (;;) { + dsb(); + wfi(); + + /* + * Getting here, means that we have come out of WFI without + * having been woken up - this shouldn't happen + * + * Just note it happening - when we're woken, we can report + * its occurrence. + */ + (*spurious)++; + } +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void zynq_platform_cpu_die(unsigned int cpu) +{ + int spurious = 0; + + /* + * we're ready for shutdown now, so do it + */ + zynq_cpu_enter_lowpower(); + zynq_platform_do_lowpower(cpu, &spurious); + + /* + * bring this CPU back into the world of cache + * coherency, and then restore interrupts + */ + zynq_cpu_leave_lowpower(); + + if (spurious) + pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); +} diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c new file mode 100644 index 000000000000..5fc167e07619 --- /dev/null +++ b/arch/arm/mach-zynq/platsmp.c @@ -0,0 +1,136 @@ +/* + * This file contains Xilinx specific SMP code, used to start up + * the second processor. + * + * Copyright (C) 2011-2013 Xilinx + * + * based on linux/arch/arm/mach-realview/platsmp.c + * + * Copyright (C) 2002 ARM Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/export.h> +#include <linux/jiffies.h> +#include <linux/init.h> +#include <linux/io.h> +#include <asm/cacheflush.h> +#include <asm/smp_scu.h> +#include <linux/irqchip/arm-gic.h> +#include "common.h" + +/* + * Store number of cores in the system + * Because of scu_get_core_count() must be in __init section and can't + * be called from zynq_cpun_start() because it is in __cpuinit section. + */ +static int ncores; + +int __cpuinit zynq_cpun_start(u32 address, int cpu) +{ + u32 trampoline_code_size = &zynq_secondary_trampoline_end - + &zynq_secondary_trampoline; + + if (cpu > ncores) { + pr_warn("CPU No. is not available in the system\n"); + return -1; + } + + /* MS: Expectation that SLCR are directly map and accessible */ + /* Not possible to jump to non aligned address */ + if (!(address & 3) && (!address || (address >= trampoline_code_size))) { + /* Store pointer to ioremap area which points to address 0x0 */ + static u8 __iomem *zero; + u32 trampoline_size = &zynq_secondary_trampoline_jump - + &zynq_secondary_trampoline; + + zynq_slcr_cpu_stop(cpu); + + if (__pa(PAGE_OFFSET)) { + zero = ioremap(0, trampoline_code_size); + if (!zero) { + pr_warn("BOOTUP jump vectors not accessible\n"); + return -1; + } + } else { + zero = (__force u8 __iomem *)PAGE_OFFSET; + } + + /* + * This is elegant way how to jump to any address + * 0x0: Load address at 0x8 to r0 + * 0x4: Jump by mov instruction + * 0x8: Jumping address + */ + memcpy((__force void *)zero, &zynq_secondary_trampoline, + trampoline_size); + writel(address, zero + trampoline_size); + + flush_cache_all(); + outer_flush_range(0, trampoline_code_size); + smp_wmb(); + + if (__pa(PAGE_OFFSET)) + iounmap(zero); + + zynq_slcr_cpu_start(cpu); + + return 0; + } + + pr_warn("Can't start CPU%d: Wrong starting address %x\n", cpu, address); + + return -1; +} +EXPORT_SYMBOL(zynq_cpun_start); + +static int __cpuinit zynq_boot_secondary(unsigned int cpu, + struct task_struct *idle) +{ + return zynq_cpun_start(virt_to_phys(secondary_startup), cpu); +} + +/* + * Initialise the CPU possible map early - this describes the CPUs + * which may be present or become present in the system. + */ +static void __init zynq_smp_init_cpus(void) +{ + int i; + + ncores = scu_get_core_count(zynq_scu_base); + + for (i = 0; i < ncores && i < CONFIG_NR_CPUS; i++) + set_cpu_possible(i, true); +} + +static void __init zynq_smp_prepare_cpus(unsigned int max_cpus) +{ + int i; + + /* + * Initialise the present map, which describes the set of CPUs + * actually populated at the present time. + */ + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); + + scu_enable(zynq_scu_base); +} + +struct smp_operations zynq_smp_ops __initdata = { + .smp_init_cpus = zynq_smp_init_cpus, + .smp_prepare_cpus = zynq_smp_prepare_cpus, + .smp_boot_secondary = zynq_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = zynq_platform_cpu_die, +#endif +}; diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c new file mode 100644 index 000000000000..c70969b9c258 --- /dev/null +++ b/arch/arm/mach-zynq/slcr.c @@ -0,0 +1,125 @@ +/* + * Xilinx SLCR driver + * + * Copyright (c) 2011-2013 Xilinx Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA + * 02139, USA. + */ + +#include <linux/export.h> +#include <linux/io.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/uaccess.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/clk/zynq.h> +#include "common.h" + +#define SLCR_UNLOCK_MAGIC 0xDF0D +#define SLCR_UNLOCK 0x8 /* SCLR unlock register */ + +#define SLCR_PS_RST_CTRL_OFFSET 0x200 /* PS Software Reset Control */ + +#define SLCR_A9_CPU_CLKSTOP 0x10 +#define SLCR_A9_CPU_RST 0x1 + +#define SLCR_A9_CPU_RST_CTRL 0x244 /* CPU Software Reset Control */ +#define SLCR_REBOOT_STATUS 0x258 /* PS Reboot Status */ + +void __iomem *zynq_slcr_base; + +/** + * zynq_slcr_system_reset - Reset the entire system. + */ +void zynq_slcr_system_reset(void) +{ + u32 reboot; + + /* + * Unlock the SLCR then reset the system. + * Note that this seems to require raw i/o + * functions or there's a lockup? + */ + writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK); + + /* + * Clear 0x0F000000 bits of reboot status register to workaround + * the FSBL not loading the bitstream after soft-reboot + * This is a temporary solution until we know more. + */ + reboot = readl(zynq_slcr_base + SLCR_REBOOT_STATUS); + writel(reboot & 0xF0FFFFFF, zynq_slcr_base + SLCR_REBOOT_STATUS); + writel(1, zynq_slcr_base + SLCR_PS_RST_CTRL_OFFSET); +} + +/** + * zynq_slcr_cpu_start - Start cpu + * @cpu: cpu number + */ +void zynq_slcr_cpu_start(int cpu) +{ + /* enable CPUn */ + writel(SLCR_A9_CPU_CLKSTOP << cpu, + zynq_slcr_base + SLCR_A9_CPU_RST_CTRL); + /* enable CLK for CPUn */ + writel(0x0 << cpu, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL); +} + +/** + * zynq_slcr_cpu_stop - Stop cpu + * @cpu: cpu number + */ +void zynq_slcr_cpu_stop(int cpu) +{ + /* stop CLK and reset CPUn */ + writel((SLCR_A9_CPU_CLKSTOP | SLCR_A9_CPU_RST) << cpu, + zynq_slcr_base + SLCR_A9_CPU_RST_CTRL); +} + +/** + * zynq_slcr_init + * Returns 0 on success, negative errno otherwise. + * + * Called early during boot from platform code to remap SLCR area. + */ +int __init zynq_slcr_init(void) +{ + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr"); + if (!np) { + pr_err("%s: no slcr node found\n", __func__); + BUG(); + } + + zynq_slcr_base = of_iomap(np, 0); + if (!zynq_slcr_base) { + pr_err("%s: Unable to map I/O memory\n", __func__); + BUG(); + } + + /* unlock the SLCR so that registers can be changed */ + writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK); + + pr_info("%s mapped to %p\n", np->name, zynq_slcr_base); + + xilinx_zynq_clocks_init(zynq_slcr_base); + + of_node_put(np); + + return 0; +} diff --git a/arch/arm/plat-orion/Makefile b/arch/arm/plat-orion/Makefile index ad97400ba3ad..2eca54b65906 100644 --- a/arch/arm/plat-orion/Makefile +++ b/arch/arm/plat-orion/Makefile @@ -3,12 +3,6 @@ # ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include -obj-$(CONFIG_ARCH_MVEBU) += addr-map.o -obj-$(CONFIG_ARCH_KIRKWOOD) += addr-map.o -obj-$(CONFIG_ARCH_DOVE) += addr-map.o -obj-$(CONFIG_ARCH_ORION5X) += addr-map.o -obj-$(CONFIG_ARCH_MV78XX0) += addr-map.o - orion-gpio-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_PLAT_ORION_LEGACY) += irq.o pcie.o time.o common.o mpp.o obj-$(CONFIG_PLAT_ORION_LEGACY) += $(orion-gpio-y) diff --git a/arch/arm/plat-orion/addr-map.c b/arch/arm/plat-orion/addr-map.c deleted file mode 100644 index 807ac8e5cbc0..000000000000 --- a/arch/arm/plat-orion/addr-map.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * arch/arm/plat-orion/addr-map.c - * - * Address map functions for Marvell Orion based SoCs - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <plat/addr-map.h> - -struct mbus_dram_target_info orion_mbus_dram_info; - -const struct mbus_dram_target_info *mv_mbus_dram_info(void) -{ - return &orion_mbus_dram_info; -} -EXPORT_SYMBOL_GPL(mv_mbus_dram_info); - -/* - * DDR target is the same on all Orion platforms. - */ -#define TARGET_DDR 0 - -/* - * Helpers to get DDR bank info - */ -#define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3)) -#define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3)) - -/* - * CPU Address Decode Windows registers - */ -#define WIN_CTRL_OFF 0x0000 -#define WIN_BASE_OFF 0x0004 -#define WIN_REMAP_LO_OFF 0x0008 -#define WIN_REMAP_HI_OFF 0x000c - -#define ATTR_HW_COHERENCY (0x1 << 4) - -/* - * Default implementation - */ -static void __init __iomem * -orion_win_cfg_base(const struct orion_addr_map_cfg *cfg, int win) -{ - return cfg->bridge_virt_base + (win << 4); -} - -/* - * Default implementation - */ -static int __init orion_cpu_win_can_remap(const struct orion_addr_map_cfg *cfg, - const int win) -{ - if (win < cfg->remappable_wins) - return 1; - - return 0; -} - -void __init orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg, - const int win, const u32 base, - const u32 size, const u8 target, - const u8 attr, const int remap) -{ - void __iomem *addr = cfg->win_cfg_base(cfg, win); - u32 ctrl, base_high, remap_addr; - - if (win >= cfg->num_wins) { - printk(KERN_ERR "setup_cpu_win: trying to allocate window " - "%d when only %d allowed\n", win, cfg->num_wins); - } - - base_high = base & 0xffff0000; - ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1; - - writel(base_high, addr + WIN_BASE_OFF); - writel(ctrl, addr + WIN_CTRL_OFF); - if (cfg->cpu_win_can_remap(cfg, win)) { - if (remap < 0) - remap_addr = base; - else - remap_addr = remap; - writel(remap_addr & 0xffff0000, addr + WIN_REMAP_LO_OFF); - writel(0, addr + WIN_REMAP_HI_OFF); - } -} - -/* - * Configure a number of windows. - */ -static void __init orion_setup_cpu_wins(const struct orion_addr_map_cfg * cfg, - const struct orion_addr_map_info *info) -{ - while (info->win != -1) { - orion_setup_cpu_win(cfg, info->win, info->base, info->size, - info->target, info->attr, info->remap); - info++; - } -} - -static void __init orion_disable_wins(const struct orion_addr_map_cfg * cfg) -{ - void __iomem *addr; - int i; - - for (i = 0; i < cfg->num_wins; i++) { - addr = cfg->win_cfg_base(cfg, i); - - writel(0, addr + WIN_BASE_OFF); - writel(0, addr + WIN_CTRL_OFF); - if (cfg->cpu_win_can_remap(cfg, i)) { - writel(0, addr + WIN_REMAP_LO_OFF); - writel(0, addr + WIN_REMAP_HI_OFF); - } - } -} - -/* - * Disable, clear and configure windows. - */ -void __init orion_config_wins(struct orion_addr_map_cfg * cfg, - const struct orion_addr_map_info *info) -{ - if (!cfg->cpu_win_can_remap) - cfg->cpu_win_can_remap = orion_cpu_win_can_remap; - - if (!cfg->win_cfg_base) - cfg->win_cfg_base = orion_win_cfg_base; - - orion_disable_wins(cfg); - - if (info) - orion_setup_cpu_wins(cfg, info); -} - -/* - * Setup MBUS dram target info. - */ -void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg, - const void __iomem *ddr_window_cpu_base) -{ - int i; - int cs; - - orion_mbus_dram_info.mbus_dram_target_id = TARGET_DDR; - - for (i = 0, cs = 0; i < 4; i++) { - u32 base = readl(ddr_window_cpu_base + DDR_BASE_CS_OFF(i)); - u32 size = readl(ddr_window_cpu_base + DDR_SIZE_CS_OFF(i)); - - /* - * We only take care of entries for which the chip - * select is enabled, and that don't have high base - * address bits set (devices can only access the first - * 32 bits of the memory). - */ - if ((size & 1) && !(base & 0xF)) { - struct mbus_dram_window *w; - - w = &orion_mbus_dram_info.cs[cs++]; - w->cs_index = i; - w->mbus_attr = 0xf & ~(1 << i); - if (cfg->hw_io_coherency) - w->mbus_attr |= ATTR_HW_COHERENCY; - w->base = base & 0xffff0000; - w->size = (size | 0x0000ffff) + 1; - } - } - orion_mbus_dram_info.num_cs = cs; -} diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index c29ee7ea200b..e39c2ba6e2fb 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c @@ -439,6 +439,64 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) } } +#ifdef CONFIG_DEBUG_FS +#include <linux/seq_file.h> + +static void orion_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + struct orion_gpio_chip *ochip = + container_of(chip, struct orion_gpio_chip, chip); + u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk; + int i; + + out = readl_relaxed(GPIO_OUT(ochip)); + io_conf = readl_relaxed(GPIO_IO_CONF(ochip)); + blink = readl_relaxed(GPIO_BLINK_EN(ochip)); + in_pol = readl_relaxed(GPIO_IN_POL(ochip)); + data_in = readl_relaxed(GPIO_DATA_IN(ochip)); + cause = readl_relaxed(GPIO_EDGE_CAUSE(ochip)); + edg_msk = readl_relaxed(GPIO_EDGE_MASK(ochip)); + lvl_msk = readl_relaxed(GPIO_LEVEL_MASK(ochip)); + + for (i = 0; i < chip->ngpio; i++) { + const char *label; + u32 msk; + bool is_out; + + label = gpiochip_is_requested(chip, i); + if (!label) + continue; + + msk = 1 << i; + is_out = !(io_conf & msk); + + seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label); + + if (is_out) { + seq_printf(s, " out %s %s\n", + out & msk ? "hi" : "lo", + blink & msk ? "(blink )" : ""); + continue; + } + + seq_printf(s, " in %s (act %s) - IRQ", + (data_in ^ in_pol) & msk ? "hi" : "lo", + in_pol & msk ? "lo" : "hi"); + if (!((edg_msk | lvl_msk) & msk)) { + seq_printf(s, " disabled\n"); + continue; + } + if (edg_msk & msk) + seq_printf(s, " edge "); + if (lvl_msk & msk) + seq_printf(s, " level"); + seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear "); + } +} +#else +#define orion_gpio_dbg_show NULL +#endif + void __init orion_gpio_init(struct device_node *np, int gpio_base, int ngpio, void __iomem *base, int mask_offset, @@ -471,6 +529,7 @@ void __init orion_gpio_init(struct device_node *np, #ifdef CONFIG_OF ochip->chip.of_node = np; #endif + ochip->chip.dbg_show = orion_gpio_dbg_show; spin_lock_init(&ochip->lock); ochip->base = (void __iomem *)base; |