diff options
author | Eric Miao <eric.miao@linaro.org> | 2012-01-12 10:29:01 +0800 |
---|---|---|
committer | Eric Miao <eric.miao@linaro.org> | 2012-01-12 10:29:01 +0800 |
commit | f4602255988c23ed729cb9e999c4caf2853142e6 (patch) | |
tree | 18c65e98323127d5fad5e47cdffa305c1f83335f | |
parent | 2cfd89e75ffe516e54c871eca15f55ee5a9520af (diff) | |
parent | 01382574cc0f67e2c9652acacfb141df1eb29f4e (diff) | |
download | imx6-f4602255988c23ed729cb9e999c4caf2853142e6.tar.gz |
Merge branch 'topic/lt-3.2-imx6-audio' into lt-3.2-imx6
* topic/lt-3.2-imx6-audio: (28 commits)
make sgtl5000 work -- need to split to small patch
ENGR00154525 SDMA: SDMA not works when event number bigger than 32
arm/imx6q: add cko1 clock
arm/imx6q: add imx-sgtl5000 device from sabrelite board
fw/imx: add sdma-imx6q-to1.bin.ihex
dts/imx6q: add sdma script
ARM: imx6q-sabrelite: add audmux
ARM: mxc/audmux-v2: add dt support
dma/imx-sdma: let imx6q choose dma driver
dts/imx6q: add ssi
alsa/imx-ssi: rename fsl,ssi-asynchronous-mode to fsl,ssi-synchronous-mode
ASoC: imx-ssi: add device tree probe support
dts/imx6q-sabrelite: add sgtl5000 audio codec
regulator/fixed: set apply_uV 0
dts/imx6q-sabrelite: add 2P5V and 3P3V regulators
regulator: pass device_node to of_get_regulator_init_data()
regulator: If a single voltage is set with device tree then set apply_uV
regulator: Fix regulator_register() API signature in Documentation
regulator: fix label names used in device tree bindings
regulator: Avoid potential NULL dereference in reg_fixed_voltage_probe()
...
62 files changed, 709 insertions, 86 deletions
diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt new file mode 100644 index 00000000000..9cf57fd042d --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt @@ -0,0 +1,29 @@ +Fixed Voltage regulators + +Required properties: +- compatible: Must be "regulator-fixed"; + +Optional properties: +- gpio: gpio to use for enable control +- startup-delay-us: startup time in microseconds +- enable-active-high: Polarity of GPIO is Active high +If this property is missing, the default assumed is Active low. + +Any property defined as part of the core regulator +binding, defined in regulator.txt, can also be used. +However a fixed voltage regulator is expected to have the +regulator-min-microvolt and regulator-max-microvolt +to be the same. + +Example: + + abc: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "fixed-supply"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio1 16 0>; + startup-delay-us = <70000>; + enable-active-high; + regulator-boot-on + }; diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt new file mode 100644 index 00000000000..5b7a408acda --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -0,0 +1,54 @@ +Voltage/Current Regulators + +Optional properties: +- regulator-name: A string used as a descriptive name for regulator outputs +- regulator-min-microvolt: smallest voltage consumers may set +- regulator-max-microvolt: largest voltage consumers may set +- regulator-microvolt-offset: Offset applied to voltages to compensate for voltage drops +- regulator-min-microamp: smallest current consumers may set +- regulator-max-microamp: largest current consumers may set +- regulator-always-on: boolean, regulator should never be disabled +- regulator-boot-on: bootloader/firmware enabled regulator +- <name>-supply: phandle to the parent supply/regulator node + +Example: + + xyzreg: regulator@0 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + vin-supply = <&vin>; + }; + +Regulator Consumers: +Consumer nodes can reference one or more of its supplies/ +regulators using the below bindings. + +- <name>-supply: phandle to the regulator node + +These are the same bindings that a regulator in the above +example used to reference its own supply, in which case +its just seen as a special case of a regulator being a +consumer itself. + +Example of a consumer device node (mmc) referencing two +regulators (twl_reg1 and twl_reg2), + + twl_reg1: regulator@0 { + ... + ... + ... + }; + + twl_reg2: regulator@1 { + ... + ... + ... + }; + + mmc: mmc@0x0 { + ... + ... + vmmc-supply = <&twl_reg1>; + vmmcaux-supply = <&twl_reg2>; + }; diff --git a/Documentation/power/regulator/regulator.txt b/Documentation/power/regulator/regulator.txt index 3f8b528f237..e272d9909e3 100644 --- a/Documentation/power/regulator/regulator.txt +++ b/Documentation/power/regulator/regulator.txt @@ -12,7 +12,7 @@ Drivers can register a regulator by calling :- struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, struct regulator_init_data *init_data, - void *driver_data); + void *driver_data, struct device_node *of_node); This will register the regulators capabilities and operations to the regulator core. 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"); } diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 5a99bb3f255..4c9ef326ad6 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -216,7 +216,7 @@ config PCH_DMA config IMX_SDMA tristate "i.MX SDMA support" - depends on ARCH_MX25 || SOC_IMX31 ||Â SOC_IMX35 || ARCH_MX5 + depends on ARCH_MX25 || SOC_IMX31 ||Â SOC_IMX35 || ARCH_MX5 || SOC_IMX6Q select DMA_ENGINE help Support the i.MX SDMA engine. This engine is integrated into diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index c3d135afe66..248469b051b 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -403,6 +403,7 @@ static int sdma_run_channel(struct sdma_channel *sdmac) init_completion(&sdmac->done); + wmb(); __raw_writel(1 << channel, sdma->regs + SDMA_H_START); ret = wait_for_completion_timeout(&sdmac->done, HZ); @@ -713,11 +714,11 @@ static int sdma_config_channel(struct sdma_channel *sdmac) sdmac->shp_addr = 0; sdmac->per_addr = 0; - if (sdmac->event_id0) { - if (sdmac->event_id0 > 32) - return -EINVAL; + if (sdmac->event_id0) sdma_event_enable(sdmac, sdmac->event_id0); - } + + if (sdmac->event_id1) + sdma_event_enable(sdmac, sdmac->event_id1); switch (sdmac->peripheral_type) { case IMX_DMATYPE_DSP: @@ -739,10 +740,10 @@ static int sdma_config_channel(struct sdma_channel *sdmac) if (sdmac->event_id1) { sdmac->event_mask1 = 1 << (sdmac->event_id1 % 32); if (sdmac->event_id1 > 31) - sdmac->watermark_level |= 1 << 31; + sdmac->watermark_level |= 1 << 29; sdmac->event_mask0 = 1 << (sdmac->event_id0 % 32); if (sdmac->event_id0 > 31) - sdmac->watermark_level |= 1 << 30; + sdmac->watermark_level |= 1 << 28; } else { sdmac->event_mask0 = 1 << sdmac->event_id0; sdmac->event_mask1 = 1 << (sdmac->event_id0 - 32); @@ -809,6 +810,7 @@ out: static void sdma_enable_channel(struct sdma_engine *sdma, int channel) { + wmb(); __raw_writel(1 << channel, sdma->regs + SDMA_H_START); } diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index ca0d608f824..df33530cec4 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -427,7 +427,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) /* replace driver_data with info */ info->regulator = regulator_register(&info->desc, &pdev->dev, - pdata, info); + pdata, info, NULL); if (IS_ERR(info->regulator)) { dev_err(&pdev->dev, "failed to register regulator %s\n", info->desc.name); diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 55d1b5dc3ae..4043b4d98f0 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_REGULATOR) += core.o dummy.o +obj-$(CONFIG_OF) += of_regulator.o obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 298c6c6a279..43b25cc9d84 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -188,7 +188,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev) ri->pdev = pdev; rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri); + pdev->dev.platform_data, ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 585e4946fe0..042271aace6 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -634,7 +634,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) rdev = regulator_register(&ab3100_regulator_desc[i], &pdev->dev, &plfdata->reg_constraints[i], - reg); + reg, NULL); if (IS_ERR(rdev)) { err = PTR_ERR(rdev); diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 6e1ae69646b..e91b8ddc279 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -822,7 +822,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) /* register regulator with framework */ info->regulator = regulator_register(&info->desc, &pdev->dev, - &pdata->regulator[i], info); + &pdata->regulator[i], info, NULL); if (IS_ERR(info->regulator)) { err = PTR_ERR(info->regulator); dev_err(&pdev->dev, "failed to register regulator %s\n", diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index a4be41614ee..483c8093085 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -233,7 +233,7 @@ static int __devinit ad5398_probe(struct i2c_client *client, chip->current_mask = (chip->current_level - 1) << chip->current_offset; chip->rdev = regulator_register(&ad5398_reg, &client->dev, - init_data, chip); + init_data, chip, NULL); if (IS_ERR(chip->rdev)) { ret = PTR_ERR(chip->rdev); dev_err(&client->dev, "failed to register %s %s\n", diff --git a/drivers/regulator/bq24022.c b/drivers/regulator/bq24022.c index e24d1b7d97a..9fab6d1bbe8 100644 --- a/drivers/regulator/bq24022.c +++ b/drivers/regulator/bq24022.c @@ -107,7 +107,7 @@ static int __init bq24022_probe(struct platform_device *pdev) ret = gpio_direction_output(pdata->gpio_nce, 1); bq24022 = regulator_register(&bq24022_desc, &pdev->dev, - pdata->init_data, pdata); + pdata->init_data, pdata, NULL); if (IS_ERR(bq24022)) { dev_dbg(&pdev->dev, "couldn't register regulator\n"); ret = PTR_ERR(bq24022); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 938398f3e86..5baa1965aa1 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -25,6 +25,8 @@ #include <linux/mutex.h> #include <linux/suspend.h> #include <linux/delay.h> +#include <linux/of.h> +#include <linux/regulator/of_regulator.h> #include <linux/regulator/consumer.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> @@ -132,6 +134,33 @@ static struct regulator *get_device_regulator(struct device *dev) return NULL; } +/** + * of_get_regulator - get a regulator device node based on supply name + * @dev: Device pointer for the consumer (of regulator) device + * @supply: regulator supply name + * + * Extract the regulator device node corresponding to the supply name. + * retruns the device node corresponding to the regulator if found, else + * returns NULL. + */ +static struct device_node *of_get_regulator(struct device *dev, const char *supply) +{ + struct device_node *regnode = NULL; + char prop_name[32]; /* 32 is max size of property name */ + + dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); + + snprintf(prop_name, 32, "%s-supply", supply); + regnode = of_parse_phandle(dev->of_node, prop_name, 0); + + if (!regnode) { + dev_warn(dev, "%s property in node %s references invalid phandle", + prop_name, dev->of_node->full_name); + return NULL; + } + return regnode; +} + /* Platform voltage constraint check */ static int regulator_check_voltage(struct regulator_dev *rdev, int *min_uV, int *max_uV) @@ -1148,6 +1177,30 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev) return rdev->desc->ops->enable_time(rdev); } +static struct regulator_dev *regulator_dev_lookup(struct device *dev, + const char *supply) +{ + struct regulator_dev *r; + struct device_node *node; + + /* first do a dt based lookup */ + if (dev && dev->of_node) { + node = of_get_regulator(dev, supply); + if (node) + list_for_each_entry(r, ®ulator_list, list) + if (r->dev.parent && + node == r->dev.of_node) + return r; + } + + /* if not found, try doing it non-dt way */ + list_for_each_entry(r, ®ulator_list, list) + if (strcmp(rdev_get_name(r), supply) == 0) + return r; + + return NULL; +} + /* Internal regulator request function */ static struct regulator *_regulator_get(struct device *dev, const char *id, int exclusive) @@ -1168,6 +1221,10 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, mutex_lock(®ulator_list_mutex); + rdev = regulator_dev_lookup(dev, id); + if (rdev) + goto found; + list_for_each_entry(map, ®ulator_map_list, list) { /* If the mapping has a device set up it must match */ if (map->dev_name && @@ -2637,11 +2694,12 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) */ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, const struct regulator_init_data *init_data, - void *driver_data) + void *driver_data, struct device_node *of_node) { static atomic_t regulator_no = ATOMIC_INIT(0); struct regulator_dev *rdev; int ret, i; + const char *supply = NULL; if (regulator_desc == NULL) return ERR_PTR(-EINVAL); @@ -2696,6 +2754,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, /* register with sysfs */ rdev->dev.class = ®ulator_class; + rdev->dev.of_node = of_node; rdev->dev.parent = dev; dev_set_name(&rdev->dev, "regulator.%d", atomic_inc_return(®ulator_no) - 1); @@ -2717,21 +2776,18 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, if (ret < 0) goto scrub; - if (init_data->supply_regulator) { + if (init_data->supply_regulator) + supply = init_data->supply_regulator; + else if (regulator_desc->supply_name) + supply = regulator_desc->supply_name; + + if (supply) { struct regulator_dev *r; - int found = 0; - list_for_each_entry(r, ®ulator_list, list) { - if (strcmp(rdev_get_name(r), - init_data->supply_regulator) == 0) { - found = 1; - break; - } - } + r = regulator_dev_lookup(dev, supply); - if (!found) { - dev_err(dev, "Failed to find supply %s\n", - init_data->supply_regulator); + if (!r) { + dev_err(dev, "Failed to find supply %s\n", supply); ret = -ENODEV; goto scrub; } diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index e23ddfa8b2c..8dbc54da7d7 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -537,7 +537,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev) ri->desc.ops = &da9030_regulator_ldo1_15_ops; rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri); + pdev->dev.platform_data, ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 78329751af5..515443fcd26 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -486,7 +486,7 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev) /* register with the regulator framework */ info->rdev = regulator_register(&info->desc, &pdev->dev, - init_data, info); + init_data, info, NULL); if (IS_ERR(info->rdev)) { err = PTR_ERR(info->rdev); dev_err(&pdev->dev, "failed to register %s: err %i\n", diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c index b8f520513ce..0ee00de4be7 100644 --- a/drivers/regulator/dummy.c +++ b/drivers/regulator/dummy.c @@ -42,7 +42,7 @@ static int __devinit dummy_regulator_probe(struct platform_device *pdev) int ret; dummy_regulator_rdev = regulator_register(&dummy_desc, NULL, - &dummy_initdata, NULL); + &dummy_initdata, NULL, NULL); if (IS_ERR(dummy_regulator_rdev)) { ret = PTR_ERR(dummy_regulator_rdev); pr_err("Failed to register regulator: %d\n", ret); diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 21ecf212a52..eedc9939632 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -27,6 +27,10 @@ #include <linux/gpio.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/regulator/of_regulator.h> +#include <linux/regulator/machine.h> struct fixed_voltage_data { struct regulator_desc desc; @@ -38,6 +42,58 @@ struct fixed_voltage_data { bool is_enabled; }; + +/** + * of_get_fixed_voltage_config - extract fixed_voltage_config structure info + * @dev: device requesting for fixed_voltage_config + * + * Populates fixed_voltage_config structure by extracting data from device + * tree node, returns a pointer to the populated structure of NULL if memory + * alloc fails. + */ +static struct fixed_voltage_config * +of_get_fixed_voltage_config(struct device *dev) +{ + struct fixed_voltage_config *config; + struct device_node *np = dev->of_node; + const __be32 *delay; + struct regulator_init_data *init_data; + + config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config), + GFP_KERNEL); + if (!config) + return NULL; + + config->init_data = of_get_regulator_init_data(dev, dev->of_node); + if (!config->init_data) + return NULL; + + init_data = config->init_data; + init_data->constraints.apply_uV = 0; + + config->supply_name = init_data->constraints.name; + if (init_data->constraints.min_uV == init_data->constraints.max_uV) { + config->microvolts = init_data->constraints.min_uV; + } else { + dev_err(dev, + "Fixed regulator specified with variable voltages\n"); + return NULL; + } + + if (init_data->constraints.boot_on) + config->enabled_at_boot = true; + + config->gpio = of_get_named_gpio(np, "gpio", 0); + delay = of_get_property(np, "startup-delay-us", NULL); + if (delay) + config->startup_delay = be32_to_cpu(*delay); + + if (of_find_property(np, "enable-active-high", NULL)) + config->enable_high = true; + + return config; +} + static int fixed_voltage_is_enabled(struct regulator_dev *dev) { struct fixed_voltage_data *data = rdev_get_drvdata(dev); @@ -105,10 +161,18 @@ static struct regulator_ops fixed_voltage_ops = { static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) { - struct fixed_voltage_config *config = pdev->dev.platform_data; + struct fixed_voltage_config *config; struct fixed_voltage_data *drvdata; int ret; + if (pdev->dev.of_node) + config = of_get_fixed_voltage_config(&pdev->dev); + else + config = pdev->dev.platform_data; + + if (!config) + return -ENOMEM; + drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL); if (drvdata == NULL) { dev_err(&pdev->dev, "Failed to allocate device data\n"); @@ -180,7 +244,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) } drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, - config->init_data, drvdata); + config->init_data, drvdata, pdev->dev.of_node); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); @@ -217,12 +281,23 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id fixed_of_match[] __devinitconst = { + { .compatible = "regulator-fixed", }, + {}, +}; +MODULE_DEVICE_TABLE(of, fixed_of_match); +#else +#define fixed_of_match NULL +#endif + static struct platform_driver regulator_fixed_voltage_driver = { .probe = reg_fixed_voltage_probe, .remove = __devexit_p(reg_fixed_voltage_remove), .driver = { .name = "reg-fixed-voltage", .owner = THIS_MODULE, + .of_match_table = fixed_of_match, }, }; diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index f0acf52498b..42e1cb1835e 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -284,7 +284,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) drvdata->state = state; drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, - config->init_data, drvdata); + config->init_data, drvdata, NULL); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index e4b3592e817..c1a456c4257 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -170,7 +170,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, for (i = 0; i < 3; i++) { pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev, - init_data, pmic); + init_data, pmic, NULL); if (IS_ERR(pmic->rdev[i])) { dev_err(&i2c->dev, "failed to register %s\n", id->name); err = PTR_ERR(pmic->rdev[i]); diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 72b16b5f3db..0cfabd318a5 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -451,7 +451,7 @@ static int __devinit setup_regulators(struct lp3971 *lp3971, for (i = 0; i < pdata->num_regulators; i++) { struct lp3971_regulator_subdev *reg = &pdata->regulators[i]; lp3971->rdev[i] = regulator_register(®ulators[reg->id], - lp3971->dev, reg->initdata, lp3971); + lp3971->dev, reg->initdata, lp3971, NULL); if (IS_ERR(lp3971->rdev[i])) { err = PTR_ERR(lp3971->rdev[i]); diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index fbc5e3741be..49a15eefe5f 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -555,7 +555,7 @@ static int __devinit setup_regulators(struct lp3972 *lp3972, for (i = 0; i < pdata->num_regulators; i++) { struct lp3972_regulator_subdev *reg = &pdata->regulators[i]; lp3972->rdev[i] = regulator_register(®ulators[reg->id], - lp3972->dev, reg->initdata, lp3972); + lp3972->dev, reg->initdata, lp3972, NULL); if (IS_ERR(lp3972->rdev[i])) { err = PTR_ERR(lp3972->rdev[i]); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 3f49512c513..40e7a4db285 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -214,7 +214,7 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client, } rdev[i] = regulator_register(&max1586_reg[id], &client->dev, pdata->subdevs[i].platform_data, - max1586); + max1586, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(&client->dev, "failed to register %s\n", diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 1062cf9f02d..524a5da23c7 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -347,7 +347,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, } info->regulator = regulator_register(&dcdc_desc, &client->dev, - pdata->regulator, info); + pdata->regulator, info, NULL); if (IS_ERR(info->regulator)) { dev_err(info->dev, "failed to register regulator %s\n", dcdc_desc.name); diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 33f5d9a492e..a838e664569 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -449,7 +449,7 @@ static int __devinit max8660_probe(struct i2c_client *client, rdev[i] = regulator_register(&max8660_reg[id], &client->dev, pdata->subdevs[i].platform_data, - max8660); + max8660, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(&client->dev, "failed to register %s\n", diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index cc9ec0e0327..f976e5d0867 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -266,7 +266,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev) ri->chip = chip; rdev = regulator_register(&ri->desc, &pdev->dev, - pdata->regulator[pdev->id], ri); + pdata->regulator[pdev->id], ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 3883d85c5b8..75d89400c12 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -208,7 +208,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, max8952->pdata = pdata; max8952->rdev = regulator_register(®ulator, max8952->dev, - &pdata->reg_data, max8952); + &pdata->reg_data, max8952, NULL); if (IS_ERR(max8952->rdev)) { ret = PTR_ERR(max8952->rdev); diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 6176129a27e..d26e8646277 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -1146,7 +1146,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) regulators[id].n_voltages = 16; rdev[i] = regulator_register(®ulators[id], max8997->dev, - pdata->regulators[i].initdata, max8997); + pdata->regulators[i].initdata, max8997, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(max8997->dev, "regulator init failed for %d\n", diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 41a1495eec2..2d38c2493a0 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -847,7 +847,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) regulators[index].n_voltages = count; } rdev[i] = regulator_register(®ulators[index], max8998->dev, - pdata->regulators[i].initdata, max8998); + pdata->regulators[i].initdata, max8998, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(max8998->dev, "regulator init failed\n"); diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 8479082e1ae..56d4a677c40 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -357,7 +357,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) init_data = &pdata->regulators[i]; priv->regulators[i] = regulator_register( &mc13783_regulators[init_data->id].desc, - &pdev->dev, init_data->init_data, priv); + &pdev->dev, init_data->init_data, priv, NULL); if (IS_ERR(priv->regulators[i])) { dev_err(&pdev->dev, "failed to register regulator %s\n", diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 023d17d022c..2824804a289 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -573,7 +573,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) init_data = &pdata->regulators[i]; priv->regulators[i] = regulator_register( &mc13892_regulators[init_data->id].desc, - &pdev->dev, init_data->init_data, priv); + &pdev->dev, init_data->init_data, priv, NULL); if (IS_ERR(priv->regulators[i])) { dev_err(&pdev->dev, "failed to register regulator %s\n", diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c new file mode 100644 index 00000000000..f1651eb6964 --- /dev/null +++ b/drivers/regulator/of_regulator.c @@ -0,0 +1,87 @@ +/* + * OF helpers for regulator framework + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Rajendra Nayak <rnayak@ti.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/regulator/machine.h> + +static void of_get_regulation_constraints(struct device_node *np, + struct regulator_init_data **init_data) +{ + const __be32 *min_uV, *max_uV, *uV_offset; + const __be32 *min_uA, *max_uA; + struct regulation_constraints *constraints = &(*init_data)->constraints; + + constraints->name = of_get_property(np, "regulator-name", NULL); + + min_uV = of_get_property(np, "regulator-min-microvolt", NULL); + if (min_uV) + constraints->min_uV = be32_to_cpu(*min_uV); + max_uV = of_get_property(np, "regulator-max-microvolt", NULL); + if (max_uV) + constraints->max_uV = be32_to_cpu(*max_uV); + + /* Voltage change possible? */ + if (constraints->min_uV != constraints->max_uV) + constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; + /* Only one voltage? Then make sure it's set. */ + if (constraints->min_uV == constraints->max_uV) + constraints->apply_uV = true; + + uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); + if (uV_offset) + constraints->uV_offset = be32_to_cpu(*uV_offset); + min_uA = of_get_property(np, "regulator-min-microamp", NULL); + if (min_uA) + constraints->min_uA = be32_to_cpu(*min_uA); + max_uA = of_get_property(np, "regulator-max-microamp", NULL); + if (max_uA) + constraints->max_uA = be32_to_cpu(*max_uA); + + /* Current change possible? */ + if (constraints->min_uA != constraints->max_uA) + constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; + + if (of_find_property(np, "regulator-boot-on", NULL)) + constraints->boot_on = true; + + if (of_find_property(np, "regulator-always-on", NULL)) + constraints->always_on = true; + else /* status change should be possible if not always on. */ + constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; +} + +/** + * of_get_regulator_init_data - extract regulator_init_data structure info + * @dev: device requesting for regulator_init_data + * + * Populates regulator_init_data structure by extracting data from device + * tree node, returns a pointer to the populated struture or NULL if memory + * alloc fails. + */ +struct regulator_init_data *of_get_regulator_init_data(struct device *dev, + struct device_node *node) +{ + struct regulator_init_data *init_data; + + if (!node) + return NULL; + + init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); + if (!init_data) + return NULL; /* Out of memory? */ + + of_get_regulation_constraints(node, &init_data); + return init_data; +} +EXPORT_SYMBOL_GPL(of_get_regulator_init_data); diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index 31f6e11a7f1..a5aab1b08bc 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -277,7 +277,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev) void *pcap = dev_get_drvdata(pdev->dev.parent); rdev = regulator_register(&pcap_regulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, pcap); + pdev->dev.platform_data, pcap, NULL); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 69a11d9dd87..1d1c3105629 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -320,7 +320,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) pcf = dev_to_pcf50633(pdev->dev.parent); rdev = regulator_register(®ulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, pcf); + pdev->dev.platform_data, pcf, NULL); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index 1011873896d..d9278da18a9 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -151,7 +151,8 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) /* Register regulator with framework */ tps6105x->regulator = regulator_register(&tps6105x_regulator_desc, &tps6105x->client->dev, - pdata->regulator_data, tps6105x); + pdata->regulator_data, tps6105x, + NULL); if (IS_ERR(tps6105x->regulator)) { ret = PTR_ERR(tps6105x->regulator); dev_err(&tps6105x->client->dev, diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 9fb4c7b8175..7fd3b9092d1 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -496,7 +496,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client, /* Register the regulators */ rdev = regulator_register(&tps->desc[i], &client->dev, - init_data, tps); + init_data, tps, NULL); if (IS_ERR(rdev)) { dev_err(&client->dev, "failed to register %s\n", id->name); diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index bdef70365f5..0b63ef71a5f 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -599,7 +599,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev) tps->desc[i].owner = THIS_MODULE; rdev = regulator_register(&tps->desc[i], - tps6507x_dev->dev, init_data, tps); + tps6507x_dev->dev, init_data, tps, NULL); if (IS_ERR(rdev)) { dev_err(tps6507x_dev->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 9166aa0a9df..70b7b1f4f00 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -651,7 +651,7 @@ static int __devinit pmic_probe(struct spi_device *spi) hw->desc[i].n_voltages = 1; hw->rdev[i] = regulator_register(&hw->desc[i], dev, - init_data, hw); + init_data, hw, NULL); if (IS_ERR(hw->rdev[i])) { ret = PTR_ERR(hw->rdev[i]); hw->rdev[i] = NULL; diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 14b9389dd52..c75fb20faa5 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -396,7 +396,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) return err; rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri); + pdev->dev.platform_data, ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index b552aae55b4..654bc5bab9a 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -965,7 +965,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) pmic->desc[i].owner = THIS_MODULE; rdev = regulator_register(&pmic->desc[i], - tps65910->dev, reg_data, pmic); + tps65910->dev, reg_data, pmic, NULL); if (IS_ERR(rdev)) { dev_err(tps65910->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 39d4a1749e7..da00d88f94b 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -727,7 +727,7 @@ static __devinit int tps65912_probe(struct platform_device *pdev) pmic->desc[i].owner = THIS_MODULE; range = tps65912_get_range(pmic, i); rdev = regulator_register(&pmic->desc[i], - tps65912->dev, reg_data, pmic); + tps65912->dev, reg_data, pmic, NULL); if (IS_ERR(rdev)) { dev_err(tps65912->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 11cc308d66e..181a2cfe180 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1112,7 +1112,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) break; } - rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); + rdev = regulator_register(&info->desc, &pdev->dev, initdata, info, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index bd3531d8b2a..7558a9666a5 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -553,7 +553,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data); dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + pdata->dcdc[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -747,7 +747,7 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) dcdc->desc.owner = THIS_MODULE; dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + pdata->dcdc[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -874,7 +874,7 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) dcdc->desc.owner = THIS_MODULE; dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + pdata->dcdc[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -973,7 +973,7 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) dcdc->desc.owner = THIS_MODULE; dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->epe[id], dcdc); + pdata->epe[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register EPE%d: %d\n", diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index 01f27c7f423..d3ad3f5cff4 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -189,7 +189,7 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev) isink->desc.owner = THIS_MODULE; isink->regulator = regulator_register(&isink->desc, &pdev->dev, - pdata->isink[id], isink); + pdata->isink[id], isink, NULL); if (IS_ERR(isink->regulator)) { ret = PTR_ERR(isink->regulator); dev_err(wm831x->dev, "Failed to register ISINK%d: %d\n", diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 6709710a059..5e96a2386b1 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -351,7 +351,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo); + pdata->ldo[id], ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", @@ -621,7 +621,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo); + pdata->ldo[id], ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", @@ -818,7 +818,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo); + pdata->ldo[id], ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 1bcb22c4409..6894009d815 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1428,7 +1428,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev) /* register regulator */ rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev, pdev->dev.platform_data, - dev_get_drvdata(&pdev->dev)); + dev_get_drvdata(&pdev->dev), NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register %s\n", wm8350_reg[pdev->id].name); diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 71632ddc378..706f39563a7 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -326,7 +326,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev) struct regulator_dev *rdev; rdev = regulator_register(®ulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, wm8400); + pdev->dev.platform_data, wm8400, NULL); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index b87bf5c841f..435e335d6e6 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -269,7 +269,7 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) ldo->is_enabled = true; ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev, - pdata->ldo[id].init_data, ldo); + pdata->ldo[id].init_data, ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm8994->dev, "Failed to register LDO%d: %d\n", diff --git a/firmware/Makefile b/firmware/Makefile index 66d0e990285..fdfc88ced67 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -146,6 +146,7 @@ ifdef CONFIG_IMX_SDMA fw-shipped-$(CONFIG_SOC_IMX50) += imx/sdma/sdma-imx50-to1.bin fw-shipped-$(CONFIG_SOC_IMX51) += imx/sdma/sdma-imx51-to3.bin fw-shipped-$(CONFIG_SOC_IMX53) += imx/sdma/sdma-imx53-to1.bin +fw-shipped-$(CONFIG_SOC_IMX6Q) += imx/sdma/sdma-imx6q-to1.bin endif fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-) diff --git a/firmware/imx/sdma/sdma-imx6q-to1.bin b/firmware/imx/sdma/sdma-imx6q-to1.bin Binary files differnew file mode 100644 index 00000000000..d20b897c75b --- /dev/null +++ b/firmware/imx/sdma/sdma-imx6q-to1.bin diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 52c89ae32f6..4214b9a9d1c 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -154,6 +154,7 @@ enum regulator_type { * this type. * * @name: Identifying name for the regulator. + * @supply_name: Identifying the regulator supply * @id: Numerical identifier for the regulator. * @n_voltages: Number of selectors available for ops.list_voltage(). * @ops: Regulator operations table. @@ -163,6 +164,7 @@ enum regulator_type { */ struct regulator_desc { const char *name; + const char *supply_name; int id; unsigned n_voltages; struct regulator_ops *ops; @@ -212,7 +214,7 @@ struct regulator_dev { struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, const struct regulator_init_data *init_data, - void *driver_data); + void *driver_data, struct device_node *of_node); void regulator_unregister(struct regulator_dev *rdev); int regulator_notifier_call_chain(struct regulator_dev *rdev, diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h new file mode 100644 index 00000000000..769704f296e --- /dev/null +++ b/include/linux/regulator/of_regulator.h @@ -0,0 +1,22 @@ +/* + * OpenFirmware regulator support routines + * + */ + +#ifndef __LINUX_OF_REG_H +#define __LINUX_OF_REG_H + +#if defined(CONFIG_OF) +extern struct regulator_init_data + *of_get_regulator_init_data(struct device *dev, + struct device_node *node); +#else +static inline struct regulator_init_data + *of_get_regulator_init_data(struct device *dev, + struct device_node *node) +{ + return NULL; +} +#endif /* CONFIG_OF */ + +#endif /* __LINUX_OF_REG_H */ diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index cb9818c5830..690193d439b 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -841,7 +841,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec, ldo->voltage = voltage; ldo->dev = regulator_register(&ldo->desc, codec->dev, - init_data, ldo); + init_data, ldo, NULL); if (IS_ERR(ldo->dev)) { int ret = PTR_ERR(ldo->dev); diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 7ffeed2d351..32f0af77869 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -49,7 +49,7 @@ config SND_SOC_PHYCORE_AC97 config SND_SOC_IMX_SGTL5000 tristate "SoC Audio support for i.MX boards with sgtl5000" - depends on MACH_MX35_3DS || MACH_MX51_BABBAGE || MACH_MX53_LOCO + depends on MACH_MX35_3DS || MACH_MX51_BABBAGE || MACH_MX53_LOCO || SOC_IMX6Q select SND_SOC_SGTL5000 select SND_MXC_SOC_MX2 help diff --git a/sound/soc/imx/imx-sgtl5000.c b/sound/soc/imx/imx-sgtl5000.c index 0ff8ee00b3c..2b025631779 100644 --- a/sound/soc/imx/imx-sgtl5000.c +++ b/sound/soc/imx/imx-sgtl5000.c @@ -275,9 +275,9 @@ static struct snd_soc_dai_link imx_sgtl5000_dai[] = { .name = "HiFi", .stream_name = "HiFi", .codec_dai_name = "sgtl5000", - .codec_name = "sgtl5000.1-000a", - .cpu_dai_name = "imx-ssi.1", - .platform_name = "imx-pcm-audio.1", + .codec_name = "sgtl5000.0-000a", + .cpu_dai_name = "202c000.ssi", + .platform_name = "imx-pcm-audio", .init = imx_3stack_sgtl5000_init, .ops = &imx_sgtl5000_hifi_ops, }, @@ -361,7 +361,7 @@ static int __init imx_sgtl5000_init(void) if (ret) return -ENOMEM; - if (machine_is_mx35_3ds()) + if (machine_is_mx35_3ds() || of_machine_is_compatible("fsl,imx6q-sabrelite")) imx_sgtl5000_dai[0].codec_name = "sgtl5000.0-000a"; else imx_sgtl5000_dai[0].codec_name = "sgtl5000.1-000a"; diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 563d197e37d..a58440a2345 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -40,6 +40,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/of.h> #include <sound/core.h> #include <sound/initval.h> @@ -54,6 +55,11 @@ #define SSI_SACNT_DEFAULT (SSI_SACNT_AC97EN | SSI_SACNT_FV) +static const struct of_device_id imx_ssi_dt_ids[] = { + { .compatible = "fsl,imx1-ssi", }, + { /* sentinel */ } +}; + /* * SSI Network Mode or TDM slots configuration. * Should only be called when port is inactive (i.e. SSIEN = 0). @@ -603,11 +609,45 @@ struct snd_ac97_bus_ops soc_ac97_ops = { }; EXPORT_SYMBOL_GPL(soc_ac97_ops); +#ifdef CONFIG_OF +static int imx_ssi_probe_dt(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct imx_ssi *ssi = platform_get_drvdata(pdev); + + if (!np) + return -ENODEV; + + if (of_get_property(np, "fsl,ssi-uses-dma", NULL)) + ssi->flags |= IMX_SSI_DMA; + + if (of_get_property(np, "fsl,ssi-synchronous-mode", NULL)) + ssi->flags |= IMX_SSI_SYN; + + if (of_get_property(np, "fsl,ssi-network-mode", NULL)) + ssi->flags |= IMX_SSI_NET; + + if (of_get_property(np, "fsl,ssi-as-ac97", NULL)) + ssi->flags |= IMX_SSI_USE_AC97; + + if (of_get_property(np, "fsl,ssi-as-i2s-slave", NULL)) + ssi->flags |= IMX_SSI_USE_I2S_SLAVE; + + return 0; +} +#else +static inline int imx_ssi_probe_dt(struct platform_device *pdev) +{ + return -ENODEV; +} +#endif + static int imx_ssi_probe(struct platform_device *pdev) { struct resource *res; struct imx_ssi *ssi; struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; + int dma_events[2]; int ret = 0; struct snd_soc_dai_driver *dai; @@ -616,7 +656,8 @@ static int imx_ssi_probe(struct platform_device *pdev) return -ENOMEM; dev_set_drvdata(&pdev->dev, ssi); - if (pdata) { + ret = imx_ssi_probe_dt(pdev); + if (ret < 0 && pdata) { ssi->ac97_reset = pdata->ac97_reset; ssi->ac97_warm_reset = pdata->ac97_warm_reset; ssi->flags = pdata->flags; @@ -673,13 +714,20 @@ static int imx_ssi_probe(struct platform_device *pdev) ssi->dma_params_tx.peripheral_type = IMX_DMATYPE_SSI_SP; ssi->dma_params_rx.peripheral_type = IMX_DMATYPE_SSI_SP; - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); - if (res) - ssi->dma_params_tx.dma = res->start; + ret = of_property_read_u32_array(pdev->dev.of_node, "fsl,dma-events", + dma_events, ARRAY_SIZE(dma_events)); + if (ret < 0) { + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); + if (res) + ssi->dma_params_tx.dma = res->start; - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); - if (res) - ssi->dma_params_rx.dma = res->start; + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); + if (res) + ssi->dma_params_rx.dma = res->start; + } else { + ssi->dma_params_tx.dma = dma_events[0]; + ssi->dma_params_rx.dma = dma_events[1]; + } platform_set_drvdata(pdev, ssi); @@ -768,6 +816,7 @@ static struct platform_driver imx_ssi_driver = { .driver = { .name = "imx-ssi", .owner = THIS_MODULE, + .of_match_table = imx_ssi_dt_ids, }, }; |