[v2,16/16] ASoC: fsl-ssi: Use regmap
diff mbox

Message ID 1394887464-969-17-git-send-email-mpa@pengutronix.de
State New, archived
Headers show

Commit Message

Markus Pargmann March 15, 2014, 12:44 p.m. UTC
This patch replaces the ssi specific functions write_ssi, read_ssi and
write_ssi_mask by standard regmap function calls.

Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
---
 sound/soc/fsl/Kconfig   |   1 +
 sound/soc/fsl/fsl_ssi.c | 232 ++++++++++++++++++++++++++----------------------
 sound/soc/fsl/fsl_ssi.h |  50 +++++------
 3 files changed, 153 insertions(+), 130 deletions(-)

Comments

Alexander Shiyan March 15, 2014, 2:43 p.m. UTC | #1
???????, 15 ????? 2014, 13:44 +01:00 ?? Markus Pargmann <mpa@pengutronix.de>:
> This patch replaces the ssi specific functions write_ssi, read_ssi and
> write_ssi_mask by standard regmap function calls.
...
> diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
...
> +static const struct regmap_config fsl_ssi_regconfig = {
> +	.max_register = CCSR_SSI_SACCDIS,
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +#ifdef PPC
> +	.val_format_endian = REGMAP_ENDIAN_BIG,
> +#endif
> +};

Why we cannot use REGMAP_ENDIAN_NATIVE here for all cases?
Theoretically, we can use for i.MX SOCs with different endianness,
so this will help us.

---
Markus Pargmann March 18, 2014, 8:10 a.m. UTC | #2
On Sat, Mar 15, 2014 at 06:43:36PM +0400, Alexander Shiyan wrote:
> ???????, 15 ????? 2014, 13:44 +01:00 ?? Markus Pargmann <mpa@pengutronix.de>:
> > This patch replaces the ssi specific functions write_ssi, read_ssi and
> > write_ssi_mask by standard regmap function calls.
> ...
> > diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
> ...
> > +static const struct regmap_config fsl_ssi_regconfig = {
> > +	.max_register = CCSR_SSI_SACCDIS,
> > +	.reg_bits = 32,
> > +	.val_bits = 32,
> > +	.reg_stride = 4,
> > +#ifdef PPC
> > +	.val_format_endian = REGMAP_ENDIAN_BIG,
> > +#endif
> > +};
> 
> Why we cannot use REGMAP_ENDIAN_NATIVE here for all cases?
> Theoretically, we can use for i.MX SOCs with different endianness,
> so this will help us.

I can change and test it on i.MX, but I am not sure if it helps with the
PPC situation as I don't have the hardware.

Regards,

Markus

> 
> ---
Xiubo Li March 20, 2014, 6:07 a.m. UTC | #3
> Subject: Re: [PATCH v2 16/16] ASoC: fsl-ssi: Use regmap

> 

> On Sat, Mar 15, 2014 at 06:43:36PM +0400, Alexander Shiyan wrote:

> > ???????, 15 ????? 2014, 13:44 +01:00 ?? Markus Pargmann <mpa@pengutronix.de>:

> > > This patch replaces the ssi specific functions write_ssi, read_ssi and

> > > write_ssi_mask by standard regmap function calls.

> > ...

> > > diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c

> > ...

> > > +static const struct regmap_config fsl_ssi_regconfig = {

> > > +	.max_register = CCSR_SSI_SACCDIS,

> > > +	.reg_bits = 32,

> > > +	.val_bits = 32,

> > > +	.reg_stride = 4,

> > > +#ifdef PPC

> > > +	.val_format_endian = REGMAP_ENDIAN_BIG,

> > > +#endif

> > > +};

> >

> > Why we cannot use REGMAP_ENDIAN_NATIVE here for all cases?

> > Theoretically, we can use for i.MX SOCs with different endianness,

> > so this will help us.

> 

> I can change and test it on i.MX, but I am not sure if it helps with the

> PPC situation as I don't have the hardware.

> 


For the scenario of PowerPC(for CPU and devices mostly are in BE mode):
CPU		SSI
BE		BE	we can just use the REGMAP_ENDIAN_NATIVE here.

For the scenario of ARM(for CPU and devices mostly are in LE mode):
CPU		SSI
LE		LE	we can also just use the REGMAP_ENDIAN_NATIVE here.

