LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: Commits added to powerpc.git master and powerpc-next branches
From: Jochen Friedrich @ 2008-07-02 12:35 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <AF0B4FF7-06C8-4AF8-B1C2-23697326BDDB@kernel.crashing.org>

Hi Kumar,

>> any chance to get this one into 2.6.27?
>>
>> [POWERPC] Add i2c pins to dts and board setup
>>  http://patchwork.ozlabs.org/linuxppc/patch?person=1023&id=18603
> 
> Will we always want defconfig updates to enable the driver?

Good question. Maybe not, as the i2c bus seems to be unused on these
boards unless someone connects some i2c devices.

I'll resubmit just the booting-without-of part then.

Thanks,
Jochen

^ permalink raw reply

* Re: [alsa-devel] [PATCH 3/3] ALSA SoC: Add Texas Instruments TLV320AIC26 codec driver
From: Liam Girdwood @ 2008-07-02 10:48 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev, alsa-devel, broonie, timur
In-Reply-To: <20080701235340.16923.48024.stgit@trillian.secretlab.ca>

On Tue, 2008-07-01 at 17:53 -0600, Grant Likely wrote:
> From: Grant Likely <grant.likely@secretlab.ca>
> 
> ASoC Codec driver for the TLV320AIC26 device.  This driver uses the ASoC
> v1 API, so I don't expect it to get merged as-is, but I want to get it
> out there for review.
> ---
> 
>  sound/soc/codecs/Kconfig       |    4 
>  sound/soc/codecs/Makefile      |    2 
>  sound/soc/codecs/tlv320aic26.c |  630 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 636 insertions(+), 0 deletions(-)
> 
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 3903ab7..96c7bfe 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -41,6 +41,10 @@ config SND_SOC_CS4270_VD33_ERRATA
>  	bool
>  	depends on SND_SOC_CS4270
>  
> +config SND_SOC_TLV320AIC26
> +	tristate "TI TLB320AIC26 Codec support"
> +	depends on SND_SOC && SPI
> +
>  config SND_SOC_TLV320AIC3X
>  	tristate
>  	depends on SND_SOC && I2C
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index 4e1314c..ec0cd93 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -5,6 +5,7 @@ snd-soc-wm8753-objs := wm8753.o
>  snd-soc-wm9712-objs := wm9712.o
>  snd-soc-wm9713-objs := wm9713.o
>  snd-soc-cs4270-objs := cs4270.o
> +snd-soc-tlv320aic26-objs := tlv320aic26.o
>  snd-soc-tlv320aic3x-objs := tlv320aic3x.o
>  
>  obj-$(CONFIG_SND_SOC_AC97_CODEC)	+= snd-soc-ac97.o
> @@ -14,4 +15,5 @@ obj-$(CONFIG_SND_SOC_WM8753)	+= snd-soc-wm8753.o
>  obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
>  obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
>  obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
> +obj-$(CONFIG_SND_SOC_TLV320AIC26)	+= snd-soc-tlv320aic26.o
>  obj-$(CONFIG_SND_SOC_TLV320AIC3X)	+= snd-soc-tlv320aic3x.o
> diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
> new file mode 100644
> index 0000000..aee1dbc
> --- /dev/null
> +++ b/sound/soc/codecs/tlv320aic26.c
> @@ -0,0 +1,630 @@
> +/*
> + * Texas Instruments TLV320AIC26 low power audio CODEC
> + * ALSA SoC CODEC driver
> + *
> + * Copyright (C) 2008 Secret Lab Technologies Ltd.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/init.h>
> +#include <linux/delay.h>
> +#include <linux/pm.h>
> +#include <linux/device.h>
> +#include <linux/sysfs.h>
> +#include <linux/spi/spi.h>
> +#include <sound/core.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include <sound/soc-dapm.h>
> +#include <sound/soc-of.h>
> +#include <sound/initval.h>
> +
> +MODULE_DESCRIPTION("ASoC TLV320AIC26 codec driver");
> +MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
> +MODULE_LICENSE("GPL");
> +
> +/* AIC26 Registers */
> +#define AIC26_READ_COMMAND_WORD(addr)	((1 << 15) | (addr << 5))
> +#define AIC26_WRITE_COMMAND_WORD(addr)	((0 << 15) | (addr << 5))
> +#define AIC26_PAGE_ADDR(page, offset)	((page << 6) | offset)
> +#define AIC26_NUM_REGS			AIC26_PAGE_ADDR(3, 0)
> +#define AIC26_REG_CACHE_SIZE		(0x20) /* only page 2 cached */
> +#define AIC26_REG_IS_CACHED(addr)	((addr & ~0x1f) == (2 << 6))
> +#define AIC26_REG_CACHE_ADDR(addr)	(addr & 0x1f)
> +
> +/* Page 0: Auxillary data registers */
> +#define AIC26_REG_BAT1			AIC26_PAGE_ADDR(0, 0x05)
> +#define AIC26_REG_BAT2			AIC26_PAGE_ADDR(0, 0x06)
> +#define AIC26_REG_AUX			AIC26_PAGE_ADDR(0, 0x07)
> +#define AIC26_REG_TEMP1			AIC26_PAGE_ADDR(0, 0x09)
> +#define AIC26_REG_TEMP2			AIC26_PAGE_ADDR(0, 0x0A)
> +
> +/* Page 1: Auxillary control registers */
> +#define AIC26_REG_AUX_ADC		AIC26_PAGE_ADDR(1, 0x00)
> +#define AIC26_REG_STATUS		AIC26_PAGE_ADDR(1, 0x01)
> +#define AIC26_REG_REFERENCE		AIC26_PAGE_ADDR(1, 0x03)
> +#define AIC26_REG_RESET			AIC26_PAGE_ADDR(1, 0x04)
> +
> +/* Page 2: Audio control registers */
> +#define AIC26_REG_AUDIO_CTRL1		AIC26_PAGE_ADDR(2, 0x00)
> +#define AIC26_REG_ADC_GAIN		AIC26_PAGE_ADDR(2, 0x01)
> +#define AIC26_REG_DAC_GAIN		AIC26_PAGE_ADDR(2, 0x02)
> +#define AIC26_REG_SIDETONE		AIC26_PAGE_ADDR(2, 0x03)
> +#define AIC26_REG_AUDIO_CTRL2		AIC26_PAGE_ADDR(2, 0x04)
> +#define AIC26_REG_POWER_CTRL		AIC26_PAGE_ADDR(2, 0x05)
> +#define AIC26_REG_AUDIO_CTRL3		AIC26_PAGE_ADDR(2, 0x06)
> +
> +#define AIC26_REG_FILTER_COEFF_L_N0	AIC26_PAGE_ADDR(2, 0x07)
> +#define AIC26_REG_FILTER_COEFF_L_N1	AIC26_PAGE_ADDR(2, 0x08)
> +#define AIC26_REG_FILTER_COEFF_L_N2	AIC26_PAGE_ADDR(2, 0x09)
> +#define AIC26_REG_FILTER_COEFF_L_N3	AIC26_PAGE_ADDR(2, 0x0A)
> +#define AIC26_REG_FILTER_COEFF_L_N4	AIC26_PAGE_ADDR(2, 0x0B)
> +#define AIC26_REG_FILTER_COEFF_L_N5	AIC26_PAGE_ADDR(2, 0x0C)
> +#define AIC26_REG_FILTER_COEFF_L_D1	AIC26_PAGE_ADDR(2, 0x0D)
> +#define AIC26_REG_FILTER_COEFF_L_D2	AIC26_PAGE_ADDR(2, 0x0E)
> +#define AIC26_REG_FILTER_COEFF_L_D4	AIC26_PAGE_ADDR(2, 0x0F)
> +#define AIC26_REG_FILTER_COEFF_L_D5	AIC26_PAGE_ADDR(2, 0x10)
> +#define AIC26_REG_FILTER_COEFF_R_N0	AIC26_PAGE_ADDR(2, 0x11)
> +#define AIC26_REG_FILTER_COEFF_R_N1	AIC26_PAGE_ADDR(2, 0x12)
> +#define AIC26_REG_FILTER_COEFF_R_N2	AIC26_PAGE_ADDR(2, 0x13)
> +#define AIC26_REG_FILTER_COEFF_R_N3	AIC26_PAGE_ADDR(2, 0x14)
> +#define AIC26_REG_FILTER_COEFF_R_N4	AIC26_PAGE_ADDR(2, 0x15)
> +#define AIC26_REG_FILTER_COEFF_R_N5	AIC26_PAGE_ADDR(2, 0x16)
> +#define AIC26_REG_FILTER_COEFF_R_D1	AIC26_PAGE_ADDR(2, 0x17)
> +#define AIC26_REG_FILTER_COEFF_R_D2	AIC26_PAGE_ADDR(2, 0x18)
> +#define AIC26_REG_FILTER_COEFF_R_D4	AIC26_PAGE_ADDR(2, 0x19)
> +#define AIC26_REG_FILTER_COEFF_R_D5	AIC26_PAGE_ADDR(2, 0x1A)
> +
> +#define AIC26_REG_PLL_PROG1		AIC26_PAGE_ADDR(2, 0x1B)
> +#define AIC26_REG_PLL_PROG2		AIC26_PAGE_ADDR(2, 0x1C)
> +#define AIC26_REG_AUDIO_CTRL4		AIC26_PAGE_ADDR(2, 0x1D)
> +#define AIC26_REG_AUDIO_CTRL5		AIC26_PAGE_ADDR(2, 0x1E)
> +
> +#define AIC26_RATES	(SNDRV_PCM_RATE_8000  | SNDRV_PCM_RATE_11025 |\
> +			 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
> +			 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
> +			 SNDRV_PCM_RATE_48000)
> +#define AIC26_FORMATS	(SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_BE |\
> +			 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE)
> +

Fwiw, I usually put all the codec registers defs in a separate header
just in case we need to do any codec stuff in the machine driver.

> +/* fsref dividers; used in register 'Audio Control 1' */
> +enum aic26_divisors {
> +	AIC26_DIV_1	= 0,
> +	AIC26_DIV_1_5	= 1,
> +	AIC26_DIV_2	= 2,
> +	AIC26_DIV_3	= 3,
> +	AIC26_DIV_4	= 4,
> +	AIC26_DIV_5	= 5,
> +	AIC26_DIV_5_5	= 6,
> +	AIC26_DIV_6	= 7,
> +};
> +
> +/* Digital data format */
> +enum aic26_datfm {
> +	AIC26_DATFM_I2S		= 0 << 8,
> +	AIC26_DATFM_DSP		= 1 << 8,
> +	AIC26_DATFM_RIGHTJ	= 2 << 8, /* right justified */
> +	AIC26_DATFM_LEFTJ	= 3 << 8, /* left justified */
> +};
> +
> +/* Sample word length in bits; used in register 'Audio Control 1' */
> +enum aic26_wlen {
> +	AIC26_WLEN_16	= 0 << 10,
> +	AIC26_WLEN_20	= 1 << 10,
> +	AIC26_WLEN_24	= 2 << 10,
> +	AIC26_WLEN_32	= 3 << 10,
> +};
> +
> +/* AIC26 driver private data */
> +struct aic26 {
> +	struct spi_device *spi;
> +	struct snd_soc_codec codec;
> +	u16 reg_cache[AIC26_REG_CACHE_SIZE];	/* shadow registers */
> +	int master;
> +	int datfm;
> +	int mclk;
> +
> +	/* Keyclick parameters */
> +	int keyclick_amplitude;
> +	int keyclick_freq;
> +	int keyclick_len;
> +};
> +
> +/* ---------------------------------------------------------------------
> + * Register access routines
> + */
> +static unsigned int aic26_reg_read(struct snd_soc_codec *codec,
> +				   unsigned int reg)
> +{
> +	struct aic26 *aic26 = codec->private_data;
> +	u16 *cache = codec->reg_cache;
> +	u16 cmd, value;
> +	u8 buffer[2];
> +	int rc;
> +
> +	if ((reg < 0) || (reg >= AIC26_NUM_REGS)) {
> +		WARN_ON_ONCE(1);
> +		return 0;
> +	}
> +
> +	/* Do SPI transfer; first 16bits are command; remaining is
> +	 * register contents */
> +	cmd = AIC26_READ_COMMAND_WORD(reg);
> +	buffer[0] = (cmd >> 8) & 0xff;
> +	buffer[1] = cmd & 0xff;
> +	rc = spi_write_then_read(aic26->spi, buffer, 2, buffer, 2);
> +	if (rc) {
> +		dev_err(&aic26->spi->dev, "AIC26 reg read error\n");
> +		return -EIO;
> +	}
> +	value = (buffer[0] << 8) | buffer[1];
> +
> +	/* Update the cache before returning with the value */
> +	if (AIC26_REG_IS_CACHED(reg))
> +		cache[AIC26_REG_CACHE_ADDR(reg)] = value;
> +	return value;
> +}
> +
> +static unsigned int aic26_reg_read_cache(struct snd_soc_codec *codec,
> +					 unsigned int reg)
> +{
> +	u16 *cache = codec->reg_cache;
> +
> +	if ((reg < 0) || (reg >= AIC26_NUM_REGS)) {
> +		WARN_ON_ONCE(1);
> +		return 0;
> +	}
> +
> +	if (AIC26_REG_IS_CACHED(reg))
> +		return cache[AIC26_REG_CACHE_ADDR(reg)];
> +
> +	return aic26_reg_read(codec, reg);
> +}
> +
> +static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
> +		           unsigned int value)
> +{
> +	struct aic26 *aic26 = codec->private_data;
> +	u16 *cache = codec->reg_cache;
> +	u16 cmd;
> +	u8 buffer[4];
> +	int rc;
> +
> +	if ((reg < 0) || (reg >= AIC26_NUM_REGS)) {
> +		WARN_ON_ONCE(1);
> +		return -EINVAL;
> +	}
> +
> +	/* Do SPI transfer; first 16bits are command; remaining is data
> +	 * to write into register */
> +	cmd = AIC26_WRITE_COMMAND_WORD(reg);
> +	buffer[0] = (cmd >> 8) & 0xff;
> +	buffer[1] = cmd & 0xff;
> +	buffer[2] = value >> 8;
> +	buffer[3] = value;
> +	rc = spi_write(aic26->spi, buffer, 4);
> +	if (rc) {
> +		dev_err(&aic26->spi->dev, "AIC26 reg read error\n");
> +		return -EIO;
> +	}
> +
> +	/* update cache before returning */
> +	if (AIC26_REG_IS_CACHED(reg))
> +		cache[AIC26_REG_CACHE_ADDR(reg)] = value;
> +	return 0;
> +}
> +
> +/* ---------------------------------------------------------------------
> + * Digital Audio Interface Operations
> + */
> +static int aic26_hw_params(struct snd_pcm_substream *substream,
> +			   struct snd_pcm_hw_params *params)
> +{
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct snd_soc_device *socdev = rtd->socdev;
> +	struct snd_soc_codec *codec = socdev->codec;
> +	struct aic26 *aic26 = codec->private_data;
> +	int fsref, divisor, wlen, pval, jval, dval, qval;
> +	u16 reg;
> +
> +	dev_dbg(&aic26->spi->dev, "aic26_hw_params(substream=%p, params=%p)\n",
> +		substream, params);
> +	dev_dbg(&aic26->spi->dev, "rate=%i format=%i\n", params_rate(params),
> +		params_format(params));
> +
> +	switch (params_rate(params)) {
> +	 case 8000: fsref = 48000; divisor = AIC26_DIV_6; break;
> +	 case 11025: fsref = 44100; divisor = AIC26_DIV_4; break;
> +	 case 12000: fsref = 48000; divisor = AIC26_DIV_4; break;
> +	 case 16000: fsref = 48000; divisor = AIC26_DIV_3; break;
> +	 case 22050: fsref = 44100; divisor = AIC26_DIV_2; break;
> +	 case 24000: fsref = 48000; divisor = AIC26_DIV_2; break;
> +	 case 32000: fsref = 48000; divisor = AIC26_DIV_1_5; break;
> +	 case 44100: fsref = 44100; divisor = AIC26_DIV_1; break;
> +	 case 48000: fsref = 48000; divisor = AIC26_DIV_1; break;
> +	 default: dev_dbg(&aic26->spi->dev, "bad rate\n"); return -EINVAL;
> +	}
> +

Indentation.

> +	/* select data word length */
> +	switch (params_format(params)) {
> +	 case SNDRV_PCM_FORMAT_S8: wlen = AIC26_WLEN_16; break;
> +	 case SNDRV_PCM_FORMAT_S16_BE: wlen = AIC26_WLEN_16; break;
> +	 case SNDRV_PCM_FORMAT_S24_BE: wlen = AIC26_WLEN_24; break;
> +	 case SNDRV_PCM_FORMAT_S32_BE: wlen = AIC26_WLEN_32; break;
> +	 default: dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL;
> +	}
> +

ditto.

> +	/* Configure PLL */
> +	pval = 1;
> +	jval = (fsref == 44100) ? 7 : 8;
> +	dval = (fsref == 44100) ? 5264 : 1920;
> +	qval = 0;
> +	reg = 0x8000 | qval << 11 | pval << 8 | jval << 2;
> +	aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg);
> +	reg = dval << 2;
> +	aic26_reg_write(codec, AIC26_REG_PLL_PROG2, reg);
> +

