mbox series

[v4,0/7] ASoC: add driver for Atmel I2S controller

Message ID 1527251668-31396-1-git-send-email-codrin.ciubotariu@microchip.com
Headers show
Series ASoC: add driver for Atmel I2S controller | expand

Message

Codrin Ciubotariu May 25, 2018, 12:34 p.m. UTC
This is a rework of Cyrille's patches named:
[PATCH v3 0/2] ASoC: add driver for Atmel I2S controller
https://lkml.org/lkml/2015/9/29/454

This is the version 4 of the series, and addresses the received feedback
on the mailing lists.

This series applies on top of asoc-next branch of broonie/sound.git.

Based on received feedback, I created a mux clock driver to select the I2S
clock source, that also includes proper devicetree bindings and nodes.
Also, I added the I2S nodes in sama5d2's devicetree, with the missing
pin muxing for the second I2S controller.

This series of patches adds support to the new Atmel I2S controller
embedded on sama5d2 SoCs.

ChangeLog

v3 -> v4
 - as suggested by Rob Herring:
   - added a clock mux driver for I2S's clock control bit;
   - more precise description of I2S's devicetree bindings;
   - removed SoC and internal detalls from bindings;
 - addressed comments from Mark Brown;
 - added devicetree nodes and pin muxing for I2S;

v2 -> v3
- fix the coding style, add some more comments and add a section dedicated
  to sama5d2 SoCs in the DT binding documentation as suggested by Mark
  Brown.

v1 -> v2
- initialize dev->dev before calling dev->caps->mck_init()


Codrin Ciubotariu (3):
  dt-bindings: clk: at91: add an I2S mux clock
  clk: at91: add I2S clock mux driver
  ARM: dts: at91: sama5d2: add I2S clock muxing nodes

Cyrille Pitchen (4):
  ASoC: atmel-i2s: dt-bindings: add DT bindings for I2S controller
  ASoC: atmel-i2s: add driver for the new Atmel I2S controller
  ARM: dts: at91: sama5d2: add nodes for I2S controllers
  ARM: dts: at91: sama5d2 Xplained: add pin muxing for I2S

 .../devicetree/bindings/clock/at91-clock.txt       |  34 +
 .../devicetree/bindings/sound/atmel-i2s.txt        |  47 ++
 arch/arm/boot/dts/at91-sama5d2_xplained.dts        |  28 +
 arch/arm/boot/dts/sama5d2.dtsi                     |  52 ++
 arch/arm/mach-at91/Kconfig                         |   4 +
 drivers/clk/at91/Makefile                          |   1 +
 drivers/clk/at91/clk-i2s-mux.c                     | 117 ++++
 sound/soc/atmel/Kconfig                            |   9 +
 sound/soc/atmel/Makefile                           |   2 +
 sound/soc/atmel/atmel-i2s.c                        | 765 +++++++++++++++++++++
 10 files changed, 1059 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/atmel-i2s.txt
 create mode 100644 drivers/clk/at91/clk-i2s-mux.c
 create mode 100644 sound/soc/atmel/atmel-i2s.c

Comments

Stephen Boyd May 31, 2018, 3:26 p.m. UTC | #1
Quoting Codrin Ciubotariu (2018-05-25 05:34:23)
> This driver is a simple muxing driver that controls the
> I2S's clock input by using syscon/regmap to change the parrent.

s/parrent/parent/

> The available inputs can be Peripheral clock and Generated clock.

Why capitalize peripheral and generated?

