[RFC PATCH 3/3] ASoC: soc-pcm: apply BE HW constraint rules

2021-03-23 Thread Codrin Ciubotariu
Apply the HW constraint rules added by the BE DAIs. The constraint rules
are applied after the fixup is called for the HW parameters. This way, if
the HW parameters do not correspond with the HW capabilities, the
constraint rules will return an error. The mask and the interval
constraints are the same as the ones used for FE. The DAI link
dpcm_merged_* flags are used to check if the FE and BE must share the same
HW parameters.

Signed-off-by: Codrin Ciubotariu 
---
 include/sound/pcm.h |  2 ++
 sound/core/pcm_native.c | 17 +
 sound/soc/soc-pcm.c | 30 ++
 3 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 198d37d04d78..b56a4435439a 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -987,6 +987,8 @@ int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule);
 
 int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct 
snd_pcm_hw_params *params);
+int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params);
 
 int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, 
snd_pcm_hw_param_t var,
 u_int64_t mask);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index d6f14162bce5..2ff6e182c7f5 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -326,11 +327,10 @@ static int constrain_interval_params(struct 
snd_pcm_substream *substream,
return 0;
 }
 
-static int constrain_params_by_rules(struct snd_pcm_substream *substream,
-struct snd_pcm_hw_params *params)
+int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
 {
-   struct snd_pcm_hw_constraints *constrs =
-   >runtime->hw_constraints;
+   struct snd_pcm_hw_constraints *constrs;
unsigned int k;
unsigned int *rstamps;
unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
@@ -342,6 +342,14 @@ static int constrain_params_by_rules(struct 
snd_pcm_substream *substream,
bool again;
int changed, err = 0;
 
+   if (substream->pcm->internal) {
+   struct snd_soc_pcm_runtime *rtd = 
asoc_substream_to_rtd(substream);
+
+   constrs = >dpcm[substream->stream].hw_constraints;
+   } else {
+   constrs = >runtime->hw_constraints;
+   }
+
/*
 * Each application of rule has own sequence number.
 *
@@ -446,6 +454,7 @@ static int constrain_params_by_rules(struct 
snd_pcm_substream *substream,
kfree(rstamps);
return err;
 }
+EXPORT_SYMBOL(constrain_params_by_rules);
 
 static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
 struct snd_pcm_hw_params *params)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index dae246918e0d..5bd71d48c0de 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1934,11 +1934,25 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime 
*fe, int stream)
memcpy(>hw_params, >dpcm[stream].hw_params,
sizeof(struct snd_pcm_hw_params));
 
+   /* copy FE mask and interval constraints */
+   memcpy(>dpcm[stream].hw_constraints.masks,
+  _substream->runtime->hw_constraints.masks,
+  sizeof(be_substream->runtime->hw_constraints.masks));
+   memcpy(>dpcm[stream].hw_constraints.intervals,
+  _substream->runtime->hw_constraints.intervals,
+  sizeof(be_substream->runtime->hw_constraints.intervals));
+
/* perform any hw_params fixups */
ret = snd_soc_link_be_hw_params_fixup(be, >hw_params);
if (ret < 0)
goto unwind;
 
+   /* apply constrain rules */
+   dpcm->hw_params.rmask = ~0U;
+   ret = constrain_params_by_rules(be_substream, >hw_params);
+   if (ret < 0)
+   goto unwind;
+
/* copy the fixed-up hw params for BE dai */
memcpy(>dpcm[stream].hw_params, >hw_params,
   sizeof(struct snd_pcm_hw_params));
@@ -2002,6 +2016,22 @@ static int dpcm_fe_dai_hw_params(struct 
snd_pcm_substream *substream,
 
memcpy(>dpcm[stream].hw_params, params,
sizeof(struct snd_pcm_hw_params));
+   if (!fe->dai_link->dpcm_merged_format) {
+   snd_mask_any(hw_param_mask(>dpcm[stream].hw_params,
+  

[RFC PATCH 2/3] ASoC: soc-pcm: add hw_constraints for BE DAI links

2021-03-23 Thread Codrin Ciubotariu
Add a new struct snd_pcm_hw_constraints under struct snd_soc_dpcm_runtime.
The BE DAIs can use the new structure to add constraints that will not
affect the FE of the PCM and will only apply to BE HW parameters.

Signed-off-by: Codrin Ciubotariu 
---
 include/sound/pcm.h  |  9 
 include/sound/soc-dpcm.h |  1 +
 sound/core/pcm_lib.c | 12 +--
 sound/core/pcm_native.c  | 20 ++
 sound/soc/soc-pcm.c  | 44 
 5 files changed, 76 insertions(+), 10 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index af7fce2b574d..198d37d04d78 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -977,6 +977,15 @@ int snd_interval_ratnum(struct snd_interval *i,
 void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params);
 void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, 
snd_pcm_hw_param_t var);
 
+int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
+   struct snd_pcm_hw_rule *rule);
+int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
+  struct snd_pcm_hw_rule *rule);
+int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params,
+   struct snd_pcm_hw_rule *rule);
+int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params,
+   struct snd_pcm_hw_rule *rule);
+
 int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct 
snd_pcm_hw_params *params);
 
 int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, 
snd_pcm_hw_param_t var,
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
index e296a3949b18..c5825876824a 100644
--- a/include/sound/soc-dpcm.h
+++ b/include/sound/soc-dpcm.h
@@ -95,6 +95,7 @@ struct snd_soc_dpcm_runtime {
int users;
struct snd_pcm_runtime *runtime;
struct snd_pcm_hw_params hw_params;
+   struct snd_pcm_hw_constraints hw_constraints;
 
/* state and update */
enum snd_soc_dpcm_update runtime_update;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 582144f99045..125fafdf7517 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "pcm_local.h"
@@ -1121,12 +1122,19 @@ int snd_pcm_hw_rule_add(struct snd_pcm_substream 
*substream, unsigned int cond,
snd_pcm_hw_rule_func_t func, void *private,
int dep, ...)
 {
-   struct snd_pcm_hw_constraints *constrs =
-   >runtime->hw_constraints;
+   struct snd_pcm_hw_constraints *constrs;
struct snd_pcm_hw_rule *c;
unsigned int k;
va_list args;
 
+   if (substream->pcm->internal) {
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_dpcm_runtime *dpcm = 
>dpcm[substream->stream];
+
+   constrs = >hw_constraints;
+   } else {
+   constrs = >runtime->hw_constraints;
+   }
va_start(args, dep);
if (constrs->rules_num >= constrs->rules_all) {
struct snd_pcm_hw_rule *new;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 5feeef1b43f1..d6f14162bce5 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2278,23 +2278,25 @@ static int snd_pcm_unlink(struct snd_pcm_substream 
*substream)
 /*
  * hw configurator
  */
-static int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params,
-  struct snd_pcm_hw_rule *rule)
+int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params,
+   struct snd_pcm_hw_rule *rule)
 {
struct snd_interval t;
snd_interval_mul(hw_param_interval_c(params, rule->deps[0]),
 hw_param_interval_c(params, rule->deps[1]), );
return snd_interval_refine(hw_param_interval(params, rule->var), );
 }
+EXPORT_SYMBOL(snd_pcm_hw_rule_mul);
 
-static int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params,
-  struct snd_pcm_hw_rule *rule)
+int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params,
+   struct snd_pcm_hw_rule *rule)
 {
struct snd_interval t;
snd_interval_div(hw_param_interval_c(params, rule->deps[0]),
 hw_param_interval_c(params, rule->deps[1]), );
return snd_interval_refine(hw_param_interval(params, rule->var), );
 }
+EXPORT_SYMBOL(snd_pcm_hw_rule_div);
 
 static int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params,
   struct snd_pcm_hw_rule *rule)
@@ -2316,8 +2318,8 @@ static int snd_pcm_hw_rule_mulkdiv(struct 
snd_pcm_hw_params *params,
return snd_interval_refine(hw_param_interval(params, rule->var), );
 }
 
-static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params

[RFC PATCH 0/3] Separate BE DAI HW constraints from FE ones

2021-03-23 Thread Codrin Ciubotariu
HW constraints are needed to set limitations for HW parameters used to
configure the DAIs. All DAIs on the same link must agree upon the HW
parameters, so the parameters are affected by the DAIs' features and
their limitations. In case of DPCM, the FE DAIs can be used to perform
different kind of conversions, such as format or rate changing, bringing
the audio stream to a configuration supported by all the DAIs of the BE's
link. For this reason, the limitations of the BE DAIs are not always
important for the HW parameters between user-space and FE, only for the
paratemers between FE and BE DAI links. This brings us to this patch-set,
which aims to separate the FE HW constraints from the BE HW constraints.
This way, the FE can be used to perform more efficient HW conversions, on
the initial audio stream parameters, to parameters supported by the BE
DAIs.
To achieve this, the first thing needed is to detect whether a HW
constraint rule is enforced by a FE or a BE DAI. This means that
snd_pcm_hw_rule_add() needs to be able to differentiate between the two
type of DAIs. For this, the runtime pointer to struct snd_pcm_runtime is
replaced with a pointer to struct snd_pcm_substream, to be able to reach
substream->pcm->internal to differentiate between FE and BE DAIs.
This change affects many sound drivers (and one gpu drm driver).
All these changes are included in the first patch, to have a better
overview of the implications created by this change.
The second patch adds a new struct snd_pcm_hw_constraints under struct
snd_soc_dpcm_runtime, which is used to store the HW constraint rules
added by the BE DAIs. This structure is initialized with a subset of the
runtime constraint rules which does not include the rules that affect
the buffer or period size. snd_pcm_hw_rule_add() will add the BE rules
to the new struct snd_pcm_hw_constraints.
The third and last patch will apply the BE rule constraints, after the
fixup callback. If the fixup HW parameters do not respect the BE
constraint rules, the rules will exit with an error. The FE mask and
interval constraints are copied to the BE ones, to satisfy the
dai_link->dpcm_merged_* flags. The dai_link->dpcm_merged_* flags are
used to know if the FE does format or sampling rate conversion.

I tested with ad1934 and wm8731 codecs as BEs, with a not-yet-mainlined
ASRC as FE, that can also do format conversion. I realize that the
change to snd_pcm_hw_rule_add() has a big impact, even though all the
drivers use snd_pcm_hw_rule_add() with substream->runtime, so passing
substream instead of runtime is not that risky.

Codrin Ciubotariu (3):
  pcm: use substream instead of runtime in snd_pcm_hw_rule_add()
  ASoC: soc-pcm: add hw_constraints for BE DAI links
  ASoC: soc-pcm: apply BE HW constraint rules

 drivers/gpu/drm/vc4/vc4_hdmi.c|  2 +-
 include/sound/ac97_codec.h|  2 +-
 include/sound/pcm.h   | 29 +--
 include/sound/pcm_drm_eld.h   |  2 +-
 include/sound/soc-dpcm.h  |  1 +
 sound/arm/aaci.c  |  4 +-
 sound/arm/pxa2xx-pcm-lib.c|  4 +-
 sound/core/pcm_drm_eld.c  |  6 +-
 sound/core/pcm_lib.c  | 66 ---
 sound/core/pcm_native.c   | 83 +++
 sound/drivers/aloop.c |  8 +-
 sound/drivers/vx/vx_pcm.c |  8 +-
 sound/firewire/amdtp-am824.c  |  8 +-
 sound/firewire/amdtp-am824.h  |  2 +-
 sound/firewire/amdtp-stream.c | 12 +--
 sound/firewire/amdtp-stream.h |  2 +-
 sound/firewire/bebob/bebob_pcm.c  |  6 +-
 sound/firewire/dice/dice-pcm.c|  6 +-
 sound/firewire/digi00x/amdtp-dot.c|  6 +-
 sound/firewire/digi00x/digi00x-pcm.c  |  6 +-
 sound/firewire/digi00x/digi00x.h  |  2 +-
 sound/firewire/fireface/amdtp-ff.c|  6 +-
 sound/firewire/fireface/ff-pcm.c  |  6 +-
 sound/firewire/fireface/ff.h  |  2 +-
 sound/firewire/fireworks/fireworks_pcm.c  |  6 +-
 sound/firewire/motu/amdtp-motu.c  |  6 +-
 sound/firewire/motu/motu-pcm.c|  6 +-
 sound/firewire/motu/motu.h|  2 +-
 sound/firewire/oxfw/oxfw-pcm.c|  6 +-
 sound/firewire/tascam/amdtp-tascam.c  |  6 +-
 sound/firewire/tascam/tascam-pcm.c|  2 +-
 sound/firewire/tascam/tascam.h|  2 +-
 sound/pci/ac97/ac97_pcm.c |  8 +-
 sound/pci/ali5451/ali5451.c   |  2 +-
 sound/pci/atiixp.c|  2 +-
 sound/pci/atiixp_modem.c  |  2 +-
 sound/pci/au88x0/au88x0_pcm.c |  6 +-
 sound/pci/azt3328.c   |  2 +-
 sound/pci/bt87x.c |  8 +-
 sound/pci/ca010

[PATCH v2 4/7] dt-bindings: mchp,i2s-mcc: Add property to specify pin pair for TDM

2021-03-01 Thread Codrin Ciubotariu
SAMA7G5's I2S-MCC has 4 pairs of DIN/DOUT pins. Since TDM only uses a
single pair of pins for synchronous capture and playback, the controller
needs to be told which of the pair is connected. This can be mentioned
using the new "microchip,tdm-data-pair" property. The property is optional,
needed only if TDM is used, and if it's missing DIN/DOUT 0 pins will be
used by default.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
- changes are done to mchp-i2s-mcc.txt insted of mchp,i2s-mcc.yaml

 Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt 
b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt
index 2180dbd9ea81..af8fe3e657df 100644
--- a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt
+++ b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt
@@ -19,7 +19,12 @@ Required properties:
 Optional properties:
 - pinctrl-0:  Should specify pin control groups used for this controller.
 - princtrl-names: Should contain only one value - "default".
-
+- microchip,tdm-data-pair: 8 bit value that represents the DIN/DOUT pair pins
+  which are used to receive/send TDM data. It is 
optional
+  and it is only needed if the controller uses the TDM
+  mode. Not available for "microchip,sam9x60-i2smcc"
+  compatible. If it's not present, the default value 
is 0,
+  so the DIN/DOUT 0 pins are used.
 
 (1) : Only the peripheral clock is required. The generated clock is optional
   and should be set mostly when Master Mode is required.
-- 
2.27.0



[PATCH v2 6/7] ASoC: mchp-i2s-mcc: Add FIFOs support

2021-03-01 Thread Codrin Ciubotariu
I2S-MCC found on SAMA7G5 includes 2 FIFOs (capture and playback). When
FIFOs are enabled, bits I2SMCC_ISRA.TXLRDYx and I2SMCC_ISRA.TXRRDYx must
not be used. Bits I2SMCC_ISRB.TXFFRDY and I2SMCC_ISRB.RXFFRDY must be used
instead.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
- none

 sound/soc/atmel/mchp-i2s-mcc.c | 76 +-
 1 file changed, 56 insertions(+), 20 deletions(-)

diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 515ba3634fdd..673bc16cb46a 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -176,7 +176,7 @@
  */
 #define MCHP_I2SMCC_MRB_CRAMODE_REGULAR(1 << 0)
 
-#define MCHP_I2SMCC_MRB_FIFOEN BIT(1)
+#define MCHP_I2SMCC_MRB_FIFOEN BIT(4)
 
 #define MCHP_I2SMCC_MRB_DMACHUNK_MASK  GENMASK(9, 8)
 #define MCHP_I2SMCC_MRB_DMACHUNK(no_words) \
@@ -230,6 +230,7 @@ static const struct regmap_config 
mchp_i2s_mcc_regmap_config = {
 
 struct mchp_i2s_mcc_soc_data {
unsigned intdata_pin_pair_num;
+   boolhas_fifo;
 };
 
 struct mchp_i2s_mcc_dev {
@@ -257,7 +258,7 @@ struct mchp_i2s_mcc_dev {
 static irqreturn_t mchp_i2s_mcc_interrupt(int irq, void *dev_id)
 {
struct mchp_i2s_mcc_dev *dev = dev_id;
-   u32 sra, imra, srb, imrb, pendinga, pendingb, idra = 0;
+   u32 sra, imra, srb, imrb, pendinga, pendingb, idra = 0, idrb = 0;
irqreturn_t ret = IRQ_NONE;
 
regmap_read(dev->regmap, MCHP_I2SMCC_IMRA, );
@@ -275,24 +276,36 @@ static irqreturn_t mchp_i2s_mcc_interrupt(int irq, void 
*dev_id)
 * Tx/Rx ready interrupts are enabled when stopping only, to assure
 * availability and to disable clocks if necessary
 */
-   idra |= pendinga & (MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels) |
-   MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
-   if (idra)
+   if (dev->soc->has_fifo) {
+   idrb |= pendingb & (MCHP_I2SMCC_INT_TXFFRDY |
+   MCHP_I2SMCC_INT_RXFFRDY);
+   } else {
+   idra |= pendinga & (MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels) |
+   MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
+   }
+   if (idra || idrb)
ret = IRQ_HANDLED;
 
-   if ((imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) &&
-   (imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) ==
-   (idra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels))) {
+   if ((!dev->soc->has_fifo &&
+(imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) &&
+(imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) ==
+(idra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels))) ||
+   (dev->soc->has_fifo && imrb & MCHP_I2SMCC_INT_TXFFRDY)) {
dev->tx_rdy = 1;
wake_up_interruptible(>wq_txrdy);
}
-   if ((imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) &&
-   (imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) ==
-   (idra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels))) {
+   if ((!dev->soc->has_fifo &&
+(imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) &&
+(imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) ==
+(idra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels))) ||
+   (dev->soc->has_fifo && imrb & MCHP_I2SMCC_INT_RXFFRDY)) {
dev->rx_rdy = 1;
wake_up_interruptible(>wq_rxrdy);
}
-   regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra);
+   if (dev->soc->has_fifo)
+   regmap_write(dev->regmap, MCHP_I2SMCC_IDRB, idrb);
+   else
+   regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra);
 
return ret;
 }
@@ -664,6 +677,10 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream 
*substream,
}
}
 
+   /* enable FIFO if available */
+   if (dev->soc->has_fifo)
+   mrb |= MCHP_I2SMCC_MRB_FIFOEN;
+
/*
 * If we are already running, the wanted setup must be
 * the same with the one that's currently ongoing
@@ -726,8 +743,13 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream 
*substream,
if (err == 0) {
dev_warn_once(dev->dev,
  "Timeout waiting for Tx ready\n");
-   regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
-MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels));
+   if (dev->soc->has_fifo)
+   regmap_write(dev->regmap, MCHP_I2SMCC_IDRB,
+  

[PATCH v2 5/7] ASoC: mchp-i2s-mcc: Add support to select TDM pins

2021-03-01 Thread Codrin Ciubotariu
SAMA7G5's I2S-MCC has 4 pairs of DIN/DOUT pins. Since TDM only uses a
single pair of pins for synchronous capture and playback, the controller
needs to be told which of the pair is connected. This can be mentioned
using the "microchip,tdm-data-pair" property from DT. The property is
optional, useful only if TDM is used. If it's missing, DIN/DOUT 0 pins
will be used by default.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
- none

 sound/soc/atmel/mchp-i2s-mcc.c | 52 +++---
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 52d3f43148dc..515ba3634fdd 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -100,6 +100,8 @@
 #define MCHP_I2SMCC_MRA_DATALENGTH_8_BITS_COMPACT  (7 << 1)
 
 #define MCHP_I2SMCC_MRA_WIRECFG_MASK   GENMASK(5, 4)
+#define MCHP_I2SMCC_MRA_WIRECFG_TDM(pin)   (((pin) << 4) & \
+MCHP_I2SMCC_MRA_WIRECFG_MASK)
 #define MCHP_I2SMCC_MRA_WIRECFG_I2S_1_TDM_0(0 << 4)
 #define MCHP_I2SMCC_MRA_WIRECFG_I2S_2_TDM_1(1 << 4)
 #define MCHP_I2SMCC_MRA_WIRECFG_I2S_4_TDM_2(2 << 4)
@@ -245,6 +247,7 @@ struct mchp_i2s_mcc_dev {
unsigned intframe_length;
int tdm_slots;
int channels;
+   u8  tdm_data_pair;
unsigned intgclk_use:1;
unsigned intgclk_running:1;
unsigned inttx_rdy:1;
@@ -589,6 +592,8 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream 
*substream,
if (!frame_length)
frame_length = 2 * params_physical_width(params);
} else if (dev->fmt & SND_SOC_DAIFMT_DSP_A) {
+   mra |= MCHP_I2SMCC_MRA_WIRECFG_TDM(dev->tdm_data_pair);
+
if (dev->tdm_slots) {
if (channels % 2 && channels * 2 <= dev->tdm_slots) {
/*
@@ -914,6 +919,45 @@ static const struct of_device_id mchp_i2s_mcc_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, mchp_i2s_mcc_dt_ids);
 #endif
 
+static int mchp_i2s_mcc_soc_data_parse(struct platform_device *pdev,
+  struct mchp_i2s_mcc_dev *dev)
+{
+   int err;
+
+   if (!dev->soc) {
+   dev_err(>dev, "failed to get soc data\n");
+   return -ENODEV;
+   }
+
+   if (dev->soc->data_pin_pair_num == 1)
+   return 0;
+
+   err = of_property_read_u8(pdev->dev.of_node, "microchip,tdm-data-pair",
+ >tdm_data_pair);
+   if (err < 0 && err != -EINVAL) {
+   dev_err(>dev,
+   "bad property data for 'microchip,tdm-data-pair': %d",
+   err);
+   return err;
+   }
+   if (err == -EINVAL) {
+   dev_info(>dev,
+"'microchip,tdm-data-pair' not found; assuming 
DIN/DOUT 0 for TDM\n");
+   dev->tdm_data_pair = 0;
+   } else {
+   if (dev->tdm_data_pair > dev->soc->data_pin_pair_num - 1) {
+   dev_err(>dev,
+   "invalid value for 'microchip,tdm-data-pair': 
%d\n",
+   dev->tdm_data_pair);
+   return -EINVAL;
+   }
+   dev_dbg(>dev, "TMD format on DIN/DOUT %d pins\n",
+   dev->tdm_data_pair);
+   }
+
+   return 0;
+}
+
 static int mchp_i2s_mcc_probe(struct platform_device *pdev)
 {
struct mchp_i2s_mcc_dev *dev;
@@ -966,10 +1010,10 @@ static int mchp_i2s_mcc_probe(struct platform_device 
*pdev)
}
 
dev->soc = of_device_get_match_data(>dev);
-   if (!dev->soc) {
-   dev_err(>dev, "failed to get soc data\n");
-   return -ENODEV;
-   }
+   err = mchp_i2s_mcc_soc_data_parse(pdev, dev);
+   if (err < 0)
+   return err;
+
dev->dev = >dev;
dev->regmap = regmap;
platform_set_drvdata(pdev, dev);
-- 
2.27.0



[PATCH v2 3/7] ASoC: mchp-i2s-mcc: Add multi-channel support for I2S and LEFT_J formats

2021-03-01 Thread Codrin Ciubotariu
The latest I2S-MCC available in SAMA7G5 supports multi-channel for I2S and
Left-Justified formats. For this, the new version uses 8 (4 * 2) input and
output pins, with each pin being responsible for 2 channels. This sums up
to a total of 8 channels for synchronous capture and playback.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
- none

 sound/soc/atmel/mchp-i2s-mcc.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 0ee01383e307..52d3f43148dc 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -225,6 +226,10 @@ static const struct regmap_config 
mchp_i2s_mcc_regmap_config = {
.max_register = MCHP_I2SMCC_VERSION,
 };
 
+struct mchp_i2s_mcc_soc_data {
+   unsigned intdata_pin_pair_num;
+};
+
 struct mchp_i2s_mcc_dev {
struct wait_queue_head  wq_txrdy;
struct wait_queue_head  wq_rxrdy;
@@ -232,6 +237,7 @@ struct mchp_i2s_mcc_dev {
struct regmap   *regmap;
struct clk  *pclk;
struct clk  *gclk;
+   const struct mchp_i2s_mcc_soc_data  *soc;
struct snd_dmaengine_dai_dma_data   playback;
struct snd_dmaengine_dai_dma_data   capture;
unsigned intfmt;
@@ -549,6 +555,17 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream 
*substream,
}
 
if (dev->fmt & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) {
+   /* for I2S and LEFT_J one pin is needed for every 2 channels */
+   if (channels > dev->soc->data_pin_pair_num * 2) {
+   dev_err(dev->dev,
+   "unsupported number of audio channels: %d\n",
+   channels);
+   return -EINVAL;
+   }
+
+   /* enable for interleaved format */
+   mrb |= MCHP_I2SMCC_MRB_CRAMODE_REGULAR;
+
switch (channels) {
case 1:
if (is_playback)
@@ -558,6 +575,12 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream 
*substream,
break;
case 2:
break;
+   case 4:
+   mra |= MCHP_I2SMCC_MRA_WIRECFG_I2S_2_TDM_1;
+   break;
+   case 8:
+   mra |= MCHP_I2SMCC_MRA_WIRECFG_I2S_4_TDM_2;
+   break;
default:
dev_err(dev->dev, "unsupported number of audio 
channels\n");
return -EINVAL;
@@ -869,12 +892,22 @@ static const struct snd_soc_component_driver 
mchp_i2s_mcc_component = {
 };
 
 #ifdef CONFIG_OF
+static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sam9x60 = {
+   .data_pin_pair_num = 1,
+};
+
+static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sama7g5 = {
+   .data_pin_pair_num = 4,
+};
+
 static const struct of_device_id mchp_i2s_mcc_dt_ids[] = {
{
.compatible = "microchip,sam9x60-i2smcc",
+   .data = _i2s_mcc_sam9x60,
},
{
.compatible = "microchip,sama7g5-i2smcc",
+   .data = _i2s_mcc_sama7g5,
},
{ /* sentinel */ }
 };
@@ -932,6 +965,11 @@ static int mchp_i2s_mcc_probe(struct platform_device *pdev)
dev->gclk = NULL;
}
 
+   dev->soc = of_device_get_match_data(>dev);
+   if (!dev->soc) {
+   dev_err(>dev, "failed to get soc data\n");
+   return -ENODEV;
+   }
dev->dev = >dev;
dev->regmap = regmap;
platform_set_drvdata(pdev, dev);
-- 
2.27.0



[PATCH v2 2/7] ASoC: mchp-i2s-mcc: Add compatible for SAMA7G5

2021-03-01 Thread Codrin Ciubotariu
Microchip's new SAMA7G5 includes an updated I2S-MCC compatible with the
previous version found on SAM9X60. The new controller includes 8 (4 * 2)
input and output data pins for up to 8 channels for I2S and Left-Justified
formats.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
- none

 sound/soc/atmel/Kconfig| 3 +++
 sound/soc/atmel/mchp-i2s-mcc.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 9fe9471f4514..ec04e3386bc0 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -127,10 +127,13 @@ config SND_MCHP_SOC_I2S_MCC
  Say Y or M if you want to add support for I2S Multi-Channel ASoC
  driver on the following Microchip platforms:
  - sam9x60
+ - sama7g5
 
  The I2SMCC complies with the Inter-IC Sound (I2S) bus specification
  and supports a Time Division Multiplexed (TDM) interface with
  external multi-channel audio codecs.
+ Starting with sama7g5, I2S and Left-Justified multi-channel is
+ supported by using multiple data pins, output and input, without TDM.
 
 config SND_MCHP_SOC_SPDIFTX
tristate "Microchip ASoC driver for boards using S/PDIF TX"
diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 6d5ae18f8b38..0ee01383e307 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -873,6 +873,9 @@ static const struct of_device_id mchp_i2s_mcc_dt_ids[] = {
{
.compatible = "microchip,sam9x60-i2smcc",
},
+   {
+   .compatible = "microchip,sama7g5-i2smcc",
+   },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mchp_i2s_mcc_dt_ids);
-- 
2.27.0



[PATCH v2 7/7] ASoC: convert Microchip I2SMCC binding to yaml

2021-03-01 Thread Codrin Ciubotariu
This patch converts the Microchip I2SMCC bindings to DT schema format
using json-schema.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
- moved from the beginning to the end of the patch series;
- includes the changes (to yaml) from the rest of the patches that
  update the DT binding;

 .../bindings/sound/mchp,i2s-mcc.yaml  | 108 ++
 .../bindings/sound/mchp-i2s-mcc.txt   |  49 
 2 files changed, 108 insertions(+), 49 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
 delete mode 100644 Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt

diff --git a/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml 
b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
new file mode 100644
index ..0481315cb5f2
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
@@ -0,0 +1,108 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mchp,i2s-mcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip I2S Multi-Channel Controller
+
+maintainers:
+  - Codrin Ciubotariu 
+
+description:
+  The I2SMCC complies with the Inter-IC Sound (I2S) bus specification and
+  supports a Time Division Multiplexed (TDM) interface with external
+  multi-channel audio codecs. It consists of a receiver, a transmitter and a
+  common clock generator that can be enabled separately to provide Adapter,
+  Client or Controller modes with receiver and/or transmitter active.
+  On later I2SMCC versions (starting with Microchip's SAMA7G5) I2S
+  multi-channel is supported by using multiple data pins, output and
+  input, without TDM.
+
+properties:
+  "#sound-dai-cells":
+const: 0
+
+  compatible:
+enum:
+  - microchip,sam9x60-i2smcc
+  - microchip,sama7g5-i2smcc
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  clocks:
+items:
+  - description: Peripheral Bus Clock
+  - description: Generic Clock (Optional). Should be set mostly when Master
+  Mode is required.
+minItems: 1
+
+  clock-names:
+items:
+  - const: pclk
+  - const: gclk
+minItems: 1
+
+  dmas:
+items:
+  - description: TX DMA Channel
+  - description: RX DMA Channel
+
+  dma-names:
+items:
+  - const: tx
+  - const: rx
+
+  microchip,tdm-data-pair:
+description:
+  Represents the DIN/DOUT pair pins that are used to receive/send
+  TDM data. It is optional and it is only needed if the controller
+  uses the TDM mode.
+$ref: /schemas/types.yaml#/definitions/uint8
+enum: [0, 1, 2, 3]
+default: 0
+
+if:
+  properties:
+compatible:
+  const: microchip,sam9x60-i2smcc
+then:
+  properties:
+microchip,tdm-data-pair: false
+
+required:
+  - "#sound-dai-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+
+i2s@f001c000 {
+#sound-dai-cells = <0>;
+compatible = "microchip,sam9x60-i2smcc";
+reg = <0xf001c000 0x100>;
+interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>;
+dmas = < (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+   AT91_XDMAC_DT_PERID(36))>,
+   < (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+   AT91_XDMAC_DT_PERID(37))>;
+dma-names = "tx", "rx";
+clocks = <_clk>, <_gclk>;
+clock-names = "pclk", "gclk";
+pinctrl-names = "default";
+pinctrl-0 = <_i2s_default>;
+};
diff --git a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt 
b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt
deleted file mode 100644
index af8fe3e657df..
--- a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-* Microchip I2S Multi-Channel Controller
-
-Required properties:
-- compatible: Should be "microchip,sam9x60-i2smcc" or
- "microchip,sama7g5-i2smcc".
-- reg:Should be the physical base address of the controller and the
-  length of memory mapped region.
-- interrupts: Should contain the interrupt for the controller.
-- dmas:   Should be one per channel name listed in the dma-names 
property,
-  as described in atmel-dma.txt and dma.txt files.
-- dma-names:  Identifier string for each DMA request line in the dmas 
property.
- Two dmas have to be defined, "tx" and "rx".
-- clocks: Must contain an entry for each entry in clock-names.
-  Please refer to clock-bindings.txt.
-- clock-names:Should be one of each entry matching the clocks p

[PATCH v2 0/7] Add I2S-MCC support for Microchip's SAMA7G5

2021-03-01 Thread Codrin Ciubotariu
SAMA7G5 includes an updated version of I2S-MCC, found previously on
SAM9X60. This controller includes 8 data pins, 4 for playback and 4 for
capture. For I2S and LEFT_J formats, these pins can be used to
send/receive up to 8 audio channels. For DSP_A, with TDM, any pins pair
(DIN/DOUT) from these 4 can be selected to send/receive data. This
version also includes 2 FIFOs (send and receive).
This patch set starts by moving the driver's bindings to yaml and
continues with adding a new compatible for the SAMA7G5 variant, followed
by the changes needed for I2S/LEFT_J support, TDM pin pair selection and
FIFO support, exclusively for SAMA7G5.

Changes in v2:
- moved DT binding conversion patch from the beginning to the end of the
  patch serieses
- patches that update the DT binding are modified to change .txt file
  instead of .yaml

Codrin Ciubotariu (7):
  dt-bindings: mchp,i2s-mcc: Add SAMA7G5 to binding
  ASoC: mchp-i2s-mcc: Add compatible for SAMA7G5
  ASoC: mchp-i2s-mcc: Add multi-channel support for I2S and LEFT_J
formats
  dt-bindings: mchp,i2s-mcc: Add property to specify pin pair for TDM
  ASoC: mchp-i2s-mcc: Add support to select TDM pins
  ASoC: mchp-i2s-mcc: Add FIFOs support
  ASoC: convert Microchip I2SMCC binding to yaml

 .../bindings/sound/mchp,i2s-mcc.yaml  | 108 
 .../bindings/sound/mchp-i2s-mcc.txt   |  43 -
 sound/soc/atmel/Kconfig   |   3 +
 sound/soc/atmel/mchp-i2s-mcc.c| 161 +++---
 4 files changed, 252 insertions(+), 63 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
 delete mode 100644 Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt

-- 
2.27.0



[PATCH v2 1/7] dt-bindings: mchp,i2s-mcc: Add SAMA7G5 to binding

2021-03-01 Thread Codrin Ciubotariu
SAMA7G5 includes an updated version of the I2S-MCC driver, that includes
3 more DIN/DOUT pin pairs for multi-channel.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
- changes are done to mchp-i2s-mcc.txt insted of mchp,i2s-mcc.yaml

 Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt 
b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt
index 91ec83a6faed..2180dbd9ea81 100644
--- a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt
+++ b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt
@@ -1,7 +1,8 @@
 * Microchip I2S Multi-Channel Controller
 
 Required properties:
-- compatible: Should be "microchip,sam9x60-i2smcc".
+- compatible: Should be "microchip,sam9x60-i2smcc" or
+ "microchip,sama7g5-i2smcc".
 - reg:Should be the physical base address of the controller and the
   length of memory mapped region.
 - interrupts: Should contain the interrupt for the controller.
-- 
2.27.0



[PATCH 7/7] ASoC: mchp-i2s-mcc: Add FIFOs support

2021-02-23 Thread Codrin Ciubotariu
I2S-MCC found on SAMA7G5 includes 2 FIFOs (capture and playback). When
FIFOs are enabled, bits I2SMCC_ISRA.TXLRDYx and I2SMCC_ISRA.TXRRDYx must
not be used. Bits I2SMCC_ISRB.TXFFRDY and I2SMCC_ISRB.RXFFRDY must be used
instead.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/mchp-i2s-mcc.c | 76 +-
 1 file changed, 56 insertions(+), 20 deletions(-)

diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 3d13efb11444..f951fa0f39fd 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -176,7 +176,7 @@
  */
 #define MCHP_I2SMCC_MRB_CRAMODE_REGULAR(1 << 0)
 
-#define MCHP_I2SMCC_MRB_FIFOEN BIT(1)
+#define MCHP_I2SMCC_MRB_FIFOEN BIT(4)
 
 #define MCHP_I2SMCC_MRB_DMACHUNK_MASK  GENMASK(9, 8)
 #define MCHP_I2SMCC_MRB_DMACHUNK(no_words) \
@@ -230,6 +230,7 @@ static const struct regmap_config 
mchp_i2s_mcc_regmap_config = {
 
 struct mchp_i2s_mcc_soc_data {
unsigned intdata_pin_pair_num;
+   boolhas_fifo;
 };
 
 struct mchp_i2s_mcc_dev {
@@ -257,7 +258,7 @@ struct mchp_i2s_mcc_dev {
 static irqreturn_t mchp_i2s_mcc_interrupt(int irq, void *dev_id)
 {
struct mchp_i2s_mcc_dev *dev = dev_id;
-   u32 sra, imra, srb, imrb, pendinga, pendingb, idra = 0;
+   u32 sra, imra, srb, imrb, pendinga, pendingb, idra = 0, idrb = 0;
irqreturn_t ret = IRQ_NONE;
 
regmap_read(dev->regmap, MCHP_I2SMCC_IMRA, );
@@ -275,24 +276,36 @@ static irqreturn_t mchp_i2s_mcc_interrupt(int irq, void 
*dev_id)
 * Tx/Rx ready interrupts are enabled when stopping only, to assure
 * availability and to disable clocks if necessary
 */
-   idra |= pendinga & (MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels) |
-   MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
-   if (idra)
+   if (dev->soc->has_fifo) {
+   idrb |= pendingb & (MCHP_I2SMCC_INT_TXFFRDY |
+   MCHP_I2SMCC_INT_RXFFRDY);
+   } else {
+   idra |= pendinga & (MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels) |
+   MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels));
+   }
+   if (idra || idrb)
ret = IRQ_HANDLED;
 
-   if ((imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) &&
-   (imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) ==
-   (idra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels))) {
+   if ((!dev->soc->has_fifo &&
+(imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) &&
+(imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) ==
+(idra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels))) ||
+   (dev->soc->has_fifo && imrb & MCHP_I2SMCC_INT_TXFFRDY)) {
dev->tx_rdy = 1;
wake_up_interruptible(>wq_txrdy);
}
-   if ((imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) &&
-   (imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) ==
-   (idra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels))) {
+   if ((!dev->soc->has_fifo &&
+(imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) &&
+(imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) ==
+(idra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels))) ||
+   (dev->soc->has_fifo && imrb & MCHP_I2SMCC_INT_RXFFRDY)) {
dev->rx_rdy = 1;
wake_up_interruptible(>wq_rxrdy);
}
-   regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra);
+   if (dev->soc->has_fifo)
+   regmap_write(dev->regmap, MCHP_I2SMCC_IDRB, idrb);
+   else
+   regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra);
 
