[PATCH 2/6] eSPI: add eSPI controller support

Hu Mingkai-B21284 B21284 at freescale.com
Mon Jul 26 17:02:08 EST 2010


 

> -----Original Message-----
> From: Grant Likely [mailto:glikely at secretlab.ca] On Behalf Of 
> Grant Likely
> Sent: Monday, July 26, 2010 8:25 AM
> To: Hu Mingkai-B21284
> Cc: linuxppc-dev at ozlabs.org; galak at kernel.crashing.org; Zang 
> Roy-R61911
> Subject: Re: [PATCH 2/6] eSPI: add eSPI controller support
> 
> > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 
> > cd564e2..c647a00 100644
> > --- a/drivers/spi/Kconfig
> > +++ b/drivers/spi/Kconfig
> > @@ -196,6 +196,13 @@ config SPI_FSL_SPI
> >  	help
> >  	  This enables using the Freescale SPI controllers in 
> master mode.
> >  
> > +config SPI_FSL_ESPI
> > +	tristate "Freescale eSPI controller"
> > +	depends on FSL_SOC
> > +	select SPI_MPC8xxx
> > +	help
> > +	  This enables using the Freescale eSPI controllers in 
> master mode.
> > +
> 
> Ditto from last patch.  config SPI_MPC8xxx_SPI
> 

Ok.

> >  config SPI_OMAP_UWIRE
> >  	tristate "OMAP1 MicroWire"
> >  	depends on ARCH_OMAP1
> > diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 
> > dca9fea..6af459b 100644
> > --- a/drivers/spi/Makefile
> > +++ b/drivers/spi/Makefile
> > @@ -36,6 +36,7 @@ obj-$(CONFIG_SPI_MPC52xx_PSC)		
> += mpc52xx_psc_spi.o
> >  obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
> >  obj-$(CONFIG_SPI_MPC8xxx)		+= spi_mpc8xxx.o
> >  obj-$(CONFIG_SPI_FSL_SPI)		+= fsl_spi.o
> > +obj-$(CONFIG_SPI_FSL_ESPI)		+= fsl_espi.o
> 
> spi_mpc8xxx_espi.o
> 

Ok.

> >  obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
> >  obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
> >  obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx_hw.o
> > diff --git a/drivers/spi/fsl_espi.c 
> b/drivers/spi/fsl_espi.c new file 
> > mode 100644 index 0000000..ac70c8c
> > --- /dev/null
> > +++ b/drivers/spi/fsl_espi.c
> > @@ -0,0 +1,562 @@
> > +/*
> > + * MPC8xxx eSPI controller driver.
> > + *
> > + * Copyright 2010 Freescale Semiconductor, Inc.
> > + *
> > + * This program is free software; you can redistribute  it and/or 
> > +modify it
> > + * under  the terms of  the GNU General  Public License as 
> published 
> > +by the
> > + * Free Software Foundation;  either version 2 of the  License, or 
> > +(at your
> > + * option) any later version.
> > + */
> > +#include <linux/module.h>
> > +#include <linux/delay.h>
> > +#include <linux/irq.h>
> > +#include <linux/spi/spi.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/fsl_devices.h>
> > +#include <linux/mm.h>
> > +#include <linux/of.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/of_spi.h>
> > +#include <sysdev/fsl_soc.h>
> > +
> > +#include "spi_mpc8xxx.h"
> > +
> > +/* eSPI Controller mode register definitions */
> > +#define SPMODE_ENABLE		(1 << 31)
> > +#define SPMODE_LOOP		(1 << 30)
> > +#define SPMODE_TXTHR(x)		((x) << 8)
> > +#define SPMODE_RXTHR(x)		((x) << 0)
> > +
> > +/* eSPI Controller CS mode register definitions */
> > +#define CSMODE_CI_INACTIVEHIGH	(1 << 31)
> > +#define CSMODE_CP_BEGIN_EDGECLK	(1 << 30)
> > +#define CSMODE_REV		(1 << 29)
> > +#define CSMODE_DIV16		(1 << 28)
> > +#define CSMODE_PM(x)		((x) << 24)
> > +#define CSMODE_POL_1		(1 << 20)
> > +#define CSMODE_LEN(x)		((x) << 16)
> > +#define CSMODE_BEF(x)		((x) << 12)
> > +#define CSMODE_AFT(x)		((x) << 8)
> > +#define CSMODE_CG(x)		((x) << 3)
> > +
> > +/* Default mode/csmode for eSPI controller */ #define 
> SPMODE_INIT_VAL 
> > +(SPMODE_TXTHR(4) | SPMODE_RXTHR(3)) #define CSMODE_INIT_VAL 
> > +(CSMODE_POL_1 | CSMODE_BEF(0) \
> > +			| CSMODE_AFT(0) | CSMODE_CG(1))
> > +
> > +/* SPIE register values */
> > +#define	SPIE_NE		0x00000200	/* Not empty */
> > +#define	SPIE_NF		0x00000100	/* Not full */
> > +
> > +/* SPIM register values */
> > +#define	SPIM_NE		0x00000200	/* Not empty */
> > +#define	SPIM_NF		0x00000100	/* Not full */
> > +#define SPIE_RXCNT(reg)     ((reg >> 24) & 0x3F)
> > +#define SPIE_TXCNT(reg)     ((reg >> 16) & 0x3F)
> > +
> > +/* SPCOM register values */
> > +#define SPCOM_CS(x)		((x) << 30)
> > +#define SPCOM_TRANLEN(x)	((x) << 0)
> > +#define	SPCOM_TRANLEN_MAX	0xFFFF	/* Max 
> transaction length */
> 
> Inconsistent whitespacing.  Some lines use tabs; others 
> spaces.  Should be consistent on all the lines.
> 