> 
> Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
> ---
> diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
> index 1254bf9..903f23c 100644
> --- a/arch/arm/mach-at91/Kconfig
> +++ b/arch/arm/mach-at91/Kconfig
> @@ -27,6 +27,7 @@ config SOC_SAMA5D2
>         select HAVE_AT91_H32MX
>         select HAVE_AT91_GENERATED_CLK
>         select HAVE_AT91_AUDIO_PLL
> +       select HAVE_AT91_I2S_MUX_CLK
>         select PINCTRL_AT91PIO4
>         help
>           Select this if ou are using one of Microchip's SAMA5D2 family SoC.
> @@ -129,6 +130,9 @@ config HAVE_AT91_GENERATED_CLK
>  config HAVE_AT91_AUDIO_PLL
>         bool
>  
> +config HAVE_AT91_I2S_MUX_CLK
> +       bool
> +
>  config SOC_SAM_V4_V5
>         bool
>  

I guess this is OK.

> diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
> index 082596f..facc169 100644
> --- a/drivers/clk/at91/Makefile
> +++ b/drivers/clk/at91/Makefile
> @@ -13,3 +13,4 @@ obj-$(CONFIG_HAVE_AT91_USB_CLK)               += clk-usb.o
>  obj-$(CONFIG_HAVE_AT91_SMD)            += clk-smd.o
>  obj-$(CONFIG_HAVE_AT91_H32MX)          += clk-h32mx.o
>  obj-$(CONFIG_HAVE_AT91_GENERATED_CLK)  += clk-generated.o
> +obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK)    += clk-i2s-mux.o
> diff --git a/drivers/clk/at91/clk-i2s-mux.c b/drivers/clk/at91/clk-i2s-mux.c
> new file mode 100644
> index 0000000..2d56ded
> --- /dev/null
> +++ b/drivers/clk/at91/clk-i2s-mux.c
> @@ -0,0 +1,117 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + *  Copyright (C) 2018 Microchip Technology Inc,
> + *                     Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
> + *
> + *
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +
> +#include <soc/at91/atmel-sfr.h>
> +
> +#define        I2S_BUS_NR      2
> +
> +struct clk_i2s_mux {
> +       struct clk_hw hw;
> +       struct regmap *regmap;
> +       u32 bus_id;

Can be a u8?

> +};
> +
> +#define to_clk_i2s_mux(hw) container_of(hw, struct clk_i2s_mux, hw)
> +
> +static u8 clk_i2s_mux_get_parent(struct clk_hw *hw)
> +{
> +       struct clk_i2s_mux *mux = to_clk_i2s_mux(hw);
> +       u32 val;
> +
> +       regmap_read(mux->regmap, AT91_SFR_I2SCLKSEL, &val);
> +
> +       return (val & BIT(mux->bus_id)) >> mux->bus_id;
> +}
> +
> +static int clk_i2s_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       struct clk_i2s_mux *mux = to_clk_i2s_mux(hw);
> +
> +       return regmap_update_bits(mux->regmap, AT91_SFR_I2SCLKSEL,
> +                                 BIT(mux->bus_id), index << mux->bus_id);
> +}
> +
> +const struct clk_ops clk_i2s_mux_ops = {

static?

> +       .get_parent = clk_i2s_mux_get_parent,
> +       .set_parent = clk_i2s_mux_set_parent,
> +       .determine_rate = __clk_mux_determine_rate,
> +};
> +
> +static struct clk_hw * __init
> +at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
> +                         const char * const *parent_names,
> +                         unsigned int num_parents, u32 bus_id)
> +{
> +       struct clk_init_data init = {};
> +       struct clk_i2s_mux *i2s_ck;
> +       int ret;
> +
> +       i2s_ck = kzalloc(sizeof(*i2s_ck), GFP_KERNEL);
> +       if (!i2s_ck)
> +               return ERR_PTR(-ENOMEM);
> +
> +       init.name = name;
> +       init.ops = &clk_i2s_mux_ops;
> +       init.parent_names = parent_names;
> +       init.num_parents = num_parents;
> +       init.flags = CLK_IGNORE_UNUSED;

Really? Why?

> +
> +       i2s_ck->hw.init = &init;
> +       i2s_ck->bus_id = bus_id;
> +       i2s_ck->regmap = regmap;
> +
> +       ret = clk_hw_register(NULL, &i2s_ck->hw);
> +       if (ret) {
> +               kfree(i2s_ck);
> +               return ERR_PTR(ret);
> +       }
> +
> +       return &i2s_ck->hw;
> +}
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Codrin Ciubotariu June 4, 2018, 8:20 a.m. UTC | #2
On 31.05.2018 18:26, Stephen Boyd wrote:
> Quoting Codrin Ciubotariu (2018-05-25 05:34:23)
>> This driver is a simple muxing driver that controls the
>> I2S's clock input by using syscon/regmap to change the parrent.
> 
> s/parrent/parent/