return ret;
 }
@@ -664,6 +677,10 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream 
*substream,
}
}
 
+   /* enable FIFO if available */
+   if (dev->soc->has_fifo)
+   mrb |= MCHP_I2SMCC_MRB_FIFOEN;
+
/*
 * If we are already running, the wanted setup must be
 * the same with the one that's currently ongoing
@@ -726,8 +743,13 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream 
*substream,
if (err == 0) {
dev_warn_once(dev->dev,
  "Timeout waiting for Tx ready\n");
-   regmap_write(dev->regmap, MCHP_I2SMCC_IDRA,
-MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels));
+   if (dev->soc->has_fifo)
+   regmap_write(dev->regmap, MCHP_I2SMCC_IDRB,
+  

[PATCH 4/7] ASoC: mchp-i2s-mcc: Add multi-channel support for I2S and LEFT_J formats

2021-02-23 Thread Codrin Ciubotariu
The latest I2S-MCC available in SAMA7G5 supports multi-channel for I2S and
Left-Justified formats. For this, the new version uses 8 (4 * 2) input and
output pins, with each pin being responsible for 2 channels. This sums up
to a total of 8 channels for synchronous capture and playback.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/mchp-i2s-mcc.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 0ee01383e307..52d3f43148dc 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -225,6 +226,10 @@ static const struct regmap_config 
mchp_i2s_mcc_regmap_config = {
.max_register = MCHP_I2SMCC_VERSION,
 };
 
+struct mchp_i2s_mcc_soc_data {
+   unsigned intdata_pin_pair_num;
+};
+
 struct mchp_i2s_mcc_dev {
struct wait_queue_head  wq_txrdy;
struct wait_queue_head  wq_rxrdy;
@@ -232,6 +237,7 @@ struct mchp_i2s_mcc_dev {
struct regmap   *regmap;
struct clk  *pclk;
struct clk  *gclk;
+   const struct mchp_i2s_mcc_soc_data  *soc;
struct snd_dmaengine_dai_dma_data   playback;
struct snd_dmaengine_dai_dma_data   capture;
unsigned intfmt;
@@ -549,6 +555,17 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream 
*substream,
}
 
if (dev->fmt & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) {
+   /* for I2S and LEFT_J one pin is needed for every 2 channels */
+   if (channels > dev->soc->data_pin_pair_num * 2) {
+   dev_err(dev->dev,
+   "unsupported number of audio channels: %d\n",
+   channels);
+   return -EINVAL;
+   }
+
+   /* enable for interleaved format */
+   mrb |= MCHP_I2SMCC_MRB_CRAMODE_REGULAR;
+
switch (channels) {
case 1:
if (is_playback)
@@ -558,6 +575,12 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream 
*substream,
break;
case 2:
break;
+   case 4:
+   mra |= MCHP_I2SMCC_MRA_WIRECFG_I2S_2_TDM_1;
+   break;
+   case 8:
+   mra |= MCHP_I2SMCC_MRA_WIRECFG_I2S_4_TDM_2;
+   break;
default:
dev_err(dev->dev, "unsupported number of audio 
channels\n");
return -EINVAL;
@@ -869,12 +892,22 @@ static const struct snd_soc_component_driver 
mchp_i2s_mcc_component = {
 };
 
 #ifdef CONFIG_OF
+static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sam9x60 = {
+   .data_pin_pair_num = 1,
+};
+
+static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sama7g5 = {
+   .data_pin_pair_num = 4,
+};
+
 static const struct of_device_id mchp_i2s_mcc_dt_ids[] = {
{
.compatible = "microchip,sam9x60-i2smcc",
+   .data = _i2s_mcc_sam9x60,
},
{
.compatible = "microchip,sama7g5-i2smcc",
+   .data = _i2s_mcc_sama7g5,
},
{ /* sentinel */ }
 };
@@ -932,6 +965,11 @@ static int mchp_i2s_mcc_probe(struct platform_device *pdev)
dev->gclk = NULL;
}
 
+   dev->soc = of_device_get_match_data(>dev);
+   if (!dev->soc) {
+   dev_err(>dev, "failed to get soc data\n");
+   return -ENODEV;
+   }
dev->dev = >dev;
dev->regmap = regmap;
platform_set_drvdata(pdev, dev);
-- 
2.27.0



[PATCH 5/7] dt-bindings: mchp,i2s-mcc: Add property to specify pin pair for TDM

2021-02-23 Thread Codrin Ciubotariu
SAMA7G5's I2S-MCC has 4 pairs of DIN/DOUT pins. Since TDM only uses a
single pair of pins for synchronous capture and playback, the controller
needs to be told which of the pair is connected. This can be mentioned
using the new "microchip,tdm-data-pair" property. The property is optional,
needed only if TDM is used, and if it's missing DIN/DOUT 0 pins will be
used by default.

Signed-off-by: Codrin Ciubotariu 
---
 .../devicetree/bindings/sound/mchp,i2s-mcc.yaml | 17 +
 1 file changed, 17 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml 
b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
index a8a73f3ed473..0481315cb5f2 100644
--- a/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
+++ b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
@@ -57,6 +57,23 @@ properties:
   - const: tx
   - const: rx
 
+  microchip,tdm-data-pair:
+description:
+  Represents the DIN/DOUT pair pins that are used to receive/send
+  TDM data. It is optional and it is only needed if the controller
+  uses the TDM mode.
+$ref: /schemas/types.yaml#/definitions/uint8
+enum: [0, 1, 2, 3]
+default: 0
+
+if:
+  properties:
+compatible:
+  const: microchip,sam9x60-i2smcc
+then:
+  properties:
+microchip,tdm-data-pair: false
+
 required:
   - "#sound-dai-cells"
   - compatible
-- 
2.27.0



[PATCH 1/7] ASoC: convert Microchip I2SMCC binding to yaml

2021-02-23 Thread Codrin Ciubotariu
This patch converts the Microchip I2SMCC bindings to DT schema format
using json-schema.

Signed-off-by: Codrin Ciubotariu 
---
 .../bindings/sound/mchp,i2s-mcc.yaml  | 86 +++
 .../bindings/sound/mchp-i2s-mcc.txt   | 43 --
 2 files changed, 86 insertions(+), 43 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
 delete mode 100644 Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt

diff --git a/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml 
b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
new file mode 100644
index ..79445f5f2804
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mchp,i2s-mcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip I2S Multi-Channel Controller
+
+maintainers:
+  - Codrin Ciubotariu 
+
+description:
+  The I2SMCC complies with the Inter-IC Sound (I2S) bus specification and
+  supports a Time Division Multiplexed (TDM) interface with external
+  multi-channel audio codecs. It consists of a receiver, a transmitter and a
+  common clock generator that can be enabled separately to provide Adapter,
+  Client or Controller modes with receiver and/or transmitter active.
+
+properties:
+  "#sound-dai-cells":
+const: 0
+
+  compatible:
+const: microchip,sam9x60-i2smcc
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  clocks:
+items:
+  - description: Peripheral Bus Clock
+  - description: Generic Clock (Optional). Should be set mostly when Master
+  Mode is required.
+minItems: 1
+
+  clock-names:
+items:
+  - const: pclk
+  - const: gclk
+minItems: 1
+
+  dmas:
+items:
+  - description: TX DMA Channel
+  - description: RX DMA Channel
+
+  dma-names:
+items:
+  - const: tx
+  - const: rx
+
+required:
+  - "#sound-dai-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+
+i2s@f001c000 {
+#sound-dai-cells = <0>;
+compatible = "microchip,sam9x60-i2smcc";
+reg = <0xf001c000 0x100>;
+interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>;
+dmas = < (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+   AT91_XDMAC_DT_PERID(36))>,
+   < (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+   AT91_XDMAC_DT_PERID(37))>;
+dma-names = "tx", "rx";
+clocks = <_clk>, <_gclk>;
+clock-names = "pclk", "gclk";
+pinctrl-names = "default";
+pinctrl-0 = <_i2s_default>;
+};
diff --git a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt 
b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt
deleted file mode 100644
index 91ec83a6faed..
--- a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-* Microchip I2S Multi-Channel Controller
-
-Required properties:
-- compatible: Should be "microchip,sam9x60-i2smcc".
-- reg:Should be the physical base address of the controller and the
-  length of memory mapped region.
-- interrupts: Should contain the interrupt for the controller.
-- dmas:   Should be one per channel name listed in the dma-names 
property,
-  as described in atmel-dma.txt and dma.txt files.
-- dma-names:  Identifier string for each DMA request line in the dmas 
property.
- Two dmas have to be defined, "tx" and "rx".
-- clocks: Must contain an entry for each entry in clock-names.
-  Please refer to clock-bindings.txt.
-- clock-names:Should be one of each entry matching the clocks phandles 
list:
-  - "pclk" (peripheral clock) Required.
-  - "gclk" (generated clock) Optional (1).
-
-Optional properties:
-- pinctrl-0:  Should specify pin control groups used for this controller.
-- princtrl-names: Should contain only one value - "default".
-
-
-(1) : Only the peripheral clock is required. The generated clock is optional
-  and should be set mostly when Master Mode is required.
-
-Example:
-
-   i2s@f001c000 {
-   compatible = "microchip,sam9x60-i2smcc";
-   reg = <0xf001c000 0x100>;
-   interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>;
-   dmas = <
-   (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
-AT91_XDMAC_DT_PERID(36))>,
-

[PATCH 6/7] ASoC: mchp-i2s-mcc: Add support to select TDM pins

2021-02-23 Thread Codrin Ciubotariu
SAMA7G5's I2S-MCC has 4 pairs of DIN/DOUT pins. Since TDM only uses a
single pair of pins for synchronous capture and playback, the controller
needs to be told which of the pair is connected. This can be mentioned
using the "microchip,tdm-data-pair" property from DT. The property is
optional, useful only if TDM is used. If it's missing, DIN/DOUT 0 pins
will be used by default.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/mchp-i2s-mcc.c | 52 +++---
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 52d3f43148dc..3d13efb11444 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -100,6 +100,8 @@
 #define MCHP_I2SMCC_MRA_DATALENGTH_8_BITS_COMPACT  (7 << 1)
 
 #define MCHP_I2SMCC_MRA_WIRECFG_MASK   GENMASK(5, 4)
+#define MCHP_I2SMCC_MRA_WIRECFG_TDM(pin)   (((pin) << 4) & \
+MCHP_I2SMCC_MRA_WIRECFG_MASK)
 #define MCHP_I2SMCC_MRA_WIRECFG_I2S_1_TDM_0(0 << 4)
 #define MCHP_I2SMCC_MRA_WIRECFG_I2S_2_TDM_1(1 << 4)
 #define MCHP_I2SMCC_MRA_WIRECFG_I2S_4_TDM_2(2 << 4)
@@ -245,6 +247,7 @@ struct mchp_i2s_mcc_dev {
unsigned intframe_length;
int tdm_slots;
int channels;
+   u8  tdm_data_pair;
unsigned intgclk_use:1;
unsigned intgclk_running:1;
unsigned inttx_rdy:1;
@@ -589,6 +592,8 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream 
*substream,
if (!frame_length)
frame_length = 2 * params_physical_width(params);
} else if (dev->fmt & SND_SOC_DAIFMT_DSP_A) {
+   mra |= MCHP_I2SMCC_MRA_WIRECFG_TDM(dev->tdm_data_pair);
+
if (dev->tdm_slots) {
if (channels % 2 && channels * 2 <= dev->tdm_slots) {
/*
@@ -914,6 +919,45 @@ static const struct of_device_id mchp_i2s_mcc_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, mchp_i2s_mcc_dt_ids);
 #endif
 
+static int mchp_i2s_mcc_soc_data_parse(struct platform_device *pdev,
+  struct mchp_i2s_mcc_dev *dev)
+{
+   int err;
+
+   if (!dev->soc) {
+   dev_err(>dev, "failed to get soc data\n");
+   return -ENODEV;
+   }
+
+   if (dev->soc->data_pin_pair_num == 1)
+   return 0;
+
+   err = of_property_read_u8(pdev->dev.of_node, "microchip,tdm-data-pair",
+ >tdm_data_pair);
+   if (err < 0 && err != -EINVAL) {
+   dev_err(>dev,
+   "bad property data for 'microchip,tdm-data-pair': %d",
+   err);
+   return err;
+   }
+   if (err == -EINVAL) {
+   dev_info(>dev,
+   "'microchip,tdm-data-pair' not found; assuming DIN/DOUT 
0 for TDM\n");
+   dev->tdm_data_pair = 0;
+   } else {
+   if (dev->tdm_data_pair > dev->soc->data_pin_pair_num - 1) {
+   dev_err(>dev,
+   "invalid value for 'microchip,tdm-data-pair': 
%d\n",
+   dev->tdm_data_pair);
+   return -EINVAL;
+   }
+   dev_dbg(>dev, "TMD format on DIN/DOUT %d pins\n",
+   dev->tdm_data_pair);
+   }
+
+   return 0;
+}
+
 static int mchp_i2s_mcc_probe(struct platform_device *pdev)
 {
struct mchp_i2s_mcc_dev *dev;
@@ -966,10 +1010,10 @@ static int mchp_i2s_mcc_probe(struct platform_device 
*pdev)
}
 
dev->soc = of_device_get_match_data(>dev);
-   if (!dev->soc) {
-   dev_err(>dev, "failed to get soc data\n");
-   return -ENODEV;
-   }
+   err = mchp_i2s_mcc_soc_data_parse(pdev, dev);
+   if (err < 0)
+   return err;
+
dev->dev = >dev;
dev->regmap = regmap;
platform_set_drvdata(pdev, dev);
-- 
2.27.0



[PATCH 3/7] ASoC: mchp-i2s-mcc: Add compatible for SAMA7G5

2021-02-23 Thread Codrin Ciubotariu
Microchip's new SAMA7G5 includes an updated I2S-MCC compatible with the
previous version found on SAM9X60. The new controller includes 8 (4 * 2)
input and output data pins for up to 8 channels for I2S and Left-Justified
formats.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/Kconfig| 3 +++
 sound/soc/atmel/mchp-i2s-mcc.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 9fe9471f4514..ec04e3386bc0 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -127,10 +127,13 @@ config SND_MCHP_SOC_I2S_MCC
  Say Y or M if you want to add support for I2S Multi-Channel ASoC
  driver on the following Microchip platforms:
  - sam9x60
+ - sama7g5
 
  The I2SMCC complies with the Inter-IC Sound (I2S) bus specification
  and supports a Time Division Multiplexed (TDM) interface with
  external multi-channel audio codecs.
+ Starting with sama7g5, I2S and Left-Justified multi-channel is
+ supported by using multiple data pins, output and input, without TDM.
 
 config SND_MCHP_SOC_SPDIFTX
tristate "Microchip ASoC driver for boards using S/PDIF TX"
diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c
index 6d5ae18f8b38..0ee01383e307 100644
--- a/sound/soc/atmel/mchp-i2s-mcc.c
+++ b/sound/soc/atmel/mchp-i2s-mcc.c
@@ -873,6 +873,9 @@ static const struct of_device_id mchp_i2s_mcc_dt_ids[] = {
{
.compatible = "microchip,sam9x60-i2smcc",
},
+   {
+   .compatible = "microchip,sama7g5-i2smcc",
+   },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mchp_i2s_mcc_dt_ids);
-- 
2.27.0



[PATCH 0/7] Add I2S-MCC support for Microchip's SAMA7G5

2021-02-23 Thread Codrin Ciubotariu
SAMA7G5 includes an updated version of I2S-MCC, found previously on
SAM9X60. This controller includes 8 data pins, 4 for playback and 4 for
capture. For I2S and LEFT_J formats, these pins can be used to
send/receive up to 8 audio channels. For DSP_A, with TDM, any pins pair
(DIN/DOUT) from these 4 can be selected to send/receive data. This
version also includes 2 FIFOs (send and receive).
This patch set starts by moving the driver's bindings to yaml and
continues with adding a new compatible for the SAMA7G5 variant, followed
by the changes needed for I2S/LEFT_J support, TDM pin pair selection and
FIFO support, exclusively for SAMA7G5.

Codrin Ciubotariu (7):
  ASoC: convert Microchip I2SMCC binding to yaml
  dt-bindings: mchp,i2s-mcc: Add SAMA7G5 to binding
  ASoC: mchp-i2s-mcc: Add compatible for SAMA7G5
  ASoC: mchp-i2s-mcc: Add multi-channel support for I2S and LEFT_J
formats
  dt-bindings: mchp,i2s-mcc: Add property to specify pin pair for TDM
  ASoC: mchp-i2s-mcc: Add support to select TDM pins
  ASoC: mchp-i2s-mcc: Add FIFOs support

 .../bindings/sound/mchp,i2s-mcc.yaml  | 108 
 .../bindings/sound/mchp-i2s-mcc.txt   |  43 -
 sound/soc/atmel/Kconfig   |   3 +
 sound/soc/atmel/mchp-i2s-mcc.c| 161 +++---
 4 files changed, 252 insertions(+), 63 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
 delete mode 100644 Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt

-- 
2.27.0



[PATCH 2/7] dt-bindings: mchp,i2s-mcc: Add SAMA7G5 to binding

2021-02-23 Thread Codrin Ciubotariu
SAMA7G5 includes an updated version of the I2S-MCC driver, that includes
3 more DIN/DOUT pin pairs for multi-channel.

Signed-off-by: Codrin Ciubotariu 
---
 Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml 
b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
index 79445f5f2804..a8a73f3ed473 100644
--- a/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
+++ b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
@@ -15,13 +15,18 @@ description:
   multi-channel audio codecs. It consists of a receiver, a transmitter and a
   common clock generator that can be enabled separately to provide Adapter,
   Client or Controller modes with receiver and/or transmitter active.
+  On later I2SMCC versions (starting with Microchip's SAMA7G5) I2S
+  multi-channel is supported by using multiple data pins, output and
+  input, without TDM.
 
 properties:
   "#sound-dai-cells":
 const: 0
 
   compatible:
-const: microchip,sam9x60-i2smcc
+enum:
+  - microchip,sam9x60-i2smcc
+  - microchip,sama7g5-i2smcc
 
   reg:
 maxItems: 1
-- 
2.27.0



[RFC PATCH] ASoC: pcm_dmaengine: Add support for BE DAIs

2020-12-02 Thread Codrin Ciubotariu
Considering the bellow scenarios:
/- Gen DMA engine -\
   48KHz ***   44.1KHz   *** 
*
PCM0 <-FE DAI-> * FE   * <-> * DSP * <-BE DAI-> *  * * * *  
 *
* Ring * * ** Ring * <-> * CPU * <-> * 
Codec *
* buff * **** buff * * DAI * * DAI  
 *
   44.1KHz  *  * * * *  
 *
PCM1 <DAI-> *  * * * *  
 *
 *** 
*

For PCM0, we have two DAI links. The first DAI link is a FE, with a DSP as
a CPU DAI and a platform driver .The second DAI link is a BE DAI link,
with separate CPU, codec and platform drivers. We can also notice that
there are two Ring buffers: the first one used by the DSP to communicate
with the user-space and the second one used to move data between FE
(DSP) and BE (CPU).
PCM1 is a normal DAI link, with a CPU, codec and platform driver. It is
exactly the previous BE DAI link from PCM0, so the samples from user-space
are copied directly into the second Ring buffer.

In this scenario, the BE DAI link driver should be the same, since it is
decided at runtime whether the DAI is a used as a BE or not. The generic
platform driver needs to be aware of this thing. For the BE case (PCM0),
some callbacks of the platform driver are not called, hence the
preallocated buffer is not available. Also, the PCM runtime strcture
must not be touched, since it should be only used by the FE platform
driver.

With these changes, the generic dmaengine can also be used as a BE
platform driver.

Signed-off-by: Codrin Ciubotariu 
---

Hello,
 
This patch is more or less incomplete for the described scenario. This
is because DMAengine's pcm->config is ignored for the BE DAI link, so
runtime->hw is not updated. Also, since pcm_construct/destruct are not
called, the DMA channels are allocated only if DT is used.
Underrun/overrun support would also be a nice to have for the transfers
involving the buffer allocated for the BE.
One way to hold trach of these would be to use a substream_be->runtime
different than the one used for the FE.

Please share your thoughts.

 sound/core/pcm_dmaengine.c| 18 ++--
 sound/soc/soc-generic-dmaengine-pcm.c | 40 +++
 2 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 4d059ff2b2e4..5e96bc27628d 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -137,7 +137,9 @@ static void dmaengine_pcm_dma_complete(void *arg)
if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
prtd->pos = 0;
 
-   snd_pcm_period_elapsed(substream);
+   /* do no update period for an internal PCM */
+   if (!substream->pcm->internal)
+   snd_pcm_period_elapsed(substream);
 }
 
 static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream 
*substream)
@@ -147,6 +149,7 @@ static int dmaengine_pcm_prepare_and_submit(struct 
snd_pcm_substream *substream)
struct dma_async_tx_descriptor *desc;
enum dma_transfer_direction direction;
unsigned long flags = DMA_CTRL_ACK;
+   dma_addr_t addr;
 
direction = snd_pcm_substream_to_dma_direction(substream);
 
@@ -154,11 +157,15 @@ static int dmaengine_pcm_prepare_and_submit(struct 
snd_pcm_substream *substream)
flags |= DMA_PREP_INTERRUPT;
 
prtd->pos = 0;
+   if (substream->pcm->internal)
+   addr = substream->dma_buffer.addr;
+   else
+   addr = substream->runtime->dma_addr;
+
desc = dmaengine_prep_dma_cyclic(chan,
-   substream->runtime->dma_addr,
+   addr,
snd_pcm_lib_buffer_bytes(substream),
snd_pcm_lib_period_bytes(substream), direction, flags);
-
if (!desc)
return -ENOMEM;
 
@@ -315,6 +322,11 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream 
*substream,
 
substream->runtime->private_data = prtd;
 
+   if (substream->pcm->internal) {
+   substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV_IRAM;
+   substream->dma_buffer.dev.dev = chan->device->dev;
+   }
+
return 0;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c 
b/sound/soc/soc-generic-dmaengine-pcm.c
index 9ef80a48707e..f403849cd1aa 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -97,6 +97,31 @@ static int dmaengine_pcm_hw_params(struct snd_soc_component 
*component,
if (ret)
return ret;

[PATCH] ASoC: mchp-spdiftx: Do not set Validity bit(s)

2020-11-04 Thread Codrin Ciubotariu
The Validity bits (bit 28) must not be set in order to have the samples
valid. Some controllers look for this bit and ignore the samples if it
is set.

Fixes: 06ca24e98e6b ("ASoC: mchp-spdiftx: add driver for S/PDIF TX Controller")
Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/mchp-spdiftx.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
index 82c1eecd2528..3bd350afb743 100644
--- a/sound/soc/atmel/mchp-spdiftx.c
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -487,7 +487,6 @@ static int mchp_spdiftx_hw_params(struct snd_pcm_substream 
*substream,
}
mchp_spdiftx_channel_status_write(dev);
spin_unlock_irqrestore(>lock, flags);
-   mr |= SPDIFTX_MR_VALID1 | SPDIFTX_MR_VALID2;
 
if (dev->gclk_enabled) {
clk_disable_unprepare(dev->gclk);
-- 
2.27.0



[PATCH] ASoC: atmel-i2s: do not warn if muxclk is missing

2020-11-03 Thread Codrin Ciubotariu
Besides the fact that muxclk is optional, muxclk can be set using
assigned-clocks, removing the need to set it in driver. The warning is
thus unneeded, so we can transform it in a debug print, eventually to just
reflect that muxclk was not set by the driver.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/atmel-i2s.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c
index bbe2b638abb5..232300dda548 100644
--- a/sound/soc/atmel/atmel-i2s.c
+++ b/sound/soc/atmel/atmel-i2s.c
@@ -563,8 +563,8 @@ static int atmel_i2s_sama5d2_mck_init(struct atmel_i2s_dev 
*dev,
err = PTR_ERR(muxclk);
if (err == -EPROBE_DEFER)
return -EPROBE_DEFER;
-   dev_warn(dev->dev,
-"failed to get the I2S clock control: %d\n", err);
+   dev_dbg(dev->dev,
+   "failed to get the I2S clock control: %d\n", err);
return 0;
}
 
-- 
2.25.1



[PATCH] mfd: at91-usart: do not use compatible to register child devices

2020-11-03 Thread Codrin Ciubotariu
There are no separate serial/SPI devices under the at91-usart MFD, but
actually the MFD is used as a serial or a SPI device. There are no DT
sub-nodes for the MFD children, so we should use platform device API to
register the drivers.

Suggested-by: Lee Jones 
Signed-off-by: Codrin Ciubotariu 
---
 drivers/mfd/at91-usart.c | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/mfd/at91-usart.c b/drivers/mfd/at91-usart.c
index 6a8351a4588e..7f08cb60c58b 100644
--- a/drivers/mfd/at91-usart.c
+++ b/drivers/mfd/at91-usart.c
@@ -15,15 +15,11 @@
 #include 
 #include 
 
-static const struct mfd_cell at91_usart_spi_subdev = {
-   .name = "at91_usart_spi",
-   .of_compatible = "microchip,at91sam9g45-usart-spi",
-};
+static const struct mfd_cell at91_usart_spi_subdev =
+   MFD_CELL_NAME("at91_usart_spi");
 
-static const struct mfd_cell at91_usart_serial_subdev = {
-   .name = "atmel_usart_serial",
-   .of_compatible = "atmel,at91rm9200-usart-serial",
-};
+static const struct mfd_cell at91_usart_serial_subdev =
+   MFD_CELL_NAME("atmel_usart_serial");
 
 static int at91_usart_mode_probe(struct platform_device *pdev)
 {
-- 
2.25.1



[PATCH] ARM: dts: at91: add serial MFD sub-node for usart

2020-10-30 Thread Codrin Ciubotariu
The "atmel,at91sam9260-usart" driver is a MFD driver, so it needs sub-nodes
to match the registered platform device. For this reason, we add a serial
subnode to all the "atmel,at91sam9260-usart" serial compatible nods. This
will also remove the boot warning:
"atmel_usart_serial: Failed to locate of_node [id: -2]"

Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/boot/dts/at91-sam9x60ek.dts |  3 +++
 arch/arm/boot/dts/at91rm9200.dtsi| 15 
 arch/arm/boot/dts/at91sam9261.dtsi   | 12 ++
 arch/arm/boot/dts/at91sam9261ek.dts  |  3 +++
 arch/arm/boot/dts/at91sam9263.dtsi   | 12 ++
 arch/arm/boot/dts/at91sam9g45.dtsi   | 15 
 arch/arm/boot/dts/at91sam9n12.dtsi   | 15 
 arch/arm/boot/dts/at91sam9rl.dtsi| 15 
 arch/arm/boot/dts/at91sam9x5.dtsi| 18 ++
 arch/arm/boot/dts/at91sam9x5_usart3.dtsi |  3 +++
 arch/arm/boot/dts/sam9x60.dtsi   |  3 +++
 arch/arm/boot/dts/sama5d2.dtsi   | 30 
 arch/arm/boot/dts/sama5d3.dtsi   | 18 ++
 arch/arm/boot/dts/sama5d3_uart.dtsi  |  6 +
 arch/arm/boot/dts/sama5d4.dtsi   | 30 
 15 files changed, 198 insertions(+)

diff --git a/arch/arm/boot/dts/at91-sam9x60ek.dts 
b/arch/arm/boot/dts/at91-sam9x60ek.dts
index eae28b82c7fd..e317531f7363 100644
--- a/arch/arm/boot/dts/at91-sam9x60ek.dts
+++ b/arch/arm/boot/dts/at91-sam9x60ek.dts
@@ -280,6 +280,9 @@ AT91_XDMAC_DT_PERID(10))>,
atmel,use-dma-rx;
atmel,use-dma-tx;
status = "okay";
+   serial {
+   compatible = "atmel,at91rm9200-usart-serial";
+   };
};
 };
 
diff --git a/arch/arm/boot/dts/at91rm9200.dtsi 
b/arch/arm/boot/dts/at91rm9200.dtsi
index d1181ead18e5..2abb646f6b68 100644
--- a/arch/arm/boot/dts/at91rm9200.dtsi
+++ b/arch/arm/boot/dts/at91rm9200.dtsi
@@ -602,6 +602,9 @@ dbgu: serial@f200 {
clocks = < PMC_TYPE_CORE PMC_MCK>;
clock-names = "usart";
status = "disabled";
+   serial {
+   compatible = 
"atmel,at91rm9200-usart-serial";
+   };
};
 
usart0: serial@fffc {
@@ -615,6 +618,9 @@ usart0: serial@fffc {
clocks = < PMC_TYPE_PERIPHERAL 6>;
clock-names = "usart";
status = "disabled";
+   serial {
+   compatible = 
"atmel,at91rm9200-usart-serial";
+   };
};
 
usart1: serial@fffc4000 {
@@ -628,6 +634,9 @@ usart1: serial@fffc4000 {
clocks = < PMC_TYPE_PERIPHERAL 7>;
clock-names = "usart";
status = "disabled";
+   serial {
+   compatible = 
"atmel,at91rm9200-usart-serial";
+   };
};
 
usart2: serial@fffc8000 {
@@ -641,6 +650,9 @@ usart2: serial@fffc8000 {
clocks = < PMC_TYPE_PERIPHERAL 8>;
clock-names = "usart";
status = "disabled";
+   serial {
+   compatible = 
"atmel,at91rm9200-usart-serial";
+   };
};
 
usart3: serial@fffcc000 {
@@ -654,6 +666,9 @@ usart3: serial@fffcc000 {
clocks = < PMC_TYPE_PERIPHERAL 9>;
clock-names = "usart";
status = "disabled";
+   serial {
+   compatible = 
"atmel,at91rm9200-usart-serial";
+   };
};
 
usb1: gadget@fffb {
diff --git a/arch/arm/boot/dts/at91sam9261.dtsi 
b/arch/arm/boot/dts/at91sam9261.dtsi
index 7adc36ca8a46..e9602378f92c 100644
--- a/arch/arm/boot/dts/at91sam9261.dtsi
+++ b/arch/arm/boot/dts/at91sam9261.dtsi
@@ -187,6 +187,9 @@ usart0: serial@fffb {
clocks = < PMC_TYPE_PERIPHERAL 6>;
clock-names = "usart";
status = "disabled";
+ 

[PATCH] ASoC: pcm5102a: Make codec selectable

2020-10-12 Thread Codrin Ciubotariu
The TI PCM5102A codec driver can be used with the generic sound card
drivers, so it should be selectable. For example, with the addition
of #sound-dai-cells = <0> property in DT, it can be used with simple/graph
card drivers.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/codecs/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 34c6dd04b85a..5791b7056af6 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1003,7 +1003,7 @@ config SND_SOC_PCM3168A_SPI
select REGMAP_SPI
 
 config SND_SOC_PCM5102A
-   tristate
+   tristate "Texas Instruments PCM5102A CODEC"
 
 config SND_SOC_PCM512x
tristate
-- 
2.25.1



[PATCH] ASoC: mchp-spdiftx: remove 'TX' from playback stream name

2020-10-09 Thread Codrin Ciubotariu
Do not include the 'TX' in the stream name since it's obvious for
playback.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/mchp-spdiftx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
index 36c23eb3a5ad..82c1eecd2528 100644
--- a/sound/soc/atmel/mchp-spdiftx.c
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -744,7 +744,7 @@ static struct snd_soc_dai_driver mchp_spdiftx_dai = {
.probe  = mchp_spdiftx_dai_probe,
.remove = mchp_spdiftx_dai_remove,
.playback = {
-   .stream_name = "S/PDIF TX Playback",
+   .stream_name = "S/PDIF Playback",
.channels_min = 1,
.channels_max = 2,
.rates = MCHP_SPDIFTX_RATES,
-- 
2.25.1



[PATCH v3] i2c: pxa: move to generic GPIO recovery

2020-10-04 Thread Codrin Ciubotariu
Starting with
commit 75820314de26 ("i2c: core: add generic I2C GPIO recovery")
GPIO bus recovery is supported by the I2C core, so we can remove the
driver implementation and use that one instead.

Signed-off-by: Codrin Ciubotariu 
---

patch not tested.

Changes in v3:
 - fix compile errors from unprepare_recovery callback

Changes in v2:
 - readded the pinctrl state change to default from the
   unprepare_recovery callback;

 drivers/i2c/busses/i2c-pxa.c | 76 
 1 file changed, 8 insertions(+), 68 deletions(-)

diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 35ca2c02c9b9..a636ea0eb50a 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -264,9 +264,6 @@ struct pxa_i2c {
u32 hs_mask;
 
struct i2c_bus_recovery_info recovery;
-   struct pinctrl  *pinctrl;
-   struct pinctrl_state*pinctrl_default;
-   struct pinctrl_state*pinctrl_recovery;
 };
 
 #define _IBMR(i2c) ((i2c)->reg_ibmr)
@@ -1305,13 +1302,12 @@ static void i2c_pxa_prepare_recovery(struct i2c_adapter 
*adap)
 */
gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS);
gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS);
-
-   WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery));
 }
 
 static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
 {
struct pxa_i2c *i2c = adap->algo_data;
+   struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
u32 isr;
 
/*
@@ -1325,7 +1321,7 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter 
*adap)
i2c_pxa_do_reset(i2c);
}
 
-   WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default));
+   WARN_ON(pinctrl_select_state(bri->pinctrl, bri->pins_default));
 
dev_dbg(>adap.dev, "recovery: IBMR 0x%08x ISR 0x%08x\n",
readl(_IBMR(i2c)), readl(_ISR(i2c)));
@@ -1347,76 +1343,20 @@ static int i2c_pxa_init_recovery(struct pxa_i2c *i2c)
if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE))
return 0;
 
-   i2c->pinctrl = devm_pinctrl_get(dev);
-   if (PTR_ERR(i2c->pinctrl) == -ENODEV)
-   i2c->pinctrl = NULL;
-   if (IS_ERR(i2c->pinctrl))
-   return PTR_ERR(i2c->pinctrl);
-
-   if (!i2c->pinctrl)
-   return 0;
-
-   i2c->pinctrl_default = pinctrl_lookup_state(i2c->pinctrl,
-   PINCTRL_STATE_DEFAULT);
-   i2c->pinctrl_recovery = pinctrl_lookup_state(i2c->pinctrl, "recovery");
-
-   if (IS_ERR(i2c->pinctrl_default) || IS_ERR(i2c->pinctrl_recovery)) {
-   dev_info(dev, "missing pinmux recovery information: %ld %ld\n",
-PTR_ERR(i2c->pinctrl_default),
-PTR_ERR(i2c->pinctrl_recovery));
-   return 0;
-   }
-
-   /*
-* Claiming GPIOs can influence the pinmux state, and may glitch the
-* I2C bus. Do this carefully.
-*/
-   bri->scl_gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
-   if (bri->scl_gpiod == ERR_PTR(-EPROBE_DEFER))
-   return -EPROBE_DEFER;
-   if (IS_ERR(bri->scl_gpiod)) {
-   dev_info(dev, "missing scl gpio recovery information: %pe\n",
-bri->scl_gpiod);
-   return 0;
-   }
-
-   /*
-* We have SCL. Pull SCL low and wait a bit so that SDA glitches
-* have no effect.
-*/
-   gpiod_direction_output(bri->scl_gpiod, 0);
-   udelay(10);
-   bri->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_OUT_HIGH_OPEN_DRAIN);
-
-   /* Wait a bit in case of a SDA glitch, and then release SCL. */
-   udelay(10);
-   gpiod_direction_output(bri->scl_gpiod, 1);
-
-   if (bri->sda_gpiod == ERR_PTR(-EPROBE_DEFER))
-   return -EPROBE_DEFER;
-
-   if (IS_ERR(bri->sda_gpiod)) {
-   dev_info(dev, "missing sda gpio recovery information: %pe\n",
-bri->sda_gpiod);
+   bri->pinctrl = devm_pinctrl_get(dev);
+   if (PTR_ERR(bri->pinctrl) == -ENODEV) {
+   bri->pinctrl = NULL;
return 0;
}
+   if (IS_ERR(bri->pinctrl))
+   return PTR_ERR(bri->pinctrl);
 
bri->prepare_recovery = i2c_pxa_prepare_recovery;
bri->unprepare_recovery = i2c_pxa_unprepare_recovery;
-   bri->recover_bus = i2c_generic_scl_recovery;
 
i2c->adap.bus_recovery_info = bri;
 
-   /*
-* Claiming GPIOs can change the pinmux state, which confuses the
-* pinctrl since pinctrl's idea of the current setting is unaffected
-* by th

[PATCH] ASoC: mchp-spdifrx: convert to devm_platform_get_and_ioremap_resource

2020-10-04 Thread Codrin Ciubotariu
Use the helper function that wraps the calls to platform_get_resource()
and devm_ioremap_resource() together.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/mchp-spdifrx.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c
index 6776d89d56df..726e4951d9a5 100644
--- a/sound/soc/atmel/mchp-spdifrx.c
+++ b/sound/soc/atmel/mchp-spdifrx.c
@@ -873,8 +873,7 @@ static int mchp_spdifrx_probe(struct platform_device *pdev)
return -ENOMEM;
 
/* Map I/O registers. */
-   mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-   base = devm_ioremap_resource(>dev, mem);
+   base = devm_platform_get_and_ioremap_resource(pdev, 0, );
if (IS_ERR(base))
return PTR_ERR(base);
 
-- 
2.25.1



[PATCH v2] i2c: pxa: move to generic GPIO recovery

2020-10-04 Thread Codrin Ciubotariu
Starting with
commit 75820314de26 ("i2c: core: add generic I2C GPIO recovery")
GPIO bus recovery is supported by the I2C core, so we can remove the
driver implementation and use that one instead.

Signed-off-by: Codrin Ciubotariu 
---

This patch is not tested.

Changes in v2:
 - readded the pinctrl state change to default from the
   unprepare_recovery callback;

 drivers/i2c/busses/i2c-pxa.c | 73 +++-
 1 file changed, 6 insertions(+), 67 deletions(-)

diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 35ca2c02c9b9..006cc1d5931f 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -264,9 +264,6 @@ struct pxa_i2c {
u32 hs_mask;
 
struct i2c_bus_recovery_info recovery;
-   struct pinctrl  *pinctrl;
-   struct pinctrl_state*pinctrl_default;
-   struct pinctrl_state*pinctrl_recovery;
 };
 
 #define _IBMR(i2c) ((i2c)->reg_ibmr)
@@ -1305,8 +1302,6 @@ static void i2c_pxa_prepare_recovery(struct i2c_adapter 
*adap)
 */
gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS);
gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS);
-
-   WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery));
 }
 
 static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
@@ -1347,76 +1342,20 @@ static int i2c_pxa_init_recovery(struct pxa_i2c *i2c)
if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE))
return 0;
 