PLL/FLL/clock config is usually done in a separate function
(codec_set_pll(), callable by machine driver) so that we can change
clocks depending on the available machine clocks and srate. 

> +	/* Power up CODEC */
> +	aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0);
> +

Codec domain (i.e Bias power) PM stuff should be done in
codec_dapm_event(). This allows us to power the codec on when we do
things like sidetone (with no active playback or capture stream).

> +	/* Audio Control 3 (master mode, fsref rate) */
> +	reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3);
> +	reg &= ~0xf800;
> +	if (aic26->master)
> +		reg |= 0x0800;
> +	if (fsref == 48000)
> +		reg |= 0x2000;
> +	aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
> +
> +	/* Audio Control 1 (FSref divisor) */
> +	reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1);
> +	reg &= ~0x0fff;
> +	reg |= wlen | aic26->datfm | (divisor << 3) | divisor;
> +	aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL1, reg);
> +
> +	return 0;
> +}
> +
> +/**
> + * aic26_mute - Mute control to reduce noise when changing audio format
> + */
> +static int aic26_mute(struct snd_soc_codec_dai *dai, int mute)
> +{
> +	struct snd_soc_codec *codec = dai->codec;
> +	struct aic26 *aic26 = codec->private_data;
> +	u16 reg = aic26_reg_read_cache(codec, AIC26_REG_DAC_GAIN);
> +
> +	dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n",
> +		dai, mute);
> +
> +	if (mute)
> +		reg |= 0x8080;
> +	else
> +		reg &= ~0x8080;
> +	aic26_reg_write(codec, AIC26_REG_DAC_GAIN, reg);
> +
> +	return 0;
> +}
> +
> +static int aic26_set_sysclk(struct snd_soc_codec_dai *codec_dai,
> +			    int clk_id, unsigned int freq, int dir)
> +{
> +	struct snd_soc_codec *codec = codec_dai->codec;
> +	struct aic26 *aic26 = codec->private_data;
> +
> +	dev_dbg(&aic26->spi->dev, "aic26_set_sysclk(dai=%p, clk_id==%i,"
> +		" freq=%i, dir=%i)\n",
> +		codec_dai, clk_id, freq, dir);
> +
> +	/* MCLK needs to fall between 2MHz and 50 MHz */
> +	if ((freq < 2000000) || (freq > 50000000))
> +		return -EINVAL;
> +
> +	aic26->mclk = freq;
> +	return 0;
> +}
> +
> +static int aic26_set_fmt(struct snd_soc_codec_dai *codec_dai, unsigned int fmt)
> +{
> +	struct snd_soc_codec *codec = codec_dai->codec;
> +	struct aic26 *aic26 = codec->private_data;
> +
> +	dev_dbg(&aic26->spi->dev, "aic26_set_fmt(dai=%p, fmt==%i)\n",
> +		codec_dai, fmt);
> +
> +	/* set master/slave audio interface */
> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +	 case SND_SOC_DAIFMT_CBM_CFM: aic26->master = 1; break;
> +	 //case SND_SOC_DAIFMT_CBS_CFS: aic26->master = 0; break;
> +	 default: dev_dbg(&aic26->spi->dev, "bad master\n"); return -EINVAL;
> +	}
> +
> +	/* interface format */
> +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +	 case SND_SOC_DAIFMT_I2S: aic26->datfm = AIC26_DATFM_I2S; break;
> +	 case SND_SOC_DAIFMT_DSP_A: aic26->datfm = AIC26_DATFM_DSP; break;
> +	 case SND_SOC_DAIFMT_RIGHT_J: aic26->datfm = AIC26_DATFM_RIGHTJ; break;
> +	 case SND_SOC_DAIFMT_LEFT_J: aic26->datfm = AIC26_DATFM_LEFTJ; break;
> +	 default: dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +/* ---------------------------------------------------------------------
> + * Digital Audio Interface Definition
> + */
> +struct snd_soc_codec_dai aic26_dai = {
> +	.name = "tlv320aic26",
> +	.playback = {
> +		.stream_name = "Playback",
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = AIC26_RATES,
> +		.formats = AIC26_FORMATS,
> +	},
> +	.capture = {
> +		.stream_name = "Capture",
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = AIC26_RATES,
> +		.formats = AIC26_FORMATS,
> +	},
> +	.ops = {
> +		.hw_params = aic26_hw_params,
> +	},
> +	.dai_ops = {
> +		.digital_mute = aic26_mute,
> +		.set_sysclk = aic26_set_sysclk,
> +		.set_fmt = aic26_set_fmt,
> +	},
> +};
> +EXPORT_SYMBOL_GPL(aic26_dai);
> +
> +/* ---------------------------------------------------------------------
> + * ALSA controls
> + */
> +static const char *aic26_capture_src_text[] = {"Mic", "Aux"};
> +static const struct soc_enum aic26_capture_src_enum =
> +	SOC_ENUM_SINGLE(AIC26_REG_AUDIO_CTRL1, 12,2, aic26_capture_src_text);
> +
> +static const struct snd_kcontrol_new aic26_snd_controls[] = {
> +	/* Output */
> +	SOC_DOUBLE("PCM Playback Volume", AIC26_REG_DAC_GAIN, 8, 0, 0x7f, 1),
> +	SOC_DOUBLE("PCM Playback Switch", AIC26_REG_DAC_GAIN, 15, 7, 1, 1),
> +	SOC_SINGLE("PCM Capture Volume", AIC26_REG_ADC_GAIN, 8, 0x7f, 0),
> +	SOC_SINGLE("PCM Capture Mute", AIC26_REG_ADC_GAIN, 15, 1, 1),
> +	SOC_ENUM("Capture Source", aic26_capture_src_enum),
> +};
> +
> +/* ---------------------------------------------------------------------
> + * SoC CODEC portion of driver: probe and release routines
> + */
> +static int aic26_probe(struct platform_device *pdev)
> +{
> +	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
> +	struct snd_soc_codec *codec;
> +	struct snd_kcontrol *kcontrol;
> +	struct aic26 *aic26;
> +	int i, ret, err;
> +
> +	dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n");
> +	dev_dbg(&pdev->dev, "socdev=%p\n", socdev);
> +	dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data);
> +
> +	/* Fetch the relevant aic26 private data here (it's already been
> +	 * stored in the .codec pointer) */
> +	aic26 = socdev->codec_data;
> +	if (aic26 == NULL) {
> +		dev_err(&pdev->dev, "aic26: missing codec pointer\n");
> +		return -ENODEV;
> +	}
> +	codec = &aic26->codec;
> +	socdev->codec = codec;
> +
> +	dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n",
> +		&pdev->dev, socdev->dev);
> +	/* register pcms */
> +	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "aic26: failed to create pcms\n");
> +		return -ENODEV;
> +	}
> +
> +	/* register controls */
> +	dev_dbg(&pdev->dev, "Registering controls\n");
> +	for (i = 0; i < ARRAY_SIZE(aic26_snd_controls); i++) {
> +		kcontrol = snd_soc_cnew(&aic26_snd_controls[i], codec, NULL);
> +		err = snd_ctl_add(codec->card, kcontrol);
> +		WARN_ON(err < 0);
> +	}
> +
> +	/* CODEC is setup, we can register the card now */
> +	dev_dbg(&pdev->dev, "Registering card\n");
> +	ret = snd_soc_register_card(socdev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "aic26: failed to register card\n");
> +		goto card_err;
> +	}
> +	return 0;
> +
> + card_err:
> +	snd_soc_free_pcms(socdev);
> +	return ret;
> +}
> +
> +static int aic26_remove(struct platform_device *pdev)
> +{
> +	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
> +	snd_soc_free_pcms(socdev);
> +	return 0;
> +}
> +
> +struct snd_soc_codec_device aic26_soc_codec_dev = {
> +	.probe = aic26_probe,
> +	.remove = aic26_remove,
> +};
> +
> +/* ---------------------------------------------------------------------
> + * SPI device portion of driver: sysfs files for debugging
> + */
> +
> +static ssize_t aic26_regs_show(struct device *dev,
> +				struct device_attribute *attr, char *buf)
> +{
> +	struct aic26 *aic26 = dev_get_drvdata(dev);
> +	char *idx = buf;
> +	int cache_flag, addr, page, i, reg;
> +
> +	cache_flag = (strcmp(attr->attr.name, "regs_cache") == 0);
> +
> +	for (page = 0; page < 3; page++) {
> +		for (i = 0; i < 0x20; i++) {
> +			addr = AIC26_PAGE_ADDR(page, i);
> +			if (i % 8 == 0)
> +				idx += sprintf(idx, "%i:%.2i:", page,i);
> +			if (cache_flag)
> +				reg = aic26_reg_read_cache(&aic26->codec, addr);
> +			else
> +				reg = aic26_reg_read(&aic26->codec, addr);
> +			idx += sprintf(idx, " %.4x", reg);
> +			if (i % 8 == 7)
> +				idx += sprintf(idx, "\n");
> +		}
> +	}
> +	return idx - buf;
> +}
> +

The soc_core already has a codec reg dump sysfs file, so we don't need
this.

> +static ssize_t aic26_keyclick_show(struct device *dev,
> +				   struct device_attribute *attr, char *buf)
> +{
> +	struct aic26 *aic26 = dev_get_drvdata(dev);
> +	int val, amp, freq, len;
> +
> +	val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2);
> +	amp = (val >> 12) & 0x7;
> +	freq = (125 << ((val >> 8) & 0x7)) >> 1;
> +	len = 2 * (1 +((val >> 8) & 0xf));
> +
> +	return sprintf(buf, "amp=%x freq=%iHz len=%iclks\n", amp, freq, len);
> +}
> +
> +/* Any write to the keyclick attribute will trigger the keyclick */
> +static ssize_t aic26_keyclick_set(struct device *dev,
> +				  struct device_attribute *attr,
> +				  const char *buf, size_t count)
> +{
> +	struct aic26 *aic26 = dev_get_drvdata(dev);
> +	int val;
> +
> +	val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2);
> +	val |= 0x8000;
> +	aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL2, val);
> +
> +	return count;
> +}
> +
> +DEVICE_ATTR(regs, 0644, aic26_regs_show, NULL);
> +DEVICE_ATTR(regs_cache, 0644, aic26_regs_show, NULL);
> +DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
> +
> +/* ---------------------------------------------------------------------
> + * SPI device portion of driver: probe and release routines and SPI
> + * 				 driver registration.
> + */
> +static int aic26_spi_probe(struct spi_device *spi)
> +{
> +	struct aic26 *aic26;
> +	int rc, i, reg;
> +
> +	dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
> +
> +	/* Allocate driver data */
> +	aic26 = kzalloc(sizeof *aic26, GFP_KERNEL);
> +	if (!aic26)
> +		return -ENOMEM;
> +
> +	/* Initialize the driver data */
> +	aic26->spi = spi;
> +	dev_set_drvdata(&spi->dev, aic26);
> +
> +	/* Setup what we can in the codec structure so that the register
> +	 * access functions will work as expected.  More will be filled
> +	 * out when it is probed by the SoC CODEC part of this driver */
> +	aic26->codec.private_data = aic26;
> +	aic26->codec.name = "aic26";
> +	aic26->codec.owner = THIS_MODULE;
> +	aic26->codec.dai = &aic26_dai;
> +	aic26->codec.num_dai = 1;
> +	aic26->codec.read = aic26_reg_read;
> +	aic26->codec.write = aic26_reg_write;
> +	aic26->master = 1;
> +	mutex_init(&aic26->codec.mutex);
> +	INIT_LIST_HEAD(&aic26->codec.dapm_widgets);
> +	INIT_LIST_HEAD(&aic26->codec.dapm_paths);
> +	aic26->codec.reg_cache_size = sizeof(aic26->reg_cache);
> +	aic26->codec.reg_cache = aic26->reg_cache;
> +
> +	/* Reset the codec to power on defaults */
> +	aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00);
> +
> +	/* Power up CODEC */
> +	aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0);
> +
> +	/* Audio Control 3 (master mode, fsref rate) */
> +	reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3);
> +	reg &= ~0xf800;
> +	reg |= 0x0800; /* set master mode */
> +	aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg);
> +
> +	/* Fill page 2 register cache */
> +	for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++)
> +		aic26_reg_read(&aic26->codec, AIC26_PAGE_ADDR(2, i));
> +
> +	/* Register the sysfs files for debugging */
> +	/* Create SysFS files */
> +	rc = device_create_file(&spi->dev, &dev_attr_regs);
> +	rc |= device_create_file(&spi->dev, &dev_attr_regs_cache);
> +	rc |= device_create_file(&spi->dev, &dev_attr_keyclick);
> +	if (rc)
> +		dev_info(&spi->dev, "error creating sysfs files\n");
> +
> +	/* Tell the of_soc helper about this codec */
> +	of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai,
> +				  spi->dev.archdata.of_node);
> +
> +	dev_dbg(&spi->dev, "SPI device initialized\n");
> +	return 0;
> +}
> +
> +static int aic26_spi_remove(struct spi_device *spi)
> +{
> +	struct aic26 *aic26 = dev_get_drvdata(&spi->dev);
> +
> +	kfree(aic26);
> +
> +	return 0;
> +}
> +
> +static struct spi_driver aic26_spi = {
> +	.driver = {
> +		.name = "tlv320aic26",
> +		.owner = THIS_MODULE,
> +	},
> +	.probe = aic26_spi_probe,
> +	.remove = aic26_spi_remove,
> +};
> +
> +static int __init aic26_init(void)
> +{
> +	return spi_register_driver(&aic26_spi);
> +}
> +module_init(aic26_init);
> +
> +static void __exit aic26_exit(void)
> +{
> +	spi_unregister_driver(&aic26_spi);
> +}
> +module_exit(aic26_exit);
> 
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel


Privacy & Confidentiality Notice
-------------------------------------------------
This message and any attachments contain privileged and confidential information that is intended solely for the person(s) to whom it is addressed. If you are not an intended recipient you must not: read; copy; distribute; discuss; take any action in or make any reliance upon the contents of this message; nor open or read any attachment. If you have received this message in error, please notify us as soon as possible on the following telephone number and destroy this message including any attachments. Thank you.
-------------------------------------------------
Wolfson Microelectronics plc
Tel: +44 (0)131 272 7000
Fax: +44 (0)131 272 7001
Web: www.wolfsonmicro.com

Registered in Scotland

Company number SC089839

Registered office: 

Westfield House, 26 Westfield Road, Edinburgh, EH11 2QB, UK

^ permalink raw reply

* Re: [alsa-devel] [PATCH 2/3] ALSA SoC: Add mpc5200-psc I2S driver
From: Liam Girdwood @ 2008-07-02 10:34 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev, alsa-devel, broonie, timur
In-Reply-To: <20080701235335.16923.43253.stgit@trillian.secretlab.ca>

On Tue, 2008-07-01 at 17:53 -0600, Grant Likely wrote:
> From: Grant Likely <grant.likely@secretlab.ca>
> 
> This is an I2S bus driver for the MPC5200 PSC device.  It is probably
> will not be merged as-is because it uses v1 of the ASoC API, but I want
> to get it out there for comments.

Looks good, just minor comments.

> ---
> 
>  sound/soc/fsl/Kconfig           |    6 
>  sound/soc/fsl/Makefile          |    2 
>  sound/soc/fsl/mpc5200_psc_i2s.c |  899 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 907 insertions(+), 0 deletions(-)
> 
> diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
> index 257101f..5daa8d3 100644
> --- a/sound/soc/fsl/Kconfig
> +++ b/sound/soc/fsl/Kconfig
> @@ -17,4 +17,10 @@ config SND_SOC_MPC8610_HPCD
>  	help
>  	  Say Y if you want to enable audio on the Freescale MPC8610 HPCD.
>  
> +config SND_SOC_MPC5200_I2S
> +	bool "Freescale MPC5200 PSC in I2S mode driver"

Is this built-in only ?

> +	depends on SND_SOC && PPC_MPC52xx
> +	help
> +	  Say Y here to support the MPC5200 PSCs in I2S mode.
> +
>  endmenu
> diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
> index 62f680a..98729a1 100644
> --- a/sound/soc/fsl/Makefile
> +++ b/sound/soc/fsl/Makefile
> @@ -4,3 +4,5 @@ obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o
>  # MPC8610 Platform Support
>  obj-$(CONFIG_SND_SOC_MPC8610) += fsl_ssi.o fsl_dma.o
>  
> +obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o
> +
> diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
> new file mode 100644
> index 0000000..81d0933
> --- /dev/null
> +++ b/sound/soc/fsl/mpc5200_psc_i2s.c
> @@ -0,0 +1,899 @@
> +/*
> + * Freescale MPC5200 PSC in I2S mode
> + * ALSA SoC Digital Audio Interface (DAI) driver
> + *
> + * Copyright (C) 2008 Secret Lab Technologies Ltd.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/device.h>
> +#include <linux/delay.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/dma-mapping.h>
> +
> +#include <sound/core.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/initval.h>
> +#include <sound/soc.h>
> +#include <sound/soc-of.h>
> +
> +#include <sysdev/bestcomm/bestcomm.h>
> +#include <sysdev/bestcomm/gen_bd.h>
> +#include <asm/mpc52xx_psc.h>
> +
> +MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
> +MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver");
> +MODULE_LICENSE("GPL");
> +
> +/**
> + * PSC_I2S_RATES: sample rates supported by the I2S
> + *
> + * This driver currently only supports the PSC running in I2S slave mode,
> + * which means the codec determines the sample rate.  Therefore, we tell
> + * ALSA that we support all rates and let the codec driver decide what rates
> + * are really supported.
> + */
> +#define PSC_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
> +			SNDRV_PCM_RATE_CONTINUOUS)
> +
> +/**
> + * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode
> + */
> +#define PSC_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \
> +			 SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE | \
> +			 SNDRV_PCM_FMTBIT_S32_BE)
> +
> +/**
> + * psc_i2s_stream - Data specific to a single stream (playback or capture)
> + * @active:		flag indicating if the stream is active
> + * @psc_i2s:		pointer back to parent psc_i2s data structure
> + * @bcom_task:		bestcomm task structure
> + * @irq:		irq number for bestcomm task
> + * @period_start:	physical address of start of DMA region
> + * @period_end:		physical address of end of DMA region
> + * @period_next_pt:	physical address of next DMA buffer to enqueue
> + * @period_bytes:	size of DMA period in bytes
> + */
> +struct psc_i2s_stream {
> +	int active;
> +	struct psc_i2s *psc_i2s;
> +	struct bcom_task *bcom_task;
> +	int irq;
> +	struct snd_pcm_substream *stream;
> +	dma_addr_t period_start;
> +	dma_addr_t period_end;
> +	dma_addr_t period_next_pt;
> +	dma_addr_t period_current_pt;
> +	int period_bytes;
> +};
> +
> +/**
> + * psc_i2s - Private driver data
> + * @name: short name for this device ("PSC0", "PSC1", etc)
> + * @psc_regs: pointer to the PSC's registers
> + * @fifo_regs: pointer to the PSC's FIFO registers
> + * @irq: IRQ of this PSC
> + * @dev: struct device pointer
> + * @playback: the number of playback streams opened
> + * @capture: the number of capture streams opened
> + * @dai: the CPU DAI for this device
> + * @playback_stream: Playback stream context data
> + * @capture_stream: Capture stream context data
> + */
> +struct psc_i2s {
> +	char name[32];
> +	struct mpc52xx_psc __iomem *psc_regs;
> +	struct mpc52xx_psc_fifo __iomem *fifo_regs;
> +	unsigned int irq;
> +	struct device *dev;
> +	struct snd_soc_cpu_dai dai;
> +	spinlock_t lock;
> +
> +	/* per-stream data */
> +	struct psc_i2s_stream playback_stream;
> +	struct psc_i2s_stream capture_stream;
> +
> +	/* Statistics */
> +	struct {
> +		int overrun_count;
> +		int underrun_count;
> +	} stats;
> +};
> +
> +/*
> + * Interrupt handlers
> + */
> +static irqreturn_t psc_i2s_status_irq(int irq, void *_psc_i2s)
> +{
> +	struct psc_i2s *psc_i2s = _psc_i2s;
> +	struct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;
> +	u16 imr;
> +	u16 isr;
> +
> +	isr = in_be16(&regs->mpc52xx_psc_isr);
> +	imr = in_be16(&regs->mpc52xx_psc_imr);
> +
> +	/* Playback underrun error */
> +	if (isr & imr & MPC52xx_PSC_IMR_TXEMP)
> +		psc_i2s->stats.underrun_count++;
> +
> +	/* Capture overrun error */
> +	if (isr & imr & MPC52xx_PSC_IMR_ORERR)
> +		psc_i2s->stats.overrun_count++;
> +
> +	out_8(&regs->command, 4 << 4);	/* reset the error status */
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + * psc_i2s_bcom_enqueue_next_buffer - Enqueue another audio buffer
> + * @s: pointer to stream private data structure
> + *
> + * Enqueues another audio period buffer into the bestcomm queue.
> + *
> + * Note: The routine must only be called when there is space available in
> + * the queue.  Otherwise the enqueue will fail and the audio ring buffer
> + * will get out of sync
> + */
> +static void psc_i2s_bcom_enqueue_next_buffer(struct psc_i2s_stream *s)
> +{
> +	struct bcom_bd *bd;
> +
> +	/* Prepare and enqueue the next buffer descriptor */
> +	bd = bcom_prepare_next_buffer(s->bcom_task);
> +	bd->status = s->period_bytes;
> +	bd->data[0] = s->period_next_pt;
> +	bcom_submit_next_buffer(s->bcom_task, NULL);
> +
> +	/* Update for next period */
> +	s->period_next_pt += s->period_bytes;
> +	if (s->period_next_pt >= s->period_end)
> +		s->period_next_pt = s->period_start;
> +}
> +
> +/* Bestcomm DMA irq handler */
> +static irqreturn_t psc_i2s_bcom_irq(int irq, void *_psc_i2s_stream)
> +{
> +	struct psc_i2s_stream *s = _psc_i2s_stream;
> +
> +	//spin_lock(&s->psc_i2s->lock);
> +
> +	/* For each finished period, dequeue the completed period buffer
> +	 * and enqueue a new one in it's place. */
> +	while (bcom_buffer_done(s->bcom_task)) {
> +		bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
> +		s->period_current_pt += s->period_bytes;
> +		if (s->period_current_pt >= s->period_end)
> +			s->period_current_pt = s->period_start;
> +		psc_i2s_bcom_enqueue_next_buffer(s);
> +		bcom_enable(s->bcom_task);
> +	}
> +
> +	//spin_unlock(&s->psc_i2s->lock);
> +
> +	/* If the stream is active, then also inform the PCM middle layer
> +	 * of the period finished event. */
> +	if (s->active)
> +		snd_pcm_period_elapsed(s->stream);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + * psc_i2s_startup: create a new substream
> + *
> + * This is the first function called when a stream is opened.
> + *
> + * If this is the first stream open, then grab the IRQ and program most of
> + * the PSC registers.
> + */
> +static int psc_i2s_startup(struct snd_pcm_substream *substream)
> +{
> +	int playback_irq, capture_irq, rc;
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
> +	struct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;
> +	struct mpc52xx_psc_fifo __iomem *fiforegs = psc_i2s->fifo_regs;
> +
> +	dev_dbg(psc_i2s->dev, "psc_i2s_startup(substream=%p)\n", substream);
> +
> +	/* Disable all interrupts and reset the PSC */
> +	out_be16(&regs->mpc52xx_psc_imr, 0);
> +	out_8(&regs->command, 3 << 4); /* reset transmitter */
> +	out_8(&regs->command, 2 << 4); /* reset receiver */
> +	out_8(&regs->command, 1 << 4); /* reset mode */
> +	out_8(&regs->command, 4 << 4); /* reset error */
> +
> +	/* Default to CODEC8 mode */
> +	out_be32(&regs->sicr,
> +		 MPC52xx_PSC_SICR_DTS1 | MPC52xx_PSC_SICR_I2S |
> +		 MPC52xx_PSC_SICR_CLKPOL | MPC52xx_PSC_SICR_SIM_CODEC_8);
> +
> +	/* First write: RxRdy (FIFO Alarm) generates receive FIFO interrupt */
> +	/* Second write to mode: register Normal mode for non loopback */
> +	out_8(&regs->mode, 0);
> +	out_8(&regs->mode, 0);
> +
> +	/* Set the TX and RX fifo alarm thresholds */
> +	out_be16(&fiforegs->rfalarm, 0x100);	/* set RFALARM level */
> +	out_8(&fiforegs->rfcntl, 0x4);		/* set RFGRAN level (bytes) */
> +	out_be16(&fiforegs->tfalarm, 0x100);	/* set TFALARM level */
> +	out_8(&fiforegs->tfcntl, 0x7);		/* set TFGRAN level (bytes*4) */
> +
> +	/* Setup the IRQs */
> +	playback_irq = bcom_get_task_irq(psc_i2s->playback_stream.bcom_task);
> +	capture_irq = bcom_get_task_irq(psc_i2s->capture_stream.bcom_task);
> +	rc = request_irq(psc_i2s->irq, &psc_i2s_status_irq, IRQF_SHARED,
> +			 "psc-i2s-status", psc_i2s);
> +	rc |= request_irq(capture_irq, &psc_i2s_bcom_irq, IRQF_SHARED,
> +			  "psc-i2s-capture", &psc_i2s->capture_stream);
> +	rc |= request_irq(playback_irq, &psc_i2s_bcom_irq, IRQF_SHARED,
> +			  "psc-i2s-playback", &psc_i2s->playback_stream);
> +	if (rc) {
> +		free_irq(psc_i2s->irq, psc_i2s);
> +		free_irq(capture_irq, &psc_i2s->capture_stream);
> +		free_irq(playback_irq, &psc_i2s->playback_stream);
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
> +				 struct snd_pcm_hw_params *params)
> +{
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
> +	u32 sicr;
> +
> +	dev_dbg(psc_i2s->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
> +		" periods=%i buffer_size=%i  buffer_bytes=%i\n",
> +		__FUNCTION__, substream, params_period_size(params),
> +		params_period_bytes(params), params_periods(params),
> +		params_buffer_size(params), params_buffer_bytes(params));
> +
> +	sicr = MPC52xx_PSC_SICR_DTS1 |
> +	       MPC52xx_PSC_SICR_I2S | MPC52xx_PSC_SICR_CLKPOL;
> +	switch (params_format(params)) {
> +	 case SNDRV_PCM_FORMAT_S8:
> +		sicr |= MPC52xx_PSC_SICR_SIM_CODEC_8;
> +		break;
> +	 case SNDRV_PCM_FORMAT_S16_BE:
> +		sicr |= MPC52xx_PSC_SICR_SIM_CODEC_16;
> +		break;
> +	 case SNDRV_PCM_FORMAT_S24_BE:
> +		sicr |= MPC52xx_PSC_SICR_SIM_CODEC_24;
> +		break;
> +	 case SNDRV_PCM_FORMAT_S32_BE:
> +		sicr |= MPC52xx_PSC_SICR_SIM_CODEC_32;
> +		break;
> +	 default:
> +		dev_dbg(psc_i2s->dev, "invalid format\n");
> +		return -EINVAL;
> +	}

case should have the same indent level as switch.

> +	out_be32(&psc_i2s->psc_regs->sicr, sicr);
> +
> +	//rc = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
> +	//if (rc) {
> +	//	dev_err(psc_i2s->dev, "could not allocate dma buffer\n");
> +	//	return rc;
> +	//}
> +
> +	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
> +
> +	return 0;
> +}
> +
> +static int psc_i2s_hw_free(struct snd_pcm_substream *substream)
> +{
> +	//return snd_pcm_lib_free_pages(substream);
> +	snd_pcm_set_runtime_buffer(substream, NULL);
> +	return 0;
> +}
> +
> +/**
> + * psc_i2s_trigger: start and stop the DMA transfer.
> + *
> + * This function is called by ALSA to start, stop, pause, and resume the DMA
> + * transfer of data.
> + */
> +static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
> +{
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	struct psc_i2s_stream *s;
> +	struct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;
> +	u16 imr;
> +	u8 psc_cmd;
> +	long flags;
> +
> +	if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
> +		s = &psc_i2s->capture_stream;
> +	else
> +		s = &psc_i2s->playback_stream;
> +
> +	dev_dbg(psc_i2s->dev, "psc_i2s_trigger(substream=%p, cmd=%i)"
> +		" stream_id=%i\n",
> +		substream, cmd, substream->pstr->stream);
> +
> +	switch (cmd) {
> +	 case SNDRV_PCM_TRIGGER_START:

ditto re case indent.

> +		s->period_bytes = frames_to_bytes(runtime,
> +						  runtime->period_size);
> +		s->period_start = virt_to_phys(runtime->dma_area);
> +		s->period_end = s->period_start +
> +				(s->period_bytes * runtime->periods);
> +		s->period_next_pt = s->period_start;
> +		s->period_current_pt = s->period_start;
> +		s->active = 1;
> +
> +		/* First; reset everything */
> +		if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
> +			out_8(&regs->command, MPC52xx_PSC_RST_RX);
> +			out_8(&regs->command, MPC52xx_PSC_RST_ERR_STAT);
> +		} else {
> +			out_8(&regs->command, MPC52xx_PSC_RST_TX);
> +			out_8(&regs->command, MPC52xx_PSC_RST_ERR_STAT);
> +		}
> +
> +		/* Next, fill up the bestcomm bd queue and enable DMA.
> +		 * This will begin filling the PSC's fifo. */
> +		if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
> +			bcom_gen_bd_rx_reset(s->bcom_task);
> +		else
> +			bcom_gen_bd_tx_reset(s->bcom_task);
> +		while (!bcom_queue_full(s->bcom_task))
> +			psc_i2s_bcom_enqueue_next_buffer(s);
> +		bcom_enable(s->bcom_task);
> +
> +		/* Update interrupt enable settings.  This must be done
> +		 * before the PSC is enabled so that TX underrun events
> +		 * are not missed. */
> +		imr = 0;
> +		if (psc_i2s->playback_stream.active)
> +			imr |= MPC52xx_PSC_IMR_TXEMP;
> +		if (psc_i2s->capture_stream.active)
> +			imr |= MPC52xx_PSC_IMR_ORERR;
> +		out_be16(&regs->isr_imr.imr, imr);
> +
> +		/* Due to errata in the i2s mode; need to line up enabling
> +		 * the transmitter with a transition on the frame sync
> +		 * line */
> +
> +		spin_lock_irqsave(&psc_i2s->lock, flags);
> +		/* first make sure it is low */
> +		while ((in_8(&regs->ipcr_acr.ipcr) & 0x80) != 0);
> +		/* then wait for the transition to high */
> +		while ((in_8(&regs->ipcr_acr.ipcr) & 0x80) == 0);

We should be able to exit both while loops if the conditions are not met
within a certain time limit. 

> +		/* Finally, enable the PSC.
> +		 * Receiver must always be enabled; even when we only want
> +		 * transmit.  (see 15.3.2.3 of MPC5200B User's Guide) */
> +		psc_cmd = MPC52xx_PSC_RX_ENABLE;
> +		if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK)
> +			psc_cmd |= MPC52xx_PSC_TX_ENABLE;
> +		out_8(&regs->command, psc_cmd);
> +		spin_unlock_irqrestore(&psc_i2s->lock, flags);
> +
> +		break;
> +
> +	 case SNDRV_PCM_TRIGGER_STOP:
> +		/* Turn off the PSC */
> +		s->active = 0;
> +		if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
> +			if (!psc_i2s->playback_stream.active) {
> +				out_8(&regs->command, 2 << 4);	/* reset rx */
> +				out_8(&regs->command, 3 << 4);	/* reset tx */
> +				out_8(&regs->command, 4 << 4);	/* reset err */
> +			}
> +		} else {
> +			out_8(&regs->command, 3 << 4);	/* reset tx */
> +			out_8(&regs->command, 4 << 4);	/* reset err */
> +			if (!psc_i2s->capture_stream.active)
> +				out_8(&regs->command, 2 << 4);	/* reset rx */
> +		}
> +
> +		bcom_disable(s->bcom_task);
> +		while (!bcom_queue_empty(s->bcom_task))
> +			bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
> +
> +		break;
> +
> +	 default:
> +		dev_dbg(psc_i2s->dev, "invalid command\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Update interrupt enable settings */
> +	imr = 0;
> +	if (psc_i2s->playback_stream.active) imr |= MPC52xx_PSC_IMR_TXEMP;
> +	if (psc_i2s->capture_stream.active) imr |= MPC52xx_PSC_IMR_ORERR;
> +	out_be16(&regs->isr_imr.imr, imr);
> +
> +	return 0;
> +}
> +
> +/**
> + * psc_i2s_shutdown: shutdown the data transfer on a stream
> + *
> + * Shutdown the PSC if there are no other substreams open.
> + */
> +static void psc_i2s_shutdown(struct snd_pcm_substream *substream)
> +{
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
> +
> +	dev_dbg(psc_i2s->dev, "psc_i2s_shutdown(substream=%p)\n", substream);
> +
> +	/*
> +	 * If this is the last active substream, disable the PSC and release
> +	 * the IRQ.
> +	 */
> +	if (!psc_i2s->playback_stream.active &&
> +	    !psc_i2s->capture_stream.active) {
> +		/* TODO: shut off channels */
> +		free_irq(psc_i2s->irq, psc_i2s);
> +		free_irq(bcom_get_task_irq(psc_i2s->capture_stream.bcom_task),
> +			 &psc_i2s->capture_stream);
> +		free_irq(bcom_get_task_irq(psc_i2s->playback_stream.bcom_task),
> +			 &psc_i2s->playback_stream);
> +	}
> +}
> +
> +/**
> + * psc_i2s_set_sysclk: set the clock frequency and direction
> + *
> + * This function is called by the machine driver to tell us what the clock
> + * frequency and direction are.
> + *
> + * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN),
> + * and we don't care about the frequency.  Return an error if the direction
> + * is not SND_SOC_CLOCK_IN.
> + *
> + * @clk_id: reserved, should be zero
> + * @freq: the frequency of the given clock ID, currently ignored
> + * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master)
> + */
> +static int psc_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
> +			      int clk_id, unsigned int freq, int dir)
> +{
> +	struct psc_i2s *psc_i2s = cpu_dai->private_data;
> +	dev_dbg(psc_i2s->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n",
> +				cpu_dai, dir);
> +	return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
> +}
> +
> +/**
> + * psc_i2s_set_fmt: set the serial format.
> + *
> + * This function is called by the machine driver to tell us what serial
> + * format to use.
> + *
> + * This driver only supports I2S mode.  Return an error if the format is
> + * not SND_SOC_DAIFMT_I2S.
> + *
> + * @format: one of SND_SOC_DAIFMT_xxx
> + */
> +static int psc_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai, unsigned int format)
> +{
> +	struct psc_i2s *psc_i2s = cpu_dai->private_data;
> +	dev_dbg(psc_i2s->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n",
> +				cpu_dai, format);
> +	return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
> +}
> +
> +/* ---------------------------------------------------------------------
> + * ALSA SoC Bindings
> + *
> + * - Digital Audio Interface (DAI) template
> + * - create/destroy dai hooks
> + */
> +
> +/**
> + * psc_i2s_dai_template: template CPU Digital Audio Interface
> + */
> +static struct snd_soc_cpu_dai psc_i2s_dai_template = {
> +	.type = SND_SOC_DAI_I2S,
> +	.playback = {
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = PSC_I2S_RATES,
> +		.formats = PSC_I2S_FORMATS,
> +	},
> +	.capture = {
> +		.channels_min = 2,
> +		.channels_max = 2,
> +		.rates = PSC_I2S_RATES,
> +		.formats = PSC_I2S_FORMATS,
> +	},
> +	.ops = {
> +		.startup = psc_i2s_startup,
> +		.hw_params = psc_i2s_hw_params,
> +		.hw_free = psc_i2s_hw_free,
> +		.shutdown = psc_i2s_shutdown,
> +		.trigger = psc_i2s_trigger,
> +	},
> +	.dai_ops = {
> +		.set_sysclk = psc_i2s_set_sysclk,
> +		.set_fmt = psc_i2s_set_fmt,
> +	},
> +};
> +
> +/* ---------------------------------------------------------------------
> + * The PSC I2S 'ASoC platform' driver
> + *
> + * Can be referenced by an 'ASoC machine' driver
> + * This driver only deals with the audio bus; it doesn't have any
> + * interaction with the attached codec
> + */
> +
> +static const struct snd_pcm_hardware psc_i2s_pcm_hardware = {
> +	.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
> +		SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER,
> +	.formats = SNDRV_PCM_FMTBIT_S8 |SNDRV_PCM_FMTBIT_S16_BE |
> +		   SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,
> +	.rate_min = 8000,
> +	.rate_max = 48000,
> +	.channels_min = 2,
> +	.channels_max = 2,
> +	.period_bytes_max	= 1024 * 1024,
> +	.period_bytes_min	= 32,
> +	.period_bytes_max	= 1024 * 1024,
> +	.periods_min		= 2,
> +	.periods_max		= 256,
> +	.buffer_bytes_max	= 2 * 1024 * 1024,
> +	.fifo_size		= 0,
> +};
> +

