diff mbox

[RFC] spi: spi-fsl-spi: Making spi-fsl-spi partly platform-agnostic and adding a new mode for a new core

Message ID 1353576375-8560-1-git-send-email-andreas@gaisler.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Andreas Larsson Nov. 22, 2012, 9:26 a.m. UTC
I am looking into writing a driver for a core running on sparc that is mostly
but not entirely compatible with the cpu mode of spi-fsl-spi. I am thinking of
what could be the best approach for realizing this. Any comments on a preferred
approach in this situation?

These are two different approaches I see to solve the situation without too much
code duplication:

Appproach A: Extend spi-fsl-spi and spi-fsl-lib to work outside of a FSL SOC
environtment and outside powerpc. This would require ifdefs for the driver to be
able to compile and work on sparc (or other platforms) - see patch draft at the
end. Everything that has to do with cpm and sysdev/fsl_soc.h needs to be within
ifdefs. Then the core in question could be added as another "mode" in the
spi-fsl-spi driver with core specific code embedded inside spi-fsl-spi.c just as
for the other existing modes.

Approach B: Put the general and cpu mode specific functions from spi-fsl-spi in
spi-fsl-lib or in a new separate c file and use these from both spi-fsl-spi and
a new driver for the core in question. Some ifdefs would still be needed, but
most things should be able to be handled with function pointers in such a
solution. The question is where to move the general and cpu mode functions (but
not the cpm related ones that could not compile)

Of course something in between A and B could be done as well, where all
functions stay in spi-fsl-spi.c but is exported so that they can be used with a
new driver. Then most ifdefs in fsl-spi-fsl would need to be in place for
compileability though.

Of course a third option that leaves spi-fsl-* alone but results in a lot of
code duplication is:

Approach C: Submit a totally separate driver for this core (with heavy copying
and pasting from spi-fsl-* as most of the functionality is the same as the cpu
mode parts of spi-fsl-spi). A lot of ugly code duplication. The only upside
compared to approach B is that there are mode register bits for this core that
conflicts with mode register bits in other mpc8xxx cores that are not currently
in use by the driver. If those would be used in the future in spi-fsl-spi, a
separate driver would not break for this core.

Core specific things that is needed in any approach (but can be mostly isolated
from spi-fsl-* in approach B):
- Add entries to the register struct for additional registers
- Adding core-specific chipselect discovery/handling code as there might be
  built in chip select capabilities in the core.
- Add core-specific code to handle driver matching, bus numbering, getting clock
  frequency, tx/rx_shifting, and dealing with possible word-length limitations.


Below follows a draft patch on how spi-fsl-spi with friends could be made
functioning in cpu mode outside of a FSL SOC environment. Approach A pointed out
above would add the new mode on top of this for the needed core specific
things. Note the ugly define on in/out_be16/32 that would need to be done in a
proper way in a real patch. I didn't want to clutter the patch below with that
now instead showing the ifdefs clearly.

Cheers,
Andreas Larsson

---
 drivers/spi/Kconfig       |    4 ++--
 drivers/spi/spi-fsl-lib.c |   10 ++++++++++
 drivers/spi/spi-fsl-lib.h |    8 ++++++++
 drivers/spi/spi-fsl-spi.c |   32 ++++++++++++++++++++++++++++----
 4 files changed, 48 insertions(+), 6 deletions(-)

--
1.7.0.4

------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov

Comments

Andreas Larsson Dec. 4, 2012, 7:58 a.m. UTC | #1
On 2012-11-22 10:26, Andreas Larsson wrote:
> I am looking into writing a driver for a core running on sparc that is mostly
> but not entirely compatible with the cpu mode of spi-fsl-spi. I am thinking of
> what could be the best approach for realizing this. Any comments on a preferred
> approach in this situation?

Any comments on this? A fair amount of rearranging and ifdefing would be needed 
to make the spi-fsl-spi driver workable outside an fsl and powerpc environment 
so I rather get some input before before trying to perfect a solution that could 
not be acceptable into mainline.

Cheers,
Andreas