-   i2c->pinctrl = devm_pinctrl_get(dev);
-   if (PTR_ERR(i2c->pinctrl) == -ENODEV)
-   i2c->pinctrl = NULL;
-   if (IS_ERR(i2c->pinctrl))
-   return PTR_ERR(i2c->pinctrl);
-
-   if (!i2c->pinctrl)
-   return 0;
-
-   i2c->pinctrl_default = pinctrl_lookup_state(i2c->pinctrl,
-   PINCTRL_STATE_DEFAULT);
-   i2c->pinctrl_recovery = pinctrl_lookup_state(i2c->pinctrl, "recovery");
-
-   if (IS_ERR(i2c->pinctrl_default) || IS_ERR(i2c->pinctrl_recovery)) {
-   dev_info(dev, "missing pinmux recovery information: %ld %ld\n",
-PTR_ERR(i2c->pinctrl_default),
-PTR_ERR(i2c->pinctrl_recovery));
-   return 0;
-   }
-
-   /*
-* Claiming GPIOs can influence the pinmux state, and may glitch the
-* I2C bus. Do this carefully.
-*/
-   bri->scl_gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
-   if (bri->scl_gpiod == ERR_PTR(-EPROBE_DEFER))
-   return -EPROBE_DEFER;
-   if (IS_ERR(bri->scl_gpiod)) {
-   dev_info(dev, "missing scl gpio recovery information: %pe\n",
-bri->scl_gpiod);
-   return 0;
-   }
-
-   /*
-* We have SCL. Pull SCL low and wait a bit so that SDA glitches
-* have no effect.
-*/
-   gpiod_direction_output(bri->scl_gpiod, 0);
-   udelay(10);
-   bri->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_OUT_HIGH_OPEN_DRAIN);
-
-   /* Wait a bit in case of a SDA glitch, and then release SCL. */
-   udelay(10);
-   gpiod_direction_output(bri->scl_gpiod, 1);
-
-   if (bri->sda_gpiod == ERR_PTR(-EPROBE_DEFER))
-   return -EPROBE_DEFER;
-
-   if (IS_ERR(bri->sda_gpiod)) {
-   dev_info(dev, "missing sda gpio recovery information: %pe\n",
-bri->sda_gpiod);
+   bri->pinctrl = devm_pinctrl_get(dev);
+   if (PTR_ERR(bri->pinctrl) == -ENODEV) {
+   bri->pinctrl = NULL;
return 0;
}
+   if (IS_ERR(bri->pinctrl))
+   return PTR_ERR(bri->pinctrl);
 
bri->prepare_recovery = i2c_pxa_prepare_recovery;
bri->unprepare_recovery = i2c_pxa_unprepare_recovery;
-   bri->recover_bus = i2c_generic_scl_recovery;
 
i2c->adap.bus_recovery_info = bri;
 
-   /*
-* Claiming GPIOs can change the pinmux state, which confuses the
-* pinctrl since pinctrl's idea of the current setting is unaffected
-* by the pinmux change caused by claiming the GPIO. Work around that
-* by switching pinctrl to the GPIO state here. We do it this way to
-* avoid glitching the I2C bus.
-*/
-   pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery);
-
-   return pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default);
+   return 0;
 }
 
 static int i2c_pxa_probe(struct platform_device *dev)
-- 
2.25.1



[PATCH] i2c: pxa: move to generic GPIO recovery

2020-10-03 Thread Codrin Ciubotariu
Starting with
commit 75820314de26 ("i2c: core: add generic I2C GPIO recovery")
GPIO bus recovery is supported by the I2C core, so we can remove the
driver implementation and use that one instead.

Signed-off-by: Codrin Ciubotariu 
---

This patch is not tested.
The only different thing should be the fact that the pinctl state is
now switched back to the default state after the bus is enabled.

 drivers/i2c/busses/i2c-pxa.c | 75 +++-
 1 file changed, 6 insertions(+), 69 deletions(-)

diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 35ca2c02c9b9..dd357b6e6c61 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -264,9 +264,6 @@ struct pxa_i2c {
u32 hs_mask;
 
struct i2c_bus_recovery_info recovery;
-   struct pinctrl  *pinctrl;
-   struct pinctrl_state*pinctrl_default;
-   struct pinctrl_state*pinctrl_recovery;
 };
 
 #define _IBMR(i2c) ((i2c)->reg_ibmr)
@@ -1305,8 +1302,6 @@ static void i2c_pxa_prepare_recovery(struct i2c_adapter 
*adap)
 */
gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS);
gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS);
-
-   WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery));
 }
 
 static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
@@ -1325,8 +1320,6 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter 
*adap)
i2c_pxa_do_reset(i2c);
}
 
-   WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default));
-
dev_dbg(>adap.dev, "recovery: IBMR 0x%08x ISR 0x%08x\n",
readl(_IBMR(i2c)), readl(_ISR(i2c)));
 
@@ -1347,76 +1340,20 @@ static int i2c_pxa_init_recovery(struct pxa_i2c *i2c)
if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE))
return 0;
 
-   i2c->pinctrl = devm_pinctrl_get(dev);
-   if (PTR_ERR(i2c->pinctrl) == -ENODEV)
-   i2c->pinctrl = NULL;
-   if (IS_ERR(i2c->pinctrl))
-   return PTR_ERR(i2c->pinctrl);
-
-   if (!i2c->pinctrl)
-   return 0;
-
-   i2c->pinctrl_default = pinctrl_lookup_state(i2c->pinctrl,
-   PINCTRL_STATE_DEFAULT);
-   i2c->pinctrl_recovery = pinctrl_lookup_state(i2c->pinctrl, "recovery");
-
-   if (IS_ERR(i2c->pinctrl_default) || IS_ERR(i2c->pinctrl_recovery)) {
-   dev_info(dev, "missing pinmux recovery information: %ld %ld\n",
-PTR_ERR(i2c->pinctrl_default),
-PTR_ERR(i2c->pinctrl_recovery));
-   return 0;
-   }
-
-   /*
-* Claiming GPIOs can influence the pinmux state, and may glitch the
-* I2C bus. Do this carefully.
-*/
-   bri->scl_gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
-   if (bri->scl_gpiod == ERR_PTR(-EPROBE_DEFER))
-   return -EPROBE_DEFER;
-   if (IS_ERR(bri->scl_gpiod)) {
-   dev_info(dev, "missing scl gpio recovery information: %pe\n",
-bri->scl_gpiod);
-   return 0;
-   }
-
-   /*
-* We have SCL. Pull SCL low and wait a bit so that SDA glitches
-* have no effect.
-*/
-   gpiod_direction_output(bri->scl_gpiod, 0);
-   udelay(10);
-   bri->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_OUT_HIGH_OPEN_DRAIN);
-
-   /* Wait a bit in case of a SDA glitch, and then release SCL. */
-   udelay(10);
-   gpiod_direction_output(bri->scl_gpiod, 1);
-
-   if (bri->sda_gpiod == ERR_PTR(-EPROBE_DEFER))
-   return -EPROBE_DEFER;
-
-   if (IS_ERR(bri->sda_gpiod)) {
-   dev_info(dev, "missing sda gpio recovery information: %pe\n",
-bri->sda_gpiod);
+   bri->pinctrl = devm_pinctrl_get(dev);
+   if (PTR_ERR(bri->pinctrl) == -ENODEV) {
+   bri->pinctrl = NULL;
return 0;
}
+   if (IS_ERR(bri->pinctrl))
+   return PTR_ERR(bri->pinctrl);
 
bri->prepare_recovery = i2c_pxa_prepare_recovery;
bri->unprepare_recovery = i2c_pxa_unprepare_recovery;
-   bri->recover_bus = i2c_generic_scl_recovery;
 
i2c->adap.bus_recovery_info = bri;
 
-   /*
-* Claiming GPIOs can change the pinmux state, which confuses the
-* pinctrl since pinctrl's idea of the current setting is unaffected
-* by the pinmux change caused by claiming the GPIO. Work around that
-* by switching pinctrl to the GPIO state here. We do it this way to
-* avoid glitching the I2C bus.
-*/
-   pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery);
-
-   return pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default);
+   return 0;
 }
 
 static int i2c_pxa_probe(struct platform_device *dev)
-- 
2.25.1



[PATCH 2/2] ASoC: mchp-spdifrx: add driver for SPDIF RX

2020-10-02 Thread Codrin Ciubotariu
The new SPDIF RX controller is a serial port compliant with the IEC-60958
standard. It also supports programmable User Data and Channel Status
fields.

This IP is embedded in Microchip's sama7g5 SoC.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/Kconfig|  13 +
 sound/soc/atmel/Makefile   |   2 +
 sound/soc/atmel/mchp-spdifrx.c | 954 +
 3 files changed, 969 insertions(+)
 create mode 100644 sound/soc/atmel/mchp-spdifrx.c

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 93beb7d670a3..bd8854bfd2ee 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -144,4 +144,17 @@ config SND_MCHP_SOC_SPDIFTX
 
  This S/PDIF TX driver is compliant with IEC-60958 standard and
  includes programable User Data and Channel Status fields.
+
+config SND_MCHP_SOC_SPDIFRX
+   tristate "Microchip ASoC driver for boards using S/PDIF RX"
+   depends on OF && (ARCH_AT91 || COMPILE_TEST)
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   help
+ Say Y or M if you want to add support for Microchip S/PDIF RX ASoc
+ driver on the following Microchip platforms:
+ - sama7g5
+
+ This S/PDIF RX driver is compliant with IEC-60958 standard and
+ includes programable User Data and Channel Status fields.
 endif
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index 3fd89a0063df..016188397210 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -6,6 +6,7 @@ snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
 snd-soc-atmel-i2s-objs := atmel-i2s.o
 snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o
 snd-soc-mchp-spdiftx-objs := mchp-spdiftx.o
+snd-soc-mchp-spdifrx-objs := mchp-spdifrx.o
 
 # pdc and dma need to both be built-in if any user of
 # ssc is built-in.
@@ -19,6 +20,7 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
 obj-$(CONFIG_SND_MCHP_SOC_I2S_MCC) += snd-soc-mchp-i2s-mcc.o
 obj-$(CONFIG_SND_MCHP_SOC_SPDIFTX) += snd-soc-mchp-spdiftx.o
+obj-$(CONFIG_SND_MCHP_SOC_SPDIFRX) += snd-soc-mchp-spdifrx.o
 
 # AT91 Machine Support
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c
new file mode 100644
index ..6776d89d56df
--- /dev/null
+++ b/sound/soc/atmel/mchp-spdifrx.c
@@ -0,0 +1,954 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Driver for Microchip S/PDIF RX Controller
+//
+// Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
+//
+// Author: Codrin Ciubotariu 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/*
+ *  S/PDIF Receiver Controller Register map 
+ */
+#define SPDIFRX_CR 0x00/* Control Register */
+#define SPDIFRX_MR 0x04/* Mode Register */
+
+#define SPDIFRX_IER0x10/* Interrupt Enable Register */
+#define SPDIFRX_IDR0x14/* Interrupt Disable Register */
+#define SPDIFRX_IMR0x18/* Interrupt Mask Register */
+#define SPDIFRX_ISR0x1c/* Interrupt Status Register */
+#define SPDIFRX_RSR0x20/* Status Register */
+#define SPDIFRX_RHR0x24/* Holding Register */
+
+#define SPDIFRX_CHSR(channel, reg) \
+   (0x30 + (channel) * 0x30 + (reg) * 4)   /* Channel x Status Registers */
+
+#define SPDIFRX_CHUD(channel, reg) \
+   (0x48 + (channel) * 0x30 + (reg) * 4)   /* Channel x User Data 
Registers */
+
+#define SPDIFRX_WPMR   0xE4/* Write Protection Mode 
Register */
+#define SPDIFRX_WPSR   0xE8/* Write Protection Status 
Register */
+
+#define SPDIFRX_VERSION0xFC/* Version Register */
+
+/*
+ *  Control Register (Write-only) 
+ */
+#define SPDIFRX_CR_SWRST   BIT(0)  /* Software Reset */
+
+/*
+ *  Mode Register (Read/Write) 
+ */
+/* Receive Enable */
+#define SPDIFRX_MR_RXEN_MASK   GENMASK(0, 0)
+#define SPDIFRX_MR_RXEN_DISABLE(0 << 0)/* SPDIF 
Receiver Disabled */
+#define SPDIFRX_MR_RXEN_ENABLE (1 << 0)/* SPDIF Receiver 
Enabled */
+
+/* Validity Bit Mode */
+#define SPDIFRX_MR_VBMODE_MASK GENAMSK(1, 1)
+#define SPDIFRX_MR_VBMODE_ALWAYS_LOAD \
+   (0 << 1)/* Load sample regardles of validity bit value */
+#define SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 \
+   (1 << 1)/* Load sample only if validity bit is 0 */
+
+/* Data Word Endian Mode */
+#define SPDIFRX_MR_ENDIAN_MASK GENMASK(2, 2)
+#define SPDIFRX_MR_ENDIAN_LITTLE   (0 << 2)/* Little Endian Mode */
+#define SPDIFRX_MR_ENDIAN_BIG  (1 << 2)/* Big Endian Mode */
+
+/* Parity Bit Mode */
+#define

[PATCH 0/2] Add driver for Microchip S/PDIF RX

2020-10-02 Thread Codrin Ciubotariu
The Sony/Philips Digital Interface Receiver (SPDIFRX) is a serial port
compliant with the IEC-60958 standard. Among its caracteristics, we
mention the following:
 - SPDIF/AES-EBU Compatible Serial Port
 - 32 Samples FIFO
 - Data Width Configurable to 24 bits, 20 bits or 16 bits
 - Packed and Unpacked Data Support for System Memory Optimization
 - Line State Events Report and Source of Interrupt
 - Line Error Rate Report
 - Full Memory Map of 192 bits for Channel 1 and Channel 2 Status and
   User Data
 - First 32-bit Status A, Status B Change Report and Source of Interrupt
 - Line Digital Filter
 - Register Write Protection
 - Abnormal Software Access and Internal Sequencer Integrity Check Reports

This interface is available in Microchip's SAMA7G5 SoC.

Codrin Ciubotariu (2):
  dt-bindings: sound: add DT bindings for Microchip S/PDIF RX Controller
  ASoC: mchp-spdifrx: add driver for SPDIF RX

 .../bindings/sound/mchp,spdifrx.yaml  |  73 ++
 sound/soc/atmel/Kconfig   |  13 +
 sound/soc/atmel/Makefile  |   2 +
 sound/soc/atmel/mchp-spdifrx.c| 954 ++
 4 files changed, 1042 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mchp,spdifrx.yaml
 create mode 100644 sound/soc/atmel/mchp-spdifrx.c

-- 
2.25.1



[PATCH 1/2] dt-bindings: sound: add DT bindings for Microchip S/PDIF RX Controller

2020-10-02 Thread Codrin Ciubotariu
This patch adds DT bindings for the new Microchip S/PDIF RX Controller
embedded inside sama7g5 SoCs.

Signed-off-by: Codrin Ciubotariu 
---
 .../bindings/sound/mchp,spdifrx.yaml  | 73 +++
 1 file changed, 73 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mchp,spdifrx.yaml

diff --git a/Documentation/devicetree/bindings/sound/mchp,spdifrx.yaml 
b/Documentation/devicetree/bindings/sound/mchp,spdifrx.yaml
new file mode 100644
index ..7d8bd4e14434
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mchp,spdifrx.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mchp,spdifrx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip S/PDIF Rx Controller Device Tree Bindings
+
+maintainers:
+  - Codrin Ciubotariu 
+
+description:
+The Microchip Sony/Philips Digital Interface Receiver is a
+serial port compliant with the IEC-60958 standard.
+
+properties:
+  "#sound-dai-cells":
+const: 0
+
+  compatible:
+const: microchip,sama7g5-spdifrx
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  clocks:
+items:
+  - description: Peripheral Bus Clock
+  - description: Generic Clock
+
+  clock-names:
+items:
+  - const: pclk
+  - const: gclk
+
+  dmas:
+description: RX DMA Channel
+maxItems: 1
+
+  dma-names:
+const: rx
+
+required:
+  - "#sound-dai-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+
+spdifrx: spdifrx@e1614000 {
+#sound-dai-cells = <0>;
+compatible = "microchip,sama7g5-spdifrx";
+reg = <0xe1614000 0x4000>;
+interrupts = ;
+dmas = < AT91_XDMAC_DT_PERID(49)>;
+dma-names = "rx";
+clocks = < PMC_TYPE_PERIPHERAL 84>, < PMC_TYPE_GCK 84>;
+clock-names = "pclk", "gclk";
+};
-- 
2.25.1



[PATCH v4 1/2] dt-bindings: sound: add DT bindings for Microchip S/PDIF TX Controller

2020-09-09 Thread Codrin Ciubotariu
This patch adds DT bindings for the new Microchip S/PDIF TX Controller
embedded inside sama7g5 SoCs.

Signed-off-by: Codrin Ciubotariu 
Reviewed-by: Rob Herring 
---

Changes in v4:
 - added 'Reviewed-by' tag from Rob

Changes in v3:
 - removed 'oneOf' from 'compatible' property;
 - added 'maxItems: 1' to 'dmas' property;
 - removed pinctrl related properties;

Changes in v2:
 - replaced https with http;
 - reworked example, included bindings;

 .../bindings/sound/mchp,spdiftx.yaml  | 75 +++
 1 file changed, 75 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml

diff --git a/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml 
b/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
new file mode 100644
index ..a03b0b871fc9
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mchp,spdiftx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip S/PDIF Tx Controller Device Tree Bindings
+
+maintainers:
+  - Codrin Ciubotariu 
+
+description:
+The Microchip Sony/Philips Digital Interface Transmitter is a
+serial port compliant with the IEC-60958 standard.
+
+properties:
+  "#sound-dai-cells":
+const: 0
+
+  compatible:
+const: microchip,sama7g5-spdiftx
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  clocks:
+items:
+  - description: Peripheral Bus Clock
+  - description: Generic Clock
+
+  clock-names:
+items:
+  - const: pclk
+  - const: gclk
+
+  dmas:
+description: TX DMA Channel
+maxItems: 1
+
+  dma-names:
+const: tx
+
+required:
+  - "#sound-dai-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+
+spdiftx@e1618000 {
+#sound-dai-cells = <0>;
+compatible = "microchip,sama7g5-spdiftx";
+reg = <0xe1618000 0x4000>;
+interrupts = ;
+dmas = < AT91_XDMAC_DT_PERID(50)>;
+dma-names = "tx";
+clocks = < PMC_TYPE_PERIPHERAL 85>, < PMC_TYPE_GCK 85>;
+clock-names = "pclk", "gclk";
+pinctrl-names = "default";
+pinctrl-0 = <_spdiftx_default>;
+};
-- 
2.25.1



[PATCH v4 2/2] ASoC: mchp-spdiftx: add driver for S/PDIF TX Controller

2020-09-09 Thread Codrin Ciubotariu
The new SPDIF TX controller is a serial port compliant with the IEC-
60958 standard. It also supports programmable User Data and Channel
Status fields.

This IP is embedded in Microchip's sama7g5 SoC.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v4:
 - moved enable/disable of pclk clock from DAI startup/shutdown ops to
   probe/remove callbacks;
 - removed extra newline;
 - added comment description for spinlock;

Changes in v2,v3:
 - none

 sound/soc/atmel/Kconfig|  12 +
 sound/soc/atmel/Makefile   |   2 +
 sound/soc/atmel/mchp-spdiftx.c | 871 +
 3 files changed, 885 insertions(+)
 create mode 100644 sound/soc/atmel/mchp-spdiftx.c

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 71f2d42188c4..93beb7d670a3 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -132,4 +132,16 @@ config SND_MCHP_SOC_I2S_MCC
  and supports a Time Division Multiplexed (TDM) interface with
  external multi-channel audio codecs.
 
+config SND_MCHP_SOC_SPDIFTX
+   tristate "Microchip ASoC driver for boards using S/PDIF TX"
+   depends on OF && (ARCH_AT91 || COMPILE_TEST)
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   help
+ Say Y or M if you want to add support for Microchip S/PDIF TX ASoc
+ driver on the following Microchip platforms:
+ - sama7g5
+
+ This S/PDIF TX driver is compliant with IEC-60958 standard and
+ includes programable User Data and Channel Status fields.
 endif
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index c7d2989791be..3fd89a0063df 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -5,6 +5,7 @@ snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
 snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
 snd-soc-atmel-i2s-objs := atmel-i2s.o
 snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o
+snd-soc-mchp-spdiftx-objs := mchp-spdiftx.o
 
 # pdc and dma need to both be built-in if any user of
 # ssc is built-in.