Ok.

> > +
> > +static
> > +int fsl_espi_setup_transfer(struct spi_device *spi, struct 
> > +spi_transfer *t)
> 
> Break the line in the arguments instead of the declaration.  
> When grepping, the stuff at the front of the line is more 
> important to see.  So:
> 
> +static int fsl_espi_setup_transfer(struct spi_device *spi,
> +				   struct spi_transfer *t)
> 

Ok.

> > +{
> > +	struct mpc8xxx_spi *mpc8xxx_spi;
> > +	u8 bits_per_word, pm;
> > +	u32 hz;
> > +	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
> > +
> > +	mpc8xxx_spi = spi_master_get_devdata(spi->master);
> > +
> > +	if (t) {
> > +		bits_per_word = t->bits_per_word;
> > +		hz = t->speed_hz;
> > +	} else {
> > +		bits_per_word = 0;
> > +		hz = 0;
> > +	}
> 
> Just initialize bits_per_word and hz to 0 when they are 
> declared to eliminate the else clause.
> 

Good suggestion.

> > +
> > +	/* spi_transfer level calls that work per-word */
> > +	if (!bits_per_word)
> > +		bits_per_word = spi->bits_per_word;
> > +
> > +	/* Make sure its a bit width we support [4..16] */
> > +	if ((bits_per_word < 4) || (bits_per_word > 16))
> > +		return -EINVAL;
> > +
> > +	if (!hz)
> > +		hz = spi->max_speed_hz;
> > +
> > +	cs->rx_shift = 0;
> > +	cs->tx_shift = 0;
> > +	cs->get_rx = mpc8xxx_spi_rx_buf_u32;
> > +	cs->get_tx = mpc8xxx_spi_tx_buf_u32;
> > +	if (bits_per_word <= 8) {
> > +		cs->rx_shift = 8 - bits_per_word;
> > +	} else if (bits_per_word <= 16) {
> > +		cs->rx_shift = 16 - bits_per_word;
> > +		if (spi->mode & SPI_LSB_FIRST)
> > +			cs->get_tx = fsl_espi_tx_buf_lsb;
> > +	} else
> > +		return -EINVAL;
> > +
> > +	mpc8xxx_spi->rx_shift = cs->rx_shift;
> > +	mpc8xxx_spi->tx_shift = cs->tx_shift;
> > +	mpc8xxx_spi->get_rx = cs->get_rx;
> > +	mpc8xxx_spi->get_tx = cs->get_tx;
> > +
> > +	bits_per_word = bits_per_word - 1;
> > +
> > +	/* mask out bits we are going to set */
> > +	cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16
> > +				  | CSMODE_PM(0xF));
> > +
> > +	cs->hw_mode |= CSMODE_LEN(bits_per_word);
> > +
> > +	if ((mpc8xxx_spi->spibrg / hz) > 64) {
> > +		cs->hw_mode |= CSMODE_DIV16;
> > +		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
> > +
> > +		WARN_ONCE(pm > 16, "%s: Requested speed is too 
> low: %d Hz. "
> > +			  "Will use %d Hz instead.\n", 
> dev_name(&spi->dev),
> > +			  hz, mpc8xxx_spi->spibrg / 1024);
> > +		if (pm > 16)
> > +			pm = 16;
> > +	} else
> > +		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
> 
> When the if clause has { }, please use braces in the else clause also.
> 

