/* * Copyright 2013-2014 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 * published by the Free Software Foundation. * */ #include #include #include #include #include #include #include #include "clk.h" #include "common.h" #define CCSR 0xc #define BM_CCSR_PLL1_SW_CLK_SEL (1 << 2) #define CACRR 0x10 #define CDHIPR 0x48 #define BM_CDHIPR_ARM_PODF_BUSY (1 << 16) #define ARM_WAIT_DIV_396M 2 #define ARM_WAIT_DIV_792M 4 #define ARM_WAIT_DIV_996M 6 #define PLL_ARM 0x0 #define BM_PLL_ARM_DIV_SELECT (0x7f << 0) #define BM_PLL_ARM_POWERDOWN (1 << 12) #define BM_PLL_ARM_ENABLE (1 << 13) #define BM_PLL_ARM_LOCK (1 << 31) #define PLL_ARM_DIV_792M 66 static const char *step_sels[] = { "osc", "pll2_pfd2", }; static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; static const char *ocram_alt_sels[] = { "pll2_pfd2", "pll3_pfd1", }; static const char *ocram_sels[] = { "periph", "ocram_alt_sels", }; static const char *pre_periph_sels[] = { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", }; static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy", }; static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", }; static const char *periph_sels[] = { "pre_periph_sel", "periph_clk2_podf", }; static const char *periph2_sels[] = { "pre_periph2_sel", "periph2_clk2_podf", }; static const char *csi_sels[] = { "osc", "pll2_pfd2", "pll3_120m", "pll3_pfd1", }; static const char *lcdif_axi_sels[] = { "pll2_bus", "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", }; static const char *usdhc_sels[] = { "pll2_pfd2", "pll2_pfd0", }; static const char *ssi_sels[] = { "pll3_pfd2", "pll3_pfd3", "pll4_audio_div", "dummy", }; static const char *perclk_sels[] = { "ipg", "osc", }; static const char *pxp_axi_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd3", }; static const char *epdc_axi_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd2", }; static const char *gpu2d_ovg_sels[] = { "pll3_pfd1", "pll3_usb_otg", "pll2_bus", "pll2_pfd2", }; static const char *gpu2d_sels[] = { "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", "pll2_bus", }; static const char *lcdif_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll3_pfd0", "pll3_pfd1", }; static const char *epdc_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", }; static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2", "pll3_pfd3", "pll3_usb_otg", }; static const char *ecspi_sels[] = { "pll3_60m", "osc", }; static const char *uart_sels[] = { "pll3_80m", "osc", }; static const char *lvds_sels[] = { "pll1_sys", "pll2_bus", "pll2_pfd0", "pll2_pfd1", "pll2_pfd2", "dummy", "pll4_audio", "pll5_video", "dummy", "enet_ref", "dummy", "dummy", "pll3_usb_otg", "pll7_usb_host", "pll3_pfd0", "pll3_pfd1", "pll3_pfd2", "pll3_pfd3", "osc", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", }; static const char *pll_bypass_src_sels[] = { "osc", "lvds1_in", }; static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", }; static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", }; static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", }; static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", }; static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", }; static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", }; static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", }; static struct clk_div_table clk_enet_ref_table[] = { { .val = 0, .div = 20, }, { .val = 1, .div = 10, }, { .val = 2, .div = 5, }, { .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, }, { } }; static unsigned int share_count_ssi1; static unsigned int share_count_ssi2; static unsigned int share_count_ssi3; static struct clk *clks[IMX6SL_CLK_END]; static struct clk_onecell_data clk_data; static void __iomem *ccm_base; static void __iomem *anatop_base; static const u32 clks_init_on[] __initconst = { IMX6SL_CLK_IPG, IMX6SL_CLK_ARM, IMX6SL_CLK_MMDC_ROOT, }; /* * ERR005311 CCM: After exit from WAIT mode, unwanted interrupt(s) taken * during WAIT mode entry process could cause cache memory * corruption. * * Software workaround: * To prevent this issue from occurring, software should ensure that the * ARM to IPG clock ratio is less than 12:5 (that is < 2.4x), before * entering WAIT mode. * * This function will set the ARM clk to max value within the 12:5 limit. * As IPG clock is fixed at 66MHz(so ARM freq must not exceed 158.4MHz), * ARM freq are one of below setpoints: 396MHz, 792MHz and 996MHz, since * the clk APIs can NOT be called in idle thread(may cause kernel schedule * as there is sleep function in PLL wait function), so here we just slow * down ARM to below freq according to previous freq: * * run mode wait mode * 396MHz -> 132MHz; * 792MHz -> 158.4MHz; * 996MHz -> 142.3MHz; */ static int imx6sl_get_arm_divider_for_wait(void) { if (readl_relaxed(ccm_base + CCSR) & BM_CCSR_PLL1_SW_CLK_SEL) { return ARM_WAIT_DIV_396M; } else { if ((readl_relaxed(anatop_base + PLL_ARM) & BM_PLL_ARM_DIV_SELECT) == PLL_ARM_DIV_792M) return ARM_WAIT_DIV_792M; else return ARM_WAIT_DIV_996M; } } static void imx6sl_enable_pll_arm(bool enable) { static u32 saved_pll_arm; u32 val; if (enable) { saved_pll_arm = val = readl_relaxed(anatop_base + PLL_ARM); val |= BM_PLL_ARM_ENABLE; val &= ~BM_PLL_ARM_POWERDOWN; writel_relaxed(val, anatop_base + PLL_ARM); while (!(__raw_readl(anatop_base + PLL_ARM) & BM_PLL_ARM_LOCK)) ; } else { writel_relaxed(saved_pll_arm, anatop_base + PLL_ARM); } } void imx6sl_set_wait_clk(bool enter) { static unsigned long saved_arm_div; int arm_div_for_wait = imx6sl_get_arm_divider_for_wait(); /* * According to hardware design, arm podf change need * PLL1 clock enabled. */ if (arm_div_for_wait == ARM_WAIT_DIV_396M) imx6sl_enable_pll_arm(true); if (enter) { saved_arm_div = readl_relaxed(ccm_base + CACRR); writel_relaxed(arm_div_for_wait, ccm_base + CACRR); } else { writel_relaxed(saved_arm_div, ccm_base + CACRR); } while (__raw_readl(ccm_base + CDHIPR) & BM_CDHIPR_ARM_PODF_BUSY) ; if (arm_div_for_wait == ARM_WAIT_DIV_3
.. This work is licensed under a Creative Commons Attribution 4.0 International
.. License.
.. http://creativecommons.org/licenses/by/4.0
.. (c) OPNFV, Huawei Technologies Co.,Ltd and others.