Fwiw, I usually separate out the DMA from I2S so it can be used by AC97,
PCM interfaces etc. If your hardware only has I2S the it's not required.

> +static unsigned int psc_i2s_fixed_rates[] = {
> +	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
> +};
> +
> +static struct snd_pcm_hw_constraint_list psc_i2s_constraints_rates = {
> +	.count = ARRAY_SIZE(psc_i2s_fixed_rates),
> +	.list = psc_i2s_fixed_rates,
> +	.mask = 0,
> +};
> +
> +static int psc_i2s_pcm_open(struct snd_pcm_substream *substream)
> +{
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
> +	struct psc_i2s_stream *s;
> +	int rc;
> +
> +	dev_dbg(psc_i2s->dev, "psc_i2s_pcm_open(substream=%p)\n", substream);
> +
> +	if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
> +		s = &psc_i2s->capture_stream;
> +	else
> +		s = &psc_i2s->playback_stream;
> +
> +	snd_soc_set_runtime_hwparams(substream, &psc_i2s_pcm_hardware);
> +
> +	rc = snd_pcm_hw_constraint_integer(substream->runtime,
> +					   SNDRV_PCM_HW_PARAM_PERIODS);
> +	if (rc < 0) {
> +		dev_err(psc_i2s->dev, "invalid buffer size\n");
> +		return rc;
> +	}
> +	rc = snd_pcm_hw_constraint_list(substream->runtime, 0,
> +					SNDRV_PCM_HW_PARAM_RATE,
> +					&psc_i2s_constraints_rates);
> +	if (rc < 0) {
> +		dev_err(psc_i2s->dev, "invalid rate\n");
> +		return rc;
> +	}
> +
> +	s->stream = substream;
> +	return 0;
> +}
> +
> +static int psc_i2s_pcm_close(struct snd_pcm_substream * substream)
> +{
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
> +	struct psc_i2s_stream *s;
> +
> +	dev_dbg(psc_i2s->dev, "psc_i2s_pcm_close(substream=%p)\n", substream);
> +
> +	if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
> +		s = &psc_i2s->capture_stream;
> +	else
> +		s = &psc_i2s->playback_stream;
> +
> +	s->stream = NULL;
> +	return 0;
> +}
> +
> +static snd_pcm_uframes_t
> +psc_i2s_pcm_pointer(struct snd_pcm_substream *substream)
> +{
> +	struct snd_soc_pcm_runtime *rtd = substream->private_data;
> +	struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
> +	struct psc_i2s_stream *s;
> +	dma_addr_t count;
> +
> +	if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
> +		s = &psc_i2s->capture_stream;
> +	else
> +		s = &psc_i2s->playback_stream;
> +
> +	/*FIXME: count = s->sdma->bd[s->sdma->outdex].data - s->period_start;*/
> +	count = s->period_current_pt - s->period_start;
> +
> +	return bytes_to_frames(substream->runtime, count);
> +}
> +
> +static struct snd_pcm_ops psc_i2s_pcm_ops = {
> +	.open		= psc_i2s_pcm_open,
> +	.close		= psc_i2s_pcm_close,
> +	.ioctl		= snd_pcm_lib_ioctl,
> +	.pointer	= psc_i2s_pcm_pointer,
> +};
> +
> +static u64 psc_i2s_pcm_dmamask = 0xffffffff;
> +static int psc_i2s_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
> +			   struct snd_pcm *pcm)
> +{
> +	struct snd_soc_pcm_runtime *rtd = pcm->private_data;
> +	size_t size = psc_i2s_pcm_hardware.buffer_bytes_max;
> +	int rc = 0;
> +
> +	dev_dbg(rtd->socdev->dev, "psc_i2s_pcm_new(card=%p, dai=%p, pcm=%p)\n",
> +		card, dai, pcm);
> +
> +	if (!card->dev->dma_mask)
> +		card->dev->dma_mask = &psc_i2s_pcm_dmamask;
> +	if (!card->dev->coherent_dma_mask)
> +		card->dev->coherent_dma_mask = 0xffffffff;
> +
> +	rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size,
> +				 &pcm->streams[0].substream->dma_buffer);
> +	if (rc) {
> +		dev_err(card->dev, "Cannot alloc playback DMA buffer\n");
> +		return -ENOMEM;
> +	}
> +
> +	rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size,
> +				 &pcm->streams[1].substream->dma_buffer);
> +	if (rc) {
> +		snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
> +		dev_err(card->dev, "Can't allocate capture DMA buffer\n");
> +		return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
> +static void psc_i2s_pcm_free(struct snd_pcm *pcm)
> +{
> +	struct snd_soc_pcm_runtime *rtd = pcm->private_data;
> +	struct snd_pcm_substream *substream;
> +	int stream;
> +
> +	dev_dbg(rtd->socdev->dev, "psc_i2s_pcm_free(pcm=%p)\n", pcm);
> +
> +	for (stream = 0; stream < 2; stream++) {
> +		substream = pcm->streams[stream].substream;
> +		if (substream) {
> +			snd_dma_free_pages(&substream->dma_buffer);
> +			substream->dma_buffer.area = NULL;
> +			substream->dma_buffer.addr = 0;
> +		}
> +	}
> +}
> +
> +struct snd_soc_platform psc_i2s_pcm_soc_platform = {
> +	.name		= "mpc5200-psc-audio",
> +	.pcm_ops	= &psc_i2s_pcm_ops,
> +	.pcm_new	= &psc_i2s_pcm_new,
> +	.pcm_free	= &psc_i2s_pcm_free,
> +};
> +
> +/* ---------------------------------------------------------------------
> + * Sysfs attributes for debugging
> + */
> +
> +static ssize_t psc_i2s_status_show(struct device *dev,
> +			   struct device_attribute *attr, char *buf)
> +{
> +	struct psc_i2s *psc_i2s = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "status=%.4x sicr=%.8x rfnum=%i rfstat=0x%.4x tfnum=%i tfstat=0x%.4x\n",
> +			in_be16(&psc_i2s->psc_regs->sr_csr.status),
> +			in_be32(&psc_i2s->psc_regs->sicr),
> +			in_be16(&psc_i2s->fifo_regs->rfnum) & 0x1ff,
> +			in_be16(&psc_i2s->fifo_regs->rfstat),
> +			in_be16(&psc_i2s->fifo_regs->tfnum) & 0x1ff,
> +			in_be16(&psc_i2s->fifo_regs->tfstat));
> +}
> +
> +static int * psc_i2s_get_stat_attr(struct psc_i2s *psc_i2s,
> +				   const char *name)
> +{
> +	if (strcmp(name, "playback_underrun") == 0)
> +		return &psc_i2s->stats.underrun_count;
> +	if (strcmp(name, "capture_overrun") == 0)
> +		return &psc_i2s->stats.overrun_count;
> +
> +	return NULL;
> +}
> +
> +static ssize_t psc_i2s_stat_show(struct device *dev,
> +				 struct device_attribute *attr, char *buf)
> +{
> +	struct psc_i2s *psc_i2s = dev_get_drvdata(dev);
> +	int *attrib;
> +
> +	attrib = psc_i2s_get_stat_attr(psc_i2s, attr->attr.name);
> +	if (!attrib)
> +		return 0;
> +
> +	return sprintf(buf, "%i\n", *attrib);
> +}
> +
> +static ssize_t psc_i2s_stat_store(struct device *dev,
> +				  struct device_attribute *attr,
> +				  const char *buf,
> +				  size_t count)
> +{
> +	struct psc_i2s *psc_i2s = dev_get_drvdata(dev);
> +	int *attrib;
> +
> +	attrib = psc_i2s_get_stat_attr(psc_i2s, attr->attr.name);
> +	if (!attrib)
> +		return 0;
> +
> +	*attrib = simple_strtoul(buf, NULL, 0);
> +	return count;
> +}
> +
> +DEVICE_ATTR(status, 0644, psc_i2s_status_show, NULL);
> +DEVICE_ATTR(playback_underrun, 0644, psc_i2s_stat_show,psc_i2s_stat_store);
> +DEVICE_ATTR(capture_overrun, 0644, psc_i2s_stat_show, psc_i2s_stat_store);
> +
> +/* ---------------------------------------------------------------------
> + * OF platform bus binding code:
> + * - Probe/remove operations
> + * - OF device match table
> + */
> +static int __devinit psc_i2s_of_probe(struct of_device *op,
> +				      const struct of_device_id *match)
> +{
> +	phys_addr_t fifo;
> +	struct psc_i2s *psc_i2s;
> +	struct resource res;
> +	int size, psc_id, irq, rc;
> +	const __be32 *prop;
> +	void __iomem *regs;
> +
> +	dev_dbg(&op->dev, "probing psc i2s device\n");
> +
> +	/* Get the PSC ID */
> +	prop = of_get_property(op->node, "cell-index", &size);
> +	if (!prop || size < sizeof *prop)
> +		return -ENODEV;
> +	psc_id = be32_to_cpu(*prop);
> +
> +	/* Fetch the registers and IRQ of the PSC */
> +	irq = irq_of_parse_and_map(op->node, 0);
> +	if (of_address_to_resource(op->node, 0, &res)) {
> +		dev_err(&op->dev, "Missing reg property\n");
> +		return -ENODEV;
> +	}
> +	regs = ioremap(res.start, 1 + res.end - res.start);
> +	if (!regs) {
> +		dev_err(&op->dev, "Could not map registers\n");
> +		return -ENODEV;
> +	}
> +
> +	/* Allocate and initialize the driver private data */
> +	psc_i2s = kzalloc(sizeof *psc_i2s, GFP_KERNEL);
> +	if (!psc_i2s) {
> +		iounmap(regs);
> +		return -ENOMEM;
> +	}
> +	spin_lock_init(&psc_i2s->lock);
> +	psc_i2s->irq = irq;
> +	psc_i2s->psc_regs = regs;
> +	psc_i2s->fifo_regs = regs + sizeof *psc_i2s->psc_regs;
> +	psc_i2s->dev = &op->dev;
> +	psc_i2s->playback_stream.psc_i2s = psc_i2s;
> +	psc_i2s->capture_stream.psc_i2s = psc_i2s;
> +	snprintf(psc_i2s->name, sizeof psc_i2s->name, "PSC%u", psc_id+1);
> +
> +	/* Fill out the CPU DAI structure */
> +	memcpy(&psc_i2s->dai, &psc_i2s_dai_template, sizeof psc_i2s->dai);
> +	psc_i2s->dai.private_data = psc_i2s;
> +	psc_i2s->dai.name = psc_i2s->name;
> +	psc_i2s->dai.id = psc_id;
> +
> +	/* Find the address of the fifo data registers and setup the
> +	 * DMA tasks */
> +	fifo = res.start + offsetof(struct mpc52xx_psc, buffer.buffer_32);
> +	psc_i2s->capture_stream.bcom_task =
> +		bcom_psc_gen_bd_rx_init(psc_id, 10, fifo, 512);
> +	psc_i2s->playback_stream.bcom_task =
> +		bcom_psc_gen_bd_tx_init(psc_id, 10, fifo);
> +	if (!psc_i2s->capture_stream.bcom_task ||
> +	    !psc_i2s->playback_stream.bcom_task) {
> +		dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
> +		iounmap(regs);
> +		kfree(psc_i2s);
> +		return -ENODEV;
> +	}
> +
> +	/* Save what we've done so it can be found again later */
> +	dev_set_drvdata(&op->dev, psc_i2s);
> +
> +	/* Register the SYSFS files */
> +	rc = device_create_file(psc_i2s->dev, &dev_attr_status);
> +	rc = device_create_file(psc_i2s->dev, &dev_attr_capture_overrun);
> +	rc = device_create_file(psc_i2s->dev, &dev_attr_playback_underrun);
> +	if (rc)
> +		dev_info(psc_i2s->dev, "error creating sysfs files\n");
> +
> +	/* Tell the ASoC OF helpers about it */
> +	of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node,
> +				     &psc_i2s->dai);
> +
> +	return 0;
> +}
> +
> +static int __devexit psc_i2s_of_remove(struct of_device *op)
> +{
> +	struct psc_i2s *psc_i2s = dev_get_drvdata(&op->dev);
> +
> +	dev_dbg(&op->dev, "psc_i2s_remove()\n");
> +
> +	bcom_gen_bd_rx_release(psc_i2s->capture_stream.bcom_task);
> +	bcom_gen_bd_tx_release(psc_i2s->playback_stream.bcom_task);
> +
> +	iounmap(psc_i2s->psc_regs);
> +	iounmap(psc_i2s->fifo_regs);
> +	kfree(psc_i2s);
> +	dev_set_drvdata(&op->dev, NULL);
> +
> +	return 0;
> +}
> +
> +/* Match table for of_platform binding */
> +static struct of_device_id psc_i2s_match[] __devinitdata = {
> +	{ .compatible = "fsl,mpc5200-psc-i2s", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, psc_i2s_match);
> +
> +static struct of_platform_driver psc_i2s_driver = {
> +	.match_table = psc_i2s_match,
> +	.probe = psc_i2s_of_probe,
> +	.remove = __devexit_p(psc_i2s_of_remove),
> +	.driver = {
> +		.name = "mpc5200-psc-i2s",
> +		.owner = THIS_MODULE,
> +	},
> +};
> +
> +/* ---------------------------------------------------------------------
> + * Module setup and teardown; simply register the of_platform driver
> + * for the PSC in I2S mode.
> + */
> +static int __init psc_i2s_init(void)
> +{
> +	return of_register_platform_driver(&psc_i2s_driver);
> +}
> +module_init(psc_i2s_init);
> +
> +static void __exit psc_i2s_exit(void)
> +{
> +	of_unregister_platform_driver(&psc_i2s_driver);
> +}
> +module_exit(psc_i2s_exit);
> +
> +
> 
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel


Privacy & Confidentiality Notice
-------------------------------------------------
This message and any attachments contain privileged and confidential information that is intended solely for the person(s) to whom it is addressed. If you are not an intended recipient you must not: read; copy; distribute; discuss; take any action in or make any reliance upon the contents of this message; nor open or read any attachment. If you have received this message in error, please notify us as soon as possible on the following telephone number and destroy this message including any attachments. Thank you.
-------------------------------------------------
Wolfson Microelectronics plc
Tel: +44 (0)131 272 7000
Fax: +44 (0)131 272 7001
Web: www.wolfsonmicro.com

Registered in Scotland

Company number SC089839

Registered office: 

Westfield House, 26 Westfield Road, Edinburgh, EH11 2QB, UK

^ permalink raw reply

* [PATCH] [POWERPC] 52xx: add missing MSCAN FDT nodes for TQM52xx
From: Wolfgang Grandegger @ 2008-07-02  9:56 UTC (permalink / raw)
  To: Linuxppc-dev

This patch adds the still missing FDT nodes for the MSCAN devices for
the TQM52xx modules.

Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
 arch/powerpc/boot/dts/tqm5200.dts |   16 ++++++++++++++++
 1 file changed, 16 insertions(+)

Index: linux-2.6-galak/arch/powerpc/boot/dts/tqm5200.dts
===================================================================
--- linux-2.6-galak.orig/arch/powerpc/boot/dts/tqm5200.dts
+++ linux-2.6-galak/arch/powerpc/boot/dts/tqm5200.dts
@@ -70,6 +70,22 @@
 			fsl,has-wdt;
 		};
 
