LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH net-next 3/3] powerpc/mpc5xxx: add OF platform binding doc for FSL MSCAN devices
From: Wolfram Sang @ 2010-01-02 14:05 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Socketcan-core, Netdev, Devicetree-discuss, Linuxppc-dev,
	Wolfgang Grandegger
In-Reply-To: <1262420274-16586-4-git-send-email-wg@grandegger.com>

[-- Attachment #1: Type: text/plain, Size: 3975 bytes --]

On Sat, Jan 02, 2010 at 09:17:54AM +0100, Wolfgang Grandegger wrote:
> From: Wolfgang Grandegger <wg@denx.de>
> 
> This patch adds documentation for the MSCAN OF device bindings for
> the MPC512x and moves the one for the MPC5200 to the new common file
> "Documentation/powerpc/dts-bindings/fsl/can.txt".
> 
> Signed-off-by: Wolfgang Grandegger <wg@denx.de>

Looks good to me (except for the typos ;))

Acked-by: Wolfram Sang <w.sang@pengutronix.de>

> ---
>  Documentation/powerpc/dts-bindings/fsl/can.txt     |   53 ++++++++++++++++++++
>  Documentation/powerpc/dts-bindings/fsl/mpc5200.txt |    9 +---
>  2 files changed, 54 insertions(+), 8 deletions(-)
>  create mode 100644 Documentation/powerpc/dts-bindings/fsl/can.txt
> 
> diff --git a/Documentation/powerpc/dts-bindings/fsl/can.txt b/Documentation/powerpc/dts-bindings/fsl/can.txt
> new file mode 100644
> index 0000000..44cfb61
> --- /dev/null
> +++ b/Documentation/powerpc/dts-bindings/fsl/can.txt
> @@ -0,0 +1,53 @@
> +CAN Device Tree Bindings
> +------------------------
> +
> +(c) 2006-2009 Secret Lab Technologies Ltd
> +Grant Likely <grant.likely@secretlab.ca>
> +
> +fsl,mpc5200-mscan nodes
> +-----------------------
> +In addition to the required compatible-, reg- and interrupt-properites, you can

properties.

> +also specify which clock source shall be used for the controller:
> +
> +- fsl,mscan-clock-source : a string describing the clock source. Valid values
> +			   are:	"ip" for ip bus clock
> +				 "ref" for reference clock (XTAL)
> +			   "ref" is default in case this property is not
> +			   present.
> +
> +fsl,mpc5121-mscan nodes
> +-----------------------
> +In addition to the required compatible-, reg- and interrupt-properites, you can

properties.

> +also specify which clock source shall be used for the controller:
> +
> +- fsl,mscan-clock-source : a string describing the clock source. Valid values
> +			   are:	"ip" for ip bus clock
> +				"ref" for reference clock
> +				"sys" for system clock
> +			   If this property is not present, an optimal CAN
> +			   clock source and frequency based on the system
> +			   will be selected. If this is not possible, the
> +			   reference clock will be used.
> +
> +- fsl,mscan-clock-divider: for the reference and system clock an additional
> +			   clock divider can be specified. By default a

I wonder if there should be a comma after 'default'. Maybe a native speaker can
help?

> +			   value of 1 is used.
> +
> +Examples:
> +	can@1300 {
> +		compatible = "fsl,mpc5121-mscan";
> +		cell-index = <0>;
> +		interrupts = <12 0x8>;
> +		interrupt-parent = < &ipic >;
> +		reg = <0x1300 0x80>;
> +	};
> +
> +	can@1380 {
> +		compatible = "fsl,mpc5121-mscan";
> +		cell-index = <1>;
> +		interrupts = <13 0x8>;
> +		interrupt-parent = < &ipic >;
> +		reg = <0x1380 0x80>;
> +		fsl,mscan-clock-source = "ref";
> +		fsl,mscan-clock-divider = <3>;
> +	};
> diff --git a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
> index 5c6602d..4ccb2cd 100644
> --- a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
> +++ b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
> @@ -195,11 +195,4 @@ External interrupts:
>  
>  fsl,mpc5200-mscan nodes
>  -----------------------
> -In addition to the required compatible-, reg- and interrupt-properites, you can
> -also specify which clock source shall be used for the controller:
> -
> -- fsl,mscan-clock-source- a string describing the clock source. Valid values
> -			  are:	"ip" for ip bus clock
> -				"ref" for reference clock (XTAL)
> -			  "ref" is default in case this property is not
> -			  present.
> +See file can.txt in this directory.
> -- 
> 1.6.2.5
> 

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH net-next 2/3] can: mscan-mpc5xxx: add support for the MPC521x processor
From: Wolfram Sang @ 2010-01-02 13:57 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Socketcan-core, Netdev, Devicetree-discuss, Linuxppc-dev,
	Wolfgang Grandegger
In-Reply-To: <1262420274-16586-3-git-send-email-wg@grandegger.com>

[-- Attachment #1: Type: text/plain, Size: 22807 bytes --]

On Sat, Jan 02, 2010 at 09:17:53AM +0100, Wolfgang Grandegger wrote:
> From: Wolfgang Grandegger <wg@denx.de>
> 
> The main differences compared to the MSCAN on the MPC5200 are:
> 
> - More flexibility in choosing the CAN source clock and frequency:
> 
>   Three different clock sources can be selected: "ip", "ref" or "sys".
>   For the latter two, a clock divider can be defined as well. If the
>   clock source is not specified by the device tree, we first try to
>   find an optimal CAN source clock based on the system clock. If that
>   is not possible, the reference clock will be used.
> 
> - The behavior of bus-off recovery is configurable:
> 
>   To comply with the usual handling of Socket-CAN bus-off recovery,
>   "recovery on request" is selected (instead of automatic recovery).
> 
> Signed-off-by: Wolfgang Grandegger <wg@denx.de>
> ---
>  drivers/net/can/mscan/Kconfig       |    2 +-
>  drivers/net/can/mscan/mpc5xxx_can.c |  234 +++++++++++++++++++++++++++++------
>  drivers/net/can/mscan/mscan.c       |   41 +++++--
>  drivers/net/can/mscan/mscan.h       |   81 ++++++------
>  4 files changed, 271 insertions(+), 87 deletions(-)
> 
> diff --git a/drivers/net/can/mscan/Kconfig b/drivers/net/can/mscan/Kconfig
> index cd0f2d6..723d009 100644
> --- a/drivers/net/can/mscan/Kconfig
> +++ b/drivers/net/can/mscan/Kconfig
> @@ -11,7 +11,7 @@ if CAN_MSCAN
>  
>  config CAN_MPC5XXX
>  	tristate "Freescale MPC5xxx onboard CAN controller"
> -	depends on PPC_MPC52xx
> +	depends on (PPC_MPC52xx || PPC_MPC512x)
>  	---help---
>  	  If you say yes here you get support for Freescale's MPC5xxx
>  	  onboard CAN controller.
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> index 1de6f63..42c719b 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -29,6 +29,7 @@
>  #include <linux/can/dev.h>
>  #include <linux/of_platform.h>
>  #include <sysdev/fsl_soc.h>
> +#include <linux/clk.h>
>  #include <linux/io.h>
>  #include <asm/mpc52xx.h>
>  
> @@ -36,22 +37,15 @@
>  
>  #define DRV_NAME "mpc5xxx_can"
>  
> +#ifdef CONFIG_PPC_MPC5200
>  static struct of_device_id mpc52xx_cdm_ids[] __devinitdata = {
>  	{ .compatible = "fsl,mpc5200-cdm", },
>  	{}
>  };
>  
> -/*
> - * Get frequency of the MSCAN clock source
> - *
> - * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock (IP_CLK)
> - * can be selected. According to the MPC5200 user's manual, the oscillator
> - * clock is the better choice as it has less jitter but due to a hardware
> - * bug, it can not be selected for the old MPC5200 Rev. A chips.
> - */
> -
> -static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
> -						      int clock_src)
> +static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
> +					   const char *clock_name,
> +					   int *mscan_clksrc)
>  {
>  	unsigned int pvr;
>  	struct mpc52xx_cdm  __iomem *cdm;
> @@ -61,11 +55,24 @@ static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
>  
>  	pvr = mfspr(SPRN_PVR);
>  
> -	freq = mpc5xxx_get_bus_frequency(of->node);
> +	/*
> +	 * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock
> +	 * (IP_CLK) can be selected as MSCAN clock source. According to
> +	 * the MPC5200 user's manual, the oscillator clock is the better
> +	 * choice as it has less jitter. For this reason, it is selected
> +	 * by default. Unfortunately, it can not be selected for the old
> +	 * MPC5200 Rev. A chips due toa hardware bug (check errata).

s/toa/to a/

> +	 */
> +	if (clock_name && strcmp(clock_name, "ip") == 0)
> +		*mscan_clksrc = MSCAN_CLKSRC_BUS;
> +	else
> +		*mscan_clksrc = MSCAN_CLKSRC_XTAL;
> +
> +	freq = mpc5xxx_get_bus_frequency(ofdev->node);
>  	if (!freq)
>  		return 0;
>  
> -	if (clock_src == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
> +	if (*mscan_clksrc == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
>  		return freq;
>  
>  	/* Determine SYS_XTAL_IN frequency from the clock domain settings */
> @@ -75,7 +82,6 @@ static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
>  		return 0;
>  	}
>  	cdm = of_iomap(np_cdm, 0);
> -	of_node_put(np_cdm);
>  
>  	if (in_8(&cdm->ipb_clk_sel) & 0x1)
>  		freq *= 2;
> @@ -84,10 +90,157 @@ static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
>  	freq *= (val & (1 << 5)) ? 8 : 4;
>  	freq /= (val & (1 << 6)) ? 12 : 16;
>  
> +	of_node_put(np_cdm);
>  	iounmap(cdm);
>  
>  	return freq;
>  }
> +#else /* !CONFIG_PPC_MPC5200 */
> +static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
> +					   const char *clock_name,
> +					   int *mscan_clksrc)
> +{
> +	return 0;
> +}
> +#endif /* CONFIG_PPC_MPC5200 */

Hmmm, I don't really like those empty functions. I once used the data-field of
struct of_device_id, which carried a function pointer to a specific
init-function for the matched device. What do you think about such an approach?

> +
> +#ifdef CONFIG_PPC_MPC512x
> +struct mpc512x_clockctl {
> +	u32 spmr;		/* System PLL Mode Reg */
> +	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
> +	u32 scfr1;		/* System Clk Freq Reg 1 */
> +	u32 scfr2;		/* System Clk Freq Reg 2 */
> +	u32 reserved;
> +	u32 bcr;		/* Bread Crumb Reg */
> +	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
> +	u32 spccr;		/* SPDIF Clk Ctrl Reg */
> +	u32 cccr;		/* CFM Clk Ctrl Reg */
> +	u32 dccr;		/* DIU Clk Cnfg Reg */
> +	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
> +};
> +
> +static struct of_device_id mpc512x_clock_ids[] __devinitdata = {
> +	{ .compatible = "fsl,mpc5121-clock", },
> +	{}
> +};
> +
> +static u32  __devinit mpc512x_can_get_clock(struct of_device *ofdev,
> +					    const char *clock_name,
> +					    int *mscan_clksrc,
> +					    ssize_t mscan_addr)
> +{
> +	struct mpc512x_clockctl __iomem *clockctl;
> +	struct device_node *np_clock;
> +	struct clk *sys_clk, *ref_clk;
> +	int plen, clockidx, clocksrc = -1;
> +	u32 sys_freq, val, clockdiv = 1, freq = 0;
> +	const u32 *pval;
> +
> +	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
> +	if (!np_clock) {
> +		dev_err(&ofdev->dev, "couldn't find clock node\n");
> +		return -ENODEV;
> +	}
> +	clockctl = of_iomap(np_clock, 0);
> +	if (!clockctl) {
> +		dev_err(&ofdev->dev, "couldn't map clock registers\n");
> +		return 0;
> +	}
> +
> +	/* Determine the MSCAN device index from the physical address */
> +	clockidx = (mscan_addr & 0x80) ? 1 : 0;
> +	if (mscan_addr & 0x2000)
> +		clockidx += 2;

The PSCs use 'cell-index', here we use mscan_addr to derive the index. This is
not consistent, but should be IMHO. Now, which is the preferred way? I think
I'd go for 'cell-index', as other processors might have mscan_addr shuffled.
Also, we could use 'of_iomap' again in the probe_routine.

> +
> +	/*
> +	 * Clock source and divider selection: 3 different clock sources
> +	 * can be selected: "ip", "ref" or "sys". For the latetr two, a
> +	 * clock divider can be defined as well. If the clock source is
> +	 * not specified by the device tree, we first try to find an
> +	 * optimal CAN source clock based on the system clock. If that
> +	 * is not posslible, the reference clock will be used.
> +	 */
> +	if (clock_name && !strcmp(clock_name, "ip")) {
> +		*mscan_clksrc = MSCAN_CLKSRC_IPS;
> +		freq = mpc5xxx_get_bus_frequency(ofdev->node);
> +	} else {
> +		*mscan_clksrc = MSCAN_CLKSRC_BUS;
> +
> +		pval = of_get_property(ofdev->node,
> +				       "fsl,mscan-clock-divider", &plen);
> +		if (pval && plen == sizeof(*pval))
> +			clockdiv = *pval;
> +		if (!clockdiv)
> +			clockdiv = 1;
> +
> +		if (!clock_name || !strcmp(clock_name, "sys")) {
> +			sys_clk = clk_get(&ofdev->dev, "sys_clk");
> +			if (!sys_clk) {
> +				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
> +				goto exit_unmap;
> +			}
> +			/* Get and round up/down sys clock rate */
> +			sys_freq = 1000000 *
> +				((clk_get_rate(sys_clk) + 499999) / 1000000);
> +
> +			if (!clock_name) {
> +				/* A multiple of 16 MHz would be optimal */
> +				if ((sys_freq % 16000000) == 0) {
> +					clocksrc = 0;
> +					clockdiv = sys_freq / 16000000;
> +					freq = sys_freq / clockdiv;
> +				}
> +			} else {
> +				clocksrc = 0;
> +				freq = sys_freq / clockdiv;
> +			}
> +		}
> +
> +		if (clocksrc < 0) {
> +			ref_clk = clk_get(&ofdev->dev, "ref_clk");
> +			if (!ref_clk) {
> +				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
> +				goto exit_unmap;
> +			}
> +			clocksrc = 1;
> +			freq = clk_get_rate(ref_clk) / clockdiv;
> +		}
> +	}
> +
> +	/* Disable clock */
> +	out_be32(&clockctl->mccr[clockidx], 0x0);
> +	if (clocksrc >= 0) {
> +		/* Set source and divider */
> +		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
> +		out_be32(&clockctl->mccr[clockidx], val);
> +		/* Dnable clock */

Enable

> +		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
> +	}
> +
> +	/* Enable MSCAN clock domain */
> +	val = in_be32(&clockctl->sccr[1]);
> +	if (!(val & (1 << 25)))
> +		out_be32(&clockctl->sccr[1], val | (1 << 25));
> +
> +	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
> +		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
> +		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
> +
> +exit_unmap:
> +	of_node_put(np_clock);
> +	iounmap(clockctl);
> +
> +	return freq;
> +}
> +#else /* !CONFIG_PPC_MPC512x */
> +static u32  __devinit mpc512x_can_get_clock(struct of_device *ofdev,
> +					    const char *clock_name,
> +					    int *mscan_clksrc,
> +					    ssize_t mscan_addr)
> +{
> +	return 0;
> +}
> +#endif /* CONFIG_PPC_MPC512x */
>  
>  static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
>  				       const struct of_device_id *id)
> @@ -95,15 +248,21 @@ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
>  	struct device_node *np = ofdev->node;
>  	struct net_device *dev;
>  	struct mscan_priv *priv;
> +	struct resource res;
>  	void __iomem *base;
> -	const char *clk_src;
> -	int err, irq, clock_src;
> +	const char *clock_name = NULL;
> +	int irq, clock_src = 0;
> +	int err = -ENOMEM;
>  
> -	base = of_iomap(ofdev->node, 0);
> +	if (of_address_to_resource(np, 0, &res)) {
> +		dev_err(&ofdev->dev, "couldn't get resource address\n");
> +		return err;
> +	}
> +
> +	base = ioremap(res.start, resource_size(&res));
>  	if (!base) {
>  		dev_err(&ofdev->dev, "couldn't ioremap\n");
> -		err = -ENOMEM;
> -		goto exit_release_mem;
> +		return err;
>  	}
>  
>  	irq = irq_of_parse_and_map(np, 0);
> @@ -114,31 +273,27 @@ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
>  	}
>  
>  	dev = alloc_mscandev();
> -	if (!dev) {
> -		err = -ENOMEM;
> +	if (!dev)
>  		goto exit_dispose_irq;
> -	}
>  
>  	priv = netdev_priv(dev);
>  	priv->reg_base = base;
>  	dev->irq = irq;
>  
> -	/*
> -	 * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock
> -	 * (IP_CLK) can be selected as MSCAN clock source. According to
> -	 * the MPC5200 user's manual, the oscillator clock is the better
> -	 * choice as it has less jitter. For this reason, it is selected
> -	 * by default.
> -	 */
> -	clk_src = of_get_property(np, "fsl,mscan-clock-source", NULL);
> -	if (clk_src && strcmp(clk_src, "ip") == 0)
> -		clock_src = MSCAN_CLKSRC_BUS;
> -	else
> -		clock_src = MSCAN_CLKSRC_XTAL;
> -	priv->can.clock.freq = mpc52xx_can_clock_freq(ofdev, clock_src);
> +	clock_name = of_get_property(np, "fsl,mscan-clock-source", NULL);
> +
> +	if (of_device_is_compatible(np, "fsl,mpc5121-mscan")) {
> +		priv->type = MSCAN_TYPE_MPC5121;
> +		priv->can.clock.freq =
> +			mpc512x_can_get_clock(ofdev, clock_name, &clock_src,
> +					      res.start);
> +	} else {
> +		priv->type = MSCAN_TYPE_MPC5200;
> +		priv->can.clock.freq =
> +			mpc52xx_can_get_clock(ofdev, clock_name, &clock_src);
> +	}
>  	if (!priv->can.clock.freq) {
> -		dev_err(&ofdev->dev, "couldn't get MSCAN clock frequency\n");
> -		err = -ENODEV;
> +		dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n");
>  		goto exit_free_mscan;
>  	}
>  
> @@ -164,7 +319,7 @@ exit_dispose_irq:
>  	irq_dispose_mapping(irq);
>  exit_unmap_mem:
>  	iounmap(base);
> -exit_release_mem:
> +
>  	return err;
>  }
>  
> @@ -227,6 +382,7 @@ static int mpc5xxx_can_resume(struct of_device *ofdev)
>  
>  static struct of_device_id __devinitdata mpc5xxx_can_table[] = {
>  	{.compatible = "fsl,mpc5200-mscan"},
> +	{.compatible = "fsl,mpc5121-mscan"},
>  	{},
>  };
>  
> @@ -255,5 +411,5 @@ static void __exit mpc5xxx_can_exit(void)
>  module_exit(mpc5xxx_can_exit);
>  
>  MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
> -MODULE_DESCRIPTION("Freescale MPC5200 CAN driver");
> +MODULE_DESCRIPTION("Freescale MPC5200 and MPC521x CAN driver");

simply 5xxx?