@@ -17,6 +18,7 @@ endif
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
 obj-$(CONFIG_SND_MCHP_SOC_I2S_MCC) += snd-soc-mchp-i2s-mcc.o
+obj-$(CONFIG_SND_MCHP_SOC_SPDIFTX) += snd-soc-mchp-spdiftx.o
 
 # AT91 Machine Support
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
new file mode 100644
index ..36c23eb3a5ad
--- /dev/null
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -0,0 +1,871 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Driver for Microchip S/PDIF TX Controller
+//
+// Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
+//
+// Author: Codrin Ciubotariu 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+ *  S/PDIF Transmitter Controller Register map 
+ */
+#define SPDIFTX_CR 0x00/* Control Register */
+#define SPDIFTX_MR 0x04/* Mode Register */
+#define SPDIFTX_CDR0x0C/* Common Data Register */
+
+#define SPDIFTX_IER0x14/* Interrupt Enable Register */
+#define SPDIFTX_IDR0x18/* Interrupt Disable Register */
+#define SPDIFTX_IMR0x1C/* Interrupt Mask Register */
+#define SPDIFTX_ISR0x20/* Interrupt Status Register */
+
+#define SPDIFTX_CH1UD(reg) (0x50 + (reg) * 4)  /* User Data 1 Register 
x */
+#define SPDIFTX_CH1S(reg)  (0x80 + (reg) * 4)  /* Channel Status 1 
Register x */
+
+#define SPDIFTX_VERSION0xF0
+
+/*
+ *  Control Register (Write-only) 
+ */
+#define SPDIFTX_CR_SWRST   BIT(0)  /* Software Reset */
+#define SPDIFTX_CR_FCLRBIT(1)  /* FIFO clear */
+
+/*
+ *  Mode Register (Read/Write) 
+ */
+/* Transmit Enable */
+#define SPDIFTX_MR_TXEN_MASK   GENMASK(0, 0)
+#define SPDIFTX_MR_TXEN_DISABLE(0 << 0)
+#define SPDIFTX_MR_TXEN_ENABLE (1 << 0)
+
+/* Multichannel Transfer */
+#define SPDIFTX_MR_MULTICH_MASKGENAMSK(1, 1)
+#define SPDIFTX_MR_MULTICH_MONO(0 << 1)
+#define SPDIFTX_MR_MULTICH_DUAL(1 << 1)
+
+/* Data Word Endian Mode */
+#define SPDIFTX_MR_ENDIAN_MASK GENMASK(2, 2)
+#define SPDIFTX_MR_ENDIAN_LITTLE   (0 << 2)
+#define SPDIFTX_MR_ENDIAN_BIG  (1 << 2)
+
+/* Data Justification */
+#define SPDIFTX_MR_JUSTIFY_MASKGENMASK(3, 3)
+#define SPDIFTX_MR_JUSTIFY_LSB (0 << 3)
+#define SPDIFTX_MR_JUSTIFY_MSB (1 << 3)
+
+/* Common Audio Register Transfer Mode */
+#define SPDIFTX_MR_CMODE_MASK  GENMASK(5, 4)
+#define SPDIFTX_MR_CMODE_INDEX_ACCESS  (0 << 4)
+#define SPDIFTX_MR_CMODE_TOGGLE_ACCESS 

[PATCH 4/4] i2c: at91: Move to generic GPIO bus recovery

2020-08-04 Thread Codrin Ciubotariu
Make the Microchip at91 driver the first to use the generic GPIO bus
recovery support from the I2C core and discard the driver implementation.

Signed-off-by: Codrin Ciubotariu 
---

Changes from RFC:
 - none;

 drivers/i2c/busses/i2c-at91-master.c | 69 ++--
 drivers/i2c/busses/i2c-at91.h|  3 --
 2 files changed, 3 insertions(+), 69 deletions(-)

diff --git a/drivers/i2c/busses/i2c-at91-master.c 
b/drivers/i2c/busses/i2c-at91-master.c
index 363d540a8345..66864f9cf7ac 100644
--- a/drivers/i2c/busses/i2c-at91-master.c
+++ b/drivers/i2c/busses/i2c-at91-master.c
@@ -816,79 +816,16 @@ static int at91_twi_configure_dma(struct at91_twi_dev 
*dev, u32 phy_addr)
return ret;
 }
 
-static void at91_prepare_twi_recovery(struct i2c_adapter *adap)
-{
-   struct at91_twi_dev *dev = i2c_get_adapdata(adap);
-
-   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_gpio);
-}
-
-static void at91_unprepare_twi_recovery(struct i2c_adapter *adap)
-{
-   struct at91_twi_dev *dev = i2c_get_adapdata(adap);
-
-   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
-}
-
 static int at91_init_twi_recovery_gpio(struct platform_device *pdev,
   struct at91_twi_dev *dev)
 {
struct i2c_bus_recovery_info *rinfo = >rinfo;
 
-   dev->pinctrl = devm_pinctrl_get(>dev);
-   if (!dev->pinctrl || IS_ERR(dev->pinctrl)) {
+   rinfo->pinctrl = devm_pinctrl_get(>dev);
+   if (!rinfo->pinctrl || IS_ERR(rinfo->pinctrl)) {
dev_info(dev->dev, "can't get pinctrl, bus recovery not 
supported\n");
-   return PTR_ERR(dev->pinctrl);
+   return PTR_ERR(rinfo->pinctrl);
}
-
-   dev->pinctrl_pins_default = pinctrl_lookup_state(dev->pinctrl,
-PINCTRL_STATE_DEFAULT);
-   dev->pinctrl_pins_gpio = pinctrl_lookup_state(dev->pinctrl,
- "gpio");
-   if (IS_ERR(dev->pinctrl_pins_default) ||
-   IS_ERR(dev->pinctrl_pins_gpio)) {
-   dev_info(>dev, "pinctrl states incomplete for 
recovery\n");
-   return -EINVAL;
-   }
-
-   /*
-* pins will be taken as GPIO, so we might as well inform pinctrl about
-* this and move the state to GPIO
-*/
-   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_gpio);
-
-   rinfo->sda_gpiod = devm_gpiod_get(>dev, "sda", GPIOD_IN);
-   if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER)
-   return -EPROBE_DEFER;
-
-   rinfo->scl_gpiod = devm_gpiod_get(>dev, "scl",
- GPIOD_OUT_HIGH_OPEN_DRAIN);
-   if (PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER)
-   return -EPROBE_DEFER;
-
-   if (IS_ERR(rinfo->sda_gpiod) ||
-   IS_ERR(rinfo->scl_gpiod)) {
-   dev_info(>dev, "recovery information incomplete\n");
-   if (!IS_ERR(rinfo->sda_gpiod)) {
-   gpiod_put(rinfo->sda_gpiod);
-   rinfo->sda_gpiod = NULL;
-   }
-   if (!IS_ERR(rinfo->scl_gpiod)) {
-   gpiod_put(rinfo->scl_gpiod);
-   rinfo->scl_gpiod = NULL;
-   }
-   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
-   return -EINVAL;
-   }
-
-   /* change the state of the pins back to their default state */
-   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
-
-   dev_info(>dev, "using scl, sda for recovery\n");
-
-   rinfo->prepare_recovery = at91_prepare_twi_recovery;
-   rinfo->unprepare_recovery = at91_unprepare_twi_recovery;
-   rinfo->recover_bus = i2c_generic_scl_recovery;
dev->adapter.bus_recovery_info = rinfo;
 
return 0;
diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h
index 7e7b4955ca7f..eae673ae786c 100644
--- a/drivers/i2c/busses/i2c-at91.h
+++ b/drivers/i2c/busses/i2c-at91.h
@@ -157,9 +157,6 @@ struct at91_twi_dev {
struct at91_twi_dma dma;
bool slave_detected;
struct i2c_bus_recovery_info rinfo;
-   struct pinctrl *pinctrl;
-   struct pinctrl_state *pinctrl_pins_default;
-   struct pinctrl_state *pinctrl_pins_gpio;
 #ifdef CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL
unsigned smr;
struct i2c_client *slave;
-- 
2.25.1



[PATCH 3/4] i2c: core: treat EPROBE_DEFER when acquiring SCL/SDA GPIOs

2020-08-04 Thread Codrin Ciubotariu
Even if I2C bus GPIO recovery is optional, devm_gpiod_get() can return
-EPROBE_DEFER, so we should at least treat that. This ends up with
i2c_register_adapter() to be able to return -EPROBE_DEFER.

Signed-off-by: Codrin Ciubotariu 
---

Changes from RFC:
 - return -EINVAL if i2c_init_recovery() doesn't have the complete
   information;
 - 'else if' added when checking if i2c_generic_scl_recovery() is used;
 - moved i2c_init_recovery() before class-link creation; class-link
   cleanup removed;
 - moved debug print when the adapter is probed after call to
   i2c_init_recovery();

 drivers/i2c/i2c-core-base.c | 26 ++
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index cf0c5eb152e1..99dbaead269e 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -375,15 +375,16 @@ static int i2c_gpio_init_recovery(struct i2c_adapter 
*adap)
return i2c_gpio_init_generic_recovery(adap);
 }
 
-static void i2c_init_recovery(struct i2c_adapter *adap)
+static int i2c_init_recovery(struct i2c_adapter *adap)
 {
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
char *err_str;
 
if (!bri)
-   return;
+   return 0;
 
-   i2c_gpio_init_recovery(adap);
+   if (i2c_gpio_init_recovery(adap) == -EPROBE_DEFER)
+   return -EPROBE_DEFER;
 
if (!bri->recover_bus) {
err_str = "no recover_bus() found";
@@ -399,10 +400,7 @@ static void i2c_init_recovery(struct i2c_adapter *adap)
if (gpiod_get_direction(bri->sda_gpiod) == 0)
bri->set_sda = set_sda_gpio_value;
}
-   return;
-   }
-
-   if (bri->recover_bus == i2c_generic_scl_recovery) {
+   } else if (bri->recover_bus == i2c_generic_scl_recovery) {
/* Generic SCL recovery */
if (!bri->set_scl || !bri->get_scl) {
err_str = "no {get|set}_scl() found";
@@ -414,10 +412,12 @@ static void i2c_init_recovery(struct i2c_adapter *adap)
}
}
 
-   return;
+   return 0;
  err:
dev_err(>dev, "Not using recovery: %s\n", err_str);
adap->bus_recovery_info = NULL;
+
+   return -EINVAL;
 }
 
 static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client)
@@ -1444,12 +1444,16 @@ static int i2c_register_adapter(struct i2c_adapter 
*adap)
if (res)
goto out_reg;
 
-   dev_dbg(>dev, "adapter [%s] registered\n", adap->name);
-
pm_runtime_no_callbacks(>dev);
pm_suspend_ignore_children(>dev, true);
pm_runtime_enable(>dev);
 
+   res = i2c_init_recovery(adap);
+   if (res == -EPROBE_DEFER)
+   goto out_reg;
+
+   dev_dbg(>dev, "adapter [%s] registered\n", adap->name);
+
 #ifdef CONFIG_I2C_COMPAT
res = class_compat_create_link(i2c_adapter_compat_class, >dev,
   adap->dev.parent);
@@ -1458,8 +1462,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 "Failed to create compatibility class link\n");
 #endif
 
-   i2c_init_recovery(adap);
-
/* create pre-declared device nodes */
of_i2c_register_devices(adap);
i2c_acpi_register_devices(adap);
-- 
2.25.1



[PATCH 2/4] i2c: core: add generic I2C GPIO recovery

2020-08-04 Thread Codrin Ciubotariu
Multiple I2C bus drivers use similar bindings to obtain information needed
for I2C recovery. For example, for platforms using device-tree, the
properties look something like this:

 {
...
pinctrl-names = "default", "gpio";
pinctrl-0 = <_i2c_default>;
pinctrl-1 = <_i2c_gpio>;
sda-gpios = < 0 GPIO_ACTIVE_HIGH>;
scl-gpios = < 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
...
}

For this reason, we can add this common initialization in the core. This
way, other I2C bus drivers will be able to support GPIO recovery just by
providing a pointer to platform's pinctrl and calling i2c_recover_bus()
when SDA is stuck low.

Signed-off-by: Codrin Ciubotariu 
---

Changes from RFC:
 - removed comment with "recovery" pinctrl state from description;
 - pinctrl state is changed to gpio after calling prepare_recovery()
   callback;
 - addressed requested changes on comments;
 - removed cleanup_pinctrl label from i2c_gpio_init_pinctrl_recovery()
 - added glitch protection for SDA line when its corresponding gpio is
   taken at initialization;

 drivers/i2c/i2c-core-base.c | 126 
 include/linux/i2c.h |  11 
 2 files changed, 137 insertions(+)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 69217d2193da..cf0c5eb152e1 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -181,6 +182,8 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
 
if (bri->prepare_recovery)
bri->prepare_recovery(adap);
+   if (bri->pinctrl)
+   pinctrl_select_state(bri->pinctrl, bri->pins_gpio);
 