I will fix it.

> 
>> The available inputs can be Peripheral clock and Generated clock.
> 
> Why capitalize peripheral and generated?

In DS, at I2S block these clocks appear defined with capital letters... 
I will fix it.

> 
>>
>> Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
>> ---
>> diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
>> index 1254bf9..903f23c 100644
>> --- a/arch/arm/mach-at91/Kconfig
>> +++ b/arch/arm/mach-at91/Kconfig
>> @@ -27,6 +27,7 @@ config SOC_SAMA5D2
>>          select HAVE_AT91_H32MX
>>          select HAVE_AT91_GENERATED_CLK
>>          select HAVE_AT91_AUDIO_PLL
>> +       select HAVE_AT91_I2S_MUX_CLK
>>          select PINCTRL_AT91PIO4
>>          help
>>            Select this if ou are using one of Microchip's SAMA5D2 family SoC.
>> @@ -129,6 +130,9 @@ config HAVE_AT91_GENERATED_CLK
>>   config HAVE_AT91_AUDIO_PLL
>>          bool
>>   
>> +config HAVE_AT91_I2S_MUX_CLK
>> +       bool
>> +
>>   config SOC_SAM_V4_V5
>>          bool
>>   
> 
> I guess this is OK.
> 
>> diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
>> index 082596f..facc169 100644
>> --- a/drivers/clk/at91/Makefile
>> +++ b/drivers/clk/at91/Makefile
>> @@ -13,3 +13,4 @@ obj-$(CONFIG_HAVE_AT91_USB_CLK)               += clk-usb.o
>>   obj-$(CONFIG_HAVE_AT91_SMD)            += clk-smd.o
>>   obj-$(CONFIG_HAVE_AT91_H32MX)          += clk-h32mx.o
>>   obj-$(CONFIG_HAVE_AT91_GENERATED_CLK)  += clk-generated.o
>> +obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK)    += clk-i2s-mux.o
>> diff --git a/drivers/clk/at91/clk-i2s-mux.c b/drivers/clk/at91/clk-i2s-mux.c
>> new file mode 100644
>> index 0000000..2d56ded
>> --- /dev/null
>> +++ b/drivers/clk/at91/clk-i2s-mux.c
>> @@ -0,0 +1,117 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + *  Copyright (C) 2018 Microchip Technology Inc,
>> + *                     Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
>> + *
>> + *
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/of.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/regmap.h>
>> +#include <linux/slab.h>
>> +
>> +#include <soc/at91/atmel-sfr.h>
>> +
>> +#define        I2S_BUS_NR      2
>> +
>> +struct clk_i2s_mux {
>> +       struct clk_hw hw;
>> +       struct regmap *regmap;
>> +       u32 bus_id;
> 
> Can be a u8?

I think so, I will cast out_value parameter of of_property_read_u32() to u8.

> 
>> +};
>> +
>> +#define to_clk_i2s_mux(hw) container_of(hw, struct clk_i2s_mux, hw)
>> +
>> +static u8 clk_i2s_mux_get_parent(struct clk_hw *hw)
>> +{
>> +       struct clk_i2s_mux *mux = to_clk_i2s_mux(hw);
>> +       u32 val;
>> +
>> +       regmap_read(mux->regmap, AT91_SFR_I2SCLKSEL, &val);
>> +
>> +       return (val & BIT(mux->bus_id)) >> mux->bus_id;
>> +}
>> +
>> +static int clk_i2s_mux_set_parent(struct clk_hw *hw, u8 index)
>> +{
>> +       struct clk_i2s_mux *mux = to_clk_i2s_mux(hw);
>> +
>> +       return regmap_update_bits(mux->regmap, AT91_SFR_I2SCLKSEL,
>> +                                 BIT(mux->bus_id), index << mux->bus_id);
>> +}
>> +
>> +const struct clk_ops clk_i2s_mux_ops = {
> 
> static?

Yes, I will fix it.

> 
>> +       .get_parent = clk_i2s_mux_get_parent,
>> +       .set_parent = clk_i2s_mux_set_parent,
>> +       .determine_rate = __clk_mux_determine_rate,
>> +};
>> +
>> +static struct clk_hw * __init
>> +at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
>> +                         const char * const *parent_names,
>> +                         unsigned int num_parents, u32 bus_id)
>> +{
>> +       struct clk_init_data init = {};
>> +       struct clk_i2s_mux *i2s_ck;
>> +       int ret;
>> +
>> +       i2s_ck = kzalloc(sizeof(*i2s_ck), GFP_KERNEL);
>> +       if (!i2s_ck)
>> +               return ERR_PTR(-ENOMEM);
>> +
>> +       init.name = name;
>> +       init.ops = &clk_i2s_mux_ops;
>> +       init.parent_names = parent_names;
>> +       init.num_parents = num_parents;
>> +       init.flags = CLK_IGNORE_UNUSED;
> 
> Really? Why?

I am thinking that there is no need to gate this clock, since there is 
no way to gate this clock in HW.

> 
>> +
>> +       i2s_ck->hw.init = &init;
>> +       i2s_ck->bus_id = bus_id;
>> +       i2s_ck->regmap = regmap;
>> +
>> +       ret = clk_hw_register(NULL, &i2s_ck->hw);
>> +       if (ret) {
>> +               kfree(i2s_ck);
>> +               return ERR_PTR(ret);
>> +       }
>> +
>> +       return &i2s_ck->hw;
>> +}