>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
> index abdf5e8..9812aa0 100644
> --- a/drivers/net/can/mscan/mscan.c
> +++ b/drivers/net/can/mscan/mscan.c
> @@ -169,6 +169,27 @@ static int mscan_start(struct net_device *dev)
>  	return 0;
>  }
>  
> +static int mscan_restart(struct net_device *dev)
> +{
> +	struct mscan_priv *priv = netdev_priv(dev);
> +
> +	if (priv->type == MSCAN_TYPE_MPC5121) {
> +		struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
> +
> +		priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +		if (!(in_8(&regs->canmisc) & MSCAN_BOHOLD))
> +			dev_err(dev->dev.parent, "Oops, not bus-off");

I think this error-message could be improved :)

> +		else
> +			out_8(&regs->canmisc, MSCAN_BOHOLD);
> +	} else {
> +		if (priv->can.state <= CAN_STATE_BUS_OFF)
> +			mscan_set_mode(dev, MSCAN_INIT_MODE);
> +		return mscan_start(dev);
> +	}
> +
> +	return 0;
> +}
> +
>  static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  {
>  	struct can_frame *frame = (struct can_frame *)skb->data;
> @@ -364,9 +385,12 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame,
>  			 * automatically. To avoid that we stop the chip doing
>  			 * a light-weight stop (we are in irq-context).
>  			 */
> -			out_8(&regs->cantier, 0);
> -			out_8(&regs->canrier, 0);
> -			setbits8(&regs->canctl0, MSCAN_SLPRQ | MSCAN_INITRQ);
> +			if (priv->type != MSCAN_TYPE_MPC5121) {
> +				out_8(&regs->cantier, 0);
> +				out_8(&regs->canrier, 0);
> +				setbits8(&regs->canctl0,
> +					 MSCAN_SLPRQ | MSCAN_INITRQ);
> +			}
>  			can_bus_off(dev);
>  			break;
>  		default:
> @@ -496,9 +520,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
>  
>  	switch (mode) {
>  	case CAN_MODE_START:
> -		if (priv->can.state <= CAN_STATE_BUS_OFF)
> -			mscan_set_mode(dev, MSCAN_INIT_MODE);
> -		ret = mscan_start(dev);
> +		ret = mscan_restart(dev);
>  		if (ret)
>  			break;
>  		if (netif_queue_stopped(dev))
> @@ -597,18 +619,21 @@ static const struct net_device_ops mscan_netdev_ops = {
>         .ndo_start_xmit         = mscan_start_xmit,
>  };
>  
> -int register_mscandev(struct net_device *dev, int clock_src)
> +int register_mscandev(struct net_device *dev, int mscan_clksrc)
>  {
>  	struct mscan_priv *priv = netdev_priv(dev);
>  	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
>  	u8 ctl1;
>  
>  	ctl1 = in_8(&regs->canctl1);
> -	if (clock_src)
> +	if (mscan_clksrc)
>  		ctl1 |= MSCAN_CLKSRC;
>  	else
>  		ctl1 &= ~MSCAN_CLKSRC;
>  
> +	if (priv->type == MSCAN_TYPE_MPC5121)
> +		ctl1 |= MSCAN_BORM; /* bus-off recovery upon request */
> +
>  	ctl1 |= MSCAN_CANE;
>  	out_8(&regs->canctl1, ctl1);
>  	udelay(100);
> diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
> index 00fc4aa..2114942 100644
> --- a/drivers/net/can/mscan/mscan.h
> +++ b/drivers/net/can/mscan/mscan.h
> @@ -39,17 +39,19 @@
>  #define MSCAN_LOOPB		0x20
>  #define MSCAN_LISTEN		0x10
>  #define MSCAN_WUPM		0x04
> +#define MSCAN_BORM		0x08

This should be one line up to keep the sorting intact.

>  #define MSCAN_SLPAK		0x02
>  #define MSCAN_INITAK		0x01
>  
> -/* Use the MPC5200 MSCAN variant? */
> +/* Use the MPC5XXX MSCAN variant? */
>  #ifdef CONFIG_PPC
> -#define MSCAN_FOR_MPC5200
> +#define MSCAN_FOR_MPC5XXX
>  #endif
>  
> -#ifdef MSCAN_FOR_MPC5200
> +#ifdef MSCAN_FOR_MPC5XXX
>  #define MSCAN_CLKSRC_BUS	0
>  #define MSCAN_CLKSRC_XTAL	MSCAN_CLKSRC
> +#define MSCAN_CLKSRC_IPS	MSCAN_CLKSRC
>  #else
>  #define MSCAN_CLKSRC_BUS	MSCAN_CLKSRC
>  #define MSCAN_CLKSRC_XTAL	0
> @@ -136,7 +138,7 @@
>  #define MSCAN_EFF_RTR_SHIFT	0
>  #define MSCAN_EFF_FLAGS		0x18	/* IDE + SRR */
>  
> -#ifdef MSCAN_FOR_MPC5200
> +#ifdef MSCAN_FOR_MPC5XXX
>  #define _MSCAN_RESERVED_(n, num) u8 _res##n[num]
>  #define _MSCAN_RESERVED_DSR_SIZE	2
>  #else
> @@ -165,67 +167,66 @@ struct mscan_regs {
>  	u8 cantbsel;				/* + 0x14     0x0a */
>  	u8 canidac;				/* + 0x15     0x0b */
>  	u8 reserved;				/* + 0x16     0x0c */
> -	_MSCAN_RESERVED_(6, 5);			/* + 0x17          */
> -#ifndef MSCAN_FOR_MPC5200
> -	u8 canmisc;				/*            0x0d */
> -#endif
> +	_MSCAN_RESERVED_(6, 2);			/* + 0x17          */
> +	u8 canmisc;				/* + 0x19     0x0d */
> +	_MSCAN_RESERVED_(7, 2);			/* + 0x1a          */
>  	u8 canrxerr;				/* + 0x1c     0x0e */
>  	u8 cantxerr;				/* + 0x1d     0x0f */
> -	_MSCAN_RESERVED_(7, 2);			/* + 0x1e          */
> +	_MSCAN_RESERVED_(8, 2);			/* + 0x1e          */
>  	u16 canidar1_0;				/* + 0x20     0x10 */
> -	_MSCAN_RESERVED_(8, 2);			/* + 0x22          */
> +	_MSCAN_RESERVED_(9, 2);			/* + 0x22          */
>  	u16 canidar3_2;				/* + 0x24     0x12 */
> -	_MSCAN_RESERVED_(9, 2);			/* + 0x26          */
> +	_MSCAN_RESERVED_(10, 2);		/* + 0x26          */
>  	u16 canidmr1_0;				/* + 0x28     0x14 */
> -	_MSCAN_RESERVED_(10, 2);		/* + 0x2a          */
> +	_MSCAN_RESERVED_(11, 2);		/* + 0x2a          */
>  	u16 canidmr3_2;				/* + 0x2c     0x16 */
> -	_MSCAN_RESERVED_(11, 2);		/* + 0x2e          */
> +	_MSCAN_RESERVED_(12, 2);		/* + 0x2e          */
>  	u16 canidar5_4;				/* + 0x30     0x18 */
> -	_MSCAN_RESERVED_(12, 2);		/* + 0x32          */
> +	_MSCAN_RESERVED_(13, 2);		/* + 0x32          */
>  	u16 canidar7_6;				/* + 0x34     0x1a */
> -	_MSCAN_RESERVED_(13, 2);		/* + 0x36          */
> +	_MSCAN_RESERVED_(14, 2);		/* + 0x36          */
>  	u16 canidmr5_4;				/* + 0x38     0x1c */
> -	_MSCAN_RESERVED_(14, 2);		/* + 0x3a          */
> +	_MSCAN_RESERVED_(15, 2);		/* + 0x3a          */
>  	u16 canidmr7_6;				/* + 0x3c     0x1e */
> -	_MSCAN_RESERVED_(15, 2);		/* + 0x3e          */
> +	_MSCAN_RESERVED_(16, 2);		/* + 0x3e          */
>  	struct {
>  		u16 idr1_0;			/* + 0x40     0x20 */
> -		 _MSCAN_RESERVED_(16, 2);	/* + 0x42          */
> +		_MSCAN_RESERVED_(17, 2);	/* + 0x42          */
>  		u16 idr3_2;			/* + 0x44     0x22 */
> -		 _MSCAN_RESERVED_(17, 2);	/* + 0x46          */
> +		_MSCAN_RESERVED_(18, 2);	/* + 0x46          */
>  		u16 dsr1_0;			/* + 0x48     0x24 */
> -		 _MSCAN_RESERVED_(18, 2);	/* + 0x4a          */
> +		_MSCAN_RESERVED_(19, 2);	/* + 0x4a          */
>  		u16 dsr3_2;			/* + 0x4c     0x26 */
> -		 _MSCAN_RESERVED_(19, 2);	/* + 0x4e          */
> +		_MSCAN_RESERVED_(20, 2);	/* + 0x4e          */
>  		u16 dsr5_4;			/* + 0x50     0x28 */
> -		 _MSCAN_RESERVED_(20, 2);	/* + 0x52          */
> +		_MSCAN_RESERVED_(21, 2);	/* + 0x52          */
>  		u16 dsr7_6;			/* + 0x54     0x2a */
> -		 _MSCAN_RESERVED_(21, 2);	/* + 0x56          */
> +		_MSCAN_RESERVED_(22, 2);	/* + 0x56          */
>  		u8 dlr;				/* + 0x58     0x2c */
> -		 u8:8;				/* + 0x59     0x2d */
> -		 _MSCAN_RESERVED_(22, 2);	/* + 0x5a          */
> +		u8 reserved;			/* + 0x59     0x2d */
> +		_MSCAN_RESERVED_(23, 2);	/* + 0x5a          */
>  		u16 time;			/* + 0x5c     0x2e */
>  	} rx;
> -	 _MSCAN_RESERVED_(23, 2);		/* + 0x5e          */
> +	_MSCAN_RESERVED_(24, 2);		/* + 0x5e          */
>  	struct {
>  		u16 idr1_0;			/* + 0x60     0x30 */
> -		 _MSCAN_RESERVED_(24, 2);	/* + 0x62          */
> +		_MSCAN_RESERVED_(25, 2);	/* + 0x62          */
>  		u16 idr3_2;			/* + 0x64     0x32 */
> -		 _MSCAN_RESERVED_(25, 2);	/* + 0x66          */
> +		_MSCAN_RESERVED_(26, 2);	/* + 0x66          */
>  		u16 dsr1_0;			/* + 0x68     0x34 */
> -		 _MSCAN_RESERVED_(26, 2);	/* + 0x6a          */
> +		_MSCAN_RESERVED_(27, 2);	/* + 0x6a          */
>  		u16 dsr3_2;			/* + 0x6c     0x36 */
> -		 _MSCAN_RESERVED_(27, 2);	/* + 0x6e          */
> +		_MSCAN_RESERVED_(28, 2);	/* + 0x6e          */
>  		u16 dsr5_4;			/* + 0x70     0x38 */
> -		 _MSCAN_RESERVED_(28, 2);	/* + 0x72          */
> +		_MSCAN_RESERVED_(29, 2);	/* + 0x72          */
>  		u16 dsr7_6;			/* + 0x74     0x3a */
> -		 _MSCAN_RESERVED_(29, 2);	/* + 0x76          */
> +		_MSCAN_RESERVED_(30, 2);	/* + 0x76          */
>  		u8 dlr;				/* + 0x78     0x3c */
>  		u8 tbpr;			/* + 0x79     0x3d */
> -		 _MSCAN_RESERVED_(30, 2);	/* + 0x7a          */
> +		_MSCAN_RESERVED_(31, 2);	/* + 0x7a          */
>  		u16 time;			/* + 0x7c     0x3e */
>  	} tx;
> -	 _MSCAN_RESERVED_(31, 2);		/* + 0x7e          */
> +	_MSCAN_RESERVED_(32, 2);		/* + 0x7e          */
>  } __attribute__ ((packed));
>  
>  #undef _MSCAN_RESERVED_
> @@ -238,6 +239,12 @@ struct mscan_regs {
>  #define MSCAN_SET_MODE_RETRIES	255
>  #define MSCAN_ECHO_SKB_MAX	3
>  
> +/* MSCAN type variants */
> +enum {
> +	MSCAN_TYPE_MPC5200,
> +	MSCAN_TYPE_MPC5121
> +};
> +
>  #define BTR0_BRP_MASK		0x3f
>  #define BTR0_SJW_SHIFT		6
>  #define BTR0_SJW_MASK		(0x3 << BTR0_SJW_SHIFT)
> @@ -270,6 +277,7 @@ struct tx_queue_entry {
>  
>  struct mscan_priv {
>  	struct can_priv can;	/* must be the first member */
> +	unsigned int type; 	/* MSCAN type variants */
>  	long open_time;
>  	unsigned long flags;
>  	void __iomem *reg_base;	/* ioremap'ed address to registers */
> @@ -285,11 +293,6 @@ struct mscan_priv {
>  };
>  
>  extern struct net_device *alloc_mscandev(void);
> -/*
> - * clock_src:
> - *	1 = The MSCAN clock source is the onchip Bus Clock.
> - *	0 = The MSCAN clock source is the chip Oscillator Clock.
> - */
>  extern int register_mscandev(struct net_device *dev, int clock_src);

s/clock_src/mscan_clksrc/

>  extern void unregister_mscandev(struct net_device *dev);
>  
> -- 
> 1.6.2.5
> 

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH net-next 1/3] can: mscan: fix improper return if dlc < 8 in start_xmit function
From: Wolfram Sang @ 2010-01-02 13:30 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Socketcan-core, Netdev, Devicetree-discuss, Linuxppc-dev,
	Wolfgang Grandegger
In-Reply-To: <1262420274-16586-2-git-send-email-wg@grandegger.com>

[-- Attachment #1: Type: text/plain, Size: 2106 bytes --]

On Sat, Jan 02, 2010 at 09:17:52AM +0100, Wolfgang Grandegger wrote:
> From: Wolfgang Grandegger <wg@denx.de>
> 
> The start_xmit function of the MSCAN Driver did return improperly if
> the CAN dlc check failed (skb not freed and invalid return code). This
> patch adds a proper check of the frame lenght and data size and returns
> now correctly. Furthermore, a typo has been fixed.

A few little things, but in general:

Acked-by: Wolfram Sang <w.sang@pengutronix.de>

> 
> Signed-off-by: Wolfgang Grandegger <wg@denx.de>
> ---
>  drivers/net/can/mscan/mscan.c |   11 ++++++++---
>  1 files changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
> index 07346f8..abdf5e8 100644
> --- a/drivers/net/can/mscan/mscan.c
> +++ b/drivers/net/can/mscan/mscan.c
> @@ -4,7 +4,7 @@
>   * Copyright (C) 2005-2006 Andrey Volkov <avolkov@varma-el.com>,
>   *                         Varma Electronics Oy
>   * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
> - * Copytight (C) 2008-2009 Pengutronix <kernel@pengutronix.de>
> + * Copyright (C) 2008-2009 Pengutronix <kernel@pengutronix.de>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the version 2 of the GNU General Public License
> @@ -177,8 +177,13 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  	int i, rtr, buf_id;
>  	u32 can_id;
>  
> -	if (frame->can_dlc > 8)
> -		return -EINVAL;
> +	if (skb->len != sizeof(*frame) || frame->can_dlc > 8) {
> +		dev_err(dev->dev.parent,
> +			"Dropping non-conform paket: len %d, can_dlc %d\n",

s/paket/packet/

> +			skb->len, frame->can_dlc);

Also, shouldn't it rather be %u (sk_buff->len is unsigned int)?

> +		kfree_skb(skb);
> +		return  NETDEV_TX_OK;
> +	}
>  
>  	out_8(&regs->cantier, 0);
>  
> -- 
> 1.6.2.5
> 

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH net-next 0/3] can: mscan-mpc5xxx: add support for the Freescale MPC512x
From: Wolfram Sang @ 2010-01-02 13:27 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Socketcan-core, Netdev, Devicetree-discuss, Linuxppc-dev
In-Reply-To: <1262420274-16586-1-git-send-email-wg@grandegger.com>

[-- Attachment #1: Type: text/plain, Size: 512 bytes --]

On Sat, Jan 02, 2010 at 09:17:51AM +0100, Wolfgang Grandegger wrote:
> This patch series adds support for the MPC512x from Freescale to
> the mpc5xxx_can MSCAN driver.

Yay, cool :) I will test the patches with our board when I am back in the
office next week. So far, a few comments by having a look will follow.

Happy new 2010,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH 1/2] pmac-zilog: add platform driver
From: Geert Uytterhoeven @ 2010-01-02 12:43 UTC (permalink / raw)
  To: Finn Thain; +Cc: linux-m68k, linuxppc-dev
In-Reply-To: <alpine.OSX.2.00.0911171657290.371@silk.local>

On Tue, Nov 17, 2009 at 10:04, Finn Thain <fthain@telegraphics.com.au> wrot=
e:
> Add platform driver to the pmac-zilog driver for mac 68k, putting the
> powermac-specific bits inside #ifdef CONFIG_PPC_PMAC.

> --- linux-2.6.31.orig/drivers/serial/pmac_zilog.c =C2=A0 =C2=A0 =C2=A0 20=
09-11-17 17:07:28.000000000 +1100
> +++ linux-2.6.31/drivers/serial/pmac_zilog.c =C2=A0 =C2=A02009-11-17 17:0=
7:38.000000000 +1100

> @@ -1427,6 +1439,8 @@ static struct uart_ops pmz_pops =3D {
> =C2=A0#endif
> =C2=A0};
>
> +#ifdef CONFIG_PPC_PMAC
> +
> =C2=A0/*
> =C2=A0* Setup one port structure after probing, HW is down at this point,
> =C2=A0* Unlike sunzilog, we don't need to pre-init the spinlock as we don=
't
> @@ -1823,6 +1837,88 @@ next:
> =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
> =C2=A0}
>
> +#else
> +
> +extern struct platform_device scc_a_pdev, scc_b_pdev;

scripts/checkpatch.pl doesn't like this extern, and it's right.
Can't this be found using standard platform device/driver matching?

BTW, there are a few other minor checkpatch issues with some of the
other patches in the series,
too.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org

In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
							    -- Linus Torvalds

^ permalink raw reply

* [PATCH net-next 3/3] powerpc/mpc5xxx: add OF platform binding doc for FSL MSCAN devices
From: Wolfgang Grandegger @ 2010-01-02  8:17 UTC (permalink / raw)
  To: Netdev
  Cc: Socketcan-core, Devicetree-discuss, Linuxppc-dev,
	Wolfgang Grandegger
In-Reply-To: <1262420274-16586-3-git-send-email-wg@grandegger.com>

From: Wolfgang Grandegger <wg@denx.de>

This patch adds documentation for the MSCAN OF device bindings for
the MPC512x and moves the one for the MPC5200 to the new common file
"Documentation/powerpc/dts-bindings/fsl/can.txt".

Signed-off-by: Wolfgang Grandegger <wg@denx.de>
---
 Documentation/powerpc/dts-bindings/fsl/can.txt     |   53 ++++++++++++++++++++
 Documentation/powerpc/dts-bindings/fsl/mpc5200.txt |    9 +---
 2 files changed, 54 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/powerpc/dts-bindings/fsl/can.txt

diff --git a/Documentation/powerpc/dts-bindings/fsl/can.txt b/Documentation/powerpc/dts-bindings/fsl/can.txt
new file mode 100644
index 0000000..44cfb61
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/can.txt
@@ -0,0 +1,53 @@
+CAN Device Tree Bindings
+------------------------
+
+(c) 2006-2009 Secret Lab Technologies Ltd
+Grant Likely <grant.likely@secretlab.ca>
+
+fsl,mpc5200-mscan nodes
+-----------------------
+In addition to the required compatible-, reg- and interrupt-properites, you can
+also specify which clock source shall be used for the controller:
+
+- fsl,mscan-clock-source : a string describing the clock source. Valid values
+			   are:	"ip" for ip bus clock
+				 "ref" for reference clock (XTAL)
+			   "ref" is default in case this property is not
+			   present.
+
+fsl,mpc5121-mscan nodes
+-----------------------
+In addition to the required compatible-, reg- and interrupt-properites, you can
+also specify which clock source shall be used for the controller:
+
+- fsl,mscan-clock-source : a string describing the clock source. Valid values
+			   are:	"ip" for ip bus clock
+				"ref" for reference clock
+				"sys" for system clock
+			   If this property is not present, an optimal CAN
+			   clock source and frequency based on the system
+			   will be selected. If this is not possible, the
+			   reference clock will be used.
+
+- fsl,mscan-clock-divider: for the reference and system clock an additional
+			   clock divider can be specified. By default a
+			   value of 1 is used.
+
+Examples:
+	can@1300 {
+		compatible = "fsl,mpc5121-mscan";
+		cell-index = <0>;
+		interrupts = <12 0x8>;
+		interrupt-parent = < &ipic >;
+		reg = <0x1300 0x80>;
+	};
+
+	can@1380 {
+		compatible = "fsl,mpc5121-mscan";
+		cell-index = <1>;
+		interrupts = <13 0x8>;
+		interrupt-parent = < &ipic >;
+		reg = <0x1380 0x80>;
+		fsl,mscan-clock-source = "ref";
+		fsl,mscan-clock-divider = <3>;
+	};
diff --git a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
index 5c6602d..4ccb2cd 100644
--- a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
@@ -195,11 +195,4 @@ External interrupts:
 
 fsl,mpc5200-mscan nodes
 -----------------------
-In addition to the required compatible-, reg- and interrupt-properites, you can
-also specify which clock source shall be used for the controller:
-
-- fsl,mscan-clock-source- a string describing the clock source. Valid values
-			  are:	"ip" for ip bus clock
-				"ref" for reference clock (XTAL)
-			  "ref" is default in case this property is not
-			  present.
+See file can.txt in this directory.
-- 
1.6.2.5

^ permalink raw reply related

* [PATCH net-next 2/3] can: mscan-mpc5xxx: add support for the MPC521x processor
From: Wolfgang Grandegger @ 2010-01-02  8:17 UTC (permalink / raw)
  To: Netdev
  Cc: Socketcan-core, Devicetree-discuss, Linuxppc-dev,
	Wolfgang Grandegger
In-Reply-To: <1262420274-16586-2-git-send-email-wg@grandegger.com>

From: Wolfgang Grandegger <wg@denx.de>

The main differences compared to the MSCAN on the MPC5200 are:

- More flexibility in choosing the CAN source clock and frequency:

  Three different clock sources can be selected: "ip", "ref" or "sys".
  For the latter two, a clock divider can be defined as well. If the
  clock source is not specified by the device tree, we first try to
  find an optimal CAN source clock based on the system clock. If that
  is not possible, the reference clock will be used.

- The behavior of bus-off recovery is configurable:

  To comply with the usual handling of Socket-CAN bus-off recovery,
  "recovery on request" is selected (instead of automatic recovery).

Signed-off-by: Wolfgang Grandegger <wg@denx.de>
---
 drivers/net/can/mscan/Kconfig       |    2 +-
 drivers/net/can/mscan/mpc5xxx_can.c |  234 +++++++++++++++++++++++++++++------
 drivers/net/can/mscan/mscan.c       |   41 +++++--
 drivers/net/can/mscan/mscan.h       |   81 ++++++------
 4 files changed, 271 insertions(+), 87 deletions(-)

diff --git a/drivers/net/can/mscan/Kconfig b/drivers/net/can/mscan/Kconfig
index cd0f2d6..723d009 100644
--- a/drivers/net/can/mscan/Kconfig
+++ b/drivers/net/can/mscan/Kconfig
@@ -11,7 +11,7 @@ if CAN_MSCAN
 
 config CAN_MPC5XXX
 	tristate "Freescale MPC5xxx onboard CAN controller"
-	depends on PPC_MPC52xx
+	depends on (PPC_MPC52xx || PPC_MPC512x)
 	---help---
 	  If you say yes here you get support for Freescale's MPC5xxx
 	  onboard CAN controller.
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 1de6f63..42c719b 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -29,6 +29,7 @@
 #include <linux/can/dev.h>
 #include <linux/of_platform.h>
 #include <sysdev/fsl_soc.h>
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <asm/mpc52xx.h>
 
@@ -36,22 +37,15 @@
 
 #define DRV_NAME "mpc5xxx_can"
 
+#ifdef CONFIG_PPC_MPC5200
 static struct of_device_id mpc52xx_cdm_ids[] __devinitdata = {
 	{ .compatible = "fsl,mpc5200-cdm", },
 	{}
 };
 
-/*
- * Get frequency of the MSCAN clock source
- *
- * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock (IP_CLK)
- * can be selected. According to the MPC5200 user's manual, the oscillator
- * clock is the better choice as it has less jitter but due to a hardware
- * bug, it can not be selected for the old MPC5200 Rev. A chips.
- */
-
-static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
-						      int clock_src)
+static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
+					   const char *clock_name,
+					   int *mscan_clksrc)
 {
 	unsigned int pvr;
 	struct mpc52xx_cdm  __iomem *cdm;
@@ -61,11 +55,24 @@ static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
 
 	pvr = mfspr(SPRN_PVR);
 
-	freq = mpc5xxx_get_bus_frequency(of->node);
+	/*
+	 * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock
+	 * (IP_CLK) can be selected as MSCAN clock source. According to
+	 * the MPC5200 user's manual, the oscillator clock is the better
+	 * choice as it has less jitter. For this reason, it is selected
+	 * by default. Unfortunately, it can not be selected for the old
+	 * MPC5200 Rev. A chips due toa hardware bug (check errata).
+	 */
+	if (clock_name && strcmp(clock_name, "ip") == 0)
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+	else
+		*mscan_clksrc = MSCAN_CLKSRC_XTAL;
+
+	freq = mpc5xxx_get_bus_frequency(ofdev->node);
 	if (!freq)
 		return 0;
 
-	if (clock_src == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
+	if (*mscan_clksrc == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
 		return freq;
 
 	/* Determine SYS_XTAL_IN frequency from the clock domain settings */
@@ -75,7 +82,6 @@ static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
 		return 0;
 	}
 	cdm = of_iomap(np_cdm, 0);
-	of_node_put(np_cdm);
 
 	if (in_8(&cdm->ipb_clk_sel) & 0x1)
 		freq *= 2;
@@ -84,10 +90,157 @@ static unsigned int  __devinit mpc52xx_can_clock_freq(struct of_device *of,
 	freq *= (val & (1 << 5)) ? 8 : 4;
 	freq /= (val & (1 << 6)) ? 12 : 16;
 
+	of_node_put(np_cdm);
 	iounmap(cdm);
 
 	return freq;
 }
+#else /* !CONFIG_PPC_MPC5200 */
+static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
+					   const char *clock_name,
+					   int *mscan_clksrc)
+{
+	return 0;
+}
+#endif /* CONFIG_PPC_MPC5200 */
+
+#ifdef CONFIG_PPC_MPC512x
+struct mpc512x_clockctl {
+	u32 spmr;		/* System PLL Mode Reg */
+	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */
+	u32 scfr1;		/* System Clk Freq Reg 1 */
+	u32 scfr2;		/* System Clk Freq Reg 2 */
+	u32 reserved;
+	u32 bcr;		/* Bread Crumb Reg */
+	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */
+	u32 spccr;		/* SPDIF Clk Ctrl Reg */
+	u32 cccr;		/* CFM Clk Ctrl Reg */
+	u32 dccr;		/* DIU Clk Cnfg Reg */
+	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */
+};
+
+static struct of_device_id mpc512x_clock_ids[] __devinitdata = {
+	{ .compatible = "fsl,mpc5121-clock", },
+	{}
+};
+
+static u32  __devinit mpc512x_can_get_clock(struct of_device *ofdev,
+					    const char *clock_name,
+					    int *mscan_clksrc,
+					    ssize_t mscan_addr)
+{
+	struct mpc512x_clockctl __iomem *clockctl;
+	struct device_node *np_clock;
+	struct clk *sys_clk, *ref_clk;
+	int plen, clockidx, clocksrc = -1;
+	u32 sys_freq, val, clockdiv = 1, freq = 0;
+	const u32 *pval;
+
+	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
+	if (!np_clock) {
+		dev_err(&ofdev->dev, "couldn't find clock node\n");
+		return -ENODEV;
+	}
+	clockctl = of_iomap(np_clock, 0);
+	if (!clockctl) {
+		dev_err(&ofdev->dev, "couldn't map clock registers\n");
+		return 0;
+	}
+
+	/* Determine the MSCAN device index from the physical address */
+	clockidx = (mscan_addr & 0x80) ? 1 : 0;
+	if (mscan_addr & 0x2000)
+		clockidx += 2;
+
+	/*
+	 * Clock source and divider selection: 3 different clock sources
+	 * can be selected: "ip", "ref" or "sys". For the latetr two, a
+	 * clock divider can be defined as well. If the clock source is
+	 * not specified by the device tree, we first try to find an
+	 * optimal CAN source clock based on the system clock. If that
+	 * is not posslible, the reference clock will be used.
+	 */
+	if (clock_name && !strcmp(clock_name, "ip")) {
+		*mscan_clksrc = MSCAN_CLKSRC_IPS;
+		freq = mpc5xxx_get_bus_frequency(ofdev->node);
+	} else {
+		*mscan_clksrc = MSCAN_CLKSRC_BUS;
+
+		pval = of_get_property(ofdev->node,
+				       "fsl,mscan-clock-divider", &plen);
+		if (pval && plen == sizeof(*pval))
+			clockdiv = *pval;
+		if (!clockdiv)
+			clockdiv = 1;
+
+		if (!clock_name || !strcmp(clock_name, "sys")) {
+			sys_clk = clk_get(&ofdev->dev, "sys_clk");
+			if (!sys_clk) {
+				dev_err(&ofdev->dev, "couldn't get sys_clk\n");
+				goto exit_unmap;
+			}
+			/* Get and round up/down sys clock rate */
+			sys_freq = 1000000 *
+				((clk_get_rate(sys_clk) + 499999) / 1000000);
+
+			if (!clock_name) {
+				/* A multiple of 16 MHz would be optimal */
+				if ((sys_freq % 16000000) == 0) {
+					clocksrc = 0;
+					clockdiv = sys_freq / 16000000;
+					freq = sys_freq / clockdiv;
+				}
+			} else {
+				clocksrc = 0;
+				freq = sys_freq / clockdiv;
+			}
+		}
+
+		if (clocksrc < 0) {
+			ref_clk = clk_get(&ofdev->dev, "ref_clk");
+			if (!ref_clk) {
+				dev_err(&ofdev->dev, "couldn't get ref_clk\n");
+				goto exit_unmap;
+			}
+			clocksrc = 1;
+			freq = clk_get_rate(ref_clk) / clockdiv;
+		}
+	}
+
+	/* Disable clock */
+	out_be32(&clockctl->mccr[clockidx], 0x0);
+	if (clocksrc >= 0) {
+		/* Set source and divider */
+		val = (clocksrc << 14) | ((clockdiv - 1) << 17);
+		out_be32(&clockctl->mccr[clockidx], val);
+		/* Dnable clock */
+		out_be32(&clockctl->mccr[clockidx], val | 0x10000);
+	}
+
+	/* Enable MSCAN clock domain */
+	val = in_be32(&clockctl->sccr[1]);
+	if (!(val & (1 << 25)))
+		out_be32(&clockctl->sccr[1], val | (1 << 25));
+
+	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
+		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
+		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
+
+exit_unmap:
+	of_node_put(np_clock);
+	iounmap(clockctl);
+
+	return freq;
+}
+#else /* !CONFIG_PPC_MPC512x */
+static u32  __devinit mpc512x_can_get_clock(struct of_device *ofdev,
+					    const char *clock_name,
+					    int *mscan_clksrc,
+					    ssize_t mscan_addr)
+{
+	return 0;
+}
+#endif /* CONFIG_PPC_MPC512x */
 
 static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
 				       const struct of_device_id *id)
@@ -95,15 +248,21 @@ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
 	struct device_node *np = ofdev->node;
 	struct net_device *dev;
 	struct mscan_priv *priv;
+	struct resource res;
 	void __iomem *base;
-	const char *clk_src;
-	int err, irq, clock_src;
+	const char *clock_name = NULL;
+	int irq, clock_src = 0;
+	int err = -ENOMEM;
 
-	base = of_iomap(ofdev->node, 0);
+	if (of_address_to_resource(np, 0, &res)) {
+		dev_err(&ofdev->dev, "couldn't get resource address\n");
+		return err;
+	}
+
+	base = ioremap(res.start, resource_size(&res));
 	if (!base) {
 		dev_err(&ofdev->dev, "couldn't ioremap\n");
-		err = -ENOMEM;
-		goto exit_release_mem;
+		return err;
 	}
 
 	irq = irq_of_parse_and_map(np, 0);
@@ -114,31 +273,27 @@ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
 	}
 
 	dev = alloc_mscandev();
-	if (!dev) {
-		err = -ENOMEM;
+	if (!dev)
 		goto exit_dispose_irq;
-	}
 
 	priv = netdev_priv(dev);
 	priv->reg_base = base;
 	dev->irq = irq;
 
-	/*
-	 * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock
-	 * (IP_CLK) can be selected as MSCAN clock source. According to
-	 * the MPC5200 user's manual, the oscillator clock is the better
-	 * choice as it has less jitter. For this reason, it is selected
-	 * by default.
-	 */
-	clk_src = of_get_property(np, "fsl,mscan-clock-source", NULL);
-	if (clk_src && strcmp(clk_src, "ip") == 0)
-		clock_src = MSCAN_CLKSRC_BUS;
-	else
-		clock_src = MSCAN_CLKSRC_XTAL;
-	priv->can.clock.freq = mpc52xx_can_clock_freq(ofdev, clock_src);
+	clock_name = of_get_property(np, "fsl,mscan-clock-source", NULL);
+
+	if (of_device_is_compatible(np, "fsl,mpc5121-mscan")) {
+		priv->type = MSCAN_TYPE_MPC5121;
+		priv->can.clock.freq =
+			mpc512x_can_get_clock(ofdev, clock_name, &clock_src,
+					      res.start);
+	} else {
+		priv->type = MSCAN_TYPE_MPC5200;
+		priv->can.clock.freq =
+			mpc52xx_can_get_clock(ofdev, clock_name, &clock_src);
+	}
 	if (!priv->can.clock.freq) {
-		dev_err(&ofdev->dev, "couldn't get MSCAN clock frequency\n");
-		err = -ENODEV;
+		dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n");
 		goto exit_free_mscan;
 	}
 
@@ -164,7 +319,7 @@ exit_dispose_irq:
 	irq_dispose_mapping(irq);
 exit_unmap_mem:
 	iounmap(base);
-exit_release_mem:
+
 	return err;
 }
 
