diff options
-rw-r--r-- | Documentation/devicetree/bindings/clock/imx6q-clock.txt | 6 | ||||
-rw-r--r-- | arch/arm/configs/imx_v4_v5_defconfig | 19 | ||||
-rw-r--r-- | arch/arm/configs/imx_v6_v7_defconfig | 51 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-dt-sama5.c | 17 | ||||
-rw-r--r-- | arch/arm/mach-imx/Kconfig | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/anatop.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-fixup-div.c | 129 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-fixup-mux.c | 107 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx6q.c | 46 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx6sl.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-pllv3.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk.c | 26 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk.h | 10 | ||||
-rw-r--r-- | arch/arm/mach-imx/common.h | 13 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6q.c | 120 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6sl.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/mm-imx5.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-imx/pm-imx5.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-imx/system.c | 33 | ||||
-rw-r--r-- | include/linux/micrel_phy.h | 6 |
21 files changed, 499 insertions, 143 deletions
diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt index a0e104f0527e..5a90a724b520 100644 --- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt +++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt @@ -209,6 +209,12 @@ clocks and IDs. pll5_post_div 194 pll5_video_div 195 eim_slow 196 + spdif 197 + cko2_sel 198 + cko2_podf 199 + cko2 200 + cko 201 + vdoa 202 Examples: diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig index f07a847b00c9..e958ebe79779 100644 --- a/arch/arm/configs/imx_v4_v5_defconfig +++ b/arch/arm/configs/imx_v4_v5_defconfig @@ -1,4 +1,3 @@ -CONFIG_EXPERIMENTAL=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -17,16 +16,18 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_MXC=y CONFIG_ARCH_MULTI_V4T=y CONFIG_ARCH_MULTI_V5=y # CONFIG_ARCH_MULTI_V7 is not set +CONFIG_ARCH_MXC=y +CONFIG_MXC_IRQ_PRIOR=y CONFIG_ARCH_MX1ADS=y CONFIG_MACH_SCB9328=y CONFIG_MACH_APF9328=y CONFIG_MACH_MX21ADS=y CONFIG_MACH_MX25_3DS=y CONFIG_MACH_EUKREA_CPUIMX25SD=y +CONFIG_MACH_IMX25_DT=y CONFIG_MACH_MX27ADS=y CONFIG_MACH_PCM038=y CONFIG_MACH_CPUIMX27=y @@ -39,8 +40,6 @@ CONFIG_MACH_PCA100=y CONFIG_MACH_MXT_TD60=y CONFIG_MACH_IMX27IPCAM=y CONFIG_MACH_IMX27_DT=y -CONFIG_MXC_IRQ_PRIOR=y -CONFIG_MXC_PWM=y CONFIG_PREEMPT=y CONFIG_AEABI=y CONFIG_ZBOOT_ROM_TEXT=0x0 @@ -67,7 +66,6 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_ADV_OPTIONS=y @@ -123,24 +121,20 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_MC13783=y CONFIG_REGULATOR_MC13892=y CONFIG_MEDIA_SUPPORT=y -CONFIG_VIDEO_DEV=y -CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_SOC_CAMERA=y -CONFIG_SOC_CAMERA_OV2640=y CONFIG_VIDEO_MX2=y CONFIG_V4L_MEM2MEM_DRIVERS=y CONFIG_VIDEO_CODA=y +CONFIG_SOC_CAMERA_OV2640=y CONFIG_FB=y CONFIG_FB_IMX=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_L4F00242T03=y CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_PWM=y CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FONTS=y -CONFIG_FONT_8x8=y CONFIG_LOGO=y CONFIG_SOUND=y CONFIG_SND=y @@ -157,7 +151,6 @@ CONFIG_USB_HID=m CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_MXC=y -CONFIG_USB_ULPI=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y @@ -198,3 +191,5 @@ CONFIG_NLS_CODEPAGE_850=m CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_15=m # CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_FONTS=y +CONFIG_FONT_8x8=y diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 06686e7303a9..5d488c24b132 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -1,4 +1,3 @@ -CONFIG_EXPERIMENTAL=y # CONFIG_LOCALVERSION_AUTO is not set CONFIG_KERNEL_LZO=y CONFIG_SYSVIPC=y @@ -17,10 +16,8 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set -CONFIG_ARCH_MXC=y CONFIG_ARCH_MULTI_V6=y -CONFIG_ARCH_MULTI_V7=y -CONFIG_MACH_IMX31_DT=y +CONFIG_ARCH_MXC=y CONFIG_MACH_MX31LILLY=y CONFIG_MACH_MX31LITE=y CONFIG_MACH_PCM037=y @@ -30,6 +27,7 @@ CONFIG_MACH_MX31MOBOARD=y CONFIG_MACH_QONG=y CONFIG_MACH_ARMADILLO5X0=y CONFIG_MACH_KZM_ARM11_01=y +CONFIG_MACH_IMX31_DT=y CONFIG_MACH_PCM043=y CONFIG_MACH_MX35_3DS=y CONFIG_MACH_VPR200=y @@ -39,7 +37,6 @@ CONFIG_SOC_IMX53=y CONFIG_SOC_IMX6Q=y CONFIG_SOC_IMX6SL=y CONFIG_SOC_VF610=y -CONFIG_MXC_PWM=y CONFIG_SMP=y CONFIG_VMSPLIT_2G=y CONFIG_PREEMPT_VOLUNTARY=y @@ -64,20 +61,24 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_LRO is not set CONFIG_IPV6=y CONFIG_NETFILTER=y -# CONFIG_WIRELESS is not set +CONFIG_CFG80211=y +CONFIG_MAC80211=y +CONFIG_RFKILL=y +CONFIG_RFKILL_INPUT=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set +CONFIG_IMX_WEIM=y CONFIG_CONNECTOR=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_JEDECPROBE=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_PHYSMAP_OF=y CONFIG_MTD_DATAFLASH=y CONFIG_MTD_M25P80=y CONFIG_MTD_SST25L=y @@ -88,6 +89,7 @@ CONFIG_MTD_UBI=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_SRAM=y CONFIG_EEPROM_AT24=y CONFIG_EEPROM_AT25=y # CONFIG_SCSI_PROC_FS is not set @@ -98,10 +100,11 @@ CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y # CONFIG_SCSI_LOWLEVEL is not set CONFIG_ATA=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_IMX=y CONFIG_PATA_IMX=y CONFIG_NETDEVICES=y # CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_CHELSIO is not set CONFIG_CS89x0=y CONFIG_CS89x0_PLATFORM=y # CONFIG_NET_VENDOR_FARADAY is not set @@ -115,7 +118,7 @@ CONFIG_SMC91X=y CONFIG_SMC911X=y CONFIG_SMSC911X=y # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_WLAN is not set +CONFIG_BRCMFMAC=m # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVBUG=m @@ -124,6 +127,7 @@ CONFIG_KEYBOARD_IMX=y CONFIG_MOUSE_PS2=m CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_EGALAX=y CONFIG_TOUCHSCREEN_MC13783=y CONFIG_INPUT_MISC=y CONFIG_INPUT_MMA8450=y @@ -133,13 +137,13 @@ CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_DEVKMEM is not set CONFIG_SERIAL_IMX=y CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_MXC_RNGA=y -CONFIG_I2C=y # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y # CONFIG_I2C_HELPER_AUTO is not set -CONFIG_I2C_ALGOBIT=m CONFIG_I2C_ALGOPCF=m CONFIG_I2C_ALGOPCA=m CONFIG_I2C_IMX=y @@ -155,30 +159,26 @@ CONFIG_MFD_MC13XXX_SPI=y CONFIG_MFD_MC13XXX_I2C=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_DA9052=y CONFIG_REGULATOR_ANATOP=y +CONFIG_REGULATOR_DA9052=y CONFIG_REGULATOR_MC13783=y CONFIG_REGULATOR_MC13892=y CONFIG_MEDIA_SUPPORT=y -CONFIG_VIDEO_DEV=y -CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_SOC_CAMERA=y +CONFIG_VIDEO_MX3=y +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_CODA=y CONFIG_SOC_CAMERA_OV2640=y CONFIG_DRM=y -CONFIG_VIDEO_MX3=y -CONFIG_FB=y -CONFIG_LCD_PLATFORM=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_L4F00242T03=y +CONFIG_LCD_PLATFORM=y CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_PWM=y CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -CONFIG_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y CONFIG_LOGO=y CONFIG_SOUND=y CONFIG_SND=y @@ -192,11 +192,12 @@ CONFIG_SND_SOC_IMX_MC13783=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_MXC=y +CONFIG_USB_STORAGE=y CONFIG_USB_CHIPIDEA=y CONFIG_USB_CHIPIDEA_HOST=y CONFIG_USB_PHY=y +CONFIG_NOP_USB_XCEIV=y CONFIG_USB_MXS_PHY=y -CONFIG_USB_STORAGE=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y @@ -213,9 +214,10 @@ CONFIG_IMX_SDMA=y CONFIG_MXS_DMA=y CONFIG_STAGING=y CONFIG_DRM_IMX=y -CONFIG_DRM_IMX_TVE=y CONFIG_DRM_IMX_FB_HELPER=y CONFIG_DRM_IMX_PARALLEL_DISPLAY=y +CONFIG_DRM_IMX_TVE=y +CONFIG_DRM_IMX_LDB=y CONFIG_DRM_IMX_IPUV3_CORE=y CONFIG_DRM_IMX_IPUV3=y CONFIG_COMMON_CLK_DEBUG=y @@ -269,3 +271,6 @@ CONFIG_CRC_CCITT=m CONFIG_CRC_T10DIF=y CONFIG_CRC7=m CONFIG_LIBCRC32C=m +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y diff --git a/arch/arm/mach-at91/board-dt-sama5.c b/arch/arm/mach-at91/board-dt-sama5.c index ad95f6a23a28..bf00d15d954d 100644 --- a/arch/arm/mach-at91/board-dt-sama5.c +++ b/arch/arm/mach-at91/board-dt-sama5.c @@ -42,20 +42,15 @@ static int ksz9021rn_phy_fixup(struct phy_device *phy) { int value; -#define GMII_RCCPSR 260 -#define GMII_RRDPSR 261 -#define GMII_ERCR 11 -#define GMII_ERDWR 12 - /* Set delay values */ - value = GMII_RCCPSR | 0x8000; - phy_write(phy, GMII_ERCR, value); + value = MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW | 0x8000; + phy_write(phy, MICREL_KSZ9021_EXTREG_CTRL, value); value = 0xF2F4; - phy_write(phy, GMII_ERDWR, value); - value = GMII_RRDPSR | 0x8000; - phy_write(phy, GMII_ERCR, value); + phy_write(phy, MICREL_KSZ9021_EXTREG_DATA_WRITE, value); + value = MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW | 0x8000; + phy_write(phy, MICREL_KSZ9021_EXTREG_CTRL, value); value = 0x2222; - phy_write(phy, GMII_ERDWR, value); + phy_write(phy, MICREL_KSZ9021_EXTREG_DATA_WRITE, value); return 0; } diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index f54656091a9d..546723b305b6 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -1,6 +1,7 @@ config ARCH_MXC bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7 select ARCH_REQUIRE_GPIOLIB + select ARM_CPU_SUSPEND if PM select ARM_PATCH_PHYS_VIRT select AUTO_ZRELADDR if !ZBOOT_ROM select CLKDEV_LOOKUP @@ -8,6 +9,7 @@ config ARCH_MXC select GENERIC_ALLOCATOR select GENERIC_CLOCKEVENTS select GENERIC_IRQ_CHIP + select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7 select MULTI_IRQ_HANDLER select SPARSE_IRQ select USE_OF @@ -785,7 +787,6 @@ config SOC_IMX6Q bool "i.MX6 Quad/DualLite support" select ARCH_HAS_CPUFREQ select ARCH_HAS_OPP - select ARM_CPU_SUSPEND if PM select ARM_ERRATA_754322 select ARM_ERRATA_764369 if SMP select ARM_ERRATA_775420 diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index e20f22d58fd8..5383c589ad71 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -15,7 +15,8 @@ imx5-pm-$(CONFIG_PM) += pm-imx5.o obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(imx5-pm-y) obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \ - clk-pfd.o clk-busy.o clk.o + clk-pfd.o clk-busy.o clk.o \ + clk-fixup-div.o clk-fixup-mux.o obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c index 0cfa07dd9aa4..ad3b755abb78 100644 --- a/arch/arm/mach-imx/anatop.c +++ b/arch/arm/mach-imx/anatop.c @@ -66,7 +66,7 @@ void imx_anatop_post_resume(void) imx_anatop_enable_weak2p5(false); } -void imx_anatop_usb_chrg_detect_disable(void) +static void imx_anatop_usb_chrg_detect_disable(void) { regmap_write(anatop, ANADIG_USB1_CHRG_DETECT, BM_ANADIG_USB_CHRG_DETECT_EN_B @@ -100,4 +100,6 @@ void __init imx_anatop_init(void) pr_err("%s: failed to find imx6q-anatop regmap!\n", __func__); return; } + + imx_anatop_usb_chrg_detect_disable(); } diff --git a/arch/arm/mach-imx/clk-fixup-div.c b/arch/arm/mach-imx/clk-fixup-div.c new file mode 100644 index 000000000000..21db020b1f2d --- /dev/null +++ b/arch/arm/mach-imx/clk-fixup-div.c @@ -0,0 +1,129 @@ +/* + * 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/clk-provider.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/slab.h> +#include "clk.h" + +#define to_clk_div(_hw) container_of(_hw, struct clk_divider, hw) +#define div_mask(d) ((1 << (d->width)) - 1) + +/** + * struct clk_fixup_div - imx integer fixup divider clock + * @divider: the parent class + * @ops: pointer to clk_ops of parent class + * @fixup: a hook to fixup the write value + * + * The imx fixup divider clock is a subclass of basic clk_divider + * with an addtional fixup hook. + */ +struct clk_fixup_div { + struct clk_divider divider; + const struct clk_ops *ops; + void (*fixup)(u32 *val); +}; + +static inline struct clk_fixup_div *to_clk_fixup_div(struct clk_hw *hw) +{ + struct clk_divider *divider = to_clk_div(hw); + + return container_of(divider, struct clk_fixup_div, divider); +} + +static unsigned long clk_fixup_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw); + + return fixup_div->ops->recalc_rate(&fixup_div->divider.hw, parent_rate); +} + +static long clk_fixup_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw); + + return fixup_div->ops->round_rate(&fixup_div->divider.hw, rate, prate); +} + +static int clk_fixup_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw); + struct clk_divider *div = to_clk_div(hw); + unsigned int divider, value; + unsigned long flags = 0; + u32 val; + + divider = parent_rate / rate; + + /* Zero based divider */ + value = divider - 1; + + if (value > div_mask(div)) + value = div_mask(div); + + spin_lock_irqsave(div->lock, flags); + + val = readl(div->reg); + val &= ~(div_mask(div) << div->shift); + val |= value << div->shift; + fixup_div->fixup(&val); + writel(val, div->reg); + + spin_unlock_irqrestore(div->lock, flags); + + return 0; +} + +static const struct clk_ops clk_fixup_div_ops = { + .recalc_rate = clk_fixup_div_recalc_rate, + .round_rate = clk_fixup_div_round_rate, + .set_rate = clk_fixup_div_set_rate, +}; + +struct clk *imx_clk_fixup_divider(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width, + void (*fixup)(u32 *val)) +{ + struct clk_fixup_div *fixup_div; + struct clk *clk; + struct clk_init_data init; + + if (!fixup) + return ERR_PTR(-EINVAL); + + fixup_div = kzalloc(sizeof(*fixup_div), GFP_KERNEL); + if (!fixup_div) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &clk_fixup_div_ops; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = parent ? &parent : NULL; + init.num_parents = parent ? 1 : 0; + + fixup_div->divider.reg = reg; + fixup_div->divider.shift = shift; + fixup_div->divider.width = width; + fixup_div->divider.lock = &imx_ccm_lock; + fixup_div->divider.hw.init = &init; + fixup_div->ops = &clk_divider_ops; + fixup_div->fixup = fixup; + + clk = clk_register(NULL, &fixup_div->divider.hw); + if (IS_ERR(clk)) + kfree(fixup_div); + + return clk; +} diff --git a/arch/arm/mach-imx/clk-fixup-mux.c b/arch/arm/mach-imx/clk-fixup-mux.c new file mode 100644 index 000000000000..deb4b8093b30 --- /dev/null +++ b/arch/arm/mach-imx/clk-fixup-mux.c @@ -0,0 +1,107 @@ +/* + * 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/clk-provider.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/slab.h> +#include "clk.h" + +#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) + +/** + * struct clk_fixup_mux - imx integer fixup multiplexer clock + * @mux: the parent class + * @ops: pointer to clk_ops of parent class + * @fixup: a hook to fixup the write value + * + * The imx fixup multiplexer clock is a subclass of basic clk_mux + * with an addtional fixup hook. + */ +struct clk_fixup_mux { + struct clk_mux mux; + const struct clk_ops *ops; + void (*fixup)(u32 *val); +}; + +static inline struct clk_fixup_mux *to_clk_fixup_mux(struct clk_hw *hw) +{ + struct clk_mux *mux = to_clk_mux(hw); + + return container_of(mux, struct clk_fixup_mux, mux); +} + +static u8 clk_fixup_mux_get_parent(struct clk_hw *hw) +{ + struct clk_fixup_mux *fixup_mux = to_clk_fixup_mux(hw); + + return fixup_mux->ops->get_parent(&fixup_mux->mux.hw); +} + +static int clk_fixup_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_fixup_mux *fixup_mux = to_clk_fixup_mux(hw); + struct clk_mux *mux = to_clk_mux(hw); + unsigned long flags = 0; + u32 val; + + spin_lock_irqsave(mux->lock, flags); + + val = readl(mux->reg); + val &= ~(mux->mask << mux->shift); + val |= index << mux->shift; + fixup_mux->fixup(&val); + writel(val, mux->reg); + + spin_unlock_irqrestore(mux->lock, flags); + + return 0; +} + +static const struct clk_ops clk_fixup_mux_ops = { + .get_parent = clk_fixup_mux_get_parent, + .set_parent = clk_fixup_mux_set_parent, +}; + +struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg, + u8 shift, u8 width, const char **parents, + int num_parents, void (*fixup)(u32 *val)) +{ + struct clk_fixup_mux *fixup_mux; + struct clk *clk; + struct clk_init_data init; + + if (!fixup) + return ERR_PTR(-EINVAL); + + fixup_mux = kzalloc(sizeof(*fixup_mux), GFP_KERNEL); + if (!fixup_mux) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &clk_fixup_mux_ops; + init.parent_names = parents; + init.num_parents = num_parents; + + fixup_mux->mux.reg = reg; + fixup_mux->mux.shift = shift; + fixup_mux->mux.mask = BIT(width) - 1; + fixup_mux->mux.lock = &imx_ccm_lock; + fixup_mux->mux.hw.init = &init; + fixup_mux->ops = &clk_mux_ops; + fixup_mux->fixup = fixup; + + clk = clk_register(NULL, &fixup_mux->mux.hw); + if (IS_ERR(clk)) + kfree(fixup_mux); + + return clk; +} diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 86567d980b07..bbafa3ccacb5 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -206,6 +206,17 @@ 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_div", "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0", "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_post_div", }; +static const char *cko2_sels[] = { + "mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1", + "gpu2d_axi", "dummy", "ecspi_root", "gpu3d_axi", + "usdhc3", "dummy", "arm", "ipu1", + "ipu2", "vdo_axi", "osc", "gpu2d_core", + "gpu3d_core", "usdhc2", "ssi1", "ssi2", + "ssi3", "gpu3d_shader", "vpu_axi", "can_root", + "ldb_di0", "ldb_di1", "esai", "eim_slow", + "uart_serial", "spdif", "asrc", "hsi_tx", +}; +static const char *cko_sels[] = { "cko1", "cko2", }; enum mx6q_clks { dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m, @@ -239,7 +250,8 @@ 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, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, clk_max + usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, + spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, clk_max }; static struct clk *clk[clk_max]; @@ -384,19 +396,21 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[ipu2_di1_sel] = imx_clk_mux("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels)); clk[hsi_tx_sel] = imx_clk_mux("hsi_tx_sel", base + 0x30, 28, 1, hsi_tx_sels, ARRAY_SIZE(hsi_tx_sels)); clk[pcie_axi_sel] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels)); - clk[ssi1_sel] = imx_clk_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); - clk[ssi2_sel] = imx_clk_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); - clk[ssi3_sel] = imx_clk_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); - clk[usdhc1_sel] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); - clk[usdhc2_sel] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); - clk[usdhc3_sel] = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); - clk[usdhc4_sel] = imx_clk_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clk[ssi1_sel] = imx_clk_fixup_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); + clk[ssi2_sel] = imx_clk_fixup_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); + clk[ssi3_sel] = imx_clk_fixup_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); + clk[usdhc1_sel] = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); + clk[usdhc2_sel] = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); + clk[usdhc3_sel] = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); + clk[usdhc4_sel] = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); clk[enfc_sel] = imx_clk_mux("enfc_sel", base + 0x2c, 16, 2, enfc_sels, ARRAY_SIZE(enfc_sels)); - clk[emi_sel] = imx_clk_mux("emi_sel", base + 0x1c, 27, 2, emi_sels, ARRAY_SIZE(emi_sels)); - clk[emi_slow_sel] = imx_clk_mux("emi_slow_sel", base + 0x1c, 29, 2, emi_slow_sels, ARRAY_SIZE(emi_slow_sels)); + clk[emi_sel] = imx_clk_fixup_mux("emi_sel", base + 0x1c, 27, 2, emi_sels, ARRAY_SIZE(emi_sels), imx_cscmr1_fixup); + clk[emi_slow_sel] = imx_clk_fixup_mux("emi_slow_sel", base + 0x1c, 29, 2, emi_slow_sels, ARRAY_SIZE(emi_slow_sels), imx_cscmr1_fixup); clk[vdo_axi_sel] = imx_clk_mux("vdo_axi_sel", base + 0x18, 11, 1, vdo_axi_sels, ARRAY_SIZE(vdo_axi_sels)); clk[vpu_axi_sel] = imx_clk_mux("vpu_axi_sel", base + 0x18, 14, 2, vpu_axi_sels, ARRAY_SIZE(vpu_axi_sels)); clk[cko1_sel] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels)); + clk[cko2_sel] = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels)); + clk[cko] = imx_clk_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels)); /* name reg shift width busy: reg, shift parent_names num_parents */ clk[periph] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels)); @@ -406,7 +420,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[periph_clk2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3); clk[periph2_clk2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3); clk[ipg] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2); - clk[ipg_per] = imx_clk_divider("ipg_per", "ipg", base + 0x1c, 0, 6); + clk[ipg_per] = imx_clk_fixup_divider("ipg_per", "ipg", base + 0x1c, 0, 6, imx_cscmr1_fixup); clk[esai_pred] = imx_clk_divider("esai_pred", "esai_sel", base + 0x28, 9, 3); clk[esai_podf] = imx_clk_divider("esai_podf", "esai_pred", base + 0x28, 25, 3); clk[asrc_pred] = imx_clk_divider("asrc_pred", "asrc_sel", base + 0x30, 12, 3); @@ -442,10 +456,11 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[usdhc4_podf] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3); clk[enfc_pred] = imx_clk_divider("enfc_pred", "enfc_sel", base + 0x2c, 18, 3); clk[enfc_podf] = imx_clk_divider("enfc_podf", "enfc_pred", base + 0x2c, 21, 6); - clk[emi_podf] = imx_clk_divider("emi_podf", "emi_sel", base + 0x1c, 20, 3); - clk[emi_slow_podf] = imx_clk_divider("emi_slow_podf", "emi_slow_sel", base + 0x1c, 23, 3); + clk[emi_podf] = imx_clk_fixup_divider("emi_podf", "emi_sel", base + 0x1c, 20, 3, imx_cscmr1_fixup); + clk[emi_slow_podf] = imx_clk_fixup_divider("emi_slow_podf", "emi_slow_sel", base + 0x1c, 23, 3, imx_cscmr1_fixup); clk[vpu_axi_podf] = imx_clk_divider("vpu_axi_podf", "vpu_axi_sel", base + 0x24, 25, 3); clk[cko1_podf] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3); + clk[cko2_podf] = imx_clk_divider("cko2_podf", "cko2_sel", base + 0x60, 21, 3); /* name parent_name reg shift width busy: reg, shift */ clk[axi] = imx_clk_busy_divider("axi", "axi_sel", base + 0x14, 16, 3, base + 0x48, 0); @@ -486,6 +501,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[i2c3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10); clk[iim] = imx_clk_gate2("iim", "ipg", base + 0x70, 12); clk[enfc] = imx_clk_gate2("enfc", "enfc_podf", base + 0x70, 14); + clk[vdoa] = imx_clk_gate2("vdoa", "vdo_axi", base + 0x70, 26); clk[ipu1] = imx_clk_gate2("ipu1", "ipu1_podf", base + 0x74, 0); clk[ipu1_di0] = imx_clk_gate2("ipu1_di0", "ipu1_di0_sel", base + 0x74, 2); clk[ipu1_di1] = imx_clk_gate2("ipu1_di1", "ipu1_di1_sel", base + 0x74, 4); @@ -521,6 +537,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[sata] = imx_clk_gate2("sata", "ipg", base + 0x7c, 4); clk[sdma] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6); clk[spba] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); + clk[spdif] = imx_clk_gate2("spdif", "spdif_podf", base + 0x7c, 14); clk[ssi1_ipg] = imx_clk_gate2("ssi1_ipg", "ipg", base + 0x7c, 18); clk[ssi2_ipg] = imx_clk_gate2("ssi2_ipg", "ipg", base + 0x7c, 20); clk[ssi3_ipg] = imx_clk_gate2("ssi3_ipg", "ipg", base + 0x7c, 22); @@ -535,6 +552,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[vdo_axi] = imx_clk_gate2("vdo_axi", "vdo_axi_sel", base + 0x80, 12); clk[vpu_axi] = imx_clk_gate2("vpu_axi", "vpu_axi_podf", base + 0x80, 14); clk[cko1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7); + clk[cko2] = imx_clk_gate("cko2", "cko2_podf", base + 0x60, 24); for (i = 0; i < ARRAY_SIZE(clk); i++) if (IS_ERR(clk[i])) @@ -554,7 +572,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk_register_clkdev(clk[pll4_post_div], "pll4_post_div", NULL); clk_register_clkdev(clk[pll4_audio], "pll4_audio", NULL); - if (imx6q_revision() != IMX_CHIP_REVISION_1_0) { + if ((imx6q_revision() != IMX_CHIP_REVISION_1_0) || cpu_is_imx6dl()) { clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]); clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]); } diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c index a307ac22dffe..a5c3c5d21aee 100644 --- a/arch/arm/mach-imx/clk-imx6sl.c +++ b/arch/arm/mach-imx/clk-imx6sl.c @@ -138,14 +138,14 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) clks[IMX6SL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); clks[IMX6SL_CLK_CSI_SEL] = imx_clk_mux("csi_sel", base + 0x3c, 9, 2, csi_lcdif_sels, ARRAY_SIZE(csi_lcdif_sels)); clks[IMX6SL_CLK_LCDIF_AXI_SEL] = imx_clk_mux("lcdif_axi_sel", base + 0x3c, 14, 2, csi_lcdif_sels, ARRAY_SIZE(csi_lcdif_sels)); - clks[IMX6SL_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); - clks[IMX6SL_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); - clks[IMX6SL_CLK_USDHC3_SEL] = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); - clks[IMX6SL_CLK_USDHC4_SEL] = imx_clk_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); - clks[IMX6SL_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); - clks[IMX6SL_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); - clks[IMX6SL_CLK_SSI3_SEL] = imx_clk_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); - clks[IMX6SL_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels)); + clks[IMX6SL_CLK_USDHC1_SEL] = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); + clks[IMX6SL_CLK_USDHC2_SEL] = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); + clks[IMX6SL_CLK_USDHC3_SEL] = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); + clks[IMX6SL_CLK_USDHC4_SEL] = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup); + clks[IMX6SL_CLK_SSI1_SEL] = imx_clk_fixup_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); + clks[IMX6SL_CLK_SSI2_SEL] = imx_clk_fixup_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); + clks[IMX6SL_CLK_SSI3_SEL] = imx_clk_fixup_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); + clks[IMX6SL_CLK_PERCLK_SEL] = imx_clk_fixup_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels), imx_cscmr1_fixup); clks[IMX6SL_CLK_PXP_AXI_SEL] = imx_clk_mux("pxp_axi_sel", base + 0x34, 6, 3, epdc_pxp_sels, ARRAY_SIZE(epdc_pxp_sels)); clks[IMX6SL_CLK_EPDC_AXI_SEL] = imx_clk_mux("epdc_axi_sel", base + 0x34, 15, 3, epdc_pxp_sels, ARRAY_SIZE(epdc_pxp_sels)); clks[IMX6SL_CLK_GPU2D_OVG_SEL] = imx_clk_mux("gpu2d_ovg_sel", base + 0x18, 4, 2, gpu2d_ovg_sels, ARRAY_SIZE(gpu2d_ovg_sels)); @@ -179,14 +179,14 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) clks[IMX6SL_CLK_SSI2_PODF] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6); clks[IMX6SL_CLK_SSI3_PRED] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3); clks[IMX6SL_CLK_SSI3_PODF] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6); - clks[IMX6SL_CLK_PERCLK] = imx_clk_divider("perclk", "perclk_sel", base + 0x1c, 0, 6); + clks[IMX6SL_CLK_PERCLK] = imx_clk_fixup_divider("perclk", "perclk_sel", base + 0x1c, 0, 6, imx_cscmr1_fixup); clks[IMX6SL_CLK_PXP_AXI_PODF] = imx_clk_divider("pxp_axi_podf", "pxp_axi_sel", base + 0x34, 3, 3); clks[IMX6SL_CLK_EPDC_AXI_PODF] = imx_clk_divider("epdc_axi_podf", "epdc_axi_sel", base + 0x34, 12, 3); clks[IMX6SL_CLK_GPU2D_OVG_PODF] = imx_clk_divider("gpu2d_ovg_podf", "gpu2d_ovg_sel", base + 0x18, 26, 3); clks[IMX6SL_CLK_GPU2D_PODF] = imx_clk_divider("gpu2d_podf", "gpu2d_sel", base + 0x18, 29, 3); clks[IMX6SL_CLK_LCDIF_PIX_PRED] = imx_clk_divider("lcdif_pix_pred", "lcdif_pix_sel", base + 0x38, 3, 3); clks[IMX6SL_CLK_EPDC_PIX_PRED] = imx_clk_divider("epdc_pix_pred", "epdc_pix_sel", base + 0x38, 12, 3); - clks[IMX6SL_CLK_LCDIF_PIX_PODF] = imx_clk_divider("lcdif_pix_podf", "lcdif_pix_pred", base + 0x1c, 20, 3); + clks[IMX6SL_CLK_LCDIF_PIX_PODF] = imx_clk_fixup_divider("lcdif_pix_podf", "lcdif_pix_pred", base + 0x1c, 20, 3, imx_cscmr1_fixup); clks[IMX6SL_CLK_EPDC_PIX_PODF] = imx_clk_divider("epdc_pix_podf", "epdc_pix_pred", base + 0x18, 23, 3); clks[IMX6SL_CLK_SPDIF0_PRED] = imx_clk_divider("spdif0_pred", "spdif0_sel", base + 0x30, 25, 3); clks[IMX6SL_CLK_SPDIF0_PODF] = imx_clk_divider("spdif0_podf", "spdif0_pred", base + 0x30, 22, 3); diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index a9fad5f8d340..f6640b6a7b31 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c @@ -48,7 +48,7 @@ struct clk_pllv3 { static int clk_pllv3_prepare(struct clk_hw *hw) { struct clk_pllv3 *pll = to_clk_pllv3(hw); - unsigned long timeout = jiffies + msecs_to_jiffies(10); + unsigned long timeout; u32 val; val = readl_relaxed(pll->base); @@ -59,12 +59,19 @@ static int clk_pllv3_prepare(struct clk_hw *hw) val &= ~BM_PLL_POWER; writel_relaxed(val, pll->base); + timeout = jiffies + msecs_to_jiffies(10); /* Wait for PLL to lock */ - while (!(readl_relaxed(pll->base) & BM_PLL_LOCK)) + do { + if (readl_relaxed(pll->base) & BM_PLL_LOCK) + break; if (time_after(jiffies, timeout)) - return -ETIMEDOUT; + break; + } while (1); - return 0; + if (readl_relaxed(pll->base) & BM_PLL_LOCK) + return 0; + else + return -ETIMEDOUT; } static void clk_pllv3_unprepare(struct clk_hw *hw) diff --git a/arch/arm/mach-imx/clk.c b/arch/arm/mach-imx/clk.c index 55bc80a00666..edc35df7bed4 100644 --- a/arch/arm/mach-imx/clk.c +++ b/arch/arm/mach-imx/clk.c @@ -37,3 +37,29 @@ struct clk * __init imx_obtain_fixed_clock( clk = imx_clk_fixed(name, rate); return clk; } + +/* + * This fixups the register CCM_CSCMR1 write value. + * The write/read/divider values of the aclk_podf field + * of that register have the relationship described by + * the following table: + * + * write value read value divider + * 3b'000 3b'110 7 + * 3b'001 3b'111 8 + * 3b'010 3b'100 5 + * 3b'011 3b'101 6 + * 3b'100 3b'010 3 + * 3b'101 3b'011 4 + * 3b'110 3b'000 1 + * 3b'111 3b'001 2(default) + * + * That's why we do the xor operation below. + */ +#define CSCMR1_FIXUP 0x00600000 + +void imx_cscmr1_fixup(u32 *val) +{ + *val ^= CSCMR1_FIXUP; + return; +} diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 0e4e8bb261b9..3451f1f8ba1f 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -6,6 +6,8 @@ extern spinlock_t imx_ccm_lock; +extern void imx_cscmr1_fixup(u32 *val); + struct clk *imx_clk_pllv1(const char *name, const char *parent, void __iomem *base); @@ -49,6 +51,14 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift, u8 width, void __iomem *busy_reg, u8 busy_shift, const char **parent_names, int num_parents); +struct clk *imx_clk_fixup_divider(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width, + void (*fixup)(u32 *val)); + +struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg, + u8 shift, u8 width, const char **parents, + int num_parents, void (*fixup)(u32 *val)); + static inline struct clk *imx_clk_fixed(const char *name, int rate) { return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate); diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index cb6c838b63ed..4517fd760bfc 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -137,7 +137,6 @@ 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); @@ -147,12 +146,10 @@ extern int imx_cpu_kill(unsigned int cpu); #ifdef CONFIG_PM extern void imx6q_pm_init(void); -extern void imx51_pm_init(void); -extern void imx53_pm_init(void); +extern void imx5_pm_init(void); #else static inline void imx6q_pm_init(void) {} -static inline void imx51_pm_init(void) {} -static inline void imx53_pm_init(void) {} +static inline void imx5_pm_init(void) {} #endif #ifdef CONFIG_NEON @@ -161,6 +158,12 @@ extern int mx51_neon_fixup(void); static inline int mx51_neon_fixup(void) { return 0; } #endif +#ifdef CONFIG_CACHE_L2X0 +extern void imx_init_l2cache(void); +#else +static inline void imx_init_l2cache(void) {} +#endif + extern struct smp_operations imx_smp_ops; #endif diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 7be13f8e69a0..1e093abe7b95 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -31,7 +31,7 @@ #include <linux/regmap.h> #include <linux/micrel_phy.h> #include <linux/mfd/syscon.h> -#include <asm/hardware/cache-l2x0.h> +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/system_misc.h> @@ -103,18 +103,65 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev) { if (IS_BUILTIN(CONFIG_PHYLIB)) { /* min rx data delay */ - phy_write(phydev, 0x0b, 0x8105); - phy_write(phydev, 0x0c, 0x0000); + phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL, + 0x8000 | MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW); + phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0x0000); /* max rx/tx clock delay, min rx/tx control delay */ - phy_write(phydev, 0x0b, 0x8104); - phy_write(phydev, 0x0c, 0xf0f0); - phy_write(phydev, 0x0b, 0x104); + 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); } return 0; } +static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val) +{ + phy_write(dev, 0x0d, device); + phy_write(dev, 0x0e, reg); + phy_write(dev, 0x0d, (1 << 14) | device); + phy_write(dev, 0x0e, val); +} + +static int ksz9031rn_phy_fixup(struct phy_device *dev) +{ + /* + * min rx data delay, max rx/tx clock delay, + * min rx/tx control delay + */ + mmd_write_reg(dev, 2, 4, 0); + mmd_write_reg(dev, 2, 5, 0); + mmd_write_reg(dev, 2, 8, 0x003ff); + + return 0; +} + +static int ar8031_phy_fixup(struct phy_device *dev) +{ + u16 val; + + /* To enable AR8031 output a 125MHz clk from CLK_25M */ + phy_write(dev, 0xd, 0x7); + phy_write(dev, 0xe, 0x8016); + phy_write(dev, 0xd, 0x4007); + + val = phy_read(dev, 0xe); + val &= 0xffe3; + val |= 0x18; + phy_write(dev, 0xe, val); + + /* introduce tx clock delay */ + phy_write(dev, 0x1d, 0x5); + val = phy_read(dev, 0x1e); + val |= 0x0100; + phy_write(dev, 0x1e, val); + + return 0; +} + static void __init imx6q_sabrelite_cko1_setup(void) { struct clk *cko1_sel, *ahb, *cko1; @@ -139,12 +186,18 @@ put_clk: clk_put(cko1); } -static void __init imx6q_sabrelite_init(void) +#define PHY_ID_AR8031 0x004dd074 + +static void __init imx6q_enet_phy_init(void) { - if (IS_BUILTIN(CONFIG_PHYLIB)) + if (IS_BUILTIN(CONFIG_PHYLIB)) { phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, ksz9021rn_phy_fixup); - imx6q_sabrelite_cko1_setup(); + phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK, + ksz9031rn_phy_fixup); + phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff, + ar8031_phy_fixup); + } } static void __init imx6q_sabresd_cko1_setup(void) @@ -192,29 +245,28 @@ static void __init imx6q_1588_init(void) gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); if (!IS_ERR(gpr)) - regmap_update_bits(gpr, 0x4, 1 << 21, 1 << 21); + regmap_update_bits(gpr, IOMUXC_GPR1, + IMX6Q_GPR1_ENET_CLK_SEL_MASK, + IMX6Q_GPR1_ENET_CLK_SEL_ANATOP); else pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n"); } -static void __init imx6q_usb_init(void) -{ - imx_anatop_usb_chrg_detect_disable(); -} static void __init imx6q_init_machine(void) { if (of_machine_is_compatible("fsl,imx6q-sabrelite")) - imx6q_sabrelite_init(); + imx6q_sabrelite_cko1_setup(); else if (of_machine_is_compatible("fsl,imx6q-sabresd") || of_machine_is_compatible("fsl,imx6dl-sabresd")) imx6q_sabresd_init(); + imx6q_enet_phy_init(); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); imx_anatop_init(); imx6q_pm_init(); - imx6q_usb_init(); imx6q_1588_init(); } @@ -297,44 +349,10 @@ static void __init imx6q_map_io(void) imx_scu_map_io(); } -#ifdef CONFIG_CACHE_L2X0 -static void __init imx6q_init_l2cache(void) -{ - void __iomem *l2x0_base; - struct device_node *np; - unsigned int val; - - np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache"); - if (!np) - goto out; - - l2x0_base = of_iomap(np, 0); - if (!l2x0_base) { - of_node_put(np); - goto out; - } - - /* Configure the L2 PREFETCH and POWER registers */ - val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); - val |= 0x70800000; - writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL); - val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN; - writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL); - - iounmap(l2x0_base); - of_node_put(np); - -out: - l2x0_of_init(0, ~0UL); -} -#else -static inline void imx6q_init_l2cache(void) {} -#endif - static void __init imx6q_init_irq(void) { imx6q_init_revision(); - imx6q_init_l2cache(); + imx_init_l2cache(); imx_src_init(); imx_gpc_init(); irqchip_init(); diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c index 132db2609507..0d75dc54f715 100644 --- a/arch/arm/mach-imx/mach-imx6sl.c +++ b/arch/arm/mach-imx/mach-imx6sl.c @@ -11,7 +11,6 @@ #include <linux/irqchip.h> #include <linux/of.h> #include <linux/of_platform.h> -#include <asm/hardware/cache-l2x0.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -26,7 +25,7 @@ static void __init imx6sl_init_machine(void) static void __init imx6sl_init_irq(void) { - l2x0_of_init(0, ~0UL); + imx_init_l2cache(); imx_src_init(); imx_gpc_init(); irqchip_init(); diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c index cf193d87274a..a8229b7f10bf 100644 --- a/arch/arm/mach-imx/mm-imx5.c +++ b/arch/arm/mach-imx/mm-imx5.c @@ -153,10 +153,10 @@ void __init imx51_soc_init(void) void __init imx51_init_late(void) { mx51_neon_fixup(); - imx51_pm_init(); + imx5_pm_init(); } void __init imx53_init_late(void) { - imx53_pm_init(); + imx5_pm_init(); } diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c index 82e79c658eb2..58aeaf5baaf6 100644 --- a/arch/arm/mach-imx/pm-imx5.c +++ b/arch/arm/mach-imx/pm-imx5.c @@ -169,14 +169,9 @@ static int __init imx5_pm_common_init(void) return imx5_cpuidle_init(); } -void __init imx51_pm_init(void) +void __init imx5_pm_init(void) { int ret = imx5_pm_common_init(); if (!ret) suspend_set_ops(&mx5_suspend_ops); } - -void __init imx53_pm_init(void) -{ - imx5_pm_common_init(); -} diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index 6fe81bb4d3c9..64ff37ea72b1 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c @@ -27,6 +27,7 @@ #include <asm/system_misc.h> #include <asm/proc-fns.h> #include <asm/mach-types.h> +#include <asm/hardware/cache-l2x0.h> #include "common.h" #include "hardware.h" @@ -95,3 +96,35 @@ void __init mxc_arch_reset_init_dt(void) clk_prepare(wdog_clk); } + +#ifdef CONFIG_CACHE_L2X0 +void __init imx_init_l2cache(void) +{ + void __iomem *l2x0_base; + struct device_node *np; + unsigned int val; + + np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache"); + if (!np) + goto out; + + l2x0_base = of_iomap(np, 0); + if (!l2x0_base) { + of_node_put(np); + goto out; + } + + /* Configure the L2 PREFETCH and POWER registers */ + val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); + val |= 0x70800000; + writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL); + val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN; + writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL); + + iounmap(l2x0_base); + of_node_put(np); + +out: + l2x0_of_init(0, ~0UL); +} +#endif diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h index 8752dbbc6135..ad05ce60c1c9 100644 --- a/include/linux/micrel_phy.h +++ b/include/linux/micrel_phy.h @@ -17,6 +17,7 @@ #define PHY_ID_KSZ8873MLL 0x000e7237 #define PHY_ID_KSZ9021 0x00221610 +#define PHY_ID_KSZ9021RLRN 0x00221611 #define PHY_ID_KS8737 0x00221720 #define PHY_ID_KSZ8021 0x00221555 #define PHY_ID_KSZ8031 0x00221556 @@ -35,4 +36,9 @@ /* struct phy_device dev_flags definitions */ #define MICREL_PHY_50MHZ_CLK 0x00000001 +#define MICREL_KSZ9021_EXTREG_CTRL 0xB +#define MICREL_KSZ9021_EXTREG_DATA_WRITE 0xC +#define MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW 0x104 +#define MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW 0x105 + #endif /* _MICREL_PHY_H */ |