+		can@900 {
+			compatible = "fsl,mpc5200-mscan";
+			cell-index = <0>;
+			interrupts = <2 17 0>;
+			interrupt-parent = <&mpc5200_pic>;
+			reg = <0x900 0x80>;
+		};
+
+		can@980 {
+			compatible = "fsl,mpc5200-mscan";
+			cell-index = <1>;
+			interrupts = <2 18 0>;
+			interrupt-parent = <&mpc5200_pic>;
+			reg = <0x980 0x80>;
+		};
+
 		gpio@b00 {
 			compatible = "fsl,mpc5200-gpio";
 			reg = <0xb00 0x40>;

^ permalink raw reply

* Re: [alsa-devel] [PATCH 1/3] ALSA SoC: Add OpenFirmware helper for matching bus and codec drivers
From: Takashi Iwai @ 2008-07-02  9:50 UTC (permalink / raw)
  To: Grant Likely; +Cc: liam.girdwood, alsa-devel, broonie, timur, linuxppc-dev
In-Reply-To: <20080701235330.16923.67218.stgit@trillian.secretlab.ca>

At Tue, 01 Jul 2008 17:53:30 -0600,
Grant Likely wrote:
> diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
> index 18f28ac..c5736e5 100644
> --- a/sound/soc/Kconfig
> +++ b/sound/soc/Kconfig
> @@ -23,6 +23,12 @@ config SND_SOC
>  	  This ASoC audio support can also be built as a module.  If so, the module
>  	  will be called snd-soc-core.
>  
> +config SND_SOC_OF
> +	tristate "OF helpers for SoC audio support"
> +	depends on SND_SOC
> +	---help---
> +	  Add support for OpenFirmware device tree descriptions of sound device
> +

This is a helper module and not necessarily manually selectable.
Better to make the other driver selecting this.


> diff --git a/sound/soc/soc-of.c b/sound/soc/soc-of.c
> new file mode 100644
> index 0000000..9694979
> --- /dev/null
> +++ b/sound/soc/soc-of.c
(snip)
> +DEFINE_MUTEX(of_snd_soc_mutex);
> +LIST_HEAD(of_snd_soc_device_list);

Missing static.


Takashi

^ permalink raw reply

* Re: [PATCH] powerpc/mpc5200: Fix lite5200b suspend/resume
From: Tim Yamin @ 2008-07-02  9:38 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <20080701211033.13852.31692.stgit@trillian.secretlab.ca>

Hi Grant,

This patch works fine for me.

Cheers,

Tim

On Tue, Jul 1, 2008 at 10:12 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> From: Tim Yamin <plasm@roo.me.uk>
>
> Suspend/resume ("echo mem > /sys/power/state") does not work with
> vanilla kernels -- the system does not suspend correctly and just
> hangs. This patch fixes this so suspend/resume works:
>
> 1) of_iomap does not map the whole 0xC000 of the MPC5200 immr so
> saving registers does not work.
> 2) PCI registers need to be saved and restored.
>
> Signed-off-by: Tim Yamin <plasm@roo.me.uk>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
>
> Tim, please test this version.  I fixed a couple of bugs and want to make
> sure I haven't broken anything.  Once you ack it I'll ask Paul to pull it
> into 2.6.26.
>
> g.
>
>  arch/powerpc/platforms/52xx/lite5200_pm.c |   14 +++++++++++++-
>  1 files changed, 13 insertions(+), 1 deletions(-)
>
> diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c
> index 41c7fd9..fe92e65 100644
> --- a/arch/powerpc/platforms/52xx/lite5200_pm.c
> +++ b/arch/powerpc/platforms/52xx/lite5200_pm.c
> @@ -14,6 +14,7 @@ static struct mpc52xx_sdma __iomem *bes;
>  static struct mpc52xx_xlb __iomem *xlb;
>  static struct mpc52xx_gpio __iomem *gps;
>  static struct mpc52xx_gpio_wkup __iomem *gpw;
> +static void __iomem *pci;
>  static void __iomem *sram;
>  static const int sram_size = 0x4000;   /* 16 kBytes */
>  static void __iomem *mbar;
> @@ -50,6 +51,8 @@ static int lite5200_pm_prepare(void)
>                { .type = "builtin", .compatible = "mpc5200", }, /* efika */
>                {}
>        };
> +       u64 regaddr64 = 0;
> +       const u32 *regaddr_p;
>
>        /* deep sleep? let mpc52xx code handle that */
>        if (lite5200_pm_target_state == PM_SUSPEND_STANDBY)
> @@ -60,8 +63,12 @@ static int lite5200_pm_prepare(void)
>
>        /* map registers */
>        np = of_find_matching_node(NULL, immr_ids);
> -       mbar = of_iomap(np, 0);
> +       regaddr_p = of_get_address(np, 0, NULL, NULL);
> +       if (regaddr_p)
> +               regaddr64 = of_translate_address(np, regaddr_p);
>        of_node_put(np);
> +
> +       mbar = ioremap((u32) regaddr64, 0xC000);
>        if (!mbar) {
>                printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
>                return -ENOSYS;
> @@ -71,6 +78,7 @@ static int lite5200_pm_prepare(void)
>        pic = mbar + 0x500;
>        gps = mbar + 0xb00;
>        gpw = mbar + 0xc00;
> +       pci = mbar + 0xd00;
>        bes = mbar + 0x1200;
>        xlb = mbar + 0x1f00;
>        sram = mbar + 0x8000;
> @@ -85,6 +93,7 @@ static struct mpc52xx_sdma sbes;
>  static struct mpc52xx_xlb sxlb;
>  static struct mpc52xx_gpio sgps;
>  static struct mpc52xx_gpio_wkup sgpw;
> +static char spci[0x200];
>
>  static void lite5200_save_regs(void)
>  {
> @@ -94,6 +103,7 @@ static void lite5200_save_regs(void)
>        _memcpy_fromio(&sxlb, xlb, sizeof(*xlb));
>        _memcpy_fromio(&sgps, gps, sizeof(*gps));
>        _memcpy_fromio(&sgpw, gpw, sizeof(*gpw));
> +       _memcpy_fromio(spci, pci, 0x200);
>
>        _memcpy_fromio(saved_sram, sram, sram_size);
>  }
> @@ -103,6 +113,8 @@ static void lite5200_restore_regs(void)
>        int i;
>        _memcpy_toio(sram, saved_sram, sram_size);
>
> +       /* PCI Configuration */
> +       _memcpy_toio(pci, spci, 0x200);
>
>        /*
>         * GPIOs. Interrupt Master Enable has higher address then other

^ permalink raw reply

* Re: [PATCH v2 1/2] powerpc: Fix building of feature-fixup tests on ppc32
From: Michael Ellerman @ 2008-07-02  9:35 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0807011015390.20129@blarg.am.freescale.net>

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

On Tue, 2008-07-01 at 10:16 -0500, Kumar Gala wrote:
> We need to use PPC_LCMPI otherwise we get compile errors like:
> 
> arch/powerpc/lib/feature-fixups-test.S: Assembler messages:
> arch/powerpc/lib/feature-fixups-test.S:142: Error: Unrecognized opcode: `cmpdi'
> arch/powerpc/lib/feature-fixups-test.S:149: Error: Unrecognized opcode: `cmpdi'
> arch/powerpc/lib/feature-fixups-test.S:164: Error: Unrecognized opcode: `cmpdi'

Sorry, I definitely built (and booted) a 32-bit config, so I'm not sure
how I missed that. What toolchain are you using?

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH] powerpc: fixup lwsync at runtime
From: Michael Ellerman @ 2008-07-02  9:34 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <DBD7C7F7-1EBB-4D73-88A0-72D079E800DB@kernel.crashing.org>

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

On Tue, 2008-07-01 at 09:48 -0500, Kumar Gala wrote:
> On Jul 1, 2008, at 1:29 AM, Michael Ellerman wrote:

> >> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/ 
> >> setup_32.c
> >> index 9e83add..0109e7f 100644
> >> --- a/arch/powerpc/kernel/setup_32.c
> >> +++ b/arch/powerpc/kernel/setup_32.c
> >> @@ -101,6 +101,10 @@ unsigned long __init early_init(unsigned long  
> >> dt_ptr)
> >> 			  PTRRELOC(&__start___ftr_fixup),
> >> 			  PTRRELOC(&__stop___ftr_fixup));
> >>
> >> +	do_lwsync_fixups(spec->cpu_features,
> >> +			 PTRRELOC(&__start___lwsync_fixup),
> >> +			 PTRRELOC(&__stop___lwsync_fixup));
> >> +
> >
> > This could be changed to use cur_cpu_spec->cpu_features, and then all
> > the call sites would be passing that, which would mean
> > do_lwsync_fixups() could just check cur_cpu_spec->cpu_features  
> > directly.
> 
> cur_cpu_spec and spec at this point arent the same thing.

Aren't they? I must be missing something:

struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
{
        struct cpu_spec *s = cpu_specs;
        struct cpu_spec *t = &the_cpu_spec;
        int i;

        for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
                if ((pvr & s->pvr_mask) == s->pvr_value) {
			...
                        *t = *s;
                        *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
			...
                        return s;

then:

unsigned long __init early_init(unsigned long dt_ptr)
{
	...
	spec = identify_cpu(offset, mfspr(SPRN_PVR));

        do_feature_fixups(spec->cpu_features,
                          PTRRELOC(&__start___ftr_fixup),
                          PTRRELOC(&__stop___ftr_fixup));
}


cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: patches for 2.6.27... (Kumar Gala)
From: Heiko Schocher @ 2008-07-02  9:58 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <mailman.486.1214989131.2883.linuxppc-dev@ozlabs.org>

Hello Kumar,

On Wednesday 02 July 2008, Kumar Gala wrote:
> Please point out any patches that have been posted but havent made it
> into a git tree related to Freescale chips.

Here are 2 patches that I'd like to see in 2.6.27. They haven't made into
any git tree as far as I know.

http://ozlabs.org/pipermail/linuxppc-dev/2008-June/058118.html

http://ozlabs.org/pipermail/linuxppc-dev/2008-June/057972.html

thanks.
bye
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply

* [PATCHv2] cpm_uart: Support uart_wait_until_sent()
From: Laurent Pinchart @ 2008-07-02  8:58 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, linux-serial
In-Reply-To: <4768A00D-3C8B-4AF2-A2E1-DE9C9BD055E4@kernel.crashing.org>

Set port->fifosize to the software FIFO size, and update the port timeout
when the baud rate is modified. SCC ports have an optional 32 byte hardware
FIFO which is currently not taken into account, as there is no documented way
to check when the FIFO becomes empty.

Signed-off-by: Laurent Pinchart <laurentp@cse-semaphore.com>
---
 drivers/serial/cpm_uart/cpm_uart_core.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index a19dc7e..151cad2 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -608,6 +608,11 @@ static void cpm_uart_set_termios(struct uart_port *port,
 	}
 
 	/*
+	 * Update the timeout
+	 */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	/*
 	 * Set up parity check flag
 	 */
 #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
@@ -1068,6 +1073,7 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
 	pinfo->port.type = PORT_CPM;
 	pinfo->port.ops = &cpm_uart_pops,
 	pinfo->port.iotype = UPIO_MEM;
+	pinfo->port.fifosize = pinfo->tx_nrfifos * pinfo->tx_fifosize;
 	spin_lock_init(&pinfo->port.lock);
 
 	pinfo->port.irq = of_irq_to_resource(np, 0, NULL);
-- 
1.5.0

-- 
Laurent Pinchart
CSE Semaphore Belgium

Chaussee de Bruxelles, 732A
B-1410 Waterloo
Belgium

T +32 (2) 387 42 59
F +32 (2) 387 42 75

^ permalink raw reply related

* Re: Linux on Virtex board with ARCH=powerpc
From: Peter Mendham @ 2008-07-02  8:49 UTC (permalink / raw)
  To: Peter Korsgaard; +Cc: John Linn, linuxppc-embedded
In-Reply-To: <874p7eeodw.fsf@macbook.be.48ers.dk>

Hi,

Peter Korsgaard wrote:
> Hi,
>
>  Peter> I now have a new and rather bizarre problem, which maybe you
>  Peter> or someone else has met before.  I have a simple FPGA design
>  Peter> with memory, a sysace and a uart16550 on an ML405 (I've put my
>  Peter> hardware to one side for the moment).  It works just fine.  If
>  Peter> I swap the uart16550 for a uartlite (remaking the kernel with
>  Peter> the correct device tree) I see all the boot messages and the
>  Peter> kernel seems to start OK, the root partition is mounted but
>  Peter> then I see nothing from /sbin/init.  This is the same root fs
>  Peter> that I was using with the uart16550 example I just mentioned.
>
> Did you remember to change your inittab to use /dev/ttyUL0?
>   
Yes, I'm using a buildroot/busybox system and have changed inittab and 
securetty for ttyUL0.  From what I understand, initialisation lines in a 
busybox inittab that do not specify a tty at the beginning go out on 
/dev/console.  To collaborate this, if I set my hardware up for a 
uart16550 and leave the inittab specifying ttyUL0, I see the messages 
from the init scripts (which must be going to console) but then I 
messages (again on console I guess) saying that ttyUL0 doesn't exist.  
When I try things the other way round, I don't see anything at all (none 
of the stuff that I think is going to console) and it doesn't moan at 
me.  Which I guess means something is wrong with /dev/console?

