ARM: Tegra: Device Tree: i2c & wm8903
Subsystems (9)
cover ARM: Tegra: Device Tree: i2c & wm8903
This is revision 2 of my previous patch series:
Tegra: Harmony: Device Tree first steps
The following patch series is a step in the direction of getting board specific devices initialized from a device tree.
This patch set adds intiailization of i2c and the wm8903. The i2c controller is in the SoC and is initialized statically, but the board specific information is pulled in from the device tree. The wm8903 is initialized using only the device tree when using the board-dt.c general Tegra board initialization file.
---
John Bonesio (3):
ARM: Tegra: Device Tree Support: Update how sdhci devices are initialized
ARM: Tegra: Device Tree Support: Add i2c devices
ARM:Tegra: Device Tree Support: Initialize from wm8903 the device tree
arch/arm/boot/dts/tegra-harmony.dts | 37 ++++++++++++++ arch/arm/boot/dts/tegra250.dtsi | 37 ++++++++++++++ arch/arm/mach-tegra/Makefile | 1 arch/arm/mach-tegra/board-dt.c | 94 ++++------------------------------- drivers/i2c/busses/i2c-tegra.c | 16 ++++++ sound/soc/codecs/wm8903.c | 93 +++++++++++++++++++++++++++++++++-- sound/soc/tegra/Kconfig | 2 - sound/soc/tegra/harmony.c | 8 +++ 8 files changed, 200 insertions(+), 88 deletions(-)
Signature · 1 line
- John
RFC 1/3 ARM: Tegra: Device Tree Support: Update how sdhci devices are initialized
This patch changes how sdhci devices are initialized so that a later patch can easily add support for i2c devies.
---
arch/arm/mach-tegra/Makefile | 1 arch/arm/mach-tegra/board-dt.c | 88 ++-------------------------------------- 2 files changed, 6 insertions(+), 83 deletions(-)
arch/arm/mach-tegra/Makefile +1 -0
@@ -31,6 +31,7 @@ obj-${CONFIG_MACH_SEABOARD} += board-seaboard.o obj-${CONFIG_MACH_SEABOARD} += board-seaboard-pinmux.o obj-${CONFIG_MACH_TEGRA_DT} += board-dt.o +obj-${CONFIG_MACH_TEGRA_DT} += board-harmony-pinmux.o obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice.o obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice-pinmux.o
arch/arm/mach-tegra/board-dt.c +5 -83
104 lines not on this page · raw message
RFC 1/3 ARM: Tegra: Device Tree Support: Update how sdhci devices are initialized
John Bonesio wrote at Wednesday, May 11, 2011 5:27 PM:
arch/arm/mach-tegra/board-dt.c line 44
Quoted 8 lines
This patch changes how sdhci devices are initialized so that a later patch can easily add support for i2c devies.
...arch/arm/mach-tegra/board-dt.c +2
-0+#include <mach/sdhci.h> +#include "gpio-names.h"
I don't think either of those headers are needed any more.
Otherwise, looks good.
Signature · 1 line
nvpublic
RFC 2/3 ARM: Tegra: Device Tree Support: Add i2c devices
In reply to John BonesioThis patch initializes i2c controller devices in board-dt.c. The i2c controller is added to tegra250.dtsi so later on-board i2c devices can be found and initialized based on the device tree information.
Board specific i2c parameters are placed in tegra-harmony.dts.
---
arch/arm/boot/dts/tegra-harmony.dts | 20 +++++++++++++++++++ arch/arm/boot/dts/tegra250.dtsi | 37 +++++++++++++++++++++++++++++++++++ arch/arm/mach-tegra/board-dt.c | 8 ++++++++ drivers/i2c/busses/i2c-tegra.c | 16 ++++++++++++++- 4 files changed, 80 insertions(+), 1 deletions(-)
arch/arm/boot/dts/tegra-harmony.dts +20 -0
@@ -16,6 +16,26 @@ reg = < 0x00000000 0x40000000 >; }; + i2c@7000c000 { + status = "ok"; + clock-frequency = <400000>; + }; + + i2c@7000c400 { + status = "ok"; + clock-frequency = <400000>; + }; + + i2c@7000c500 { + status = "ok"; + clock-frequency = <400000>; + }; + + i2c@7000d000 { + status = "ok"; + clock-frequency = <400000>; + }; + serial@70006300 { status = "ok"; clock-frequency = < 216000000 >;
arch/arm/boot/dts/tegra250.dtsi +37 -0
@@ -20,6 +20,43 @@ }; }; + + i2c@7000c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra250-i2c"; + reg = <0x7000C000 0x100>; + interrupts = < 70 >; + status = "disabled"; + }; + + i2c@7000c400 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra250-i2c"; + reg = <0x7000C400 0x100>; + interrupts = < 116 >; + status = "disabled"; + }; + + i2c@7000c500 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra250-i2c"; + reg = <0x7000C500 0x100>; + interrupts = < 124 >; + status = "disabled"; + }; + + i2c@7000d000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nvidia,tegra250-i2c"; + reg = <0x7000D000 0x200>; + interrupts = < 85 >; + status = "disabled"; + }; + gpio: gpio@6000d000 { compatible = "nvidia,tegra250-gpio"; reg = < 0x6000d000 0x1000 >;
arch/arm/mach-tegra/board-dt.c +8 -0
@@ -28,6 +28,8 @@#include <linux/of_platform.h> #include <linux/pda_power.h> #include <linux/io.h> +#include <linux/i2c.h> +#include <linux/i2c-tegra.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -43,11 +45,17 @@#include "devices.h" #include "gpio-names.h" +void harmony_pinmux_init (void ); +static struct platform_device *tegra250_devices[]__initdata = { &tegra_sdhci_device1, &tegra_sdhci_device2, &tegra_sdhci_device3, &tegra_sdhci_device4, + &tegra_i2c_device1, + &tegra_i2c_device2, + &tegra_i2c_device3, + &tegra_i2c_device4, };static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
drivers/i2c/busses/i2c-tegra.c +15 -1
@@ -26,6 +26,7 @@#include <linux/delay.h> #include <linux/slab.h> #include <linux/i2c-tegra.h> +#include <linux/of_i2c.h> #include <asm/unaligned.h>
@@ -511,6 +512,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)struct resource *iomem;struct clk *clk;struct clk *i2c_clk; +const unsigned int *prop;void *base;int irq;int ret =0 ;
@@ -568,7 +570,16 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->irq = irq; i2c_dev->cont_id = pdev->id; i2c_dev->dev = &pdev->dev; - i2c_dev->bus_clk_rate = pdata ? pdata->bus_clk_rate :100000 ; + + i2c_dev->bus_clk_rate =100000 ;/* default clock rate */ +if (i2c_dev->dev->of_node) {/* if there is a device tree node ... */ + prop =of_get_property (i2c_dev->dev->of_node, +"clock-frequency" ,NULL ); +if (prop) + i2c_dev->bus_clk_rate =be32_to_cpup (prop); + + }else if (pdata) + i2c_dev->bus_clk_rate = pdata->bus_clk_rate;if (pdev->id ==3 ) i2c_dev->is_dvc =1 ;
@@ -598,6 +609,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->adapter.algo = &tegra_i2c_algo; i2c_dev->adapter.dev.parent = &pdev->dev; i2c_dev->adapter.nr = pdev->id; + i2c_dev->adapter.dev.of_node =of_node_get (pdev->dev.of_node); ret =i2c_add_numbered_adapter (&i2c_dev->adapter);if (ret) {
@@ -605,6 +617,8 @@ static int tegra_i2c_probe(struct platform_device *pdev) goto err_free_irq; } +of_i2c_register_devices (&i2c_dev->adapter); +return 0 ; err_free_irq:free_irq (i2c_dev->irq, i2c_dev);
RFC 2/3 ARM: Tegra: Device Tree Support: Add i2c devices
John Bonesio wrote at Wednesday, May 11, 2011 5:27 PM:
arch/arm/mach-tegra/board-dt.c line 32
Quoted 8 lines
This patch initializes i2c controller devices in
board-dt.c. The i2c controller is added totegra250.dtsiso later on-board i2c devices can be found and initialized based on the device tree information.
...arch/arm/mach-tegra/board-dt.c +2
-0+#include <linux/i2c.h> +#include <linux/i2c-tegra.h>
I don't think those headers are needed now the platform data isn't set up here.
drivers/i2c/busses/i2c-tegra.c static int tegra_i2c_probe(struct platform_device *pdev) · line 612
Quoted 7 lines
drivers/i2c/busses/i2c-tegra.c +1
-0@@ -598,6 +609,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->adapter.algo = &tegra_i2c_algo; i2c_dev->adapter.dev.parent = &pdev->dev; i2c_dev->adapter.nr = pdev->id; + i2c_dev->adapter.dev.of_node =of_node_get (pdev->dev.of_node);
It seems like users of this of_node (i.e. the probe function) could just access pdev->dev.of_node directly (since pdev is already passed in) rather than storing a copy here. At least, sdhci-tegra.c works that way. Still, this isn't a big deal, I think.
drivers/i2c/busses/i2c-tegra.c static int tegra_i2c_probe(struct platform_device *pdev) · line 621
Quoted 6 lines
drivers/i2c/busses/i2c-tegra.c +2
-0@@ -605,6 +617,8 @@ static int tegra_i2c_probe(struct platform_device *pdev) goto err_free_irq; } +of_i2c_register_devices (&i2c_dev->adapter); +
I would have expected that to be performed inside the core I2C code, probably inside i2c_add_numbered_adapter? Still, it looks like the other I2C controllers don't already work that way, so this is probably more a suggestion for future cleanup than something to be addressed in this patch.
Signature · 1 line
nvpublic
RFC 2/3 ARM: Tegra: Device Tree Support: Add i2c devices
Quoted 12 lines · Stephen Warren
John Bonesio wrote at Wednesday, May 11, 2011 5:27 PM:
arch/arm/mach-tegra/board-dt.c line 32
Quoted 8 lines
This patch initializes i2c controller devices in
board-dt.c. The i2c controller is added totegra250.dtsiso later on-board i2c devices can be found and initialized based on the device tree information.
...arch/arm/mach-tegra/board-dt.c +2
-0+#include <linux/i2c.h> +#include <linux/i2c-tegra.h> I don't think those headers are needed now the platform data isn't set up here.
Quoted 12 lines
drivers/i2c/busses/i2c-tegra.c static int tegra_i2c_probe(struct platform_device *pdev) · line 612
Quoted 7 lines
drivers/i2c/busses/i2c-tegra.c +1
-0@@ -598,6 +609,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) ? ? ? i2c_dev->adapter.algo = &tegra_i2c_algo; ? ? ? i2c_dev->adapter.dev.parent = &pdev->dev; ? ? ? i2c_dev->adapter.nr = pdev->id; + ? ? i2c_dev->adapter.dev.of_node = of_node_get(pdev->dev.of_node);It seems like users of this
of_node(i.e. the probe function) could just accesspdev->dev.of_nodedirectly (since pdev is already passed in) rather than storing a copy here. At least,sdhci-tegra.cworks that way. Still, this isn't a big deal, I think.
Actually, using of_node_get() here is the right thing since it increases the reference count on the of_node. However, the patch should also do an of_node_put() in the remove hook, or in the .probe error path.
Quoted 5 lines
Quoted 5 lines
drivers/i2c/busses/i2c-tegra.c +0
-0@@ -605,6 +617,8 @@ static int tegra_i2c_probe(struct platform_device *pdev) ? ? ? ? ? ? ? goto err_free_irq; ? ? ? }
Quoted 8 lines
drivers/i2c/busses/i2c-tegra.c static int tegra_i2c_probe(struct platform_device *pdev) · line 621
Quoted 2 lines
drivers/i2c/busses/i2c-tegra.c +2
-0+ ? ? of_i2c_register_devices(&i2c_dev->adapter); +I would have expected that to be performed inside the core I2C code, probably inside
i2c_add_numbered_adapter? Still, it looks like the other I2C controllers don't already work that way, so this is probably more a suggestion for future cleanup than something to be addressed in this patch.
This may move into core code in the future, but for the moment the drivers need to call it explicitly.
g.
RFC 2/3 ARM: Tegra: Device Tree Support: Add i2c devices
Grant Likely wrote at Wednesday, May 11, 2011 10:47 PM:
Quoted 17 lines · Stephen Warren
Quoted 15 lines
John Bonesio wrote at Wednesday, May 11, 2011 5:27 PM:
Review static int tegra_i2c_probe(struct platform_device *pdev) · line 612
Quoted 9 lines
This patch initializes i2c controller devices in
board-dt.c. The i2c controller is added totegra250.dtsiso later on-board i2c devices can be found and initialized based on the device tree information.
...(quoted diff) +1
-0@@ -598,6 +609,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) ? ? ? i2c_dev->adapter.algo = &tegra_i2c_algo; ? ? ? i2c_dev->adapter.dev.parent = &pdev->dev; ? ? ? i2c_dev->adapter.nr = pdev->id; + ? ? i2c_dev->adapter.dev.of_node = of_node_get(pdev->dev.of_node);It seems like users of this
of_node(i.e. the probe function) could just accesspdev->dev.of_nodedirectly (since pdev is already passed in) rather than storing a copy here. At least,sdhci-tegra.cworks that way. Still, this isn't a big deal, I think.
Quoted 4 lines
Actually, using
of_node_get()here is the right thing since it increases the reference count on theof_node. However, the patch should also do anof_node_put()in the remove hook, or in the .probe error path.
Ah OK, I was missing that the later all of of_i2c_register_devices() uses i2c_dev->adapter.dev.of_node; I was thinking that it'd just use i2c_dev->adapter.dev.parent->of_node directly, in which case we wouldn't need to copy the pointer, nor increment the refcount.
So, I agree this is OK.
Signature · 1 line
nvpublic
RFC 3/3 ARM:Tegra: Device Tree Support: Initialize from wm8903 the device tree
In reply to John BonesioThis patch makes it so the wm8903 is initialized from it's device tree node.
---
arch/arm/boot/dts/tegra-harmony.dts | 17 ++++++ sound/soc/codecs/wm8903.c | 93 +++++++++++++++++++++++++++++++++-- sound/soc/tegra/Kconfig | 2 - sound/soc/tegra/harmony.c | 8 +++ 4 files changed, 115 insertions(+), 5 deletions(-)
arch/arm/boot/dts/tegra-harmony.dts +17 -0
@@ -19,6 +19,23 @@ i2c@7000c000 { status = "ok"; clock-frequency = <400000>; + + codec: wm8903@1a { + compatible = "wlf,wm8903"; + reg = <0x1a>; + interrupts = < 347 >; + irq-active-low = <0>; + micdet-cfg = <0>; + micdet-delay = <100>; + + gpio-controller; + #gpio-cells = <2>; + + gpio-base = < 224 >; + gpio-num-cfg = < 5 >; + /* #define WM8903_GPIO_NO_CONFIG 0x8000 */ + gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >; + }; }; i2c@7000c400 {
sound/soc/codecs/wm8903.c +89 -4
121 lines not on this page · raw message
sound/soc/tegra/Kconfig +1 -1
@@ -16,7 +16,7 @@ config SND_TEGRA_SOC_I2S config SND_TEGRA_SOC_HARMONY tristate "SoC Audio support for Tegra Harmony reference board" - depends on SND_TEGRA_SOC && MACH_HARMONY && I2C + depends on SND_TEGRA_SOC && (MACH_HARMONY || MACH_TEGRA_DT) && I2C default m select SND_TEGRA_SOC_I2S select SND_SOC_WM8903
sound/soc/tegra/harmony.c +8 -0
@@ -292,12 +292,20 @@ static __devinit int tegra_snd_harmony_probe(struct platform_device *pdev)struct snd_soc_card *card = &snd_soc_harmony;struct tegra_harmony *harmony;struct harmony_audio_platform_data *pdata; +const char *sprop;int ret; +#ifdef CONFIG_OF +if ((!of_machine_is_compatible ("nvidia,harmony" )) && (!machine_is_harmony ())) { +dev_err (&pdev->dev,"Not running on Tegra Harmony!\n" ); +return -ENODEV ; + } +#else if (!machine_is_harmony ()) {dev_err (&pdev->dev,"Not running on Tegra Harmony!\n" );return -ENODEV ; } +#endif pdata = pdev->dev.platform_data;if (!pdata) {
RFC 3/3 ARM:Tegra: Device Tree Support: Initialize from wm8903 the device tree
John Bonesio wrote at Wednesday, May 11, 2011 5:27 PM:
Quoted 10 lines
This patch makes it so the wm8903 is initialized from it's device tree node.
arch/arm/boot/dts/tegra-harmony.dts +0
-0@@ -19,6 +19,23 @@ i2c at 7000c000 {
arch/arm/boot/dts/tegra-harmony.dts line 29
Quoted 10 lines
arch/arm/boot/dts/tegra-harmony.dts +8
-0status = "ok"; clock-frequency = <400000>; + + codec: wm8903 at 1a { + compatible = "wlf,wm8903"; + reg = <0x1a>; + interrupts = < 347 >; + irq-active-low = <0>; + micdet-cfg = <0>; + micdet-delay = <100>;
Nit: Maybe group all the WM8903-specific fields together, rather than spacing them out and interleaving the gpio-controller/gpio-cells in the middle of them?
arch/arm/boot/dts/tegra-harmony.dts line 35
Quoted 6 lines
arch/arm/boot/dts/tegra-harmony.dts +6
-0+ + gpio-controller; + #gpio-cells = <2>; + + gpio-base = < 224 >; + gpio-num-cfg = < 5 >;
I don't think gpio-num-cfg is required; the codec always exports 5 GPIOs.
Quoted 15 lines
arch/arm/boot/dts/tegra-harmony.dts +3
-0+ /* #define WM8903_GPIO_NO_CONFIG 0x8000 */ + gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >; + }; }; i2c at 7000c400 {sound/soc/codecs/wm8903.c +0
-1@@ -1865,10 +1865,14 @@ static void wm8903_init_gpio(struct snd_soc_codec *codec) wm8903->gpio_chip.ngpio =WM8903_NUM_GPIO ; wm8903->gpio_chip.dev = codec->dev; -if (pdata && pdata->gpio_base)
sound/soc/codecs/wm8903.c static void wm8903_init_gpio(struct snd_soc_codec *codec) · line 1875
Quoted 10 lines
sound/soc/codecs/wm8903.c +7
-2+ wm8903->gpio_chip.base =-1 ; +if (pdata && pdata->gpio_base) { wm8903->gpio_chip.base = pdata->gpio_base; - else - wm8903->gpio_chip.base = -1; + }else if (codec->dev->of_node) { + prop =of_get_property (codec->dev->of_node,"gpio-base" ,NULL ); +if (prop) + wm8903->gpio_chip.base =be32_to_cpup (prop); + }
The above checks for pdata first, then falls back to of_node. However, The previous i2c-tegra.c patch checks of_node first then falls back to pdata. It seems like the ordering should be consistent (although changing the I2C patch might be best, since I imagine checking pdata first would lead to least compatibility issues)
sound/soc/codecs/wm8903.c static int wm8903_probe(struct snd_soc_codec · line 1982
Quoted 11 lines
sound/soc/codecs/wm8903.c +6
-0@@ -1964,10 +1973,76 @@ static int wm8903_probe(struct snd_soc_codec *codec)WARN_ON (!mic_gpio && (pdata->micdet_cfg &WM8903_MICDET_ENA )); wm8903->mic_delay = pdata->micdet_delay; + }else if (codec->dev->of_node) { +bool mic_gpio = false; + + prop =of_get_property (codec->dev->of_node,"gpio-num-cfg" ,NULL ); +if (prop) + num_gpios =be32_to_cpup (prop);
Again, I'd just hard-code num_gpios==WM8903_NUM_GPIO in the loop below, instead of making it configurable, since the HW is fixed.
Quoted 41 lines
sound/soc/codecs/wm8903.c +41
-0+ prop =of_get_property (codec->dev->of_node,"gpio-cfg" ,NULL ); +if (num_gpios && prop) { +for (i =0 ; i < num_gpios; i++) { + gpio_cfg =be32_to_cpu (prop[i]); + +if (gpio_cfg ==WM8903_GPIO_NO_CONFIG ) +continue ; + +snd_soc_write (codec,WM8903_GPIO_CONTROL_1 + i, + gpio_cfg &0xffff ); + + val = (gpio_cfg &WM8903_GP1_FN_MASK ) + >>WM8903_GP1_FN_SHIFT ; + +switch (val) { +case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT: +case WM8903_GPn_FN_MICBIAS_SHORT_DETECT: + mic_gpio = true; +break ; +default : +break ; + } + } + } + + prop =of_get_property (codec->dev->of_node,"interrupts" ,NULL ); +if (prop) + wm8903->irq =be32_to_cpup (prop); + + prop =of_get_property (codec->dev->of_node,"micdet-cfg" ,NULL ); +if (prop) + micdet_cfg =be32_to_cpup (prop); + +snd_soc_write (codec,WM8903_MIC_BIAS_CONTROL_0 , micdet_cfg); + +if (micdet_cfg) +snd_soc_update_bits (codec,WM8903_WRITE_SEQUENCER_0 , +WM8903_WSEQ_ENA ,WM8903_WSEQ_ENA ); + +/* If microphone detection is enabled in device tree but +* detected via IRQ then interrupts can be lost before
sound/soc/codecs/wm8903.c static int wm8903_probe(struct snd_soc_codec *codec) · line 2033
Quoted 10 lines
sound/soc/codecs/wm8903.c +10
-0+* the machine driver has set up microphone detection +* IRQs as the IRQs are clear on read. The detection +* will be enabled when the machine driver configures. +*/ +WARN_ON (!mic_gpio && (micdet_cfg &WM8903_MICDET_ENA )); + + prop =of_get_property (codec->dev->of_node,"micdet-delay" ,NULL ); +if (prop) + wm8903->mic_delay =be32_to_cpup (prop); +
The above chunk duplicates a lot of code in the pdata and of_node paths.
Instead, perhaps it'd be better to do something more like:
if (!pdata && of_node) {
pdata = kalloc()
read of_node, convert & write to pdata
}
if (pdata) {
// existing code to handle pdata
}That way, the code to handle the pdata is re-used and not duplicated.
Quoted 5 lines
sound/soc/tegra/harmony.c +2
-0+#ifdef CONFIG_OF + if ((!of_machine_is_compatible("nvidia,harmony")) &&(!machine_is_harmony())) {
sound/soc/tegra/harmony.c static __devinit int tegra_snd_harmony_probe(struct platform_device *pdev) · line 308
Quoted 9 lines
sound/soc/tegra/harmony.c +5
-0+dev_err (&pdev->dev,"Not running on Tegra Harmony!\n" ); + return -ENODEV; + } +#else if (!machine_is_harmony ()) {dev_err (&pdev->dev,"Not running on Tegra Harmony!\n" );return -ENODEV ; } +#endif
Is that backwards-compatible if CONFIG_OF is enabled, but a devicetree wasn't provided, but instead the old-style Harmony machine ID was used? I note that the board-harmony.c machine description doesn't include a DT_MACHINE_START listing that compatible value; only board-dt.c does this, and that has a different ARM machine ID.
Signature · 1 line
nvpublic
RFC 3/3 ARM:Tegra: Device Tree Support: Initialize from wm8903 the device tree
In reply to John BonesioQuoted 7 lines · John Bonesio
This patch makes it so the wm8903 is initialized from it's device tree node.
Signed-off-by John Bonesio<[email protected]>---
arch/arm/boot/dts/tegra-harmony.dts | 17 ++++++ sound/soc/codecs/wm8903.c | 93 +++++++++++++++++++++++++++++++++--
This needs to be sent separately to the relevant mailing lists and maintainers. You can't go making substantial changes to drivers without even telling the maintainers about it - this will apply to any device tree work you're doing. In this case one of the maintainers happens to be me, but even so.
arch/arm/boot/dts/tegra-harmony.dts line 29
Quoted 4 lines
arch/arm/boot/dts/tegra-harmony.dts +4
-0+ interrupts = < 347 >; + irq-active-low = <0>; + micdet-cfg = <0>; + micdet-delay = <100>;
Some of this looks like chip default, why is it being configured?
arch/arm/boot/dts/tegra-harmony.dts line 32
Quoted 2 lines
arch/arm/boot/dts/tegra-harmony.dts +2
-0+ gpio-controller; + #gpio-cells = <2>;
The fact that this device is a GPIO controller is a physical property of the device, we shouldn't need to be putting it into the device tree.
arch/arm/boot/dts/tegra-harmony.dts line 35
Quoted 1 line
arch/arm/boot/dts/tegra-harmony.dts +1
-0+ gpio-num-cfg = < 5 >;
Similarly here, the device has a fixed number of GPIOs.
arch/arm/boot/dts/tegra-harmony.dts line 37
Quoted 2 lines
arch/arm/boot/dts/tegra-harmony.dts +2
-0+ /* #define WM8903_GPIO_NO_CONFIG 0x8000 */ + gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >;
This doesn't seem great for usability. I'd suggest key/value pairs rather than an array.
sound/soc/codecs/wm8903.c static void wm8903_init_gpio(struct snd_soc_codec *codec) · line 1875
Quoted 11 lines
sound/soc/codecs/wm8903.c +7
-3-if (pdata && pdata->gpio_base) + wm8903->gpio_chip.base =-1 ; +if (pdata && pdata->gpio_base) { wm8903->gpio_chip.base = pdata->gpio_base; -else - wm8903->gpio_chip.base =-1 ; + }else if (codec->dev->of_node) { + prop =of_get_property (codec->dev->of_node,"gpio-base" ,NULL ); +if (prop) + wm8903->gpio_chip.base =be32_to_cpup (prop); + }
We have to do manual endianness conversions to read from the device tree? Oh, well.
sound/soc/codecs/wm8903.c static int wm8903_probe(struct snd_soc_codec *codec) · line 2011
Quoted 5 lines
sound/soc/codecs/wm8903.c +5
-0+ + prop =of_get_property (codec->dev->of_node,"interrupts" ,NULL ); +if (prop) + wm8903->irq =be32_to_cpup (prop); +
We have a standard way of passing the IRQ number to I2C devices, surely we should make sure that works at the bus level rather than having to replicate this code everywhere?
Quoted 8 lines
sound/soc/codecs/wm8903.c +8
-0+ prop =of_get_property (codec->dev->of_node,"micdet-cfg" ,NULL ); +if (prop) + micdet_cfg =be32_to_cpup (prop); + +snd_soc_write (codec,WM8903_MIC_BIAS_CONTROL_0 , micdet_cfg); + +if (micdet_cfg) + snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
sound/soc/codecs/wm8903.c static int wm8903_probe(struct snd_soc_codec *codec) · line 2029
Quoted 10 lines
sound/soc/codecs/wm8903.c +10
-0+ WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); + +/* If microphone detection is enabled in device tree but +* detected via IRQ then interrupts can be lost before +* the machine driver has set up microphone detection +* IRQs as the IRQs are clear on read. The detection +* will be enabled when the machine driver configures. +*/ +WARN_ON (!mic_gpio && (micdet_cfg &WM8903_MICDET_ENA )); +
There's an awful lot of cut'n'paste code for the parsing code from the platform data code.
sound/soc/tegra/Kconfig config SND_TEGRA_SOC_I2S · line 19
Quoted 4 lines
config
SND_TEGRA_SOC_HARMONYsound/soc/tegra/Kconfig +1
-1tristate "SoC Audio support for Tegra Harmony reference board" - depends on SND_TEGRA_SOC && MACH_HARMONY && I2C + depends on SND_TEGRA_SOC && (MACH_HARMONY || MACH_TEGRA_DT) && I2C
You've not added anything to the device tree to register the platform device for the machine and I rather fear this won't apply to current code. You should develop against -next.
RFC 3/3 ARM:Tegra: Device Tree Support: Initialize from wm8903 the device tree
Quoted 13 lines · Mark Brown
Quoted 11 lines · John Bonesio
- ? ? if (pdata &&
pdata->gpio_base)
+ ? ?wm8903->gpio_chip.base= -1;
+ ? ? if (pdata &&pdata->gpio_base) {
? ? ? ? ? ? ?wm8903->gpio_chip.base=pdata->gpio_base;
- ? ? else
- ? ? ? ? ? ?wm8903->gpio_chip.base= -1;
+ ? ? } else if (codec->dev->of_node) {
+ ? ? ? ? ? ? prop =of_get_property(codec->dev->of_node, "gpio-base", NULL);
+ ? ? ? ? ? ? if (prop)
+ ? ? ? ? ? ? ? ? ? ?wm8903->gpio_chip.base=be32_to_cpup(prop);
+ ? ? }
Quoted 2 lines
We have to do manual endianness conversions to read from the device tree? ?Oh, well.
Yeah, it's not great. I'd really like to have a set of helper functions that locate and decode the data for the most common types of properties, but I've not sat down to focus on it and I've not seen a pattern I'm happy with yet. It does need to be solved though. The issue is I want something that handles fetching the property, error checking and decoding, all in a consistent way so that it actually reduces the amount of parsing code required.
Perhaps something like:
/* Not sure about this; in this case the return value is an error code so that bad properties can be detected */
int dt_decode_cell(struct *property, int index, u32 *out_val); int dt_decode_string(struct *property, int index, char **out_val); int dt_decode_number(struct *property, int start, int len, unsigned long long *out_val);
and perhaps a set of companion functions:
int dt_get_prop_cell(struct *device_node, char *propname, int index, u32 *out_val);
int dt_get_prop_string(struct *device_node, char *propname, int index, char **out_val);
int dt_get_prop_number(struct *device_node, char *propname, int start, int len, unsigned long long *out_val);
The first set would be used when the property pointer has already be obtained, and multiple datum need to be extracted. The second would be most useful when only one value will be extracted from a property. I'm not totally happy with returning the value via a passed in pointer though. Thoughts?
g.
RFC 3/3 ARM:Tegra: Device Tree Support: Initialize from wm8903 the device tree
Quoted 4 lines · Grant Likely
Yeah, it's not great. I'd really like to have a set of helper functions that locate and decode the data for the most common types of properties, but I've not sat down to focus on it and I've not seen a pattern I'm happy with yet. It does need to be solved though. The
Yes, looking at the examples you've got below it looks like you've got a similar set of issues to the ones that I've been running into trying to factor the register map access code out of ASoC.
Quoted 17 lines
Perhaps something like:
/* Not sure about this; in this case the return value is an error code so that bad properties can be detected */
intdt_decode_cell(struct *property, int index, u32 *out_val); intdt_decode_string(struct *property, int index, char **out_val); intdt_decode_number(struct *property, int start, int len, unsigned long long *out_val);and perhaps a set of companion functions:
intdt_get_prop_cell(struct *device_node, char *propname, int index, u32 *out_val);
intdt_get_prop_string(struct *device_node, char *propname, int index, char **out_val);
intdt_get_prop_number(struct *device_node, char *propname, int start, int len, unsigned long long *out_val);
Quoted 5 lines
The first set would be used when the property pointer has already be obtained, and multiple datum need to be extracted. The second would be most useful when only one value will be extracted from a property. I'm not totally happy with returning the value via a passed in pointer though. Thoughts?
Yes, I think this sort of format with the error out of band from the number is best if a little ugly, and especially the second set is definitely going to cut down the amount of boiler plate code. It's a little painful having to pass a pointer to the result but otherwise the error handling gets a bit rubbish, especially for the numbers where there really isn't a sensible invalid value.
RFC 3/3 ARM:Tegra: Device Tree Support: Initialize from wm8903 the device tree
In reply to Mark BrownQuoted 53 lines · Mark Brown
Quoted 7 lines · John Bonesio
This patch makes it so the wm8903 is initialized from it's device tree node.
Signed-off-by John Bonesio<[email protected]>---
?arch/arm/boot/dts/tegra-harmony.dts | ? 17 ++++++ ?sound/soc/codecs/wm8903.c ? ? ? ? ? | ? 93 +++++++++++++++++++++++++++++++++--
This needs to be sent separately to the relevant mailing lists and maintainers. ?You can't go making substantial changes to drivers without even telling the maintainers about it - this will apply to any device tree work you're doing. ?In this case one of the maintainers happens to be me, but even so.
Quoted 4 lines
+ ? ? ? ? ? ? ? ? ? ? interrupts = < 347 >;
+ ? ? ? ? ? ? ? ? ? ? irq-active-low = <0>;
+ ? ? ? ? ? ? ? ? ? ? micdet-cfg = <0>;
+ ? ? ? ? ? ? ? ? ? ? micdet-delay = <100>;Some of this looks like chip default, why is it being configured?
Quoted 2 lines
+ ? ? ? ? ? ? ? ? ? ? ? gpio-controller;
+ ? ? ? ? ? ? ? ? ? ? ? #gpio-cells = <2>;The fact that this device is a GPIO controller is a physical property of the device, we shouldn't need to be putting it into the device tree.
Quoted 1 line
+ ? ? ? ? ? ? ? ? ? ? gpio-num-cfg = < 5 >;
Similarly here, the device has a fixed number of GPIOs.
Quoted 2 lines
+ ? ? ? ? ? ? ? ? ? ? /* #define
WM8903_GPIO_NO_CONFIG0x8000*/
+ ? ? ? ? ? ? ? ? ? ? gpio-cfg = <0x80000x800000x80000x8000>;This doesn't seem great for usability. ?I'd suggest key/value pairs rather than an array.
Quoted 11 lines
- ? ? if (pdata &&
pdata->gpio_base)
+ ? ?wm8903->gpio_chip.base= -1;
+ ? ? if (pdata &&pdata->gpio_base) {
? ? ? ? ? ? ?wm8903->gpio_chip.base=pdata->gpio_base;
- ? ? else
- ? ? ? ? ? ?wm8903->gpio_chip.base= -1;
+ ? ? } else if (codec->dev->of_node) {
+ ? ? ? ? ? ? prop =of_get_property(codec->dev->of_node, "gpio-base", NULL);
+ ? ? ? ? ? ? if (prop)
+ ? ? ? ? ? ? ? ? ? ?wm8903->gpio_chip.base=be32_to_cpup(prop);
+ ? ? }We have to do manual endianness conversions to read from the device tree? ?Oh, well.
Quoted 9 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+ + ? ? ? ? ? ? prop = of_get_property(codec->dev->of_node, "interrupts", NULL); + ? ? ? ? ? ? if (prop) + ? ? ? ? ? ? ? ? ? ? wm8903->irq = be32_to_cpup(prop); +We have a standard way of passing the IRQ number to I2C devices, surely we should make sure that works at the bus level rather than having to replicate this code everywhere?
Yes actually there is. The code in drivers/of/of_i2c.c already correctly populates the i2c_client irq from the device tree. This hunk can be completely removed.
g.