While for the scenario like our LS1(ARM) platform.
CPU		SSI
LE		BE	then should we set the .val_format_endian to
			REGMAP_ENDIAN_BIG


And so not only for PowerPC, but also maybe for ARM platforms.
So here how about just adding one Boolean property like 'big-endian' in DT node
to learn the endianness of the devices dynamically ?  

Thanks,
:)

Best Regards,
Xiubo
Timur Tabi March 20, 2014, 3:10 p.m. UTC | #4
On 03/20/2014 01:07 AM, Li.Xiubo@freescale.com wrote:
> While for the scenario like our LS1(ARM) platform.
> CPU		SSI
> LE		BE	then should we set the .val_format_endian to
> 			REGMAP_ENDIAN_BIG
>
>
> And so not only for PowerPC, but also maybe for ARM platforms.
> So here how about just adding one Boolean property like 'big-endian' in DT node
> to learn the endianness of the devices dynamically ?

That's not a bad idea.  The property should be something like, 
"fsl,ssi-endian" and is should be set to "big", "little", or "native". 
In the absence of the property, it should default to native endian.
Xiubo Li March 21, 2014, 1:52 a.m. UTC | #5
> Subject: Re: [PATCH v2 16/16] ASoC: fsl-ssi: Use regmap
> 
> On 03/20/2014 01:07 AM, Li.Xiubo@freescale.com wrote:
> > While for the scenario like our LS1(ARM) platform.
> > CPU		SSI
> > LE		BE	then should we set the .val_format_endian to
> > 			REGMAP_ENDIAN_BIG
> >
> >
> > And so not only for PowerPC, but also maybe for ARM platforms.
> > So here how about just adding one Boolean property like 'big-endian' in DT
> node
> > to learn the endianness of the devices dynamically ?
> 
> That's not a bad idea.  The property should be something like,
> "fsl,ssi-endian" and is should be set to "big", "little", or "native".
> In the absence of the property, it should default to native endian.
> 

Well, yes, sounds good.
That will lead the individual driver a little more complex. I do think that
The regmap core should use the REGMAP_ENDIAN_SWAP instead of 
REGMAP_ENDIAN_BIG/LITTLE ones if possible.


:)
Thanks,
--

Best Regards,
Xiubo
Markus Pargmann March 21, 2014, 8:45 a.m. UTC | #6
Hi,

On Thu, Mar 20, 2014 at 10:10:09AM -0500, Timur Tabi wrote:
> On 03/20/2014 01:07 AM, Li.Xiubo@freescale.com wrote:
> >While for the scenario like our LS1(ARM) platform.
> >CPU		SSI
> >LE		BE	then should we set the .val_format_endian to
> >			REGMAP_ENDIAN_BIG
> >
> >
> >And so not only for PowerPC, but also maybe for ARM platforms.
> >So here how about just adding one Boolean property like 'big-endian' in DT node
> >to learn the endianness of the devices dynamically ?
> 
> That's not a bad idea.  The property should be something like,
> "fsl,ssi-endian" and is should be set to "big", "little", or
> "native". In the absence of the property, it should default to
> native endian.

Perhaps it is better to create some generic binding for that? There may
be other drivers/components that have the same strange combinations and
need a similar binding to use for regmap.

We could use something like an "endian" property with "big", "little"
and "native" which is then parsed by some function of the regmap
framework. It could directly fill those information into the
struct regmap_config.

Thanks,

Markus
Xiubo Li March 21, 2014, 9:19 a.m. UTC | #7
> Subject: Re: [PATCH v2 16/16] ASoC: fsl-ssi: Use regmap
> 
> Hi,
> 
> On Thu, Mar 20, 2014 at 10:10:09AM -0500, Timur Tabi wrote:
> > On 03/20/2014 01:07 AM, Li.Xiubo@freescale.com wrote:
> > >While for the scenario like our LS1(ARM) platform.
> > >CPU		SSI
> > >LE		BE	then should we set the .val_format_endian to
> > >			REGMAP_ENDIAN_BIG
> > >
> > >
> > >And so not only for PowerPC, but also maybe for ARM platforms.
> > >So here how about just adding one Boolean property like 'big-endian' in DT
> node
> > >to learn the endianness of the devices dynamically ?
> >
> > That's not a bad idea.  The property should be something like,
> > "fsl,ssi-endian" and is should be set to "big", "little", or
> > "native". In the absence of the property, it should default to
> > native endian.
> 
> Perhaps it is better to create some generic binding for that? There may
> be other drivers/components that have the same strange combinations and
> need a similar binding to use for regmap.
> 
> We could use something like an "endian" property with "big", "little"
> and "native" which is then parsed by some function of the regmap
> framework. It could directly fill those information into the
> struct regmap_config.
> 
> Thanks,
> 
> Markus
> 