-- Peter

The University of Dundee is a Scottish Registered Charity, No. SC015096.

^ permalink raw reply

* Re: Commits added to powerpc.git master and powerpc-next branches
From: Laurent Pinchart @ 2008-07-02  8:41 UTC (permalink / raw)
  To: Kumar Gala, Jeff Garzik; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <58163CFC-A697-4FF7-ADC5-A1B9C976965E@kernel.crashing.org>

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

On Wednesday 02 July 2008, Kumar Gala wrote:
> 
> On Jul 1, 2008, at 3:49 AM, Laurent Pinchart wrote:
> 
> > Hi Paul,
> >
> > On Tuesday 01 July 2008, Paul Mackerras wrote:
> >> The following commits have been added to the master and powerpc-next
> >> branches of the powerpc.git repository.  This includes patches pulled
> >> from Kumar's and Josh's trees.
> >
> > Any change of getting the following patches into 2.6.27 ? They have  
> > either been acked and not picked, or just ignored so far :-/
> >
> > [PATCHv2] fs_enet: restore promiscuous and multicast settings in  
> > restart()
> > 	http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=19228
> 
> Should go via netdev unless jgarizk says otherwise

On 2008-06-18, Jeff wrote:

"My general rule is, anytime I see 80%+ of the patch dealing with 
arch-specific API functions (such as OF resource stuff), I tend to 
prefer that goes via an arch tree.

If it's a networking change, of course I'd prefer it came in my direction."

Jeff, could you please tell us if you want to pick this one or if it should go through the powerpc tree ? The patch has been posted to both the linuxppc-dev and netdev lists, and I haven't received any comment from the netdev folks.

> > [PATCH 2/2] fs_enet: MDIO on GPIO support
> > 	http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=18693
> 
> ditto

Jeff, same question :-)

> > [PATCHv3 1/2] [POWERPC] CPM2: Implement GPIO LIB API on CPM2  
> > Freescale SoC.
> > 	http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=19045
> 
> I'll look at this one

Thanks.

> > [PATCH] powerpc: Modem control lines support for the cpm_uart driver
> > 	http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=17928
> 
> this seems to depend on the previous patch.

It doesn't strictly depend on the previous one. You will need GPIO LIB API on CPM2 to use the modem control lines, but the cpm_uart driver will fall back to the current behaviour if no GPIO LIB support is present.

> > [PATCH] cpm_uart: Support uart_wait_until_sent()
> > 	http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=19233
> 
> 
> applied

-- 
Laurent Pinchart
CSE Semaphore Belgium

Chaussee de Bruxelles, 732A
B-1410 Waterloo
Belgium

T +32 (2) 387 42 59
F +32 (2) 387 42 75

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: patches for 2.6.27...
From: Laurent Pinchart @ 2008-07-02  8:36 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <068935A1-11BE-4AEB-9C0E-E1AB53F1618E@kernel.crashing.org>

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

Hi Kumar,

On Wednesday 02 July 2008, Kumar Gala wrote:
> Please point out any patches that have been posted but havent made it  
> into a git tree related to Freescale chips.
> 
> I know there are probably a slew of CPM patches that need to get into  
> the tree.

Here are 5 patches that I'd like to see in 2.6.27. They haven't made into any git tree as far as I know.

[PATCHv2] fs_enet: restore promiscuous and multicast settings in restart()
        http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=19228
[PATCH 2/2] fs_enet: MDIO on GPIO support
        http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=18693
[PATCHv3 1/2] [POWERPC] CPM2: Implement GPIO LIB API on CPM2 Freescale SoC.
        http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=19045
[PATCH] powerpc: Modem control lines support for the cpm_uart driver
        http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=17928
[PATCH] cpm_uart: Support uart_wait_until_sent()
        http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=19233

-- 
Laurent Pinchart
CSE Semaphore Belgium

Chaussee de Bruxelles, 732A
B-1410 Waterloo
Belgium

T +32 (2) 387 42 59
F +32 (2) 387 42 75

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH v3] [NAND] driver extension to support NAND on TQM85xx modules
From: Wolfgang Grandegger @ 2008-07-02  8:18 UTC (permalink / raw)
  To: Linuxppc-dev; +Cc: David Woodhouse, linux-mtd
In-Reply-To: <484CE77C.70506@grandegger.com>

Hello,

I would like to ask for the status of the patch below and the related 
ones. Any chance to get them in for 2.6.27.

TIA,

Wolfgang.