/*
 * If we can set SDA, we will always create a STOP to ensure additional
@@ -236,6 +239,8 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
 
if (bri->unprepare_recovery)
bri->unprepare_recovery(adap);
+   if (bri->pinctrl)
+   pinctrl_select_state(bri->pinctrl, bri->pins_default);
 
return ret;
 }
@@ -251,6 +256,125 @@ int i2c_recover_bus(struct i2c_adapter *adap)
 }
 EXPORT_SYMBOL_GPL(i2c_recover_bus);
 
+static void i2c_gpio_init_pinctrl_recovery(struct i2c_adapter *adap)
+{
+   struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+   struct device *dev = >dev;
+   struct pinctrl *p = bri->pinctrl;
+
+   /*
+* we can't change states without pinctrl, so remove the states if
+* populated
+*/
+   if (!p) {
+   bri->pins_default = NULL;
+   bri->pins_gpio = NULL;
+   return;
+   }
+
+   if (!bri->pins_default) {
+   bri->pins_default = pinctrl_lookup_state(p,
+PINCTRL_STATE_DEFAULT);
+   if (IS_ERR(bri->pins_default)) {
+   dev_dbg(dev, PINCTRL_STATE_DEFAULT " state not found 
for GPIO recovery\n");
+   bri->pins_default = NULL;
+   }
+   }
+   if (!bri->pins_gpio) {
+   bri->pins_gpio = pinctrl_lookup_state(p, "gpio");
+   if (IS_ERR(bri->pins_gpio))
+   bri->pins_gpio = pinctrl_lookup_state(p, "recovery");
+
+   if (IS_ERR(bri->pins_gpio)) {
+   dev_dbg(dev, "no gpio or recovery state found for GPIO 
recovery\n");
+   bri->pins_gpio = NULL;
+   }
+   }
+
+   /* for pinctrl state changes, we need all the information */
+   if (!bri->pins_default || !bri->pins_gpio) {
+   bri->pinctrl = NULL;
+   bri->pins_default = NULL;
+   bri->pins_gpio = NULL;
+   } else {
+   dev_info(dev, "using pinctrl states for GPIO recovery");
+   }
+}
+
+static int i2c_gpio_init_generic_recovery(struct i2c_adapter *adap)
+{
+   struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+   struct device *dev = >dev;
+   struct gpio_desc *gpiod;
+   int ret = 0;
+
+   /*
+* don't touch the recovery information if the driver is not using
+* generic SCL recovery
+*/
+   if (bri->recover_bus && bri->recover_bus != i2c_generic_scl_recovery)
+   return 0;
+
+   /*
+* pins might be taken as GPIO, so we should inform pinctrl about
+* this and move the state to GPIO
+*/
+   if (bri->pinctrl)
+   pinctrl_select_state(bri->pinctrl, bri->pins_gpio);
+
+   /*
+* if there is incomplete or no recovery information, see if generic
+* GPIO recovery is available
+*/
+   if (!bri

[PATCH 1/4] dt-binding: i2c: add generic properties for GPIO bus recovery

2020-08-04 Thread Codrin Ciubotariu
The I2C GPIO bus recovery properties consist of two GPIOS and one extra
pinctrl state ("gpio" or "recovery"). "recovery" pinctrl state is
considered deprecated and "gpio" should be used instead.
Not all are mandatory for recovery.

Signed-off-by: Codrin Ciubotariu 
---

Changes from RFC:
 - "recovery" pinctrl state marked as deprecated; updated description to
   reflect this;

 Documentation/devicetree/bindings/i2c/i2c.txt | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c.txt 
b/Documentation/devicetree/bindings/i2c/i2c.txt
index 438ae123107e..150a67da633d 100644
--- a/Documentation/devicetree/bindings/i2c/i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c.txt
@@ -77,6 +77,16 @@ wants to support one of the below features, it should adapt 
these bindings.
this information to detect a stalled bus more reliably, for example.
Can not be combined with 'multi-master'.
 
+- scl-gpios
+   specify the gpio related to SCL pin. Used for GPIO bus recovery.
+
+- sda-gpios
+   specify the gpio related to SDA pin. Optional for GPIO bus recovery.
+
+- pinctrl
+   add extra pinctrl to configure SCL/SDA pins to GPIO function for bus
+   recovery, call it "gpio" or "recovery"(deprecated) state
+
 Required properties (per child device)
 --
 
-- 
2.25.1



[PATCH 0/4] i2c: core: add generic GPIO bus recovery

2020-08-04 Thread Codrin Ciubotariu
GPIO recovery has been added already for some I2C bus drivers, such as
imx, pxa and at91. These drivers use similar bindings and have more or
less the same code for recovery. For this reason, we aim to move the
GPIO bus recovery implementation to the I2C core so that other drivers
can benefit from it, with small modifications.
This implementation initializes the pinctrl states and the SDA/SCL
GPIOs based on common bindings. The I2C bus drivers can still use
different bindings or other particular recovery steps if needed.
The ugly part with this patch series is the handle of PROBE_DEFER
which could be returned by devm_gpiod_get(). This changes things a
little for i2c_register_adapter() and for this reason this step is
implemented in a sperate patch.
The at91 Microchip driver is the first to use this implementation,
with an AI to move the rest of the drivers in the following steps.

This patch series was previously sent as a RFC. Significant changes
since RFC:
- "recovery" pinctrl state marked as deprecared in bindings;
- move to "gpio" pinctrl state done after the call to prepare_recovery()
  callback;
- glitch protection when SDA gpio is taken at initialization;

Codrin Ciubotariu (4):
  dt-binding: i2c: add generic properties for GPIO bus recovery
  i2c: core: add generic I2C GPIO recovery
  i2c: core: treat EPROBE_DEFER when acquiring SCL/SDA GPIOs
  i2c: at91: Move to generic GPIO bus recovery

 Documentation/devicetree/bindings/i2c/i2c.txt |  10 ++
 drivers/i2c/busses/i2c-at91-master.c  |  69 +---
 drivers/i2c/busses/i2c-at91.h |   3 -
 drivers/i2c/i2c-core-base.c   | 150 --
 include/linux/i2c.h   |  11 ++
 5 files changed, 163 insertions(+), 80 deletions(-)

-- 
2.25.1



[PATCH v3 1/2] dt-bindings: sound: add DT bindings for Microchip S/PDIF TX Controller

2020-08-03 Thread Codrin Ciubotariu
This patch adds DT bindings for the new Microchip S/PDIF TX Controller
embedded inside sama7g5 SoCs.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v3:
 - removed 'oneOf' from 'compatible' property;
 - added 'maxItems: 1' to 'dmas' property;
 - removed pinctrl related properties;

Changes in v2:
 - replaced https with http;
 - reworked example, included bindings;

 .../bindings/sound/mchp,spdiftx.yaml  | 75 +++
 1 file changed, 75 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml

diff --git a/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml 
b/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
new file mode 100644
index ..a03b0b871fc9
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mchp,spdiftx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip S/PDIF Tx Controller Device Tree Bindings
+
+maintainers:
+  - Codrin Ciubotariu 
+
+description:
+The Microchip Sony/Philips Digital Interface Transmitter is a
+serial port compliant with the IEC-60958 standard.
+
+properties:
+  "#sound-dai-cells":
+const: 0
+
+  compatible:
+const: microchip,sama7g5-spdiftx
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  clocks:
+items:
+  - description: Peripheral Bus Clock
+  - description: Generic Clock
+
+  clock-names:
+items:
+  - const: pclk
+  - const: gclk
+
+  dmas:
+description: TX DMA Channel
+maxItems: 1
+
+  dma-names:
+const: tx
+
+required:
+  - "#sound-dai-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+
+spdiftx@e1618000 {
+#sound-dai-cells = <0>;
+compatible = "microchip,sama7g5-spdiftx";
+reg = <0xe1618000 0x4000>;
+interrupts = ;
+dmas = < AT91_XDMAC_DT_PERID(50)>;
+dma-names = "tx";
+clocks = < PMC_TYPE_PERIPHERAL 85>, < PMC_TYPE_GCK 85>;
+clock-names = "pclk", "gclk";
+pinctrl-names = "default";
+pinctrl-0 = <_spdiftx_default>;
+};
-- 
2.25.1



[PATCH v3 2/2] ASoC: mchp-spdiftx: add driver for S/PDIF TX Controller

2020-08-03 Thread Codrin Ciubotariu
The new SPDIF TX controller is a serial port compliant with the IEC-
60958 standard. It also supports programmable User Data and Channel
Status fields.

This IP is embedded in Microchip's sama7g5 SoC.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2, v3:
 - none;

 sound/soc/atmel/Kconfig|  12 +
 sound/soc/atmel/Makefile   |   2 +
 sound/soc/atmel/mchp-spdiftx.c | 864 +
 3 files changed, 878 insertions(+)
 create mode 100644 sound/soc/atmel/mchp-spdiftx.c

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 71f2d42188c4..93beb7d670a3 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -132,4 +132,16 @@ config SND_MCHP_SOC_I2S_MCC
  and supports a Time Division Multiplexed (TDM) interface with
  external multi-channel audio codecs.
 
+config SND_MCHP_SOC_SPDIFTX
+   tristate "Microchip ASoC driver for boards using S/PDIF TX"
+   depends on OF && (ARCH_AT91 || COMPILE_TEST)
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   help
+ Say Y or M if you want to add support for Microchip S/PDIF TX ASoc
+ driver on the following Microchip platforms:
+ - sama7g5
+
+ This S/PDIF TX driver is compliant with IEC-60958 standard and
+ includes programable User Data and Channel Status fields.
 endif
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index c7d2989791be..3fd89a0063df 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -5,6 +5,7 @@ snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
 snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
 snd-soc-atmel-i2s-objs := atmel-i2s.o
 snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o
+snd-soc-mchp-spdiftx-objs := mchp-spdiftx.o
 
 # pdc and dma need to both be built-in if any user of
 # ssc is built-in.
@@ -17,6 +18,7 @@ endif
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
 obj-$(CONFIG_SND_MCHP_SOC_I2S_MCC) += snd-soc-mchp-i2s-mcc.o
+obj-$(CONFIG_SND_MCHP_SOC_SPDIFTX) += snd-soc-mchp-spdiftx.o
 
 # AT91 Machine Support
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
new file mode 100644
index ..738f6788212e
--- /dev/null
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -0,0 +1,864 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Driver for Microchip S/PDIF TX Controller
+//
+// Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
+//
+// Author: Codrin Ciubotariu 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+ *  S/PDIF Transmitter Controller Register map 
+ */
+#define SPDIFTX_CR 0x00/* Control Register */
+#define SPDIFTX_MR 0x04/* Mode Register */
+#define SPDIFTX_CDR0x0C/* Common Data Register */
+
+#define SPDIFTX_IER0x14/* Interrupt Enable Register */
+#define SPDIFTX_IDR0x18/* Interrupt Disable Register */
+#define SPDIFTX_IMR0x1C/* Interrupt Mask Register */
+#define SPDIFTX_ISR0x20/* Interrupt Status Register */
+
+#define SPDIFTX_CH1UD(reg) (0x50 + (reg) * 4)  /* User Data 1 Register 
x */
+#define SPDIFTX_CH1S(reg)  (0x80 + (reg) * 4)  /* Channel Status 1 
Register x */
+
+#define SPDIFTX_VERSION0xF0
+
+/*
+ *  Control Register (Write-only) 
+ */
+#define SPDIFTX_CR_SWRST   BIT(0)  /* Software Reset */
+#define SPDIFTX_CR_FCLRBIT(1)  /* FIFO clear */
+
+/*
+ *  Mode Register (Read/Write) 
+ */
+/* Transmit Enable */
+#define SPDIFTX_MR_TXEN_MASK   GENMASK(0, 0)
+#define SPDIFTX_MR_TXEN_DISABLE(0 << 0)
+#define SPDIFTX_MR_TXEN_ENABLE (1 << 0)
+
+/* Multichannel Transfer */
+#define SPDIFTX_MR_MULTICH_MASKGENAMSK(1, 1)
+#define SPDIFTX_MR_MULTICH_MONO(0 << 1)
+#define SPDIFTX_MR_MULTICH_DUAL(1 << 1)
+
+/* Data Word Endian Mode */
+#define SPDIFTX_MR_ENDIAN_MASK GENMASK(2, 2)
+#define SPDIFTX_MR_ENDIAN_LITTLE   (0 << 2)
+#define SPDIFTX_MR_ENDIAN_BIG  (1 << 2)
+
+/* Data Justification */
+#define SPDIFTX_MR_JUSTIFY_MASKGENMASK(3, 3)
+#define SPDIFTX_MR_JUSTIFY_LSB (0 << 3)
+#define SPDIFTX_MR_JUSTIFY_MSB (1 << 3)
+
+/* Common Audio Register Transfer Mode */
+#define SPDIFTX_MR_CMODE_MASK  GENMASK(5, 4)
+#define SPDIFTX_MR_CMODE_INDEX_ACCESS  (0 << 4)
+#define SPDIFTX_MR_CMODE_TOGGLE_ACCESS (1 << 4)
+#define SPDIFTX_MR_CMODE_INTERLVD_ACCESS   (2 << 4)
+
+/* Valid Bits per Sample */
+#define SPDIFTX_MR_VBPS_MASK   GENMASK(13, 8)
+#define S

[PATCH v2 2/2] ASoC: mchp-spdiftx: add driver for S/PDIF TX Controller

2020-07-29 Thread Codrin Ciubotariu
The new SPDIF TX controller is a serial port compliant with the IEC-
60958 standard. It also supports programmable User Data and Channel
Status fields.

This IP is embedded in Microchip's sama7g5 SoC.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - none

 sound/soc/atmel/Kconfig|  12 +
 sound/soc/atmel/Makefile   |   2 +
 sound/soc/atmel/mchp-spdiftx.c | 864 +
 3 files changed, 878 insertions(+)
 create mode 100644 sound/soc/atmel/mchp-spdiftx.c

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 71f2d42188c4..93beb7d670a3 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -132,4 +132,16 @@ config SND_MCHP_SOC_I2S_MCC
  and supports a Time Division Multiplexed (TDM) interface with
  external multi-channel audio codecs.
 
+config SND_MCHP_SOC_SPDIFTX
+   tristate "Microchip ASoC driver for boards using S/PDIF TX"
+   depends on OF && (ARCH_AT91 || COMPILE_TEST)
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   help
+ Say Y or M if you want to add support for Microchip S/PDIF TX ASoc
+ driver on the following Microchip platforms:
+ - sama7g5
+
+ This S/PDIF TX driver is compliant with IEC-60958 standard and
+ includes programable User Data and Channel Status fields.
 endif
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index c7d2989791be..3fd89a0063df 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -5,6 +5,7 @@ snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
 snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
 snd-soc-atmel-i2s-objs := atmel-i2s.o
 snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o
+snd-soc-mchp-spdiftx-objs := mchp-spdiftx.o
 
 # pdc and dma need to both be built-in if any user of
 # ssc is built-in.
@@ -17,6 +18,7 @@ endif
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
 obj-$(CONFIG_SND_MCHP_SOC_I2S_MCC) += snd-soc-mchp-i2s-mcc.o
+obj-$(CONFIG_SND_MCHP_SOC_SPDIFTX) += snd-soc-mchp-spdiftx.o
 
 # AT91 Machine Support
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
new file mode 100644
index ..738f6788212e
--- /dev/null
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -0,0 +1,864 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Driver for Microchip S/PDIF TX Controller
+//
+// Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
+//
+// Author: Codrin Ciubotariu 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+ *  S/PDIF Transmitter Controller Register map 
+ */
+#define SPDIFTX_CR 0x00/* Control Register */
+#define SPDIFTX_MR 0x04/* Mode Register */
+#define SPDIFTX_CDR0x0C/* Common Data Register */
+
+#define SPDIFTX_IER0x14/* Interrupt Enable Register */
+#define SPDIFTX_IDR0x18/* Interrupt Disable Register */
+#define SPDIFTX_IMR0x1C/* Interrupt Mask Register */
+#define SPDIFTX_ISR0x20/* Interrupt Status Register */
+
+#define SPDIFTX_CH1UD(reg) (0x50 + (reg) * 4)  /* User Data 1 Register 
x */
+#define SPDIFTX_CH1S(reg)  (0x80 + (reg) * 4)  /* Channel Status 1 
Register x */
+
+#define SPDIFTX_VERSION0xF0
+
+/*
+ *  Control Register (Write-only) 
+ */
+#define SPDIFTX_CR_SWRST   BIT(0)  /* Software Reset */
+#define SPDIFTX_CR_FCLRBIT(1)  /* FIFO clear */
+
+/*
+ *  Mode Register (Read/Write) 
+ */
+/* Transmit Enable */
+#define SPDIFTX_MR_TXEN_MASK   GENMASK(0, 0)
+#define SPDIFTX_MR_TXEN_DISABLE(0 << 0)
+#define SPDIFTX_MR_TXEN_ENABLE (1 << 0)
+
+/* Multichannel Transfer */
+#define SPDIFTX_MR_MULTICH_MASKGENAMSK(1, 1)
+#define SPDIFTX_MR_MULTICH_MONO(0 << 1)
+#define SPDIFTX_MR_MULTICH_DUAL(1 << 1)
+
+/* Data Word Endian Mode */
+#define SPDIFTX_MR_ENDIAN_MASK GENMASK(2, 2)
+#define SPDIFTX_MR_ENDIAN_LITTLE   (0 << 2)
+#define SPDIFTX_MR_ENDIAN_BIG  (1 << 2)
+
+/* Data Justification */
+#define SPDIFTX_MR_JUSTIFY_MASKGENMASK(3, 3)
+#define SPDIFTX_MR_JUSTIFY_LSB (0 << 3)
+#define SPDIFTX_MR_JUSTIFY_MSB (1 << 3)
+
+/* Common Audio Register Transfer Mode */
+#define SPDIFTX_MR_CMODE_MASK  GENMASK(5, 4)
+#define SPDIFTX_MR_CMODE_INDEX_ACCESS  (0 << 4)
+#define SPDIFTX_MR_CMODE_TOGGLE_ACCESS (1 << 4)
+#define SPDIFTX_MR_CMODE_INTERLVD_ACCESS   (2 << 4)
+
+/* Valid Bits per Sample */
+#define SPDIFTX_MR_VBPS_MASK   GENMASK(13, 8)
+#define S

[PATCH v2 1/2] dt-bindings: sound: add DT bindings for Microchip S/PDIF TX Controller

2020-07-29 Thread Codrin Ciubotariu
This patch adds DT bindings for the new Microchip S/PDIF TX Controller
embedded inside sama7g5 SoCs.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - replaced https with http
 - reworked example, included bindings;

 .../bindings/sound/mchp,spdiftx.yaml  | 80 +++
 1 file changed, 80 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml

diff --git a/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml 
b/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
new file mode 100644
index ..2b7c27391f0d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mchp,spdiftx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip S/PDIF Tx Controller Device Tree Bindings
+
+maintainers:
+  - Codrin Ciubotariu 
+
+description:
+The Microchip Sony/Philips Digital Interface Transmitter is a
+serial port compliant with the IEC-60958 standard.
+
+properties:
+  "#sound-dai-cells":
+const: 0
+
+  compatible:
+oneOf:
+  - const: microchip,sama7g5-spdiftx
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  clocks:
+items:
+  - description: Peripheral Bus Clock
+  - description: Generic Clock
+
+  clock-names:
+items:
+  - const: pclk
+  - const: gclk
+
+  dmas:
+description: TX DMA Channel
+
+  dma-names:
+const: tx
+
+  pinctrl-0: true
+
+  pinctrl-names:
+const: default
+
+required:
+  - "#sound-dai-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+
+spdiftx@e1618000 {
+#sound-dai-cells = <0>;
+compatible = "microchip,sama7g5-spdiftx";
+reg = <0xe1618000 0x4000>;
+interrupts = ;
+dmas = < AT91_XDMAC_DT_PERID(50)>;
+dma-names = "tx";
+clocks = < PMC_TYPE_PERIPHERAL 85>, < PMC_TYPE_GCK 85>;
+clock-names = "pclk", "gclk";
+pinctrl-names = "default";
+pinctrl-0 = <_spdiftx_default>;
+};
-- 
2.25.1



[PATCH 1/2] dt-bindings: sound: add DT bindings for Microchip S/PDIF TX Controller

2020-07-28 Thread Codrin Ciubotariu
This patch adds DT bindings for the new Microchip S/PDIF TX Controller
embedded inside sama7g5 SoCs.

Signed-off-by: Codrin Ciubotariu 
---
 .../bindings/sound/mchp,spdiftx.yaml  | 76 +++
 1 file changed, 76 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml

diff --git a/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml 
b/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
new file mode 100644
index ..8e2acfbbe621
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: https://devicetree.org/schemas/sound/mchp,spdiftx.yaml#
+$schema: https://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip S/PDIF Tx Controller Device Tree Bindings
+
+maintainers:
+  - Codrin Ciubotariu 
+
+description:
+The Microchip Sony/Philips Digital Interface Transmitter is a
+serial port compliant with the IEC-60958 standard.
+
+properties:
+  "#sound-dai-cells":
+const: 0
+
+  compatible:
+oneOf:
+  - const: microchip,sama7g5-spdiftx
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  clocks:
+items:
+  - description: Peripheral Bus Clock
+  - description: Generic Clock
+
+  clock-names:
+items:
+  - const: pclk
+  - const: gclk
+
+  dmas:
+description: TX DMA Channel
+
+  dma-names:
+const: tx
+
+  pinctrl-0: true
+
+  pinctrl-names:
+const: default
+
+required:
+  - "#sound-dai-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+
+additionalProperties: false
+
+examples:
+  - |
+spdiftx@e1618000 {
+#sound-dai-cells = <0>;
+compatible = "microchip,sama7g5-spdiftx";
+reg = <0xe1618000 0x100>;
+interrupts = ;
+dmas = < AT91_XDMAC_DT_PERID(50)>;
+dma-names = "tx";
+clocks = <_clk>, <_gclk>;
+clock-names = "pclk", "gclk";
+pinctrl-names = "default";
+pinctrl-0 = <_spdiftx_default>;
+};
-- 
2.25.1



[PATCH 2/2] ASoC: mchp-spdiftx: add driver for S/PDIF TX Controller

2020-07-28 Thread Codrin Ciubotariu
The new SPDIF TX controller is a serial port compliant with the IEC-
60958 standard. It also supports programmable User Data and Channel
Status fields.

This IP is embedded in Microchip's sama7g5 SoC.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/Kconfig|  12 +
 sound/soc/atmel/Makefile   |   2 +
 sound/soc/atmel/mchp-spdiftx.c | 864 +
 3 files changed, 878 insertions(+)
 create mode 100644 sound/soc/atmel/mchp-spdiftx.c

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 71f2d42188c4..93beb7d670a3 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -132,4 +132,16 @@ config SND_MCHP_SOC_I2S_MCC
  and supports a Time Division Multiplexed (TDM) interface with
  external multi-channel audio codecs.
 
+config SND_MCHP_SOC_SPDIFTX
+   tristate "Microchip ASoC driver for boards using S/PDIF TX"
+   depends on OF && (ARCH_AT91 || COMPILE_TEST)
+   select SND_SOC_GENERIC_DMAENGINE_PCM
+   select REGMAP_MMIO
+   help
+ Say Y or M if you want to add support for Microchip S/PDIF TX ASoc
+ driver on the following Microchip platforms:
+ - sama7g5
+
+ This S/PDIF TX driver is compliant with IEC-60958 standard and
+ includes programable User Data and Channel Status fields.
 endif
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index c7d2989791be..3fd89a0063df 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -5,6 +5,7 @@ snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
 snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
 snd-soc-atmel-i2s-objs := atmel-i2s.o
 snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o
+snd-soc-mchp-spdiftx-objs := mchp-spdiftx.o
 
 # pdc and dma need to both be built-in if any user of
 # ssc is built-in.
@@ -17,6 +18,7 @@ endif
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
 obj-$(CONFIG_SND_MCHP_SOC_I2S_MCC) += snd-soc-mchp-i2s-mcc.o
+obj-$(CONFIG_SND_MCHP_SOC_SPDIFTX) += snd-soc-mchp-spdiftx.o
 
 # AT91 Machine Support
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c
new file mode 100644
index ..738f6788212e
--- /dev/null
+++ b/sound/soc/atmel/mchp-spdiftx.c
@@ -0,0 +1,864 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Driver for Microchip S/PDIF TX Controller
+//
+// Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
+//
+// Author: Codrin Ciubotariu 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+ *  S/PDIF Transmitter Controller Register map 
+ */
+#define SPDIFTX_CR 0x00/* Control Register */
+#define SPDIFTX_MR 0x04/* Mode Register */
+#define SPDIFTX_CDR0x0C/* Common Data Register */
+
+#define SPDIFTX_IER0x14/* Interrupt Enable Register */
+#define SPDIFTX_IDR0x18/* Interrupt Disable Register */
+#define SPDIFTX_IMR0x1C/* Interrupt Mask Register */
+#define SPDIFTX_ISR0x20/* Interrupt Status Register */
+
+#define SPDIFTX_CH1UD(reg) (0x50 + (reg) * 4)  /* User Data 1 Register 
x */
+#define SPDIFTX_CH1S(reg)  (0x80 + (reg) * 4)  /* Channel Status 1 
Register x */
+
+#define SPDIFTX_VERSION0xF0
+
+/*
+ *  Control Register (Write-only) 
+ */
+#define SPDIFTX_CR_SWRST   BIT(0)  /* Software Reset */
+#define SPDIFTX_CR_FCLRBIT(1)  /* FIFO clear */
+
+/*
+ *  Mode Register (Read/Write) 
+ */
+/* Transmit Enable */
+#define SPDIFTX_MR_TXEN_MASK   GENMASK(0, 0)
+#define SPDIFTX_MR_TXEN_DISABLE(0 << 0)
+#define SPDIFTX_MR_TXEN_ENABLE (1 << 0)
+
+/* Multichannel Transfer */
+#define SPDIFTX_MR_MULTICH_MASKGENAMSK(1, 1)
+#define SPDIFTX_MR_MULTICH_MONO(0 << 1)
+#define SPDIFTX_MR_MULTICH_DUAL(1 << 1)
+
+/* Data Word Endian Mode */
+#define SPDIFTX_MR_ENDIAN_MASK GENMASK(2, 2)
+#define SPDIFTX_MR_ENDIAN_LITTLE   (0 << 2)
+#define SPDIFTX_MR_ENDIAN_BIG  (1 << 2)
+
+/* Data Justification */
+#define SPDIFTX_MR_JUSTIFY_MASKGENMASK(3, 3)
+#define SPDIFTX_MR_JUSTIFY_LSB (0 << 3)
+#define SPDIFTX_MR_JUSTIFY_MSB (1 << 3)
+
+/* Common Audio Register Transfer Mode */
+#define SPDIFTX_MR_CMODE_MASK  GENMASK(5, 4)
+#define SPDIFTX_MR_CMODE_INDEX_ACCESS  (0 << 4)
+#define SPDIFTX_MR_CMODE_TOGGLE_ACCESS (1 << 4)
+#define SPDIFTX_MR_CMODE_INTERLVD_ACCESS   (2 << 4)
+
+/* Valid Bits per Sample */
+#define SPDIFTX_MR_VBPS_MASK   GENMASK(13, 8)
+#define SPDIFTX_MR_VBPS(bps)   (((b

[PATCH net-next v3 7/7] ARM: dts: at91: sam9x60: add an mdio sub-node to macb

2020-07-24 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
Reviewed-by: Florian Fainelli 
---

Changes in v3:
 - added tag from Florian

Changes in v2:
 - none

 arch/arm/boot/dts/at91-sam9x60ek.dts | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sam9x60ek.dts 
b/arch/arm/boot/dts/at91-sam9x60ek.dts
index a5f5718c711a..ba871ebe10d4 100644
--- a/arch/arm/boot/dts/at91-sam9x60ek.dts
+++ b/arch/arm/boot/dts/at91-sam9x60ek.dts
@@ -324,8 +324,12 @@  {
pinctrl-0 = <_macb0_rmii>;
status = "okay";
 
-   ethernet-phy@0 {
-   reg = <0x0>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@0 {
+   reg = <0x0>;
+   };
};
 };
 
-- 
2.25.1



[PATCH net-next v3 6/7] ARM: dts: at91: sama5d4: add an mdio sub-node to macb

2020-07-24 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
Reviewed-by: Florian Fainelli 
---

Changes in v3:
 - added tag from Florian

Changes in v2:
 - none

 arch/arm/boot/dts/at91-sama5d4_xplained.dts | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
index 924d9491780d..62598d06aead 100644
--- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
@@ -59,10 +59,14 @@ macb0: ethernet@f802 {
pinctrl-names = "default";
pinctrl-0 = <_macb0_rmii 
_macb0_phy_irq>;
 
-   phy0: ethernet-phy@1 {
-   interrupt-parent = <>;
-   interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
-   reg = <1>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   phy0: ethernet-phy@1 {
+   interrupt-parent = <>;
+   interrupts = <1 
IRQ_TYPE_LEVEL_LOW>;
+   reg = <1>;
+   };
};
};
 
-- 
2.25.1



[PATCH net-next v3 5/7] ARM: dts: at91: sama5d3: add an mdio sub-node to macb

2020-07-24 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
Reviewed-by: Florian Fainelli 
---

Changes in v3:
 - added tag from Florian

Changes in v2:
 - none

 arch/arm/boot/dts/at91-sama5d3_xplained.dts | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
index 61f068a7b362..25d2646ce4cb 100644
--- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
@@ -133,8 +133,12 @@ macb0: ethernet@f0028000 {
#size-cells = <0>;
status = "okay";
 
-   ethernet-phy@7 {
-   reg = <0x7>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@7 {
+   reg = <0x7>;
+   };
};
};
 
@@ -200,8 +204,12 @@ macb1: ethernet@f802c000 {
#size-cells = <0>;
status = "okay";
 
-   ethernet-phy@1 {
-   reg = <0x1>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@1 {
+   reg = <0x1>;
+   };
};
};
 
-- 
2.25.1



[PATCH net-next v3 0/7] Add an MDIO sub-node under MACB

2020-07-24 Thread Codrin Ciubotariu
Changes in v3:
 - in patch 3/7, moved the checking for mdio node at the beginning of
   the macb_mdiobus_register(). This allows to probe the MDIO devices
   even if macb is a fixed-link
 - added tags received on v2

Changes in v2:
 - renamed patch 2/7 from "macb: bindings doc: use an MDIO node as a
   container for PHY nodes" to "dt-bindings: net: macb: use an MDIO
   node as a container for PHY nodes"
 - added back a newline removed by mistake in patch 3/7

Codrin Ciubotariu (7):
  net: macb: use device-managed devm_mdiobus_alloc()
  dt-bindings: net: macb: use an MDIO node as a container for PHY nodes
  net: macb: parse PHY nodes found under an MDIO node
  ARM: dts: at91: sama5d2: add an mdio sub-node to macb
  ARM: dts: at91: sama5d3: add an mdio sub-node to macb
  ARM: dts: at91: sama5d4: add an mdio sub-node to macb
  ARM: dts: at91: sam9x60: add an mdio sub-node to macb

 Documentation/devicetree/bindings/net/macb.txt | 15 ---
 arch/arm/boot/dts/at91-sam9x60ek.dts   |  8 ++--
 arch/arm/boot/dts/at91-sama5d27_som1.dtsi  | 16 ++--
 arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi| 17 ++---
 arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts  | 13 -
 arch/arm/boot/dts/at91-sama5d2_xplained.dts| 12 
 arch/arm/boot/dts/at91-sama5d3_xplained.dts| 16 
 arch/arm/boot/dts/at91-sama5d4_xplained.dts| 12 
 drivers/net/ethernet/cadence/macb_main.c   | 18 --
 9 files changed, 86 insertions(+), 41 deletions(-)

-- 
2.25.1



[PATCH net-next v3 3/7] net: macb: parse PHY nodes found under an MDIO node

2020-07-24 Thread Codrin Ciubotariu
The MACB embeds an MDIO bus controller. For this reason, the PHY nodes
were represented as sub-nodes in the MACB node. Generally, the
Ethernet controller is different than the MDIO controller, so the PHYs
are probed by a separate MDIO driver. Since adding the PHY nodes directly
under the ETH node became deprecated, we adjust the MACB driver to look
for an MDIO node and register the subnode MDIO devices.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v3:
 - moved the check for the mdio node at the beginnging of
   macb_mdiobus_register(). This way, the mdio devices will be probed even
   if macb is a fixed-link

Changes in v2:
 - readded newline removed by mistake;

 drivers/net/ethernet/cadence/macb_main.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 89fe7af5e408..cb0b3637651c 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -740,6 +740,16 @@ static int macb_mii_probe(struct net_device *dev)
 static int macb_mdiobus_register(struct macb *bp)
 {
struct device_node *child, *np = bp->pdev->dev.of_node;
+   struct device_node *mdio_node;
+   int ret;
+
+   /* if an MDIO node is present, it should contain the PHY nodes */
+   mdio_node = of_get_child_by_name(np, "mdio");
+   if (mdio_node) {
+   ret = of_mdiobus_register(bp->mii_bus, mdio_node);
+   of_node_put(mdio_node);
+   return ret;
+   }
 
if (of_phy_is_fixed_link(np))
return mdiobus_register(bp->mii_bus);
-- 
2.25.1



[PATCH net-next v3 4/7] ARM: dts: at91: sama5d2: add an mdio sub-node to macb

2020-07-24 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
Reviewed-by: Florian Fainelli 
---

Changes in v3:
 - added tag from Florian

Changes in v2:
 - none

 arch/arm/boot/dts/at91-sama5d27_som1.dtsi   | 16 ++--
 arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi | 17 ++---
 arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts   | 13 -
 arch/arm/boot/dts/at91-sama5d2_xplained.dts | 12 
 4 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi 
b/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
index b1f994c0ae79..dfcee23dcce0 100644
--- a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
+++ b/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
@@ -84,12 +84,16 @@ macb0: ethernet@f8008000 {
pinctrl-0 = <_macb0_default>;
phy-mode = "rmii";
 
-   ethernet-phy@0 {
-   reg = <0x0>;
-   interrupt-parent = <>;
-   interrupts = ;
-   pinctrl-names = "default";
-   pinctrl-0 = <_macb0_phy_irq>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@0 {
+   reg = <0x0>;
+   interrupt-parent = <>;
+   interrupts = ;
+   pinctrl-names = "default";
+   pinctrl-0 = 
<_macb0_phy_irq>;
+   };
};
};
 
diff --git a/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi 
b/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi
index a06700e53e4c..9c4dce29d2fe 100644
--- a/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi
+++ b/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi
@@ -181,13 +181,16 @@  {
pinctrl-names = "default";
pinctrl-0 = <_macb0_default>;
phy-mode = "rmii";
-
-   ethernet-phy@0 {
-   reg = <0x0>;
-   interrupt-parent = <>;
-   interrupts = ;
-   pinctrl-names = "default";
-   pinctrl-0 = <_macb0_phy_irq>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@0 {
+   reg = <0x0>;
+   interrupt-parent = <>;
+   interrupts = ;
+   pinctrl-names = "default";
+   pinctrl-0 = <_macb0_phy_irq>;
+   };
};
 };
 
diff --git a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts 
b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
index c894c7c788a9..fc3375c43ef6 100644
--- a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
@@ -140,11 +140,14 @@ macb0: ethernet@f8008000 {
pinctrl-0 = <_macb0_default 
_macb0_phy_irq>;
phy-mode = "rmii";
status = "okay";
-
-   ethernet-phy@1 {
-   reg = <0x1>;
-   interrupt-parent = <>;
-   interrupts = <56 IRQ_TYPE_LEVEL_LOW>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@1 {
+   reg = <0x1>;
+   interrupt-parent = <>;
+   interrupts = <56 
IRQ_TYPE_LEVEL_LOW>;
+   };
};
};
 
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index a927165ea7c2..a62f475d9d0a 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -149,10 +149,14 @@ macb0: ethernet@f8008000 {
phy-mode = "rmii";
status = "okay";
 
-   ethernet-phy@1 {
-   reg = <0x1>

[PATCH net-next v3 1/7] net: macb: use device-managed devm_mdiobus_alloc()

2020-07-24 Thread Codrin Ciubotariu
Use the device-managed variant for the allocating the MDIO bus. This
cleans-up the code a little on the remove and error paths.

Signed-off-by: Codrin Ciubotariu 
Tested-by: Claudiu Beznea 
Acked-by: Claudiu Beznea 
Reviewed-by: Florian Fainelli 
---

Changes in v3:
 - added tags from Claudiu and Florian

Changes in v2:
 - none

 drivers/net/ethernet/cadence/macb_main.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index a6a35e1b0115..89fe7af5e408 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -769,7 +769,7 @@ static int macb_mii_init(struct macb *bp)
/* Enable management port */
macb_writel(bp, NCR, MACB_BIT(MPE));
 
-   bp->mii_bus = mdiobus_alloc();
+   bp->mii_bus = devm_mdiobus_alloc(>pdev->dev);
if (!bp->mii_bus) {
err = -ENOMEM;
goto err_out;
@@ -787,7 +787,7 @@ static int macb_mii_init(struct macb *bp)
 
err = macb_mdiobus_register(bp);
if (err)
-   goto err_out_free_mdiobus;
+   goto err_out;
 
err = macb_mii_probe(bp->dev);
if (err)
@@ -797,8 +797,6 @@ static int macb_mii_init(struct macb *bp)
 
 err_out_unregister_bus:
mdiobus_unregister(bp->mii_bus);
-err_out_free_mdiobus:
-   mdiobus_free(bp->mii_bus);
 err_out:
return err;
 }
@@ -4571,7 +4569,6 @@ static int macb_probe(struct platform_device *pdev)
 
 err_out_unregister_mdio:
mdiobus_unregister(bp->mii_bus);
-   mdiobus_free(bp->mii_bus);
 
 err_out_free_netdev:
free_netdev(dev);
@@ -4599,7 +4596,6 @@ static int macb_remove(struct platform_device *pdev)
if (dev) {
bp = netdev_priv(dev);
mdiobus_unregister(bp->mii_bus);
-   mdiobus_free(bp->mii_bus);
 
unregister_netdev(dev);
tasklet_kill(>hresp_err_tasklet);
-- 
2.25.1



[PATCH net-next v3 2/7] dt-bindings: net: macb: use an MDIO node as a container for PHY nodes

2020-07-24 Thread Codrin Ciubotariu
The MACB driver embeds an MDIO bus controller and for this reason there
was no need for an MDIO sub-node present to contain the PHY nodes. Adding
MDIO devies directly under an Ethernet node is deprecated, so an MDIO node
is included to contain of the PHY nodes (and other MDIO devices' nodes).

Signed-off-by: Codrin Ciubotariu 
Acked-by: Claudiu Beznea 
Reviewed-by: Rob Herring 
Reviewed-by: Florian Fainelli 
---

Changes in v3:
 - Added tags from Claudiu, Rob and Florian

Changes in v2:
 - patch renamed from "macb: bindings doc: use an MDIO node as a
   container for PHY nodes" to "dt-bindings: net: macb: use an MDIO
   node as a container for PHY nodes" 

 Documentation/devicetree/bindings/net/macb.txt | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/macb.txt 
b/Documentation/devicetree/bindings/net/macb.txt
index 0b61a90f1592..88d5199c2279 100644
--- a/Documentation/devicetree/bindings/net/macb.txt
+++ b/Documentation/devicetree/bindings/net/macb.txt
@@ -32,6 +32,11 @@ Required properties:
 The MAC address will be determined using the optional properties
 defined in ethernet.txt.
 
+Optional subnodes:
+- mdio : specifies the MDIO bus in the MACB, used as a container for PHY nodes 
or other
+  nodes of devices present on the MDIO bus. Please see ethernet-phy.yaml in 
the same
+  directory for more details.
+
 Optional properties for PHY child node:
 - reset-gpios : Should specify the gpio for phy reset
 - magic-packet : If present, indicates that the hardware supports waking
@@ -48,8 +53,12 @@ Examples:
local-mac-address = [3a 0e 03 04 05 06];
clock-names = "pclk", "hclk", "tx_clk";
clocks = < 30>, < 30>, < 13>;
-   ethernet-phy@1 {
-   reg = <0x1>;
-   reset-gpios = < 6 1>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@1 {
+   reg = <0x1>;
+   reset-gpios = < 6 1>;
+   };
};
};
-- 
2.25.1



[PATCH 3/3] ARM: configs: at91: sama5: enable CAN PLATFORM driver

2020-07-23 Thread Codrin Ciubotariu
From: Cristian Birsan 

CAN_M_CAN_PLATFORM is needed to probe the driver on sama5 platforms
after the driver was split into multiple files.

Signed-off-by: Cristian Birsan 
Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/configs/sama5_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index f4d71ffcb6e9..7b7e333157fe 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -56,6 +56,7 @@ CONFIG_VLAN_8021Q=m
 CONFIG_CAN=y
 CONFIG_CAN_AT91=y
 CONFIG_CAN_M_CAN=y
+CONFIG_CAN_M_CAN_PLATFORM=y
 CONFIG_CFG80211=y
 CONFIG_MAC80211=y
 CONFIG_MAC80211_LEDS=y
-- 
2.25.1



[PATCH 2/3] ARM: configs: at91: sama5: enable bridge and VLAN filtering

2020-07-23 Thread Codrin Ciubotariu
From: Razvan Stefanescu 

These modules are needed to configure bridges in Linux, to take full
advantage of the KSZ switch capabilities.

Signed-off-by: Razvan Stefanescu 
Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/configs/sama5_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index 123b95c1447a..f4d71ffcb6e9 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -49,7 +49,10 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET6_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET6_XFRM_MODE_BEET is not set
 CONFIG_IPV6_SIT_6RD=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
 CONFIG_NET_DSA=m
+CONFIG_VLAN_8021Q=m
 CONFIG_CAN=y
 CONFIG_CAN_AT91=y
 CONFIG_CAN_M_CAN=y
-- 
2.25.1



[PATCH 1/3] ARM: configs: at91: sama5: add support for KSZ ethernet switches

2020-07-23 Thread Codrin Ciubotariu
From: Razvan Stefanescu 

Enable DSA and KSZ9477 support as modules. Ethernet switches are used by
the SAMA5D2-ICP board.

Signed-off-by: Razvan Stefanescu 
Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/configs/sama5_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index f688443fe7bf..123b95c1447a 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -49,6 +49,7 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET6_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET6_XFRM_MODE_BEET is not set
 CONFIG_IPV6_SIT_6RD=y
+CONFIG_NET_DSA=m
 CONFIG_CAN=y
 CONFIG_CAN_AT91=y
 CONFIG_CAN_M_CAN=y
@@ -80,6 +81,8 @@ CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
+CONFIG_NET_DSA_MICROCHIP_KSZ9477=m
+CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI=m
 CONFIG_MACB=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
-- 
2.25.1



[PATCH net-next v2 7/7] ARM: dts: at91: sam9x60: add an mdio sub-node to macb

2020-07-21 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - none

 arch/arm/boot/dts/at91-sam9x60ek.dts | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sam9x60ek.dts 
b/arch/arm/boot/dts/at91-sam9x60ek.dts
index a5f5718c711a..ba871ebe10d4 100644
--- a/arch/arm/boot/dts/at91-sam9x60ek.dts
+++ b/arch/arm/boot/dts/at91-sam9x60ek.dts
@@ -324,8 +324,12 @@  {
pinctrl-0 = <_macb0_rmii>;
status = "okay";
 
-   ethernet-phy@0 {
-   reg = <0x0>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@0 {
+   reg = <0x0>;
+   };
};
 };
 
-- 
2.25.1



[PATCH net-next v2 6/7] ARM: dts: at91: sama5d4: add an mdio sub-node to macb

2020-07-21 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - none

 arch/arm/boot/dts/at91-sama5d4_xplained.dts | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
index 924d9491780d..62598d06aead 100644
--- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
@@ -59,10 +59,14 @@ macb0: ethernet@f802 {
pinctrl-names = "default";
pinctrl-0 = <_macb0_rmii 
_macb0_phy_irq>;
 
-   phy0: ethernet-phy@1 {
-   interrupt-parent = <>;
-   interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
-   reg = <1>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   phy0: ethernet-phy@1 {
+   interrupt-parent = <>;
+   interrupts = <1 
IRQ_TYPE_LEVEL_LOW>;
+   reg = <1>;
+   };
};
};
 
-- 
2.25.1



[PATCH net-next v2 5/7] ARM: dts: at91: sama5d3: add an mdio sub-node to macb

2020-07-21 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - none;

 arch/arm/boot/dts/at91-sama5d3_xplained.dts | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
index 61f068a7b362..25d2646ce4cb 100644
--- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
@@ -133,8 +133,12 @@ macb0: ethernet@f0028000 {
#size-cells = <0>;
status = "okay";
 
-   ethernet-phy@7 {
-   reg = <0x7>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@7 {
+   reg = <0x7>;
+   };
};
};
 
@@ -200,8 +204,12 @@ macb1: ethernet@f802c000 {
#size-cells = <0>;
status = "okay";
 
-   ethernet-phy@1 {
-   reg = <0x1>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@1 {
+   reg = <0x1>;
+   };
};
};
 
-- 
2.25.1



[PATCH net-next v2 4/7] ARM: dts: at91: sama5d2: add an mdio sub-node to macb

2020-07-21 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - none

 arch/arm/boot/dts/at91-sama5d27_som1.dtsi   | 16 ++--
 arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi | 17 ++---
 arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts   | 13 -
 arch/arm/boot/dts/at91-sama5d2_xplained.dts | 12 
 4 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi 
b/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
index b1f994c0ae79..dfcee23dcce0 100644
--- a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
+++ b/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
@@ -84,12 +84,16 @@ macb0: ethernet@f8008000 {
pinctrl-0 = <_macb0_default>;
phy-mode = "rmii";
 
-   ethernet-phy@0 {
-   reg = <0x0>;
-   interrupt-parent = <>;
-   interrupts = ;
-   pinctrl-names = "default";
-   pinctrl-0 = <_macb0_phy_irq>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@0 {
+   reg = <0x0>;
+   interrupt-parent = <>;
+   interrupts = ;
+   pinctrl-names = "default";
+   pinctrl-0 = 
<_macb0_phy_irq>;
+   };
};
};
 
diff --git a/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi 
b/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi
index a06700e53e4c..9c4dce29d2fe 100644
--- a/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi
+++ b/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi
@@ -181,13 +181,16 @@  {
pinctrl-names = "default";
pinctrl-0 = <_macb0_default>;
phy-mode = "rmii";
-
-   ethernet-phy@0 {
-   reg = <0x0>;
-   interrupt-parent = <>;
-   interrupts = ;
-   pinctrl-names = "default";
-   pinctrl-0 = <_macb0_phy_irq>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@0 {
+   reg = <0x0>;
+   interrupt-parent = <>;
+   interrupts = ;
+   pinctrl-names = "default";
+   pinctrl-0 = <_macb0_phy_irq>;
+   };
};
 };
 
diff --git a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts 
b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
index c894c7c788a9..fc3375c43ef6 100644
--- a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
@@ -140,11 +140,14 @@ macb0: ethernet@f8008000 {
pinctrl-0 = <_macb0_default 
_macb0_phy_irq>;
phy-mode = "rmii";
status = "okay";
-
-   ethernet-phy@1 {
-   reg = <0x1>;
-   interrupt-parent = <>;
-   interrupts = <56 IRQ_TYPE_LEVEL_LOW>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@1 {
+   reg = <0x1>;
+   interrupt-parent = <>;
+   interrupts = <56 
IRQ_TYPE_LEVEL_LOW>;
+   };
};
};
 
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index a927165ea7c2..a62f475d9d0a 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -149,10 +149,14 @@ macb0: ethernet@f8008000 {
phy-mode = "rmii";
status = "okay";
 
-   ethernet-phy@1 {
-   reg = <0x1>;
-   interrupt-parent = <>;
-   interr

[PATCH net-next v2 3/7] net: macb: parse PHY nodes found under an MDIO node

2020-07-21 Thread Codrin Ciubotariu
The MACB embeds an MDIO bus controller. For this reason, the PHY nodes
were represented as sub-nodes in the MACB node. Generally, the
Ethernet controller is different than the MDIO controller, so the PHYs
are probed by a separate MDIO driver. Since adding the PHY nodes directly
under the ETH node became deprecated, we adjust the MACB driver to look
for an MDIO node and register the subnode MDIO devices.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - readded newline removed by mistake;

 drivers/net/ethernet/cadence/macb_main.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 89fe7af5e408..b25c64b45148 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -740,10 +740,20 @@ static int macb_mii_probe(struct net_device *dev)
 static int macb_mdiobus_register(struct macb *bp)
 {
struct device_node *child, *np = bp->pdev->dev.of_node;
+   struct device_node *mdio_node;
+   int ret;
 
if (of_phy_is_fixed_link(np))
return mdiobus_register(bp->mii_bus);
 
+   /* if an MDIO node is present, it should contain the PHY nodes */
+   mdio_node = of_get_child_by_name(np, "mdio");
+   if (mdio_node) {
+   ret = of_mdiobus_register(bp->mii_bus, mdio_node);
+   of_node_put(mdio_node);
+   return ret;
+   }
+
/* Only create the PHY from the device tree if at least one PHY is
 * described. Otherwise scan the entire MDIO bus. We do this to support
 * old device tree that did not follow the best practices and did not
-- 
2.25.1



[PATCH net-next v2 2/7] dt-bindings: net: macb: use an MDIO node as a container for PHY nodes

2020-07-21 Thread Codrin Ciubotariu
The MACB driver embeds an MDIO bus controller and for this reason there
was no need for an MDIO sub-node present to contain the PHY nodes. Adding
MDIO devies directly under an Ethernet node is deprecated, so an MDIO node
is included to contain of the PHY nodes (and other MDIO devices' nodes).

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - patch renamed from "macb: bindings doc: use an MDIO node as a
   container for PHY nodes" to "dt-bindings: net: macb: use an MDIO
   node as a container for PHY nodes" 

 Documentation/devicetree/bindings/net/macb.txt | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/macb.txt 
b/Documentation/devicetree/bindings/net/macb.txt
index 0b61a90f1592..88d5199c2279 100644
--- a/Documentation/devicetree/bindings/net/macb.txt
+++ b/Documentation/devicetree/bindings/net/macb.txt
@@ -32,6 +32,11 @@ Required properties:
 The MAC address will be determined using the optional properties
 defined in ethernet.txt.
 
+Optional subnodes:
+- mdio : specifies the MDIO bus in the MACB, used as a container for PHY nodes 
or other
+  nodes of devices present on the MDIO bus. Please see ethernet-phy.yaml in 
the same
+  directory for more details.
+
 Optional properties for PHY child node:
 - reset-gpios : Should specify the gpio for phy reset
 - magic-packet : If present, indicates that the hardware supports waking
@@ -48,8 +53,12 @@ Examples:
local-mac-address = [3a 0e 03 04 05 06];
clock-names = "pclk", "hclk", "tx_clk";
clocks = < 30>, < 30>, < 13>;
-   ethernet-phy@1 {
-   reg = <0x1>;
-   reset-gpios = < 6 1>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@1 {
+   reg = <0x1>;
+   reset-gpios = < 6 1>;
+   };
};
};
-- 
2.25.1



[PATCH net-next v2 1/7] net: macb: use device-managed devm_mdiobus_alloc()

2020-07-21 Thread Codrin Ciubotariu
Use the device-managed variant for the allocating the MDIO bus. This
cleans-up the code a little on the remove and error paths.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - none

 drivers/net/ethernet/cadence/macb_main.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index a6a35e1b0115..89fe7af5e408 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -769,7 +769,7 @@ static int macb_mii_init(struct macb *bp)
/* Enable management port */
macb_writel(bp, NCR, MACB_BIT(MPE));
 
-   bp->mii_bus = mdiobus_alloc();
+   bp->mii_bus = devm_mdiobus_alloc(>pdev->dev);
if (!bp->mii_bus) {
err = -ENOMEM;
goto err_out;
@@ -787,7 +787,7 @@ static int macb_mii_init(struct macb *bp)
 
err = macb_mdiobus_register(bp);
if (err)
-   goto err_out_free_mdiobus;
+   goto err_out;
 
err = macb_mii_probe(bp->dev);
if (err)
@@ -797,8 +797,6 @@ static int macb_mii_init(struct macb *bp)
 
 err_out_unregister_bus:
mdiobus_unregister(bp->mii_bus);
-err_out_free_mdiobus:
-   mdiobus_free(bp->mii_bus);
 err_out:
return err;
 }
@@ -4571,7 +4569,6 @@ static int macb_probe(struct platform_device *pdev)
 
 err_out_unregister_mdio:
mdiobus_unregister(bp->mii_bus);
-   mdiobus_free(bp->mii_bus);
 
 err_out_free_netdev:
free_netdev(dev);
@@ -4599,7 +4596,6 @@ static int macb_remove(struct platform_device *pdev)
if (dev) {
bp = netdev_priv(dev);
mdiobus_unregister(bp->mii_bus);
-   mdiobus_free(bp->mii_bus);
 
unregister_netdev(dev);
tasklet_kill(>hresp_err_tasklet);
-- 
2.25.1



[PATCH net-next v2 0/7] Add an MDIO sub-node under MACB

2020-07-21 Thread Codrin Ciubotariu
Adding the PHY nodes directly under the Ethernet node became deprecated,
so the aim of this patch series is to make MACB use an MDIO node as
container for MDIO devices.
This patch series starts with a small patch to use the device-managed
devm_mdiobus_alloc(). In the next two patches we update the bindings and
adapt macb driver to parse the device-tree PHY nodes from under an MDIO
node. The last patches add the MDIO node in the device-trees of sama5d2,
sama5d3, samad4 and sam9x60 boards.

Changes in v2:
 - renamed patch 2/7 from "macb: bindings doc: use an MDIO node as a
   container for PHY nodes" to "dt-bindings: net: macb: use an MDIO
   node as a container for PHY nodes"
 - added back a newline removed by mistake in patch 3/7

Codrin Ciubotariu (7):
  net: macb: use device-managed devm_mdiobus_alloc()
  dt-bindings: net: macb: use an MDIO node as a container for PHY nodes
  net: macb: parse PHY nodes found under an MDIO node
  ARM: dts: at91: sama5d2: add an mdio sub-node to macb
  ARM: dts: at91: sama5d3: add an mdio sub-node to macb
  ARM: dts: at91: sama5d4: add an mdio sub-node to macb
  ARM: dts: at91: sam9x60: add an mdio sub-node to macb

 Documentation/devicetree/bindings/net/macb.txt | 15 ---
 arch/arm/boot/dts/at91-sam9x60ek.dts   |  8 ++--
 arch/arm/boot/dts/at91-sama5d27_som1.dtsi  | 16 ++--
 arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi| 17 ++---
 arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts  | 13 -
 arch/arm/boot/dts/at91-sama5d2_xplained.dts| 12 
 arch/arm/boot/dts/at91-sama5d3_xplained.dts| 16 
 arch/arm/boot/dts/at91-sama5d4_xplained.dts| 12 
 drivers/net/ethernet/cadence/macb_main.c   | 18 --
 9 files changed, 86 insertions(+), 41 deletions(-)

-- 
2.25.1



[PATCH net-next 7/7] ARM: dts: at91: sam9x60: add an mdio sub-node to macb

2020-07-21 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/boot/dts/at91-sam9x60ek.dts | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sam9x60ek.dts 
b/arch/arm/boot/dts/at91-sam9x60ek.dts
index a5f5718c711a..ba871ebe10d4 100644
--- a/arch/arm/boot/dts/at91-sam9x60ek.dts
+++ b/arch/arm/boot/dts/at91-sam9x60ek.dts
@@ -324,8 +324,12 @@  {
pinctrl-0 = <_macb0_rmii>;
status = "okay";
 
-   ethernet-phy@0 {
-   reg = <0x0>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@0 {
+   reg = <0x0>;
+   };
};
 };
 
-- 
2.25.1



[PATCH net-next 6/7] ARM: dts: at91: sama5d4: add an mdio sub-node to macb

2020-07-21 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/boot/dts/at91-sama5d4_xplained.dts | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
index 924d9491780d..62598d06aead 100644
--- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
@@ -59,10 +59,14 @@ macb0: ethernet@f802 {
pinctrl-names = "default";
pinctrl-0 = <_macb0_rmii 
_macb0_phy_irq>;
 
-   phy0: ethernet-phy@1 {
-   interrupt-parent = <>;
-   interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
-   reg = <1>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   phy0: ethernet-phy@1 {
+   interrupt-parent = <>;
+   interrupts = <1 
IRQ_TYPE_LEVEL_LOW>;
+   reg = <1>;
+   };
};
};
 
-- 
2.25.1



[PATCH net-next 5/7] ARM: dts: at91: sama5d3: add an mdio sub-node to macb

2020-07-21 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/boot/dts/at91-sama5d3_xplained.dts | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
index 61f068a7b362..25d2646ce4cb 100644
--- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
@@ -133,8 +133,12 @@ macb0: ethernet@f0028000 {
#size-cells = <0>;
status = "okay";
 
-   ethernet-phy@7 {
-   reg = <0x7>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@7 {
+   reg = <0x7>;
+   };
};
};
 
@@ -200,8 +204,12 @@ macb1: ethernet@f802c000 {
#size-cells = <0>;
status = "okay";
 
-   ethernet-phy@1 {
-   reg = <0x1>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@1 {
+   reg = <0x1>;
+   };
};
};
 
-- 
2.25.1



[PATCH net-next 4/7] ARM: dts: at91: sama5d2: add an mdio sub-node to macb

2020-07-21 Thread Codrin Ciubotariu
Use the new macb bindings and add an mdio sub-node to contain all the
phy nodes.

Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/boot/dts/at91-sama5d27_som1.dtsi   | 16 ++--
 arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi | 17 ++---
 arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts   | 13 -
 arch/arm/boot/dts/at91-sama5d2_xplained.dts | 12 
 4 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi 
b/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
index b1f994c0ae79..dfcee23dcce0 100644
--- a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
+++ b/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
@@ -84,12 +84,16 @@ macb0: ethernet@f8008000 {
pinctrl-0 = <_macb0_default>;
phy-mode = "rmii";
 
-   ethernet-phy@0 {
-   reg = <0x0>;
-   interrupt-parent = <>;
-   interrupts = ;
-   pinctrl-names = "default";
-   pinctrl-0 = <_macb0_phy_irq>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@0 {
+   reg = <0x0>;
+   interrupt-parent = <>;
+   interrupts = ;
+   pinctrl-names = "default";
+   pinctrl-0 = 
<_macb0_phy_irq>;
+   };
};
};
 
diff --git a/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi 
b/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi
index a06700e53e4c..9c4dce29d2fe 100644
--- a/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi
+++ b/arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi
@@ -181,13 +181,16 @@  {
pinctrl-names = "default";
pinctrl-0 = <_macb0_default>;
phy-mode = "rmii";
-
-   ethernet-phy@0 {
-   reg = <0x0>;
-   interrupt-parent = <>;
-   interrupts = ;
-   pinctrl-names = "default";
-   pinctrl-0 = <_macb0_phy_irq>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@0 {
+   reg = <0x0>;
+   interrupt-parent = <>;
+   interrupts = ;
+   pinctrl-names = "default";
+   pinctrl-0 = <_macb0_phy_irq>;
+   };
};
 };
 
diff --git a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts 
b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
index c894c7c788a9..fc3375c43ef6 100644
--- a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
@@ -140,11 +140,14 @@ macb0: ethernet@f8008000 {
pinctrl-0 = <_macb0_default 
_macb0_phy_irq>;
phy-mode = "rmii";
status = "okay";
-
-   ethernet-phy@1 {
-   reg = <0x1>;
-   interrupt-parent = <>;
-   interrupts = <56 IRQ_TYPE_LEVEL_LOW>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@1 {
+   reg = <0x1>;
+   interrupt-parent = <>;
+   interrupts = <56 
IRQ_TYPE_LEVEL_LOW>;
+   };
};
};
 
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index a927165ea7c2..a62f475d9d0a 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -149,10 +149,14 @@ macb0: ethernet@f8008000 {
phy-mode = "rmii";
status = "okay";
 
-   ethernet-phy@1 {
-   reg = <0x1>;
-   interrupt-parent = <>;
-   interr

[PATCH net-next 3/7] net: macb: parse PHY nodes found under an MDIO node

2020-07-21 Thread Codrin Ciubotariu
The MACB embeds an MDIO bus controller. For this reason, the PHY nodes
were represented as sub-nodes in the MACB node. Generally, the
Ethernet controller is different than the MDIO controller, so the PHYs
are probed by a separate MDIO driver. Since adding the PHY nodes directly
under the ETH node became deprecated, we adjust the MACB driver to look
for an MDIO node and register the subnode MDIO devices.

Signed-off-by: Codrin Ciubotariu 
---
 drivers/net/ethernet/cadence/macb_main.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 89fe7af5e408..66f02c16cc7c 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -740,10 +740,20 @@ static int macb_mii_probe(struct net_device *dev)
 static int macb_mdiobus_register(struct macb *bp)
 {
struct device_node *child, *np = bp->pdev->dev.of_node;
+   struct device_node *mdio_node;
+   int ret;
 
if (of_phy_is_fixed_link(np))
return mdiobus_register(bp->mii_bus);
 
+   /* if an MDIO node is present, it should contain the PHY nodes */
+   mdio_node = of_get_child_by_name(np, "mdio");
+   if (mdio_node) {
+   ret = of_mdiobus_register(bp->mii_bus, mdio_node);
+   of_node_put(mdio_node);
+   return ret;
+   }
+
/* Only create the PHY from the device tree if at least one PHY is
 * described. Otherwise scan the entire MDIO bus. We do this to support
 * old device tree that did not follow the best practices and did not
@@ -755,7 +765,6 @@ static int macb_mdiobus_register(struct macb *bp)
 * decrement it before returning.
 */
of_node_put(child);
-
return of_mdiobus_register(bp->mii_bus, np);
}
 
-- 
2.25.1



[PATCH net-next 1/7] net: macb: use device-managed devm_mdiobus_alloc()

2020-07-21 Thread Codrin Ciubotariu
Use the device-managed variant for the allocating the MDIO bus. This
cleans-up the code a little on the remove and error paths.

Signed-off-by: Codrin Ciubotariu 
---
 drivers/net/ethernet/cadence/macb_main.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index a6a35e1b0115..89fe7af5e408 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -769,7 +769,7 @@ static int macb_mii_init(struct macb *bp)
/* Enable management port */
macb_writel(bp, NCR, MACB_BIT(MPE));
 
-   bp->mii_bus = mdiobus_alloc();
+   bp->mii_bus = devm_mdiobus_alloc(>pdev->dev);
if (!bp->mii_bus) {
err = -ENOMEM;
goto err_out;
@@ -787,7 +787,7 @@ static int macb_mii_init(struct macb *bp)
 
err = macb_mdiobus_register(bp);
if (err)
-   goto err_out_free_mdiobus;
+   goto err_out;
 
err = macb_mii_probe(bp->dev);
if (err)
@@ -797,8 +797,6 @@ static int macb_mii_init(struct macb *bp)
 
 err_out_unregister_bus:
mdiobus_unregister(bp->mii_bus);
-err_out_free_mdiobus:
-   mdiobus_free(bp->mii_bus);
 err_out:
return err;
 }
@@ -4571,7 +4569,6 @@ static int macb_probe(struct platform_device *pdev)
 
 err_out_unregister_mdio:
mdiobus_unregister(bp->mii_bus);
-   mdiobus_free(bp->mii_bus);
 
 err_out_free_netdev:
free_netdev(dev);
@@ -4599,7 +4596,6 @@ static int macb_remove(struct platform_device *pdev)
if (dev) {
bp = netdev_priv(dev);
mdiobus_unregister(bp->mii_bus);
-   mdiobus_free(bp->mii_bus);
 
unregister_netdev(dev);
tasklet_kill(>hresp_err_tasklet);
-- 
2.25.1



[PATCH net-next 2/7] macb: bindings doc: use an MDIO node as a container for PHY nodes

2020-07-21 Thread Codrin Ciubotariu
The MACB driver embeds an MDIO bus controller and for this reason there
was no need for an MDIO sub-node present to contain the PHY nodes. Adding
MDIO devies directly under an Ethernet node is deprecated, so an MDIO node
is included to contain of the PHY nodes (and other MDIO devices' nodes).

Signed-off-by: Codrin Ciubotariu 
---
 Documentation/devicetree/bindings/net/macb.txt | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/macb.txt 
b/Documentation/devicetree/bindings/net/macb.txt
index 0b61a90f1592..88d5199c2279 100644
--- a/Documentation/devicetree/bindings/net/macb.txt
+++ b/Documentation/devicetree/bindings/net/macb.txt
@@ -32,6 +32,11 @@ Required properties:
 The MAC address will be determined using the optional properties
 defined in ethernet.txt.
 
+Optional subnodes:
+- mdio : specifies the MDIO bus in the MACB, used as a container for PHY nodes 
or other
+  nodes of devices present on the MDIO bus. Please see ethernet-phy.yaml in 
the same
+  directory for more details.
+
 Optional properties for PHY child node:
 - reset-gpios : Should specify the gpio for phy reset
 - magic-packet : If present, indicates that the hardware supports waking
@@ -48,8 +53,12 @@ Examples:
local-mac-address = [3a 0e 03 04 05 06];
clock-names = "pclk", "hclk", "tx_clk";
clocks = < 30>, < 30>, < 13>;
-   ethernet-phy@1 {
-   reg = <0x1>;
-   reset-gpios = < 6 1>;
+   mdio {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   ethernet-phy@1 {
+   reg = <0x1>;
+   reset-gpios = < 6 1>;
+   };
};
};
-- 
2.25.1



[PATCH net-next 0/7] Add an MDIO sub-node under MACB

2020-07-21 Thread Codrin Ciubotariu
Adding the PHY nodes directly under the Ethernet node became deprecated,
so the aim of this patch series is to make MACB use an MDIO node as
container for MDIO devices.
This patch series starts with a small patch to use the device-managed
devm_mdiobus_alloc(). In the next two patches we update the bindings and
adapt macb driver to parse the device-tree PHY nodes from under an MDIO
node. The last patches add the MDIO node in the device-trees of sama5d2,
sama5d3, samad4 and sam9x60 boards.

Codrin Ciubotariu (7):
  net: macb: use device-managed devm_mdiobus_alloc()
  macb: bindings doc: use an MDIO node as a container for PHY nodes
  net: macb: parse PHY nodes found under an MDIO node
  ARM: dts: at91: sama5d2: add an mdio sub-node to macb
  ARM: dts: at91: sama5d3: add an mdio sub-node to macb
  ARM: dts: at91: sama5d4: add an mdio sub-node to macb
  ARM: dts: at91: sam9x60: add an mdio sub-node to macb

 .../devicetree/bindings/net/macb.txt  | 15 ---
 arch/arm/boot/dts/at91-sam9x60ek.dts  |  8 ++--
 arch/arm/boot/dts/at91-sama5d27_som1.dtsi | 16 ++--
 arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi   | 17 ++---
 arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts | 13 -
 arch/arm/boot/dts/at91-sama5d2_xplained.dts   | 12 
 arch/arm/boot/dts/at91-sama5d3_xplained.dts   | 16 
 arch/arm/boot/dts/at91-sama5d4_xplained.dts   | 12 
 drivers/net/ethernet/cadence/macb_main.c  | 19 ---
 9 files changed, 86 insertions(+), 42 deletions(-)

-- 
2.25.1



[PATCH] ASoC: atmel-pdmic: remove codec component

2020-07-08 Thread Codrin Ciubotariu
The CPU and the codec both are represented now as components, so for
PDMIC we are registering two componenets with the same name. Since
there is no actual codec, we will merge the codec component into the
CPU one and use a dummy codec instead, for the DAI link.
As a bonus, debugfs will no longer report an error when will try to
create entries for both componenets with the same name.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/atmel-pdmic.c | 110 +-
 1 file changed, 41 insertions(+), 69 deletions(-)

diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c
index 5245826cd99d..c2b639928c69 100644
--- a/sound/soc/atmel/atmel-pdmic.c
+++ b/sound/soc/atmel/atmel-pdmic.c
@@ -147,32 +147,26 @@ static int atmel_pdmic_cpu_dai_prepare(struct 
snd_pcm_substream *substream,
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card);
+   struct snd_soc_component *component = cpu_dai->component;
u32 val;
+   int ret;
 
/* Clean the PDMIC Converted Data Register */
-   return regmap_read(dd->regmap, PDMIC_CDR, );
-}
-
-static const struct snd_soc_dai_ops atmel_pdmic_cpu_dai_ops = {
-   .startup= atmel_pdmic_cpu_dai_startup,
-   .shutdown   = atmel_pdmic_cpu_dai_shutdown,
-   .prepare= atmel_pdmic_cpu_dai_prepare,
-};
+   ret = regmap_read(dd->regmap, PDMIC_CDR, );
+   if (ret < 0)
+   return 0;
 
-#define ATMEL_PDMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
+   ret = snd_soc_component_update_bits(component, PDMIC_CR,
+   PDMIC_CR_ENPDM_MASK,
+   PDMIC_CR_ENPDM_DIS <<
+   PDMIC_CR_ENPDM_SHIFT);
+   if (ret < 0)
+   return ret;
 
-static struct snd_soc_dai_driver atmel_pdmic_cpu_dai = {
-   .capture = {
-   .channels_min   = 1,
-   .channels_max   = 1,
-   .rates  = SNDRV_PCM_RATE_KNOT,
-   .formats= ATMEL_PDMIC_FORMATS,},
-   .ops = _pdmic_cpu_dai_ops,
-};
+   return 0;
+}
 
-static const struct snd_soc_component_driver atmel_pdmic_cpu_dai_component = {
-   .name = "atmel-pdmic",
-};
+#define ATMEL_PDMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 /* platform */
 #define ATMEL_PDMIC_MAX_BUF_SIZE  (64 * 1024)
@@ -355,27 +349,16 @@ static int atmel_pdmic_component_probe(struct 
snd_soc_component *component)
return 0;
 }
 
-static struct snd_soc_component_driver soc_component_dev_pdmic = {
-   .probe  = atmel_pdmic_component_probe,
-   .controls   = atmel_pdmic_snd_controls,
-   .num_controls   = ARRAY_SIZE(atmel_pdmic_snd_controls),
-   .idle_bias_on   = 1,
-   .use_pmdown_time= 1,
-   .endianness = 1,
-   .non_legacy_dai_naming  = 1,
-};
-
-/* codec dai component */
 #define PDMIC_MR_PRESCAL_MAX_VAL 127
 
 static int
-atmel_pdmic_codec_dai_hw_params(struct snd_pcm_substream *substream,
-   struct snd_pcm_hw_params *params,
-   struct snd_soc_dai *codec_dai)
+atmel_pdmic_cpu_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *cpu_dai)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card);
-   struct snd_soc_component *component = codec_dai->component;
+   struct snd_soc_component *component = cpu_dai->component;
unsigned int rate_min = substream->runtime->hw.rate_min;
unsigned int rate_max = substream->runtime->hw.rate_max;
int fs = params_rate(params);
@@ -445,21 +428,10 @@ atmel_pdmic_codec_dai_hw_params(struct snd_pcm_substream 
*substream,
return 0;
 }
 
-static int atmel_pdmic_codec_dai_prepare(struct snd_pcm_substream *substream,
-   struct snd_soc_dai *codec_dai)
-{
-   struct snd_soc_component *component = codec_dai->component;
-
-   snd_soc_component_update_bits(component, PDMIC_CR, PDMIC_CR_ENPDM_MASK,
-   PDMIC_CR_ENPDM_DIS << PDMIC_CR_ENPDM_SHIFT);
-
-   return 0;
-}
-
-static int atmel_pdmic_codec_dai_trigger(struct snd_pcm_substream *substream,
-   int cmd, struct snd_soc_dai *codec_dai)
+static int atmel_pdmic_cpu_dai_trigger(struct snd_pcm_substream *substream,
+  int cmd, struct snd_soc_dai *cpu_dai)
 {
-   struct snd_soc_component *component = codec_dai->component;
+   struct snd_soc_component *component = cpu_dai->component

[PATCH v3] ASoC: atmel-classd: remove codec component

2020-07-08 Thread Codrin Ciubotariu
The CPU and the codec both are represented now as components, so for
CLASS-D we are registering two componenets with the same name. Since
there is no actual codec, we will merge the codec component into the
CPU one and use a dummy codec instead, for the DAI link.
As a bonus, debugfs will no longer report an error when will try to
create entries for both componenets with the same name.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v3:
 - fixed some newlines modified by no reason;

Changes in v2:
 - removed no longer used ATMEL_CLASSD_CODEC_DAI_NAME macro;

 sound/soc/atmel/atmel-classd.c | 132 -
 1 file changed, 47 insertions(+), 85 deletions(-)

diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
index e98601eccfa3..2d35b08f0565 100644
--- a/sound/soc/atmel/atmel-classd.c
+++ b/sound/soc/atmel/atmel-classd.c
@@ -120,39 +120,21 @@ static int atmel_classd_cpu_dai_startup(struct 
snd_pcm_substream *substream,
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
+   int err;
 
regmap_write(dd->regmap, CLASSD_THR, 0x0);
 
-   return clk_prepare_enable(dd->pclk);
-}
-
-static void atmel_classd_cpu_dai_shutdown(struct snd_pcm_substream *substream,
-   struct snd_soc_dai *cpu_dai)
-{
-   struct snd_soc_pcm_runtime *rtd = substream->private_data;
-   struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
-
-   clk_disable_unprepare(dd->pclk);
+   err = clk_prepare_enable(dd->pclk);
+   if (err)
+   return err;
+   err = clk_prepare_enable(dd->gclk);
+   if (err) {
+   clk_disable_unprepare(dd->pclk);
+   return err;
+   }
+   return 0;
 }
 
-static const struct snd_soc_dai_ops atmel_classd_cpu_dai_ops = {
-   .startup= atmel_classd_cpu_dai_startup,
-   .shutdown   = atmel_classd_cpu_dai_shutdown,
-};
-
-static struct snd_soc_dai_driver atmel_classd_cpu_dai = {
-   .playback = {
-   .channels_min   = 1,
-   .channels_max   = 2,
-   .rates  = ATMEL_CLASSD_RATES,
-   .formats= SNDRV_PCM_FMTBIT_S16_LE,},
-   .ops = _classd_cpu_dai_ops,
-};
-
-static const struct snd_soc_component_driver atmel_classd_cpu_dai_component = {
-   .name = "atmel-classd",
-};
-
 /* platform */
 static int
 atmel_classd_platform_configure_dma(struct snd_pcm_substream *substream,
@@ -306,31 +288,10 @@ static int atmel_classd_component_resume(struct 
snd_soc_component *component)
return regcache_sync(dd->regmap);
 }
 
-static struct snd_soc_component_driver soc_component_dev_classd = {
-   .probe  = atmel_classd_component_probe,
-   .resume = atmel_classd_component_resume,
-   .controls   = atmel_classd_snd_controls,
-   .num_controls   = ARRAY_SIZE(atmel_classd_snd_controls),
-   .idle_bias_on   = 1,
-   .use_pmdown_time= 1,
-   .endianness = 1,
-   .non_legacy_dai_naming  = 1,
-};
-
-/* codec dai component */
-static int atmel_classd_codec_dai_startup(struct snd_pcm_substream *substream,
-   struct snd_soc_dai *codec_dai)
-{
-   struct snd_soc_pcm_runtime *rtd = substream->private_data;
-   struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
-
-   return clk_prepare_enable(dd->gclk);
-}
-
-static int atmel_classd_codec_dai_digital_mute(struct snd_soc_dai *codec_dai,
-   int mute)
+static int atmel_classd_cpu_dai_digital_mute(struct snd_soc_dai *cpu_dai,
+int mute)
 {
-   struct snd_soc_component *component = codec_dai->component;
+   struct snd_soc_component *component = cpu_dai->component;
u32 mask, val;
 
mask = CLASSD_MR_LMUTE_MASK | CLASSD_MR_RMUTE_MASK;
@@ -373,13 +334,13 @@ static struct {
 };
 
 static int
-atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream,
-   struct snd_pcm_hw_params *params,
-   struct snd_soc_dai *codec_dai)
+atmel_classd_cpu_dai_hw_params(struct snd_pcm_substream *substream,
+  struct snd_pcm_hw_params *params,
+  struct snd_soc_dai *cpu_dai)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
-   struct snd_soc_component *component = codec_dai->component;
+   struct snd_soc_component *component = cpu_dai->component;
int fs;
int i, best, best_val, cur_val, ret;
u32 mask, val;
@@ -417,8 +378,8 @@ atmel_classd_codec_dai_hw_params(struct snd_pcm_substream 
*substream,
 }
 
 static voi

[PATCH v2] ASoC: atmel-classd: remove codec component

2020-07-08 Thread Codrin Ciubotariu
The CPU and the codec both are represented now as components, so for
CLASS-D we are registering two componenets with the same name. Since
there is no actual codec, we will merge the codec component into the
CPU one and use a dummy codec instead, for the DAI link.
As a bonus, debugfs will no longer report an error when will try to
create entries for both componenets with the same name.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - removed no longer used ATMEL_CLASSD_CODEC_DAI_NAME macro;

 sound/soc/atmel/atmel-classd.c | 134 -
 1 file changed, 48 insertions(+), 86 deletions(-)

diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
index e98601eccfa3..24bc93c468af 100644
--- a/sound/soc/atmel/atmel-classd.c
+++ b/sound/soc/atmel/atmel-classd.c
@@ -5,7 +5,6 @@
  *
  * Author: Songjun Wu 
  */
-
 #include 
 #include 
 #include 
@@ -120,39 +119,21 @@ static int atmel_classd_cpu_dai_startup(struct 
snd_pcm_substream *substream,
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
+   int err;
 
regmap_write(dd->regmap, CLASSD_THR, 0x0);
 
-   return clk_prepare_enable(dd->pclk);
-}
-
-static void atmel_classd_cpu_dai_shutdown(struct snd_pcm_substream *substream,
-   struct snd_soc_dai *cpu_dai)
-{
-   struct snd_soc_pcm_runtime *rtd = substream->private_data;
-   struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
-
-   clk_disable_unprepare(dd->pclk);
+   err = clk_prepare_enable(dd->pclk);
+   if (err)
+   return err;
+   err = clk_prepare_enable(dd->gclk);
+   if (err) {
+   clk_disable_unprepare(dd->pclk);
+   return err;
+   }
+   return 0;
 }
 
-static const struct snd_soc_dai_ops atmel_classd_cpu_dai_ops = {
-   .startup= atmel_classd_cpu_dai_startup,
-   .shutdown   = atmel_classd_cpu_dai_shutdown,
-};
-
-static struct snd_soc_dai_driver atmel_classd_cpu_dai = {
-   .playback = {
-   .channels_min   = 1,
-   .channels_max   = 2,
-   .rates  = ATMEL_CLASSD_RATES,
-   .formats= SNDRV_PCM_FMTBIT_S16_LE,},
-   .ops = _classd_cpu_dai_ops,
-};
-
-static const struct snd_soc_component_driver atmel_classd_cpu_dai_component = {
-   .name = "atmel-classd",
-};
-
 /* platform */
 static int
 atmel_classd_platform_configure_dma(struct snd_pcm_substream *substream,
@@ -306,31 +287,10 @@ static int atmel_classd_component_resume(struct 
snd_soc_component *component)
return regcache_sync(dd->regmap);
 }
 
-static struct snd_soc_component_driver soc_component_dev_classd = {
-   .probe  = atmel_classd_component_probe,
-   .resume = atmel_classd_component_resume,
-   .controls   = atmel_classd_snd_controls,
-   .num_controls   = ARRAY_SIZE(atmel_classd_snd_controls),
-   .idle_bias_on   = 1,
-   .use_pmdown_time= 1,
-   .endianness = 1,
-   .non_legacy_dai_naming  = 1,
-};
-
-/* codec dai component */
-static int atmel_classd_codec_dai_startup(struct snd_pcm_substream *substream,
-   struct snd_soc_dai *codec_dai)
-{
-   struct snd_soc_pcm_runtime *rtd = substream->private_data;
-   struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
-
-   return clk_prepare_enable(dd->gclk);
-}
-
-static int atmel_classd_codec_dai_digital_mute(struct snd_soc_dai *codec_dai,
-   int mute)
+static int atmel_classd_cpu_dai_digital_mute(struct snd_soc_dai *cpu_dai,
+int mute)
 {
-   struct snd_soc_component *component = codec_dai->component;
+   struct snd_soc_component *component = cpu_dai->component;
u32 mask, val;
 
mask = CLASSD_MR_LMUTE_MASK | CLASSD_MR_RMUTE_MASK;
@@ -373,13 +333,13 @@ static struct {
 };
 
 static int
-atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream,
-   struct snd_pcm_hw_params *params,
-   struct snd_soc_dai *codec_dai)
+atmel_classd_cpu_dai_hw_params(struct snd_pcm_substream *substream,
+  struct snd_pcm_hw_params *params,
+  struct snd_soc_dai *cpu_dai)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
-   struct snd_soc_component *component = codec_dai->component;
+   struct snd_soc_component *component = cpu_dai->component;
int fs;
int i, best, best_val, cur_val, ret;
u32 mask, val;
@@ -417,8 +377,8 @@ atmel_classd_codec_dai_hw_params(struct snd_pcm_substream 
*substream,
 }
 

[PATCH] ASoC: atmel-classd: remove codec component

2020-07-08 Thread Codrin Ciubotariu
The CPU and the codec both are represented now as components, so for
CLASS-D we are registering two componenets with the same name. Since
there is no actual codec, we will merge the codec component into the
CPU one and use a dummy codec instead, for the DAI link.
As a bonus, debugfs will no longer report an error when will try to
create entries for both componenets with the same name.

Signed-off-by: Codrin Ciubotariu 
---
 sound/soc/atmel/atmel-classd.c | 133 -
 1 file changed, 48 insertions(+), 85 deletions(-)

diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
index e98601eccfa3..d1ce67d30cd7 100644
--- a/sound/soc/atmel/atmel-classd.c
+++ b/sound/soc/atmel/atmel-classd.c
@@ -5,7 +5,6 @@
  *
  * Author: Songjun Wu 
  */
-
 #include 
 #include 
 #include 
@@ -120,39 +119,21 @@ static int atmel_classd_cpu_dai_startup(struct 
snd_pcm_substream *substream,
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
+   int err;
 
regmap_write(dd->regmap, CLASSD_THR, 0x0);
 
-   return clk_prepare_enable(dd->pclk);
-}
-
-static void atmel_classd_cpu_dai_shutdown(struct snd_pcm_substream *substream,
-   struct snd_soc_dai *cpu_dai)
-{
-   struct snd_soc_pcm_runtime *rtd = substream->private_data;
-   struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
-
-   clk_disable_unprepare(dd->pclk);
+   err = clk_prepare_enable(dd->pclk);
+   if (err)
+   return err;
+   err = clk_prepare_enable(dd->gclk);
+   if (err) {
+   clk_disable_unprepare(dd->pclk);
+   return err;
+   }
+   return 0;
 }
 
-static const struct snd_soc_dai_ops atmel_classd_cpu_dai_ops = {
-   .startup= atmel_classd_cpu_dai_startup,
-   .shutdown   = atmel_classd_cpu_dai_shutdown,
-};
-
-static struct snd_soc_dai_driver atmel_classd_cpu_dai = {
-   .playback = {
-   .channels_min   = 1,
-   .channels_max   = 2,
-   .rates  = ATMEL_CLASSD_RATES,
-   .formats= SNDRV_PCM_FMTBIT_S16_LE,},
-   .ops = _classd_cpu_dai_ops,
-};
-
-static const struct snd_soc_component_driver atmel_classd_cpu_dai_component = {
-   .name = "atmel-classd",
-};
-
 /* platform */
 static int
 atmel_classd_platform_configure_dma(struct snd_pcm_substream *substream,
@@ -306,31 +287,10 @@ static int atmel_classd_component_resume(struct 
snd_soc_component *component)
return regcache_sync(dd->regmap);
 }
 
-static struct snd_soc_component_driver soc_component_dev_classd = {
-   .probe  = atmel_classd_component_probe,
-   .resume = atmel_classd_component_resume,
-   .controls   = atmel_classd_snd_controls,
-   .num_controls   = ARRAY_SIZE(atmel_classd_snd_controls),
-   .idle_bias_on   = 1,
-   .use_pmdown_time= 1,
-   .endianness = 1,
-   .non_legacy_dai_naming  = 1,
-};
-
-/* codec dai component */
-static int atmel_classd_codec_dai_startup(struct snd_pcm_substream *substream,
-   struct snd_soc_dai *codec_dai)
-{
-   struct snd_soc_pcm_runtime *rtd = substream->private_data;
-   struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
-
-   return clk_prepare_enable(dd->gclk);
-}
-
-static int atmel_classd_codec_dai_digital_mute(struct snd_soc_dai *codec_dai,
-   int mute)
+static int atmel_classd_cpu_dai_digital_mute(struct snd_soc_dai *cpu_dai,
+int mute)
 {
-   struct snd_soc_component *component = codec_dai->component;
+   struct snd_soc_component *component = cpu_dai->component;
u32 mask, val;
 
mask = CLASSD_MR_LMUTE_MASK | CLASSD_MR_RMUTE_MASK;
@@ -373,13 +333,13 @@ static struct {
 };
 
 static int
-atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream,
-   struct snd_pcm_hw_params *params,
-   struct snd_soc_dai *codec_dai)
+atmel_classd_cpu_dai_hw_params(struct snd_pcm_substream *substream,
+  struct snd_pcm_hw_params *params,
+  struct snd_soc_dai *cpu_dai)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card);
-   struct snd_soc_component *component = codec_dai->component;
+   struct snd_soc_component *component = cpu_dai->component;
int fs;
int i, best, best_val, cur_val, ret;
u32 mask, val;
@@ -417,8 +377,8 @@ atmel_classd_codec_dai_hw_params(struct snd_pcm_substream 
*substream,
 }
 
 static void
-atmel_classd_codec_dai_shutdown(struct snd_pcm_substream

[PATCH net-next v2 2/2] net: dsa: microchip: remove unused private members

2020-07-02 Thread Codrin Ciubotariu
Private structure members live_ports, on_ports, rx_ports, tx_ports are
initialized but not used anywhere. Let's remove them.

Suggested-by: Russell King 
Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - new patch, there was no v1

 drivers/net/dsa/microchip/ksz8795.c| 18 --
 drivers/net/dsa/microchip/ksz9477.c| 23 ++
 drivers/net/dsa/microchip/ksz_common.c | 33 --
 drivers/net/dsa/microchip/ksz_common.h |  8 ---
 4 files changed, 2 insertions(+), 80 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
index 862306a9db2c..4202411627f1 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -731,15 +731,6 @@ static void ksz8795_port_stp_state_set(struct dsa_switch 
*ds, int port,
 
ksz_pwrite8(dev, port, P_STP_CTRL, data);
p->stp_state = state;
-   if (data & PORT_RX_ENABLE)
-   dev->rx_ports |= BIT(port);
-   else
-   dev->rx_ports &= ~BIT(port);
-   if (data & PORT_TX_ENABLE)
-   dev->tx_ports |= BIT(port);
-   else
-   dev->tx_ports &= ~BIT(port);
-
/* Port membership may share register with STP state. */
if (member >= 0 && member != p->member)
ksz8795_cfg_port_member(dev, port, (u8)member);
@@ -976,15 +967,8 @@ static void ksz8795_port_setup(struct ksz_device *dev, int 
port, bool cpu_port)
p->phydev.duplex = 1;
 
member = dev->port_mask;
-   dev->on_ports = dev->host_mask;
-   dev->live_ports = dev->host_mask;
} else {
member = dev->host_mask | p->vid_member;
-   dev->on_ports |= BIT(port);
-
-   /* Link was detected before port is enabled. */
-   if (p->phydev.link)
-   dev->live_ports |= BIT(port);
}
ksz8795_cfg_port_member(dev, port, member);
 }
@@ -1112,9 +1096,7 @@ static const struct dsa_switch_ops ksz8795_switch_ops = {
.phy_read   = ksz_phy_read16,
.phy_write  = ksz_phy_write16,
.phylink_mac_link_down  = ksz_mac_link_down,
-   .phylink_mac_link_up= ksz_mac_link_up,
.port_enable= ksz_enable_port,
-   .port_disable   = ksz_disable_port,
.get_strings= ksz8795_get_strings,
.get_ethtool_stats  = ksz_get_ethtool_stats,
.get_sset_count = ksz_sset_count,
diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 9e4bdd950194..b939e0b82aa0 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -452,15 +452,6 @@ static void ksz9477_port_stp_state_set(struct dsa_switch 
*ds, int port,
ksz_pwrite8(dev, port, P_STP_CTRL, data);
p->stp_state = state;
mutex_lock(>dev_mutex);
-   if (data & PORT_RX_ENABLE)
-   dev->rx_ports |= (1 << port);
-   else
-   dev->rx_ports &= ~(1 << port);
-   if (data & PORT_TX_ENABLE)
-   dev->tx_ports |= (1 << port);
-   else
-   dev->tx_ports &= ~(1 << port);
-
/* Port membership may share register with STP state. */
if (member >= 0 && member != p->member)
ksz9477_cfg_port_member(dev, port, (u8)member);
@@ -1268,18 +1259,10 @@ static void ksz9477_port_setup(struct ksz_device *dev, 
int port, bool cpu_port)
p->phydev.duplex = 1;
}
mutex_lock(>dev_mutex);
-   if (cpu_port) {
+   if (cpu_port)
member = dev->port_mask;
-   dev->on_ports = dev->host_mask;
-   dev->live_ports = dev->host_mask;
-   } else {
+   else
member = dev->host_mask | p->vid_member;
-   dev->on_ports |= (1 << port);
-
-   /* Link was detected before port is enabled. */
-   if (p->phydev.link)
-   dev->live_ports |= (1 << port);
-   }
mutex_unlock(>dev_mutex);
ksz9477_cfg_port_member(dev, port, member);
 
@@ -1400,9 +1383,7 @@ static const struct dsa_switch_ops ksz9477_switch_ops = {
.phy_read   = ksz9477_phy_read16,
.phy_write  = ksz9477_phy_write16,
.phylink_mac_link_down  = ksz_mac_link_down,
-   .phylink_mac_link_up= ksz_mac_link_up,
.port_enable= ksz_enable_port,
-   .port_disable   = ksz_disable_port,
.get_strings= ksz9477_get_strings,
.get_ethtool_stats  = ksz_get_ethtool_stats,
.get_sset_count = ksz_sset_count,
diff --git a/drivers/net/dsa/microchip/ksz_commo

[PATCH net-next v2 1/2] net: dsa: microchip: split adjust_link() in phylink_mac_link_{up|down}()

2020-07-02 Thread Codrin Ciubotariu
The DSA subsystem moved to phylink and adjust_link() became deprecated in
the process. This patch removes adjust_link from the KSZ DSA switches and
adds phylink_mac_link_up() and phylink_mac_link_down().

Signed-off-by: Codrin Ciubotariu 
Reviewed-by: Russell King 
---

Changes in v2:
 - added reviewed-by tag;

 drivers/net/dsa/microchip/ksz8795.c|  3 ++-
 drivers/net/dsa/microchip/ksz9477.c|  3 ++-
 drivers/net/dsa/microchip/ksz_common.c | 32 --
 drivers/net/dsa/microchip/ksz_common.h |  7 --
 4 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
index 47d65b77caf7..862306a9db2c 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -,7 +,8 @@ static const struct dsa_switch_ops ksz8795_switch_ops = {
.setup  = ksz8795_setup,
.phy_read   = ksz_phy_read16,
.phy_write  = ksz_phy_write16,
-   .adjust_link= ksz_adjust_link,
+   .phylink_mac_link_down  = ksz_mac_link_down,
+   .phylink_mac_link_up= ksz_mac_link_up,
.port_enable= ksz_enable_port,
.port_disable   = ksz_disable_port,
.get_strings= ksz8795_get_strings,
diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 9a51b8a4de5d..9e4bdd950194 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1399,7 +1399,8 @@ static const struct dsa_switch_ops ksz9477_switch_ops = {
.setup  = ksz9477_setup,
.phy_read   = ksz9477_phy_read16,
.phy_write  = ksz9477_phy_write16,
-   .adjust_link= ksz_adjust_link,
+   .phylink_mac_link_down  = ksz_mac_link_down,
+   .phylink_mac_link_up= ksz_mac_link_up,
.port_enable= ksz_enable_port,
.port_disable   = ksz_disable_port,
.get_strings= ksz9477_get_strings,
diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index fd1d6676ae4f..55ceaf00ece1 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -135,26 +135,34 @@ int ksz_phy_write16(struct dsa_switch *ds, int addr, int 
reg, u16 val)
 }
 EXPORT_SYMBOL_GPL(ksz_phy_write16);
 
-void ksz_adjust_link(struct dsa_switch *ds, int port,
-struct phy_device *phydev)
+void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
+  phy_interface_t interface)
 {
struct ksz_device *dev = ds->priv;
struct ksz_port *p = >ports[port];
 
/* Read all MIB counters when the link is going down. */
-   if (!phydev->link) {
-   p->read = true;
-   schedule_delayed_work(>mib_read, 0);
-   }
+   p->read = true;
+   schedule_delayed_work(>mib_read, 0);
+
+   mutex_lock(>dev_mutex);
+   dev->live_ports &= ~(1 << port);
+   mutex_unlock(>dev_mutex);
+}
+EXPORT_SYMBOL_GPL(ksz_mac_link_down);
+
+void ksz_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
+phy_interface_t interface, struct phy_device *phydev,
+int speed, int duplex, bool tx_pause, bool rx_pause)
+{
+   struct ksz_device *dev = ds->priv;
+
+   /* Remember which port is connected and active. */
mutex_lock(>dev_mutex);
-   if (!phydev->link)
-   dev->live_ports &= ~(1 << port);
-   else
-   /* Remember which port is connected and active. */
-   dev->live_ports |= (1 << port) & dev->on_ports;
+   dev->live_ports |= (1 << port) & dev->on_ports;
mutex_unlock(>dev_mutex);
 }
-EXPORT_SYMBOL_GPL(ksz_adjust_link);
+EXPORT_SYMBOL_GPL(ksz_mac_link_up);
 
 int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
 {
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index f2c9bb68fd33..c0224dd0cf8a 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -159,8 +159,11 @@ void ksz_init_mib_timer(struct ksz_device *dev);
 
 int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
 int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
-void ksz_adjust_link(struct dsa_switch *ds, int port,
-struct phy_device *phydev);
+void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
+  phy_interface_t interface);
+void ksz_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
+phy_interface_t interface, struct phy_device *phydev,
+int speed, int duplex, bool tx_pause, bool rx_pa

[PATCH net-next] net: dsa: microchip: split adjust_link() in phylink_mac_link_{up|down}()

2020-07-02 Thread Codrin Ciubotariu
The DSA subsystem moved to phylink and adjust_link() became deprecated in
the process. This patch removes adjust_link from the KSZ DSA switches and
adds phylink_mac_link_up() and phylink_mac_link_down().

Signed-off-by: Codrin Ciubotariu 
---
 drivers/net/dsa/microchip/ksz8795.c|  3 ++-
 drivers/net/dsa/microchip/ksz9477.c|  3 ++-
 drivers/net/dsa/microchip/ksz_common.c | 32 --
 drivers/net/dsa/microchip/ksz_common.h |  7 --
 4 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
index 47d65b77caf7..862306a9db2c 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -,7 +,8 @@ static const struct dsa_switch_ops ksz8795_switch_ops = {
.setup  = ksz8795_setup,
.phy_read   = ksz_phy_read16,
.phy_write  = ksz_phy_write16,
-   .adjust_link= ksz_adjust_link,
+   .phylink_mac_link_down  = ksz_mac_link_down,
+   .phylink_mac_link_up= ksz_mac_link_up,
.port_enable= ksz_enable_port,
.port_disable   = ksz_disable_port,
.get_strings= ksz8795_get_strings,
diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 9a51b8a4de5d..9e4bdd950194 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1399,7 +1399,8 @@ static const struct dsa_switch_ops ksz9477_switch_ops = {
.setup  = ksz9477_setup,
.phy_read   = ksz9477_phy_read16,
.phy_write  = ksz9477_phy_write16,
-   .adjust_link= ksz_adjust_link,
+   .phylink_mac_link_down  = ksz_mac_link_down,
+   .phylink_mac_link_up= ksz_mac_link_up,
.port_enable= ksz_enable_port,
.port_disable   = ksz_disable_port,
.get_strings= ksz9477_get_strings,
diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index fd1d6676ae4f..55ceaf00ece1 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -135,26 +135,34 @@ int ksz_phy_write16(struct dsa_switch *ds, int addr, int 
reg, u16 val)
 }
 EXPORT_SYMBOL_GPL(ksz_phy_write16);
 
-void ksz_adjust_link(struct dsa_switch *ds, int port,
-struct phy_device *phydev)
+void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
+  phy_interface_t interface)
 {
struct ksz_device *dev = ds->priv;
struct ksz_port *p = >ports[port];
 
/* Read all MIB counters when the link is going down. */
-   if (!phydev->link) {
-   p->read = true;
-   schedule_delayed_work(>mib_read, 0);
-   }
+   p->read = true;
+   schedule_delayed_work(>mib_read, 0);
+
+   mutex_lock(>dev_mutex);
+   dev->live_ports &= ~(1 << port);
+   mutex_unlock(>dev_mutex);
+}
+EXPORT_SYMBOL_GPL(ksz_mac_link_down);
+
+void ksz_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
+phy_interface_t interface, struct phy_device *phydev,
+int speed, int duplex, bool tx_pause, bool rx_pause)
+{
+   struct ksz_device *dev = ds->priv;
+
+   /* Remember which port is connected and active. */
mutex_lock(>dev_mutex);
-   if (!phydev->link)
-   dev->live_ports &= ~(1 << port);
-   else
-   /* Remember which port is connected and active. */
-   dev->live_ports |= (1 << port) & dev->on_ports;
+   dev->live_ports |= (1 << port) & dev->on_ports;
mutex_unlock(>dev_mutex);
 }
-EXPORT_SYMBOL_GPL(ksz_adjust_link);
+EXPORT_SYMBOL_GPL(ksz_mac_link_up);
 
 int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
 {
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index f2c9bb68fd33..c0224dd0cf8a 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -159,8 +159,11 @@ void ksz_init_mib_timer(struct ksz_device *dev);
 
 int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
 int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
-void ksz_adjust_link(struct dsa_switch *ds, int port,
-struct phy_device *phydev);
+void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
+  phy_interface_t interface);
+void ksz_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
+phy_interface_t interface, struct phy_device *phydev,
+int speed, int duplex, bool tx_pause, bool rx_pause);
 int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
 void

[PATCH net] net: dsa: microchip: set the correct number of ports

2020-07-02 Thread Codrin Ciubotariu
The number of ports is incorrectly set to the maximum available for a DSA
switch. Even if the extra ports are not used, this causes some functions
to be called later, like port_disable() and port_stp_state_set(). If the
driver doesn't check the port index, it will end up modifying unknown
registers.

Fixes: b987e98e50ab ("dsa: add DSA switch driver for Microchip KSZ9477")
Signed-off-by: Codrin Ciubotariu 
---
 drivers/net/dsa/microchip/ksz8795.c | 3 +++
 drivers/net/dsa/microchip/ksz9477.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
index 47d65b77caf7..7c17b0f705ec 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -1268,6 +1268,9 @@ static int ksz8795_switch_init(struct ksz_device *dev)
return -ENOMEM;
}
 
+   /* set the real number of ports */
+   dev->ds->num_ports = dev->port_cnt;
+
return 0;
 }
 
diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 9a51b8a4de5d..8d15c3016024 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1588,6 +1588,9 @@ static int ksz9477_switch_init(struct ksz_device *dev)
return -ENOMEM;
}
 
+   /* set the real number of ports */
+   dev->ds->num_ports = dev->port_cnt;
+
return 0;
 }
 
-- 
2.25.1



[PATCH 1/2] net: dsa: microchip: set the correct number of ports in dsa_switch

2020-07-01 Thread Codrin Ciubotariu
The number of ports is incorrectly set to the maximum available for a DSA
switch. Even if the extra ports are not used, this causes some functions
to be called later, like port_disable() and port_stp_state_set(). If the
driver doesn't check the port index, it will end up modifying unknown
registers.

Fixes: b987e98e50ab ("dsa: add DSA switch driver for Microchip KSZ9477")
Signed-off-by: Codrin Ciubotariu 
---
 drivers/net/dsa/microchip/ksz8795.c|  7 +--
 drivers/net/dsa/microchip/ksz9477.c|  7 +--
 drivers/net/dsa/microchip/ksz_common.c | 26 --
 drivers/net/dsa/microchip/ksz_common.h |  1 +
 4 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
index 47d65b77caf7..b0227b0e31e6 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -1225,8 +1225,6 @@ static int ksz8795_switch_init(struct ksz_device *dev)
 {
int i;
 
-   dev->ds->ops = _switch_ops;
-
for (i = 0; i < ARRAY_SIZE(ksz8795_switch_chips); i++) {
const struct ksz_chip_data *chip = _switch_chips[i];
 
@@ -1268,6 +1266,11 @@ static int ksz8795_switch_init(struct ksz_device *dev)
return -ENOMEM;
}
 
+   dev->ds = ksz_dsa_switch_alloc(dev);
+   if (!dev->ds)
+   return -ENOMEM;
+   dev->ds->ops = _switch_ops;
+
return 0;
 }
 
diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 9a51b8a4de5d..833cf3763000 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1545,8 +1545,6 @@ static int ksz9477_switch_init(struct ksz_device *dev)
 {
int i;
 
-   dev->ds->ops = _switch_ops;
-
for (i = 0; i < ARRAY_SIZE(ksz9477_switch_chips); i++) {
const struct ksz_chip_data *chip = _switch_chips[i];
 
@@ -1588,6 +1586,11 @@ static int ksz9477_switch_init(struct ksz_device *dev)
return -ENOMEM;
}
 
+   dev->ds = ksz_dsa_switch_alloc(dev);
+   if (!dev->ds)
+   return -ENOMEM;
+   dev->ds->ops = _switch_ops;
+
return 0;
 }
 
diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index fd1d6676ae4f..4a41f0c7dbbc 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -387,30 +387,36 @@ EXPORT_SYMBOL_GPL(ksz_disable_port);
 
 struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
 {
-   struct dsa_switch *ds;
struct ksz_device *swdev;
 
-   ds = devm_kzalloc(base, sizeof(*ds), GFP_KERNEL);
-   if (!ds)
-   return NULL;
-
-   ds->dev = base;
-   ds->num_ports = DSA_MAX_PORTS;
-
swdev = devm_kzalloc(base, sizeof(*swdev), GFP_KERNEL);
if (!swdev)
return NULL;
 
-   ds->priv = swdev;
swdev->dev = base;
 
-   swdev->ds = ds;
swdev->priv = priv;
 
return swdev;
 }
 EXPORT_SYMBOL(ksz_switch_alloc);
 
+struct dsa_switch *ksz_dsa_switch_alloc(struct ksz_device *swdev)
+{
+   struct dsa_switch *ds;
+
+   ds = devm_kzalloc(swdev->dev, sizeof(*ds), GFP_KERNEL);
+   if (!ds)
+   return NULL;
+
+   ds->dev = swdev->dev;
+   ds->num_ports = swdev->port_cnt;
+   ds->priv = swdev;
+
+   return ds;
+}
+EXPORT_SYMBOL(ksz_dsa_switch_alloc);
+
 int ksz_switch_register(struct ksz_device *dev,
const struct ksz_dev_ops *ops)
 {
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index f2c9bb68fd33..785702514a46 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -145,6 +145,7 @@ struct ksz_dev_ops {
 };
 
 struct ksz_device *ksz_switch_alloc(struct device *base, void *priv);
+struct dsa_switch *ksz_dsa_switch_alloc(struct ksz_device *swdev);
 int ksz_switch_register(struct ksz_device *dev,
const struct ksz_dev_ops *ops);
 void ksz_switch_remove(struct ksz_device *dev);
-- 
2.25.1



[PATCH 2/2] net: dsa: microchip: split adjust_link() in phylink_mac_link_{up|down}()

2020-07-01 Thread Codrin Ciubotariu
The DSA subsystem moved to phylink and adjust_link() became deprecated in
the process. This patch removes adjust_link from the KSZ DSA switches and
adds phylink_mac_link_up() and phylink_mac_link_down().

Signed-off-by: Codrin Ciubotariu 
---
 drivers/net/dsa/microchip/ksz8795.c|  3 ++-
 drivers/net/dsa/microchip/ksz9477.c|  3 ++-
 drivers/net/dsa/microchip/ksz_common.c | 32 --
 drivers/net/dsa/microchip/ksz_common.h |  7 --
 4 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
index b0227b0e31e6..d07231d1def5 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -,7 +,8 @@ static const struct dsa_switch_ops ksz8795_switch_ops = {
.setup  = ksz8795_setup,
.phy_read   = ksz_phy_read16,
.phy_write  = ksz_phy_write16,
-   .adjust_link= ksz_adjust_link,
+   .phylink_mac_link_down  = ksz_mac_link_down,
+   .phylink_mac_link_up= ksz_mac_link_up,
.port_enable= ksz_enable_port,
.port_disable   = ksz_disable_port,
.get_strings= ksz8795_get_strings,
diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 833cf3763000..162f2bd84774 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1399,7 +1399,8 @@ static const struct dsa_switch_ops ksz9477_switch_ops = {
.setup  = ksz9477_setup,
.phy_read   = ksz9477_phy_read16,
.phy_write  = ksz9477_phy_write16,
-   .adjust_link= ksz_adjust_link,
+   .phylink_mac_link_down  = ksz_mac_link_down,
+   .phylink_mac_link_up= ksz_mac_link_up,
.port_enable= ksz_enable_port,
.port_disable   = ksz_disable_port,
.get_strings= ksz9477_get_strings,
diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index 4a41f0c7dbbc..a35d6ba8dd8a 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -135,26 +135,34 @@ int ksz_phy_write16(struct dsa_switch *ds, int addr, int 
reg, u16 val)
 }
 EXPORT_SYMBOL_GPL(ksz_phy_write16);
 
-void ksz_adjust_link(struct dsa_switch *ds, int port,
-struct phy_device *phydev)
+void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
+  phy_interface_t interface)
 {
struct ksz_device *dev = ds->priv;
struct ksz_port *p = >ports[port];
 
/* Read all MIB counters when the link is going down. */
-   if (!phydev->link) {
-   p->read = true;
-   schedule_delayed_work(>mib_read, 0);
-   }
+   p->read = true;
+   schedule_delayed_work(>mib_read, 0);
+
+   mutex_lock(>dev_mutex);
+   dev->live_ports &= ~(1 << port);
+   mutex_unlock(>dev_mutex);
+}
+EXPORT_SYMBOL_GPL(ksz_mac_link_down);
+
+void ksz_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
+phy_interface_t interface, struct phy_device *phydev,
+int speed, int duplex, bool tx_pause, bool rx_pause)
+{
+   struct ksz_device *dev = ds->priv;
+
+   /* Remember which port is connected and active. */
mutex_lock(>dev_mutex);
-   if (!phydev->link)
-   dev->live_ports &= ~(1 << port);
-   else
-   /* Remember which port is connected and active. */
-   dev->live_ports |= (1 << port) & dev->on_ports;
+   dev->live_ports |= (1 << port) & dev->on_ports;
mutex_unlock(>dev_mutex);
 }
-EXPORT_SYMBOL_GPL(ksz_adjust_link);
+EXPORT_SYMBOL_GPL(ksz_mac_link_up);
 
 int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
 {
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index 785702514a46..b1c468713609 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -160,8 +160,11 @@ void ksz_init_mib_timer(struct ksz_device *dev);
 
 int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
 int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
-void ksz_adjust_link(struct dsa_switch *ds, int port,
-struct phy_device *phydev);
+void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
+  phy_interface_t interface);
+void ksz_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
+phy_interface_t interface, struct phy_device *phydev,
+int speed, int duplex, bool tx_pause, bool rx_pause);
 int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
 void

[RFC PATCH 3/4] i2c: core: treat EPROBE_DEFER when acquiring SCL/SDA GPIOs

2020-06-19 Thread Codrin Ciubotariu
Even if I2C bus GPIO recovery is optional, devm_gpiod_get() can return
-EPROBE_DEFER, so we should at least treat that. This ends up with
i2c_register_adapter() to be able to return -EPROBE_DEFER.

Signed-off-by: Codrin Ciubotariu 
---
 drivers/i2c/i2c-core-base.c | 22 --
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 4ee29fec4e93..f8d9f2048ca8 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -368,15 +368,16 @@ static int i2c_gpio_init_recovery(struct i2c_adapter 
*adap)
return i2c_gpio_init_generic_recovery(adap);
 }
 
-static void i2c_init_recovery(struct i2c_adapter *adap)
+static int i2c_init_recovery(struct i2c_adapter *adap)
 {
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
char *err_str;
 
if (!bri)
-   return;
+   return 0;
 
-   i2c_gpio_init_recovery(adap);
+   if (i2c_gpio_init_recovery(adap) == -EPROBE_DEFER)
+   return -EPROBE_DEFER;
 
if (!bri->recover_bus) {
err_str = "no recover_bus() found";
@@ -392,7 +393,7 @@ static void i2c_init_recovery(struct i2c_adapter *adap)
if (gpiod_get_direction(bri->sda_gpiod) == 0)
bri->set_sda = set_sda_gpio_value;
}
-   return;
+   return 0;
}
 
if (bri->recover_bus == i2c_generic_scl_recovery) {
@@ -407,10 +408,12 @@ static void i2c_init_recovery(struct i2c_adapter *adap)
}
}
 
-   return;
+   return 0;
  err:
dev_err(>dev, "Not using recovery: %s\n", err_str);
adap->bus_recovery_info = NULL;
+
+   return 0;
 }
 
 static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client)