Yes, actually the fsl-sai, fsl-esai and fsl-spdif have already supported
this. In our Platforms of Vybird, LS1 and LS2 will support different endianess
of these devices and also many other IP blocks.

But I used the Boolean property like "big-endian" and this is enough, because
for now the regmap core does not support the following scenario:

CPU		IP
------------------
BE		LE

:)

Thanks,
--

Best Regards,
Xiubo

Patch
diff mbox

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 07f8f14..fbaea8a 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -3,6 +3,7 @@  config SND_SOC_FSL_SAI
 	select SND_SOC_GENERIC_DMAENGINE_PCM
 
 config SND_SOC_FSL_SSI
+	select REGMAP_MMIO
 	tristate
 
 config SND_SOC_FSL_SPDIF
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 6095a15..7873815 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -53,25 +53,6 @@ 
 #include "fsl_ssi.h"
 #include "imx-pcm.h"
 
-#ifdef PPC
-#define read_ssi(addr)			 in_be32(addr)
-#define write_ssi(val, addr)		 out_be32(addr, val)
-#define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set)
-#else
-#define read_ssi(addr)			 readl(addr)
-#define write_ssi(val, addr)		 writel(val, addr)
-/*
- * FIXME: Proper locking should be added at write_ssi_mask caller level
- * to ensure this register read/modify/write sequence is race free.
- */
-static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
-{
-	u32 val = readl(addr);
-	val = (val & ~clear) | set;
-	writel(val, addr);
-}
-#endif
-
 /**
  * FSLSSI_I2S_RATES: sample rates supported by the I2S
  *
@@ -131,6 +112,15 @@  struct fsl_ssi_rxtx_reg_val {
 	struct fsl_ssi_reg_val rx;
 	struct fsl_ssi_reg_val tx;
 };
+static const struct regmap_config fsl_ssi_regconfig = {
+	.max_register = CCSR_SSI_SACCDIS,
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+#ifdef PPC
+	.val_format_endian = REGMAP_ENDIAN_BIG,
+#endif
+};
 
 /**
  * fsl_ssi_private: per-SSI private data
@@ -165,7 +155,7 @@  struct fsl_ssi_rxtx_reg_val {
  * @dbg_stats: Debugging statistics
  */
 struct fsl_ssi_private {
-	struct ccsr_ssi __iomem *ssi;
+	struct regmap *regs;
 	unsigned int irq;
 	struct snd_soc_dai_driver cpu_dai_drv;
 
@@ -275,7 +265,7 @@  static bool fsl_ssi_offline_config(struct fsl_ssi_private *ssi_private)
 static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 {
 	struct fsl_ssi_private *ssi_private = dev_id;
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+	struct regmap *regs = ssi_private->regs;
 	__be32 sisr;
 	__be32 sisr2;
 	__be32 sisr_write_mask = 0;
@@ -302,12 +292,12 @@  static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 	   were interrupted for.  We mask it with the Interrupt Enable register
 	   so that we only check for events that we're interested in.
 	 */
-	sisr = read_ssi(&ssi->sisr);
+	regmap_read(regs, CCSR_SSI_SISR, &sisr);
 
 	sisr2 = sisr & sisr_write_mask;
 	/* Clear the bits that we set */
 	if (sisr2)
-		write_ssi(sisr2, &ssi->sisr);
+		regmap_write(regs, CCSR_SSI_SISR, sisr2);
 
 	fsl_ssi_dbg_isr(&ssi_private->dbg_stats, sisr);
 
@@ -320,17 +310,26 @@  static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
 		bool enable)
 {
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+	struct regmap *regs = ssi_private->regs;
 	struct fsl_ssi_rxtx_reg_val *vals = &ssi_private->rxtx_reg_val;
 
 	if (enable) {
-		write_ssi_mask(&ssi->sier, 0, vals->rx.sier | vals->tx.sier);
-		write_ssi_mask(&ssi->srcr, 0, vals->rx.srcr | vals->tx.srcr);
-		write_ssi_mask(&ssi->stcr, 0, vals->rx.stcr | vals->tx.stcr);
+		regmap_update_bits(regs, CCSR_SSI_SIER,
+				vals->rx.sier | vals->tx.sier,
+				vals->rx.sier | vals->tx.sier);
+		regmap_update_bits(regs, CCSR_SSI_SRCR,
+				vals->rx.srcr | vals->tx.srcr,
+				vals->rx.srcr | vals->tx.srcr);
+		regmap_update_bits(regs, CCSR_SSI_STCR,
+				vals->rx.stcr | vals->tx.stcr,
+				vals->rx.stcr | vals->tx.stcr);
 	} else {
-		write_ssi_mask(&ssi->srcr, vals->rx.srcr | vals->tx.srcr, 0);
-		write_ssi_mask(&ssi->stcr, vals->rx.stcr | vals->tx.stcr, 0);
-		write_ssi_mask(&ssi->sier, vals->rx.sier | vals->tx.sier, 0);
+		regmap_update_bits(regs, CCSR_SSI_SRCR,
+				vals->rx.srcr | vals->tx.srcr, 0);
+		regmap_update_bits(regs, CCSR_SSI_STCR,
+				vals->rx.stcr | vals->tx.stcr, 0);
+		regmap_update_bits(regs, CCSR_SSI_SIER,
+				vals->rx.sier | vals->tx.sier, 0);
 	}
 }
 
@@ -361,13 +360,16 @@  static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
 static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
 		struct fsl_ssi_reg_val *vals)
 {
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+	struct regmap *regs = ssi_private->regs;
 	struct fsl_ssi_reg_val *avals;
-	u32 scr_val = read_ssi(&ssi->scr);
-	int nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) +
-				!!(scr_val & CCSR_SSI_SCR_RE);
+	u32 scr_val;
+	int nr_active_streams;
 	int keep_active;
 
