2019-05-27 09:55:08 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2011-09-06 11:05:25 +04:00
/*
2013-03-21 03:39:42 +04:00
* Copyright 2011 - 2013 Freescale Semiconductor , Inc .
2011-09-06 11:05:25 +04:00
* Copyright 2011 Linaro Ltd .
*/
2012-04-24 10:19:13 +04:00
# include <linux/clk.h>
2012-11-06 02:18:28 +04:00
# include <linux/irqchip.h>
2011-09-06 11:05:25 +04:00
# include <linux/of_platform.h>
2013-10-23 08:51:28 +04:00
# include <linux/pci.h>
2011-12-14 05:26:47 +04:00
# include <linux/phy.h>
2012-09-05 06:57:15 +04:00
# include <linux/regmap.h>
2011-12-14 05:26:47 +04:00
# include <linux/micrel_phy.h>
2012-09-05 06:57:15 +04:00
# include <linux/mfd/syscon.h>
2013-06-26 17:08:49 +04:00
# include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
2011-09-06 11:05:25 +04:00
# include <asm/mach/arch.h>
2013-01-17 12:37:42 +04:00
# include <asm/mach/map.h>
2011-09-06 11:05:25 +04:00
2012-09-13 17:01:00 +04:00
# include "common.h"
2012-09-13 17:12:50 +04:00
# include "cpuidle.h"
2012-09-14 10:14:45 +04:00
# include "hardware.h"
2012-05-22 02:50:30 +04:00
2011-12-14 05:26:47 +04:00
/* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
static int ksz9021rn_phy_fixup ( struct phy_device * phydev )
{
2012-08-16 11:42:50 +04:00
if ( IS_BUILTIN ( CONFIG_PHYLIB ) ) {
2012-05-08 17:39:33 +04:00
/* min rx data delay */
2013-08-13 18:59:00 +04:00
phy_write ( phydev , MICREL_KSZ9021_EXTREG_CTRL ,
0x8000 | MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW ) ;
phy_write ( phydev , MICREL_KSZ9021_EXTREG_DATA_WRITE , 0x0000 ) ;
2011-12-14 05:26:47 +04:00
2012-05-08 17:39:33 +04:00
/* max rx/tx clock delay, min rx/tx control delay */
2013-08-13 18:59:00 +04:00
phy_write ( phydev , MICREL_KSZ9021_EXTREG_CTRL ,
0x8000 | MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW ) ;
phy_write ( phydev , MICREL_KSZ9021_EXTREG_DATA_WRITE , 0xf0f0 ) ;
phy_write ( phydev , MICREL_KSZ9021_EXTREG_CTRL ,
MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW ) ;
2012-05-08 17:39:33 +04:00
}
2011-12-14 05:26:47 +04:00
return 0 ;
}
2013-10-23 08:51:28 +04:00
/*
* fixup for PLX PEX8909 bridge to configure GPIO1 - 7 as output High
* as they are used for slots1 - 7 PERST #
*/
static void ventana_pciesw_early_fixup ( struct pci_dev * dev )
{
u32 dw ;
if ( ! of_machine_is_compatible ( " gw,ventana " ) )
return ;
if ( dev - > devfn ! = 0 )
return ;
pci_read_config_dword ( dev , 0x62c , & dw ) ;
dw | = 0xaaa8 ; // GPIO1-7 outputs
pci_write_config_dword ( dev , 0x62c , dw ) ;
pci_read_config_dword ( dev , 0x644 , & dw ) ;
dw | = 0xfe ; // GPIO1-7 output high
pci_write_config_dword ( dev , 0x644 , dw ) ;
msleep ( 100 ) ;
}
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_PLX , 0x8609 , ventana_pciesw_early_fixup ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_PLX , 0x8606 , ventana_pciesw_early_fixup ) ;
DECLARE_PCI_FIXUP_EARLY ( PCI_VENDOR_ID_PLX , 0x8604 , ventana_pciesw_early_fixup ) ;
2013-06-20 19:34:31 +04:00
static void __init imx6q_enet_phy_init ( void )
2013-06-13 15:50:56 +04:00
{
2013-06-20 19:34:31 +04:00
if ( IS_BUILTIN ( CONFIG_PHYLIB ) ) {
2012-05-08 17:39:33 +04:00
phy_register_fixup_for_uid ( PHY_ID_KSZ9021 , MICREL_PHY_ID_MASK ,
2012-04-27 11:02:59 +04:00
ksz9021rn_phy_fixup ) ;
2013-06-20 19:34:31 +04:00
}
2013-06-13 15:50:56 +04:00
}
2012-10-30 22:25:22 +04:00
static void __init imx6q_1588_init ( void )
{
2014-02-06 09:22:02 +04:00
struct device_node * np ;
struct clk * ptp_clk ;
struct clk * enet_ref ;
2012-10-30 22:25:22 +04:00
struct regmap * gpr ;
2014-02-06 09:22:02 +04:00
u32 clksel ;
2012-10-30 22:25:22 +04:00
2014-02-06 09:22:02 +04:00
np = of_find_compatible_node ( NULL , NULL , " fsl,imx6q-fec " ) ;
if ( ! np ) {
pr_warn ( " %s: failed to find fec node \n " , __func__ ) ;
return ;
}
ptp_clk = of_clk_get ( np , 2 ) ;
if ( IS_ERR ( ptp_clk ) ) {
pr_warn ( " %s: failed to get ptp clock \n " , __func__ ) ;
goto put_node ;
}
enet_ref = clk_get_sys ( NULL , " enet_ref " ) ;
if ( IS_ERR ( enet_ref ) ) {
pr_warn ( " %s: failed to get enet clock \n " , __func__ ) ;
goto put_ptp_clk ;
}
/*
* If enet_ref from ANATOP / CCM is the PTP clock source , we need to
* set bit IOMUXC_GPR1 [ 21 ] . Or the PTP clock must be from pad
* ( external OSC ) , and we need to clear the bit .
*/
2015-02-25 17:53:32 +03:00
clksel = clk_is_match ( ptp_clk , enet_ref ) ?
IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
IMX6Q_GPR1_ENET_CLK_SEL_PAD ;
2012-10-30 22:25:22 +04:00
gpr = syscon_regmap_lookup_by_compatible ( " fsl,imx6q-iomuxc-gpr " ) ;
if ( ! IS_ERR ( gpr ) )
2013-06-26 17:08:49 +04:00
regmap_update_bits ( gpr , IOMUXC_GPR1 ,
IMX6Q_GPR1_ENET_CLK_SEL_MASK ,
2014-02-06 09:22:02 +04:00
clksel ) ;
2012-10-30 22:25:22 +04:00
else
2016-05-23 18:16:25 +03:00
pr_err ( " failed to find fsl,imx6q-iomuxc-gpr regmap \n " ) ;
2012-10-30 22:25:22 +04:00
2014-02-06 09:22:02 +04:00
clk_put ( enet_ref ) ;
put_ptp_clk :
clk_put ( ptp_clk ) ;
put_node :
of_node_put ( np ) ;
2012-10-30 22:25:22 +04:00
}
2012-07-12 06:25:24 +04:00
2014-02-24 17:51:50 +04:00
static void __init imx6q_axi_init ( void )
{
struct regmap * gpr ;
unsigned int mask ;
gpr = syscon_regmap_lookup_by_compatible ( " fsl,imx6q-iomuxc-gpr " ) ;
if ( ! IS_ERR ( gpr ) ) {
/*
* Enable the cacheable attribute of VPU and IPU
* AXI transactions .
*/
mask = IMX6Q_GPR4_VPU_WR_CACHE_SEL |
IMX6Q_GPR4_VPU_RD_CACHE_SEL |
IMX6Q_GPR4_VPU_P_WR_CACHE_VAL |
IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK |
IMX6Q_GPR4_IPU_WR_CACHE_CTL |
IMX6Q_GPR4_IPU_RD_CACHE_CTL ;
regmap_update_bits ( gpr , IOMUXC_GPR4 , mask , mask ) ;
/* Increase IPU read QoS priority */
regmap_update_bits ( gpr , IOMUXC_GPR6 ,
IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK |
IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK ,
( 0xf < < 16 ) | ( 0x7 < < 20 ) ) ;
regmap_update_bits ( gpr , IOMUXC_GPR7 ,
IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK |
IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK ,
( 0xf < < 16 ) | ( 0x7 < < 20 ) ) ;
} else {
pr_warn ( " failed to find fsl,imx6q-iomuxc-gpr regmap \n " ) ;
}
}
2011-09-06 11:05:25 +04:00
static void __init imx6q_init_machine ( void )
{
2020-11-04 19:54:18 +03:00
if ( cpu_is_imx6q ( ) & & imx_get_soc_revision ( ) > = IMX_CHIP_REVISION_2_0 )
/*
* SoCs that identify as i . MX6Q > = rev 2.0 are really i . MX6QP .
* Quirk : i . MX6QP revision = i . MX6Q revision - ( 1 , 0 ) ,
* e . g . i . MX6QP rev 1.1 identifies as i . MX6Q rev 2.1 .
*/
imx_print_silicon_rev ( " i.MX6QP " , imx_get_soc_revision ( ) - 0x10 ) ;
2016-02-02 13:01:38 +03:00
else
imx_print_silicon_rev ( cpu_is_imx6dl ( ) ? " i.MX6DL " : " i.MX6Q " ,
imx_get_soc_revision ( ) ) ;
2013-08-27 16:50:00 +04:00
2013-06-20 19:34:31 +04:00
imx6q_enet_phy_init ( ) ;
2021-09-21 02:43:11 +03:00
of_platform_default_populate ( NULL , NULL , NULL ) ;
2013-03-21 03:39:42 +04:00
imx_anatop_init ( ) ;
2014-01-17 07:39:05 +04:00
cpu_is_imx6q ( ) ? imx6q_pm_init ( ) : imx6dl_pm_init ( ) ;
2012-10-30 22:25:22 +04:00
imx6q_1588_init ( ) ;
2014-02-24 17:51:50 +04:00
imx6q_axi_init ( ) ;
2011-09-06 11:05:25 +04:00
}
2012-05-22 02:50:30 +04:00
static void __init imx6q_init_late ( void )
{
2012-12-04 18:55:15 +04:00
/*
2017-10-11 15:08:23 +03:00
* WAIT mode is broken on imx6 Dual / Quad revision 1.0 and 1.1 so
* there is no point to run cpuidle on them .
*
* It does work on imx6 Solo / DualLite starting from 1.1
2012-12-04 18:55:15 +04:00
*/
2017-10-11 15:08:23 +03:00
if ( ( cpu_is_imx6q ( ) & & imx_get_soc_revision ( ) > IMX_CHIP_REVISION_1_1 ) | |
( cpu_is_imx6dl ( ) & & imx_get_soc_revision ( ) > IMX_CHIP_REVISION_1_0 ) )
2012-12-04 18:55:15 +04:00
imx6q_cpuidle_init ( ) ;
2013-01-08 10:25:14 +04:00
2017-09-30 18:16:46 +03:00
if ( IS_ENABLED ( CONFIG_ARM_IMX6Q_CPUFREQ ) )
platform_device_register_simple ( " imx6q-cpufreq " , - 1 , NULL , 0 ) ;
2012-05-22 02:50:30 +04:00
}
2011-09-06 11:05:25 +04:00
static void __init imx6q_map_io ( void )
{
2013-01-17 12:37:42 +04:00
debug_ll_io_init ( ) ;
2011-09-06 11:05:25 +04:00
imx_scu_map_io ( ) ;
}
static void __init imx6q_init_irq ( void )
{
2015-03-13 19:05:37 +03:00
imx_gpc_check_dt ( ) ;
2013-08-13 10:59:43 +04:00
imx_init_revision_from_anatop ( ) ;
2013-07-08 17:45:20 +04:00
imx_init_l2cache ( ) ;
2011-09-06 11:05:25 +04:00
imx_src_init ( ) ;
2012-11-06 02:18:28 +04:00
irqchip_init ( ) ;
2015-04-29 08:07:03 +03:00
imx6_pm_ccm_init ( " fsl,imx6q-ccm " ) ;
2011-09-06 11:05:25 +04:00
}
2014-07-01 12:03:00 +04:00
static const char * const imx6q_dt_compat [ ] __initconst = {
2013-04-01 18:13:32 +04:00
" fsl,imx6dl " ,
2012-02-17 15:07:00 +04:00
" fsl,imx6q " ,
2016-02-02 13:01:38 +03:00
" fsl,imx6qp " ,
2011-09-06 11:05:25 +04:00
NULL ,
} ;
2013-04-01 18:13:32 +04:00
DT_MACHINE_START ( IMX6Q , " Freescale i.MX6 Quad/DualLite (Device Tree) " )
2016-06-19 04:09:31 +03:00
. l2c_aux_val = 0 ,
. l2c_aux_mask = ~ 0 ,
2011-09-08 16:15:22 +04:00
. smp = smp_ops ( imx_smp_ops ) ,
2011-09-06 11:05:25 +04:00
. map_io = imx6q_map_io ,
. init_irq = imx6q_init_irq ,
. init_machine = imx6q_init_machine ,
2012-05-22 02:50:30 +04:00
. init_late = imx6q_init_late ,
2011-09-06 11:05:25 +04:00
. dt_compat = imx6q_dt_compat ,
MACHINE_END