Wolfgang Grandegger wrote:
> This patch extends the FSL UPM NAND driver from Anton Vorontsov to
> support hardware which does not have the R/B pin of the NAND chip
> connected, like the TQM8548 module:
> 
> - The OF_GPIO dependency has been removed from the Kconfig option
>   because GPIO is not needed. The relevant gpio_* function are then
>   stubbed out in <linux/gpio.h>.
>  
> - It re-introduces the chip-delay property to define an appropriate
>   maximum delay time (tR) required for read operations. The binding
>   will be documented in a separate patch.
> 
> Note: this patch is based on a patch from Anton Vorontsov aöready
>       posted to this list:
> 
>       http://ozlabs.org/pipermail/linuxppc-dev/2008-April/055587.html.
>       http://ozlabs.org/pipermail/linuxppc-dev/2008-May/057158.html
> 
> Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
> ---
>  drivers/mtd/nand/Kconfig   |    2 +-
>  drivers/mtd/nand/fsl_upm.c |   17 +++++++++++++----
>  2 files changed, 14 insertions(+), 5 deletions(-)
> 
> Index: linux-2.6-galak/drivers/mtd/nand/Kconfig
> ===================================================================
> --- linux-2.6-galak.orig/drivers/mtd/nand/Kconfig
> +++ linux-2.6-galak/drivers/mtd/nand/Kconfig
> @@ -380,7 +380,7 @@ config MTD_NAND_FSL_ELBC
>  
>  config MTD_NAND_FSL_UPM
>  	tristate "Support for NAND on Freescale UPM"
> -	depends on MTD_NAND && OF_GPIO && (PPC_83xx || PPC_85xx)
> +	depends on MTD_NAND && (PPC_83xx || PPC_85xx)
>  	select FSL_LBC
>  	help
>  	  Enables support for NAND Flash chips wired onto Freescale PowerPC
> Index: linux-2.6-galak/drivers/mtd/nand/fsl_upm.c
> ===================================================================
> --- linux-2.6-galak.orig/drivers/mtd/nand/fsl_upm.c
> +++ linux-2.6-galak/drivers/mtd/nand/fsl_upm.c
> @@ -13,6 +13,7 @@
>  
>  #include <linux/kernel.h>
>  #include <linux/module.h>
> +#include <linux/delay.h>
>  #include <linux/mtd/nand.h>
>  #include <linux/mtd/nand_ecc.h>
>  #include <linux/mtd/partitions.h>
> @@ -36,6 +37,7 @@ struct fsl_upm_nand {
>  	uint8_t upm_cmd_offset;
>  	void __iomem *io_base;
>  	int rnb_gpio;
> +	int chip_delay;
>  };
>  
>  #define to_fsl_upm_nand(mtd) container_of(mtd, struct fsl_upm_nand, mtd)
> @@ -58,10 +60,11 @@ static void fun_wait_rnb(struct fsl_upm_
>  	if (fun->rnb_gpio >= 0) {
>  		while (--cnt && !fun_chip_ready(&fun->mtd))
>  			cpu_relax();
> +		if (!cnt)
> +			dev_err(fun->dev, "tired waiting for RNB\n");
> +	} else {
> +		ndelay(100);
>  	}
> -
> -	if (!cnt)
> -		dev_err(fun->dev, "tired waiting for RNB\n");
>  }
>  
>  static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
> @@ -129,7 +132,7 @@ static int __devinit fun_chip_init(struc
>  	fun->chip.IO_ADDR_R = fun->io_base;
>  	fun->chip.IO_ADDR_W = fun->io_base;
>  	fun->chip.cmd_ctrl = fun_cmd_ctrl;
> -	fun->chip.chip_delay = 50;
> +	fun->chip.chip_delay = fun->chip_delay;
>  	fun->chip.read_byte = fun_read_byte;
>  	fun->chip.read_buf = fun_read_buf;
>  	fun->chip.write_buf = fun_write_buf;
> @@ -233,6 +236,12 @@ static int __devinit fun_probe(struct of
>  		goto err2;
>  	}
>  
> +	prop = of_get_property(ofdev->node, "chip-delay", NULL);
> +	if (prop)
> +		fun->chip_delay = *prop;
> +	else
> +		fun->chip_delay = 50;
> +
>  	fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start,
>  					  io_res.end - io_res.start + 1);
>  	if (!fun->io_base) {
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 
> 

^ permalink raw reply

* patches for 2.6.27...
From: Kumar Gala @ 2008-07-02  7:56 UTC (permalink / raw)
  To: linuxppc-dev@ozlabs.org list

Please point out any patches that have been posted but havent made it  
into a git tree related to Freescale chips.

I know there are probably a slew of CPM patches that need to get into  
the tree.

- k

^ permalink raw reply

* Re: [PATCH 06/12] net: use linux/of_{device, platform}.h instead of asm
From: Kumar Gala @ 2008-07-02  7:55 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: ppc-dev, Jeff Garzik, netdev
In-Reply-To: <4864737D.80306@garzik.org>


On Jun 26, 2008, at 11:58 PM, Jeff Garzik wrote:

> Stephen Rothwell wrote:
>> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
>> ---
>> drivers/net/fs_enet/fs_enet-main.c |    2 +-
>> drivers/net/fs_enet/mac-scc.c      |    2 +-
>> drivers/net/fs_enet/mii-fec.c      |    2 +-
>> drivers/net/ibm_newemac/core.h     |    2 +-
>> drivers/net/ucc_geth.c             |    2 +-
>> drivers/net/ucc_geth_mii.c         |    2 +-
>> 6 files changed, 6 insertions(+), 6 deletions(-)
>
> ACK
>
> I'll let a ppc person queue this


I'll pick it up (since it mainly touches fsl enet controllers) if you  
can repost it.  I seem to have lost the patch.

- k

^ permalink raw reply

* Re: [BUG] 2.6.26-rc8-git2 - kernel BUG at mm/page_alloc.c:585
From: Andrew Morton @ 2008-07-02  7:50 UTC (permalink / raw)
  To: Kamalesh Babulal
  Cc: linuxppc-dev, kernel list, linux-mm, kernel-testers, Balbir Singh
In-Reply-To: <486B1F60.1030608@linux.vnet.ibm.com>

On Wed, 02 Jul 2008 11:55:36 +0530 Kamalesh Babulal <kamalesh@linux.vnet.ibm.com> wrote:

> Hi,
> 
> when running kernbench on powerpc box booted with the 2.6.26-rc8-git2
> kernel the machine drops to xmon with the kernel BUG
> 
> kernel BUG at mm/page_alloc.c:585!

static int bad_range(struct zone *zone, struct page *page)
{
	if (page_outside_zone_boundaries(zone, page))
		return 1;
	if (!page_is_consistent(zone, page))
		return 1;

	return 0;
}

Called from

static inline void expand(struct zone *zone, struct page *page,
	int low, int high, struct free_area *area,
	int migratetype)
{
	unsigned long size = 1 << high;

	while (high > low) {
		area--;
		high--;
		size >>= 1;
		VM_BUG_ON(bad_range(zone, &page[size]));
		list_add(&page[size].lru, &area->free_list[migratetype]);
		area->nr_free++;
		set_page_order(&page[size], high);
	}
}

We goofed - we now don't know whether page_outside_zone_boundaries()
evaluated true, or if !page_is_consistent() evaluated true.  Bad us.

I'd suspect that something went wrong in powerpc land.

> cpu 0x0: Vector: 700 (Program Check) at [c0000000c389ed50]
>     pc: c0000000000e22ec: .__rmqueue+0x178/0x25c
>     lr: c0000000000e22ec: .__rmqueue+0x178/0x25c
>     sp: c0000000c389efd0
>    msr: 8000000000029032
>   current = 0xc0000000f6e0e790
>   paca    = 0xc000000000873480
>     pid   = 3421, comm = tar
> kernel BUG at mm/page_alloc.c:585!
> enter ? for help
> [c0000000c389efd0] c0000000000e22d0 .__rmqueue+0x15c/0x25c (unreliable)
> [c0000000c389f0a0] c0000000000e2438 .rmqueue_bulk+0x68/0xf0
> [c0000000c389f170] c0000000000e43cc .get_page_from_freelist+0x2d0/0x848
> [c0000000c389f2b0] c0000000000e4abc .__alloc_pages_internal+0x12c/0x494
> [c0000000c389f3c0] c0000000000e4e6c .__alloc_pages+0x1c/0x30
> [c0000000c389f440] c0000000001107d8 .kmem_getpages+0x90/0x198
> [c0000000c389f4e0] c000000000111200 .fallback_alloc+0x190/0x26c
> [c0000000c389f5b0] c000000000111478 .____cache_alloc_node+0x19c/0x1d0
> [c0000000c389f660] c000000000111e90 .kmem_cache_alloc+0x150/0x1f8
> [c0000000c389f710] d00000000019fb50 .ext3_alloc_inode+0x2c/0x74 [ext3]
> [c0000000c389f790] c00000000013725c .alloc_inode+0x58/0x278
> [c0000000c389f830] c0000000001374b4 .new_inode+0x38/0xd4
> [c0000000c389f8d0] d000000000193930 .ext3_new_inode+0x90/0xc64 [ext3]
> [c0000000c389f9f0] d00000000019dc28 .ext3_create+0xc4/0x16c [ext3]
> [c0000000c389fab0] c000000000127944 .vfs_create+0x12c/0x1d4
> [c0000000c389fb60] c00000000012b54c .do_filp_open+0x210/0x8b4
> [c0000000c389fd00] c0000000001191f8 .do_sys_open+0x80/0x144
> [c0000000c389fdb0] c00000000015f5d8 .compat_sys_open+0x2c/0x44
> [c0000000c389fe30] c0000000000086dc syscall_exit+0x0/0x40
> --- Exception: c00 (System Call) at 000000000ff0e6d4
> SP (ffd3f5a0) is in userspace
> 0:mon> r
> R00 = 00000000f0008d00   R16 = 0000000000000001
> R01 = c0000000c389efd0   R17 = 0000000000000044
> R02 = c0000000007e74e0   R18 = 0000000000000001
> R03 = 0000000000000001   R19 = c00000010ffff828
> R04 = f000000000069000   R20 = c00000010ffff800
> R05 = 0000000000000003   R21 = c0000001ffff5700
> R06 = 0000000000000008   R22 = 0000000000000000
> R07 = 0000000000000000   R23 = 0000000000000001
> R08 = 0000000000001180   R24 = 0000000000000007
> R09 = 00000000f0008cff   R25 = 0000000000000007
> R10 = c0000001ffff5700   R26 = 0000000000000080
> R11 = c000000000885df8   R27 = c0000001ffff5e28
> R12 = c000000010010080   R28 = f000000000066000
> R13 = c000000000873480   R29 = f000000000069000
> R14 = 0000000000000001   R30 = c000000000791ce0
> R15 = 0000000000000001   R31 = c0000000c389efd0
> pc  = c0000000000e22ec .__rmqueue+0x178/0x25c
> lr  = c0000000000e22ec .__rmqueue+0x178/0x25c
> msr = 8000000000029032   cr  = 24000442
> ctr = 0000000000000003   xer = 0000000020000000   trap =  700
> 0:mon> u
> SLB contents of cpu 0
> 00 c000000008000000 40004f7ca3000510  1T  ESID=   c00000  VSID=       4f7ca3 LLP:110 
> 01 d000000008000000 4000eb71b0000510  1T  ESID=   d00000  VSID=       eb71b0 LLP:110 
> 11 0000000008000000 000020b2b24a4d90 256M ESID=        0  VSID=    20b2b24a4 LLP:110 
> 12 00000000f8000000 00002bea2a039d90 256M ESID=        f  VSID=    2bea2a039 LLP:110 
> 13 0000000048000000 000023b06bd10d90 256M ESID=        4  VSID=    23b06bd10 LLP:110 
> 14 0000000018000000 0000217220abfd90 256M ESID=        1  VSID=    217220abf LLP:110 
> 38 f000000008000000 4000235bcc000500  1T  ESID=   f00000  VSID=       235bcc LLP:100 

^ permalink raw reply

* Re: [PATCH] cpm_uart: Support uart_wait_until_sent()
From: Kumar Gala @ 2008-07-02  7:46 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linuxppc-dev, linux-serial
In-Reply-To: <200806261355.09334.laurentp@cse-semaphore.com>


On Jun 26, 2008, at 6:55 AM, Laurent Pinchart wrote:

> Set port->fifosize to the software FIFO size, and update the port  
> timeout
> when the baud rate is modified. SCC ports have an optional 32 byte  
> hardware
> FIFO which is currently not taken into account, as there is no  
> documented way
> to check when the FIFO becomes empty.
>
> Signed-off-by: Laurent Pinchart <laurentp@cse-semaphore.com>
> ---
> drivers/serial/cpm_uart/cpm_uart_core.c |    6 ++++++
> 1 files changed, 6 insertions(+), 0 deletions(-)

I spoke to soon about being able to apply this.  Can you respin this  
against my powerpc-next tree.  Also, I had troubles applying this due  
to mailer formatting issues.

- k

> diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/ 
> serial/cpm_uart/cpm_uart_core.c
> index a19dc7e..151cad2 100644
> --- a/drivers/serial/cpm_uart/cpm_uart_core.c
> +++ b/drivers/serial/cpm_uart/cpm_uart_core.c
> @@ -547,6 +547,11 @@ static void cpm_uart_set_termios(struct  
> uart_port *port,
> 	}
>
> 	/*
> +	 * Update the timeout
> +	 */
> +	uart_update_timeout(port, termios->c_cflag, baud);
> +
> +	/*
> 	 * Set up parity check flag
> 	 */
> #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK| 
> INPCK))
> @@ -1154,6 +1159,7 @@ int cpm_uart_drv_get_platform_data(struct  
> platform_device *pdev, int is_con)
> 	pinfo->port.uartclk = pdata->uart_clk;
> 	pinfo->port.mapbase = (unsigned long)mem;
> 	pinfo->port.irq = platform_get_irq(pdev, 0);
> +	pinfo->port.fifosize = pinfo->tx_nrfifos * pinfo->tx_fifosize;
>
> 	return 0;
> }
> -- 
> 1.5.0
>
> -- 
> Laurent Pinchart
> CSE Semaphore Belgium
>
> Chaussee de Bruxelles, 732A
> B-1410 Waterloo
> Belgium
>
> T +32 (2) 387 42 59
> F +32 (2) 387 42 75

^ permalink raw reply

* Re: Commits added to powerpc.git master and powerpc-next branches
From: Kumar Gala @ 2008-07-02  7:42 UTC (permalink / raw)
  To: Jochen Friedrich; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <486A533B.40402@scram.de>


On Jul 1, 2008, at 10:54 AM, Jochen Friedrich wrote:

> Hi Paul,
>
> On Tuesday 01 July 2008, Paul Mackerras wrote:
>
>> The following commits have been added to the master and powerpc-next
>> branches of the powerpc.git repository.  This includes patches pulled
>> from Kumar's and Josh's trees.
>
> Now that the I2C driver for CPM1/CPM2 boards is in the i2c tree, is  
> there
> any chance to get this one into 2.6.27?
>
> [POWERPC] Add i2c pins to dts and board setup
>  http://patchwork.ozlabs.org/linuxppc/patch?person=1023&id=18603

Will we always want defconfig updates to enable the driver?

- k

^ permalink raw reply

* Re: Commits added to powerpc.git master and powerpc-next branches
From: Kumar Gala @ 2008-07-02  7:41 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <200807011049.32699.laurentp@cse-semaphore.com>


On Jul 1, 2008, at 3:49 AM, Laurent Pinchart wrote:

> Hi Paul,
>
> On Tuesday 01 July 2008, Paul Mackerras wrote:
>> The following commits have been added to the master and powerpc-next
>> branches of the powerpc.git repository.  This includes patches pulled
>> from Kumar's and Josh's trees.
>
> Any change of getting the following patches into 2.6.27 ? They have  
> either been acked and not picked, or just ignored so far :-/
>
> [PATCHv2] fs_enet: restore promiscuous and multicast settings in  
> restart()
> 	http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=19228

Should go via netdev unless jgarizk says otherwise

> [PATCH 2/2] fs_enet: MDIO on GPIO support
> 	http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=18693

ditto

> [PATCHv3 1/2] [POWERPC] CPM2: Implement GPIO LIB API on CPM2  
> Freescale SoC.
> 	http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=19045

I'll look at this one