@@ -1476,7 +1479,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 "Failed to create compatibility class link\n");
 #endif
 
-   i2c_init_recovery(adap);
+   res = i2c_init_recovery(adap);
+   if (res == -EPROBE_DEFER)
+   goto out_link;
 
/* create pre-declared device nodes */
of_i2c_register_devices(adap);
@@ -1493,6 +1498,11 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 
return 0;
 
+out_link:
+#ifdef CONFIG_I2C_COMPAT
+   class_compat_remove_link(i2c_adapter_compat_class, >dev,
+adap->dev.parent);
+#endif
 out_reg:
init_completion(>dev_released);
device_unregister(>dev);
-- 
2.25.1



[RFC PATCH 4/4] i2c: at91: Move to generic GPIO bus recovery

2020-06-19 Thread Codrin Ciubotariu
Make the Microchip at91 driver the first to use the generic GPIO bus
recovery support from the I2C core and discard the driver implementation.

Signed-off-by: Codrin Ciubotariu 
---
 drivers/i2c/busses/i2c-at91-master.c | 69 ++--
 drivers/i2c/busses/i2c-at91.h|  3 --
 2 files changed, 3 insertions(+), 69 deletions(-)

diff --git a/drivers/i2c/busses/i2c-at91-master.c 
b/drivers/i2c/busses/i2c-at91-master.c
index 363d540a8345..66864f9cf7ac 100644
--- a/drivers/i2c/busses/i2c-at91-master.c
+++ b/drivers/i2c/busses/i2c-at91-master.c
@@ -816,79 +816,16 @@ static int at91_twi_configure_dma(struct at91_twi_dev 
*dev, u32 phy_addr)
return ret;
 }
 