+	regmap_read(regs, CCSR_SSI_SCR, &scr_val);
+	nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) +
+			!!(scr_val & CCSR_SSI_SCR_RE);
+
 	if (nr_active_streams - 1 > 0)
 		keep_active = 1;
 	else
@@ -384,7 +386,7 @@  static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
 	if (!enable) {
 		u32 scr = fsl_ssi_disable_val(vals->scr, avals->scr,
 				keep_active);
-		write_ssi_mask(&ssi->scr, scr, 0);
+		regmap_update_bits(regs, CCSR_SSI_SCR, scr, 0);
 	}
 
 	/*
@@ -405,9 +407,9 @@  static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
 	 * (online configuration)
 	 */
 	if (enable) {
-		write_ssi_mask(&ssi->sier, 0, vals->sier);
-		write_ssi_mask(&ssi->srcr, 0, vals->srcr);
-		write_ssi_mask(&ssi->stcr, 0, vals->stcr);
+		regmap_update_bits(regs, CCSR_SSI_SIER, vals->sier, vals->sier);
+		regmap_update_bits(regs, CCSR_SSI_SRCR, vals->srcr, vals->srcr);
+		regmap_update_bits(regs, CCSR_SSI_STCR, vals->stcr, vals->stcr);
 	} else {
 		u32 sier;
 		u32 srcr;
@@ -430,15 +432,15 @@  static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
 		stcr = fsl_ssi_disable_val(vals->stcr, avals->stcr,
 				keep_active);
 
-		write_ssi_mask(&ssi->srcr, srcr, 0);
-		write_ssi_mask(&ssi->stcr, stcr, 0);
-		write_ssi_mask(&ssi->sier, sier, 0);
+		regmap_update_bits(regs, CCSR_SSI_SRCR, srcr, 0);
+		regmap_update_bits(regs, CCSR_SSI_STCR, stcr, 0);
+		regmap_update_bits(regs, CCSR_SSI_SIER, sier, 0);
 	}
 
 config_done:
 	/* Enabling of subunits is done after configuration */
 	if (enable)
-		write_ssi_mask(&ssi->scr, 0, vals->scr);
+		regmap_update_bits(regs, CCSR_SSI_SCR, vals->scr, vals->scr);
 }
 
 