*************************************
Yardstick Test Case Description TC063
*************************************

.. _iostat: http://linux.die.net/man/1/iostat
.. _fdisk: http://www.tldp.org/HOWTO/Partition/fdisk_partitioning.html

+-----------------------------------------------------------------------------+
|Storage Capacity                                                             |
|                                                                             |
+--------------+--------------------------------------------------------------+
|test case id  | OPNFV_YARDSTICK_TC063_Storage Capacity                       |
|              |                                                              |
+--------------+--------------------------------------------------------------+
|metric        | Storage/disk size, block size                                |
|              | Disk Utilization                                             |
+--------------+--------------------------------------------------------------+
|test purpose  | This test case will check the parameters which could decide  |
|              | several models and each model has its specified task to      |
|              | measure. The test purposes are to measure disk size, block   |
|              | size and disk utilization. With the test results, we could   |
|              | evaluate the storage capacity of the host.                   |
|              |                                                              |
+--------------+--------------------------------------------------------------+
|configuration | file: opnfv_yardstick_tc063.yaml                             |
|              |                                                              |
|              |* test_type: "disk_size"                                      |
|              |* runner:                                                     |
|              |    type: Iteration                                           |
|              |    iterations: 1 - test is run 1 time iteratively.           |
|              |                                                              |
+--------------+--------------------------------------------------------------+
|test tool     | fdisk                                                        |
|              | A command-line utility that provides disk partitioning       |
|              | functions                                                    |
|              |                                                              |
|              | iostat                                                       |
|              | This is a computer system monitor tool used to collect and   |
|              | show operating system storage input and output statistics.   |
+--------------+--------------------------------------------------------------+
|references    | iostat_                                                      |
|              | fdisk_                                                       |
|              |                                                              |
|              | ETSI-NFV-TST001                                              |
|              |                                                              |
+--------------+--------------------------------------------------------------+
|applicability | Test can be configured with different:                       |
|              |                                                              |
|              |  * test_type: "disk size", "block size", "disk utilization"  |
|              |  * interval: 1 - how ofter to stat disk utilization          |
|              |       type: int                                              |
|              |       unit: seconds                                          |
|              |  * count: 15 - how many times to stat disk utilization       |
|              |     type: int                                                |
|              |     unit: na                                                 |
|              | There are default values for each above-mentioned option.    |
|              | Run in background with other test cases.                     |
|              |                                                              |
+--------------+--------------------------------------------------------------+
|pre-test      | The test case image needs to be installed into Glance        |
|conditions    |                                                              |
|              | No POD specific requirements have been identified.           |
|              |                                                              |
+--------------+--------------------------------------------------------------+
|test sequence | Output the specific storage capacity of disk information as  |
|              | the sequence into file.                                      |
|              |                                                              |
+--------------+--------------------------------------------------------------+
|step 1        | The pod is available and the hosts are installed. Node5 is   |
|              | used and logs are produced and stored.                       |
|              |                                                              |
|              | Result: Logs are stored.                                     |
|              |                                                              |
+--------------+--------------------------------------------------------------+
|test verdict  | None.                                                        |
+--------------+--------------------------------------------------------------+
("ecspi2", "ecspi_root", base + 0x6c, 2); clks[IMX6SL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4); clks[IMX6SL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6); clks[IMX6SL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10); clks[IMX6SL_CLK_EPIT1] = imx_clk_gate2("epit1", "perclk", base + 0x6c, 12); clks[IMX6SL_CLK_EPIT2] = imx_clk_gate2("epit2", "perclk", base + 0x6c, 14); clks[IMX6SL_CLK_EXTERN_AUDIO] = imx_clk_gate2("extern_audio", "extern_audio_podf", base + 0x6c, 16); clks[IMX6SL_CLK_GPT] = imx_clk_gate2("gpt", "perclk", base + 0x6c, 20); clks[IMX6SL_CLK_GPT_SERIAL] = imx_clk_gate2("gpt_serial", "perclk", base + 0x6c, 22); clks[IMX6SL_CLK_GPU2D_OVG] = imx_clk_gate2("gpu2d_ovg", "gpu2d_ovg_podf", base + 0x6c, 26); clks[IMX6SL_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6); clks[IMX6SL_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8); clks[IMX6SL_CLK_I2C3] = imx_clk_gate2("i2c3", "perclk", base + 0x70, 10); clks[IMX6SL_CLK_OCOTP] = imx_clk_gate2("ocotp", "ipg", base + 0x70, 12); clks[IMX6SL_CLK_CSI] = imx_clk_gate2("csi", "csi_podf", base + 0x74, 0); clks[IMX6SL_CLK_PXP_AXI] = imx_clk_gate2("pxp_axi", "pxp_axi_podf", base + 0x74, 2); clks[IMX6SL_CLK_EPDC_AXI] = imx_clk_gate2("epdc_axi", "epdc_axi_podf", base + 0x74, 4); clks[IMX6SL_CLK_LCDIF_AXI] = imx_clk_gate2("lcdif_axi", "lcdif_axi_podf", base + 0x74, 6); clks[IMX6SL_CLK_LCDIF_PIX] = imx_clk_gate2("lcdif_pix", "lcdif_pix_podf", base + 0x74, 8); clks[IMX6SL_CLK_EPDC_PIX] = imx_clk_gate2("epdc_pix", "epdc_pix_podf", base + 0x74, 10); clks[IMX6SL_CLK_OCRAM] = imx_clk_gate2("ocram", "ocram_podf", base + 0x74, 28); clks[IMX6SL_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16); clks[IMX6SL_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18); clks[IMX6SL_CLK_PWM3] = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20); clks[IMX6SL_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22); clks[IMX6SL_CLK_SDMA] = imx_clk_gate2("sdma", "ipg", base + 0x7c, 6); clks[IMX6SL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); clks[IMX6SL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif0_podf", base + 0x7c, 14); clks[IMX6SL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1); clks[IMX6SL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2); clks[IMX6SL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3); clks[IMX6SL_CLK_SSI1] = imx_clk_gate2_shared("ssi1", "ssi1_podf", base + 0x7c, 18, &share_count_ssi1); clks[IMX6SL_CLK_SSI2] = imx_clk_gate2_shared("ssi2", "ssi2_podf", base + 0x7c, 20, &share_count_ssi2); clks[IMX6SL_CLK_SSI3] = imx_clk_gate2_shared("ssi3", "ssi3_podf", base + 0x7c, 22, &share_count_ssi3); clks[IMX6SL_CLK_UART] = imx_clk_gate2("uart", "ipg", base + 0x7c, 24); clks[IMX6SL_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_root", base + 0x7c, 26); clks[IMX6SL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); clks[IMX6SL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2); clks[IMX6SL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4); clks[IMX6SL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6); clks[IMX6SL_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8); imx_check_clocks(clks, ARRAY_SIZE(clks)); clk_data.clks = clks; clk_data.clk_num = ARRAY_SIZE(clks); of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); /* Ensure the AHB clk is at 132MHz. */ ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000); if (ret) pr_warn("%s: failed to set AHB clock rate %d!\n", __func__, ret); /* * Make sure those always on clocks are enabled to maintain the correct * usecount and enabling/disabling of parent PLLs. */ for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) clk_prepare_enable(clks[clks_init_on[i]]); if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { clk_prepare_enable(clks[IMX6SL_CLK_USBPHY1_GATE]); clk_prepare_enable(clks[IMX6SL_CLK_USBPHY2_GATE]); } /* Audio-related clocks configuration */ clk_set_parent(clks[IMX6SL_CLK_SPDIF0_SEL], clks[IMX6SL_CLK_PLL3_PFD3]); /* set PLL5 video as lcdif pix parent clock */ clk_set_parent(clks[IMX6SL_CLK_LCDIF_PIX_SEL], clks[IMX6SL_CLK_PLL5_VIDEO_DIV]); clk_set_parent(clks[IMX6SL_CLK_LCDIF_AXI_SEL], clks[IMX6SL_CLK_PLL2_PFD2]); /* Set initial power mode */ imx6q_set_lpm(WAIT_CLOCKED); } CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);