[PATCH 11/11] ARM: dts: imx6q-sabrelite: add sound device imx6q-sabrelite-sgtl5000
From: Richard Zhao Signed-off-by: Richard Zhao Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q-sabrelite.dts | 13 + 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index cdae2dd..20aa767 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -97,4 +97,17 @@ regulator-always-on; }; }; + + sound { + compatible = "fsl,imx6q-sabrelite-sgtl5000", +"fsl,imx-audio-sgtl5000"; + model = "imx6q-sabrelite-sgtl5000"; + ssi-controller = <&ssi1>; + audio-codec = <&codec>; + audio-routing = + "MIC_IN", "Mic Jack", + "Headphone Jack", "HP_OUT"; + mux-int-port = <1>; + mux-ext-port = <4>; + }; }; -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/11] ARM: imx6q_sabrelite: clkdev_add cko1 for sgtl5000
Signed-off-by: Richard Zhao --- arch/arm/mach-imx/clk-imx6q.c |3 +++ arch/arm/mach-imx/mach-imx6q.c | 28 2 files changed, 31 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 9a03dcc..4ea0de0 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -419,6 +419,9 @@ int __init mx6q_clocks_init(void) clk_register_clkdev(clk[dummy], NULL, "20bc000.wdog"); clk_register_clkdev(clk[dummy], NULL, "20c.wdog"); clk_register_clkdev(clk[ssi1], NULL, "2028000.ssi"); + clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL); + clk_register_clkdev(clk[ahb], "ahb", NULL); + clk_register_clkdev(clk[cko1], "cko1", NULL); for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) { c = clk_get_sys(clks_init_on[i], NULL); diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index d25c5d8..e9b2522 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -10,6 +10,8 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include +#include #include #include #include @@ -75,10 +77,36 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev) return 0; } +static void __init imx6q_cko1_setup(void) +{ + struct clk *cko1_sel, *ahb, *cko1; + unsigned long rate; + + cko1_sel = clk_get_sys(NULL, "cko1_sel"); + ahb = clk_get_sys(NULL, "ahb"); + cko1 = clk_get_sys(NULL, "cko1"); + if (IS_ERR(cko1_sel) || IS_ERR(ahb) || IS_ERR(cko1)) { + printk(KERN_ERR "cko1 setup failed!\n"); + goto put_clk; + } + clk_set_parent(cko1_sel, ahb); + rate = clk_round_rate(cko1, 1600); + clk_set_rate(cko1, rate); + clk_register_clkdev(cko1, NULL, "0-000a"); +put_clk: + if (!IS_ERR(cko1_sel)) + clk_put(cko1_sel); + if (!IS_ERR(ahb)) + clk_put(ahb); + if (!IS_ERR(cko1)) + clk_put(cko1); +} + static void __init imx6q_sabrelite_init(void) { phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, ksz9021rn_phy_fixup); + imx6q_cko1_setup(); } static void __init imx6q_init_machine(void) -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/11] ARM: imx6q: add ssi1 clk_lookup
It's used by audio drivers. Signed-off-by: Richard Zhao --- arch/arm/mach-imx/clk-imx6q.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index f40a35d..9a03dcc 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -418,6 +418,7 @@ int __init mx6q_clocks_init(void) clk_register_clkdev(clk[sdma], NULL, "20ec000.sdma"); clk_register_clkdev(clk[dummy], NULL, "20bc000.wdog"); clk_register_clkdev(clk[dummy], NULL, "20c.wdog"); + clk_register_clkdev(clk[ssi1], NULL, "2028000.ssi"); for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) { c = clk_get_sys(clks_init_on[i], NULL); -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 08/11] ASoC: imx-audmux: add pinctrl support
Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q-sabrelite.dts |3 +++ arch/arm/boot/dts/imx6q.dtsi | 10 ++ sound/soc/fsl/imx-audmux.c|8 3 files changed, 21 insertions(+), 0 deletions(-) diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index 02f93bc..cdae2dd 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -54,7 +54,10 @@ audmux@021d8000 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audmux_1>; }; + uart2: uart@021e8000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 7bf402e..3c3004d 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -402,6 +402,16 @@ reg = <0x020e 0x4000>; /* shared pinctrl settings */ + audmux { + pinctrl_audmux_1: audmux-1 { + fsl,pins = "MX6Q_PAD_SD2_DAT0", + "MX6Q_PAD_SD2_DAT3", + "MX6Q_PAD_SD2_DAT2", + "MX6Q_PAD_SD2_DAT1"; + fsl,mux = <3 3 3 3>; + }; + }; + i2c1 { pinctrl_i2c1_1: i2c1grp-1 { fsl,pins = "MX6Q_PAD_EIM_D21", diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index f237003..6c7dfc0 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "imx-audmux.h" @@ -249,6 +250,7 @@ EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port); static int __devinit imx_audmux_probe(struct platform_device *pdev) { struct resource *res; + struct pinctrl *pct; const struct of_device_id *of_id = of_match_device(imx_audmux_dt_ids, &pdev->dev); @@ -257,6 +259,12 @@ static int __devinit imx_audmux_probe(struct platform_device *pdev) if (!audmux_base) return -EADDRNOTAVAIL; + pct = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pct)) { + dev_err(&pdev->dev, "setup pinctrl failed!"); + return PTR_ERR(pct); + } + audmux_clk = clk_get(&pdev->dev, "audmux"); if (IS_ERR(audmux_clk)) { dev_dbg(&pdev->dev, "cannot get clock: %ld\n", -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 07/11] ARM: dts: imx6q-sabrelite: add audmux device
From: Richard Zhao Signed-off-by: Richard Zhao Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q-sabrelite.dts |3 +++ arch/arm/boot/dts/imx6q.dtsi |2 ++ 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index 7bd8855..02f93bc 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -52,6 +52,9 @@ status = "okay"; }; + audmux@021d8000 { + status = "okay"; + }; uart2: uart@021e8000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index da42fc0..7bf402e 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -596,7 +596,9 @@ }; audmux@021d8000 { + compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux"; reg = <0x021d8000 0x4000>; + status = "disabled"; }; mipi@021dc000 { /* MIPI-CSI */ -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 06/11] ARM: dts: imx6q-sabrelite: add ssi device
From: Richard Zhao Signed-off-by: Richard Zhao Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q-sabrelite.dts |9 + arch/arm/boot/dts/imx6q.dtsi | 18 +++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index 4e13293..7bd8855 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -22,6 +22,15 @@ }; soc { + aips-bus@0200 { /* AIPS1 */ + spba-bus@0200 { + ssi1: ssi@02028000 { + fsl,mode = "i2s-slave"; + status = "okay"; + }; + }; + }; + aips-bus@0210 { /* AIPS2 */ enet@02188000 { phy-mode = "rgmii"; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index fe8c80d..da42fc0 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -177,19 +177,31 @@ interrupts = <0 51 0x04>; }; - ssi@02028000 { /* SSI1 */ + ssi1: ssi@02028000 { + compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; reg = <0x02028000 0x4000>; interrupts = <0 46 0x04>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <38 37>; + status = "disabled"; }; - ssi@0202c000 { /* SSI2 */ + ssi2: ssi@0202c000 { + compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; reg = <0x0202c000 0x4000>; interrupts = <0 47 0x04>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <42 41>; + status = "disabled"; }; - ssi@0203 { /* SSI3 */ + ssi3: ssi@0203 { + compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; reg = <0x0203 0x4000>; interrupts = <0 48 0x04>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <46 45>; + status = "disabled"; }; asrc@02034000 { -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 05/11] ARM: imx6q: move imx6q_sabrelite specific code to a dedicated function
It'll be easier to add other board specific code. Signed-off-by: Richard Zhao --- arch/arm/mach-imx/mach-imx6q.c |9 +++-- 1 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index da6c1d9..d25c5d8 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -75,11 +75,16 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev) return 0; } +static void __init imx6q_sabrelite_init(void) +{ + phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, + ksz9021rn_phy_fixup); +} + static void __init imx6q_init_machine(void) { if (of_machine_is_compatible("fsl,imx6q-sabrelite")) - phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, - ksz9021rn_phy_fixup); + imx6q_sabrelite_init(); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 04/11] i2c: imx: add pinctrl support
Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q-sabrelite.dts |2 ++ arch/arm/boot/dts/imx6q.dtsi | 16 drivers/i2c/busses/i2c-imx.c |9 + 3 files changed, 27 insertions(+), 0 deletions(-) diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index 4663a4e..4e13293 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -50,6 +50,8 @@ i2c@021a { /* I2C1 */ status = "okay"; clock-frequency = <10>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1_1>; codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 2ba32e7..fe8c80d 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -390,6 +390,22 @@ reg = <0x020e 0x4000>; /* shared pinctrl settings */ + i2c1 { + pinctrl_i2c1_1: i2c1grp-1 { + fsl,pins = "MX6Q_PAD_EIM_D21", + "MX6Q_PAD_EIM_D28"; + fsl,hysteresis = <1>; + fsl,mux = <0x16 0x11>; + fsl,pull = <2>; + fsl,pue = <1>; + fsl,pke = <1>; + fsl,open-drain = <1>; + fsl,speed = <2>; + fsl,drive-strength = <6>; + fsl,slew-rate = <1>; + }; + }; + uart4 { pinctrl_uart4_1: uart4grp-1 { fsl,pins = "MX6Q_PAD_KEY_COL0", diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index dfb84b7..7a52067 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -470,6 +471,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) struct imx_i2c_struct *i2c_imx; struct resource *res; struct imxi2c_platform_data *pdata = pdev->dev.platform_data; + struct pinctrl *pct; void __iomem *base; resource_size_t res_size; int irq, bitrate; @@ -520,6 +522,13 @@ static int __init i2c_imx_probe(struct platform_device *pdev) i2c_imx->base = base; i2c_imx->res= res; + pct = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pct)) { + dev_err(&pdev->dev, "can't get/select pinctrl\n"); + ret = PTR_ERR(pct); + goto fail3; + } + /* Get I2C clock */ i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk"); if (IS_ERR(i2c_imx->clk)) { -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 03/11] ASoC: fsl: add sgtl5000 clock support for imx-sgtl5000
From: Richard Zhao It tries to clk_get the clock. And if it failed, it assumes the clock by default enabled. Signed-off-by: Richard Zhao --- sound/soc/fsl/imx-sgtl5000.c | 40 1 files changed, 32 insertions(+), 8 deletions(-) diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 73b935e..3a729ca 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include "../codecs/sgtl5000.h" @@ -25,6 +27,7 @@ struct imx_sgtl5000_data { struct snd_soc_card card; char codec_dai_name[DAI_NAME_SIZE]; char platform_name[DAI_NAME_SIZE]; + struct clk *codec_clk; unsigned int clk_frequency; }; @@ -58,6 +61,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct device_node *ssi_np, *codec_np; struct platform_device *ssi_pdev; + struct i2c_client *codec_dev; struct imx_sgtl5000_data *data; int int_port, ext_port; int ret; @@ -113,6 +117,11 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) ret = -EINVAL; goto fail; } + codec_dev = of_find_i2c_device_by_node(codec_np); + if (!codec_dev) { + dev_err(&pdev->dev, "failed to find codec platform device\n"); + return -EINVAL; + } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) { @@ -120,11 +129,20 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) goto fail; } - ret = of_property_read_u32(codec_np, "clock-frequency", - &data->clk_frequency); - if (ret) { - dev_err(&pdev->dev, "clock-frequency missing or invalid\n"); - goto fail; + data->codec_clk = clk_get(&codec_dev->dev, NULL); + if (IS_ERR(data->codec_clk)) { + /* assuming clock enabled by default */ + data->codec_clk = NULL; + ret = of_property_read_u32(codec_np, "clock-frequency", + &data->clk_frequency); + if (ret) { + dev_err(&codec_dev->dev, + "clock-frequency missing or invalid\n"); + goto fail; + } + } else { + data->clk_frequency = clk_get_rate(data->codec_clk); + clk_prepare_enable(data->codec_clk); } data->dai.name = "HiFi"; @@ -140,10 +158,10 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) data->card.dev = &pdev->dev; ret = snd_soc_of_parse_card_name(&data->card, "model"); if (ret) - goto fail; + goto clk_fail; ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); if (ret) - goto fail; + goto clk_fail; data->card.num_links = 1; data->card.dai_link = &data->dai; data->card.dapm_widgets = imx_sgtl5000_dapm_widgets; @@ -152,10 +170,12 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) ret = snd_soc_register_card(&data->card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto fail; + goto clk_fail; } platform_set_drvdata(pdev, data); +clk_fail: + clk_put(data->codec_clk); fail: if (ssi_np) of_node_put(ssi_np); @@ -169,6 +189,10 @@ static int __devexit imx_sgtl5000_remove(struct platform_device *pdev) { struct imx_sgtl5000_data *data = platform_get_drvdata(pdev); + if (data->codec_clk) { + clk_disable_unprepare(data->codec_clk); + clk_put(data->codec_clk); + } snd_soc_unregister_card(&data->card); return 0; -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 00/11] enable imx6q_sabrelite sgtl5000 audio support
It's based on Dong Aisheng's early pinctrl patch and Sascha's v2 convert to common clk patch. You can also get at: https://github.com/riczhao/kernel-imx/tree/topics/audio Richard Zhao (11): dma: imx-sdma: make channel0 operations atomic ASoC: imx-sgtl5000: add of_node_put when probe fail. ASoC: fsl: add sgtl5000 clock support for imx-sgtl5000 i2c: imx: add pinctrl support ARM: imx6q: move imx6q_sabrelite specific code to a dedicated function ARM: dts: imx6q-sabrelite: add ssi device ARM: dts: imx6q-sabrelite: add audmux device ASoC: imx-audmux: add pinctrl support ARM: imx6q: add ssi1 clk_lookup ARM: imx6q_sabrelite: clkdev_add cko1 for sgtl5000 ARM: dts: imx6q-sabrelite: add sound device imx6q-sabrelite-sgtl5000 arch/arm/boot/dts/imx6q-sabrelite.dts | 30 arch/arm/boot/dts/imx6q.dtsi | 46 +++-- arch/arm/mach-imx/clk-imx6q.c |4 ++ arch/arm/mach-imx/mach-imx6q.c| 37 +++- drivers/dma/imx-sdma.c| 57 ++- drivers/i2c/busses/i2c-imx.c |9 + sound/soc/fsl/imx-audmux.c|8 sound/soc/fsl/imx-sgtl5000.c | 61 + 8 files changed, 208 insertions(+), 44 deletions(-) Thanks Richard -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/11] ASoC: imx-sgtl5000: add of_node_put when probe fail.
Signed-off-by: Richard Zhao --- sound/soc/fsl/imx-sgtl5000.c | 29 ++--- 1 files changed, 18 insertions(+), 11 deletions(-) diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index e1a7441..73b935e 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -103,24 +103,28 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0); if (!ssi_np || !codec_np) { dev_err(&pdev->dev, "phandle missing or invalid\n"); - return -EINVAL; + ret = -EINVAL; + goto fail; } ssi_pdev = of_find_device_by_node(ssi_np); if (!ssi_pdev) { dev_err(&pdev->dev, "failed to find SSI platform device\n"); - return -EINVAL; + ret = -EINVAL; + goto fail; } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; + if (!data) { + ret = -ENOMEM; + goto fail; + } ret = of_property_read_u32(codec_np, "clock-frequency", &data->clk_frequency); if (ret) { dev_err(&pdev->dev, "clock-frequency missing or invalid\n"); - return ret; + goto fail; } data->dai.name = "HiFi"; @@ -136,10 +140,10 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) data->card.dev = &pdev->dev; ret = snd_soc_of_parse_card_name(&data->card, "model"); if (ret) - return ret; + goto fail; ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); if (ret) - return ret; + goto fail; data->card.num_links = 1; data->card.dai_link = &data->dai; data->card.dapm_widgets = imx_sgtl5000_dapm_widgets; @@ -148,14 +152,17 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) ret = snd_soc_register_card(&data->card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - return ret; + goto fail; } platform_set_drvdata(pdev, data); - of_node_put(ssi_np); - of_node_put(codec_np); +fail: + if (ssi_np) + of_node_put(ssi_np); + if (codec_np) + of_node_put(codec_np); - return 0; + return ret; } static int __devexit imx_sgtl5000_remove(struct platform_device *pdev) -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 01/11] dma: imx-sdma: make channel0 operations atomic
device_prep_dma_cyclic may be call in audio trigger function which is atomic context, so we make it atomic too. - change channel0 lock to spinlock. - Use polling to wait for channel0 finish running. Signed-off-by: Lothar Waßmann Signed-off-by: Richard Zhao --- drivers/dma/imx-sdma.c | 57 +++ 1 files changed, 33 insertions(+), 24 deletions(-) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index fddccae..fc49ffa 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -324,7 +324,7 @@ struct sdma_engine { struct dma_device dma_device; struct clk *clk_ipg; struct clk *clk_ahb; - struct mutexchannel_0_lock; + spinlock_t channel_0_lock; struct sdma_script_start_addrs *script_addrs; }; @@ -402,19 +402,31 @@ static void sdma_enable_channel(struct sdma_engine *sdma, int channel) } /* - * sdma_run_channel - run a channel and wait till it's done + * sdma_run_channel0 - run a channel and wait till it's done */ -static int sdma_run_channel(struct sdma_channel *sdmac) +static int sdma_run_channel0(struct sdma_channel *sdmac) { struct sdma_engine *sdma = sdmac->sdma; int channel = sdmac->channel; int ret; + unsigned long timeout = 500; - init_completion(&sdmac->done); - + if (channel) + return -EINVAL; sdma_enable_channel(sdma, channel); - ret = wait_for_completion_timeout(&sdmac->done, HZ); + while (!(ret = readl_relaxed(sdma->regs + SDMA_H_INTR) & 1)) { + if (timeout-- <= 0) + break; + udelay(1); + } + + if (ret) { + /* Clear the interrupt status */ + writel_relaxed(ret, sdma->regs + SDMA_H_INTR); + } else { + dev_err(sdma->dev, "Timeout waiting for CH0 ready\n"); + } return ret ? 0 : -ETIMEDOUT; } @@ -426,17 +438,17 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size, void *buf_virt; dma_addr_t buf_phys; int ret; - - mutex_lock(&sdma->channel_0_lock); + unsigned long flags; buf_virt = dma_alloc_coherent(NULL, size, &buf_phys, GFP_KERNEL); if (!buf_virt) { - ret = -ENOMEM; - goto err_out; + return -ENOMEM; } + spin_lock_irqsave(&sdma->channel_0_lock, flags); + bd0->mode.command = C0_SETPM; bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; bd0->mode.count = size / 2; @@ -445,12 +457,11 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size, memcpy(buf_virt, buf, size); - ret = sdma_run_channel(&sdma->channel[0]); + ret = sdma_run_channel0(&sdma->channel[0]); - dma_free_coherent(NULL, size, buf_virt, buf_phys); + spin_unlock_irqrestore(&sdma->channel_0_lock, flags); -err_out: - mutex_unlock(&sdma->channel_0_lock); + dma_free_coherent(NULL, size, buf_virt, buf_phys); return ret; } @@ -539,10 +550,6 @@ static void mxc_sdma_handle_channel(struct sdma_channel *sdmac) { complete(&sdmac->done); - /* not interested in channel 0 interrupts */ - if (sdmac->channel == 0) - return; - if (sdmac->flags & IMX_DMA_SG_LOOP) sdma_handle_channel_loop(sdmac); else @@ -555,6 +562,8 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id) unsigned long stat; stat = readl_relaxed(sdma->regs + SDMA_H_INTR); + /* not interested in channel 0 interrupts */ + stat &= ~1; writel_relaxed(stat, sdma->regs + SDMA_H_INTR); while (stat) { @@ -660,6 +669,7 @@ static int sdma_load_context(struct sdma_channel *sdmac) struct sdma_context_data *context = sdma->context; struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd; int ret; + unsigned long flags; if (sdmac->direction == DMA_DEV_TO_MEM) { load_address = sdmac->pc_from_device; @@ -677,7 +687,7 @@ static int sdma_load_context(struct sdma_channel *sdmac) dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", (u32)sdmac->event_mask[0]); dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", (u32)sdmac->event_mask[1]); - mutex_lock(&sdma->channel_0_lock); + spin_lock_irqsave(&sdma->channel_0_lock, flags); memset(context, 0, sizeof(*context)); context->channel_state.pc = load_address; @@ -696,10 +706,9 @@ static int sdma_load_context(struct sdma_channel *sdmac) bd0->mode.count = sizeof(*context) / 4; bd0->buffer_addr = sdma->context_phys; bd0->ext_buf
[PATCH v2 0/5] MIPS: OCTEON: Convert some device to use Device Tree.
From: David Daney This patch set depends on the previous set to add Device Tree to OCTEON. That set can be found among other places here: http://marc.info/?l=linux-kernel&m=133548781607480 For v2: No functional changes, but minor clean-ups to use some new device tree helper functions. Some Acked-bys added. I am suggesting that all these go via Ralf's linux-mips.org tree as they depend on other patches in that tree. >From v1: The patches are for drivers scattered throughout the tree, but there is an order dependency as well as the dependency mentioned above, so it may be preferable to merge them all via Ralf's linux-mips.org tree rather that separately via the various device sub-system maintainers. The mdio-octeon.c and octeon_mgmt patches were already Acked-by davem. The i2c has been seen before, but to my knowledge was never acked. The octeon_ethernet patch is in staging and has also been seen before. The serial patch is new. David Daney (5): i2c: Convert i2c-octeon.c to use device tree. netdev: mdio-octeon.c: Convert to use device tree. netdev: octeon_mgmt: Convert to use device tree. staging: octeon_ethernet: Convert to use device tree. MIPS: Octeon: Use device tree to register serial ports. arch/mips/cavium-octeon/octeon-irq.c |8 - arch/mips/cavium-octeon/octeon-platform.c | 176 arch/mips/cavium-octeon/serial.c | 134 + arch/mips/include/asm/octeon/octeon.h |5 - drivers/i2c/busses/i2c-octeon.c | 92 + drivers/net/ethernet/octeon/octeon_mgmt.c | 312 +++-- drivers/net/phy/mdio-octeon.c | 92 ++--- drivers/staging/octeon/ethernet-mdio.c| 28 ++-- drivers/staging/octeon/ethernet.c | 153 +- drivers/staging/octeon/octeon-ethernet.h |3 + 10 files changed, 484 insertions(+), 519 deletions(-) Cc: net...@vger.kernel.org Cc: Greg Kroah-Hartman Cc: David S. Miller Cc: "Jean Delvare (PC drivers, core)" Cc: "Ben Dooks (embedded platforms)" Cc: "Wolfram Sang (embedded platforms)" Cc: linux-i2c@vger.kernel.org -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/5] i2c: Convert i2c-octeon.c to use device tree.
From: David Daney There are three parts to this: 1) Remove the definitions of OCTEON_IRQ_TWSI and OCTEON_IRQ_TWSI2. The interrupts are specified by the device tree and these hard coded irq numbers block the used of the irq lines by the irq_domain code. 2) Remove platform device setup code from octeon-platform.c, it is now unused. 3) Convert i2c-octeon.c to use device tree. Part of this includes using the devm_* functions instead of the raw counterparts, thus simplifying error handling. No functionality is changed. Signed-off-by: David Daney Acked-by: Rob Herring Cc: "Jean Delvare (PC drivers, core)" Cc: "Ben Dooks (embedded platforms)" Cc: "Wolfram Sang (embedded platforms)" Cc: linux-i2c@vger.kernel.org --- arch/mips/cavium-octeon/octeon-irq.c |2 - arch/mips/cavium-octeon/octeon-platform.c | 84 -- arch/mips/include/asm/octeon/octeon.h |5 -- drivers/i2c/busses/i2c-octeon.c | 92 +++- 4 files changed, 49 insertions(+), 134 deletions(-) diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index fc40d0b..c6b0b41 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -1183,13 +1183,11 @@ static void __init octeon_irq_init_ciu(void) for (i = 0; i < 4; i++) octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq); for (i = 0; i < 4; i++) octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq); diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index 2754bc2..f62a40f 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -168,90 +168,6 @@ out: } device_initcall(octeon_rng_device_init); -static struct i2c_board_info __initdata octeon_i2c_devices[] = { - { - I2C_BOARD_INFO("ds1337", 0x68), - }, -}; - -static int __init octeon_i2c_devices_init(void) -{ - return i2c_register_board_info(0, octeon_i2c_devices, - ARRAY_SIZE(octeon_i2c_devices)); -} -arch_initcall(octeon_i2c_devices_init); - -#define OCTEON_I2C_IO_BASE 0x118001000ull -#define OCTEON_I2C_IO_UNIT_OFFSET 0x200 - -static struct octeon_i2c_data octeon_i2c_data[2]; - -static int __init octeon_i2c_device_init(void) -{ - struct platform_device *pd; - int ret = 0; - int port, num_ports; - - struct resource i2c_resources[] = { - { - .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, - } - }; - - if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) - num_ports = 2; - else - num_ports = 1; - - for (port = 0; port < num_ports; port++) { - octeon_i2c_data[port].sys_freq = octeon_get_io_clock_rate(); - /*FIXME: should be examined. At the moment is set for 100Khz */ - octeon_i2c_data[port].i2c_freq = 10; - - pd = platform_device_alloc("i2c-octeon", port); - if (!pd) { - ret = -ENOMEM; - goto out; - } - - pd->dev.platform_data = octeon_i2c_data + port; - - i2c_resources[0].start = - OCTEON_I2C_IO_BASE + (port * OCTEON_I2C_IO_UNIT_OFFSET); - i2c_resources[0].end = i2c_resources[0].start + 0x1f; - switch (port) { - case 0: - i2c_resources[1].start = OCTEON_IRQ_TWSI; - i2c_resources[1].end = OCTEON_IRQ_TWSI; - break; - case 1: - i2c_resources[1].start = OCTEON_IRQ_TWSI2; - i2c_resources[1].end = OCTEON_IRQ_TWSI2; - break; - default: - BUG(); - } - - ret = platform_device_add_resources(pd, - i2c_resources, - ARRAY_SIZE(i2c_resources)); - if (ret) - goto fail; - - ret = platform_device_add(pd); - if (ret) -
Re: possible MXS-i2c bug
Dear Wolfram Sang, > Hi Marek, > > you forgot the most important list, linux-i2c ;) > > > I recently tried mxs-i2c (on 3.4-rc4) with at24 eeprom, didn't work as > > expected. > > Yes, we had the same this week/last week. Ah ok ;-) > > > Apparently, there might be some timing issue, when I put printk() into > > the at24 driver eeprom write function, it "fixed" itself. Though, > > replacing the i2c driver with i2c gpio also fixed the issue, so I > > suspect the i2c driver has some flaw in it. > > Try removing the printk and use the module paramter "io_limit=24" for > at24. Does this help? (Or bs<=24 with dd) > > > If noone has any fixes already, I'll debug this tonight or so. > > The write FIFO overflows, since it only can carry 8 words. There is > currently no check for that. One solution would be to check the FIFO > status and fill them as needed. This will probably require additional > locking, so I think the proper solution would be to use DMA for > transfers bigger than the write FIFO size (we would get MX23 support > then, too). Sadly, we don't have DMA support yet and I don't have time > to implement it. > > I am thinking if such transfers which would fail anyway, should > currently be rejected or if the driver should depend on BROKEN or both. > > I am still undecided, though. I've been thinking about the DMA approach. The problem I found out is that we need to transfer all messages we're given at time in one DMA chain ... at least that's how I understand it from the FSL manual (see Fig. 27-10 in the mx28 manual). Therefore we'd have to prepare scatterlist for each message that we're given to transfer. In case we'd be given huge set of messages, we'd have to allocate these scatterlists at runtime. And maybe we'd even have to allocate buffers (to resize the ones in msg.buf for the additional one byte for i2c address). I don't like the idea of calling kmalloc() in mxs_i2c_xfer_message() at all, does anyone have any hint how to handle these? > > Please also check the patch I sent yesterday, there is also another one > coming after I get confirmation from a customer. Thanks > Regards, > >Wolfram Best regards, Marek Vasut -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Query : NACK
Hello, Currently the i2c * Returns negative errno, else the number of messages executed. * * Note that there is no requirement that each message be sent to * the same slave address, although that is the most common model. */ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { unsigned long orig_jiffies; int ret, try; /* REVISIT the fault reporting model here is weak: * * - When we get an error after receiving N bytes from a slave, *there is no way to report "N". * * - When we get a NAK after transmitting N bytes to a slave, *there is no way to report "N" ... or to let the master *continue executing the rest of this combined message, if *that's the appropriate response. * * - When for example "num" is two and we successfully complete *the first message but get an error part way through the *second, it's unclear whether that should be reported as *one (discarding status on the second message) or errno *(discarding status on the first one). */ Some of the drivers expect to get the no of bytes transmitted on NACK so that they can re-transmit the remaining bytes. I did a quick search and didnt find a patch that currently targets to resend the number of bytes. In case I missed a discussion please feel free to point. Will it be acceptable solution if if (ret == NOERR) return count if (ret == NACKERR) return no_of_bytes; else return ret; Or are there better suggestions to achieve it by _not_changing existing drivers. Thanks and Regards, Shubhro -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] i2c: Split I2C_M_NOSTART support out of I2C_FUNC_PROTOCOL_MANGLING
Since there are uses for I2C_M_NOSTART which are much more sensible and standard than most of the protocol mangling functionality (the main one being gather writes to devices where something like a register address needs to be inserted before a block of data) create a new I2C_FUNC_NOSTART for this feature and update all the users to use it. In the case of regmap-i2c we remove the requirement for mangling as I2C_M_NOSTART is the only mangling feature which is being used. Signed-off-by: Mark Brown --- Documentation/i2c/functionality |1 + drivers/base/regmap/regmap-i2c.c |2 +- drivers/i2c/algos/i2c-algo-bit.c |2 +- drivers/i2c/algos/i2c-algo-pcf.c |2 +- drivers/i2c/busses/i2c-nuc900.c |3 ++- drivers/i2c/busses/i2c-s3c2410.c |3 ++- drivers/input/joystick/as5011.c |1 + drivers/video/matrox/matroxfb_maven.c |1 + include/linux/i2c.h |3 ++- 9 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality index 42c17c1..fb2e77e 100644 --- a/Documentation/i2c/functionality +++ b/Documentation/i2c/functionality @@ -33,6 +33,7 @@ For the most up-to-date list of functionality constants, please check I2C_FUNC_SMBUS_WRITE_BLOCK_DATA Handles the SMBus write_block_data command I2C_FUNC_SMBUS_READ_I2C_BLOCK Handles the SMBus read_i2c_block_data command I2C_FUNC_SMBUS_WRITE_I2C_BLOCK Handles the SMBus write_i2c_block_data command + I2C_FUNC_NOSTARTTransfers can be sent without a start A few combinations of the above flags are also defined for your convenience: diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c index 5f6b247..fa6bf52 100644 --- a/drivers/base/regmap/regmap-i2c.c +++ b/drivers/base/regmap/regmap-i2c.c @@ -42,7 +42,7 @@ static int regmap_i2c_gather_write(void *context, /* If the I2C controller can't do a gather tell the core, it * will substitute in a linear write for us. */ - if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_PROTOCOL_MANGLING)) + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_NOSTART)) return -ENOTSUPP; xfer[0].addr = i2c->addr; diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 7f0b832..fad22b0 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -608,7 +608,7 @@ bailout: static u32 bit_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 5c23795..8b38986 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -401,7 +401,7 @@ out: static u32 pcf_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; } diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c index 03b6157..a26dfb8 100644 --- a/drivers/i2c/busses/i2c-nuc900.c +++ b/drivers/i2c/busses/i2c-nuc900.c @@ -502,7 +502,8 @@ static int nuc900_i2c_xfer(struct i2c_adapter *adap, /* declare our i2c functionality */ static u32 nuc900_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART | + I2C_FUNC_PROTOCOL_MANGLING; } /* i2c bus registration info */ diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 8764d6a..faa1f23 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -591,7 +591,8 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, /* declare our i2c functionality */ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART | + I2C_FUNC_PROTOCOL_MANGLING; } /* i2c bus registration info */ diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c index 3063464..57d19d4 100644 --- a/drivers/input/joystick/as5011.c +++ b/drivers/input/joystick/as5011.c @@ -231,6 +231,7 @@ static int __devinit as5011_probe(struct i2c_client *client, } if (!i2c_check_functionality(client->adapter, +I2C_FUNC_NOSTART | I2C_FUNC_PROTOCOL_MANGLING)) { dev_err(&client->dev, "need i2c bus that supports pro
Re: possible MXS-i2c bug
Hi Marek, you forgot the most important list, linux-i2c ;) > I recently tried mxs-i2c (on 3.4-rc4) with at24 eeprom, didn't work as > expected. Yes, we had the same this week/last week. > Apparently, there might be some timing issue, when I put printk() into the > at24 > driver eeprom write function, it "fixed" itself. Though, replacing the i2c > driver with i2c gpio also fixed the issue, so I suspect the i2c driver has > some > flaw in it. Try removing the printk and use the module paramter "io_limit=24" for at24. Does this help? (Or bs<=24 with dd) > If noone has any fixes already, I'll debug this tonight or so. The write FIFO overflows, since it only can carry 8 words. There is currently no check for that. One solution would be to check the FIFO status and fill them as needed. This will probably require additional locking, so I think the proper solution would be to use DMA for transfers bigger than the write FIFO size (we would get MX23 support then, too). Sadly, we don't have DMA support yet and I don't have time to implement it. I am thinking if such transfers which would fail anyway, should currently be rejected or if the driver should depend on BROKEN or both. I am still undecided, though. Please also check the patch I sent yesterday, there is also another one coming after I get confirmation from a customer. Regards, Wolfram -- Pengutronix e.K. | Wolfram Sang| Industrial Linux Solutions | http://www.pengutronix.de/ | signature.asc Description: Digital signature
Re: [PATCH v10 3/4] drivers/i2c/busses/i2c-at91.c: add new driver
Hi Carsten, On Wed, 25 Apr 2012, Carsten Behling wrote: I cannot find the fix for the RXRDY overrun bug in this patch: The fix refers to the bug when RXRDY flag was masked out by TXCOMP, reported by Hubert. I hope this is fixed with v10. [...] here you only report the status flags after a complete transfer, but an overrun can happen after every byte. After reading the status register after an overrun for the next byte this info will be lost ! Right, I didn't consider this. Would you mind to test if the attached patch on top of v10 fixes your problem? Thanks, Niko P.S. Are you using a RM9200? Seems that this SOC has some problems... diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 97f4365..df0f6ed 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -186,9 +186,11 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id) else if (irqstatus & AT91_TWI_TXRDY) at91_twi_write_next_byte(dev); + /* catch error flags */ + dev->transfer_status |= status; + if (irqstatus & AT91_TWI_TXCOMP) { at91_disable_twi_interrupts(dev); - dev->transfer_status = status; complete(&dev->cmd_complete); } @@ -203,6 +205,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len); INIT_COMPLETION(dev->cmd_complete); + dev->transfer_status = 0; if (dev->msg->flags & I2C_M_RD) { unsigned start_flags = AT91_TWI_START; -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html