> [PATCH] powerpc: Modem control lines support for the cpm_uart driver
> 	http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=17928

this seems to depend on the previous patch.

> [PATCH] cpm_uart: Support uart_wait_until_sent()
> 	http://patchwork.ozlabs.org/linuxppc/patch?person=968&id=19233


applied

- k

^ permalink raw reply

* Re: [PATCH] powerpc/86xx: mpc8610_hpcd: fix interrupt trigger type for ULi IDE
From: Kumar Gala @ 2008-07-02  7:37 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linuxppc-dev, Timur Tabi
In-Reply-To: <20080701130438.GA25531@polina.dev.rtsoft.ru>


On Jul 1, 2008, at 8:04 AM, Anton Vorontsov wrote:

> i8259 PIC is disabled on MPC8610HPCD, and ULi IDE is configured to use
> PCI sideband interrupt that is specified in the device tree.
>
> Current HPCD's device tree specify that IDE interrupt is low to high
> sensitive, but in practice ULi IDE throws active-high interrupts (not
> active-low as all normal PCI devices).
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
>
> This is for -next, since the bug could be triggered only on RT kernels
> with hardirq preemption.

applied.

- k

^ permalink raw reply

* Re: [PATCH] [POWERPC] 85xx: TQM8548: add missing support for RTC and LM75
From: Kumar Gala @ 2008-07-02  7:37 UTC (permalink / raw)
  To: Wolfgang Grandegger; +Cc: Linuxppc-dev
In-Reply-To: <4863967F.8060806@grandegger.com>


On Jun 26, 2008, at 8:15 AM, Wolfgang Grandegger wrote:

> It adds the missing RTC node to tqm8548.dts and enables support for
> I2C, DS1307 and LM75 in the default configuration.
>
> Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
> ---
> arch/powerpc/boot/dts/tqm8548.dts           |    5
> arch/powerpc/configs/85xx/tqm8548_defconfig |  143 ++++++++++++++++++ 
> ++++++++--
> 2 files changed, 142 insertions(+), 6 deletions(-)

applied.

- k

^ permalink raw reply

* Re: [PATCH] POWERPC CPM: Minor cosmetic changes to udbg_putc
From: Kumar Gala @ 2008-07-02  7:37 UTC (permalink / raw)
  To: Nye Liu; +Cc: scottwood, linuxppc-dev, linux-kernel
In-Reply-To: <20080627200100.GA16661@mrv.com>


On Jun 27, 2008, at 3:01 PM, Nye Liu wrote:

> From: Nye Liu <nyet@mrv.com>
>
> udbg_putc is a *function pointer* that is initialized during
> udbg_init_cpm. It might not be initialized properly when called from
> udbg_putc_cpm(), so (recursively) call udbg_putc_cpm() directly.
>
> Printing an "X" on initialization is ugly. How about a "\n" instead?
>
> Signed-off-by: Nye Liu <nyet@mrv.com>
>
> ---

Applied.  I removed the "\n" per Scott's feedback.

- k

^ permalink raw reply

* [PATCH v2] powerpc/85xx: Add support for MPC8536DS
From: Kumar Gala @ 2008-07-02  7:19 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: linuxppc-dev
In-Reply-To: <20080702170814.de282293.sfr@canb.auug.org.au>

Add support for the MPC8536 process and MPC8536DS reference board.  The
MPC8536 is an e500v2 based SoC which eTSEC, USB, SATA, PCI, and PCIe.

The USB and SATA IP blocks are similiar to those on the PQ2 Pro SoCs and
thus use the same drivers.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---

Fixed issues pointed out by sfr:
* removed unncessary initialization
* fixed OF reference count issue w/mpic
* maked of_device_ids as __initdata.

- k

 arch/powerpc/boot/dts/mpc8536ds.dts       |  420 ++++++++
 arch/powerpc/configs/mpc8536_ds_defconfig | 1637 +++++++++++++++++++++++++++++
 arch/powerpc/platforms/85xx/Kconfig       |    6 +
 arch/powerpc/platforms/85xx/Makefile      |    1 +
 arch/powerpc/platforms/85xx/mpc8536_ds.c  |  125 +++
 arch/powerpc/sysdev/fsl_pci.c             |    2 +
 include/linux/pci_ids.h                   |    2 +
 7 files changed, 2193 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/mpc8536ds.dts
 create mode 100644 arch/powerpc/configs/mpc8536_ds_defconfig
 create mode 100644 arch/powerpc/platforms/85xx/mpc8536_ds.c

diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts
new file mode 100644
index 0000000..98ad27a
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8536ds.dts
@@ -0,0 +1,420 @@
+/*
+ * MPC8536 DS Device Tree Source
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "fsl,mpc8536ds";
+	compatible = "fsl,mpc8536ds";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		pci3 = &pci3;
+	};
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8536@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 00000000>;	// Filled by U-Boot
+	};
+
+	soc@ffe00000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		ranges = <0x0 0xffe00000 0x100000>;
+		reg = <0xffe00000 0x1000>;
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		memory-controller@2000 {
+			compatible = "fsl,mpc8536-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 0x2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,mpc8536-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <16 0x2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 0x2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 0x2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+			rtc@68 {
+				compatible = "dallas,ds3232";
+				reg = <0x68>;
+			};
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8536-dma", "fsl,eloplus-dma";
+			reg = <0x21300 4>;
+			ranges = <0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8536-dma-channel",
+					     "fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <14 0x2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8536-dma-channel",
+					     "fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <15 0x2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8536-dma-channel",
+					     "fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <16 0x2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8536-dma-channel",
+					     "fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <17 0x2>;
+			};
+		};
+
+		mdio@24520 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,gianfar-mdio";
+			reg = <0x24520 0x20>;
+
+			phy0: ethernet-phy@0 {
+				interrupt-parent = <&mpic>;
+				interrupts = <10 0x1>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			phy1: ethernet-phy@1 {
+				interrupt-parent = <&mpic>;
+				interrupts = <10 0x1>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		usb@22000 {
+			compatible = "fsl,mpc8536-usb2-mph", "fsl-usb2-mph";
+			reg = <0x22000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <&mpic>;
+			interrupts = <28 0x2>;
+			phy_type = "ulpi";
+		};
+
+		usb@23000 {
+			compatible = "fsl,mpc8536-usb2-mph", "fsl-usb2-mph";
+			reg = <0x23000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <&mpic>;
+			interrupts = <46 0x2>;
+			phy_type = "ulpi";
+		};
+
+		enet0: ethernet@24000 {
+			cell-index = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy1>;
+			phy-connection-type = "rgmii-id";
+		};
+
+		enet1: ethernet@26000 {
+			cell-index = <1>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <31 2 32 2 33 2>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy0>;
+			phy-connection-type = "rgmii-id";
+		};
+
+		usb@2b000 {
+			compatible = "fsl,mpc8536-usb2-dr", "fsl-usb2-dr";
+			reg = <0x2b000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <&mpic>;
+			interrupts = <60 0x2>;
+			dr_mode = "peripheral";
+			phy_type = "ulpi";
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		sata@18000 {
+			compatible = "fsl,mpc8536-sata", "fsl,pq-sata";
+			reg = <0x18000 0x1000>;
+			cell-index = <1>;
+			interrupts = <74 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		sata@19000 {
+			compatible = "fsl,mpc8536-sata", "fsl,pq-sata";
+			reg = <0x19000 0x1000>;
+			cell-index = <2>;
+			interrupts = <41 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,mpc8548-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+			big-endian;
+		};
+
+		msi@41600 {
+			compatible = "fsl,mpc8536-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+
+	pci0: pci@ffe08000 {
+		cell-index = <0>;
+		compatible = "fsl,mpc8540-pci";
+		device_type = "pci";
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+
+			/* IDSEL 0x11 J17 Slot 1 */
+			0x8800 0 0 1 &mpic 1 1
+			0x8800 0 0 2 &mpic 2 1
+			0x8800 0 0 3 &mpic 3 1
+			0x8800 0 0 4 &mpic 4 1>;
+
+		interrupt-parent = <&mpic>;
+		interrupts = <24 0x2>;
+		bus-range = <0 0xff>;
+		ranges = <0x02000000 0 0x80000000 0x80000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xffc00000 0 0x00010000>;
+		clock-frequency = <66666666>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xffe08000 0x1000>;
+	};
+
+	pci1: pcie@ffe09000 {
+		cell-index = <1>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xffe09000 0x1000>;
+		bus-range = <0 0xff>;
+		ranges = <0x02000000 0 0x98000000 0x98000000 0 0x08000000
+			  0x01000000 0 0x00000000 0xffc20000 0 0x00010000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <25 0x2>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0 0 1 &mpic 4 1
+			0000 0 0 2 &mpic 5 1
+			0000 0 0 3 &mpic 6 1
+			0000 0 0 4 &mpic 7 1
+			>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x02000000 0 0x98000000
+				  0x02000000 0 0x98000000
+				  0 0x08000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci2: pcie@ffe0a000 {
+		cell-index = <2>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xffe0a000 0x1000>;
+		bus-range = <0 0xff>;
+		ranges = <0x02000000 0 0x90000000 0x90000000 0 0x08000000
+			  0x01000000 0 0x00000000 0xffc10000 0 0x00010000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <26 0x2>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0 0 1 &mpic 0 1
+			0000 0 0 2 &mpic 1 1
+			0000 0 0 3 &mpic 2 1
+			0000 0 0 4 &mpic 3 1
+			>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x02000000 0 0x90000000
+				  0x02000000 0 0x90000000
+				  0 0x08000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci3: pcie@ffe0b000 {
+		cell-index = <3>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xffe0b000 0x1000>;
+		bus-range = <0 0xff>;
+		ranges = <0x02000000 0 0xa0000000 0xa0000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xffc30000 0 0x00010000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <27 0x2>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0 0 1 &mpic 8 1
+			0000 0 0 2 &mpic 9 1
+			0000 0 0 3 &mpic 10 1
+			0000 0 0 4 &mpic 11 1
+			>;
+
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x02000000 0 0xa0000000
+				  0x02000000 0 0xa0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00100000>;
+		};
+	};
+};
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 9cb8e29..cebea5c 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -38,6 +38,12 @@ config MPC85xx_MDS
 	help
 	  This option enables support for the MPC85xx MDS board

+config MPC8536_DS
+	bool "Freescale MPC8536 DS"
+	select DEFAULT_UIMAGE
+	help
+	  This option enables support for the MPC8536 DS board
+
 config MPC85xx_DS
 	bool "Freescale MPC85xx DS"
 	select PPC_I8259
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 6cea185..cb3054e 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -4,6 +4,7 @@
 obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
+obj-$(CONFIG_MPC8536_DS)  += mpc8536_ds.o
 obj-$(CONFIG_MPC85xx_DS)  += mpc85xx_ds.o
 obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
 obj-$(CONFIG_STX_GP3)	  += stx_gp3.o
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
new file mode 100644
index 0000000..71d7c03
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -0,0 +1,125 @@
+/*
+ * MPC8536 DS Board Setup
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/of_platform.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+void __init mpc8536_ds_pic_init(void)
+{
+	struct mpic *mpic;
+	struct resource r;
+	struct device_node *np;
+
+	np = of_find_node_by_type(np, "open-pic");
+	if (np == NULL) {
+		printk(KERN_ERR "Could not find open-pic node\n");
+		return;
+	}
+
+	if (of_address_to_resource(np, 0, &r)) {
+		printk(KERN_ERR "Failed to map mpic register space\n");
+		of_node_put(np);
+		return;
+	}
+
+	mpic = mpic_alloc(np, r.start,
+			  MPIC_PRIMARY | MPIC_WANTS_RESET |
+			  MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS,
+			0, 256, " OpenPIC  ");
+	BUG_ON(mpic == NULL);
+	of_node_put(np);
+
+	mpic_init(mpic);
+}
+
+/*
+ * Setup the architecture
+ */
+static void __init mpc8536_ds_setup_arch(void)
+{
+#ifdef CONFIG_PCI
+	struct device_node *np;
+#endif
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc8536_ds_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+	for_each_node_by_type(np, "pci") {
+		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
+		    of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
+			struct resource rsrc;
+			of_address_to_resource(np, 0, &rsrc);
+			if ((rsrc.start & 0xfffff) == 0x8000)
+				fsl_add_bridge(np, 1);
+			else
+				fsl_add_bridge(np, 0);
+		}
+	}
+
+#endif
+
+	printk("MPC8536 DS board from Freescale Semiconductor\n");
+}
+
+static struct of_device_id __initdata mpc8536_ds_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{},
+};
+
+static int __init mpc8536_ds_publish_devices(void)
+{
+	return of_platform_bus_probe(NULL, mpc8536_ds_ids, NULL);
+}
+machine_device_initcall(mpc8536_ds, mpc8536_ds_publish_devices);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc8536_ds_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	return of_flat_dt_is_compatible(root, "fsl,mpc8536ds");
+}
+
+define_machine(mpc8536_ds) {
+	.name			= "MPC8536 DS",
+	.probe			= mpc8536_ds_probe,
+	.setup_arch		= mpc8536_ds_setup_arch,
+	.init_IRQ		= mpc8536_ds_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 489ca5a..87b0aa1 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -243,6 +243,8 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index eafc9d6..8b605bd 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2170,6 +2170,8 @@
 #define PCI_DEVICE_ID_MPC8544		0x0033
 #define PCI_DEVICE_ID_MPC8572E		0x0040
 #define PCI_DEVICE_ID_MPC8572		0x0041
+#define PCI_DEVICE_ID_MPC8536E		0x0050
+#define PCI_DEVICE_ID_MPC8536		0x0051
 #define PCI_DEVICE_ID_MPC8641		0x7010
 #define PCI_DEVICE_ID_MPC8641D		0x7011
 #define PCI_DEVICE_ID_MPC8610		0x7018
-- 
1.5.5.1

^ permalink raw reply related

* [PATCH] USB: EHCI: Reconciling USB register differences on MPC85xx vs MPC83xx
From: Kumar Gala @ 2008-07-02  7:14 UTC (permalink / raw)
  To: dbrownell, Greg KH; +Cc: linuxppc-dev, linux-usb

From: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>

A couple of USB register initializations had to be changed on MPC85xx
platforms.  This is due to the internal SoC buses being different on
MPC83xx SoCs vs MPC85xx SoCs.

We currently handle this via an ifdef since 83xx and 85xx are mutually
exclusive kernel builds.

Signed-off-by: Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---

This is for 2.6.27 and is need for proper USB functionality of the
MPC8536DS platform that will go in via the powerpc tree in 2.6.27.

- k

 drivers/usb/host/ehci-fsl.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 7370d61..237a779 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -230,8 +230,13 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)

 	/* put controller in host mode. */
 	ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
+#ifdef CONFIG_PPC_85xx
+	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
+	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
+#else
 	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
 	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
+#endif
 	out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
 }

-- 
1.5.5.1

^ permalink raw reply related


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