Thank you for your review. I will wait a few more days for more comments 
on this series and send a V5 afterwards.

Best regards,
Codrin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Stephen Boyd June 12, 2018, 4:33 p.m. UTC | #3
Quoting Codrin Ciubotariu (2018-06-04 01:20:29)
> On 31.05.2018 18:26, Stephen Boyd wrote:
> > Quoting Codrin Ciubotariu (2018-05-25 05:34:23)
> > 
> >> +       .get_parent = clk_i2s_mux_get_parent,
> >> +       .set_parent = clk_i2s_mux_set_parent,
> >> +       .determine_rate = __clk_mux_determine_rate,
> >> +};
> >> +
> >> +static struct clk_hw * __init
> >> +at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
> >> +                         const char * const *parent_names,
> >> +                         unsigned int num_parents, u32 bus_id)
> >> +{
> >> +       struct clk_init_data init = {};
> >> +       struct clk_i2s_mux *i2s_ck;
> >> +       int ret;
> >> +
> >> +       i2s_ck = kzalloc(sizeof(*i2s_ck), GFP_KERNEL);
> >> +       if (!i2s_ck)
> >> +               return ERR_PTR(-ENOMEM);
> >> +
> >> +       init.name = name;
> >> +       init.ops = &clk_i2s_mux_ops;
> >> +       init.parent_names = parent_names;
> >> +       init.num_parents = num_parents;
> >> +       init.flags = CLK_IGNORE_UNUSED;
> > 
> > Really? Why?
> 
> I am thinking that there is no need to gate this clock, since there is 
> no way to gate this clock in HW.

This flag is not necessary if the clk can't be gated via hardware
control registers. Please remove the flag.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html