@@ -227,6 +382,7 @@ static int mpc5xxx_can_resume(struct of_device *ofdev)
 
 static struct of_device_id __devinitdata mpc5xxx_can_table[] = {
 	{.compatible = "fsl,mpc5200-mscan"},
+	{.compatible = "fsl,mpc5121-mscan"},
 	{},
 };
 
@@ -255,5 +411,5 @@ static void __exit mpc5xxx_can_exit(void)
 module_exit(mpc5xxx_can_exit);
 
 MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
-MODULE_DESCRIPTION("Freescale MPC5200 CAN driver");
+MODULE_DESCRIPTION("Freescale MPC5200 and MPC521x CAN driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index abdf5e8..9812aa0 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -169,6 +169,27 @@ static int mscan_start(struct net_device *dev)
 	return 0;
 }
 
+static int mscan_restart(struct net_device *dev)
+{
+	struct mscan_priv *priv = netdev_priv(dev);
+
+	if (priv->type == MSCAN_TYPE_MPC5121) {
+		struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		if (!(in_8(&regs->canmisc) & MSCAN_BOHOLD))
+			dev_err(dev->dev.parent, "Oops, not bus-off");
+		else
+			out_8(&regs->canmisc, MSCAN_BOHOLD);
+	} else {
+		if (priv->can.state <= CAN_STATE_BUS_OFF)
+			mscan_set_mode(dev, MSCAN_INIT_MODE);
+		return mscan_start(dev);
+	}
+
+	return 0;
+}
+
 static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct can_frame *frame = (struct can_frame *)skb->data;
@@ -364,9 +385,12 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame,
 			 * automatically. To avoid that we stop the chip doing
 			 * a light-weight stop (we are in irq-context).
 			 */
-			out_8(&regs->cantier, 0);
-			out_8(&regs->canrier, 0);
-			setbits8(&regs->canctl0, MSCAN_SLPRQ | MSCAN_INITRQ);
+			if (priv->type != MSCAN_TYPE_MPC5121) {
+				out_8(&regs->cantier, 0);
+				out_8(&regs->canrier, 0);
+				setbits8(&regs->canctl0,
+					 MSCAN_SLPRQ | MSCAN_INITRQ);
+			}
 			can_bus_off(dev);
 			break;
 		default:
@@ -496,9 +520,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
 
 	switch (mode) {
 	case CAN_MODE_START:
-		if (priv->can.state <= CAN_STATE_BUS_OFF)
-			mscan_set_mode(dev, MSCAN_INIT_MODE);
-		ret = mscan_start(dev);
+		ret = mscan_restart(dev);
 		if (ret)
 			break;
 		if (netif_queue_stopped(dev))
@@ -597,18 +619,21 @@ static const struct net_device_ops mscan_netdev_ops = {
        .ndo_start_xmit         = mscan_start_xmit,
 };
 
-int register_mscandev(struct net_device *dev, int clock_src)
+int register_mscandev(struct net_device *dev, int mscan_clksrc)
 {
 	struct mscan_priv *priv = netdev_priv(dev);
 	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
 	u8 ctl1;
 
 	ctl1 = in_8(&regs->canctl1);
-	if (clock_src)
+	if (mscan_clksrc)
 		ctl1 |= MSCAN_CLKSRC;
 	else
 		ctl1 &= ~MSCAN_CLKSRC;
 
+	if (priv->type == MSCAN_TYPE_MPC5121)
+		ctl1 |= MSCAN_BORM; /* bus-off recovery upon request */
+
 	ctl1 |= MSCAN_CANE;
 	out_8(&regs->canctl1, ctl1);
 	udelay(100);
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index 00fc4aa..2114942 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -39,17 +39,19 @@
 #define MSCAN_LOOPB		0x20
 #define MSCAN_LISTEN		0x10
 #define MSCAN_WUPM		0x04
+#define MSCAN_BORM		0x08
 #define MSCAN_SLPAK		0x02
 #define MSCAN_INITAK		0x01
 
-/* Use the MPC5200 MSCAN variant? */
+/* Use the MPC5XXX MSCAN variant? */
 #ifdef CONFIG_PPC
-#define MSCAN_FOR_MPC5200
+#define MSCAN_FOR_MPC5XXX
 #endif
 
-#ifdef MSCAN_FOR_MPC5200
+#ifdef MSCAN_FOR_MPC5XXX
 #define MSCAN_CLKSRC_BUS	0
 #define MSCAN_CLKSRC_XTAL	MSCAN_CLKSRC
+#define MSCAN_CLKSRC_IPS	MSCAN_CLKSRC
 #else
 #define MSCAN_CLKSRC_BUS	MSCAN_CLKSRC
 #define MSCAN_CLKSRC_XTAL	0
@@ -136,7 +138,7 @@
 #define MSCAN_EFF_RTR_SHIFT	0
 #define MSCAN_EFF_FLAGS		0x18	/* IDE + SRR */
 
-#ifdef MSCAN_FOR_MPC5200
+#ifdef MSCAN_FOR_MPC5XXX
 #define _MSCAN_RESERVED_(n, num) u8 _res##n[num]
 #define _MSCAN_RESERVED_DSR_SIZE	2
 #else
@@ -165,67 +167,66 @@ struct mscan_regs {
 	u8 cantbsel;				/* + 0x14     0x0a */
 	u8 canidac;				/* + 0x15     0x0b */
 	u8 reserved;				/* + 0x16     0x0c */
-	_MSCAN_RESERVED_(6, 5);			/* + 0x17          */
-#ifndef MSCAN_FOR_MPC5200
-	u8 canmisc;				/*            0x0d */
-#endif
+	_MSCAN_RESERVED_(6, 2);			/* + 0x17          */
+	u8 canmisc;				/* + 0x19     0x0d */
+	_MSCAN_RESERVED_(7, 2);			/* + 0x1a          */
 	u8 canrxerr;				/* + 0x1c     0x0e */
 	u8 cantxerr;				/* + 0x1d     0x0f */
-	_MSCAN_RESERVED_(7, 2);			/* + 0x1e          */
+	_MSCAN_RESERVED_(8, 2);			/* + 0x1e          */
 	u16 canidar1_0;				/* + 0x20     0x10 */
-	_MSCAN_RESERVED_(8, 2);			/* + 0x22          */
+	_MSCAN_RESERVED_(9, 2);			/* + 0x22          */
 	u16 canidar3_2;				/* + 0x24     0x12 */
-	_MSCAN_RESERVED_(9, 2);			/* + 0x26          */
+	_MSCAN_RESERVED_(10, 2);		/* + 0x26          */
 	u16 canidmr1_0;				/* + 0x28     0x14 */
-	_MSCAN_RESERVED_(10, 2);		/* + 0x2a          */
+	_MSCAN_RESERVED_(11, 2);		/* + 0x2a          */
 	u16 canidmr3_2;				/* + 0x2c     0x16 */
-	_MSCAN_RESERVED_(11, 2);		/* + 0x2e          */
+	_MSCAN_RESERVED_(12, 2);		/* + 0x2e          */
 	u16 canidar5_4;				/* + 0x30     0x18 */
-	_MSCAN_RESERVED_(12, 2);		/* + 0x32          */
+	_MSCAN_RESERVED_(13, 2);		/* + 0x32          */
 	u16 canidar7_6;				/* + 0x34     0x1a */
-	_MSCAN_RESERVED_(13, 2);		/* + 0x36          */
+	_MSCAN_RESERVED_(14, 2);		/* + 0x36          */
 	u16 canidmr5_4;				/* + 0x38     0x1c */
-	_MSCAN_RESERVED_(14, 2);		/* + 0x3a          */
+	_MSCAN_RESERVED_(15, 2);		/* + 0x3a          */
 	u16 canidmr7_6;				/* + 0x3c     0x1e */
-	_MSCAN_RESERVED_(15, 2);		/* + 0x3e          */
+	_MSCAN_RESERVED_(16, 2);		/* + 0x3e          */
 	struct {
 		u16 idr1_0;			/* + 0x40     0x20 */
-		 _MSCAN_RESERVED_(16, 2);	/* + 0x42          */
+		_MSCAN_RESERVED_(17, 2);	/* + 0x42          */
 		u16 idr3_2;			/* + 0x44     0x22 */
-		 _MSCAN_RESERVED_(17, 2);	/* + 0x46          */
+		_MSCAN_RESERVED_(18, 2);	/* + 0x46          */
 		u16 dsr1_0;			/* + 0x48     0x24 */
-		 _MSCAN_RESERVED_(18, 2);	/* + 0x4a          */
+		_MSCAN_RESERVED_(19, 2);	/* + 0x4a          */
 		u16 dsr3_2;			/* + 0x4c     0x26 */
-		 _MSCAN_RESERVED_(19, 2);	/* + 0x4e          */
+		_MSCAN_RESERVED_(20, 2);	/* + 0x4e          */
 		u16 dsr5_4;			/* + 0x50     0x28 */
-		 _MSCAN_RESERVED_(20, 2);	/* + 0x52          */
+		_MSCAN_RESERVED_(21, 2);	/* + 0x52          */
 		u16 dsr7_6;			/* + 0x54     0x2a */
-		 _MSCAN_RESERVED_(21, 2);	/* + 0x56          */
+		_MSCAN_RESERVED_(22, 2);	/* + 0x56          */
 		u8 dlr;				/* + 0x58     0x2c */
-		 u8:8;				/* + 0x59     0x2d */
-		 _MSCAN_RESERVED_(22, 2);	/* + 0x5a          */
+		u8 reserved;			/* + 0x59     0x2d */
+		_MSCAN_RESERVED_(23, 2);	/* + 0x5a          */
 		u16 time;			/* + 0x5c     0x2e */
 	} rx;
-	 _MSCAN_RESERVED_(23, 2);		/* + 0x5e          */
+	_MSCAN_RESERVED_(24, 2);		/* + 0x5e          */
 	struct {
 		u16 idr1_0;			/* + 0x60     0x30 */
-		 _MSCAN_RESERVED_(24, 2);	/* + 0x62          */
+		_MSCAN_RESERVED_(25, 2);	/* + 0x62          */
 		u16 idr3_2;			/* + 0x64     0x32 */
-		 _MSCAN_RESERVED_(25, 2);	/* + 0x66          */
+		_MSCAN_RESERVED_(26, 2);	/* + 0x66          */
 		u16 dsr1_0;			/* + 0x68     0x34 */
-		 _MSCAN_RESERVED_(26, 2);	/* + 0x6a          */
+		_MSCAN_RESERVED_(27, 2);	/* + 0x6a          */
 		u16 dsr3_2;			/* + 0x6c     0x36 */
-		 _MSCAN_RESERVED_(27, 2);	/* + 0x6e          */
+		_MSCAN_RESERVED_(28, 2);	/* + 0x6e          */
 		u16 dsr5_4;			/* + 0x70     0x38 */
-		 _MSCAN_RESERVED_(28, 2);	/* + 0x72          */
+		_MSCAN_RESERVED_(29, 2);	/* + 0x72          */
 		u16 dsr7_6;			/* + 0x74     0x3a */
-		 _MSCAN_RESERVED_(29, 2);	/* + 0x76          */
+		_MSCAN_RESERVED_(30, 2);	/* + 0x76          */
 		u8 dlr;				/* + 0x78     0x3c */
 		u8 tbpr;			/* + 0x79     0x3d */
-		 _MSCAN_RESERVED_(30, 2);	/* + 0x7a          */
+		_MSCAN_RESERVED_(31, 2);	/* + 0x7a          */
 		u16 time;			/* + 0x7c     0x3e */
 	} tx;
-	 _MSCAN_RESERVED_(31, 2);		/* + 0x7e          */
+	_MSCAN_RESERVED_(32, 2);		/* + 0x7e          */
 } __attribute__ ((packed));
 
 #undef _MSCAN_RESERVED_
@@ -238,6 +239,12 @@ struct mscan_regs {
 #define MSCAN_SET_MODE_RETRIES	255
 #define MSCAN_ECHO_SKB_MAX	3
 
+/* MSCAN type variants */
+enum {
+	MSCAN_TYPE_MPC5200,
+	MSCAN_TYPE_MPC5121
+};
+
 #define BTR0_BRP_MASK		0x3f
 #define BTR0_SJW_SHIFT		6
 #define BTR0_SJW_MASK		(0x3 << BTR0_SJW_SHIFT)
@@ -270,6 +277,7 @@ struct tx_queue_entry {
 
 struct mscan_priv {
 	struct can_priv can;	/* must be the first member */
+	unsigned int type; 	/* MSCAN type variants */
 	long open_time;
 	unsigned long flags;
 	void __iomem *reg_base;	/* ioremap'ed address to registers */
@@ -285,11 +293,6 @@ struct mscan_priv {
 };
 
 extern struct net_device *alloc_mscandev(void);
-/*
- * clock_src:
- *	1 = The MSCAN clock source is the onchip Bus Clock.
- *	0 = The MSCAN clock source is the chip Oscillator Clock.
- */
 extern int register_mscandev(struct net_device *dev, int clock_src);
 extern void unregister_mscandev(struct net_device *dev);
 
-- 
1.6.2.5

^ permalink raw reply related

* [PATCH net-next 1/3] can: mscan: fix improper return if dlc < 8 in start_xmit function
From: Wolfgang Grandegger @ 2010-01-02  8:17 UTC (permalink / raw)
  To: Netdev
  Cc: Socketcan-core, Devicetree-discuss, Linuxppc-dev,
	Wolfgang Grandegger
In-Reply-To: <1262420274-16586-1-git-send-email-wg@grandegger.com>

From: Wolfgang Grandegger <wg@denx.de>

The start_xmit function of the MSCAN Driver did return improperly if
the CAN dlc check failed (skb not freed and invalid return code). This
patch adds a proper check of the frame lenght and data size and returns
now correctly. Furthermore, a typo has been fixed.

Signed-off-by: Wolfgang Grandegger <wg@denx.de>
---
 drivers/net/can/mscan/mscan.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index 07346f8..abdf5e8 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -4,7 +4,7 @@
  * Copyright (C) 2005-2006 Andrey Volkov <avolkov@varma-el.com>,
  *                         Varma Electronics Oy
  * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
- * Copytight (C) 2008-2009 Pengutronix <kernel@pengutronix.de>
+ * Copyright (C) 2008-2009 Pengutronix <kernel@pengutronix.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the version 2 of the GNU General Public License
@@ -177,8 +177,13 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	int i, rtr, buf_id;
 	u32 can_id;
 
-	if (frame->can_dlc > 8)
-		return -EINVAL;
+	if (skb->len != sizeof(*frame) || frame->can_dlc > 8) {
+		dev_err(dev->dev.parent,
+			"Dropping non-conform paket: len %d, can_dlc %d\n",
+			skb->len, frame->can_dlc);
+		kfree_skb(skb);
+		return  NETDEV_TX_OK;
+	}
 
 	out_8(&regs->cantier, 0);
 
-- 
1.6.2.5

^ permalink raw reply related

* [PATCH net-next 0/3] can: mscan-mpc5xxx: add support for the Freescale MPC512x
From: Wolfgang Grandegger @ 2010-01-02  8:17 UTC (permalink / raw)
  To: Netdev; +Cc: Socketcan-core, Devicetree-discuss, Linuxppc-dev

This patch series adds support for the MPC512x from Freescale to
the mpc5xxx_can MSCAN driver.

Wolfgang

Wolfgang Grandegger (3):
  can: mscan: fix improper return if dlc < 8 in start_xmit function
  can: mscan-mpc5xxx: add support for the MPC521x processor
  powerpc/mpc5xxx: add OF platform binding doc for FSL MSCAN devices

 Documentation/powerpc/dts-bindings/fsl/can.txt     |   53 +++++
 Documentation/powerpc/dts-bindings/fsl/mpc5200.txt |    9 +-
 drivers/net/can/mscan/Kconfig                      |    2 +-
 drivers/net/can/mscan/mpc5xxx_can.c                |  234 ++++++++++++++++----
 drivers/net/can/mscan/mscan.c                      |   52 ++++-
 drivers/net/can/mscan/mscan.h                      |   81 ++++----
 6 files changed, 333 insertions(+), 98 deletions(-)
 create mode 100644 Documentation/powerpc/dts-bindings/fsl/can.txt

^ permalink raw reply

* Re: [PATCH] HVSI: Fix apparently backwards args to time_before() in hvsi.c
From: Benjamin Herrenschmidt @ 2010-01-01 21:11 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: Joe Perches, linuxppc-dev, Robert P. J. Day,
	Linux Kernel Mailing List
In-Reply-To: <201001011915.47849.bzolnier@gmail.com>

On Fri, 2010-01-01 at 19:15 +0100, Bartlomiej Zolnierkiewicz wrote:
> On Friday 01 January 2010 06:28:03 pm Robert P. J. Day wrote:
> > 
> > Signed-off-by: Robert P. J. Day <rpjday@crashcourse.ca>
> > 
> > ---
> > 
> >   no appropriate subsystem maintainer listed in MAINTAINERS.
> 
> drivers/char/Makefile:
> obj-$(CONFIG_HVC_CONSOLE)       += hvc_vio.o hvsi.o
> 
> so it should belong to:
> 
> HYPERVISOR VIRTUAL CONSOLE DRIVER
> L:      linuxppc-dev@ozlabs.org
> S:      Odd Fixes
> F:      drivers/char/hvc_*
> 
> [ Though maybe Ben would be willing to pick this one up directly
>   as hvsi is PPC specific thingy and patch is obviously correct. ]

Sure, I'll pick that one up.

Cheers,
Ben.

> > diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
> > index 793b236..71c0fcd 100644
> > --- a/drivers/char/hvsi.c
> > +++ b/drivers/char/hvsi.c
> > @@ -711,7 +711,7 @@ static void hvsi_drain_input(struct hvsi_struct *hp)
> >  	uint8_t buf[HVSI_MAX_READ] __ALIGNED__;
> >  	unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
> > 
> > -	while (time_before(end_jiffies, jiffies))
> > +	while (time_before(jiffies, end_jiffies))
> >  		if (0 == hvsi_read(hp, buf, HVSI_MAX_READ))
> >  			break;
> >  }
> 
> --
> Bartlomiej Zolnierkiewicz
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH] HVSI: Fix apparently backwards args to time_before() in hvsi.c
From: Bartlomiej Zolnierkiewicz @ 2010-01-01 18:15 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Joe Perches, linuxppc-dev, Linux Kernel Mailing List
In-Reply-To: <alpine.LFD.2.00.1001011226020.24958@localhost>

On Friday 01 January 2010 06:28:03 pm Robert P. J. Day wrote:
> 
> Signed-off-by: Robert P. J. Day <rpjday@crashcourse.ca>
> 
> ---
> 
>   no appropriate subsystem maintainer listed in MAINTAINERS.

drivers/char/Makefile:
obj-$(CONFIG_HVC_CONSOLE)       += hvc_vio.o hvsi.o

so it should belong to:

HYPERVISOR VIRTUAL CONSOLE DRIVER
L:      linuxppc-dev@ozlabs.org
S:      Odd Fixes
F:      drivers/char/hvc_*

[ Though maybe Ben would be willing to pick this one up directly
  as hvsi is PPC specific thingy and patch is obviously correct. ]

> diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
> index 793b236..71c0fcd 100644
> --- a/drivers/char/hvsi.c
> +++ b/drivers/char/hvsi.c
> @@ -711,7 +711,7 @@ static void hvsi_drain_input(struct hvsi_struct *hp)
>  	uint8_t buf[HVSI_MAX_READ] __ALIGNED__;
>  	unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
> 
> -	while (time_before(end_jiffies, jiffies))
> +	while (time_before(jiffies, end_jiffies))
>  		if (0 == hvsi_read(hp, buf, HVSI_MAX_READ))
>  			break;
>  }

--
Bartlomiej Zolnierkiewicz

^ permalink raw reply

* Re: [PATCH v2 2/3] powerpc: Add support for creating FIT uImages
From: Wolfgang Denk @ 2010-01-01 14:18 UTC (permalink / raw)
  To: Grant Likely; +Cc: Peter Tyser, linux-kbuild, linuxppc-dev
In-Reply-To: <fa686aa40912301457l704c324bk511a207d07218525@mail.gmail.com>

Dear Grant,

In message <fa686aa40912301457l704c324bk511a207d07218525@mail.gmail.com> you wrote:
>
> Unfortunately, the wrapper script is also being used to do things that
> are completely unrelated to creating wrapper binaries.  FIT images
> (and uImages) don't use any of the wrapper bits at all.  In fact, as
> seen in this patch, generating them involves bailing out of the
> wrapper script early to avoid linking the wrapper bits.  I think for
> all types of uImages, the wrapper script is being misused and I don't
> like the extra complexity that it adds.

Agreed.

> Rather than adding new paths to arch/powerpc/boot/wrapper, I would
> rather see a new script used for generating FIT image that isn't
> complicated by all the current wrapper cruft.  Also, the Makefile rule
> doesn't need to depend on $(wrapperbits) which means faster build
> times when only building uImages.
> 
> Bonus points if you also convert the uImage target to use the new
> script; but I'm not demanding that you do that yet.

I think if this is handles in a separate script, the legacy uImage
support must be handled in this new script, too. Otherwise it would be
too difficult to understanmd the relation of the two image formats.

> Finally, you need to add documentation about the new target to
> Documentation/powerpc/bootwrapper.txt.

Let's keep in mind that the uImage formats (both the old legacy and
the new FIT format) are inherently architecture independent. We want
to use this same mechanism for example on ARM, and on other
architectures as well.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
How many Unix hacks does it take to change a light bulb?  Let's  see,
   can you use a shell script for that or does it need a C program?

^ permalink raw reply

* Re: [PATCH v2 3/3] powerpc: Add support for ram filesystems in FIT uImages
From: Wolfgang Denk @ 2010-01-01 14:12 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev, Peter Tyser, linux-kbuild, u-boot
In-Reply-To: <fa686aa40912301601s6cd0ec4y85b88976159a36af@mail.gmail.com>

Dear Grant,

In message <fa686aa40912301601s6cd0ec4y85b88976159a36af@mail.gmail.com> you wrote:
>
> Thinking further, I do actually have another concern, at least with
> regard to the way the current patch set implements things.  Is it
> expected or even "recommended" that fit images will *always* contain a
> .dtb image?  The current patch only handles the case of a .dtb
> embedded inside the fit image.

I think this can be expected.

Historically, the need to pass the dtb image to the Linux kernel,
too, was what actually triggered the development of the FIT image
format, as it turned out that the old image format with it's fixed
binary header was too inflexible. So bundling the kernel image and
the device tree blob into one image file is the specific use case
this image format was created for (which does not mean that other
usage would be impossible).

> Personally, I don't get any benefit out of the new image format, so I
> haven't spent any time looking at it.  However, I'm concerned about

Assume you want to boot over DHCP or similar, where you can provide
just a single image file for download. Here it is definitely nice if
you can bundle the kernel image and the DTB into one image file. We
were able to extend the old so-called "multi-file" uImage format to
handle this situation, too, but it was clear that further extensions
were not really possible.

We consider the old legace uImage format as something we want to move
away from, and the new FIT image format shall be the new default.

> the drift back towards a different image per target when the move over
> the last 4 years has been towards multiplatform kernel images.  I
> certainly don't want to encourage embedding the device tree blob into
> the kernel image, and I'm not very interested in merging code to do
> that into the kernel tree.  If someone really needs to do that for
> their particular target, it is certainly easy enough for them to weld
> in the .dtb after the fact before transferring the image to the
> target, but I want that mode to be the exception, not the rule.

This is specific for particular targets, but for  specific  modes  of
operation,  like  booting  over  the network or other szenarios where
transferring a single image file is essential - another example where
we often see this request is upgrade procedures for devics, where the
vendor wants to be able to distribute a single file  for  his  target
systems   to  avoid  customers  bricking  their  devices  by  chosing
incompatible combinations.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Perfection is reached, not when there is no longer anything  to  add,
but when there is no longer anything to take away.
                                           - Antoine de Saint-Exupery

^ permalink raw reply

* Re: [PATCH v2 3/3] powerpc: Add support for ram filesystems in FIT uImages
From: Wolfgang Denk @ 2010-01-01 10:44 UTC (permalink / raw)
  To: Peter Tyser; +Cc: linuxppc-dev, linux-kbuild
In-Reply-To: <1262301038.29396.137.camel@localhost.localdomain>

Dear Peter,

In message <1262301038.29396.137.camel@localhost.localdomain> you wrote:
> 
> > Why chose a different name at all? We could still call it "uImage",
> > meaning "U-Boot image" - U-Boot is clever enought o detect
> > automatically if we pass it an old style or a fit image.
> 
> I agree with your point to an extent, but having 2 types of uImages is
> somewhat confusing to a user, even if U-Boot can differentiate between
> them.  And if the legacy image and FIT image had the same Make target,
> how does a user specify which type they want to build?  The fact that
> both "legacy" and FIT images would reside at arch/powerpc/boot/uImage
> doesn't make things any less confusing to Joe User.

Agreed.

> Currently U-Boot supports booting:
> 1 "legacy" uImages
> 2 "new" Flattened Image Tree (FIT) uImages

The "legacy" uImage format has a number of restrictions not unsimilar
to the restrictions we had in the bootloader / kernel interface when
using the old binary bd_info data structur. For the kernel interface
this has been replaced by using the device tree, and I would like to
see the same happen in U-Boot.

The "new" FIT image type should become the default, and old "legacy"
images should only be generated upon special request (i. e. if some-
one needs these for compatibility with an old, not yet FIT-aware
version of the boot loader).

> What do you think about changing the U-Boot documentation to rename
> those 2 image types to:
> 1 uImages
> 2 FIT Images

Let's make this "uImage.old" (or "uImage.legacy" similar) and
"uImage", then.

> The FIT image is a relatively generic image type - its just a blob that
> dtc created from a device tree and some input binaries.  In my mind its
> not intimately tied to U-Boot, at least not conceptually.  The "legacy"

Correct. The intention was to provide an open and somewhat
"standardized" format that can be easily extended for new
requirements, whatever these may be.

> uImages have to agree with U-Boot's header format defined in the U-Boot
> source code, so the uImage name does make sense with respect to the
> "legacy" uImages.

Well, you can read "uImage" as "universal Image", which kind of fits
the FIT approach :-)

> My vote would be to make the Linux FIT target rule "fitImage" and then
> update the U-Boot documentation to make obvious the differences between
> uImages and FIT images.