> These are two different approaches I see to solve the situation without too much
> code duplication:
>
> Appproach A: Extend spi-fsl-spi and spi-fsl-lib to work outside of a FSL SOC
> environtment and outside powerpc. This would require ifdefs for the driver to be
> able to compile and work on sparc (or other platforms) - see patch draft at the
> end. Everything that has to do with cpm and sysdev/fsl_soc.h needs to be within
> ifdefs. Then the core in question could be added as another "mode" in the
> spi-fsl-spi driver with core specific code embedded inside spi-fsl-spi.c just as
> for the other existing modes.
>
> Approach B: Put the general and cpu mode specific functions from spi-fsl-spi in
> spi-fsl-lib or in a new separate c file and use these from both spi-fsl-spi and
> a new driver for the core in question. Some ifdefs would still be needed, but
> most things should be able to be handled with function pointers in such a
> solution. The question is where to move the general and cpu mode functions (but
> not the cpm related ones that could not compile)
>
> Of course something in between A and B could be done as well, where all
> functions stay in spi-fsl-spi.c but is exported so that they can be used with a
> new driver. Then most ifdefs in fsl-spi-fsl would need to be in place for
> compileability though.
>
> Of course a third option that leaves spi-fsl-* alone but results in a lot of
> code duplication is:
>
> Approach C: Submit a totally separate driver for this core (with heavy copying
> and pasting from spi-fsl-* as most of the functionality is the same as the cpu
> mode parts of spi-fsl-spi). A lot of ugly code duplication. The only upside
> compared to approach B is that there are mode register bits for this core that
> conflicts with mode register bits in other mpc8xxx cores that are not currently
> in use by the driver. If those would be used in the future in spi-fsl-spi, a
> separate driver would not break for this core.
>
> Core specific things that is needed in any approach (but can be mostly isolated
> from spi-fsl-* in approach B):
> - Add entries to the register struct for additional registers
> - Adding core-specific chipselect discovery/handling code as there might be
>    built in chip select capabilities in the core.
> - Add core-specific code to handle driver matching, bus numbering, getting clock
>    frequency, tx/rx_shifting, and dealing with possible word-length limitations.
>
>
> Below follows a draft patch on how spi-fsl-spi with friends could be made
> functioning in cpu mode outside of a FSL SOC environment. Approach A pointed out
> above would add the new mode on top of this for the needed core specific
> things. Note the ugly define on in/out_be16/32 that would need to be done in a
> proper way in a real patch. I didn't want to clutter the patch below with that
> now instead showing the ifdefs clearly.
>
> Cheers,
> Andreas Larsson
>
> ---
>   drivers/spi/Kconfig       |    4 ++--
>   drivers/spi/spi-fsl-lib.c |   10 ++++++++++
>   drivers/spi/spi-fsl-lib.h |    8 ++++++++
>   drivers/spi/spi-fsl-spi.c |   32 ++++++++++++++++++++++++++++----
>   4 files changed, 48 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 5b017af..8fbd698 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -218,11 +218,11 @@ config SPI_MPC512x_PSC
>
>   config SPI_FSL_LIB
>   	tristate
> -	depends on FSL_SOC
> +	depends on OF
>
>   config SPI_FSL_SPI
>   	bool "Freescale SPI controller"
> -	depends on FSL_SOC
> +	depends on OF
>   	select SPI_FSL_LIB
>   	help
>   	  This enables using the Freescale SPI controllers in master mode.
> diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c
> index 1503574..0c9021d 100644
> --- a/drivers/spi/spi-fsl-lib.c
> +++ b/drivers/spi/spi-fsl-lib.c
> @@ -23,7 +23,9 @@
>   #include <linux/mm.h>
>   #include <linux/of_platform.h>
>   #include <linux/spi/spi.h>
> +#ifdef CONFIG_FSL_SOC
>   #include <sysdev/fsl_soc.h>
> +#endif
>
>   #include "spi-fsl-lib.h"
>
> @@ -208,6 +210,7 @@ int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev)
>   	/* Allocate bus num dynamically. */
>   	pdata->bus_num = -1;
>
> +#ifdef CONFIG_FSL_SOC
>   	/* SPI controller is either clocked from QE or SoC clock. */
>   	pdata->sysclk = get_brgfreq();
>   	if (pdata->sysclk == -1) {
> @@ -217,16 +220,23 @@ int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev)
>   			goto err;
>   		}
>   	}
> +#else
> +	ret = of_property_read_u32(np, "clock-frequency", &pdata->sysclk);
> +	if (ret)
> +		goto err;
> +#endif
>
>   	prop = of_get_property(np, "mode", NULL);
>   	if (prop && !strcmp(prop, "cpu-qe"))
>   		pdata->flags = SPI_QE_CPU_MODE;
> +#ifdef CONFIG_FSL_SOC
>   	else if (prop && !strcmp(prop, "qe"))
>   		pdata->flags = SPI_CPM_MODE | SPI_QE;
>   	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
>   		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
>   	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
>   		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
> +#endif
>
>   	return 0;
>
> diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h
> index cbe881b..cd85170 100644
> --- a/drivers/spi/spi-fsl-lib.h
> +++ b/drivers/spi/spi-fsl-lib.h
> @@ -20,6 +20,12 @@
>
>   #include <asm/io.h>
>
> +/* Inline replacement or something like that in a real patch */
> +#define out_be32(reg, val) iowrite32be((val), (reg))
> +#define out_be16(reg, val) iowrite16be((val), (reg))
> +#define in_be32(reg) ioread32be((reg))
> +#define in_be16(reg) ioread16be((reg))
> +
>   /* SPI/eSPI Controller driver's private data. */
>   struct mpc8xxx_spi {
>   	struct device *dev;
> @@ -34,8 +40,10 @@ struct mpc8xxx_spi {
>
>   	int subblock;
>   	struct spi_pram __iomem *pram;
> +#ifdef CONFIG_FSL_SOC
>   	struct cpm_buf_desc __iomem *tx_bd;
>   	struct cpm_buf_desc __iomem *rx_bd;
> +#endif
>
>   	struct spi_transfer *xfer_in_progress;
>
> diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
> index 6a62934..f459416 100644
> --- a/drivers/spi/spi-fsl-spi.c
> +++ b/drivers/spi/spi-fsl-spi.c
> @@ -30,15 +30,20 @@
>   #include <linux/mutex.h>
>   #include <linux/of.h>
>   #include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
>   #include <linux/gpio.h>
>   #include <linux/of_gpio.h>
>
> +#ifdef CONFIG_FSL_SOC
>   #include <sysdev/fsl_soc.h>
>   #include <asm/cpm.h>
>   #include <asm/qe.h>
> +#endif
>
>   #include "spi-fsl-lib.h"
>
> +#ifdef CONFIG_FSL_SOC
>   /* CPM1 and CPM2 are mutually exclusive. */
>   #ifdef CONFIG_CPM1
>   #include <asm/cpm1.h>
> @@ -47,6 +52,7 @@
>   #include <asm/cpm2.h>
>   #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
>   #endif
> +#endif
>
>   /* SPI Controller registers */
>   struct fsl_spi_reg {
> @@ -96,9 +102,11 @@ struct fsl_spi_reg {
>   #define	SPI_PRAM_SIZE	0x100
>   #define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
>
> +#ifdef CONFIG_FSL_SOC
>   static void *fsl_dummy_rx;
>   static DEFINE_MUTEX(fsl_dummy_rx_lock);
>   static int fsl_dummy_rx_refcnt;
> +#endif
>
>   static void fsl_spi_change_mode(struct spi_device *spi)
>   {
> @@ -117,6 +125,7 @@ static void fsl_spi_change_mode(struct spi_device *spi)
>   	/* Turn off SPI unit prior changing mode */
>   	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
>
> +#ifdef CONFIG_FSL_SOC
>   	/* When in CPM mode, we need to reinit tx and rx. */
>   	if (mspi->flags & SPI_CPM_MODE) {
>   		if (mspi->flags & SPI_QE) {
> @@ -132,6 +141,7 @@ static void fsl_spi_change_mode(struct spi_device *spi)
>   			}
>   		}
>   	}
> +#endif
>   	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
>   	local_irq_restore(flags);
>   }
> @@ -295,6 +305,7 @@ static int fsl_spi_setup_transfer(struct spi_device *spi,
>   	return 0;
>   }
>
> +#ifdef CONFIG_FSL_SOC
>   static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
>   {
>   	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
> @@ -323,6 +334,9 @@ static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
>   	/* start transfer */
>   	mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
>   }
> +#else
> +static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) { }
> +#endif
>
>   static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
>   				struct spi_transfer *t, bool is_dma_mapped)
> @@ -568,6 +582,7 @@ static int fsl_spi_setup(struct spi_device *spi)
>   	return 0;
>   }
>
> +#ifdef CONFIG_FSL_SOC
>   static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
>   {
>   	u16 len;
> @@ -591,6 +606,9 @@ static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
>   	else
>   		complete(&mspi->done);
>   }
> +#else
> +static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) { }
> +#endif
>
>   static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
>   {
> @@ -646,6 +664,7 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
>   	return ret;
>   }
>
> +#ifdef CONFIG_FSL_SOC
>   static void *fsl_spi_alloc_dummy_rx(void)
>   {
>   	mutex_lock(&fsl_dummy_rx_lock);
> @@ -836,6 +855,10 @@ static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
>   	cpm_muram_free(cpm_muram_offset(mspi->pram));
>   	fsl_spi_free_dummy_rx();
>   }
> +#else
> +static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) { return -EINVAL; }
> +static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) { }
> +#endif
>
>   static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
>   {
> @@ -1047,7 +1070,7 @@ static int __devinit of_fsl_spi_probe(struct platform_device *ofdev)
>   	struct device_node *np = ofdev->dev.of_node;
>   	struct spi_master *master;
>   	struct resource mem;
> -	struct resource irq;
> +	int irq;
>   	int ret = -ENOMEM;
>
>   	ret = of_mpc8xxx_spi_probe(ofdev);
> @@ -1062,13 +1085,14 @@ static int __devinit of_fsl_spi_probe(struct platform_device *ofdev)
>   	if (ret)
>   		goto err;
>
> -	ret = of_irq_to_resource(np, 0, &irq);
> -	if (!ret) {
> +	irq = irq_of_parse_and_map(np, 0);
> +	if (!irq) {
> +		dev_err(&ofdev->dev, "Could not get irq\n");
>   		ret = -EINVAL;
>   		goto err;
>   	}
>
> -	master = fsl_spi_probe(dev, &mem, irq.start);
> +	master = fsl_spi_probe(dev, &mem, irq);
>   	if (IS_ERR(master)) {
>   		ret = PTR_ERR(master);
>   		goto err;
> --
> 1.7.0.4
>
> ------------------------------------------------------------------------------
> Monitor your physical, virtual and cloud infrastructure from a single
> web console. Get in-depth insight into apps, servers, databases, vmware,
> SAP, cloud infrastructure, etc. Download 30-day Free Trial.
> Pricing starts from $795 for 25 servers or applications!
> http://p.sf.net/sfu/zoho_dev2dev_nov
> _______________________________________________
> spi-devel-general mailing list
> spi-devel-general@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/spi-devel-general
>


------------------------------------------------------------------------------
LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
Remotely access PCs and mobile devices and provide instant support
Improve your efficiency, and focus on delivering more value-add services
Discover what IT Professionals Know. Rescue delivers
http://p.sf.net/sfu/logmein_12329d2d
Joakim Tjernlund Dec. 4, 2012, 9:11 a.m. UTC | #2
Andreas Larsson <andreas@gaisler.com> wrote on 2012/12/04 08:58:50:
> 
> On 2012-11-22 10:26, Andreas Larsson wrote:
> > I am looking into writing a driver for a core running on sparc that is 
mostly
> > but not entirely compatible with the cpu mode of spi-fsl-spi. I am 
thinking of
> > what could be the best approach for realizing this. Any comments on a 
preferred
> > approach in this situation?
> 
> Any comments on this? A fair amount of rearranging and ifdefing would be 
needed 
> to make the spi-fsl-spi driver workable outside an fsl and powerpc 
environment 
> so I rather get some input before before trying to perfect a solution 
that could 
> not be acceptable into mainline.

I am far from kernel devlopment ATM but I do have one comment, how to
ensure this new combined driver doesn't break on existing powerpc
systems?

 Jocke

> 
> Cheers,
> Andreas
> 
> > These are two different approaches I see to solve the situation 
without too much
> > code duplication:
> >
> > Appproach A: Extend spi-fsl-spi and spi-fsl-lib to work outside of a 
FSL SOC
> > environtment and outside powerpc. This would require ifdefs for the 
driver to be
> > able to compile and work on sparc (or other platforms) - see patch 
draft at the
> > end. Everything that has to do with cpm and sysdev/fsl_soc.h needs to 
be within
> > ifdefs. Then the core in question could be added as another "mode" in 
the
> > spi-fsl-spi driver with core specific code embedded inside 
spi-fsl-spi.c just as
> > for the other existing modes.
> >
> > Approach B: Put the general and cpu mode specific functions from 
spi-fsl-spi in
> > spi-fsl-lib or in a new separate c file and use these from both 
spi-fsl-spi and
> > a new driver for the core in question. Some ifdefs would still be 
needed, but
> > most things should be able to be handled with function pointers in 
such a
> > solution. The question is where to move the general and cpu mode 
functions (but
> > not the cpm related ones that could not compile)
> >
> > Of course something in between A and B could be done as well, where 
all
> > functions stay in spi-fsl-spi.c but is exported so that they can be 
used with a
> > new driver. Then most ifdefs in fsl-spi-fsl would need to be in place 
for
> > compileability though.
> >
> > Of course a third option that leaves spi-fsl-* alone but results in a 
lot of
> > code duplication is:
> >
> > Approach C: Submit a totally separate driver for this core (with heavy 
copying
> > and pasting from spi-fsl-* as most of the functionality is the same as 
the cpu
> > mode parts of spi-fsl-spi). A lot of ugly code duplication. The only 
upside
> > compared to approach B is that there are mode register bits for this 
core that
> > conflicts with mode register bits in other mpc8xxx cores that are not 
currently
> > in use by the driver. If those would be used in the future in 
spi-fsl-spi, a
> > separate driver would not break for this core.
> >
> > Core specific things that is needed in any approach (but can be mostly 
isolated
> > from spi-fsl-* in approach B):
> > - Add entries to the register struct for additional registers
> > - Adding core-specific chipselect discovery/handling code as there 
might be
> >    built in chip select capabilities in the core.
> > - Add core-specific code to handle driver matching, bus numbering, 
getting clock
> >    frequency, tx/rx_shifting, and dealing with possible word-length 
limitations.
> >
> >
> > Below follows a draft patch on how spi-fsl-spi with friends could be 
made
> > functioning in cpu mode outside of a FSL SOC environment. Approach A 
pointed out
> > above would add the new mode on top of this for the needed core 
specific
> > things. Note the ugly define on in/out_be16/32 that would need to be 
done in a
> > proper way in a real patch. I didn't want to clutter the patch below 
with that
> > now instead showing the ifdefs clearly.
> >
> > Cheers,
> > Andreas Larsson
> >
> > ---
> >   drivers/spi/Kconfig       |    4 ++--
> >   drivers/spi/spi-fsl-lib.c |   10 ++++++++++
> >   drivers/spi/spi-fsl-lib.h |    8 ++++++++
> >   drivers/spi/spi-fsl-spi.c |   32 ++++++++++++++++++++++++++++----
> >   4 files changed, 48 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> > index 5b017af..8fbd698 100644
> > --- a/drivers/spi/Kconfig
> > +++ b/drivers/spi/Kconfig
> > @@ -218,11 +218,11 @@ config SPI_MPC512x_PSC
> >
> >   config SPI_FSL_LIB
> >      tristate
> > -   depends on FSL_SOC
> > +   depends on OF
> >
> >   config SPI_FSL_SPI
> >      bool "Freescale SPI controller"
> > -   depends on FSL_SOC
> > +   depends on OF
> >      select SPI_FSL_LIB
> >      help
> >        This enables using the Freescale SPI controllers in master 
mode.
> > diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c
> > index 1503574..0c9021d 100644
> > --- a/drivers/spi/spi-fsl-lib.c
> > +++ b/drivers/spi/spi-fsl-lib.c
> > @@ -23,7 +23,9 @@
> >   #include <linux/mm.h>
> >   #include <linux/of_platform.h>
> >   #include <linux/spi/spi.h>
> > +#ifdef CONFIG_FSL_SOC
> >   #include <sysdev/fsl_soc.h>
> > +#endif
> >
> >   #include "spi-fsl-lib.h"
> >
> > @@ -208,6 +210,7 @@ int __devinit of_mpc8xxx_spi_probe(struct 
platform_device *ofdev)
> >      /* Allocate bus num dynamically. */
> >      pdata->bus_num = -1;
> >
> > +#ifdef CONFIG_FSL_SOC
> >      /* SPI controller is either clocked from QE or SoC clock. */
> >      pdata->sysclk = get_brgfreq();
> >      if (pdata->sysclk == -1) {
> > @@ -217,16 +220,23 @@ int __devinit of_mpc8xxx_spi_probe(struct 
> platform_device *ofdev)
> >            goto err;
> >         }
> >      }
> > +#else
> > +   ret = of_property_read_u32(np, "clock-frequency", &pdata->sysclk);
> > +   if (ret)
> > +      goto err;
> > +#endif
> >
> >      prop = of_get_property(np, "mode", NULL);
> >      if (prop && !strcmp(prop, "cpu-qe"))
> >         pdata->flags = SPI_QE_CPU_MODE;
> > +#ifdef CONFIG_FSL_SOC
> >      else if (prop && !strcmp(prop, "qe"))
> >         pdata->flags = SPI_CPM_MODE | SPI_QE;
> >      else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
> >         pdata->flags = SPI_CPM_MODE | SPI_CPM2;
> >      else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
> >         pdata->flags = SPI_CPM_MODE | SPI_CPM1;
> > +#endif
> >
> >      return 0;
> >
> > diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h
> > index cbe881b..cd85170 100644
> > --- a/drivers/spi/spi-fsl-lib.h
> > +++ b/drivers/spi/spi-fsl-lib.h
> > @@ -20,6 +20,12 @@
> >
> >   #include <asm/io.h>
> >
> > +/* Inline replacement or something like that in a real patch */
> > +#define out_be32(reg, val) iowrite32be((val), (reg))
> > +#define out_be16(reg, val) iowrite16be((val), (reg))
> > +#define in_be32(reg) ioread32be((reg))
> > +#define in_be16(reg) ioread16be((reg))
> > +
> >   /* SPI/eSPI Controller driver's private data. */
> >   struct mpc8xxx_spi {
> >      struct device *dev;
> > @@ -34,8 +40,10 @@ struct mpc8xxx_spi {
> >
> >      int subblock;
> >      struct spi_pram __iomem *pram;
> > +#ifdef CONFIG_FSL_SOC
> >      struct cpm_buf_desc __iomem *tx_bd;
> >      struct cpm_buf_desc __iomem *rx_bd;
> > +#endif
> >
> >      struct spi_transfer *xfer_in_progress;
> >
> > diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
> > index 6a62934..f459416 100644
> > --- a/drivers/spi/spi-fsl-spi.c
> > +++ b/drivers/spi/spi-fsl-spi.c
> > @@ -30,15 +30,20 @@
> >   #include <linux/mutex.h>
> >   #include <linux/of.h>
> >   #include <linux/of_platform.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_irq.h>
> >   #include <linux/gpio.h>
> >   #include <linux/of_gpio.h>
> >
> > +#ifdef CONFIG_FSL_SOC
> >   #include <sysdev/fsl_soc.h>
> >   #include <asm/cpm.h>
> >   #include <asm/qe.h>
> > +#endif
> >
> >   #include "spi-fsl-lib.h"
> >
> > +#ifdef CONFIG_FSL_SOC
> >   /* CPM1 and CPM2 are mutually exclusive. */
> >   #ifdef CONFIG_CPM1
> >   #include <asm/cpm1.h>
> > @@ -47,6 +52,7 @@
> >   #include <asm/cpm2.h>
> >   #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 
0)
> >   #endif
> > +#endif
> >
> >   /* SPI Controller registers */
> >   struct fsl_spi_reg {
> > @@ -96,9 +102,11 @@ struct fsl_spi_reg {
> >   #define   SPI_PRAM_SIZE   0x100
> >   #define   SPI_MRBLR   ((unsigned int)PAGE_SIZE)
> >
> > +#ifdef CONFIG_FSL_SOC
> >   static void *fsl_dummy_rx;
> >   static DEFINE_MUTEX(fsl_dummy_rx_lock);
> >   static int fsl_dummy_rx_refcnt;
> > +#endif
> >
> >   static void fsl_spi_change_mode(struct spi_device *spi)
> >   {
> > @@ -117,6 +125,7 @@ static void fsl_spi_change_mode(struct spi_device 
*spi)
> >      /* Turn off SPI unit prior changing mode */
> >      mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
> >
> > +#ifdef CONFIG_FSL_SOC
> >      /* When in CPM mode, we need to reinit tx and rx. */
> >      if (mspi->flags & SPI_CPM_MODE) {
> >         if (mspi->flags & SPI_QE) {
> > @@ -132,6 +141,7 @@ static void fsl_spi_change_mode(struct spi_device 
*spi)
> >            }
> >         }
> >      }
> > +#endif
> >      mpc8xxx_spi_write_reg(mode, cs->hw_mode);
> >      local_irq_restore(flags);
> >   }
> > @@ -295,6 +305,7 @@ static int fsl_spi_setup_transfer(struct 
spi_device *spi,
> >      return 0;
> >   }
> >
> > +#ifdef CONFIG_FSL_SOC
> >   static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
> >   {
> >      struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
> > @@ -323,6 +334,9 @@ static void fsl_spi_cpm_bufs_start(struct 
mpc8xxx_spi *mspi)
> >      /* start transfer */
> >      mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
> >   }
> > +#else
> > +static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) { }
> > +#endif
> >
> >   static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
> >               struct spi_transfer *t, bool is_dma_mapped)
> > @@ -568,6 +582,7 @@ static int fsl_spi_setup(struct spi_device *spi)
> >      return 0;
> >   }
> >
> > +#ifdef CONFIG_FSL_SOC
> >   static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
> >   {
> >      u16 len;
> > @@ -591,6 +606,9 @@ static void fsl_spi_cpm_irq(struct mpc8xxx_spi 
*mspi, u32 events)
> >      else
> >         complete(&mspi->done);
> >   }
> > +#else
> > +static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) { }
> > +#endif
> >
> >   static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
> >   {
> > @@ -646,6 +664,7 @@ static irqreturn_t fsl_spi_irq(s32 irq, void 
*context_data)
> >      return ret;
> >   }
> >
> > +#ifdef CONFIG_FSL_SOC
> >   static void *fsl_spi_alloc_dummy_rx(void)
> >   {
> >      mutex_lock(&fsl_dummy_rx_lock);
> > @@ -836,6 +855,10 @@ static void fsl_spi_cpm_free(struct mpc8xxx_spi 
*mspi)
> >      cpm_muram_free(cpm_muram_offset(mspi->pram));
> >      fsl_spi_free_dummy_rx();
> >   }
> > +#else
> > +static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) { return 
-EINVAL; }
> > +static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) { }
> > +#endif
> >
> >   static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
> >   {
> > @@ -1047,7 +1070,7 @@ static int __devinit of_fsl_spi_probe(struct 
> platform_device *ofdev)
> >      struct device_node *np = ofdev->dev.of_node;
> >      struct spi_master *master;
> >      struct resource mem;
> > -   struct resource irq;
> > +   int irq;
> >      int ret = -ENOMEM;
> >
> >      ret = of_mpc8xxx_spi_probe(ofdev);
> > @@ -1062,13 +1085,14 @@ static int __devinit of_fsl_spi_probe(struct 
> platform_device *ofdev)
> >      if (ret)
> >         goto err;
> >
> > -   ret = of_irq_to_resource(np, 0, &irq);
> > -   if (!ret) {
> > +   irq = irq_of_parse_and_map(np, 0);
> > +   if (!irq) {
> > +      dev_err(&ofdev->dev, "Could not get irq\n");
> >         ret = -EINVAL;
> >         goto err;
> >      }
> >
> > -   master = fsl_spi_probe(dev, &mem, irq.start);
> > +   master = fsl_spi_probe(dev, &mem, irq);
> >      if (IS_ERR(master)) {
> >         ret = PTR_ERR(master);
> >         goto err;
> > --
> > 1.7.0.4
> >
> > 
------------------------------------------------------------------------------
> > Monitor your physical, virtual and cloud infrastructure from a single
> > web console. Get in-depth insight into apps, servers, databases, 
vmware,
> > SAP, cloud infrastructure, etc. Download 30-day Free Trial.
> > Pricing starts from $795 for 25 servers or applications!
> > http://p.sf.net/sfu/zoho_dev2dev_nov
> > _______________________________________________
> > spi-devel-general mailing list
> > spi-devel-general@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/spi-devel-general
> >
> 


------------------------------------------------------------------------------
LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
Remotely access PCs and mobile devices and provide instant support
Improve your efficiency, and focus on delivering more value-add services
Discover what IT Professionals Know. Rescue delivers
http://p.sf.net/sfu/logmein_12329d2d
Andreas Larsson Dec. 4, 2012, 10:07 a.m. UTC | #3
On 2012-12-04 10:11, Joakim Tjernlund wrote:
> Andreas Larsson <andreas@gaisler.com> wrote on 2012/12/04 08:58:50:
>> Any comments on this? A fair amount of rearranging and ifdefing would
>> be needed to make the spi-fsl-spi driver workable outside an fsl and
>> powerpc environment so I rather get some input before before trying
>> to perfect a solution that could not be acceptable into mainline.
>
> I am far from kernel devlopment ATM but I do have one comment, how to
> ensure this new combined driver doesn't break on existing powerpc
> systems?

Of course it would be preferable if the future patch would be tested on 
the original system to be sure nothing breaks.

Taking the "do everything inside the existing driver" approach could 
limit the risk of breaking anything by not moving things around. To get 
the driver to work outside an fsl environment ifdefs can be added in a 
way that the code would essentially be the same running on the original 
systems. Then, new branches that will never be taken on the original 
boards can handle the newly added mode.

This might not produce the most elegant code in the end though. The 
easiest way to make sure that nothing is broken is of course if I submit 
a completely separate driver, the downside being the duplicate 
code/functionality.

Cheers,
Andreas

------------------------------------------------------------------------------
LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
Remotely access PCs and mobile devices and provide instant support
Improve your efficiency, and focus on delivering more value-add services
Discover what IT Professionals Know. Rescue delivers
http://p.sf.net/sfu/logmein_12329d2d
Grant Likely Dec. 6, 2012, 2:27 p.m. UTC | #4
On Thu, 22 Nov 2012 10:26:15 +0100, Andreas Larsson <andreas@gaisler.com> wrote:
> I am looking into writing a driver for a core running on sparc that is mostly
> but not entirely compatible with the cpu mode of spi-fsl-spi. I am thinking of
> what could be the best approach for realizing this. Any comments on a preferred
> approach in this situation?
> 
> These are two different approaches I see to solve the situation without too much
> code duplication:
> 
> Appproach A: Extend spi-fsl-spi and spi-fsl-lib to work outside of a FSL SOC
> environtment and outside powerpc. This would require ifdefs for the driver to be
> able to compile and work on sparc (or other platforms) - see patch draft at the
> end. Everything that has to do with cpm and sysdev/fsl_soc.h needs to be within
> ifdefs. Then the core in question could be added as another "mode" in the
> spi-fsl-spi driver with core specific code embedded inside spi-fsl-spi.c just as
> for the other existing modes.

>From what you've shown, I would support this approach.  The proof is in
what the final patch looks like though.

g.


------------------------------------------------------------------------------
LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
Remotely access PCs and mobile devices and provide instant support
Improve your efficiency, and focus on delivering more value-add services
Discover what IT Professionals Know. Rescue delivers
http://p.sf.net/sfu/logmein_12329d2d
diff mbox

Patch

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5b017af..8fbd698 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -218,11 +218,11 @@  config SPI_MPC512x_PSC

 config SPI_FSL_LIB
 	tristate
-	depends on FSL_SOC
+	depends on OF

 config SPI_FSL_SPI
 	bool "Freescale SPI controller"
-	depends on FSL_SOC
+	depends on OF
 	select SPI_FSL_LIB
 	help
 	  This enables using the Freescale SPI controllers in master mode.
diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c
index 1503574..0c9021d 100644
--- a/drivers/spi/spi-fsl-lib.c
+++ b/drivers/spi/spi-fsl-lib.c
@@ -23,7 +23,9 @@ 
 #include <linux/mm.h>
 #include <linux/of_platform.h>
 #include <linux/spi/spi.h>
+#ifdef CONFIG_FSL_SOC
 #include <sysdev/fsl_soc.h>
+#endif

 #include "spi-fsl-lib.h"

@@ -208,6 +210,7 @@  int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev)
 	/* Allocate bus num dynamically. */
 	pdata->bus_num = -1;

+#ifdef CONFIG_FSL_SOC
 	/* SPI controller is either clocked from QE or SoC clock. */
 	pdata->sysclk = get_brgfreq();
 	if (pdata->sysclk == -1) {
@@ -217,16 +220,23 @@  int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev)
 			goto err;
 		}
 	}