@@ -489,32 +491,33 @@  static void fsl_ssi_setup_reg_vals(struct fsl_ssi_private *ssi_private)
 
 static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
 {
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+	struct regmap *regs = ssi_private->regs;
 
 	/*
 	 * Setup the clock control register
 	 */
-	write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
-			&ssi->stccr);
-	write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
-			&ssi->srccr);
+	regmap_write(regs, CCSR_SSI_STCCR,
+			CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13));
+	regmap_write(regs, CCSR_SSI_SRCCR,
+			CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13));
 
 	/*
 	 * Enable AC97 mode and startup the SSI
 	 */
-	write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
-			&ssi->sacnt);
-	write_ssi(0xff, &ssi->saccdis);
-	write_ssi(0x300, &ssi->saccen);
+	regmap_write(regs, CCSR_SSI_SACNT,
+			CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV);
+	regmap_write(regs, CCSR_SSI_SACCDIS, 0xff);
+	regmap_write(regs, CCSR_SSI_SACCEN, 0x300);
 
 	/*
 	 * Enable SSI, Transmit and Receive. AC97 has to communicate with the
 	 * codec before a stream is started.
 	 */
-	write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
-			CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
+	regmap_update_bits(regs, CCSR_SSI_SCR,
+			CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE,
+			CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
 
-	write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
+	regmap_write(regs, CCSR_SSI_SOR, CCSR_SSI_SOR_WAIT(3));
 }
 
 /**
@@ -561,12 +564,16 @@  static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
 	struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+	struct regmap *regs = ssi_private->regs;
 	unsigned int channels = params_channels(hw_params);
 	unsigned int sample_size =
 		snd_pcm_format_width(params_format(hw_params));
 	u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
-	int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
+	u32 scr_val;
+	int enabled;
+
+	regmap_read(regs, CCSR_SSI_SCR, &scr_val);
+	enabled = scr_val & CCSR_SSI_SCR_SSIEN;
 
 	/*
 	 * If we're in synchronous mode, and the SSI is already enabled,
@@ -588,12 +595,14 @@  static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
 	/* In synchronous mode, the SSI uses STCCR for capture */
 	if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
 	    ssi_private->cpu_dai_drv.symmetric_rates)
-		write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
+		regmap_update_bits(regs, CCSR_SSI_STCCR, CCSR_SSI_SxCCR_WL_MASK,
+				wl);
 	else
-		write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
+		regmap_update_bits(regs, CCSR_SSI_SRCCR, CCSR_SSI_SxCCR_WL_MASK,
+				wl);
 
 	if (!fsl_ssi_is_ac97(ssi_private))
