diff options
Diffstat (limited to 'arch/arm/mach-imx/mach-imx6ul.c')
-rw-r--r-- | arch/arm/mach-imx/mach-imx6ul.c | 138 |
1 files changed, 130 insertions, 8 deletions
diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c index 58a2b88233e6..851034d5f73f 100644 --- a/arch/arm/mach-imx/mach-imx6ul.c +++ b/arch/arm/mach-imx/mach-imx6ul.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. * * 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 @@ -9,14 +9,17 @@ #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> #include <linux/micrel_phy.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/phy.h> +#include <linux/pm_opp.h> #include <linux/regmap.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include "common.h" #include "cpuidle.h" +#include "hardware.h" static void __init imx6ul_enet_clk_init(void) { @@ -46,15 +49,122 @@ static int ksz8081_phy_fixup(struct phy_device *dev) static void __init imx6ul_enet_phy_init(void) { - if (IS_BUILTIN(CONFIG_PHYLIB)) - phy_register_fixup_for_uid(PHY_ID_KSZ8081, MICREL_PHY_ID_MASK, - ksz8081_phy_fixup); + if (IS_BUILTIN(CONFIG_PHYLIB)) { + /* + * i.MX6UL EVK board RevA, RevB, RevC all use KSZ8081 + * Silicon revision 00, the PHY ID is 0x00221560, pass our + * test with the phy fixup. + */ + phy_register_fixup(PHY_ANY_ID, PHY_ID_KSZ8081, 0xffffffff, + ksz8081_phy_fixup); + + /* + * i.MX6UL EVK board RevC1 board use KSZ8081 + * Silicon revision 01, the PHY ID is 0x00221561. + * This silicon revision still need the phy fixup setting. + */ + #define PHY_ID_KSZ8081_MNRN61 0x00221561 + phy_register_fixup(PHY_ANY_ID, PHY_ID_KSZ8081_MNRN61, + 0xffffffff, ksz8081_phy_fixup); + } +} + +#define OCOTP_CFG3 0x440 +#define OCOTP_CFG3_SPEED_SHIFT 16 +#define OCOTP_CFG3_SPEED_696MHZ 0x2 +#define OCOTP_CFG3_SPEED_900MHZ 0x3 + +static void __init imx6ul_opp_check_speed_grading(struct device *cpu_dev) +{ + struct device_node *np; + void __iomem *base; + u32 val; + + if (cpu_is_imx6ul()) + np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp"); + else + np = of_find_compatible_node(NULL, NULL, "fsl,imx6ull-ocotp"); + + if (!np) { + pr_warn("failed to find ocotp node\n"); + return; + } + + base = of_iomap(np, 0); + if (!base) { + pr_warn("failed to map ocotp\n"); + goto put_node; + } + + /* + * Speed GRADING[1:0] defines the max speed of ARM: + * 2b'00: Reserved; + * 2b'01: 528000000Hz; + * 2b'10: 700000000Hz(i.MX6UL), 800000000Hz(i.MX6ULL); + * 2b'11: 900000000Hz(i.MX6ULL); + * We need to set the max speed of ARM according to fuse map. + */ + val = readl_relaxed(base + OCOTP_CFG3); + val >>= OCOTP_CFG3_SPEED_SHIFT; + val &= 0x3; + if (cpu_is_imx6ul()) { + if (val < OCOTP_CFG3_SPEED_696MHZ) { + if (dev_pm_opp_disable(cpu_dev, 696000000)) + pr_warn("Failed to disable 696MHz OPP\n"); + } + } + + if (cpu_is_imx6ull()) { + if (val != OCOTP_CFG3_SPEED_696MHZ) { + if (dev_pm_opp_disable(cpu_dev, 792000000)) + pr_warn("Failed to disable 792MHz OPP\n"); + } + + if (val != OCOTP_CFG3_SPEED_900MHZ) { + if(dev_pm_opp_disable(cpu_dev, 900000000)) + pr_warn("Failed to disable 900MHz OPP\n"); + } + } + iounmap(base); + +put_node: + of_node_put(np); +} + +static void __init imx6ul_opp_init(void) +{ + struct device_node *np; + struct device *cpu_dev = get_cpu_device(0); + + if (!cpu_dev) { + pr_warn("failed to get cpu0 device\n"); + return; + } + np = of_node_get(cpu_dev->of_node); + if (!np) { + pr_warn("failed to find cpu0 node\n"); + return; + } + + if (dev_pm_opp_of_add_table(cpu_dev)) { + pr_warn("failed to init OPP table\n"); + goto put_node; + } + + imx6ul_opp_check_speed_grading(cpu_dev); + +put_node: + of_node_put(np); } static inline void imx6ul_enet_init(void) { imx6ul_enet_clk_init(); imx6ul_enet_phy_init(); + if (cpu_is_imx6ul()) + imx6_enet_mac_init("fsl,imx6ul-fec", "fsl,imx6ul-ocotp"); + else + imx6_enet_mac_init("fsl,imx6ul-fec", "fsl,imx6ull-ocotp"); } static void __init imx6ul_init_machine(void) @@ -73,6 +183,7 @@ static void __init imx6ul_init_machine(void) static void __init imx6ul_init_irq(void) { + imx_gpc_check_dt(); imx_init_revision_from_anatop(); imx_src_init(); irqchip_init(); @@ -81,18 +192,29 @@ static void __init imx6ul_init_irq(void) static void __init imx6ul_init_late(void) { - imx6sx_cpuidle_init(); - - if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) + if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) { + imx6ul_opp_init(); platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0); + } + + imx6ul_cpuidle_init(); +} + +static void __init imx6ul_map_io(void) +{ + debug_ll_io_init(); + imx6_pm_map_io(); + imx_busfreq_map_io(); } static const char * const imx6ul_dt_compat[] __initconst = { "fsl,imx6ul", + "fsl,imx6ull", NULL, }; -DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)") +DT_MACHINE_START(IMX6UL, "Freescale i.MX6 UltraLite (Device Tree)") + .map_io = imx6ul_map_io, .init_irq = imx6ul_init_irq, .init_machine = imx6ul_init_machine, .init_late = imx6ul_init_late, |