-static void at91_prepare_twi_recovery(struct i2c_adapter *adap)
-{
-   struct at91_twi_dev *dev = i2c_get_adapdata(adap);
-
-   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_gpio);
-}
-
-static void at91_unprepare_twi_recovery(struct i2c_adapter *adap)
-{
-   struct at91_twi_dev *dev = i2c_get_adapdata(adap);
-
-   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
-}
-
 static int at91_init_twi_recovery_gpio(struct platform_device *pdev,
   struct at91_twi_dev *dev)
 {
struct i2c_bus_recovery_info *rinfo = >rinfo;
 
-   dev->pinctrl = devm_pinctrl_get(>dev);
-   if (!dev->pinctrl || IS_ERR(dev->pinctrl)) {
+   rinfo->pinctrl = devm_pinctrl_get(>dev);
+   if (!rinfo->pinctrl || IS_ERR(rinfo->pinctrl)) {
dev_info(dev->dev, "can't get pinctrl, bus recovery not 
supported\n");
-   return PTR_ERR(dev->pinctrl);
+   return PTR_ERR(rinfo->pinctrl);
}
-
-   dev->pinctrl_pins_default = pinctrl_lookup_state(dev->pinctrl,
-PINCTRL_STATE_DEFAULT);
-   dev->pinctrl_pins_gpio = pinctrl_lookup_state(dev->pinctrl,
- "gpio");
-   if (IS_ERR(dev->pinctrl_pins_default) ||
-   IS_ERR(dev->pinctrl_pins_gpio)) {
-   dev_info(>dev, "pinctrl states incomplete for 
recovery\n");
-   return -EINVAL;
-   }
-
-   /*
-* pins will be taken as GPIO, so we might as well inform pinctrl about
-* this and move the state to GPIO
-*/
-   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_gpio);
-
-   rinfo->sda_gpiod = devm_gpiod_get(>dev, "sda", GPIOD_IN);
-   if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER)
-   return -EPROBE_DEFER;
-
-   rinfo->scl_gpiod = devm_gpiod_get(>dev, "scl",
- GPIOD_OUT_HIGH_OPEN_DRAIN);
-   if (PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER)
-   return -EPROBE_DEFER;
-
-   if (IS_ERR(rinfo->sda_gpiod) ||
-   IS_ERR(rinfo->scl_gpiod)) {
-   dev_info(>dev, "recovery information incomplete\n");
-   if (!IS_ERR(rinfo->sda_gpiod)) {
-   gpiod_put(rinfo->sda_gpiod);
-   rinfo->sda_gpiod = NULL;
-   }
-   if (!IS_ERR(rinfo->scl_gpiod)) {
-   gpiod_put(rinfo->scl_gpiod);
-   rinfo->scl_gpiod = NULL;
-   }
-   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
-   return -EINVAL;
-   }
-
-   /* change the state of the pins back to their default state */
-   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
-
-   dev_info(>dev, "using scl, sda for recovery\n");
-
-   rinfo->prepare_recovery = at91_prepare_twi_recovery;
-   rinfo->unprepare_recovery = at91_unprepare_twi_recovery;
-   rinfo->recover_bus = i2c_generic_scl_recovery;
dev->adapter.bus_recovery_info = rinfo;
 
return 0;
diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h
index 7e7b4955ca7f..eae673ae786c 100644
--- a/drivers/i2c/busses/i2c-at91.h
+++ b/drivers/i2c/busses/i2c-at91.h
@@ -157,9 +157,6 @@ struct at91_twi_dev {
struct at91_twi_dma dma;
bool slave_detected;
struct i2c_bus_recovery_info rinfo;
-   struct pinctrl *pinctrl;
-   struct pinctrl_state *pinctrl_pins_default;
-   struct pinctrl_state *pinctrl_pins_gpio;
 #ifdef CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL
unsigned smr;
struct i2c_client *slave;
-- 
2.25.1



[RFC PATCH 2/4] i2c: core: add generic I2C GPIO recovery

2020-06-19 Thread Codrin Ciubotariu
Multiple I2C bus drivers use similar bindings to obtain information needed
for I2C recovery. For example, for platforms using device-tree, the
properties look something like this:

 {
...
pinctrl-names = "default", "gpio";
// or pinctrl-names = "default", "recovery";
pinctrl-0 = <_i2c_default>;
pinctrl-1 = <_i2c_gpio>;
sda-gpios = < 0 GPIO_ACTIVE_HIGH>;
scl-gpios = < 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
...
}

For this reason, we can add this common initialization in the core. This
way, other I2C bus drivers will be able to support GPIO recovery just by
providing a pointer to platform's pinctrl and calling i2c_recover_bus()
when SDA is stuck low.

Signed-off-by: Codrin Ciubotariu 
---
 drivers/i2c/i2c-core-base.c | 119 
 include/linux/i2c.h |  11 
 2 files changed, 130 insertions(+)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index d1f278f73011..4ee29fec4e93 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -179,6 +180,8 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
int i = 0, scl = 1, ret = 0;
 
+   if (bri->pinctrl)
+   pinctrl_select_state(bri->pinctrl, bri->pins_gpio);
if (bri->prepare_recovery)
bri->prepare_recovery(adap);
 
@@ -236,6 +239,8 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
 
if (bri->unprepare_recovery)
bri->unprepare_recovery(adap);
+   if (bri->pinctrl)
+   pinctrl_select_state(bri->pinctrl, bri->pins_default);
 
return ret;
 }
@@ -251,6 +256,118 @@ int i2c_recover_bus(struct i2c_adapter *adap)
 }
 EXPORT_SYMBOL_GPL(i2c_recover_bus);
 
+static void i2c_gpio_init_pinctrl_recovery(struct i2c_adapter *adap)
+{
+   struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+   struct device *dev = >dev;
+   struct pinctrl *p = bri->pinctrl;
+
+   /*
+* we can't change states without pinctrl, so remove the states if
+* available
+*/
+   if (!p) {
+   bri->pins_default = NULL;
+   bri->pins_gpio = NULL;
+   return;
+   }
+
+   if (!bri->pins_default) {
+   bri->pins_default = pinctrl_lookup_state(p,
+PINCTRL_STATE_DEFAULT);
+   if (IS_ERR(bri->pins_default)) {
+   dev_dbg(dev, PINCTRL_STATE_DEFAULT " state not found 
for GPIO recovery\n");
+   bri->pins_default = NULL;
+
+   goto cleanup_pinctrl;
+   }
+   }
+   if (!bri->pins_gpio) {
+   bri->pins_gpio = pinctrl_lookup_state(p, "gpio");
+   if (IS_ERR(bri->pins_gpio))
+   bri->pins_gpio = pinctrl_lookup_state(p, "recovery");
+
+   if (IS_ERR(bri->pins_gpio)) {
+   dev_dbg(dev, "no gpio or recovery state found for GPIO 
recovery\n");
+   bri->pins_gpio = NULL;
+
+   goto cleanup_pinctrl;
+   }
+   }
+
+cleanup_pinctrl:
+   /* for pinctrl state changes, we need all the information */
+   if (!bri->pins_default || !bri->pins_gpio) {
+   bri->pinctrl = NULL;
+   bri->pins_default = NULL;
+   bri->pins_gpio = NULL;
+   } else {
+   dev_info(dev, "using pinctrl states for GPIO recovery");
+   }
+}
+
+static int i2c_gpio_init_generic_recovery(struct i2c_adapter *adap)
+{
+   struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+   struct device *dev = >dev;
+   struct gpio_desc *gpiod;
+   int ret = 0;
+
+   /* don't touch the recovery information if the driver is not using
+* generic SCL recovery
+*/
+   if (bri->recover_bus && bri->recover_bus != i2c_generic_scl_recovery)
+   return 0;
+
+   /*
+* pins might be taken as GPIO, so we might as well inform pinctrl about
+* this and move the state to GPIO
+*/
+   if (bri->pinctrl)
+   pinctrl_select_state(bri->pinctrl, bri->pins_gpio);
+
+   /*
+* if there is incomplete or no recovery information, see if generic
+* GPIO recovery is available
+*/
+   if (!bri->scl_gpiod) {
+   gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
+   if (PTR_ERR(gpiod) == -EPROBE_DEFER) {
+   

[RFC PATCH 1/4] dt-binding: i2c: add generic properties for GPIO bus recovery

2020-06-19 Thread Codrin Ciubotariu
The I2C GPIO bus recovery properties consist of two GPIOS and one extra
pinctrl state ("gpio" or "recovery"). Not all are mandatory for recovery.

Signed-off-by: Codrin Ciubotariu 
---
 Documentation/devicetree/bindings/i2c/i2c.txt | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c.txt 
b/Documentation/devicetree/bindings/i2c/i2c.txt
index 438ae123107e..6a644a24fc1c 100644
--- a/Documentation/devicetree/bindings/i2c/i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c.txt
@@ -77,6 +77,16 @@ wants to support one of the below features, it should adapt 
these bindings.
this information to detect a stalled bus more reliably, for example.
Can not be combined with 'multi-master'.
 
+- scl-gpios
+   specify the gpio related to SCL pin. Used for GPIO bus recovery.
+
+- sda-gpios
+   specify the gpio related to SDA pin. Optional for GPIO bus recovery.
+
+- pinctrl
+   add extra pinctrl to configure SCL/SDA pins to GPIO function for bus
+   recovery, call it "gpio" or "recovery" state
+
 Required properties (per child device)
 --
 
-- 
2.25.1



[RFC PATCH 0/4] i2c: core: add generic GPIO bus recovery

2020-06-19 Thread Codrin Ciubotariu
GPIO recovery has been added already for some I2C bus drivers, such as
imx, pxa and at91. These drivers use similar bindings and have more or
less the same code for recovery. For this reason, we aim to move the
GPIO bus recovery implementation to the I2C core so that other drivers
can benefit from it, with small modifications.
This implementation initializes the pinctrl states and the SDA/SCL
GPIOs based on common bindings. The I2C bus drivers can still use
different bindings or other particular recovery steps if needed.
The ugly part with this patch series is the handle of PROBE_DEFER
which could be returned by devm_gpiod_get(). This changes things a
little for i2c_register_adapter() and for this reason this step is
implemented in a sperate patch.
The at91 Microchip driver is the first to use this implementation,
with an AI to move the rest of the drivers in the following steps.

Codrin Ciubotariu (4):
  dt-binding: i2c: add generic properties for GPIO bus recovery
  i2c: core: add generic I2C GPIO recovery
  i2c: core: treat EPROBE_DEFER when acquiring SCL/SDA GPIOs
  i2c: at91: Move to generic GPIO bus recovery

 Documentation/devicetree/bindings/i2c/i2c.txt |  10 ++
 drivers/i2c/busses/i2c-at91-master.c  |  69 +
 drivers/i2c/i2c-core-base.c   | 139 +-
 include/linux/i2c.h   |  11 ++
 4 files changed, 158 insertions(+), 71 deletions(-)

-- 
2.25.1



[PATCH] ARM: configs: at91: sama5: Enable CLASSD

2020-06-18 Thread Codrin Ciubotariu
CLASSD is present on SAMA5d2 SoCs.

Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/configs/sama5_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index 8e1f78c19920..f688443fe7bf 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -165,6 +165,7 @@ CONFIG_SND_SOC=y
 CONFIG_SND_ATMEL_SOC=y
 CONFIG_SND_ATMEL_SOC_WM8904=y
 # CONFIG_HID_GENERIC is not set
+CONFIG_SND_ATMEL_SOC_CLASSD=y
 CONFIG_SND_ATMEL_SOC_PDMIC=y
 CONFIG_SND_ATMEL_SOC_TSE850_PCM5142=m
 CONFIG_SND_ATMEL_SOC_I2S=y
-- 
2.25.1



[PATCH v2] ARM: dts: at91: sama5d2_xplained: Remove pdmic node

2020-06-18 Thread Codrin Ciubotariu
The PDMIC needs PDM microphones to work. sama5d2 xplained doesn't have
such microphones, so there is no reason to enable PDMIC and take the
pins since there is no-one using them.

Signed-off-by: Codrin Ciubotariu 
---

Changes in v2:
 - rebased on top of at91-dt;
 - added more details in the commit description;
 - changed subject from:
  "[PATCH 3/3] Revert "ARM: at91/dt: sama5d2 Xplained: add pdmic node""
to
  "[PATCH v2] ARM: dts: at91: sama5d2_xplained: Remove pdmic node"


 arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 
 1 file changed, 16 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 0e17df568d0b..058fae1b4a76 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -168,16 +168,6 @@ timer1: timer@1 {
};
};
 
-   pdmic@f8018000 {
-   pinctrl-names = "default";
-   pinctrl-0 = <_pdmic_default>;
-   atmel,model = "PDMIC @ sama5d2_xplained";
-   atmel,mic-min-freq = <100>;
-   atmel,mic-max-freq = <3246000>;
-   atmel,mic-offset = <0x0>;
-   status = "okay";
-   };
-
uart1: serial@f802 {
pinctrl-names = "default";
pinctrl-0 = <_uart1_default>;
@@ -599,12 +589,6 @@ pinctrl_macb0_phy_irq: macb0_phy_irq {
bias-disable;
};
 
-   pinctrl_pdmic_default: pdmic_default {
-   pinmux = ,
-   ;
-   bias-disable;
-   };
-
pinctrl_qspi0_default: qspi0_default {
sck_cs {
pinmux = ,
-- 
2.25.1



[PATCH 1/3] ARM: dts: at91: sama5d2_xplained: classd: pull-down the R1 and R3 lines

2020-06-15 Thread Codrin Ciubotariu
The R1 and R3 lines drive NMOS transistors that are OFF with a low level.
On the SAMA5D2 Xplained board, if the pins corresponding to R1 and R3
have pull-ups enabled, there is an extra 2 x 30uA power consumption.
Use pull-downs for these 2 lines to remove the unnecessary power
consumption.

Fixes: b133ca7a653c ("ARM: dts: at91: sama5d2_xplained: add pin muxing and 
enable classd")
Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/boot/dts/at91-sama5d2_xplained.dts | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 055ee53e4773..54d96649da77 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -430,14 +430,18 @@ pinctrl_charger_lbo: charger_lbo {
bias-pull-up;
};
 
-   pinctrl_classd_default: classd_default {
+   pinctrl_classd_default_pfets: 
classd_default_pfets {
pinmux = ,
-,
-,
-;
+;
bias-pull-up;
};
 
+   pinctrl_classd_default_nfets: 
classd_default_nfets {
+   pinmux = ,
+;
+   bias-pull-down;
+   };
+
pinctrl_flx0_default: flx0_default {
pinmux = ,
 ;
@@ -614,7 +618,7 @@ pinctrl_pwm0_pwm2_default: pwm0_pwm2_default {
 
classd: classd@fc048000 {
pinctrl-names = "default";
-   pinctrl-0 = <_classd_default>;
+   pinctrl-0 = <_classd_default_pfets 
_classd_default_nfets>;
atmel,pwm-type = "diff";
atmel,non-overlap-time = <10>;
status = "okay";
-- 
2.25.1



[PATCH 3/3] Revert "ARM: at91/dt: sama5d2 Xplained: add pdmic node"

2020-06-15 Thread Codrin Ciubotariu
There are no PDM microphones on SAMA5D2 Xplained, to exercize the
PDMIC.

This reverts commit ca6349a8c51f2e3d6f2acdb36431e7d7328261f7.

Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 
 1 file changed, 16 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 54d96649da77..c0a255bda477 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -109,16 +109,6 @@ timer1: timer@1 {
};
};
 
-   pdmic@f8018000 {
-   pinctrl-names = "default";
-   pinctrl-0 = <_pdmic_default>;
-   atmel,model = "PDMIC @ sama5d2_xplained";
-   atmel,mic-min-freq = <100>;
-   atmel,mic-max-freq = <3246000>;
-   atmel,mic-offset = <0x0>;
-   status = "okay";
-   };
-
uart1: serial@f802 {
pinctrl-names = "default";
pinctrl-0 = <_uart1_default>;
@@ -533,12 +523,6 @@ pinctrl_macb0_phy_irq: macb0_phy_irq {
bias-disable;
};
 
-   pinctrl_pdmic_default: pdmic_default {
-   pinmux = ,
-   ;
-   bias-disable;
-   };
-
pinctrl_sdmmc0_default: sdmmc0_default {
cmd_data {
pinmux = ,
-- 
2.25.1



[PATCH 2/3] ARM: dts: at91: sam9x60ek: classd: pull-down the L1 and L3 lines

2020-06-15 Thread Codrin Ciubotariu
The L1 and L3 lines drive NMOS transistors that are OFF with a low level.
On the SAM9X60 EK board, if the pins corresponding to L1 and L3
have pull-ups enabled, there is an extra 2 x 30uA power consumption.
Use pull-downs for these 2 lines to remove the unnecessary power
consumption.

Fixes: 1e5f532c2737 ("ARM: dts: at91: sam9x60: add device tree for soc and 
board")
Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/boot/dts/at91-sam9x60ek.dts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sam9x60ek.dts 
b/arch/arm/boot/dts/at91-sam9x60ek.dts
index b484745bf2d4..3b9bb29d9e23 100644
--- a/arch/arm/boot/dts/at91-sam9x60ek.dts
+++ b/arch/arm/boot/dts/at91-sam9x60ek.dts
@@ -470,9 +470,9 @@ classd {
pinctrl_classd_default: classd {
atmel,pins =
;
+AT91_PIOA 27 AT91_PERIPH_C 
AT91_PINCTRL_PULL_DOWN>;
};
};
 
-- 
2.25.1



[PATCH] ARM: dts: at91: Configure SCL gpio of i2c2 node as open drain

2020-05-15 Thread Codrin Ciubotariu
The SCL gpio pin of i2c2 node used for recovery needs to be configured as
open drain.

Fixes: 455fec938bbb ("ARM: dts: at91: sama5d2: add i2c gpio pinctrl")
Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/boot/dts/at91-sama5d2_xplained.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 5846720fc9dc..851b8587068b 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -344,7 +344,7 @@ i2c2: i2c@600 {
pinctrl-0 = <_flx0_default>;
pinctrl-1 = <_i2c2_gpio>;
sda-gpios = < PIN_PB28 
GPIO_ACTIVE_HIGH>;
-   scl-gpios = < PIN_PB29 
GPIO_ACTIVE_HIGH>;
+   scl-gpios = < PIN_PB29 
(GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
i2c-sda-hold-time-ns = <350>;
i2c-analog-filter;
i2c-digital-filter;
-- 
2.25.1



[PATCH] clk: at91: Add peripheral clock for PTC

2020-05-15 Thread Codrin Ciubotariu
PMC generates the peripheral clock for the PTC.

Signed-off-by: Codrin Ciubotariu 
---
 drivers/clk/at91/sama5d2.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c
index ff7e3f727082..73b287fbecb8 100644
--- a/drivers/clk/at91/sama5d2.c
+++ b/drivers/clk/at91/sama5d2.c
@@ -89,6 +89,7 @@ static const struct {
{ .n = "i2s1_clk",.id = 55, .r = { .min = 0, .max = 8300 }, },
{ .n = "can0_clk",.id = 56, .r = { .min = 0, .max = 8300 }, },
{ .n = "can1_clk",.id = 57, .r = { .min = 0, .max = 8300 }, },
+   { .n = "ptc_clk", .id = 58, .r = { .min = 0, .max = 8300 }, },
{ .n = "classd_clk",  .id = 59, .r = { .min = 0, .max = 8300 }, },
 };
 
-- 
2.25.1



[PATCH] ARM: dts: at91: Configure I2C SCL gpio as open drain

2020-05-15 Thread Codrin Ciubotariu
The SCL gpio pin used by I2C bus for recovery needs to be configured as
open drain.

Fixes: 455fec938bbb ("ARM: dts: at91: sama5d2: add i2c gpio pinctrl")
Fixes: a4bd8da893a3 ("ARM: dts: at91: sama5d3: add i2c gpio pinctrl")
Fixes: 8fb82f050cf6 ("ARM: dts: at91: sama5d4: add i2c gpio pinctrl")
Signed-off-by: Codrin Ciubotariu 
---
 arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts   | 6 +++---
 arch/arm/boot/dts/at91-sama5d2_xplained.dts | 6 +++---
 arch/arm/boot/dts/sama5d3.dtsi  | 6 +++---
 arch/arm/boot/dts/sama5d4.dtsi  | 6 +++---
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts 
b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
index 32435ce1dab2..be33483013e7 100644
--- a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
@@ -182,7 +182,7 @@ i2c0: i2c@f8028000 {
pinctrl-0 = <_i2c0_default>;
pinctrl-1 = <_i2c0_gpio>;
sda-gpios = < PIN_PD21 GPIO_ACTIVE_HIGH>;
-   scl-gpios = < PIN_PD22 GPIO_ACTIVE_HIGH>;
+   scl-gpios = < PIN_PD22 (GPIO_ACTIVE_HIGH | 
GPIO_OPEN_DRAIN)>;
status = "okay";
};
 
@@ -203,7 +203,7 @@ i2c2: i2c@600 {
pinctrl-0 = <_flx0_default>;
pinctrl-1 = <_flx0_gpio>;
sda-gpios = < PIN_PB28 
GPIO_ACTIVE_HIGH>;
-   scl-gpios = < PIN_PB29 
GPIO_ACTIVE_HIGH>;
+   scl-gpios = < PIN_PB29 
(GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
atmel,fifo-size = <16>;
status = "okay";
};
@@ -234,7 +234,7 @@ i2c1: i2c@fc028000 {
pinctrl-0 = <_i2c1_default>;
pinctrl-1 = <_i2c1_gpio>;
sda-gpios = < PIN_PC6 GPIO_ACTIVE_HIGH>;
-   scl-gpios = < PIN_PC7 GPIO_ACTIVE_HIGH>;
+   scl-gpios = < PIN_PC7 (GPIO_ACTIVE_HIGH | 
GPIO_OPEN_DRAIN)>;
status = "okay";
 
at24@50 {
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts 
b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index e0c6cff1a312..862bf54376f1 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -185,7 +185,7 @@ i2c0: i2c@f8028000 {
pinctrl-0 = <_i2c0_default>;
pinctrl-1 = <_i2c0_gpio>;
sda-gpios = < PIN_PD21 GPIO_ACTIVE_HIGH>;
-   scl-gpios = < PIN_PD22 GPIO_ACTIVE_HIGH>;
+   scl-gpios = < PIN_PD22 (GPIO_ACTIVE_HIGH | 
GPIO_OPEN_DRAIN)>;
i2c-sda-hold-time-ns = <350>;
status = "okay";
 
@@ -390,7 +390,7 @@ i2c2: i2c@600 {
pinctrl-0 = <_flx4_default>;
pinctrl-1 = <_flx4_gpio>;
sda-gpios = < PIN_PD12 
GPIO_ACTIVE_HIGH>;
-   scl-gpios = < PIN_PD13 
GPIO_ACTIVE_HIGH>;
+   scl-gpios = < PIN_PD13 
(GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
atmel,fifo-size = <16>;
i2c-analog-filter;
i2c-digital-filter;
@@ -408,7 +408,7 @@ i2c1: i2c@fc028000 {
i2c-digital-filter-width-ns = <35>;
pinctrl-1 = <_i2c1_gpio>;
sda-gpios = < PIN_PD4 GPIO_ACTIVE_HIGH>;
-   scl-gpios = < PIN_PD5 GPIO_ACTIVE_HIGH>;
+   scl-gpios = < PIN_PD5 (GPIO_ACTIVE_HIGH | 
GPIO_OPEN_DRAIN)>;
status = "okay";
 
at24@54 {
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index f3ce561b46ab..c53e48445e4d 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -163,7 +163,7 @@ i2c0: i2c@f0014000 {
pinctrl-0 = <_i2c0>;
pinctrl-1 = <_i2c0_gpio>;
sda-g

[PATCH] i2c: at91: Restore pinctrl state if can't get scl/sda gpios

2020-05-13 Thread Codrin Ciubotariu
If there is a strict pinmux or if simply the scl/sda gpios are missing,
the pins will remain in gpio mode, compromizing the I2C bus.
Change to the default state of the pins before returning the error.

Fixes: a53acc7ebf27 ("i2c: at91: Fix pinmux after devm_gpiod_get() for bus 
recovery")
Signed-off-by: Codrin Ciubotariu 
---
 drivers/i2c/busses/i2c-at91-master.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/i2c/busses/i2c-at91-master.c 
b/drivers/i2c/busses/i2c-at91-master.c
index d4a3aef4a594..363d540a8345 100644
--- a/drivers/i2c/busses/i2c-at91-master.c
+++ b/drivers/i2c/busses/i2c-at91-master.c
@@ -877,6 +877,7 @@ static int at91_init_twi_recovery_gpio(struct 
platform_device *pdev,
gpiod_put(rinfo->scl_gpiod);
rinfo->scl_gpiod = NULL;
}
+   pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
return -EINVAL;
}
 
-- 
2.25.1



[PATCH v3] i2c: at91: Send bus clear command if SCL or SDA is down

2019-09-30 Thread Codrin Ciubotariu
After a transfer timeout, some faulty I2C slave devices might hold down
the SCL or the SDA pins. We can generate a bus clear command, hoping that
the slave might release the pins.

Signed-off-by: Codrin Ciubotariu 
Acked-by: Ludovic Desroches 
---

Changes in v3:
 - fixed kbuild warning;

Changes in v2:
 - added '.has_clear_cmd' struct member to specify which IPs support the
   clear command; for now, only SAMA5D2 supports it;
 - added Ludovic's V1 ack since there were no major changes;

 drivers/i2c/busses/i2c-at91-core.c   |  8 
 drivers/i2c/busses/i2c-at91-master.c | 22 ++
 drivers/i2c/busses/i2c-at91.h|  7 ++-
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-at91-core.c 
b/drivers/i2c/busses/i2c-at91-core.c
index 435c7d7377a3..cb07489e698f 100644
--- a/drivers/i2c/busses/i2c-at91-core.c
+++ b/drivers/i2c/busses/i2c-at91-core.c
@@ -68,6 +68,7 @@ static struct at91_twi_pdata at91rm9200_config = {
.has_unre_flag = true,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata at91sam9261_config = {
@@ -76,6 +77,7 @@ static struct at91_twi_pdata at91sam9261_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata at91sam9260_config = {
@@ -84,6 +86,7 @@ static struct at91_twi_pdata at91sam9260_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata at91sam9g20_config = {
@@ -92,6 +95,7 @@ static struct at91_twi_pdata at91sam9g20_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata at91sam9g10_config = {
@@ -100,6 +104,7 @@ static struct at91_twi_pdata at91sam9g10_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static const struct platform_device_id at91_twi_devtypes[] = {
@@ -130,6 +135,7 @@ static struct at91_twi_pdata at91sam9x5_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata sama5d4_config = {
@@ -138,6 +144,7 @@ static struct at91_twi_pdata sama5d4_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = true,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata sama5d2_config = {
@@ -146,6 +153,7 @@ static struct at91_twi_pdata sama5d2_config = {
.has_unre_flag = true,
.has_alt_cmd = true,
.has_hold_field = true,
+   .has_clear_cmd = true,
 };
 
 static const struct of_device_id atmel_twi_dt_ids[] = {
diff --git a/drivers/i2c/busses/i2c-at91-master.c 
b/drivers/i2c/busses/i2c-at91-master.c
index a3fcc35ffd3b..12d4fa946a82 100644
--- a/drivers/i2c/busses/i2c-at91-master.c
+++ b/drivers/i2c/busses/i2c-at91-master.c
@@ -440,6 +440,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
unsigned long time_left;
bool has_unre_flag = dev->pdata->has_unre_flag;
bool has_alt_cmd = dev->pdata->has_alt_cmd;
+   bool has_clear_cmd = dev->pdata->has_clear_cmd;
 
/*
 * WARNING: the TXCOMP bit in the Status Register is NOT a clear on
@@ -599,6 +600,27 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
at91_twi_write(dev, AT91_TWI_CR,
   AT91_TWI_THRCLR | AT91_TWI_LOCKCLR);
}
+
+   /*
+* After timeout, some faulty I2C slave devices might hold SCL/SDA down;
+* we can send a bus clear command, hoping that the pins will be
+* released
+*/
+   if (has_clear_cmd &&
+   (!(dev->transfer_status & AT91_TWI_SDA) ||
+!(dev->transfer_status & AT91_TWI_SCL))) {
+   dev_dbg(dev->dev,
+   "SDA/SCL are down; sending bus clear command\n");
+   if (dev->use_alt_cmd) {
+   unsigned int acr;
+
+   acr = at91_twi_read(dev, AT91_TWI_ACR);
+   acr &= ~AT91_TWI_ACR_DATAL_MASK;
+   at91_twi_write(dev, AT91_TWI_ACR, acr);
+   }
+   at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_CLEAR);
+   }
+
return ret;
 }
 
diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h
index 499b506f6128..0827c28a84db 100644
--- a/drivers/i2c/busses/i2c-at91.h
+++ b/drivers/i2c/busses/i2c-at91.h
@@ -36,6 +36,7 @@
 #defineAT91_TWI_SVDIS  BIT(5)  /* Slave Transfer Disable */
 #defineAT91_TWI_QUICK  BIT(6)  /* SMBus qu

[PATCH v2] i2c: at91: Send bus clear command if SCL or SDA is down

2019-09-25 Thread Codrin Ciubotariu
After a transfer timeout, some faulty I2C slave devices might hold down
the SCL or the SDA pins. We can generate a bus clear command, hoping that
the slave might release the pins.

Signed-off-by: Codrin Ciubotariu 
Acked-by: Ludovic Desroches 
---

Changes in v2:
 - added '.has_clear_cmd' struct member to specify which IPs support the
   clear command; for now, only SAMA5D2 supports it;
 - added Ludovic's V1 ack since there were no major changes;

 drivers/i2c/busses/i2c-at91-core.c   |  8 
 drivers/i2c/busses/i2c-at91-master.c | 21 +
 drivers/i2c/busses/i2c-at91.h|  7 ++-
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-at91-core.c 
b/drivers/i2c/busses/i2c-at91-core.c
index 435c7d7377a3..cb07489e698f 100644
--- a/drivers/i2c/busses/i2c-at91-core.c
+++ b/drivers/i2c/busses/i2c-at91-core.c
@@ -68,6 +68,7 @@ static struct at91_twi_pdata at91rm9200_config = {
.has_unre_flag = true,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata at91sam9261_config = {
@@ -76,6 +77,7 @@ static struct at91_twi_pdata at91sam9261_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata at91sam9260_config = {
@@ -84,6 +86,7 @@ static struct at91_twi_pdata at91sam9260_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata at91sam9g20_config = {
@@ -92,6 +95,7 @@ static struct at91_twi_pdata at91sam9g20_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata at91sam9g10_config = {
@@ -100,6 +104,7 @@ static struct at91_twi_pdata at91sam9g10_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static const struct platform_device_id at91_twi_devtypes[] = {
@@ -130,6 +135,7 @@ static struct at91_twi_pdata at91sam9x5_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = false,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata sama5d4_config = {
@@ -138,6 +144,7 @@ static struct at91_twi_pdata sama5d4_config = {
.has_unre_flag = false,
.has_alt_cmd = false,
.has_hold_field = true,
+   .has_clear_cmd = false,
 };
 
 static struct at91_twi_pdata sama5d2_config = {
@@ -146,6 +153,7 @@ static struct at91_twi_pdata sama5d2_config = {
.has_unre_flag = true,
.has_alt_cmd = true,
.has_hold_field = true,
+   .has_clear_cmd = true,
 };
 
 static const struct of_device_id atmel_twi_dt_ids[] = {
diff --git a/drivers/i2c/busses/i2c-at91-master.c 
b/drivers/i2c/busses/i2c-at91-master.c
index a3fcc35ffd3b..8082dff77724 100644
--- a/drivers/i2c/busses/i2c-at91-master.c
+++ b/drivers/i2c/busses/i2c-at91-master.c
@@ -440,6 +440,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
unsigned long time_left;
bool has_unre_flag = dev->pdata->has_unre_flag;
bool has_alt_cmd = dev->pdata->has_alt_cmd;
+   bool has_clear_cmd = dev->pdata->has_clear_cmd;
 
/*
 * WARNING: the TXCOMP bit in the Status Register is NOT a clear on
@@ -599,6 +600,26 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
at91_twi_write(dev, AT91_TWI_CR,
   AT91_TWI_THRCLR | AT91_TWI_LOCKCLR);
}
+
+   /*
+* After timeout, some faulty I2C slave devices might hold SCL/SDA down;
+* we can send a bus clear command, hoping that the pins will be
+* released
+*/
+   if (has_clear_cmd && !(dev->transfer_status & AT91_TWI_SDA) ||
+   !(dev->transfer_status & AT91_TWI_SCL)) {
+   dev_dbg(dev->dev,
+   "SDA/SCL are down; sending bus clear command\n");
+   if (dev->use_alt_cmd) {
+   unsigned int acr;
+
+   acr = at91_twi_read(dev, AT91_TWI_ACR);
+   acr &= ~AT91_TWI_ACR_DATAL_MASK;
+   at91_twi_write(dev, AT91_TWI_ACR, acr);
+   }
+   at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_CLEAR);
+   }
+
return ret;
 }
 
diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h
index 499b506f6128..0827c28a84db 100644
--- a/drivers/i2c/busses/i2c-at91.h
+++ b/drivers/i2c/busses/i2c-at91.h
@@ -36,6 +36,7 @@
 #defineAT91_TWI_SVDIS  BIT(5)  /* Slave Transfer Disable */
 #defineAT91_TWI_QUICK  BIT(6)  /* SMBus quick command */
 #defineAT91_TWI_SWRST 

[PATCH] i2c: at91: Send bus clear command if SCL or SDA is down

2019-09-11 Thread Codrin Ciubotariu
After a transfer timeout, some faulty I2C slave devices might hold down
the SCL or the SDA pins. We can generate a bus clear command, hoping that
the slave might release the pins.

Signed-off-by: Codrin Ciubotariu 
---
 drivers/i2c/busses/i2c-at91-master.c | 20 
 drivers/i2c/busses/i2c-at91.h|  6 +-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-at91-master.c 
b/drivers/i2c/busses/i2c-at91-master.c
index a3fcc35ffd3b..5f544a16db96 100644
--- a/drivers/i2c/busses/i2c-at91-master.c
+++ b/drivers/i2c/busses/i2c-at91-master.c
@@ -599,6 +599,26 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
at91_twi_write(dev, AT91_TWI_CR,
   AT91_TWI_THRCLR | AT91_TWI_LOCKCLR);
}
+
+   /*
+* After timeout, some faulty I2C slave devices might hold SCL/SDA down;
+* we can send a bus clear command, hoping that the pins will be
+* released
+*/
+   if (!(dev->transfer_status & AT91_TWI_SDA) ||
+   !(dev->transfer_status & AT91_TWI_SCL)) {
+   dev_dbg(dev->dev,
+   "SDA/SCL are down; sending bus clear command\n");
+   if (dev->use_alt_cmd) {
+   unsigned int acr;
+
+   acr = at91_twi_read(dev, AT91_TWI_ACR);
+   acr &= ~AT91_TWI_ACR_DATAL_MASK;
+   at91_twi_write(dev, AT91_TWI_ACR, acr);
+   }
+   at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_CLEAR);
+   }
+
return ret;
 }
 
diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h
index 499b506f6128..ffb870f3ffc6 100644
--- a/drivers/i2c/busses/i2c-at91.h
+++ b/drivers/i2c/busses/i2c-at91.h
@@ -36,6 +36,7 @@
 #defineAT91_TWI_SVDIS  BIT(5)  /* Slave Transfer Disable */
 #defineAT91_TWI_QUICK  BIT(6)  /* SMBus quick command */
 #defineAT91_TWI_SWRST  BIT(7)  /* Software Reset */
+#defineAT91_TWI_CLEAR  BIT(15) /* Bus clear command */
 #defineAT91_TWI_ACMEN  BIT(16) /* Alternative Command Mode 
Enable */
 #defineAT91_TWI_ACMDIS BIT(17) /* Alternative Command Mode 
Disable */
 #defineAT91_TWI_THRCLR BIT(24) /* Transmit Holding Register 
Clear */
@@ -69,6 +70,8 @@
 #defineAT91_TWI_NACK   BIT(8)  /* Not Acknowledged */
 #defineAT91_TWI_EOSACC BIT(11) /* End Of Slave Access */
 #defineAT91_TWI_LOCK   BIT(23) /* TWI Lock due to Frame Errors 
*/
+#defineAT91_TWI_SCLBIT(24) /* TWI SCL status */
+#defineAT91_TWI_SDABIT(25) /* TWI SDA status */
 
 #defineAT91_TWI_INT_MASK \
(AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY | AT91_TWI_NACK \
@@ -81,7 +84,8 @@
 #defineAT91_TWI_THR0x0034  /* Transmit Holding Register */
 
 #defineAT91_TWI_ACR0x0040  /* Alternative Command Register 
*/
-#defineAT91_TWI_ACR_DATAL(len) ((len) & 0xff)
+#defineAT91_TWI_ACR_DATAL_MASK GENMASK(15, 0)
+#defineAT91_TWI_ACR_DATAL(len) ((len) & AT91_TWI_ACR_DATAL_MASK)
 #defineAT91_TWI_ACR_DIRBIT(8)
 
 #defineAT91_TWI_FMR0x0050  /* FIFO Mode Register */
-- 
2.20.1



  1   2   >