I think we should not try to support both legacy and FIT images on the
same level - the idea is clearly that legacy images is the old, to be
replaced format, while FIT images is the new, to be used as standard
format. In this sense I vote for using plain and simple "uImage" for
the (new) standard format, and marking the old format by some ".old"
or ".legacy" suffix.

BTW: note that (IIRC) we don't even have a formal definition of the
"FIT" abbreviation yet ;-)

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
"The more data I punch in this card,  the lighter it becomes, and the
lower the mailing cost."
                     - Stan Kelly-Bootle, "The Devil's DP Dictionary"

^ permalink raw reply

* [PATCH 7/8] fsldma: rename fsl_chan to fchan
From: Ira W. Snyder @ 2010-01-01  6:10 UTC (permalink / raw)
  To: dan.j.williams
  Cc: herbert, B04825, linuxppc-dev, Vishnu, Dipen.Dudhat,
	Maneesh.Gupta, R58472
In-Reply-To: <1262326246-936-1-git-send-email-iws@ovro.caltech.edu>

The name fsl_chan seems too long, so it has been shortened to fchan.

Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
 drivers/dma/fsldma.c |  446 +++++++++++++++++++++++++-------------------------
 1 files changed, 223 insertions(+), 223 deletions(-)

diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index d8cc05b..f65b28b 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -37,19 +37,19 @@
 #include <asm/fsldma.h>
 #include "fsldma.h"
 
-static void dma_init(struct fsldma_chan *fsl_chan)
+static void dma_init(struct fsldma_chan *fchan)
 {
 	/* Reset the channel */
-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, 0, 32);
+	DMA_OUT(fchan, &fchan->regs->mr, 0, 32);
 
