diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/boot/dts/imx6q-sabrelite.dts | 44 | ||||
-rw-r--r-- | arch/arm/boot/dts/imx6q.dtsi | 12 | ||||
-rw-r--r-- | arch/arm/mach-imx/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/clock-imx6q.c | 78 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6q.c | 55 | ||||
-rw-r--r-- | arch/arm/plat-mxc/audmux-v2.c | 63 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/dma.h | 3 |
7 files changed, 250 insertions, 6 deletions
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index fe2d320275a..40a775cf0da 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -23,6 +23,14 @@ soc { aips-bus@02000000 { /* AIPS1 */ + spba-bus@02000000 { + ssi@0202c000 { /* SSI2 */ + status = "okay"; + fsl,ssi-uses-dma; + fsl,ssi-synchronous-mode; + }; + }; + ldb@020e0000 { disp-pwr-gpios = <&gpio1 0 0>; /* gpio2 0 */ mode = "sin0"; @@ -54,10 +62,26 @@ status = "okay"; }; + audmux@021d8000 { + status = "okay"; + }; + uart2: uart@021e8000 { status = "okay"; }; + i2c@021a0000 { /* I2C1 */ + status = "okay"; + clock-frequency = <100000>; + + codec: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + VDDA-supply = <®_2P5V>; + VDDIO-supply = <®_3P3V>; + }; + }; + i2c@021a4000 { /* I2C2 */ status = "okay"; clock-frequency = <100000>; @@ -140,4 +164,24 @@ compatible = "fsl,vout_ipuv3"; }; }; + + regulators { + compatible = "simple-bus"; + + reg_2P5V: regulator-2P5V { + compatible = "regulator-fixed"; + regulator-name = "2P5V"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + reg_3P3V: regulator-3P3V { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; }; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 8ba41e06a4e..519f60072ea 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -185,18 +185,27 @@ }; ssi@02028000 { /* SSI1 */ + compatible = "fsl,imx6q-ssi", "fsl,imx1-ssi"; reg = <0x02028000 0x4000>; interrupts = <0 46 0x04>; + fsl,dma-events = <38 37>; + status = "disabled"; }; ssi@0202c000 { /* SSI2 */ + compatible = "fsl,imx6q-ssi", "fsl,imx1-ssi"; reg = <0x0202c000 0x4000>; interrupts = <0 47 0x04>; + fsl,dma-events = <42 41>; + status = "disabled"; }; ssi@02030000 { /* SSI3 */ + compatible = "fsl,imx6q-ssi", "fsl,imx1-ssi"; reg = <0x02030000 0x4000>; interrupts = <0 48 0x04>; + fsl,dma-events = <46 45>; + status = "disabled"; }; asrc@02034000 { @@ -422,6 +431,7 @@ compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma"; reg = <0x020ec000 0x4000>; interrupts = <0 2 0x04>; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q-to1.bin"; }; }; @@ -550,7 +560,9 @@ }; audmux@021d8000 { + compatible = "fsl,audmux-v2"; reg = <0x021d8000 0x4000>; + status = "disabled"; }; mipi@021dc000 { /* MIPI-CSI */ diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 3ad09712400..ccb9c440b4a 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -607,6 +607,7 @@ config SOC_IMX6Q select ARM_CPU_SUSPEND if PM select USE_OF select ARCH_MXC_IOMUX_V3 + select ARCH_MXC_AUDMUX_V2 help This enables support for Freescale i.MX6 Quad processor. diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c index b9d59b8e6f0..d85b74d540a 100644 --- a/arch/arm/mach-imx/clock-imx6q.c +++ b/arch/arm/mach-imx/clock-imx6q.c @@ -331,6 +331,12 @@ #define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) #define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) +#define BP_CCOSR_CKO1_EN 7 +#define BP_CCOSR_CKO1_PODF 4 +#define BM_CCOSR_CKO1_PODF (0x7 << 4) +#define BP_CCOSR_CKO1_SEL 0 +#define BM_CCOSR_CKO1_SEL (0xf << 0) + #define FREQ_480M 480000000 #define FREQ_528M 528000000 #define FREQ_594M 594000000 @@ -401,6 +407,7 @@ static struct clk ipu1_di1_clk; static struct clk ipu2_di0_clk; static struct clk ipu2_di1_clk; static struct clk enfc_clk; +static struct clk cko1_clk; static struct clk dummy_clk = {}; static unsigned long external_high_reference; @@ -946,6 +953,24 @@ static void _clk_disable(struct clk *clk) writel_relaxed(reg, clk->enable_reg); } +static int _clk_enable_1b(struct clk *clk) +{ + u32 reg; + reg = readl_relaxed(clk->enable_reg); + reg |= 0x1 << clk->enable_shift; + writel_relaxed(reg, clk->enable_reg); + + return 0; +} + +static void _clk_disable_1b(struct clk *clk) +{ + u32 reg; + reg = readl_relaxed(clk->enable_reg); + reg &= ~(0x1 << clk->enable_shift); + writel_relaxed(reg, clk->enable_reg); +} + struct divider { struct clk *clk; void __iomem *reg; @@ -991,6 +1016,7 @@ DEF_CLK_DIV1(ipu2_di0_pre_div, &ipu2_di0_pre_clk, CSCDR2, IPU2_DI0_PRE); DEF_CLK_DIV1(ipu2_di1_pre_div, &ipu2_di1_pre_clk, CSCDR2, IPU2_DI1_PRE); DEF_CLK_DIV1(ipu1_div, &ipu1_clk, CSCDR3, IPU1_HSP); DEF_CLK_DIV1(ipu2_div, &ipu2_clk, CSCDR3, IPU2_HSP); +DEF_CLK_DIV1(cko1_div, &cko1_clk, CCOSR, CKO1); #define DEF_CLK_DIV2(d, c, r, b) \ static struct divider d = { \ @@ -1046,6 +1072,7 @@ static struct divider *dividers[] = { &enfc_div, &spdif_div, &asrc_serial_div, + &cko1_div, }; static unsigned long ldb_di_clk_get_rate(struct clk *clk) @@ -1633,6 +1660,32 @@ DEF_IPU_DI_MUX(CSCDR2, 2, 1); DEF_IPU_MUX(1); DEF_IPU_MUX(2); +static struct multiplexer cko1_mux = { + .clk = &cko1_clk, + .reg = CCOSR, + .bp = BP_CCOSR_CKO1_SEL, + .bm = BM_CCOSR_CKO1_SEL, + .parents = { + &pll3_usb_otg, + &pll2_bus, + &pll1_sys, + &pll5_video, + &dummy_clk, + &axi_clk, + &enfc_clk, + &ipu1_di0_clk, + &ipu1_di1_clk, + &ipu2_di0_clk, + &ipu2_di1_clk, + &ahb_clk, + &ipg_clk, + &ipg_perclk, + &ckil_clk, + &pll4_audio, + NULL + }, +}; + static struct multiplexer *multiplexers[] = { &axi_mux, &periph_mux, @@ -1675,6 +1728,7 @@ static struct multiplexer *multiplexers[] = { &ipu2_di1_mux, &ipu1_mux, &ipu2_mux, + &cko1_mux, }; static int _clk_set_parent(struct clk *clk, struct clk *parent) @@ -1698,7 +1752,7 @@ static int _clk_set_parent(struct clk *clk, struct clk *parent) break; i++; } - if (!m->parents[i]) + if (!m->parents[i] || m->parents[i] == &dummy_clk) return -EINVAL; val = readl_relaxed(m->reg); @@ -1755,6 +1809,21 @@ DEF_NG_CLK(asrc_serial_clk, &pll3_usb_otg); .secondary = s, \ } +#define DEF_CLK_1B(name, er, es, p, s) \ + static struct clk name = { \ + __INIT_CLK_DEBUG(name) \ + .enable_reg = er, \ + .enable_shift = es, \ + .enable = _clk_enable_1b, \ + .disable = _clk_disable_1b, \ + .get_rate = _clk_get_rate, \ + .set_rate = _clk_set_rate, \ + .round_rate = _clk_round_rate, \ + .set_parent = _clk_set_parent, \ + .parent = p, \ + .secondary = s, \ + } + DEF_CLK(aips_tz1_clk, CCGR0, CG0, &ahb_clk, NULL); DEF_CLK(aips_tz2_clk, CCGR0, CG1, &ahb_clk, NULL); DEF_CLK(apbh_dma_clk, CCGR0, CG2, &ahb_clk, NULL); @@ -1821,7 +1890,8 @@ DEF_CLK(usdhc3_clk, CCGR6, CG3, &pll2_pfd_400m, NULL); DEF_CLK(usdhc4_clk, CCGR6, CG4, &pll2_pfd_400m, NULL); DEF_CLK(emi_slow_clk, CCGR6, CG5, &axi_clk, NULL); DEF_CLK(vdo_axi_clk, CCGR6, CG6, &axi_clk, NULL); -DEF_CLK(vpu_clk, CCGR6, CG7, &axi_clk, NULL); +DEF_CLK(vpu_clk, CCGR6, CG7, &axi_clk, &ocram_clk); +DEF_CLK_1B(cko1_clk, CCOSR, BP_CCOSR_CKO1_EN, &pll2_bus, NULL); static int pcie_clk_enable(struct clk *clk) { @@ -1950,6 +2020,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "ldb_di1_clk", ldb_di1_clk), _REGISTER_CLOCK(NULL, "vpu_clk", vpu_clk), _REGISTER_CLOCK(NULL, "gpt_clk", gpt_clk), + _REGISTER_CLOCK("202c000.ssi", NULL, ssi2_clk), + _REGISTER_CLOCK(NULL, "clko_clk", cko1_clk), }; int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) @@ -2073,6 +2145,8 @@ int __init mx6q_clocks_init(void) clk_set_rate(&usdhc3_clk, 49500000); clk_set_rate(&usdhc4_clk, 49500000); + clk_set_parent(&cko1_clk, &ahb_clk); + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); base = of_iomap(np, 0); WARN_ON(!base); diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 65e0782b202..6a2568b83d5 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -23,6 +23,8 @@ #include <linux/phy.h> #include <linux/micrel_phy.h> #include <linux/dma-mapping.h> +#include <linux/clk.h> +#include <linux/fsl_devices.h> #include <asm/hardware/cache-l2x0.h> #include <asm/hardware/gic.h> #include <asm/mach/map.h> @@ -36,6 +38,12 @@ #include <mach/mxc_vpu.h> static iomux_v3_cfg_t imx6q_sabrelite_pads[] = { + /* AUDMUX */ + MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD, + MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC, + MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD, + MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS, + /* DISPLAY */ MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15, @@ -67,6 +75,11 @@ static iomux_v3_cfg_t imx6q_sabrelite_pads[] = { MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23, /* PWM1 */ MX6Q_PAD_SD1_CMD__PWM4_PWMO, + /* sgtl5000 clock */ + MX6Q_PAD_GPIO_0__CCM_CLKO, + /* I2C1, SGTL5000 */ + MX6Q_PAD_EIM_D21__I2C1_SCL, /* GPIO3[21] */ + MX6Q_PAD_EIM_D28__I2C1_SDA, /* GPIO3[28] */ /* I2C2 */ MX6Q_PAD_KEY_COL3__I2C2_SCL, MX6Q_PAD_KEY_ROW3__I2C2_SDA, @@ -157,6 +170,45 @@ static const struct of_dev_auxdata imx6q_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("fsl,vpu", MX6Q_VPU_BASE_ADDR, "mxc_vpu.0", &vpu_pdata), }; +static struct mxc_audio_platform_data mx6_sabrelite_audio_data; + +static int mx6_sabrelite_sgtl5000_init(void) +{ + struct clk *clko; + int rate; + + clko = clk_get(NULL, "clko_clk"); + if (IS_ERR(clko)) { + pr_err("can't get CLKO clock.\n"); + return PTR_ERR(clko); + } + rate = clk_round_rate(clko, 16000000); + if (rate < 8000000 || rate > 27000000) { + pr_err("Error:SGTL5000 mclk freq %d out of range!\n", rate); + clk_put(clko); + return -1; + } + mx6_sabrelite_audio_data.sysclk = rate; + clk_set_rate(clko, rate); + clk_enable(clko); + return 0; +} + +static struct mxc_audio_platform_data mx6_sabrelite_audio_data = { + .ssi_num = 1, + .src_port = 2, + .ext_port = 4, + .init = mx6_sabrelite_sgtl5000_init, + .hp_gpio = -1, +}; + +static struct platform_device mx6_sabrelite_audio_device = { + .name = "imx-sgtl5000", + .dev = { + .platform_data = &mx6_sabrelite_audio_data, + }, +}; + static void __init imx6q_init_machine(void) { if (of_machine_is_compatible("fsl,imx6q-sabrelite")) { @@ -171,6 +223,9 @@ static void __init imx6q_init_machine(void) iram_init(MX6Q_IRAM_BASE_ADDR, MX6Q_IRAM_SIZE); + if (of_machine_is_compatible("fsl,imx6q-sabrelite")) + platform_device_register(&mx6_sabrelite_audio_device); + imx6q_pm_init(); } diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c index 8cced35009b..73eb555ecb8 100644 --- a/arch/arm/plat-mxc/audmux-v2.c +++ b/arch/arm/plat-mxc/audmux-v2.c @@ -20,7 +20,9 @@ #include <linux/io.h> #include <linux/clk.h> #include <linux/debugfs.h> +#include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/of.h> #include <mach/audmux.h> #include <mach/hardware.h> @@ -184,9 +186,66 @@ int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, } EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port); +#ifdef CONFIG_OF + +static int audmux_v2_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + if (!request_mem_region(res->start, resource_size(res), "audmux_v2")) { + dev_err(&pdev->dev, "request_mem_region failed\n"); + return -EBUSY; + } + + audmux_base = ioremap(res->start, resource_size(res)); + if (!audmux_base) { + dev_err(&pdev->dev, "ioremap failed\n"); + ret = -ENODEV; + goto failed_ioremap; + } + + audmux_clk = clk_get(NULL, "audmux"); + if (IS_ERR(audmux_clk)) { + dev_warn(&pdev->dev, "%s: cannot get clock: %d\n", + __func__, ret); + audmux_clk = NULL; + } + + audmux_debugfs_init(); + return 0; + +failed_ioremap: + release_mem_region(res->start, resource_size(res)); + + return ret; +} + +static const struct of_device_id audmux_v2_dt_ids[] = { + { .compatible = "fsl,audmux-v2", }, + { /* sentinel */ } +}; + +static struct platform_driver audmux_v2_driver = { + .probe = audmux_v2_probe, + .driver = { + .name = "audmux_v2", + .of_match_table = audmux_v2_dt_ids, + }, +}; + +#endif + static int mxc_audmux_v2_init(void) { +#ifdef CONFIG_OF + return platform_driver_register(&audmux_v2_driver); +#else int ret; + if (cpu_is_mx51()) { audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR); } else if (cpu_is_mx31()) { @@ -194,10 +253,9 @@ static int mxc_audmux_v2_init(void) } else if (cpu_is_mx35()) { audmux_clk = clk_get(NULL, "audmux"); if (IS_ERR(audmux_clk)) { - ret = PTR_ERR(audmux_clk); printk(KERN_ERR "%s: cannot get clock: %d\n", __func__, ret); - return ret; + audmux_clk = NULL; } audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR); } else if (cpu_is_mx25()) { @@ -212,6 +270,7 @@ static int mxc_audmux_v2_init(void) } audmux_debugfs_init(); +#endif return 0; } diff --git a/arch/arm/plat-mxc/include/mach/dma.h b/arch/arm/plat-mxc/include/mach/dma.h index dd41a6475be..2003f44fca5 100644 --- a/arch/arm/plat-mxc/include/mach/dma.h +++ b/arch/arm/plat-mxc/include/mach/dma.h @@ -67,8 +67,7 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan) static inline int imx_dma_is_general_purpose(struct dma_chan *chan) { - return !strcmp(dev_name(chan->device->dev), "imx31-sdma") || - !strcmp(dev_name(chan->device->dev), "imx35-sdma") || + return strstr(dev_name(chan->device->dev), "sdma") || !strcmp(dev_name(chan->device->dev), "imx-dma"); } |