+#else
+	ret = of_property_read_u32(np, "clock-frequency", &pdata->sysclk);
+	if (ret)
+		goto err;
+#endif

 	prop = of_get_property(np, "mode", NULL);
 	if (prop && !strcmp(prop, "cpu-qe"))
 		pdata->flags = SPI_QE_CPU_MODE;
+#ifdef CONFIG_FSL_SOC
 	else if (prop && !strcmp(prop, "qe"))
 		pdata->flags = SPI_CPM_MODE | SPI_QE;
 	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
 		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
 	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
 		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
+#endif

 	return 0;

diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h
index cbe881b..cd85170 100644
--- a/drivers/spi/spi-fsl-lib.h
+++ b/drivers/spi/spi-fsl-lib.h
@@ -20,6 +20,12 @@ 

 #include <asm/io.h>

+/* Inline replacement or something like that in a real patch */
+#define out_be32(reg, val) iowrite32be((val), (reg))
+#define out_be16(reg, val) iowrite16be((val), (reg))
+#define in_be32(reg) ioread32be((reg))
+#define in_be16(reg) ioread16be((reg))
+
 /* SPI/eSPI Controller driver's private data. */
 struct mpc8xxx_spi {
 	struct device *dev;
@@ -34,8 +40,10 @@  struct mpc8xxx_spi {

 	int subblock;
 	struct spi_pram __iomem *pram;
+#ifdef CONFIG_FSL_SOC
 	struct cpm_buf_desc __iomem *tx_bd;
 	struct cpm_buf_desc __iomem *rx_bd;
+#endif

 	struct spi_transfer *xfer_in_progress;

diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 6a62934..f459416 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -30,15 +30,20 @@ 
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>

+#ifdef CONFIG_FSL_SOC
 #include <sysdev/fsl_soc.h>
 #include <asm/cpm.h>
 #include <asm/qe.h>
+#endif

 #include "spi-fsl-lib.h"

+#ifdef CONFIG_FSL_SOC
 /* CPM1 and CPM2 are mutually exclusive. */
 #ifdef CONFIG_CPM1
 #include <asm/cpm1.h>
@@ -47,6 +52,7 @@ 
 #include <asm/cpm2.h>
 #define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
 #endif
+#endif

 /* SPI Controller registers */
 struct fsl_spi_reg {
@@ -96,9 +102,11 @@  struct fsl_spi_reg {
 #define	SPI_PRAM_SIZE	0x100
 #define	SPI_MRBLR	((unsigned int)PAGE_SIZE)

+#ifdef CONFIG_FSL_SOC
 static void *fsl_dummy_rx;
 static DEFINE_MUTEX(fsl_dummy_rx_lock);
 static int fsl_dummy_rx_refcnt;
+#endif

 static void fsl_spi_change_mode(struct spi_device *spi)
 {
@@ -117,6 +125,7 @@  static void fsl_spi_change_mode(struct spi_device *spi)
 	/* Turn off SPI unit prior changing mode */
 	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);

+#ifdef CONFIG_FSL_SOC
 	/* When in CPM mode, we need to reinit tx and rx. */
 	if (mspi->flags & SPI_CPM_MODE) {
 		if (mspi->flags & SPI_QE) {
@@ -132,6 +141,7 @@  static void fsl_spi_change_mode(struct spi_device *spi)
 			}
 		}
 	}
+#endif
 	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
 	local_irq_restore(flags);
 }
@@ -295,6 +305,7 @@  static int fsl_spi_setup_transfer(struct spi_device *spi,
 	return 0;
 }

+#ifdef CONFIG_FSL_SOC
 static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
 {
 	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
@@ -323,6 +334,9 @@  static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
 	/* start transfer */
 	mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
 }
+#else
+static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) { }
+#endif

 static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
 				struct spi_transfer *t, bool is_dma_mapped)