Ok.

> > +static const struct of_device_id of_fsl_espi_match[] = {
> > +	{ .compatible = "fsl,espi" },
> 
> Not good practice.  Use the real chip name in the compatible 
> value.  "fsl,<chip>-espi".
> 

Ok.

> > +	{},
> 
> NIT: Drop the comma here to hint that no more elements should 
> follow after the null entry.
> 

Ok.

> > +};
> > +MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
> > +
> > +static struct of_platform_driver of_fsl_espi_driver = {
> > +	.driver = {
> > +		.name = "fsl_espi",
> > +		.owner = THIS_MODULE,
> > +		.of_match_table = of_fsl_espi_match,
> > +	},
> > +	.probe		= of_fsl_espi_probe,
> > +	.remove		= __devexit_p(of_fsl_espi_remove),
> > +};
> > +
> > +static int __init fsl_espi_init(void) {
> > +	return of_register_platform_driver(&of_fsl_espi_driver);
> > +}
> > +
> > +static void __exit fsl_espi_exit(void) {
> > +	of_unregister_platform_driver(&of_fsl_espi_driver);
> > +}
> > +
> > +module_init(fsl_espi_init);
> 
> Move module_init() to right below fsl_espi_init.
> 
Ok.

> > +module_exit(fsl_espi_exit);
> > +
> > +MODULE_AUTHOR("Mingkai Hu");
> > +MODULE_DESCRIPTION("Enhanced MPC8xxx SPI Driver"); 
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/spi/spi_mpc8xxx.h b/drivers/spi/spi_mpc8xxx.h 
> > index dcc6443..a8e8270 100644
> > --- a/drivers/spi/spi_mpc8xxx.h
> > +++ b/drivers/spi/spi_mpc8xxx.h
> > @@ -20,6 +20,7 @@
> >  
> >  /* SPI Controller registers */
> >  struct mpc8xxx_spi_reg {
> > +#ifndef CONFIG_SPI_FSL_ESPI
> >  	u8 res1[0x20];
> >  	__be32 mode;
> >  	__be32 event;
> > @@ -27,6 +28,16 @@ struct mpc8xxx_spi_reg {
> >  	__be32 command;
> >  	__be32 transmit;
> >  	__be32 receive;
> > +#else
> > +	__be32 mode;		/* 0x000 - eSPI mode register */
> > +	__be32 event;		/* 0x004 - eSPI event register */
> > +	__be32 mask;		/* 0x008 - eSPI mask register */
> > +	__be32 command;		/* 0x00c - eSPI command register */
> > +	__be32 transmit;	/* 0x010 - eSPI transmit FIFO 
> access register*/
> > +	__be32 receive;		/* 0x014 - eSPI receive FIFO 
> access register*/
> > +	u8 res1[8];		/* 0x018 - 0x01c reserved */
> > +	__be32 csmode[4];	/* 0x020 - 0x02c eSPI cs mode 
> register */
> > +#endif
> 
> Not multiplatform friendly.  If the two devices use different 
> register maps, then the register map needs to be defined in 
> the .c file.  You need to code for the case where a single 
> kernel may contain both drivers.
> 

You're right, this will disable the kernel supporting both drivers.
I'll fix it.

Thanks,
Mingkai



More information about the Linuxppc-dev mailing list