diff mbox

spi: mpc512x-psc: add support for Freescale MPC5125

Message ID 1436865596-9592-1-git-send-email-u.kleine-koenig@pengutronix.de (mailing list archive)
State Accepted
Delegated to: Anatolij Gustschin
Headers show

Commit Message

Uwe Kleine-König July 14, 2015, 9:19 a.m. UTC
The register layout of the PSC devices differ between MPC5121 and
MPC5125, but the registers are named nearly identical and their purpose
is similar enough ("freescale identical") such that substituting
mpc52xx_psc by mpc5125_psc is nearly enough to make the driver work on
MPC5125. To keep supporting MPC5121 this patch introduces a cpp
macro to select the right struct that defines the register layout.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 arch/powerpc/include/asm/mpc52xx_psc.h |  5 ++-
 drivers/spi/spi-mpc512x-psc.c          | 70 +++++++++++++++++++++++-----------
 2 files changed, 51 insertions(+), 24 deletions(-)

Comments

Mark Brown July 14, 2015, 9:54 a.m. UTC | #1
On Tue, Jul 14, 2015 at 11:19:56AM +0200, Uwe Kleine-König wrote:

>  static const struct of_device_id mpc512x_psc_spi_of_match[] = {
> -	{ .compatible = "fsl,mpc5121-psc-spi", },
> +	{ .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 },
> +	{ .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 },
>  	{},

The code seems fine but this should update the binding document to
include the new compatible string.
Uwe Kleine-König July 15, 2015, 7:40 a.m. UTC | #2
On Tue, Jul 14, 2015 at 10:54:42AM +0100, Mark Brown wrote:
> On Tue, Jul 14, 2015 at 11:19:56AM +0200, Uwe Kleine-König wrote:
> 
> >  static const struct of_device_id mpc512x_psc_spi_of_match[] = {
> > -	{ .compatible = "fsl,mpc5121-psc-spi", },
> > +	{ .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 },
> > +	{ .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 },
> >  	{},
> 
> The code seems fine but this should update the binding document to
> include the new compatible string.
I don't find fsl,mpc5121-psc-spi documented either. The best I found is
ocumentation/devicetree/bindings/powerpc/fsl/mpc5121-psc.txt which
describes fsl,mpc5121-psc-uart and fsl,mpc5121-psc.

Best regards
Uwe
Mark Brown July 16, 2015, 1:32 p.m. UTC | #3
On Wed, Jul 15, 2015 at 09:40:19AM +0200, Uwe Kleine-König wrote:
> On Tue, Jul 14, 2015 at 10:54:42AM +0100, Mark Brown wrote:

> > >  static const struct of_device_id mpc512x_psc_spi_of_match[] = {
> > > -	{ .compatible = "fsl,mpc5121-psc-spi", },
> > > +	{ .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 },
> > > +	{ .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 },
> > >  	{},

> > The code seems fine but this should update the binding document to
> > include the new compatible string.

> I don't find fsl,mpc5121-psc-spi documented either. The best I found is
> ocumentation/devicetree/bindings/powerpc/fsl/mpc5121-psc.txt which
> describes fsl,mpc5121-psc-uart and fsl,mpc5121-psc.

OK, then please add a basic binding document.  The point is that new
bindings should be being documented, if people have been lax on this in
the past that does involve a bit of cleanup.
diff mbox

Patch

diff --git a/arch/powerpc/include/asm/mpc52xx_psc.h b/arch/powerpc/include/asm/mpc52xx_psc.h
index d0ece257d310..04c7e8fc24c2 100644
--- a/arch/powerpc/include/asm/mpc52xx_psc.h
+++ b/arch/powerpc/include/asm/mpc52xx_psc.h
@@ -150,7 +150,10 @@ 
 
 /* Structure of the hardware registers */
 struct mpc52xx_psc {
-	u8		mode;		/* PSC + 0x00 */
+	union {
+		u8	mode;		/* PSC + 0x00 */
+		u8	mr2;
+	};
 	u8		reserved0[3];
 	union {				/* PSC + 0x04 */
 		u16	status;
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 965d2bdcfdcc..280794dd248a 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -30,11 +30,37 @@ 
 #include <linux/gpio.h>
 #include <asm/mpc52xx_psc.h>
 
+enum {
+	TYPE_MPC5121,
+	TYPE_MPC5125,
+};
+
+/*
+ * This macro abstracts the differences in the PSC register layout between
+ * MPC5121 (which uses a struct mpc52xx_psc) and MPC5125 (using mpc5125_psc).
+ */
+#define psc_addr(mps, regname) ({					\
+	void *__ret;							\
+	switch(mps->type) {						\
+	case TYPE_MPC5121: {						\
+			struct mpc52xx_psc __iomem *psc = mps->psc;	\
+			__ret = &psc->regname;				\
+		};							\
+		break;							\
+	case TYPE_MPC5125: {						\
+			struct mpc5125_psc __iomem *psc = mps->psc;	\
+			__ret = &psc->regname;				\
+		};							\
+		break;							\
+	}								\
+	__ret; })
+
 struct mpc512x_psc_spi {
 	void (*cs_control)(struct spi_device *spi, bool on);
 
 	/* driver internal data */
-	struct mpc52xx_psc __iomem *psc;
+	int type;
+	void __iomem *psc;
 	struct mpc512x_psc_fifo __iomem *fifo;
 	unsigned int irq;
 	u8 bits_per_word;
@@ -71,13 +97,12 @@  static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 {
 	struct mpc512x_psc_spi_cs *cs = spi->controller_state;
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
-	struct mpc52xx_psc __iomem *psc = mps->psc;
 	u32 sicr;
 	u32 ccr;
 	int speed;
 	u16 bclkdiv;
 
-	sicr = in_be32(&psc->sicr);
+	sicr = in_be32(psc_addr(mps, sicr));
 
 	/* Set clock phase and polarity */
 	if (spi->mode & SPI_CPHA)
@@ -94,9 +119,9 @@  static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 		sicr |= 0x10000000;
 	else
 		sicr &= ~0x10000000;
-	out_be32(&psc->sicr, sicr);
+	out_be32(psc_addr(mps, sicr), sicr);
 
-	ccr = in_be32(&psc->ccr);
+	ccr = in_be32(psc_addr(mps, ccr));
 	ccr &= 0xFF000000;
 	speed = cs->speed_hz;
 	if (!speed)
@@ -104,7 +129,7 @@  static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 	bclkdiv = (mps->mclk_rate / speed) - 1;
 
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
-	out_be32(&psc->ccr, ccr);
+	out_be32(psc_addr(mps, ccr), ccr);
 	mps->bits_per_word = cs->bits_per_word;
 
 	if (mps->cs_control && gpio_is_valid(spi->cs_gpio))
@@ -315,16 +340,15 @@  static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
 static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
 {
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
-	struct mpc52xx_psc __iomem *psc = mps->psc;
 
 	dev_dbg(&master->dev, "%s()\n", __func__);
 
 	/* Zero MR2 */
-	in_8(&psc->mode);
-	out_8(&psc->mode, 0x0);
+	in_8(psc_addr(mps, mr2));
+	out_8(psc_addr(mps, mr2), 0x0);
 
 	/* enable transmitter/receiver */
-	out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
+	out_8(psc_addr(mps, command), MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
 
 	return 0;
 }
@@ -332,13 +356,12 @@  static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
 static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master)
 {
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
-	struct mpc52xx_psc __iomem *psc = mps->psc;
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
 
 	dev_dbg(&master->dev, "%s()\n", __func__);
 
 	/* disable transmitter/receiver and fifo interrupt */
-	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+	out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
 	out_be32(&fifo->tximr, 0);
 
 	return 0;
@@ -388,7 +411,6 @@  static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
 static int mpc512x_psc_spi_port_config(struct spi_master *master,
 				       struct mpc512x_psc_spi *mps)
 {
-	struct mpc52xx_psc __iomem *psc = mps->psc;
 	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
 	u32 sicr;
 	u32 ccr;
@@ -396,12 +418,12 @@  static int mpc512x_psc_spi_port_config(struct spi_master *master,
 	u16 bclkdiv;
 
 	/* Reset the PSC into a known state */
-	out_8(&psc->command, MPC52xx_PSC_RST_RX);
-	out_8(&psc->command, MPC52xx_PSC_RST_TX);
-	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+	out_8(psc_addr(mps, command), MPC52xx_PSC_RST_RX);
+	out_8(psc_addr(mps, command), MPC52xx_PSC_RST_TX);
+	out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
 
 	/* Disable psc interrupts all useful interrupts are in fifo */
-	out_be16(&psc->isr_imr.imr, 0);
+	out_be16(psc_addr(mps, isr_imr.imr), 0);
 
 	/* Disable fifo interrupts, will be enabled later */
 	out_be32(&fifo->tximr, 0);
@@ -417,18 +439,18 @@  static int mpc512x_psc_spi_port_config(struct spi_master *master,
 		0x00004000 |	/* MSTR = 1   -- SPI master */
 		0x00000800;	/* UseEOF = 1 -- SS low until EOF */
 
-	out_be32(&psc->sicr, sicr);
+	out_be32(psc_addr(mps, sicr), sicr);
 
-	ccr = in_be32(&psc->ccr);
+	ccr = in_be32(psc_addr(mps, ccr));
 	ccr &= 0xFF000000;
 	speed = 1000000;	/* default 1MHz */
 	bclkdiv = (mps->mclk_rate / speed) - 1;
 	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
-	out_be32(&psc->ccr, ccr);
+	out_be32(psc_addr(mps, ccr), ccr);
 
 	/* Set 2ms DTL delay */
-	out_8(&psc->ctur, 0x00);
-	out_8(&psc->ctlr, 0x82);
+	out_8(psc_addr(mps, ctur), 0x00);
+	out_8(psc_addr(mps, ctlr), 0x82);
 
 	/* we don't use the alarms */
 	out_be32(&fifo->rxalarm, 0xfff);
@@ -482,6 +504,7 @@  static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 
 	dev_set_drvdata(dev, master);
 	mps = spi_master_get_devdata(master);
+	mps->type = (int)of_device_get_match_data(dev);
 	mps->irq = irq;
 
 	if (pdata == NULL) {
@@ -589,7 +612,8 @@  static int mpc512x_psc_spi_of_remove(struct platform_device *op)
 }
 
 static const struct of_device_id mpc512x_psc_spi_of_match[] = {
-	{ .compatible = "fsl,mpc5121-psc-spi", },
+	{ .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 },
+	{ .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 },
 	{},
 };