@@ -568,6 +582,7 @@  static int fsl_spi_setup(struct spi_device *spi)
 	return 0;
 }

+#ifdef CONFIG_FSL_SOC
 static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
 {
 	u16 len;
@@ -591,6 +606,9 @@  static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
 	else
 		complete(&mspi->done);
 }
+#else
+static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) { }
+#endif

 static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
 {
@@ -646,6 +664,7 @@  static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
 	return ret;
 }

+#ifdef CONFIG_FSL_SOC
 static void *fsl_spi_alloc_dummy_rx(void)
 {
 	mutex_lock(&fsl_dummy_rx_lock);
@@ -836,6 +855,10 @@  static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
 	cpm_muram_free(cpm_muram_offset(mspi->pram));
 	fsl_spi_free_dummy_rx();
 }
+#else
+static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) { return -EINVAL; }
+static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) { }
+#endif

 static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
 {
@@ -1047,7 +1070,7 @@  static int __devinit of_fsl_spi_probe(struct platform_device *ofdev)
 	struct device_node *np = ofdev->dev.of_node;
 	struct spi_master *master;
 	struct resource mem;
-	struct resource irq;
+	int irq;
 	int ret = -ENOMEM;

 	ret = of_mpc8xxx_spi_probe(ofdev);
@@ -1062,13 +1085,14 @@  static int __devinit of_fsl_spi_probe(struct platform_device *ofdev)
 	if (ret)
 		goto err;

-	ret = of_irq_to_resource(np, 0, &irq);
-	if (!ret) {
+	irq = irq_of_parse_and_map(np, 0);
+	if (!irq) {
+		dev_err(&ofdev->dev, "Could not get irq\n");
 		ret = -EINVAL;
 		goto err;
 	}

-	master = fsl_spi_probe(dev, &mem, irq.start);
+	master = fsl_spi_probe(dev, &mem, irq);
 	if (IS_ERR(master)) {
 		ret = PTR_ERR(master);
 		goto err;