-		write_ssi_mask(&ssi->scr,
+		regmap_update_bits(regs, CCSR_SSI_SCR,
 				CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
 				channels == 1 ? 0 : ssi_private->i2s_mode);
 
@@ -603,7 +612,7 @@  static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
 static int _fsl_ssi_set_dai_fmt(struct fsl_ssi_private *ssi_private,
 		unsigned int fmt)
 {
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+	struct regmap *regs = ssi_private->regs;
 	u32 strcr = 0, stcr, srcr, scr, mask;
 	u8 wm;
 
@@ -614,14 +623,17 @@  static int _fsl_ssi_set_dai_fmt(struct fsl_ssi_private *ssi_private,
 
 	fsl_ssi_setup_reg_vals(ssi_private);
 
-	scr = read_ssi(&ssi->scr) & ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK);
+	regmap_read(regs, CCSR_SSI_SCR, &scr);
+	scr &= ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK);
 	scr |= CCSR_SSI_SCR_SYNC_TX_FS;
 
 	mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR |
 		CCSR_SSI_STCR_TSCKP | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TFSL |
 		CCSR_SSI_STCR_TEFS;
-	stcr = read_ssi(&ssi->stcr) & ~mask;
-	srcr = read_ssi(&ssi->srcr) & ~mask;
+	regmap_read(regs, CCSR_SSI_STCR, &stcr);
+	regmap_read(regs, CCSR_SSI_SRCR, &srcr);
+	stcr &= ~mask;
+	srcr &= ~mask;
 
 	ssi_private->i2s_mode = CCSR_SSI_SCR_NET;
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -707,9 +719,9 @@  static int _fsl_ssi_set_dai_fmt(struct fsl_ssi_private *ssi_private,
 		scr |= CCSR_SSI_SCR_SYN;
 	}
 
-	write_ssi(stcr, &ssi->stcr);
-	write_ssi(srcr, &ssi->srcr);
-	write_ssi(scr, &ssi->scr);
+	regmap_write(regs, CCSR_SSI_STCR, stcr);
+	regmap_write(regs, CCSR_SSI_SRCR, srcr);
+	regmap_write(regs, CCSR_SSI_SCR, scr);
 
 	/*
 	 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't
@@ -727,16 +739,16 @@  static int _fsl_ssi_set_dai_fmt(struct fsl_ssi_private *ssi_private,
 	else
 		wm = ssi_private->fifo_depth;
 
-	write_ssi(CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
-			CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm),
-			&ssi->sfcsr);
+	regmap_write(regs, CCSR_SSI_SFCSR,
+			CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
+			CCSR_SSI_SFCSR_TFWM1(wm) | CCSR_SSI_SFCSR_RFWM1(wm));
 
 	if (ssi_private->use_dual_fifo) {
-		write_ssi_mask(&ssi->srcr, CCSR_SSI_SRCR_RFEN1,
+		regmap_update_bits(regs, CCSR_SSI_SRCR, CCSR_SSI_SRCR_RFEN1,
 				CCSR_SSI_SRCR_RFEN1);
-		write_ssi_mask(&ssi->stcr, CCSR_SSI_STCR_TFEN1,
+		regmap_update_bits(regs, CCSR_SSI_STCR, CCSR_SSI_STCR_TFEN1,
 				CCSR_SSI_STCR_TFEN1);
-		write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TCH_EN,
+		regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_TCH_EN,
 				CCSR_SSI_SCR_TCH_EN);
 	}
 
@@ -770,7 +782,7 @@  static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 				  int clk_id, unsigned int freq, int dir)
 {
 	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+	struct regmap *regs = ssi_private->regs;
 	int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
 	u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
 	unsigned long flags, clkrate, baudrate, tmprate;
@@ -834,9 +846,9 @@  static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 	mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 | CCSR_SSI_SxCCR_PSR;
 
 	if (dir == SND_SOC_CLOCK_OUT || synchronous)
-		write_ssi_mask(&ssi->stccr, mask, stccr);
+		regmap_update_bits(regs, CCSR_SSI_STCCR, mask, stccr);
 	else
-		write_ssi_mask(&ssi->srccr, mask, stccr);
+		regmap_update_bits(regs, CCSR_SSI_SRCCR, mask, stccr);
 
 	spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
 	if (!ssi_private->baudclk_locked) {
@@ -865,31 +877,34 @@  static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
 				u32 rx_mask, int slots, int slot_width)
 {
 	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+	struct regmap *regs = ssi_private->regs;
 	u32 val;
 
 	/* The slot number should be >= 2 if using Network mode or I2S mode */
-	val = read_ssi(&ssi->scr) & (CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET);
+	regmap_read(regs, CCSR_SSI_SCR, &val);
+	val &= CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET;
 	if (val && slots < 2) {
 		dev_err(cpu_dai->dev, "slot number should be >= 2 in I2S or NET\n");
 		return -EINVAL;
 	}
 
-	write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
+	regmap_update_bits(regs, CCSR_SSI_STCCR, CCSR_SSI_SxCCR_DC_MASK,
 			CCSR_SSI_SxCCR_DC(slots));
-	write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
+	regmap_update_bits(regs, CCSR_SSI_SRCCR, CCSR_SSI_SxCCR_DC_MASK,
 			CCSR_SSI_SxCCR_DC(slots));
 
 	/* The register SxMSKs needs SSI to provide essential clock due to
 	 * hardware design. So we here temporarily enable SSI to set them.
 	 */
-	val = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
-	write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN);
+	regmap_read(regs, CCSR_SSI_SCR, &val);
+	val &= CCSR_SSI_SCR_SSIEN;
+	regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN,
+			CCSR_SSI_SCR_SSIEN);
 
-	write_ssi(tx_mask, &ssi->stmsk);
-	write_ssi(rx_mask, &ssi->srmsk);
+	regmap_write(regs, CCSR_SSI_STMSK, tx_mask);
+	regmap_write(regs, CCSR_SSI_SRMSK, rx_mask);
 
-	write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, val);
+	regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN, val);
 
 	return 0;
 }
@@ -908,12 +923,12 @@  static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-	struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+	struct regmap *regs = ssi_private->regs;
 	unsigned long flags;
 	u32 val;
 	int nr_active;
 
-	val = read_ssi(&ssi->scr);
+	regmap_read(regs, CCSR_SSI_SCR, &val);
 	nr_active = !!(val & CCSR_SSI_SCR_TE) + !!(val & CCSR_SSI_SCR_RE);
 
 	switch (cmd) {
@@ -968,9 +983,9 @@  static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
 
 	if (fsl_ssi_is_ac97(ssi_private)) {
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor);
+			regmap_write(regs, CCSR_SSI_SOR, CCSR_SSI_SOR_TX_CLR);
 		else
-			write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor);
+			regmap_write(regs, CCSR_SSI_SOR, CCSR_SSI_SOR_RX_CLR);
 	}
 
 	return 0;
@@ -1044,7 +1059,7 @@  static struct fsl_ssi_private *fsl_ac97_data;
 static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 		unsigned short val)
 {
-	struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
+	struct regmap *regs = fsl_ac97_data->regs;
 	unsigned int lreg;
 	unsigned int lval;
 
@@ -1053,12 +1068,12 @@  static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 
 
 	lreg = reg <<  12;
-	write_ssi(lreg, &ssi->sacadd);
+	regmap_write(regs, CCSR_SSI_SACADD, lreg);
 
 	lval = val << 4;
-	write_ssi(lval , &ssi->sacdat);
+	regmap_write(regs, CCSR_SSI_SACDAT, lval);
 
-	write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK,
+	regmap_update_bits(regs, CCSR_SSI_SACNT, CCSR_SSI_SACNT_RDWR_MASK,
 			CCSR_SSI_SACNT_WR);
 	udelay(100);
 }
@@ -1066,19 +1081,21 @@  static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
 		unsigned short reg)
 {
-	struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
+	struct regmap *regs = fsl_ac97_data->regs;
 
 	unsigned short val = -1;
+	u32 reg_val;
 	unsigned int lreg;
 
 	lreg = (reg & 0x7f) <<  12;
-	write_ssi(lreg, &ssi->sacadd);
-	write_ssi_mask(&ssi->sacnt, CCSR_SSI_SACNT_RDWR_MASK,
+	regmap_write(regs, CCSR_SSI_SACADD, lreg);
+	regmap_update_bits(regs, CCSR_SSI_SACNT, CCSR_SSI_SACNT_RDWR_MASK,
 			CCSR_SSI_SACNT_RD);
 
 	udelay(100);
 
-	val = (read_ssi(&ssi->sacdat) >> 4) & 0xffff;
+	regmap_read(regs, CCSR_SSI_SACDAT, &reg_val);
+	val = (reg_val >> 4) & 0xffff;
 
 	return val;
 }
@@ -1141,10 +1158,8 @@  static int fsl_ssi_imx_probe(struct platform_device *pdev,
 	 */
 	ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2;
 	ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2;
-	ssi_private->dma_params_tx.addr = ssi_private->ssi_phys +
-			offsetof(struct ccsr_ssi, stx0);
-	ssi_private->dma_params_rx.addr = ssi_private->ssi_phys +
-			offsetof(struct ccsr_ssi, srx0);
+	ssi_private->dma_params_tx.addr = ssi_private->ssi_phys + CCSR_SSI_STX0;
+	ssi_private->dma_params_rx.addr = ssi_private->ssi_phys + CCSR_SSI_SRX0;
 
 	ret = !of_property_read_u32_array(np, "dmas", dmas, 4);
 	if (ssi_private->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
@@ -1207,6 +1222,7 @@  static int fsl_ssi_probe(struct platform_device *pdev)
 	const char *p, *sprop;
 	const uint32_t *iprop;
 	struct resource res;
+	void __iomem *iomem;
 	char name[64];
 
 	/* SSIs that are not connected on the board should have a
@@ -1263,12 +1279,20 @@  static int fsl_ssi_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "could not determine device resources\n");
 		return ret;
 	}
-	ssi_private->ssi = of_iomap(np, 0);
-	if (!ssi_private->ssi) {
+	ssi_private->ssi_phys = res.start;
+
+	iomem = devm_ioremap(&pdev->dev, res.start, resource_size(&res));
+	if (!iomem) {
 		dev_err(&pdev->dev, "could not map device resources\n");
 		return -ENOMEM;
 	}
-	ssi_private->ssi_phys = res.start;
+
+	ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem,
+			&fsl_ssi_regconfig);
+	if (IS_ERR(ssi_private->regs)) {
+		dev_err(&pdev->dev, "Failed to init register map\n");
+		return PTR_ERR(ssi_private->regs);
+	}
 
 	ssi_private->irq = irq_of_parse_and_map(np, 0);
 	if (!ssi_private->irq) {
@@ -1296,7 +1320,7 @@  static int fsl_ssi_probe(struct platform_device *pdev)
 	dev_set_drvdata(&pdev->dev, ssi_private);
 
 	if (fsl_ssi_on_imx(ssi_private)) {
-		ret = fsl_ssi_imx_probe(pdev, ssi_private, ssi_private->ssi);
+		ret = fsl_ssi_imx_probe(pdev, ssi_private, iomem);
 		if (ret)
 			goto error_irqmap;
 	}
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index 71c3e7e..5065105 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -12,32 +12,30 @@ 
 #ifndef _MPC8610_I2S_H
 #define _MPC8610_I2S_H
 
-/* SSI Register Map */
-struct ccsr_ssi {
-	__be32 stx0;	/* 0x.0000 - SSI Transmit Data Register 0 */
-	__be32 stx1;	/* 0x.0004 - SSI Transmit Data Register 1 */
-	__be32 srx0;	/* 0x.0008 - SSI Receive Data Register 0 */
-	__be32 srx1;	/* 0x.000C - SSI Receive Data Register 1 */
-	__be32 scr;	/* 0x.0010 - SSI Control Register */
-	__be32 sisr;	/* 0x.0014 - SSI Interrupt Status Register Mixed */
-	__be32 sier;	/* 0x.0018 - SSI Interrupt Enable Register */
-	__be32 stcr;	/* 0x.001C - SSI Transmit Configuration Register */
-	__be32 srcr;	/* 0x.0020 - SSI Receive Configuration Register */
-	__be32 stccr;	/* 0x.0024 - SSI Transmit Clock Control Register */
-	__be32 srccr;	/* 0x.0028 - SSI Receive Clock Control Register */
-	__be32 sfcsr;	/* 0x.002C - SSI FIFO Control/Status Register */
-	__be32 str;	/* 0x.0030 - SSI Test Register */
-	__be32 sor;	/* 0x.0034 - SSI Option Register */
-	__be32 sacnt;	/* 0x.0038 - SSI AC97 Control Register */
-	__be32 sacadd;	/* 0x.003C - SSI AC97 Command Address Register */
-	__be32 sacdat;	/* 0x.0040 - SSI AC97 Command Data Register */
-	__be32 satag;	/* 0x.0044 - SSI AC97 Tag Register */
-	__be32 stmsk;	/* 0x.0048 - SSI Transmit Time Slot Mask Register */
-	__be32 srmsk;	/* 0x.004C - SSI Receive Time Slot Mask Register */
-	__be32 saccst;	/* 0x.0050 - SSI AC97 Channel Status Register */
-	__be32 saccen;	/* 0x.0054 - SSI AC97 Channel Enable Register */
-	__be32 saccdis; /* 0x.0058 - SSI AC97 Channel Disable Register */
-};
+/* SSI registers */
+#define CCSR_SSI_STX0			0x00
+#define CCSR_SSI_STX1			0x04
+#define CCSR_SSI_SRX0			0x08
+#define CCSR_SSI_SRX1			0x0c
+#define CCSR_SSI_SCR			0x10
+#define CCSR_SSI_SISR			0x14
+#define CCSR_SSI_SIER			0x18
+#define CCSR_SSI_STCR			0x1c
+#define CCSR_SSI_SRCR			0x20
+#define CCSR_SSI_STCCR			0x24
+#define CCSR_SSI_SRCCR			0x28
+#define CCSR_SSI_SFCSR			0x2c
+#define CCSR_SSI_STR			0x30
+#define CCSR_SSI_SOR			0x34
+#define CCSR_SSI_SACNT			0x38
+#define CCSR_SSI_SACADD			0x3c
+#define CCSR_SSI_SACDAT			0x40
+#define CCSR_SSI_SATAG			0x44
+#define CCSR_SSI_STMSK			0x48
+#define CCSR_SSI_SRMSK			0x4c
+#define CCSR_SSI_SACCST			0x50
+#define CCSR_SSI_SACCEN			0x54
+#define CCSR_SSI_SACCDIS		0x58
 
 #define CCSR_SSI_SCR_SYNC_TX_FS		0x00001000
 #define CCSR_SSI_SCR_RFR_CLK_DIS	0x00000800