-	switch (fsl_chan->feature & FSL_DMA_IP_MASK) {
+	switch (fchan->feature & FSL_DMA_IP_MASK) {
 	case FSL_DMA_IP_85XX:
 		/* Set the channel to below modes:
 		 * EIE - Error interrupt enable
 		 * EOSIE - End of segments interrupt enable (basic mode)
 		 * EOLNIE - End of links interrupt enable
 		 */
-		DMA_OUT(fsl_chan, &fsl_chan->regs->mr, FSL_DMA_MR_EIE
+		DMA_OUT(fchan, &fchan->regs->mr, FSL_DMA_MR_EIE
 				| FSL_DMA_MR_EOLNIE | FSL_DMA_MR_EOSIE, 32);
 		break;
 	case FSL_DMA_IP_83XX:
@@ -57,154 +57,154 @@ static void dma_init(struct fsldma_chan *fsl_chan)
 		 * EOTIE - End-of-transfer interrupt enable
 		 * PRC_RM - PCI read multiple
 		 */
-		DMA_OUT(fsl_chan, &fsl_chan->regs->mr, FSL_DMA_MR_EOTIE
+		DMA_OUT(fchan, &fchan->regs->mr, FSL_DMA_MR_EOTIE
 				| FSL_DMA_MR_PRC_RM, 32);
 		break;
 	}
 
 }
 
-static void set_sr(struct fsldma_chan *fsl_chan, u32 val)
+static void set_sr(struct fsldma_chan *fchan, u32 val)
 {
-	DMA_OUT(fsl_chan, &fsl_chan->regs->sr, val, 32);
+	DMA_OUT(fchan, &fchan->regs->sr, val, 32);
 }
 
-static u32 get_sr(struct fsldma_chan *fsl_chan)
+static u32 get_sr(struct fsldma_chan *fchan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->regs->sr, 32);
+	return DMA_IN(fchan, &fchan->regs->sr, 32);
 }
 
-static void set_desc_cnt(struct fsldma_chan *fsl_chan,
+static void set_desc_cnt(struct fsldma_chan *fchan,
 				struct fsl_dma_ld_hw *hw, u32 count)
 {
-	hw->count = CPU_TO_DMA(fsl_chan, count, 32);
+	hw->count = CPU_TO_DMA(fchan, count, 32);
 }
 
-static void set_desc_src(struct fsldma_chan *fsl_chan,
+static void set_desc_src(struct fsldma_chan *fchan,
 				struct fsl_dma_ld_hw *hw, dma_addr_t src)
 {
 	u64 snoop_bits;
 
-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+	snoop_bits = ((fchan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
 		? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
-	hw->src_addr = CPU_TO_DMA(fsl_chan, snoop_bits | src, 64);
+	hw->src_addr = CPU_TO_DMA(fchan, snoop_bits | src, 64);
 }
 
-static void set_desc_dst(struct fsldma_chan *fsl_chan,
+static void set_desc_dst(struct fsldma_chan *fchan,
 				struct fsl_dma_ld_hw *hw, dma_addr_t dst)
 {
 	u64 snoop_bits;
 
-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+	snoop_bits = ((fchan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
 		? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
-	hw->dst_addr = CPU_TO_DMA(fsl_chan, snoop_bits | dst, 64);
+	hw->dst_addr = CPU_TO_DMA(fchan, snoop_bits | dst, 64);
 }
 
-static void set_desc_next(struct fsldma_chan *fsl_chan,
+static void set_desc_next(struct fsldma_chan *fchan,
 				struct fsl_dma_ld_hw *hw, dma_addr_t next)
 {
 	u64 snoop_bits;
 
-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+	snoop_bits = ((fchan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
 		? FSL_DMA_SNEN : 0;
-	hw->next_ln_addr = CPU_TO_DMA(fsl_chan, snoop_bits | next, 64);
+	hw->next_ln_addr = CPU_TO_DMA(fchan, snoop_bits | next, 64);
 }
 
-static void set_cdar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
+static void set_cdar(struct fsldma_chan *fchan, dma_addr_t addr)
 {
-	DMA_OUT(fsl_chan, &fsl_chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
+	DMA_OUT(fchan, &fchan->regs->cdar, addr | FSL_DMA_SNEN, 64);
 }
 
-static dma_addr_t get_cdar(struct fsldma_chan *fsl_chan)
+static dma_addr_t get_cdar(struct fsldma_chan *fchan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
+	return DMA_IN(fchan, &fchan->regs->cdar, 64) & ~FSL_DMA_SNEN;
 }
 
-static void set_ndar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
+static void set_ndar(struct fsldma_chan *fchan, dma_addr_t addr)
 {
-	DMA_OUT(fsl_chan, &fsl_chan->regs->ndar, addr, 64);
+	DMA_OUT(fchan, &fchan->regs->ndar, addr, 64);
 }
 
-static dma_addr_t get_ndar(struct fsldma_chan *fsl_chan)
+static dma_addr_t get_ndar(struct fsldma_chan *fchan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->regs->ndar, 64);
+	return DMA_IN(fchan, &fchan->regs->ndar, 64);
 }
 
-static u32 get_bcr(struct fsldma_chan *fsl_chan)
+static u32 get_bcr(struct fsldma_chan *fchan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->regs->bcr, 32);
+	return DMA_IN(fchan, &fchan->regs->bcr, 32);
 }
 
-static int dma_is_idle(struct fsldma_chan *fsl_chan)
+static int dma_is_idle(struct fsldma_chan *fchan)
 {
-	u32 sr = get_sr(fsl_chan);
+	u32 sr = get_sr(fchan);
 	return (!(sr & FSL_DMA_SR_CB)) || (sr & FSL_DMA_SR_CH);
 }
 
-static void dma_start(struct fsldma_chan *fsl_chan)
+static void dma_start(struct fsldma_chan *fchan)
 {
 	u32 mode;
 
-	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
+	mode = DMA_IN(fchan, &fchan->regs->mr, 32);
 
-	if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
-		if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
-			DMA_OUT(fsl_chan, &fsl_chan->regs->bcr, 0, 32);
+	if ((fchan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+		if (fchan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
+			DMA_OUT(fchan, &fchan->regs->bcr, 0, 32);
 			mode |= FSL_DMA_MR_EMP_EN;
 		} else {
 			mode &= ~FSL_DMA_MR_EMP_EN;
 		}
 	}
 
-	if (fsl_chan->feature & FSL_DMA_CHAN_START_EXT)
+	if (fchan->feature & FSL_DMA_CHAN_START_EXT)
 		mode |= FSL_DMA_MR_EMS_EN;
 	else
 		mode |= FSL_DMA_MR_CS;
 
-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+	DMA_OUT(fchan, &fchan->regs->mr, mode, 32);
 }
 
-static void dma_halt(struct fsldma_chan *fsl_chan)
+static void dma_halt(struct fsldma_chan *fchan)
 {
 	u32 mode;
 	int i;
 
-	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
+	mode = DMA_IN(fchan, &fchan->regs->mr, 32);
 	mode |= FSL_DMA_MR_CA;
-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+	DMA_OUT(fchan, &fchan->regs->mr, mode, 32);
 
 	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA);
-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+	DMA_OUT(fchan, &fchan->regs->mr, mode, 32);
 
 	for (i = 0; i < 100; i++) {
-		if (dma_is_idle(fsl_chan))
+		if (dma_is_idle(fchan))
 			break;
 		udelay(10);
 	}
 
-	if (i >= 100 && !dma_is_idle(fsl_chan))
-		dev_err(fsl_chan->dev, "DMA halt timeout!\n");
+	if (i >= 100 && !dma_is_idle(fchan))
+		dev_err(fchan->dev, "DMA halt timeout!\n");
 }
 
-static void set_ld_eol(struct fsldma_chan *fsl_chan,
+static void set_ld_eol(struct fsldma_chan *fchan,
 			struct fsl_desc_sw *desc)
 {
 	u64 snoop_bits;
 
-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+	snoop_bits = ((fchan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
 		? FSL_DMA_SNEN : 0;
 
-	desc->hw.next_ln_addr = CPU_TO_DMA(fsl_chan,
-		DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
+	desc->hw.next_ln_addr = CPU_TO_DMA(fchan,
+		DMA_TO_CPU(fchan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
 			| snoop_bits, 64);
 }
 
-static void append_ld_queue(struct fsldma_chan *fsl_chan,
+static void append_ld_queue(struct fsldma_chan *fchan,
 		struct fsl_desc_sw *new_desc)
 {
-	struct fsl_desc_sw *queue_tail = to_fsl_desc(fsl_chan->ld_queue.prev);
+	struct fsl_desc_sw *queue_tail = to_fsl_desc(fchan->ld_queue.prev);
 
-	if (list_empty(&fsl_chan->ld_queue))
+	if (list_empty(&fchan->ld_queue))
 		return;
 
 	/* Link to the new descriptor physical address and
@@ -214,15 +214,15 @@ static void append_ld_queue(struct fsldma_chan *fsl_chan,
 	 *
 	 * For FSL_DMA_IP_83xx, the snoop enable bit need be set.
 	 */
-	queue_tail->hw.next_ln_addr = CPU_TO_DMA(fsl_chan,
+	queue_tail->hw.next_ln_addr = CPU_TO_DMA(fchan,
 			new_desc->async_tx.phys | FSL_DMA_EOSIE |
-			(((fsl_chan->feature & FSL_DMA_IP_MASK)
+			(((fchan->feature & FSL_DMA_IP_MASK)
 				== FSL_DMA_IP_83XX) ? FSL_DMA_SNEN : 0), 64);
 }
 
 /**
  * fsl_chan_set_src_loop_size - Set source address hold transfer size
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  * @size     : Address loop size, 0 for disable loop
  *
  * The set source address hold transfer size. The source
@@ -231,11 +231,11 @@ static void append_ld_queue(struct fsldma_chan *fsl_chan,
  * read data from SA, SA + 1, SA + 2, SA + 3, then loop back to SA,
  * SA + 1 ... and so on.
  */
-static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
+static void fsl_chan_set_src_loop_size(struct fsldma_chan *fchan, int size)
 {
 	u32 mode;
 
-	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
+	mode = DMA_IN(fchan, &fchan->regs->mr, 32);
 
 	switch (size) {
 	case 0:
@@ -249,12 +249,12 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
 		break;
 	}
 
-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+	DMA_OUT(fchan, &fchan->regs->mr, mode, 32);
 }
 
 /**
  * fsl_chan_set_dst_loop_size - Set destination address hold transfer size
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  * @size     : Address loop size, 0 for disable loop
  *
  * The set destination address hold transfer size. The destination
@@ -263,11 +263,11 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
  * write data to TA, TA + 1, TA + 2, TA + 3, then loop back to TA,
  * TA + 1 ... and so on.
  */
-static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
+static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fchan, int size)
 {
 	u32 mode;
 
-	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
+	mode = DMA_IN(fchan, &fchan->regs->mr, 32);
 
 	switch (size) {
 	case 0:
@@ -281,12 +281,12 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
 		break;
 	}
 
-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+	DMA_OUT(fchan, &fchan->regs->mr, mode, 32);
 }
 
 /**
  * fsl_chan_set_request_count - Set DMA Request Count for external control
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  * @size     : Number of bytes to transfer in a single request
  *
  * The Freescale DMA channel can be controlled by the external signal DREQ#.
@@ -296,38 +296,38 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
  *
  * A size of 0 disables external pause control. The maximum size is 1024.
  */
-static void fsl_chan_set_request_count(struct fsldma_chan *fsl_chan, int size)
+static void fsl_chan_set_request_count(struct fsldma_chan *fchan, int size)
 {
 	u32 mode;
 
 	BUG_ON(size > 1024);
 
-	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
+	mode = DMA_IN(fchan, &fchan->regs->mr, 32);
 	mode |= (__ilog2(size) << 24) & 0x0f000000;
 
-	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
+	DMA_OUT(fchan, &fchan->regs->mr, mode, 32);
 }
 
 /**
  * fsl_chan_toggle_ext_pause - Toggle channel external pause status
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  * @enable   : 0 is disabled, 1 is enabled.
  *
  * The Freescale DMA channel can be controlled by the external signal DREQ#.
  * The DMA Request Count feature should be used in addition to this feature
  * to set the number of bytes to transfer before pausing the channel.
  */
-static void fsl_chan_toggle_ext_pause(struct fsldma_chan *fsl_chan, int enable)
+static void fsl_chan_toggle_ext_pause(struct fsldma_chan *fchan, int enable)
 {
 	if (enable)
-		fsl_chan->feature |= FSL_DMA_CHAN_PAUSE_EXT;
+		fchan->feature |= FSL_DMA_CHAN_PAUSE_EXT;
 	else
-		fsl_chan->feature &= ~FSL_DMA_CHAN_PAUSE_EXT;
+		fchan->feature &= ~FSL_DMA_CHAN_PAUSE_EXT;
 }
 
 /**
  * fsl_chan_toggle_ext_start - Toggle channel external start status
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  * @enable   : 0 is disabled, 1 is enabled.
  *
  * If enable the external start, the channel can be started by an
@@ -335,26 +335,26 @@ static void fsl_chan_toggle_ext_pause(struct fsldma_chan *fsl_chan, int enable)
  * transfer immediately. The DMA channel will wait for the
  * control pin asserted.
  */
-static void fsl_chan_toggle_ext_start(struct fsldma_chan *fsl_chan, int enable)
+static void fsl_chan_toggle_ext_start(struct fsldma_chan *fchan, int enable)
 {
 	if (enable)
-		fsl_chan->feature |= FSL_DMA_CHAN_START_EXT;
+		fchan->feature |= FSL_DMA_CHAN_START_EXT;
 	else
-		fsl_chan->feature &= ~FSL_DMA_CHAN_START_EXT;
+		fchan->feature &= ~FSL_DMA_CHAN_START_EXT;
 }
 
 static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 {
-	struct fsldma_chan *fsl_chan = to_fsl_chan(tx->chan);
+	struct fsldma_chan *fchan = to_fsl_chan(tx->chan);
 	struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
 	struct fsl_desc_sw *child;
 	unsigned long flags;
 	dma_cookie_t cookie;
 
 	/* cookie increment and adding to ld_queue must be atomic */
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+	spin_lock_irqsave(&fchan->desc_lock, flags);
 
-	cookie = fsl_chan->common.cookie;
+	cookie = fchan->common.cookie;
 	list_for_each_entry(child, &desc->tx_list, node) {
 		cookie++;
 		if (cookie < 0)
@@ -363,33 +363,33 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 		desc->async_tx.cookie = cookie;
 	}
 
-	fsl_chan->common.cookie = cookie;
-	append_ld_queue(fsl_chan, desc);
-	list_splice_init(&desc->tx_list, fsl_chan->ld_queue.prev);
+	fchan->common.cookie = cookie;
+	append_ld_queue(fchan, desc);
+	list_splice_init(&desc->tx_list, fchan->ld_queue.prev);
 
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+	spin_unlock_irqrestore(&fchan->desc_lock, flags);
 
 	return cookie;
 }
 
 /**
  * fsl_dma_alloc_descriptor - Allocate descriptor from channel's DMA pool.
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  *
  * Return - The descriptor allocated. NULL for failed.
  */
 static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
-					struct fsldma_chan *fsl_chan)
+					struct fsldma_chan *fchan)
 {
 	dma_addr_t pdesc;
 	struct fsl_desc_sw *desc_sw;
 
-	desc_sw = dma_pool_alloc(fsl_chan->desc_pool, GFP_ATOMIC, &pdesc);
+	desc_sw = dma_pool_alloc(fchan->desc_pool, GFP_ATOMIC, &pdesc);
 	if (desc_sw) {
 		memset(desc_sw, 0, sizeof(struct fsl_desc_sw));
 		INIT_LIST_HEAD(&desc_sw->tx_list);
 		dma_async_tx_descriptor_init(&desc_sw->async_tx,
-						&fsl_chan->common);
+						&fchan->common);
 		desc_sw->async_tx.tx_submit = fsl_dma_tx_submit;
 		desc_sw->async_tx.phys = pdesc;
 	}
@@ -400,7 +400,7 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
 
 /**
  * fsl_dma_alloc_chan_resources - Allocate resources for DMA channel.
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  *
  * This function will create a dma pool for descriptor allocation.
  *
@@ -408,21 +408,21 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
  */
 static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
 {
-	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsldma_chan *fchan = to_fsl_chan(chan);
 
 	/* Has this channel already been allocated? */
-	if (fsl_chan->desc_pool)
+	if (fchan->desc_pool)
 		return 1;
 
 	/* We need the descriptor to be aligned to 32bytes
 	 * for meeting FSL DMA specification requirement.
 	 */
-	fsl_chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
-			fsl_chan->dev, sizeof(struct fsl_desc_sw),
+	fchan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
+			fchan->dev, sizeof(struct fsl_desc_sw),
 			32, 0);
-	if (!fsl_chan->desc_pool) {
-		dev_err(fsl_chan->dev, "No memory for channel %d "
-			"descriptor dma pool.\n", fsl_chan->id);
+	if (!fchan->desc_pool) {
+		dev_err(fchan->dev, "No memory for channel %d "
+			"descriptor dma pool.\n", fchan->id);
 		return 0;
 	}
 
@@ -431,45 +431,45 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
 
 /**
  * fsl_dma_free_chan_resources - Free all resources of the channel.
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  */
 static void fsl_dma_free_chan_resources(struct dma_chan *chan)
 {
-	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsldma_chan *fchan = to_fsl_chan(chan);
 	struct fsl_desc_sw *desc, *_desc;
 	unsigned long flags;
 
-	dev_dbg(fsl_chan->dev, "Free all channel resources.\n");
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
-	list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) {
+	dev_dbg(fchan->dev, "Free all channel resources.\n");
+	spin_lock_irqsave(&fchan->desc_lock, flags);
+	list_for_each_entry_safe(desc, _desc, &fchan->ld_queue, node) {
 #ifdef FSL_DMA_LD_DEBUG
-		dev_dbg(fsl_chan->dev,
+		dev_dbg(fchan->dev,
 				"LD %p will be released.\n", desc);
 #endif
 		list_del(&desc->node);
 		/* free link descriptor */
-		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
+		dma_pool_free(fchan->desc_pool, desc, desc->async_tx.phys);
 	}
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
-	dma_pool_destroy(fsl_chan->desc_pool);
+	spin_unlock_irqrestore(&fchan->desc_lock, flags);
+	dma_pool_destroy(fchan->desc_pool);
 
-	fsl_chan->desc_pool = NULL;
+	fchan->desc_pool = NULL;
 }
 
 static struct dma_async_tx_descriptor *
 fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
 {
-	struct fsldma_chan *fsl_chan;
+	struct fsldma_chan *fchan;
 	struct fsl_desc_sw *new;
 
 	if (!chan)
 		return NULL;
 
-	fsl_chan = to_fsl_chan(chan);
+	fchan = to_fsl_chan(chan);
 
-	new = fsl_dma_alloc_descriptor(fsl_chan);
+	new = fsl_dma_alloc_descriptor(fchan);
 	if (!new) {
-		dev_err(fsl_chan->dev, "No free memory for link descriptor\n");
+		dev_err(fchan->dev, "No free memory for link descriptor\n");
 		return NULL;
 	}
 
@@ -480,7 +480,7 @@ fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
 	list_add_tail(&new->node, &new->tx_list);
 
 	/* Set End-of-link to the last link descriptor of new list*/
-	set_ld_eol(fsl_chan, new);
+	set_ld_eol(fchan, new);
 
 	return &new->async_tx;
 }
@@ -489,7 +489,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
 	struct dma_chan *chan, dma_addr_t dma_dst, dma_addr_t dma_src,
 	size_t len, unsigned long flags)
 {
-	struct fsldma_chan *fsl_chan;
+	struct fsldma_chan *fchan;
 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new;
 	struct list_head *list;
 	size_t copy;
@@ -500,31 +500,31 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
 	if (!len)
 		return NULL;
 
-	fsl_chan = to_fsl_chan(chan);
+	fchan = to_fsl_chan(chan);
 
 	do {
 
 		/* Allocate the link descriptor from DMA pool */
-		new = fsl_dma_alloc_descriptor(fsl_chan);
+		new = fsl_dma_alloc_descriptor(fchan);
 		if (!new) {
-			dev_err(fsl_chan->dev,
+			dev_err(fchan->dev,
 					"No free memory for link descriptor\n");
 			goto fail;
 		}
 #ifdef FSL_DMA_LD_DEBUG
-		dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
+		dev_dbg(fchan->dev, "new link desc alloc %p\n", new);
 #endif
 
 		copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT);
 
-		set_desc_cnt(fsl_chan, &new->hw, copy);
-		set_desc_src(fsl_chan, &new->hw, dma_src);
-		set_desc_dst(fsl_chan, &new->hw, dma_dst);
+		set_desc_cnt(fchan, &new->hw, copy);
+		set_desc_src(fchan, &new->hw, dma_src);
+		set_desc_dst(fchan, &new->hw, dma_dst);
 
 		if (!first)
 			first = new;
 		else
-			set_desc_next(fsl_chan, &prev->hw, new->async_tx.phys);
+			set_desc_next(fchan, &prev->hw, new->async_tx.phys);
 
 		new->async_tx.cookie = 0;
 		async_tx_ack(&new->async_tx);
@@ -542,7 +542,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
 	new->async_tx.cookie = -EBUSY;
 
 	/* Set End-of-link to the last link descriptor of new list*/
-	set_ld_eol(fsl_chan, new);
+	set_ld_eol(fchan, new);
 
 	return &first->async_tx;
 
@@ -553,7 +553,7 @@ fail:
 	list = &first->tx_list;
 	list_for_each_entry_safe_reverse(new, prev, list, node) {
 		list_del(&new->node);
-		dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);
+		dma_pool_free(fchan->desc_pool, new, new->async_tx.phys);
 	}
 
 	return NULL;
@@ -575,7 +575,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
 	struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
 	enum dma_data_direction direction, unsigned long flags)
 {
-	struct fsldma_chan *fsl_chan;
+	struct fsldma_chan *fchan;
 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;
 	struct fsl_dma_slave *slave;
 	struct list_head *tx_list;
@@ -594,7 +594,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
 	if (!chan->private)
 		return NULL;
 
-	fsl_chan = to_fsl_chan(chan);
+	fchan = to_fsl_chan(chan);
 	slave = chan->private;
 
 	if (list_empty(&slave->addresses))
@@ -644,14 +644,14 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
 			}
 
 			/* Allocate the link descriptor from DMA pool */
-			new = fsl_dma_alloc_descriptor(fsl_chan);
+			new = fsl_dma_alloc_descriptor(fchan);
 			if (!new) {
-				dev_err(fsl_chan->dev, "No free memory for "
+				dev_err(fchan->dev, "No free memory for "
 						       "link descriptor\n");
 				goto fail;
 			}
 #ifdef FSL_DMA_LD_DEBUG
-			dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
+			dev_dbg(fchan->dev, "new link desc alloc %p\n", new);
 #endif
 
 			/*
@@ -678,9 +678,9 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
 			}
 
 			/* Fill in the descriptor */
-			set_desc_cnt(fsl_chan, &new->hw, copy);
-			set_desc_src(fsl_chan, &new->hw, dma_src);
-			set_desc_dst(fsl_chan, &new->hw, dma_dst);
+			set_desc_cnt(fchan, &new->hw, copy);
+			set_desc_src(fchan, &new->hw, dma_src);
+			set_desc_dst(fchan, &new->hw, dma_dst);
 
 			/*
 			 * If this is not the first descriptor, chain the
@@ -689,7 +689,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
 			if (!first) {
 				first = new;
 			} else {
-				set_desc_next(fsl_chan, &prev->hw,
+				set_desc_next(fchan, &prev->hw,
 					      new->async_tx.phys);
 			}
 
@@ -715,23 +715,23 @@ finished:
 	new->async_tx.cookie = -EBUSY;
 
 	/* Set End-of-link to the last link descriptor of new list */
-	set_ld_eol(fsl_chan, new);
+	set_ld_eol(fchan, new);
 
 	/* Enable extra controller features */
-	if (fsl_chan->set_src_loop_size)
-		fsl_chan->set_src_loop_size(fsl_chan, slave->src_loop_size);
+	if (fchan->set_src_loop_size)
+		fchan->set_src_loop_size(fchan, slave->src_loop_size);
 
-	if (fsl_chan->set_dst_loop_size)
-		fsl_chan->set_dst_loop_size(fsl_chan, slave->dst_loop_size);
+	if (fchan->set_dst_loop_size)
+		fchan->set_dst_loop_size(fchan, slave->dst_loop_size);
 
-	if (fsl_chan->toggle_ext_start)
-		fsl_chan->toggle_ext_start(fsl_chan, slave->external_start);
+	if (fchan->toggle_ext_start)
+		fchan->toggle_ext_start(fchan, slave->external_start);
 
-	if (fsl_chan->toggle_ext_pause)
-		fsl_chan->toggle_ext_pause(fsl_chan, slave->external_pause);
+	if (fchan->toggle_ext_pause)
+		fchan->toggle_ext_pause(fchan, slave->external_pause);
 
-	if (fsl_chan->set_request_count)
-		fsl_chan->set_request_count(fsl_chan, slave->request_count);
+	if (fchan->set_request_count)
+		fchan->set_request_count(fchan, slave->request_count);
 
 	return &first->async_tx;
 
@@ -751,7 +751,7 @@ fail:
 	tx_list = &first->tx_list;
 	list_for_each_entry_safe_reverse(new, prev, tx_list, node) {
 		list_del_init(&new->node);
-		dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);
+		dma_pool_free(fchan->desc_pool, new, new->async_tx.phys);
 	}
 
 	return NULL;
@@ -759,54 +759,54 @@ fail:
 
 static void fsl_dma_device_terminate_all(struct dma_chan *chan)
 {
-	struct fsldma_chan *fsl_chan;
+	struct fsldma_chan *fchan;
 	struct fsl_desc_sw *desc, *tmp;
 	unsigned long flags;
 
 	if (!chan)
 		return;
 
-	fsl_chan = to_fsl_chan(chan);
+	fchan = to_fsl_chan(chan);
 
 	/* Halt the DMA engine */
-	dma_halt(fsl_chan);
+	dma_halt(fchan);
 
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+	spin_lock_irqsave(&fchan->desc_lock, flags);
 
 	/* Remove and free all of the descriptors in the LD queue */
-	list_for_each_entry_safe(desc, tmp, &fsl_chan->ld_queue, node) {
+	list_for_each_entry_safe(desc, tmp, &fchan->ld_queue, node) {
 		list_del(&desc->node);
-		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
+		dma_pool_free(fchan->desc_pool, desc, desc->async_tx.phys);
 	}
 
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+	spin_unlock_irqrestore(&fchan->desc_lock, flags);
 }
 
 /**
  * fsl_dma_update_completed_cookie - Update the completed cookie.
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  */
-static void fsl_dma_update_completed_cookie(struct fsldma_chan *fsl_chan)
+static void fsl_dma_update_completed_cookie(struct fsldma_chan *fchan)
 {
 	struct fsl_desc_sw *cur_desc, *desc;
 	dma_addr_t ld_phy;
 
-	ld_phy = get_cdar(fsl_chan) & FSL_DMA_NLDA_MASK;
+	ld_phy = get_cdar(fchan) & FSL_DMA_NLDA_MASK;
 
 	if (ld_phy) {
 		cur_desc = NULL;
-		list_for_each_entry(desc, &fsl_chan->ld_queue, node)
+		list_for_each_entry(desc, &fchan->ld_queue, node)
 			if (desc->async_tx.phys == ld_phy) {
 				cur_desc = desc;
 				break;
 			}
 
 		if (cur_desc && cur_desc->async_tx.cookie) {
-			if (dma_is_idle(fsl_chan))
-				fsl_chan->completed_cookie =
+			if (dma_is_idle(fchan))
+				fchan->completed_cookie =
 					cur_desc->async_tx.cookie;
 			else
-				fsl_chan->completed_cookie =
+				fchan->completed_cookie =
 					cur_desc->async_tx.cookie - 1;
 		}
 	}
@@ -814,27 +814,27 @@ static void fsl_dma_update_completed_cookie(struct fsldma_chan *fsl_chan)
 
 /**
  * fsl_chan_ld_cleanup - Clean up link descriptors
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  *
  * This function clean up the ld_queue of DMA channel.
  * If 'in_intr' is set, the function will move the link descriptor to
  * the recycle list. Otherwise, free it directly.
  */
-static void fsl_chan_ld_cleanup(struct fsldma_chan *fsl_chan)
+static void fsl_chan_ld_cleanup(struct fsldma_chan *fchan)
 {
 	struct fsl_desc_sw *desc, *_desc;
 	unsigned long flags;
 
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+	spin_lock_irqsave(&fchan->desc_lock, flags);
 
-	dev_dbg(fsl_chan->dev, "chan completed_cookie = %d\n",
-			fsl_chan->completed_cookie);
-	list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) {
+	dev_dbg(fchan->dev, "chan completed_cookie = %d\n",
+			fchan->completed_cookie);
+	list_for_each_entry_safe(desc, _desc, &fchan->ld_queue, node) {
 		dma_async_tx_callback callback;
 		void *callback_param;
 
 		if (dma_async_is_complete(desc->async_tx.cookie,
-			    fsl_chan->completed_cookie, fsl_chan->common.cookie)
+			    fchan->completed_cookie, fchan->common.cookie)
 				== DMA_IN_PROGRESS)
 			break;
 
@@ -844,119 +844,119 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *fsl_chan)
 		/* Remove from ld_queue list */
 		list_del(&desc->node);
 
-		dev_dbg(fsl_chan->dev, "link descriptor %p will be recycle.\n",
+		dev_dbg(fchan->dev, "link descriptor %p will be recycle.\n",
 				desc);
-		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
+		dma_pool_free(fchan->desc_pool, desc, desc->async_tx.phys);
 
 		/* Run the link descriptor callback function */
 		if (callback) {
-			spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
-			dev_dbg(fsl_chan->dev, "link descriptor %p callback\n",
+			spin_unlock_irqrestore(&fchan->desc_lock, flags);
+			dev_dbg(fchan->dev, "link descriptor %p callback\n",
 					desc);
 			callback(callback_param);
-			spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+			spin_lock_irqsave(&fchan->desc_lock, flags);
 		}
 	}
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+	spin_unlock_irqrestore(&fchan->desc_lock, flags);
 }
 
 /**
  * fsl_chan_xfer_ld_queue - Transfer link descriptors in channel ld_queue.
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  */
-static void fsl_chan_xfer_ld_queue(struct fsldma_chan *fsl_chan)
+static void fsl_chan_xfer_ld_queue(struct fsldma_chan *fchan)
 {
 	struct list_head *ld_node;
 	dma_addr_t next_dst_addr;
 	unsigned long flags;
 
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+	spin_lock_irqsave(&fchan->desc_lock, flags);
 
-	if (!dma_is_idle(fsl_chan))
+	if (!dma_is_idle(fchan))
 		goto out_unlock;
 
-	dma_halt(fsl_chan);
+	dma_halt(fchan);
 
 	/* If there are some link descriptors
 	 * not transfered in queue. We need to start it.
 	 */
 
 	/* Find the first un-transfer desciptor */
-	for (ld_node = fsl_chan->ld_queue.next;
-		(ld_node != &fsl_chan->ld_queue)
+	for (ld_node = fchan->ld_queue.next;
+		(ld_node != &fchan->ld_queue)
 			&& (dma_async_is_complete(
 				to_fsl_desc(ld_node)->async_tx.cookie,
-				fsl_chan->completed_cookie,
-				fsl_chan->common.cookie) == DMA_SUCCESS);
+				fchan->completed_cookie,
+				fchan->common.cookie) == DMA_SUCCESS);
 		ld_node = ld_node->next);
 
-	if (ld_node != &fsl_chan->ld_queue) {
+	if (ld_node != &fchan->ld_queue) {
 		/* Get the ld start address from ld_queue */
 		next_dst_addr = to_fsl_desc(ld_node)->async_tx.phys;
-		dev_dbg(fsl_chan->dev, "xfer LDs staring from 0x%llx\n",
+		dev_dbg(fchan->dev, "xfer LDs staring from 0x%llx\n",
 				(unsigned long long)next_dst_addr);
-		set_cdar(fsl_chan, next_dst_addr);
-		dma_start(fsl_chan);
+		set_cdar(fchan, next_dst_addr);
+		dma_start(fchan);
 	} else {
-		set_cdar(fsl_chan, 0);
-		set_ndar(fsl_chan, 0);
+		set_cdar(fchan, 0);
+		set_ndar(fchan, 0);
 	}
 
 out_unlock:
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+	spin_unlock_irqrestore(&fchan->desc_lock, flags);
 }
 
 /**
  * fsl_dma_memcpy_issue_pending - Issue the DMA start command
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  */
 static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan)
 {
-	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsldma_chan *fchan = to_fsl_chan(chan);
 
 #ifdef FSL_DMA_LD_DEBUG
 	struct fsl_desc_sw *ld;
 	unsigned long flags;
 
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
-	if (list_empty(&fsl_chan->ld_queue)) {
-		spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+	spin_lock_irqsave(&fchan->desc_lock, flags);
+	if (list_empty(&fchan->ld_queue)) {
+		spin_unlock_irqrestore(&fchan->desc_lock, flags);
 		return;
 	}
 
-	dev_dbg(fsl_chan->dev, "--memcpy issue--\n");
-	list_for_each_entry(ld, &fsl_chan->ld_queue, node) {
+	dev_dbg(fchan->dev, "--memcpy issue--\n");
+	list_for_each_entry(ld, &fchan->ld_queue, node) {
 		int i;
-		dev_dbg(fsl_chan->dev, "Ch %d, LD %08x\n",
-				fsl_chan->id, ld->async_tx.phys);
+		dev_dbg(fchan->dev, "Ch %d, LD %08x\n",
+				fchan->id, ld->async_tx.phys);
 		for (i = 0; i < 8; i++)
-			dev_dbg(fsl_chan->dev, "LD offset %d: %08x\n",
+			dev_dbg(fchan->dev, "LD offset %d: %08x\n",
 					i, *(((u32 *)&ld->hw) + i));
 	}
-	dev_dbg(fsl_chan->dev, "----------------\n");
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+	dev_dbg(fchan->dev, "----------------\n");
+	spin_unlock_irqrestore(&fchan->desc_lock, flags);
 #endif
 
-	fsl_chan_xfer_ld_queue(fsl_chan);
+	fsl_chan_xfer_ld_queue(fchan);
 }
 
 /**
  * fsl_dma_is_complete - Determine the DMA status
- * @fsl_chan : Freescale DMA channel
+ * @fchan : Freescale DMA channel
  */
 static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
 					dma_cookie_t cookie,
 					dma_cookie_t *done,
 					dma_cookie_t *used)
 {
-	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsldma_chan *fchan = to_fsl_chan(chan);
 	dma_cookie_t last_used;
 	dma_cookie_t last_complete;
 
-	fsl_chan_ld_cleanup(fsl_chan);
+	fsl_chan_ld_cleanup(fchan);
 
 	last_used = chan->cookie;
-	last_complete = fsl_chan->completed_cookie;
+	last_complete = fchan->completed_cookie;
 
 	if (done)
 		*done = last_complete;
@@ -969,30 +969,30 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
 
 static irqreturn_t fsldma_chan_irq(int irq, void *data)
 {
-	struct fsldma_chan *fsl_chan = data;
-	u32 stat;
+	struct fsldma_chan *fchan = data;
 	int update_cookie = 0;
 	int xfer_ld_q = 0;
+	u32 stat;
 
-	stat = get_sr(fsl_chan);
-	dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n",
-						fsl_chan->id, stat);
-	set_sr(fsl_chan, stat);		/* Clear the event register */
+	stat = get_sr(fchan);
+	dev_dbg(fchan->dev, "event: channel %d, stat = 0x%x\n",
+						fchan->id, stat);
+	set_sr(fchan, stat);		/* Clear the event register */
 
 	stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
 	if (!stat)
 		return IRQ_NONE;
 
 	if (stat & FSL_DMA_SR_TE)
-		dev_err(fsl_chan->dev, "Transfer Error!\n");
+		dev_err(fchan->dev, "Transfer Error!\n");
 
 	/* Programming Error
 	 * The DMA_INTERRUPT async_tx is a NULL transfer, which will
 	 * triger a PE interrupt.
 	 */
 	if (stat & FSL_DMA_SR_PE) {
-		dev_dbg(fsl_chan->dev, "event: Programming Error INT\n");
-		if (get_bcr(fsl_chan) == 0) {
+		dev_dbg(fchan->dev, "event: Programming Error INT\n");
+		if (get_bcr(fchan) == 0) {
 			/* BCR register is 0, this is a DMA_INTERRUPT async_tx.
 			 * Now, update the completed cookie, and continue the
 			 * next uncompleted transfer.
@@ -1007,10 +1007,10 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	 * we will recycle the used descriptor.
 	 */
 	if (stat & FSL_DMA_SR_EOSI) {
-		dev_dbg(fsl_chan->dev, "event: End-of-segments INT\n");
-		dev_dbg(fsl_chan->dev, "event: clndar 0x%llx, nlndar 0x%llx\n",
-			(unsigned long long)get_cdar(fsl_chan),
-			(unsigned long long)get_ndar(fsl_chan));
+		dev_dbg(fchan->dev, "event: End-of-segments INT\n");
+		dev_dbg(fchan->dev, "event: clndar 0x%llx, nlndar 0x%llx\n",
+			(unsigned long long)get_cdar(fchan),
+			(unsigned long long)get_ndar(fchan));
 		stat &= ~FSL_DMA_SR_EOSI;
 		update_cookie = 1;
 	}
@@ -1019,7 +1019,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	 * and start the next transfer if it exist.
 	 */
 	if (stat & FSL_DMA_SR_EOCDI) {
-		dev_dbg(fsl_chan->dev, "event: End-of-Chain link INT\n");
+		dev_dbg(fchan->dev, "event: End-of-Chain link INT\n");
 		stat &= ~FSL_DMA_SR_EOCDI;
 		update_cookie = 1;
 		xfer_ld_q = 1;
@@ -1030,28 +1030,28 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	 * prepare next transfer.
 	 */
 	if (stat & FSL_DMA_SR_EOLNI) {
-		dev_dbg(fsl_chan->dev, "event: End-of-link INT\n");
+		dev_dbg(fchan->dev, "event: End-of-link INT\n");
 		stat &= ~FSL_DMA_SR_EOLNI;
 		xfer_ld_q = 1;
 	}
 
 	if (update_cookie)
-		fsl_dma_update_completed_cookie(fsl_chan);
+		fsl_dma_update_completed_cookie(fchan);
 	if (xfer_ld_q)
-		fsl_chan_xfer_ld_queue(fsl_chan);
+		fsl_chan_xfer_ld_queue(fchan);
 	if (stat)
-		dev_dbg(fsl_chan->dev, "event: unhandled sr 0x%02x\n",
+		dev_dbg(fchan->dev, "event: unhandled sr 0x%02x\n",
 					stat);
 
-	dev_dbg(fsl_chan->dev, "event: Exit\n");
-	tasklet_schedule(&fsl_chan->tasklet);
+	dev_dbg(fchan->dev, "event: Exit\n");
+	tasklet_schedule(&fchan->tasklet);
 	return IRQ_HANDLED;
 }
 
 static void dma_do_tasklet(unsigned long data)
 {
-	struct fsldma_chan *fsl_chan = (struct fsldma_chan *)data;
-	fsl_chan_ld_cleanup(fsl_chan);
+	struct fsldma_chan *fchan = (struct fsldma_chan *)data;
+	fsl_chan_ld_cleanup(fchan);
 }
 
 /*----------------------------------------------------------------------------*/
-- 
1.5.4.3

^ permalink raw reply related

* [PATCH 8/8] fsldma: major cleanups and fixes
From: Ira W. Snyder @ 2010-01-01  6:10 UTC (permalink / raw)
  To: dan.j.williams
  Cc: herbert, B04825, linuxppc-dev, Vishnu, Dipen.Dudhat,
	Maneesh.Gupta, R58472
In-Reply-To: <1262326246-936-1-git-send-email-iws@ovro.caltech.edu>

Fix locking. Use two queues in the driver, one for pending transacions, and
one for transactions which are actually running on the hardware. Call
dma_run_dependencies() on descriptor cleanup so that the async_tx API works
correctly.

There are a number of places throughout the code where lists of descriptors
are freed in a loop. Create functions to handle this, and use them instead
of open-coding the loop each time.

Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
 drivers/dma/fsldma.c |  386 ++++++++++++++++++++++++++-----------------------
 drivers/dma/fsldma.h |    3 +-
 2 files changed, 207 insertions(+), 182 deletions(-)

diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index f65b28b..d49bdff 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -61,7 +61,6 @@ static void dma_init(struct fsldma_chan *fchan)
 				| FSL_DMA_MR_PRC_RM, 32);
 		break;
 	}
-
 }
 
 static void set_sr(struct fsldma_chan *fchan, u32 val)
@@ -120,11 +119,6 @@ static dma_addr_t get_cdar(struct fsldma_chan *fchan)
 	return DMA_IN(fchan, &fchan->regs->cdar, 64) & ~FSL_DMA_SNEN;
 }
 
-static void set_ndar(struct fsldma_chan *fchan, dma_addr_t addr)
-{
-	DMA_OUT(fchan, &fchan->regs->ndar, addr, 64);
-}
-
 static dma_addr_t get_ndar(struct fsldma_chan *fchan)
 {
 	return DMA_IN(fchan, &fchan->regs->ndar, 64);
@@ -178,11 +172,12 @@ static void dma_halt(struct fsldma_chan *fchan)
 
 	for (i = 0; i < 100; i++) {
 		if (dma_is_idle(fchan))
-			break;
+			return;
+
 		udelay(10);
 	}
 
-	if (i >= 100 && !dma_is_idle(fchan))
+	if (!dma_is_idle(fchan))
 		dev_err(fchan->dev, "DMA halt timeout!\n");
 }
 
@@ -199,27 +194,6 @@ static void set_ld_eol(struct fsldma_chan *fchan,
 			| snoop_bits, 64);
 }
 
-static void append_ld_queue(struct fsldma_chan *fchan,
-		struct fsl_desc_sw *new_desc)
-{
-	struct fsl_desc_sw *queue_tail = to_fsl_desc(fchan->ld_queue.prev);
-
-	if (list_empty(&fchan->ld_queue))
-		return;
-
-	/* Link to the new descriptor physical address and
-	 * Enable End-of-segment interrupt for
-	 * the last link descriptor.
-	 * (the previous node's next link descriptor)
-	 *
-	 * For FSL_DMA_IP_83xx, the snoop enable bit need be set.
-	 */
-	queue_tail->hw.next_ln_addr = CPU_TO_DMA(fchan,
-			new_desc->async_tx.phys | FSL_DMA_EOSIE |
-			(((fchan->feature & FSL_DMA_IP_MASK)
-				== FSL_DMA_IP_83XX) ? FSL_DMA_SNEN : 0), 64);
-}
-
 /**
  * fsl_chan_set_src_loop_size - Set source address hold transfer size
  * @fchan : Freescale DMA channel
@@ -343,6 +317,31 @@ static void fsl_chan_toggle_ext_start(struct fsldma_chan *fchan, int enable)
 		fchan->feature &= ~FSL_DMA_CHAN_START_EXT;
 }
 
+static void append_ld_queue(struct fsldma_chan *fchan,
+			    struct fsl_desc_sw *desc)
+{
+	struct fsl_desc_sw *tail = to_fsl_desc(fchan->ld_pending.prev);
+
+	if (list_empty(&fchan->ld_pending))
+		goto out_splice;
+
+	/*
+	 * Add the hardware descriptor to the chain of hardware descriptors
+	 * that already exists in memory.
+	 *
+	 * This will un-set the EOL bit of the existing transaction, and the
+	 * last link in this transaction will become the EOL descriptor.
+	 */
+	set_desc_next(fchan, &tail->hw, desc->async_tx.phys);
+
+	/*
+	 * Add the software descriptor and all children to the list
+	 * of pending transactions
+	 */
+out_splice:
+	list_splice_tail_init(&desc->tx_list, &fchan->ld_pending);
+}
+
 static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 {
 	struct fsldma_chan *fchan = to_fsl_chan(tx->chan);
@@ -351,9 +350,12 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 	unsigned long flags;
 	dma_cookie_t cookie;
 
-	/* cookie increment and adding to ld_queue must be atomic */
 	spin_lock_irqsave(&fchan->desc_lock, flags);
 
+	/*
+	 * assign cookies to all of the software descriptors
+	 * that make up this transaction
+	 */
 	cookie = fchan->common.cookie;
 	list_for_each_entry(child, &desc->tx_list, node) {
 		cookie++;
@@ -364,8 +366,9 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 	}
 
 	fchan->common.cookie = cookie;
+
+	/* put this transaction onto the tail of the pending queue */
 	append_ld_queue(fchan, desc);
-	list_splice_init(&desc->tx_list, fchan->ld_queue.prev);
 
 	spin_unlock_irqrestore(&fchan->desc_lock, flags);
 
@@ -381,20 +384,22 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
 					struct fsldma_chan *fchan)
 {
+	struct fsl_desc_sw *desc;
 	dma_addr_t pdesc;
-	struct fsl_desc_sw *desc_sw;
-
-	desc_sw = dma_pool_alloc(fchan->desc_pool, GFP_ATOMIC, &pdesc);
-	if (desc_sw) {
-		memset(desc_sw, 0, sizeof(struct fsl_desc_sw));
-		INIT_LIST_HEAD(&desc_sw->tx_list);
-		dma_async_tx_descriptor_init(&desc_sw->async_tx,
-						&fchan->common);
-		desc_sw->async_tx.tx_submit = fsl_dma_tx_submit;
-		desc_sw->async_tx.phys = pdesc;
+
+	desc = dma_pool_alloc(fchan->desc_pool, GFP_ATOMIC, &pdesc);
+	if (!desc) {
+		dev_dbg(fchan->dev, "out of memory for link desc\n");
+		return NULL;
 	}
 
-	return desc_sw;
+	memset(desc, 0, sizeof(*desc));
+	INIT_LIST_HEAD(&desc->tx_list);
+	dma_async_tx_descriptor_init(&desc->async_tx, &fchan->common);
+	desc->async_tx.tx_submit = fsl_dma_tx_submit;
+	desc->async_tx.phys = pdesc;
+
+	return desc;
 }
 
 
@@ -414,45 +419,69 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
 	if (fchan->desc_pool)
 		return 1;
 
-	/* We need the descriptor to be aligned to 32bytes
+	/*
+	 * We need the descriptor to be aligned to 32bytes
 	 * for meeting FSL DMA specification requirement.
 	 */
 	fchan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
-			fchan->dev, sizeof(struct fsl_desc_sw),
-			32, 0);
+					   fchan->dev,
+					   sizeof(struct fsl_desc_sw),
+					   __alignof__(struct fsl_desc_sw), 0);
 	if (!fchan->desc_pool) {
-		dev_err(fchan->dev, "No memory for channel %d "
-			"descriptor dma pool.\n", fchan->id);
-		return 0;
+		dev_err(fchan->dev, "unable to allocate channel %d "
+				    "descriptor pool\n", fchan->id);
+		return -ENOMEM;
 	}
 
+	/* there is at least one descriptor free to be allocated */
 	return 1;
 }
 
 /**
+ * fsldma_free_desc_list - Free all descriptors in a queue
+ * @fchan: Freescae DMA channel
+ * @list: the list to free
+ *
+ * LOCKING: must hold fchan->desc_lock
+ */
+static void fsldma_free_desc_list(struct fsldma_chan *fchan,
+				  struct list_head *list)
+{
+	struct fsl_desc_sw *desc, *_desc;
+
+	list_for_each_entry_safe(desc, _desc, list, node) {
+		list_del(&desc->node);
+		dma_pool_free(fchan->desc_pool, desc, desc->async_tx.phys);
+	}
+}
+
+static void fsldma_free_desc_list_reverse(struct fsldma_chan *fchan,
+					  struct list_head *list)
+{
+	struct fsl_desc_sw *desc, *_desc;
+
+	list_for_each_entry_safe_reverse(desc, _desc, list, node) {
+		list_del(&desc->node);
+		dma_pool_free(fchan->desc_pool, desc, desc->async_tx.phys);
+	}
+}
+
+/**
  * fsl_dma_free_chan_resources - Free all resources of the channel.
  * @fchan : Freescale DMA channel
  */
 static void fsl_dma_free_chan_resources(struct dma_chan *chan)
 {
 	struct fsldma_chan *fchan = to_fsl_chan(chan);
-	struct fsl_desc_sw *desc, *_desc;
 	unsigned long flags;
 
 	dev_dbg(fchan->dev, "Free all channel resources.\n");
 	spin_lock_irqsave(&fchan->desc_lock, flags);
-	list_for_each_entry_safe(desc, _desc, &fchan->ld_queue, node) {
-#ifdef FSL_DMA_LD_DEBUG
-		dev_dbg(fchan->dev,
-				"LD %p will be released.\n", desc);
-#endif
-		list_del(&desc->node);
-		/* free link descriptor */
-		dma_pool_free(fchan->desc_pool, desc, desc->async_tx.phys);
-	}
+	fsldma_free_desc_list(fchan, &fchan->ld_pending);
+	fsldma_free_desc_list(fchan, &fchan->ld_running);
 	spin_unlock_irqrestore(&fchan->desc_lock, flags);
-	dma_pool_destroy(fchan->desc_pool);
 
+	dma_pool_destroy(fchan->desc_pool);
 	fchan->desc_pool = NULL;
 }
 
@@ -491,7 +520,6 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
 {
 	struct fsldma_chan *fchan;
 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new;
-	struct list_head *list;
 	size_t copy;
 
 	if (!chan)
@@ -550,12 +578,7 @@ fail:
 	if (!first)
 		return NULL;
 
-	list = &first->tx_list;
-	list_for_each_entry_safe_reverse(new, prev, list, node) {
-		list_del(&new->node);
-		dma_pool_free(fchan->desc_pool, new, new->async_tx.phys);
-	}
-
+	fsldma_free_desc_list_reverse(fchan, &first->tx_list);
 	return NULL;
 }
 
@@ -578,7 +601,6 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
 	struct fsldma_chan *fchan;
 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;
 	struct fsl_dma_slave *slave;
-	struct list_head *tx_list;
 	size_t copy;
 
 	int i;
@@ -748,19 +770,13 @@ fail:
 	 *
 	 * We're re-using variables for the loop, oh well
 	 */
-	tx_list = &first->tx_list;
-	list_for_each_entry_safe_reverse(new, prev, tx_list, node) {
-		list_del_init(&new->node);
-		dma_pool_free(fchan->desc_pool, new, new->async_tx.phys);
-	}
-
+	fsldma_free_desc_list_reverse(fchan, &first->tx_list);
 	return NULL;
 }
 
 static void fsl_dma_device_terminate_all(struct dma_chan *chan)
 {
 	struct fsldma_chan *fchan;
-	struct fsl_desc_sw *desc, *tmp;
 	unsigned long flags;
 
 	if (!chan)
@@ -774,10 +790,8 @@ static void fsl_dma_device_terminate_all(struct dma_chan *chan)
 	spin_lock_irqsave(&fchan->desc_lock, flags);
 
 	/* Remove and free all of the descriptors in the LD queue */
-	list_for_each_entry_safe(desc, tmp, &fchan->ld_queue, node) {
-		list_del(&desc->node);
-		dma_pool_free(fchan->desc_pool, desc, desc->async_tx.phys);
-	}
+	fsldma_free_desc_list(fchan, &fchan->ld_pending);
+	fsldma_free_desc_list(fchan, &fchan->ld_running);
 
 	spin_unlock_irqrestore(&fchan->desc_lock, flags);
 }
@@ -785,31 +799,48 @@ static void fsl_dma_device_terminate_all(struct dma_chan *chan)
 /**
  * fsl_dma_update_completed_cookie - Update the completed cookie.
  * @fchan : Freescale DMA channel
+ *
+ * CONTEXT: hardirq
  */
 static void fsl_dma_update_completed_cookie(struct fsldma_chan *fchan)
 {
-	struct fsl_desc_sw *cur_desc, *desc;
-	dma_addr_t ld_phy;
-
-	ld_phy = get_cdar(fchan) & FSL_DMA_NLDA_MASK;
+	struct fsl_desc_sw *desc;
+	unsigned long flags;
+	dma_cookie_t cookie;
 
-	if (ld_phy) {
-		cur_desc = NULL;
-		list_for_each_entry(desc, &fchan->ld_queue, node)
-			if (desc->async_tx.phys == ld_phy) {
-				cur_desc = desc;
-				break;
-			}
+	spin_lock_irqsave(&fchan->desc_lock, flags);
 
-		if (cur_desc && cur_desc->async_tx.cookie) {
-			if (dma_is_idle(fchan))
-				fchan->completed_cookie =
-					cur_desc->async_tx.cookie;
-			else
-				fchan->completed_cookie =
-					cur_desc->async_tx.cookie - 1;
-		}
+	if (list_empty(&fchan->ld_running)) {
+		dev_dbg(fchan->dev, "no running descriptors\n");
+		goto out_unlock;
 	}
+
+	/* Get the last descriptor, update the cookie to that */
+	desc = to_fsl_desc(fchan->ld_running.prev);
+	if (dma_is_idle(fchan))
+		cookie = desc->async_tx.cookie;
+	else
+		cookie = desc->async_tx.cookie - 1;
+
+	fchan->completed_cookie = cookie;
+
+out_unlock:
+	spin_unlock_irqrestore(&fchan->desc_lock, flags);
+}
+
+/**
+ * fsldma_desc_status - Check the status of a descriptor
+ * @fchan: Freescale DMA channel
+ * @desc: DMA SW descriptor
+ *
+ * This function will return the status of the given descriptor
+ */
+static enum dma_status fsldma_desc_status(struct fsldma_chan *fchan,
+					  struct fsl_desc_sw *desc)
+{
+	return dma_async_is_complete(desc->async_tx.cookie,
+				     fchan->completed_cookie,
+				     fchan->common.cookie);
 }
 
 /**
@@ -817,8 +848,6 @@ static void fsl_dma_update_completed_cookie(struct fsldma_chan *fchan)
  * @fchan : Freescale DMA channel
  *
  * This function clean up the ld_queue of DMA channel.
- * If 'in_intr' is set, the function will move the link descriptor to
- * the recycle list. Otherwise, free it directly.
  */
 static void fsl_chan_ld_cleanup(struct fsldma_chan *fchan)
 {
@@ -827,80 +856,95 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *fchan)
 
 	spin_lock_irqsave(&fchan->desc_lock, flags);
 
-	dev_dbg(fchan->dev, "chan completed_cookie = %d\n",
-			fchan->completed_cookie);
-	list_for_each_entry_safe(desc, _desc, &fchan->ld_queue, node) {
+	dev_dbg(fchan->dev, "chan completed_cookie = %d\n", fchan->completed_cookie);
+	list_for_each_entry_safe(desc, _desc, &fchan->ld_running, node) {
 		dma_async_tx_callback callback;
 		void *callback_param;
 
-		if (dma_async_is_complete(desc->async_tx.cookie,
-			    fchan->completed_cookie, fchan->common.cookie)
-				== DMA_IN_PROGRESS)
+		if (fsldma_desc_status(fchan, desc) == DMA_IN_PROGRESS)
 			break;
 
-		callback = desc->async_tx.callback;
-		callback_param = desc->async_tx.callback_param;
-
-		/* Remove from ld_queue list */
+		/* Remove from the list of running transactions */
 		list_del(&desc->node);
 
-		dev_dbg(fchan->dev, "link descriptor %p will be recycle.\n",
-				desc);
-		dma_pool_free(fchan->desc_pool, desc, desc->async_tx.phys);
-
 		/* Run the link descriptor callback function */
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
 		if (callback) {
 			spin_unlock_irqrestore(&fchan->desc_lock, flags);
-			dev_dbg(fchan->dev, "link descriptor %p callback\n",
-					desc);
+			dev_dbg(fchan->dev, "LD %p callback\n", desc);
 			callback(callback_param);
 			spin_lock_irqsave(&fchan->desc_lock, flags);
 		}
+
+		/* Run any dependencies, then free the descriptor */
+		dma_run_dependencies(&desc->async_tx);
+		dma_pool_free(fchan->desc_pool, desc, desc->async_tx.phys);
 	}
+
 	spin_unlock_irqrestore(&fchan->desc_lock, flags);
 }
 
 /**
- * fsl_chan_xfer_ld_queue - Transfer link descriptors in channel ld_queue.
+ * fsl_chan_xfer_ld_queue - transfer any pending transactions
  * @fchan : Freescale DMA channel
+ *
+ * This will make sure that any pending transactions will be run.
+ * If the DMA controller is idle, it will be started. Otherwise,
+ * the DMA controller's interrupt handler will start any pending
+ * transactions when it becomes idle.
  */
 static void fsl_chan_xfer_ld_queue(struct fsldma_chan *fchan)
 {
-	struct list_head *ld_node;
-	dma_addr_t next_dst_addr;
+	struct fsl_desc_sw *desc;
 	unsigned long flags;
 
 	spin_lock_irqsave(&fchan->desc_lock, flags);
 
-	if (!dma_is_idle(fchan))
+	/*
+	 * If the list of pending descriptors is empty, then we
+	 * don't need to do any work at all
+	 */
+	if (list_empty(&fchan->ld_pending)) {
+		dev_dbg(fchan->dev, "no pending LDs\n");
 		goto out_unlock;
+	}
 
+	/*
+	 * The DMA controller is not idle, which means the interrupt
+	 * handler will start any queued transactions when it runs
+	 * at the end of the current transaction
+	 */
+	if (!dma_is_idle(fchan)) {
+		dev_dbg(fchan->dev, "DMA controller still busy\n");
+		goto out_unlock;
+	}
+
+	/*
+	 * TODO:
+	 * make sure the dma_halt() function really un-wedges the
+	 * controller as much as possible
+	 */
 	dma_halt(fchan);
 
-	/* If there are some link descriptors
-	 * not transfered in queue. We need to start it.
+	/*
+	 * If there are some link descriptors which have not been
+	 * transferred, we need to start the controller
 	 */
 
-	/* Find the first un-transfer desciptor */
-	for (ld_node = fchan->ld_queue.next;
-		(ld_node != &fchan->ld_queue)
-			&& (dma_async_is_complete(
-				to_fsl_desc(ld_node)->async_tx.cookie,
-				fchan->completed_cookie,
-				fchan->common.cookie) == DMA_SUCCESS);
-		ld_node = ld_node->next);
-
-	if (ld_node != &fchan->ld_queue) {
-		/* Get the ld start address from ld_queue */
-		next_dst_addr = to_fsl_desc(ld_node)->async_tx.phys;
-		dev_dbg(fchan->dev, "xfer LDs staring from 0x%llx\n",
-				(unsigned long long)next_dst_addr);
-		set_cdar(fchan, next_dst_addr);
-		dma_start(fchan);
-	} else {
-		set_cdar(fchan, 0);
-		set_ndar(fchan, 0);
-	}
+	/*
+	 * Move all elements from the queue of pending transactions
+	 * onto the list of running transactions
+	 */
+	desc = list_first_entry(&fchan->ld_pending, struct fsl_desc_sw, node);
+	list_splice_tail_init(&fchan->ld_pending, &fchan->ld_running);
+
+	/*
+	 * Program the descriptor's address into the DMA controller,
+	 * then start the DMA transaction
+	 */
+	set_cdar(fchan, desc->async_tx.phys);
+	dma_start(fchan);
 
 out_unlock:
 	spin_unlock_irqrestore(&fchan->desc_lock, flags);
@@ -913,30 +957,6 @@ out_unlock:
 static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan)
 {
 	struct fsldma_chan *fchan = to_fsl_chan(chan);
-
-#ifdef FSL_DMA_LD_DEBUG
-	struct fsl_desc_sw *ld;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fchan->desc_lock, flags);
-	if (list_empty(&fchan->ld_queue)) {
-		spin_unlock_irqrestore(&fchan->desc_lock, flags);
-		return;
-	}
-
-	dev_dbg(fchan->dev, "--memcpy issue--\n");
-	list_for_each_entry(ld, &fchan->ld_queue, node) {
-		int i;
-		dev_dbg(fchan->dev, "Ch %d, LD %08x\n",
-				fchan->id, ld->async_tx.phys);
-		for (i = 0; i < 8; i++)
-			dev_dbg(fchan->dev, "LD offset %d: %08x\n",
-					i, *(((u32 *)&ld->hw) + i));
-	}
-	dev_dbg(fchan->dev, "----------------\n");
-	spin_unlock_irqrestore(&fchan->desc_lock, flags);
-#endif
-
 	fsl_chan_xfer_ld_queue(fchan);
 }
 
@@ -974,10 +994,10 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	int xfer_ld_q = 0;
 	u32 stat;
 
+	/* save and clear the status register */
 	stat = get_sr(fchan);
-	dev_dbg(fchan->dev, "event: channel %d, stat = 0x%x\n",
-						fchan->id, stat);
-	set_sr(fchan, stat);		/* Clear the event register */
+	set_sr(fchan, stat);
+	dev_dbg(fchan->dev, "irq: channel %d, stat = 0x%x\n", fchan->id, stat);
 
 	stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
 	if (!stat)
@@ -986,12 +1006,13 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	if (stat & FSL_DMA_SR_TE)
 		dev_err(fchan->dev, "Transfer Error!\n");
 
-	/* Programming Error
+	/*
+	 * Programming Error
 	 * The DMA_INTERRUPT async_tx is a NULL transfer, which will
 	 * triger a PE interrupt.
 	 */
 	if (stat & FSL_DMA_SR_PE) {
-		dev_dbg(fchan->dev, "event: Programming Error INT\n");
+		dev_dbg(fchan->dev, "irq: Programming Error INT\n");
 		if (get_bcr(fchan) == 0) {
 			/* BCR register is 0, this is a DMA_INTERRUPT async_tx.
 			 * Now, update the completed cookie, and continue the
@@ -1003,34 +1024,37 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 		stat &= ~FSL_DMA_SR_PE;
 	}
 
-	/* If the link descriptor segment transfer finishes,
+	/*
+	 * If the link descriptor segment transfer finishes,
 	 * we will recycle the used descriptor.
 	 */
 	if (stat & FSL_DMA_SR_EOSI) {
-		dev_dbg(fchan->dev, "event: End-of-segments INT\n");
-		dev_dbg(fchan->dev, "event: clndar 0x%llx, nlndar 0x%llx\n",
+		dev_dbg(fchan->dev, "irq: End-of-segments INT\n");
+		dev_dbg(fchan->dev, "irq: clndar 0x%llx, nlndar 0x%llx\n",
 			(unsigned long long)get_cdar(fchan),
 			(unsigned long long)get_ndar(fchan));
 		stat &= ~FSL_DMA_SR_EOSI;
 		update_cookie = 1;
 	}
 
-	/* For MPC8349, EOCDI event need to update cookie
+	/*
+	 * For MPC8349, EOCDI event need to update cookie
 	 * and start the next transfer if it exist.
 	 */
 	if (stat & FSL_DMA_SR_EOCDI) {
-		dev_dbg(fchan->dev, "event: End-of-Chain link INT\n");
+		dev_dbg(fchan->dev, "irq: End-of-Chain link INT\n");
 		stat &= ~FSL_DMA_SR_EOCDI;
 		update_cookie = 1;
 		xfer_ld_q = 1;
 	}
 
-	/* If it current transfer is the end-of-transfer,
+	/*
+	 * If it current transfer is the end-of-transfer,
 	 * we should clear the Channel Start bit for
 	 * prepare next transfer.
 	 */
 	if (stat & FSL_DMA_SR_EOLNI) {
-		dev_dbg(fchan->dev, "event: End-of-link INT\n");
+		dev_dbg(fchan->dev, "irq: End-of-link INT\n");
 		stat &= ~FSL_DMA_SR_EOLNI;
 		xfer_ld_q = 1;
 	}
@@ -1040,10 +1064,9 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	if (xfer_ld_q)
 		fsl_chan_xfer_ld_queue(fchan);
 	if (stat)
-		dev_dbg(fchan->dev, "event: unhandled sr 0x%02x\n",
-					stat);
+		dev_dbg(fchan->dev, "irq: unhandled sr 0x%02x\n", stat);
 
-	dev_dbg(fchan->dev, "event: Exit\n");
+	dev_dbg(fchan->dev, "irq: Exit\n");
 	tasklet_schedule(&fchan->tasklet);
 	return IRQ_HANDLED;
 }
@@ -1125,7 +1148,8 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
 	}
 
 	spin_lock_init(&fchan->desc_lock);
-	INIT_LIST_HEAD(&fchan->ld_queue);
+	INIT_LIST_HEAD(&fchan->ld_pending);
+	INIT_LIST_HEAD(&fchan->ld_running);
 
 	fchan->common.device = &fdev->common;
 
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index ea3b19c..cb4d6ff 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -131,7 +131,8 @@ struct fsldma_chan {
 	struct fsldma_chan_regs __iomem *regs;
 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
 	spinlock_t desc_lock;		/* Descriptor operation lock */
-	struct list_head ld_queue;	/* Link descriptors queue */
+	struct list_head ld_pending;	/* Link descriptors queue */
+	struct list_head ld_running;	/* Link descriptors queue */
 	struct dma_chan common;		/* DMA common channel */
 	struct dma_pool *desc_pool;	/* Descriptors pool */
 	struct device *dev;		/* Channel device */
-- 
1.5.4.3

^ permalink raw reply related

* [PATCH 5/8] fsldma: clean up the OF subsystem routines
From: Ira W. Snyder @ 2010-01-01  6:10 UTC (permalink / raw)
  To: dan.j.williams
  Cc: herbert, B04825, linuxppc-dev, Vishnu, Dipen.Dudhat,
	Maneesh.Gupta, R58472
In-Reply-To: <1262326246-936-1-git-send-email-iws@ovro.caltech.edu>

This fixes some errors in the cleanup paths of the OF subsystem, including
missing checks for ioremap failing. Also, some variables were renamed for
brevity.

Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
 drivers/dma/fsldma.c |  259 +++++++++++++++++++++++++------------------------
 drivers/dma/fsldma.h |    4 +-
 2 files changed, 134 insertions(+), 129 deletions(-)

diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index c2db754..507b297 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -40,7 +40,7 @@
 static void dma_init(struct fsldma_chan *fsl_chan)
 {
 	/* Reset the channel */
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, 0, 32);
+	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, 0, 32);
 
 	switch (fsl_chan->feature & FSL_DMA_IP_MASK) {
 	case FSL_DMA_IP_85XX:
@@ -49,7 +49,7 @@ static void dma_init(struct fsldma_chan *fsl_chan)
 		 * EOSIE - End of segments interrupt enable (basic mode)
 		 * EOLNIE - End of links interrupt enable
 		 */
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EIE
+		DMA_OUT(fsl_chan, &fsl_chan->regs->mr, FSL_DMA_MR_EIE
 				| FSL_DMA_MR_EOLNIE | FSL_DMA_MR_EOSIE, 32);
 		break;
 	case FSL_DMA_IP_83XX:
@@ -57,7 +57,7 @@ static void dma_init(struct fsldma_chan *fsl_chan)
 		 * EOTIE - End-of-transfer interrupt enable
 		 * PRC_RM - PCI read multiple
 		 */
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EOTIE
+		DMA_OUT(fsl_chan, &fsl_chan->regs->mr, FSL_DMA_MR_EOTIE
 				| FSL_DMA_MR_PRC_RM, 32);
 		break;
 	}
@@ -66,12 +66,12 @@ static void dma_init(struct fsldma_chan *fsl_chan)
 
 static void set_sr(struct fsldma_chan *fsl_chan, u32 val)
 {
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->sr, val, 32);
+	DMA_OUT(fsl_chan, &fsl_chan->regs->sr, val, 32);
 }
 
 static u32 get_sr(struct fsldma_chan *fsl_chan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->sr, 32);
+	return DMA_IN(fsl_chan, &fsl_chan->regs->sr, 32);
 }
 
 static void set_desc_cnt(struct fsldma_chan *fsl_chan,
@@ -112,27 +112,27 @@ static void set_desc_next(struct fsldma_chan *fsl_chan,
 
 static void set_cdar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
 {
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->cdar, addr | FSL_DMA_SNEN, 64);
+	DMA_OUT(fsl_chan, &fsl_chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
 }
 
 static dma_addr_t get_cdar(struct fsldma_chan *fsl_chan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->cdar, 64) & ~FSL_DMA_SNEN;
+	return DMA_IN(fsl_chan, &fsl_chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
 }
 
 static void set_ndar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
 {
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->ndar, addr, 64);
+	DMA_OUT(fsl_chan, &fsl_chan->regs->ndar, addr, 64);
 }
 
 static dma_addr_t get_ndar(struct fsldma_chan *fsl_chan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64);
+	return DMA_IN(fsl_chan, &fsl_chan->regs->ndar, 64);
 }
 
 static u32 get_bcr(struct fsldma_chan *fsl_chan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->bcr, 32);
+	return DMA_IN(fsl_chan, &fsl_chan->regs->bcr, 32);
 }
 
 static int dma_is_idle(struct fsldma_chan *fsl_chan)
@@ -145,11 +145,11 @@ static void dma_start(struct fsldma_chan *fsl_chan)
 {
 	u32 mode;
 
-	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
+	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
 
 	if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
 		if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
-			DMA_OUT(fsl_chan, &fsl_chan->reg_base->bcr, 0, 32);
+			DMA_OUT(fsl_chan, &fsl_chan->regs->bcr, 0, 32);
 			mode |= FSL_DMA_MR_EMP_EN;
 		} else {
 			mode &= ~FSL_DMA_MR_EMP_EN;
@@ -161,7 +161,7 @@ static void dma_start(struct fsldma_chan *fsl_chan)
 	else
 		mode |= FSL_DMA_MR_CS;
 
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
 }
 
 static void dma_halt(struct fsldma_chan *fsl_chan)
@@ -169,12 +169,12 @@ static void dma_halt(struct fsldma_chan *fsl_chan)
 	u32 mode;
 	int i;
 
-	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
+	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
 	mode |= FSL_DMA_MR_CA;
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
 
 	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA);
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
 
 	for (i = 0; i < 100; i++) {
 		if (dma_is_idle(fsl_chan))
@@ -235,7 +235,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
 {
 	u32 mode;
 
-	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
+	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
 
 	switch (size) {
 	case 0:
@@ -249,7 +249,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
 		break;
 	}
 
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
 }
 
 /**
@@ -267,7 +267,7 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
 {
 	u32 mode;
 
-	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
+	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
 
 	switch (size) {
 	case 0:
@@ -281,7 +281,7 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
 		break;
 	}
 
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
 }
 
 /**
@@ -302,10 +302,10 @@ static void fsl_chan_set_request_count(struct fsldma_chan *fsl_chan, int size)
 
 	BUG_ON(size > 1024);
 
-	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
+	mode = DMA_IN(fsl_chan, &fsl_chan->regs->mr, 32);
 	mode |= (__ilog2(size) << 24) & 0x0f000000;
 
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+	DMA_OUT(fsl_chan, &fsl_chan->regs->mr, mode, 32);
 }
 
 /**
@@ -967,7 +967,7 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
 	return dma_async_is_complete(cookie, last_complete, last_used);
 }
 
-static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+static irqreturn_t fsldma_chan_irq(int irq, void *data)
 {
 	struct fsldma_chan *fsl_chan = data;
 	u32 stat;
@@ -1048,17 +1048,17 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t fsl_dma_do_interrupt(int irq, void *data)
+static irqreturn_t fsldma_irq(int irq, void *data)
 {
 	struct fsldma_device *fdev = data;
 	int ch_nr;
 	u32 gsr;
 
-	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->reg_base)
-			: in_le32(fdev->reg_base);
+	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->regs)
+			: in_le32(fdev->regs);
 	ch_nr = (32 - ffs(gsr)) / 8;
 
-	return fdev->chan[ch_nr] ? fsl_dma_chan_do_interrupt(irq,
+	return fdev->chan[ch_nr] ? fsldma_chan_irq(irq,
 			fdev->chan[ch_nr]) : IRQ_NONE;
 }
 
@@ -1075,140 +1075,142 @@ static void dma_do_tasklet(unsigned long data)
 static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
 	struct device_node *node, u32 feature, const char *compatible)
 {
-	struct fsldma_chan *new_fsl_chan;
+	struct fsldma_chan *fchan;
 	struct resource res;
 	int err;
 
 	/* alloc channel */
-	new_fsl_chan = kzalloc(sizeof(*new_fsl_chan), GFP_KERNEL);
-	if (!new_fsl_chan) {
-		dev_err(fdev->dev, "No free memory for allocating "
-				"dma channels!\n");
-		return -ENOMEM;
+	fchan = kzalloc(sizeof(*fchan), GFP_KERNEL);
+	if (!fchan) {
+		dev_err(fdev->dev, "no free memory for DMA channels!\n");
+		err = -ENOMEM;
+		goto out_return;
+	}
+
+	/* ioremap registers for use */
+	fchan->regs = of_iomap(node, 0);
+	if (!fchan->regs) {
+		dev_err(fdev->dev, "unable to ioremap registers\n");
+		err = -ENOMEM;
+		goto out_free_fchan;
 	}
 
-	/* get dma channel register base */
 	err = of_address_to_resource(node, 0, &res);
 	if (err) {
-		dev_err(fdev->dev, "Can't get %s property 'reg'\n",
-				node->full_name);
-		goto err_no_reg;
+		dev_err(fdev->dev, "unable to find 'reg' property\n");
+		goto out_iounmap_regs;
 	}
 
-	new_fsl_chan->feature = feature;
-
+	fchan->feature = feature;
 	if (!fdev->feature)
-		fdev->feature = new_fsl_chan->feature;
+		fdev->feature = fchan->feature;
 
-	/* If the DMA device's feature is different than its channels',
-	 * report the bug.
+	/*
+	 * If the DMA device's feature is different than the feature
+	 * of its channels, report the bug
 	 */
-	WARN_ON(fdev->feature != new_fsl_chan->feature);
-
-	new_fsl_chan->dev = fdev->dev;
-	new_fsl_chan->reg_base = ioremap(res.start, resource_size(&res));
-	new_fsl_chan->id = ((res.start - 0x100) & 0xfff) >> 7;
-	if (new_fsl_chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
-		dev_err(fdev->dev, "There is no %d channel!\n",
-				new_fsl_chan->id);
+	WARN_ON(fdev->feature != fchan->feature);
+
+	fchan->dev = fdev->dev;
+	fchan->id = ((res.start - 0x100) & 0xfff) >> 7;
+	if (fchan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
+		dev_err(fdev->dev, "too many channels for device\n");
 		err = -EINVAL;
-		goto err_no_chan;
+		goto out_iounmap_regs;
 	}
-	fdev->chan[new_fsl_chan->id] = new_fsl_chan;
-	tasklet_init(&new_fsl_chan->tasklet, dma_do_tasklet,
-			(unsigned long)new_fsl_chan);
 
-	/* Init the channel */
-	dma_init(new_fsl_chan);
+	fdev->chan[fchan->id] = fchan;
+	tasklet_init(&fchan->tasklet, dma_do_tasklet, (unsigned long)fchan);
+
+	/* Initialize the channel */
+	dma_init(fchan);
 
 	/* Clear cdar registers */
-	set_cdar(new_fsl_chan, 0);
+	set_cdar(fchan, 0);
 
-	switch (new_fsl_chan->feature & FSL_DMA_IP_MASK) {
+	switch (fchan->feature & FSL_DMA_IP_MASK) {
 	case FSL_DMA_IP_85XX:
-		new_fsl_chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
+		fchan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
 	case FSL_DMA_IP_83XX:
-		new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
-		new_fsl_chan->set_src_loop_size = fsl_chan_set_src_loop_size;
-		new_fsl_chan->set_dst_loop_size = fsl_chan_set_dst_loop_size;
-		new_fsl_chan->set_request_count = fsl_chan_set_request_count;
+		fchan->toggle_ext_start = fsl_chan_toggle_ext_start;
+		fchan->set_src_loop_size = fsl_chan_set_src_loop_size;
+		fchan->set_dst_loop_size = fsl_chan_set_dst_loop_size;
+		fchan->set_request_count = fsl_chan_set_request_count;
 	}
 
-	spin_lock_init(&new_fsl_chan->desc_lock);
-	INIT_LIST_HEAD(&new_fsl_chan->ld_queue);
+	spin_lock_init(&fchan->desc_lock);
+	INIT_LIST_HEAD(&fchan->ld_queue);
 
-	new_fsl_chan->common.device = &fdev->common;
+	fchan->common.device = &fdev->common;
 
 	/* Add the channel to DMA device channel list */
-	list_add_tail(&new_fsl_chan->common.device_node,
-			&fdev->common.channels);
+	list_add_tail(&fchan->common.device_node, &fdev->common.channels);
 	fdev->common.chancnt++;
 
-	new_fsl_chan->irq = irq_of_parse_and_map(node, 0);
-	if (new_fsl_chan->irq != NO_IRQ) {
-		err = request_irq(new_fsl_chan->irq,
-					&fsl_dma_chan_do_interrupt, IRQF_SHARED,
-					"fsldma-channel", new_fsl_chan);
+	fchan->irq = irq_of_parse_and_map(node, 0);
+	if (fchan->irq != NO_IRQ) {
+		err = request_irq(fchan->irq, &fsldma_chan_irq,
+				  IRQF_SHARED, "fsldma-channel", fchan);
 		if (err) {
-			dev_err(fdev->dev, "DMA channel %s request_irq error "
-				"with return %d\n", node->full_name, err);
-			goto err_no_irq;
+			dev_err(fdev->dev, "unable to request IRQ "
+					   "for channel %d\n", fchan->id);
+			goto out_list_del;
 		}
 	}
 
-	dev_info(fdev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
-		 compatible,
-		 new_fsl_chan->irq != NO_IRQ ? new_fsl_chan->irq : fdev->irq);
+	dev_info(fdev->dev, "#%d (%s), irq %d\n", fchan->id, compatible,
+		 fchan->irq != NO_IRQ ? fchan->irq : fdev->irq);
 
 	return 0;
 
-err_no_irq:
-	list_del(&new_fsl_chan->common.device_node);
-err_no_chan:
-	iounmap(new_fsl_chan->reg_base);
-err_no_reg:
-	kfree(new_fsl_chan);
+out_list_del:
+	irq_dispose_mapping(fchan->irq);
+	list_del_init(&fchan->common.device_node);
+out_iounmap_regs:
+	iounmap(fchan->regs);
+out_free_fchan:
+	kfree(fchan);
+out_return:
 	return err;
 }
 
 static void fsl_dma_chan_remove(struct fsldma_chan *fchan)
 {
-	if (fchan->irq != NO_IRQ)
+	if (fchan->irq != NO_IRQ) {
 		free_irq(fchan->irq, fchan);
+		irq_dispose_mapping(fchan->irq);
+	}
+
 	list_del(&fchan->common.device_node);
-	iounmap(fchan->reg_base);
+	iounmap(fchan->regs);
 	kfree(fchan);
 }
 
-static int __devinit fsldma_of_probe(struct of_device *dev,
+static int __devinit fsldma_of_probe(struct of_device *op,
 			const struct of_device_id *match)
 {
-	int err;
 	struct fsldma_device *fdev;
 	struct device_node *child;
-	struct resource res;
+	int err;
 
 	fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
 	if (!fdev) {
-		dev_err(&dev->dev, "No enough memory for 'priv'\n");
-		return -ENOMEM;
+		dev_err(&op->dev, "No enough memory for 'priv'\n");
+		err = -ENOMEM;
+		goto out_return;
 	}
-	fdev->dev = &dev->dev;
+
+	fdev->dev = &op->dev;
 	INIT_LIST_HEAD(&fdev->common.channels);
 
-	/* get DMA controller register base */
-	err = of_address_to_resource(dev->node, 0, &res);
-	if (err) {
-		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
-				dev->node->full_name);
-		goto err_no_reg;
+	/* ioremap the registers for use */
+	fdev->regs = of_iomap(op->node, 0);
+	if (!fdev->regs) {
+		dev_err(&op->dev, "unable to ioremap registers\n");
+		err = -ENOMEM;
+		goto out_free_fdev;
 	}
 
-	dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
-			"controller at 0x%llx...\n",
-			match->compatible, (unsigned long long)res.start);
-	fdev->reg_base = ioremap(res.start, resource_size(&res));
-
 	dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
 	dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
 	dma_cap_set(DMA_SLAVE, fdev->common.cap_mask);
@@ -1220,66 +1222,69 @@ static int __devinit fsldma_of_probe(struct of_device *dev,
 	fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
 	fdev->common.device_prep_slave_sg = fsl_dma_prep_slave_sg;
 	fdev->common.device_terminate_all = fsl_dma_device_terminate_all;
-	fdev->common.dev = &dev->dev;
+	fdev->common.dev = &op->dev;
 
-	fdev->irq = irq_of_parse_and_map(dev->node, 0);
+	fdev->irq = irq_of_parse_and_map(op->node, 0);
 	if (fdev->irq != NO_IRQ) {
-		err = request_irq(fdev->irq, &fsl_dma_do_interrupt, IRQF_SHARED,
-					"fsldma-device", fdev);
+		err = request_irq(fdev->irq, &fsldma_irq, IRQF_SHARED,
+				  "fsldma-device", fdev);
 		if (err) {
-			dev_err(&dev->dev, "DMA device request_irq error "
-				"with return %d\n", err);
-			goto err;
+			dev_err(&op->dev, "unable to request IRQ\n");
+			goto out_iounmap_regs;
 		}
 	}
 
-	dev_set_drvdata(&(dev->dev), fdev);
+	dev_set_drvdata(&op->dev, fdev);
 
-	/* We cannot use of_platform_bus_probe() because there is no
-	 * of_platform_bus_remove.  Instead, we manually instantiate every DMA
+	/*
+	 * We cannot use of_platform_bus_probe() because there is no
+	 * of_platform_bus_remove(). Instead, we manually instantiate every DMA
 	 * channel object.
 	 */
-	for_each_child_of_node(dev->node, child) {
-		if (of_device_is_compatible(child, "fsl,eloplus-dma-channel"))
+	for_each_child_of_node(op->node, child) {
+		if (of_device_is_compatible(child, "fsl,eloplus-dma-channel")) {
 			fsl_dma_chan_probe(fdev, child,
 				FSL_DMA_IP_85XX | FSL_DMA_BIG_ENDIAN,
 				"fsl,eloplus-dma-channel");
-		if (of_device_is_compatible(child, "fsl,elo-dma-channel"))
+		}
+
+		if (of_device_is_compatible(child, "fsl,elo-dma-channel")) {
 			fsl_dma_chan_probe(fdev, child,
 				FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN,
 				"fsl,elo-dma-channel");
+		}
 	}
 
 	dma_async_device_register(&fdev->common);
 	return 0;
 
-err:
-	iounmap(fdev->reg_base);
-err_no_reg:
+out_iounmap_regs:
+	iounmap(fdev->regs);
+out_free_fdev:
 	kfree(fdev);
+out_return:
 	return err;
 }
 
-static int fsldma_of_remove(struct of_device *of_dev)
+static int fsldma_of_remove(struct of_device *op)
 {
 	struct fsldma_device *fdev;
 	unsigned int i;
 
-	fdev = dev_get_drvdata(&of_dev->dev);
-
+	fdev = dev_get_drvdata(&op->dev);
 	dma_async_device_unregister(&fdev->common);
 
-	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++)
+	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
 		if (fdev->chan[i])
 			fsl_dma_chan_remove(fdev->chan[i]);
+	}
 
 	if (fdev->irq != NO_IRQ)
 		free_irq(fdev->irq, fdev);
 
-	iounmap(fdev->reg_base);
-
+	iounmap(fdev->regs);
+	dev_set_drvdata(&op->dev, NULL);
 	kfree(fdev);
-	dev_set_drvdata(&of_dev->dev, NULL);
 
 	return 0;
 }
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index a67b8e3..ea3b19c 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -108,7 +108,7 @@ struct fsldma_chan;
 #define FSL_DMA_MAX_CHANS_PER_DEVICE 4
 
 struct fsldma_device {
-	void __iomem *reg_base;	/* DGSR register base */
+	void __iomem *regs;	/* DGSR register base */
 	struct device *dev;
 	struct dma_device common;
 	struct fsldma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
@@ -128,7 +128,7 @@ struct fsldma_device {
 #define FSL_DMA_CHAN_START_EXT	0x00002000
 
 struct fsldma_chan {
-	struct fsldma_chan_regs __iomem *reg_base;
+	struct fsldma_chan_regs __iomem *regs;
 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
 	spinlock_t desc_lock;		/* Descriptor operation lock */
 	struct list_head ld_queue;	/* Link descriptors queue */
-- 
1.5.4.3

^ permalink raw reply related

* [PATCH 6/8] fsldma: simplify IRQ probing and handling
From: Ira W. Snyder @ 2010-01-01  6:10 UTC (permalink / raw)
  To: dan.j.williams
  Cc: herbert, B04825, linuxppc-dev, Vishnu, Dipen.Dudhat,
	Maneesh.Gupta, R58472
In-Reply-To: <1262326246-936-1-git-send-email-iws@ovro.caltech.edu>

The IRQ probing is needlessly complex. All off the 83xx device trees in
arch/powerpc/boot/dts/ specify 5 interrupts per DMA controller: one for the
controller, and one for each channel. These interrupts are all attached to
the same IRQ line.

This causes an interesting situation if two channels interrupt at the same
time. The controller's handler will handle the first channel, and the
channel handler will handle the remaining channels. Instead of this, just
let the channel handler handle all channels, and ignore the controller
handler completely.

The same can be accomplished on 83xx by removing the controller's interrupt
property from the device tree. Testing has not shown any problems with this
configuration. All in-tree device trees already have an interrupt property
specified for each channel.

Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
 Documentation/powerpc/dts-bindings/fsl/dma.txt |   17 +++++---
 drivers/dma/fsldma.c                           |   49 +++++++-----------------
 2 files changed, 25 insertions(+), 41 deletions(-)

diff --git a/Documentation/powerpc/dts-bindings/fsl/dma.txt b/Documentation/powerpc/dts-bindings/fsl/dma.txt
index 0732cdd..d5d2d3d 100644
--- a/Documentation/powerpc/dts-bindings/fsl/dma.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/dma.txt
@@ -12,6 +12,9 @@ Required properties:
 - ranges		: Should be defined as specified in 1) to describe the
 		  DMA controller channels.
 - cell-index        : controller index.  0 for controller @ 0x8100
+
+Optional properties:
+
 - interrupts        : <interrupt mapping for DMA IRQ>
 - interrupt-parent  : optional, if needed for interrupt mapping
 
@@ -23,11 +26,7 @@ Required properties:
 			 "fsl,elo-dma-channel". However, see note below.
         - reg               : <registers mapping for channel>
         - cell-index        : dma channel index starts at 0.
-
-Optional properties:
         - interrupts        : <interrupt mapping for DMA channel IRQ>
-			  (on 83xx this is expected to be identical to
-			   the interrupts property of the parent node)
         - interrupt-parent  : optional, if needed for interrupt mapping
 
 Example:
@@ -37,28 +36,34 @@ Example:
 		compatible = "fsl,mpc8349-dma", "fsl,elo-dma";
 		reg = <0x82a8 4>;
 		ranges = <0 0x8100 0x1a4>;
-		interrupt-parent = <&ipic>;
-		interrupts = <71 8>;
 		cell-index = <0>;
 		dma-channel@0 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <0>;
 			reg = <0 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
 		};
 		dma-channel@80 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <1>;
 			reg = <0x80 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
 		};
 		dma-channel@100 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <2>;
 			reg = <0x100 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
 		};
 		dma-channel@180 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <3>;
 			reg = <0x180 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
 		};
 	};
 
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 507b297..d8cc05b 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1048,20 +1048,6 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t fsldma_irq(int irq, void *data)
-{
-	struct fsldma_device *fdev = data;
-	int ch_nr;
-	u32 gsr;
-
-	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->regs)
-			: in_le32(fdev->regs);
-	ch_nr = (32 - ffs(gsr)) / 8;
-
-	return fdev->chan[ch_nr] ? fsldma_chan_irq(irq,
-			fdev->chan[ch_nr]) : IRQ_NONE;
-}
-
 static void dma_do_tasklet(unsigned long data)
 {
 	struct fsldma_chan *fsl_chan = (struct fsldma_chan *)data;
@@ -1143,19 +1129,24 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
 
 	fchan->common.device = &fdev->common;
 
+	/* find the IRQ line */
+	fchan->irq = irq_of_parse_and_map(node, 0);
+	if (fchan->irq == NO_IRQ) {
+		dev_err(fdev->dev, "unable to find IRQ line\n");
+		err = -EINVAL;
+		goto out_iounmap_regs;
+	}
+
 	/* Add the channel to DMA device channel list */
 	list_add_tail(&fchan->common.device_node, &fdev->common.channels);
 	fdev->common.chancnt++;
 
-	fchan->irq = irq_of_parse_and_map(node, 0);
-	if (fchan->irq != NO_IRQ) {
-		err = request_irq(fchan->irq, &fsldma_chan_irq,
-				  IRQF_SHARED, "fsldma-channel", fchan);
-		if (err) {
-			dev_err(fdev->dev, "unable to request IRQ "
-					   "for channel %d\n", fchan->id);
-			goto out_list_del;
-		}
+	err = request_irq(fchan->irq, fsldma_chan_irq, IRQF_SHARED,
+			  "fsldma-channel", fchan);
+	if (err) {
+		dev_err(fdev->dev, "unable to request IRQ for channel %d\n",
+			fchan->id);
+		goto out_list_del;
 	}
 
 	dev_info(fdev->dev, "#%d (%s), irq %d\n", fchan->id, compatible,
@@ -1224,16 +1215,6 @@ static int __devinit fsldma_of_probe(struct of_device *op,
 	fdev->common.device_terminate_all = fsl_dma_device_terminate_all;
 	fdev->common.dev = &op->dev;
 
-	fdev->irq = irq_of_parse_and_map(op->node, 0);
-	if (fdev->irq != NO_IRQ) {
-		err = request_irq(fdev->irq, &fsldma_irq, IRQF_SHARED,
-				  "fsldma-device", fdev);
-		if (err) {
-			dev_err(&op->dev, "unable to request IRQ\n");
-			goto out_iounmap_regs;
-		}
-	}
-
 	dev_set_drvdata(&op->dev, fdev);
 
 	/*
@@ -1258,8 +1239,6 @@ static int __devinit fsldma_of_probe(struct of_device *op,
 	dma_async_device_register(&fdev->common);
 	return 0;
 
-out_iounmap_regs:
-	iounmap(fdev->regs);
 out_free_fdev:
 	kfree(fdev);
 out_return:
-- 
1.5.4.3

^ permalink raw reply related

* [PATCH 3/8] fsldma: rename struct fsl_dma_chan to struct fsldma_chan
From: Ira W. Snyder @ 2010-01-01  6:10 UTC (permalink / raw)
  To: dan.j.williams
  Cc: herbert, B04825, linuxppc-dev, Vishnu, Dipen.Dudhat,
	Maneesh.Gupta, R58472
In-Reply-To: <1262326246-936-1-git-send-email-iws@ovro.caltech.edu>

This is the beginning of a cleanup which will change all instances of
"fsl_dma" to "fsldma" to match the name of the driver itself.

Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
 drivers/dma/fsldma.c |  128 ++++++++++++++++++++++++++-----------------------
 drivers/dma/fsldma.h |   26 +++++-----
 2 files changed, 81 insertions(+), 73 deletions(-)

diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 0b4e638..6795d96 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -37,7 +37,7 @@
 #include <asm/fsldma.h>
 #include "fsldma.h"
 
-static void dma_init(struct fsl_dma_chan *fsl_chan)
+static void dma_init(struct fsldma_chan *fsl_chan)
 {
 	/* Reset the channel */
 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, 0, 32);
@@ -64,23 +64,23 @@ static void dma_init(struct fsl_dma_chan *fsl_chan)
 
 }
 
-static void set_sr(struct fsl_dma_chan *fsl_chan, u32 val)
+static void set_sr(struct fsldma_chan *fsl_chan, u32 val)
 {
 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->sr, val, 32);
 }
 
-static u32 get_sr(struct fsl_dma_chan *fsl_chan)
+static u32 get_sr(struct fsldma_chan *fsl_chan)
 {
 	return DMA_IN(fsl_chan, &fsl_chan->reg_base->sr, 32);
 }
 
-static void set_desc_cnt(struct fsl_dma_chan *fsl_chan,
+static void set_desc_cnt(struct fsldma_chan *fsl_chan,
 				struct fsl_dma_ld_hw *hw, u32 count)
 {
 	hw->count = CPU_TO_DMA(fsl_chan, count, 32);
 }
 
-static void set_desc_src(struct fsl_dma_chan *fsl_chan,
+static void set_desc_src(struct fsldma_chan *fsl_chan,
 				struct fsl_dma_ld_hw *hw, dma_addr_t src)
 {
 	u64 snoop_bits;
@@ -90,7 +90,7 @@ static void set_desc_src(struct fsl_dma_chan *fsl_chan,
 	hw->src_addr = CPU_TO_DMA(fsl_chan, snoop_bits | src, 64);
 }
 
-static void set_desc_dest(struct fsl_dma_chan *fsl_chan,
+static void set_desc_dest(struct fsldma_chan *fsl_chan,
 				struct fsl_dma_ld_hw *hw, dma_addr_t dest)
 {
 	u64 snoop_bits;
@@ -100,7 +100,7 @@ static void set_desc_dest(struct fsl_dma_chan *fsl_chan,
 	hw->dst_addr = CPU_TO_DMA(fsl_chan, snoop_bits | dest, 64);
 }
 
-static void set_desc_next(struct fsl_dma_chan *fsl_chan,
+static void set_desc_next(struct fsldma_chan *fsl_chan,
 				struct fsl_dma_ld_hw *hw, dma_addr_t next)
 {
 	u64 snoop_bits;
@@ -110,38 +110,38 @@ static void set_desc_next(struct fsl_dma_chan *fsl_chan,
 	hw->next_ln_addr = CPU_TO_DMA(fsl_chan, snoop_bits | next, 64);
 }
 
-static void set_cdar(struct fsl_dma_chan *fsl_chan, dma_addr_t addr)
+static void set_cdar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
 {
 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->cdar, addr | FSL_DMA_SNEN, 64);
 }
 
-static dma_addr_t get_cdar(struct fsl_dma_chan *fsl_chan)
+static dma_addr_t get_cdar(struct fsldma_chan *fsl_chan)
 {
 	return DMA_IN(fsl_chan, &fsl_chan->reg_base->cdar, 64) & ~FSL_DMA_SNEN;
 }
 
-static void set_ndar(struct fsl_dma_chan *fsl_chan, dma_addr_t addr)
+static void set_ndar(struct fsldma_chan *fsl_chan, dma_addr_t addr)
 {
 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->ndar, addr, 64);
 }
 
-static dma_addr_t get_ndar(struct fsl_dma_chan *fsl_chan)
+static dma_addr_t get_ndar(struct fsldma_chan *fsl_chan)
 {
 	return DMA_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64);
 }
 
-static u32 get_bcr(struct fsl_dma_chan *fsl_chan)
+static u32 get_bcr(struct fsldma_chan *fsl_chan)
 {
 	return DMA_IN(fsl_chan, &fsl_chan->reg_base->bcr, 32);
 }
 
-static int dma_is_idle(struct fsl_dma_chan *fsl_chan)
+static int dma_is_idle(struct fsldma_chan *fsl_chan)
 {
 	u32 sr = get_sr(fsl_chan);
 	return (!(sr & FSL_DMA_SR_CB)) || (sr & FSL_DMA_SR_CH);
 }
 
-static void dma_start(struct fsl_dma_chan *fsl_chan)
+static void dma_start(struct fsldma_chan *fsl_chan)
 {
 	u32 mode;
 
@@ -164,7 +164,7 @@ static void dma_start(struct fsl_dma_chan *fsl_chan)
 	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
 }
 
-static void dma_halt(struct fsl_dma_chan *fsl_chan)
+static void dma_halt(struct fsldma_chan *fsl_chan)
 {
 	u32 mode;
 	int i;
@@ -186,7 +186,7 @@ static void dma_halt(struct fsl_dma_chan *fsl_chan)
 		dev_err(fsl_chan->dev, "DMA halt timeout!\n");
 }
 
-static void set_ld_eol(struct fsl_dma_chan *fsl_chan,
+static void set_ld_eol(struct fsldma_chan *fsl_chan,
 			struct fsl_desc_sw *desc)
 {
 	u64 snoop_bits;
@@ -199,7 +199,7 @@ static void set_ld_eol(struct fsl_dma_chan *fsl_chan,
 			| snoop_bits, 64);
 }
 
-static void append_ld_queue(struct fsl_dma_chan *fsl_chan,
+static void append_ld_queue(struct fsldma_chan *fsl_chan,
 		struct fsl_desc_sw *new_desc)
 {
 	struct fsl_desc_sw *queue_tail = to_fsl_desc(fsl_chan->ld_queue.prev);
@@ -231,7 +231,7 @@ static void append_ld_queue(struct fsl_dma_chan *fsl_chan,
  * read data from SA, SA + 1, SA + 2, SA + 3, then loop back to SA,
  * SA + 1 ... and so on.
  */
-static void fsl_chan_set_src_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
 {
 	u32 mode;
 
@@ -263,7 +263,7 @@ static void fsl_chan_set_src_loop_size(struct fsl_dma_chan *fsl_chan, int size)
  * write data to TA, TA + 1, TA + 2, TA + 3, then loop back to TA,
  * TA + 1 ... and so on.
  */
-static void fsl_chan_set_dest_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+static void fsl_chan_set_dest_loop_size(struct fsldma_chan *fsl_chan, int size)
 {
 	u32 mode;
 
@@ -296,7 +296,7 @@ static void fsl_chan_set_dest_loop_size(struct fsl_dma_chan *fsl_chan, int size)
  *
  * A size of 0 disables external pause control. The maximum size is 1024.
  */
-static void fsl_chan_set_request_count(struct fsl_dma_chan *fsl_chan, int size)
+static void fsl_chan_set_request_count(struct fsldma_chan *fsl_chan, int size)
 {
 	u32 mode;
 
@@ -317,7 +317,7 @@ static void fsl_chan_set_request_count(struct fsl_dma_chan *fsl_chan, int size)
  * The DMA Request Count feature should be used in addition to this feature
  * to set the number of bytes to transfer before pausing the channel.
  */
-static void fsl_chan_toggle_ext_pause(struct fsl_dma_chan *fsl_chan, int enable)
+static void fsl_chan_toggle_ext_pause(struct fsldma_chan *fsl_chan, int enable)
 {
 	if (enable)
 		fsl_chan->feature |= FSL_DMA_CHAN_PAUSE_EXT;
@@ -335,7 +335,7 @@ static void fsl_chan_toggle_ext_pause(struct fsl_dma_chan *fsl_chan, int enable)
  * transfer immediately. The DMA channel will wait for the
  * control pin asserted.
  */
-static void fsl_chan_toggle_ext_start(struct fsl_dma_chan *fsl_chan, int enable)
+static void fsl_chan_toggle_ext_start(struct fsldma_chan *fsl_chan, int enable)
 {
 	if (enable)
 		fsl_chan->feature |= FSL_DMA_CHAN_START_EXT;
@@ -345,7 +345,7 @@ static void fsl_chan_toggle_ext_start(struct fsl_dma_chan *fsl_chan, int enable)
 
 static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 {
-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan);
+	struct fsldma_chan *fsl_chan = to_fsl_chan(tx->chan);
 	struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
 	struct fsl_desc_sw *child;
 	unsigned long flags;
@@ -379,7 +379,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
  * Return - The descriptor allocated. NULL for failed.
  */
 static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
-					struct fsl_dma_chan *fsl_chan)
+					struct fsldma_chan *fsl_chan)
 {
 	dma_addr_t pdesc;
 	struct fsl_desc_sw *desc_sw;
@@ -408,7 +408,7 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
  */
 static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
 {
-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
 
 	/* Has this channel already been allocated? */
 	if (fsl_chan->desc_pool)
@@ -435,7 +435,7 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
  */
 static void fsl_dma_free_chan_resources(struct dma_chan *chan)
 {
-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
 	struct fsl_desc_sw *desc, *_desc;
 	unsigned long flags;
 
@@ -459,7 +459,7 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan)
 static struct dma_async_tx_descriptor *
 fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
 {
-	struct fsl_dma_chan *fsl_chan;
+	struct fsldma_chan *fsl_chan;
 	struct fsl_desc_sw *new;
 
 	if (!chan)
@@ -489,7 +489,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
 	struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
 	size_t len, unsigned long flags)
 {
-	struct fsl_dma_chan *fsl_chan;
+	struct fsldma_chan *fsl_chan;
 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new;
 	struct list_head *list;
 	size_t copy;
@@ -575,7 +575,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
 	struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
 	enum dma_data_direction direction, unsigned long flags)
 {
-	struct fsl_dma_chan *fsl_chan;
+	struct fsldma_chan *fsl_chan;
 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;
 	struct fsl_dma_slave *slave;
 	struct list_head *tx_list;
@@ -759,7 +759,7 @@ fail:
 
 static void fsl_dma_device_terminate_all(struct dma_chan *chan)
 {
-	struct fsl_dma_chan *fsl_chan;
+	struct fsldma_chan *fsl_chan;
 	struct fsl_desc_sw *desc, *tmp;
 	unsigned long flags;
 
@@ -786,7 +786,7 @@ static void fsl_dma_device_terminate_all(struct dma_chan *chan)
  * fsl_dma_update_completed_cookie - Update the completed cookie.
  * @fsl_chan : Freescale DMA channel
  */
-static void fsl_dma_update_completed_cookie(struct fsl_dma_chan *fsl_chan)
+static void fsl_dma_update_completed_cookie(struct fsldma_chan *fsl_chan)
 {
 	struct fsl_desc_sw *cur_desc, *desc;
 	dma_addr_t ld_phy;
@@ -820,7 +820,7 @@ static void fsl_dma_update_completed_cookie(struct fsl_dma_chan *fsl_chan)
  * If 'in_intr' is set, the function will move the link descriptor to
  * the recycle list. Otherwise, free it directly.
  */
-static void fsl_chan_ld_cleanup(struct fsl_dma_chan *fsl_chan)
+static void fsl_chan_ld_cleanup(struct fsldma_chan *fsl_chan)
 {
 	struct fsl_desc_sw *desc, *_desc;
 	unsigned long flags;
@@ -864,7 +864,7 @@ static void fsl_chan_ld_cleanup(struct fsl_dma_chan *fsl_chan)
  * fsl_chan_xfer_ld_queue - Transfer link descriptors in channel ld_queue.
  * @fsl_chan : Freescale DMA channel
  */
-static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
+static void fsl_chan_xfer_ld_queue(struct fsldma_chan *fsl_chan)
 {
 	struct list_head *ld_node;
 	dma_addr_t next_dest_addr;
@@ -912,7 +912,7 @@ out_unlock:
  */
 static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan)
 {
-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
 
 #ifdef FSL_DMA_LD_DEBUG
 	struct fsl_desc_sw *ld;
@@ -949,7 +949,7 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
 					dma_cookie_t *done,
 					dma_cookie_t *used)
 {
-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsldma_chan *fsl_chan = to_fsl_chan(chan);
 	dma_cookie_t last_used;
 	dma_cookie_t last_complete;
 
@@ -969,7 +969,7 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
 
 static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
 {
-	struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
+	struct fsldma_chan *fsl_chan = data;
 	u32 stat;
 	int update_cookie = 0;
 	int xfer_ld_q = 0;
@@ -1050,9 +1050,9 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
 
 static irqreturn_t fsl_dma_do_interrupt(int irq, void *data)
 {
-	struct fsl_dma_device *fdev = (struct fsl_dma_device *)data;
-	u32 gsr;
+	struct fsldma_device *fdev = data;
 	int ch_nr;
+	u32 gsr;
 
 	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->reg_base)
 			: in_le32(fdev->reg_base);
@@ -1064,19 +1064,23 @@ static irqreturn_t fsl_dma_do_interrupt(int irq, void *data)
 
 static void dma_do_tasklet(unsigned long data)
 {
-	struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
+	struct fsldma_chan *fsl_chan = (struct fsldma_chan *)data;
 	fsl_chan_ld_cleanup(fsl_chan);
 }
 
-static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
+/*----------------------------------------------------------------------------*/
+/* OpenFirmware Subsystem                                                     */
+/*----------------------------------------------------------------------------*/
+
+static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
 	struct device_node *node, u32 feature, const char *compatible)
 {
-	struct fsl_dma_chan *new_fsl_chan;
+	struct fsldma_chan *new_fsl_chan;
 	struct resource res;
 	int err;
 
 	/* alloc channel */
-	new_fsl_chan = kzalloc(sizeof(struct fsl_dma_chan), GFP_KERNEL);
+	new_fsl_chan = kzalloc(sizeof(*new_fsl_chan), GFP_KERNEL);
 	if (!new_fsl_chan) {
 		dev_err(fdev->dev, "No free memory for allocating "
 				"dma channels!\n");
@@ -1167,7 +1171,7 @@ err_no_reg:
 	return err;
 }
 
-static void fsl_dma_chan_remove(struct fsl_dma_chan *fchan)
+static void fsl_dma_chan_remove(struct fsldma_chan *fchan)
 {
 	if (fchan->irq != NO_IRQ)
 		free_irq(fchan->irq, fchan);
@@ -1176,15 +1180,15 @@ static void fsl_dma_chan_remove(struct fsl_dma_chan *fchan)
 	kfree(fchan);
 }
 
-static int __devinit of_fsl_dma_probe(struct of_device *dev,
+static int __devinit fsldma_of_probe(struct of_device *dev,
 			const struct of_device_id *match)
 {
 	int err;
-	struct fsl_dma_device *fdev;
+	struct fsldma_device *fdev;
 	struct device_node *child;
 	struct resource res;
 
-	fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
+	fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
 	if (!fdev) {
 		dev_err(&dev->dev, "No enough memory for 'priv'\n");
 		return -ENOMEM;
@@ -1256,9 +1260,9 @@ err_no_reg:
 	return err;
 }
 
-static int of_fsl_dma_remove(struct of_device *of_dev)
+static int fsldma_of_remove(struct of_device *of_dev)
 {
-	struct fsl_dma_device *fdev;
+	struct fsldma_device *fdev;
 	unsigned int i;
 
 	fdev = dev_get_drvdata(&of_dev->dev);
@@ -1280,39 +1284,43 @@ static int of_fsl_dma_remove(struct of_device *of_dev)
 	return 0;
 }
 
-static struct of_device_id of_fsl_dma_ids[] = {
+static struct of_device_id fsldma_of_ids[] = {
 	{ .compatible = "fsl,eloplus-dma", },
 	{ .compatible = "fsl,elo-dma", },
 	{}
 };
 
-static struct of_platform_driver of_fsl_dma_driver = {
-	.name = "fsl-elo-dma",
-	.match_table = of_fsl_dma_ids,
-	.probe = of_fsl_dma_probe,
-	.remove = of_fsl_dma_remove,
+static struct of_platform_driver fsldma_of_driver = {
+	.name		= "fsl-elo-dma",
+	.match_table	= fsldma_of_ids,
+	.probe		= fsldma_of_probe,
+	.remove		= fsldma_of_remove,
 };
 
-static __init int of_fsl_dma_init(void)
+/*----------------------------------------------------------------------------*/
+/* Module Init / Exit                                                         */
+/*----------------------------------------------------------------------------*/
+
+static __init int fsldma_init(void)
 {
 	int ret;
 
 	pr_info("Freescale Elo / Elo Plus DMA driver\n");
 
-	ret = of_register_platform_driver(&of_fsl_dma_driver);
+	ret = of_register_platform_driver(&fsldma_of_driver);
 	if (ret)
 		pr_err("fsldma: failed to register platform driver\n");
 
 	return ret;
 }
 
-static void __exit of_fsl_dma_exit(void)
+static void __exit fsldma_exit(void)
 {
-	of_unregister_platform_driver(&of_fsl_dma_driver);
+	of_unregister_platform_driver(&fsldma_of_driver);
 }
 
-subsys_initcall(of_fsl_dma_init);
-module_exit(of_fsl_dma_exit);
+subsys_initcall(fsldma_init);
+module_exit(fsldma_exit);
 
 MODULE_DESCRIPTION("Freescale Elo / Elo Plus DMA driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index dbb5b5c..f8c2baa 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -94,7 +94,7 @@ struct fsl_desc_sw {
 	struct dma_async_tx_descriptor async_tx;
 } __attribute__((aligned(32)));
 
-struct fsl_dma_chan_regs {
+struct fsldma_chan_regs {
 	u32 mr;	/* 0x00 - Mode Register */
 	u32 sr;	/* 0x04 - Status Register */
 	u64 cdar;	/* 0x08 - Current descriptor address register */
@@ -104,19 +104,19 @@ struct fsl_dma_chan_regs {
 	u64 ndar;	/* 0x24 - Next Descriptor Address Register */
 };
 
-struct fsl_dma_chan;
+struct fsldma_chan;
 #define FSL_DMA_MAX_CHANS_PER_DEVICE 4
 
-struct fsl_dma_device {
+struct fsldma_device {
 	void __iomem *reg_base;	/* DGSR register base */
 	struct device *dev;
 	struct dma_device common;
-	struct fsl_dma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
+	struct fsldma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
 	u32 feature;		/* The same as DMA channels */
 	int irq;		/* Channel IRQ */
 };
 
-/* Define macros for fsl_dma_chan->feature property */
+/* Define macros for fsldma_chan->feature property */
 #define FSL_DMA_LITTLE_ENDIAN	0x00000000
 #define FSL_DMA_BIG_ENDIAN	0x00000001
 
@@ -127,8 +127,8 @@ struct fsl_dma_device {
 #define FSL_DMA_CHAN_PAUSE_EXT	0x00001000
 #define FSL_DMA_CHAN_START_EXT	0x00002000
 
-struct fsl_dma_chan {
-	struct fsl_dma_chan_regs __iomem *reg_base;
+struct fsldma_chan {
+	struct fsldma_chan_regs __iomem *reg_base;
 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
 	spinlock_t desc_lock;		/* Descriptor operation lock */
 	struct list_head ld_queue;	/* Link descriptors queue */
@@ -140,14 +140,14 @@ struct fsl_dma_chan {
 	struct tasklet_struct tasklet;
 	u32 feature;
 
-	void (*toggle_ext_pause)(struct fsl_dma_chan *fsl_chan, int enable);
-	void (*toggle_ext_start)(struct fsl_dma_chan *fsl_chan, int enable);
-	void (*set_src_loop_size)(struct fsl_dma_chan *fsl_chan, int size);
-	void (*set_dest_loop_size)(struct fsl_dma_chan *fsl_chan, int size);
-	void (*set_request_count)(struct fsl_dma_chan *fsl_chan, int size);
+	void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
+	void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
+	void (*set_src_loop_size)(struct fsldma_chan *fsl_chan, int size);
+	void (*set_dest_loop_size)(struct fsldma_chan *fsl_chan, int size);
+	void (*set_request_count)(struct fsldma_chan *fsl_chan, int size);
 };
 
-#define to_fsl_chan(chan) container_of(chan, struct fsl_dma_chan, common)
+#define to_fsl_chan(chan) container_of(chan, struct fsldma_chan, common)
 #define to_fsl_desc(lh) container_of(lh, struct fsl_desc_sw, node)
 #define tx_to_fsl_desc(tx) container_of(tx, struct fsl_desc_sw, async_tx)
 
-- 
1.5.4.3

^ permalink raw reply related

* [PATCH 4/8] fsldma: rename dest to dst for uniformity
From: Ira W. Snyder @ 2010-01-01  6:10 UTC (permalink / raw)
  To: dan.j.williams
  Cc: herbert, B04825, linuxppc-dev, Vishnu, Dipen.Dudhat,
	Maneesh.Gupta, R58472
In-Reply-To: <1262326246-936-1-git-send-email-iws@ovro.caltech.edu>

Most functions in the standard library use "dst" as a parameter, rather
than "dest". This renames all use of "dest" to "dst" to match the usual
convention.

Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
 drivers/dma/fsldma.c |   32 ++++++++++++++++----------------
 drivers/dma/fsldma.h |    2 +-
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 6795d96..c2db754 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -90,14 +90,14 @@ static void set_desc_src(struct fsldma_chan *fsl_chan,
 	hw->src_addr = CPU_TO_DMA(fsl_chan, snoop_bits | src, 64);
 }
 
-static void set_desc_dest(struct fsldma_chan *fsl_chan,
-				struct fsl_dma_ld_hw *hw, dma_addr_t dest)
+static void set_desc_dst(struct fsldma_chan *fsl_chan,
+				struct fsl_dma_ld_hw *hw, dma_addr_t dst)
 {
 	u64 snoop_bits;
 
 	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
 		? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
-	hw->dst_addr = CPU_TO_DMA(fsl_chan, snoop_bits | dest, 64);
+	hw->dst_addr = CPU_TO_DMA(fsl_chan, snoop_bits | dst, 64);
 }
 
 static void set_desc_next(struct fsldma_chan *fsl_chan,
@@ -253,7 +253,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
 }
 
 /**
- * fsl_chan_set_dest_loop_size - Set destination address hold transfer size
+ * fsl_chan_set_dst_loop_size - Set destination address hold transfer size
  * @fsl_chan : Freescale DMA channel
  * @size     : Address loop size, 0 for disable loop
  *
@@ -263,7 +263,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *fsl_chan, int size)
  * write data to TA, TA + 1, TA + 2, TA + 3, then loop back to TA,
  * TA + 1 ... and so on.
  */
-static void fsl_chan_set_dest_loop_size(struct fsldma_chan *fsl_chan, int size)
+static void fsl_chan_set_dst_loop_size(struct fsldma_chan *fsl_chan, int size)
 {
 	u32 mode;
 
@@ -486,7 +486,7 @@ fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
 }
 
 static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
-	struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
+	struct dma_chan *chan, dma_addr_t dma_dst, dma_addr_t dma_src,
 	size_t len, unsigned long flags)
 {
 	struct fsldma_chan *fsl_chan;
@@ -519,7 +519,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
 
 		set_desc_cnt(fsl_chan, &new->hw, copy);
 		set_desc_src(fsl_chan, &new->hw, dma_src);
-		set_desc_dest(fsl_chan, &new->hw, dma_dest);
+		set_desc_dst(fsl_chan, &new->hw, dma_dst);
 
 		if (!first)
 			first = new;
@@ -532,7 +532,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
 		prev = new;
 		len -= copy;
 		dma_src += copy;
-		dma_dest += copy;
+		dma_dst += copy;
 
 		/* Insert the link descriptor to the LD ring */
 		list_add_tail(&new->node, &first->tx_list);
@@ -680,7 +680,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
 			/* Fill in the descriptor */
 			set_desc_cnt(fsl_chan, &new->hw, copy);
 			set_desc_src(fsl_chan, &new->hw, dma_src);
-			set_desc_dest(fsl_chan, &new->hw, dma_dst);
+			set_desc_dst(fsl_chan, &new->hw, dma_dst);
 
 			/*
 			 * If this is not the first descriptor, chain the
@@ -721,8 +721,8 @@ finished:
 	if (fsl_chan->set_src_loop_size)
 		fsl_chan->set_src_loop_size(fsl_chan, slave->src_loop_size);
 
-	if (fsl_chan->set_dest_loop_size)
-		fsl_chan->set_dest_loop_size(fsl_chan, slave->dst_loop_size);
+	if (fsl_chan->set_dst_loop_size)
+		fsl_chan->set_dst_loop_size(fsl_chan, slave->dst_loop_size);
 
 	if (fsl_chan->toggle_ext_start)
 		fsl_chan->toggle_ext_start(fsl_chan, slave->external_start);
@@ -867,7 +867,7 @@ static void fsl_chan_ld_cleanup(struct fsldma_chan *fsl_chan)
 static void fsl_chan_xfer_ld_queue(struct fsldma_chan *fsl_chan)
 {
 	struct list_head *ld_node;
-	dma_addr_t next_dest_addr;
+	dma_addr_t next_dst_addr;
 	unsigned long flags;
 
 	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
@@ -892,10 +892,10 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *fsl_chan)
 
 	if (ld_node != &fsl_chan->ld_queue) {
 		/* Get the ld start address from ld_queue */
-		next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys;
+		next_dst_addr = to_fsl_desc(ld_node)->async_tx.phys;
 		dev_dbg(fsl_chan->dev, "xfer LDs staring from 0x%llx\n",
-				(unsigned long long)next_dest_addr);
-		set_cdar(fsl_chan, next_dest_addr);
+				(unsigned long long)next_dst_addr);
+		set_cdar(fsl_chan, next_dst_addr);
 		dma_start(fsl_chan);
 	} else {
 		set_cdar(fsl_chan, 0);
@@ -1130,7 +1130,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
 	case FSL_DMA_IP_83XX:
 		new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
 		new_fsl_chan->set_src_loop_size = fsl_chan_set_src_loop_size;
-		new_fsl_chan->set_dest_loop_size = fsl_chan_set_dest_loop_size;
+		new_fsl_chan->set_dst_loop_size = fsl_chan_set_dst_loop_size;
 		new_fsl_chan->set_request_count = fsl_chan_set_request_count;
 	}
 
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index f8c2baa..a67b8e3 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -143,7 +143,7 @@ struct fsldma_chan {
 	void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
 	void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
 	void (*set_src_loop_size)(struct fsldma_chan *fsl_chan, int size);
-	void (*set_dest_loop_size)(struct fsldma_chan *fsl_chan, int size);
+	void (*set_dst_loop_size)(struct fsldma_chan *fsl_chan, int size);
 	void (*set_request_count)(struct fsldma_chan *fsl_chan, int size);
 };
 
-- 
1.5.4.3

^ permalink raw reply related

* [PATCH 1/8] fsldma: reduce kernel text size
From: Ira W. Snyder @ 2010-01-01  6:10 UTC (permalink / raw)
  To: dan.j.williams
  Cc: herbert, B04825, linuxppc-dev, Vishnu, Dipen.Dudhat,
	Maneesh.Gupta, R58472
In-Reply-To: <1262326246-936-1-git-send-email-iws@ovro.caltech.edu>

Some of the functions are written in a way where they use multiple reads
and writes where a single read/write pair could suffice. This shrinks the
kernel text size measurably, while making the functions easier to
understand.

add/remove: 0/0 grow/shrink: 1/4 up/down: 4/-196 (-192)
function                                     old     new   delta
fsl_chan_set_request_count                   120     124      +4
dma_halt                                     300     272     -28
fsl_chan_set_src_loop_size                   208     156     -52
fsl_chan_set_dest_loop_size                  208     156     -52
fsl_chan_xfer_ld_queue                       500     436     -64

Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
 drivers/dma/fsldma.c |   83 +++++++++++++++++++++++++++-----------------------
 1 files changed, 45 insertions(+), 38 deletions(-)

diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 296f9e7..0bad741 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -143,43 +143,45 @@ static int dma_is_idle(struct fsl_dma_chan *fsl_chan)
 
 static void dma_start(struct fsl_dma_chan *fsl_chan)
 {
-	u32 mr_set = 0;
-
-	if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->bcr, 0, 32);
-		mr_set |= FSL_DMA_MR_EMP_EN;
-	} else if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
-				& ~FSL_DMA_MR_EMP_EN, 32);
+	u32 mode;
+
+	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
+
+	if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+		if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
+			DMA_OUT(fsl_chan, &fsl_chan->reg_base->bcr, 0, 32);
+			mode |= FSL_DMA_MR_EMP_EN;
+		} else {
+			mode &= ~FSL_DMA_MR_EMP_EN;
+		}
 	}
 
 	if (fsl_chan->feature & FSL_DMA_CHAN_START_EXT)
-		mr_set |= FSL_DMA_MR_EMS_EN;
+		mode |= FSL_DMA_MR_EMS_EN;
 	else
-		mr_set |= FSL_DMA_MR_CS;
+		mode |= FSL_DMA_MR_CS;
 
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
-			| mr_set, 32);
+	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
 }
 
 static void dma_halt(struct fsl_dma_chan *fsl_chan)
 {
+	u32 mode;
 	int i;
 
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CA,
-		32);
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~(FSL_DMA_MR_CS
-		| FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA), 32);
+	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
+	mode |= FSL_DMA_MR_CA;
+	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
+
+	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA);
+	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
 
 	for (i = 0; i < 100; i++) {
 		if (dma_is_idle(fsl_chan))
 			break;
 		udelay(10);
 	}
+
 	if (i >= 100 && !dma_is_idle(fsl_chan))
 		dev_err(fsl_chan->dev, "DMA halt timeout!\n");
 }
@@ -231,22 +233,23 @@ static void append_ld_queue(struct fsl_dma_chan *fsl_chan,
  */
 static void fsl_chan_set_src_loop_size(struct fsl_dma_chan *fsl_chan, int size)
 {
+	u32 mode;
+
+	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
+
 	switch (size) {
 	case 0:
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) &
-			(~FSL_DMA_MR_SAHE), 32);
+		mode &= ~FSL_DMA_MR_SAHE;
 		break;
 	case 1:
 	case 2:
 	case 4:
 	case 8:
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) |
-			FSL_DMA_MR_SAHE | (__ilog2(size) << 14),
-			32);
+		mode |= FSL_DMA_MR_SAHE | (__ilog2(size) << 14);
 		break;
 	}
+
+	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
 }
 
 /**
@@ -262,22 +265,23 @@ static void fsl_chan_set_src_loop_size(struct fsl_dma_chan *fsl_chan, int size)
  */
 static void fsl_chan_set_dest_loop_size(struct fsl_dma_chan *fsl_chan, int size)
 {
+	u32 mode;
+
+	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
+
 	switch (size) {
 	case 0:
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) &
-			(~FSL_DMA_MR_DAHE), 32);
+		mode &= ~FSL_DMA_MR_DAHE;
 		break;
 	case 1:
 	case 2:
 	case 4:
 	case 8:
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) |
-			FSL_DMA_MR_DAHE | (__ilog2(size) << 16),
-			32);
+		mode |= FSL_DMA_MR_DAHE | (__ilog2(size) << 16);
 		break;
 	}
+
+	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
 }
 
 /**
@@ -294,11 +298,14 @@ static void fsl_chan_set_dest_loop_size(struct fsl_dma_chan *fsl_chan, int size)
  */
 static void fsl_chan_set_request_count(struct fsl_dma_chan *fsl_chan, int size)
 {
+	u32 mode;
+
 	BUG_ON(size > 1024);
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
-			| ((__ilog2(size) << 24) & 0x0f000000),
-		32);
+
+	mode = DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32);
+	mode |= (__ilog2(size) << 24) & 0x0f000000;
+
+	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, mode, 32);
 }
 
 /**
-- 
1.5.4.3

^ permalink raw reply related

* [PATCH 2/8] fsldma: remove unused structure members
From: Ira W. Snyder @ 2010-01-01  6:10 UTC (permalink / raw)
  To: dan.j.williams
  Cc: herbert, B04825, linuxppc-dev, Vishnu, Dipen.Dudhat,
	Maneesh.Gupta, R58472
In-Reply-To: <1262326246-936-1-git-send-email-iws@ovro.caltech.edu>

Remove some unused members from the fsldma data structures. A few trivial
uses of struct resource were converted to use the stack rather than keeping
the memory allocated for the lifetime of the driver.

Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
 drivers/dma/fsldma.c |   17 ++++++++---------
 drivers/dma/fsldma.h |    4 ----
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 0bad741..0b4e638 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1072,6 +1072,7 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
 	struct device_node *node, u32 feature, const char *compatible)
 {
 	struct fsl_dma_chan *new_fsl_chan;
+	struct resource res;
 	int err;
 
 	/* alloc channel */
@@ -1083,7 +1084,7 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
 	}
 
 	/* get dma channel register base */
-	err = of_address_to_resource(node, 0, &new_fsl_chan->reg);
+	err = of_address_to_resource(node, 0, &res);
 	if (err) {
 		dev_err(fdev->dev, "Can't get %s property 'reg'\n",
 				node->full_name);
@@ -1101,10 +1102,8 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
 	WARN_ON(fdev->feature != new_fsl_chan->feature);
 
 	new_fsl_chan->dev = fdev->dev;
-	new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start,
-			new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1);
-
-	new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7;
+	new_fsl_chan->reg_base = ioremap(res.start, resource_size(&res));
+	new_fsl_chan->id = ((res.start - 0x100) & 0xfff) >> 7;
 	if (new_fsl_chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
 		dev_err(fdev->dev, "There is no %d channel!\n",
 				new_fsl_chan->id);
@@ -1183,6 +1182,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
 	int err;
 	struct fsl_dma_device *fdev;
 	struct device_node *child;
+	struct resource res;
 
 	fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
 	if (!fdev) {
@@ -1193,7 +1193,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
 	INIT_LIST_HEAD(&fdev->common.channels);
 
 	/* get DMA controller register base */
-	err = of_address_to_resource(dev->node, 0, &fdev->reg);
+	err = of_address_to_resource(dev->node, 0, &res);
 	if (err) {
 		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
 				dev->node->full_name);
@@ -1202,9 +1202,8 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
 
 	dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
 			"controller at 0x%llx...\n",
-			match->compatible, (unsigned long long)fdev->reg.start);
-	fdev->reg_base = ioremap(fdev->reg.start, fdev->reg.end
-						- fdev->reg.start + 1);
+			match->compatible, (unsigned long long)res.start);
+	fdev->reg_base = ioremap(res.start, resource_size(&res));
 
 	dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
 	dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index 0df14cb..dbb5b5c 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -92,8 +92,6 @@ struct fsl_desc_sw {
 	struct list_head node;
 	struct list_head tx_list;
 	struct dma_async_tx_descriptor async_tx;
-	struct list_head *ld;
-	void *priv;
 } __attribute__((aligned(32)));
 
 struct fsl_dma_chan_regs {
@@ -111,7 +109,6 @@ struct fsl_dma_chan;
 
 struct fsl_dma_device {
 	void __iomem *reg_base;	/* DGSR register base */
-	struct resource reg;	/* Resource for register */
 	struct device *dev;
 	struct dma_device common;
 	struct fsl_dma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
@@ -138,7 +135,6 @@ struct fsl_dma_chan {
 	struct dma_chan common;		/* DMA common channel */
 	struct dma_pool *desc_pool;	/* Descriptors pool */
 	struct device *dev;		/* Channel device */
-	struct resource reg;		/* Resource for register */
 	int irq;			/* Channel IRQ */
 	int id;				/* Raw id of this channel */
 	struct tasklet_struct tasklet;
-- 
1.5.4.3

^ permalink raw reply related

* fsldma: cleanup driver and fix async_tx compatibility
From: Ira W. Snyder @ 2010-01-01  6:10 UTC (permalink / raw)
  To: dan.j.williams
  Cc: herbert, B04825, linuxppc-dev, Vishnu, Dipen.Dudhat,
	Maneesh.Gupta, R58472

This patch series cleans up the Freescale DMAEngine driver, including
verifying the locking and making sure that all code paths are correct.
There were a few places that seemed suspicious, and they have been fixed.

I have written a quick memory->memory DMAEngine test driver, and the
performance is identical before and after my changes (<0.1% change). I
measured both setting up the DMA operation (via device_prep_dma_interrupt()
and device_prep_dma_memcpy()) and the actual DMA transfer itself.

As an added bonus, the interrupt load is measurably reduced. My test driver
transfers 32MB as 32x 1MB chunks + 1 interrupt descriptor, using the
functions noted above. Previous to this patch series, 31 interrupts were
generated. After this patch series, only a single interrupt is generated
for the whole transaction.

Some testing on 85xx/86xx hardware would be appreciated. Also, some testing
by the users attempting to use async_tx and talitos to handle RAID offload
would be great as well.

 Documentation/powerpc/dts-bindings/fsl/dma.txt |   17 +-
 drivers/dma/fsldma.c                           | 1036 ++++++++++++------------
 drivers/dma/fsldma.h                           |   35 +-
 3 files changed, 556 insertions(+), 532 deletions(-)

Thanks,
Ira

^ permalink raw reply

* RE: How to access PPC460EX SDRAM space from PCI/PCIe.
From: Tirumala Reddy Marri @ 2009-12-31 23:50 UTC (permalink / raw)
  To: Lonsn, linuxppc-dev; +Cc: sr
In-Reply-To: <6caf4b5a0912310055h54a6efa6ka1825f19a7f0c691@mail.gmail.com>

It should be able to access any region in 32bit mode as long as it is
smaller than 4GB size. Usually whole SDRAM is mapped to inbound PCI
memory region.

-----Original Message-----
From: linuxppc-dev-bounces+tmarri=3Damcc.com@lists.ozlabs.org
[mailto:linuxppc-dev-bounces+tmarri=3Damcc.com@lists.ozlabs.org] On =
Behalf
Of Lonsn
Sent: Thursday, December 31, 2009 12:55 AM
To: linuxppc-dev@lists.ozlabs.org
Cc: sr@denx.de
Subject: How to access PPC460EX SDRAM space from PCI/PCIe.

Hi:
I'm now using canyonlands board with latest u-boot and linux kernel
from DENX git.
A PCIe card is plugged in the PCIeX4 slot. The PCIe card is a PCIe-pci
bridge(PI7C9X130) plus an Altera fpga.
The PCIe card act as a PCI master and send data to SDRAM of 460EX
space (total sdram 512MB, reserve 8M for PCI write data(0x1F800000)).
Now linux can identify this card, but CPU cann't receive any data from
PCIe and no PCIe interrupt.
I know about the PCI card works in 32bit mode and doesn't support
64bit address(No pci dual address cycle support).
Does the PCI card can access PPC460EX sdram space using just 32bit
physical address(0x1F800000)?

Best regards,
Lonsn
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH v2 3/3] powerpc: Add support for ram filesystems in FIT uImages
From: Peter Tyser @ 2009-12-31 23:10 UTC (permalink / raw)
  To: Wolfgang Denk; +Cc: linuxppc-dev, linux-kbuild
In-Reply-To: <20091231224439.AF5353F6D1@gemini.denx.de>

Hi Wolfgang,

> > IIRC, uImage.fit.initrd.% should appear before uImage.fit.% in the
> > Makefile so that make behaves more consistently.  Speaking of which,
> > the number of '.' in the name is getting rather large.  Would you
> > consider using 'fitImage' instead of 'uImage.fit'?
> 
> Why chose a different name at all? We could still call it "uImage",
> meaning "U-Boot image" - U-Boot is clever enought o detect
> automatically if we pass it an old style or a fit image.

I agree with your point to an extent, but having 2 types of uImages is
somewhat confusing to a user, even if U-Boot can differentiate between
them.  And if the legacy image and FIT image had the same Make target,
how does a user specify which type they want to build?  The fact that
both "legacy" and FIT images would reside at arch/powerpc/boot/uImage
doesn't make things any less confusing to Joe User.

Currently U-Boot supports booting:
1 "legacy" uImages
2 "new" Flattened Image Tree (FIT) uImages

What do you think about changing the U-Boot documentation to rename
those 2 image types to:
1 uImages
2 FIT Images

The FIT image is a relatively generic image type - its just a blob that
dtc created from a device tree and some input binaries.  In my mind its
not intimately tied to U-Boot, at least not conceptually.  The "legacy"
uImages have to agree with U-Boot's header format defined in the U-Boot
source code, so the uImage name does make sense with respect to the
"legacy" uImages.

My vote would be to make the Linux FIT target rule "fitImage" and then
update the U-Boot documentation to make obvious the differences between
uImages and FIT images.

What do you think of that?

Thanks,
Peter

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox