linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* Changes in the MPC8xx I2C driver
@ 2000-06-09 10:19 Kim Jørgensen
  2000-06-09 17:13 ` Dan Malek
  2000-08-07 16:39 ` I2C,SPI and QMC Frank Przybylski
  0 siblings, 2 replies; 6+ messages in thread
From: Kim Jørgensen @ 2000-06-09 10:19 UTC (permalink / raw)
  To: 'linuxppc-embedded@lists.linuxppc.org'

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

Hi,
I have made some changes in the MPC8xx I2C driver, mainly adding write
support and making the driver re-entrant. This might have some ones interest
so I'll post the driver here.

I don't use the minor number for the device address, instead I added an
ioctl function to allow set up of the device address, internal address
length and bus frequency. The setup data is saved in a struct, which is
accessed by the private pointer in the file pointer.
This allows several processes to talk to several i2c devices with different
bus frequency at the (almost) same time. I had a need for this, that's why I
made is that way.

I have removed all of the microcode relocation code in the driver, as I
couldn't make the driver work with this code and I had no need for applying
the patch.

I added these defines in commproc.h:
#define BD_SC_NAK       ((ushort)0x0004)        /* No Acknowledge */
#define BD_SC_UN        ((ushort)0x0002)        /* Underrun */
#define BD_SC_CL        ((ushort)0x0001)        /* Collision */

I made some clumsy code for converting offset to internal address, maybe
some one can tell me how to make this in a simpler way?

Any suggestions and comments are welcome.

--
Kim Jorgensen



[-- Attachment #2: iic.c --]
[-- Type: application/octet-stream, Size: 14013 bytes --]


/* MPC8xx CPM I2C interface. Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
 * This driver only support I2C master mode.
 */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/mpc8xx.h>

#include "commproc.h"

/* Print debug messages
 */
#define DEBUG

/* This is the I2C device number.
 */
#define CPM_I2C_CDEV_MAJOR 89

/* Defines to make I2C clock run at 100kHz (101kHz) @ 50MHz CPU clock */
#define I2BRG_100KHZ	0x1A
#define I2MOD_100KHZ 	0x0C

/* Defines to make I2C clock run at 400kHz (391kHz) @ 50MHz CPU clock */
#define I2BRG_400KHZ	0x0B
#define I2MOD_400KHZ 	0x0E

void	cpm_iic_init(void);
static int cpm_iic_open(struct inode *, struct file *);
static int cpm_iic_close(struct inode *, struct file *);
static ssize_t cpm_iic_read(struct file *, char *, size_t, loff_t *);
static ssize_t cpm_iic_write(struct file *, const char *, size_t, loff_t *);
static int cpm_iic_ioctl(struct inode *, struct file *, uint, ulong);
static void cpm_iic_interrupt(void *);

static struct file_operations cpm_iic_fops = {
	NULL,			/* lseek */
	cpm_iic_read,		/* read */
	cpm_iic_write,		/* write */
	NULL,			/* readdir */
	NULL,			/* select */
	cpm_iic_ioctl,		/* ioctl */
	NULL,			/* mmap */
	cpm_iic_open,		/* open */
	cpm_iic_close,		/* close */
	NULL			/* fsync */
};

/* File pointer specific setup
 */
typedef struct i2c_setup_struct_def
{
    u_char device_address;		/* The device we want to talk to */
    u_char internal_address_len;	/* The length of internal address */
    uint  clock_freq;			/* The i2c clock frequency */
} i2c_setup_struct;

/* Mutex used to make sure only one uses the i2c bus at time.
 */
struct semaphore bus_busy_mutex = MUTEX;

/* Wait queue used while waiting for interrupt
 */
static struct wait_queue *i2c_interrupt_wait;

volatile i2c8xx_t	*i2c;
volatile cbd_t		*tbdf, *rbdf;

void
cpm_iic_init()
{
	uint	mem_addr, dp_addr;
	volatile cpm8xx_t	*cp;
	volatile iic_t		*iip;
	volatile immap_t	*immap;

	/* print version string
	 */
	printk("CPM I2C driver version 0.01\n");

	/* Get pointer to Communication Processor
	 * and to internal registers
	 */
	cp = cpmp;
	immap = (immap_t *)IMAP_ADDR;

	iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
	i2c = (i2c8xx_t *)&(immap->im_i2c);

	/* Initialize Port B I2C pins.
	 */
	cp->cp_pbpar |= 0x00000030;
	cp->cp_pbdir |= 0x00000030;
	cp->cp_pbodr |= 0x00000030;

	/* Disable interrupts.
	 */
	i2c->i2c_i2cmr = 0;
	i2c->i2c_i2cer = 0xff;

	/* Set I2C controller in master mode
	 */
	i2c->i2c_i2com = 0x01;

	/* Allocate space for two transmit and one receive buffer
	 * descriptor in the DP ram.
	 */
	dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 3);

	/* Allocate space for two transmit and one receive buffer in the host memory.
	 * The most you can read or write at once from I2C is 128 bytes.
	 */
	mem_addr = m8xx_cpm_hostalloc(128 * 3);

	/* Set up the I2C parameters in the parameter ram.
	 */
	iip->iic_rbase =  dp_addr;
	iip->iic_tbase =  dp_addr + sizeof(cbd_t);

	/* Set the buffer address.
	 */
	rbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_rbase];
	tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase];

	rbdf[0].cbd_bufaddr = __pa(mem_addr);
	tbdf[0].cbd_bufaddr = __pa(mem_addr+128);
	tbdf[1].cbd_bufaddr = __pa(mem_addr+256);

	/* Set big endian byte order
	 */
	iip->iic_tfcr = SMC_EB;
	iip->iic_rfcr = SMC_EB;

	/* Set maximum receive size.
	 */
	iip->iic_mrblr = 128;

	/* Initialize Tx/Rx parameters.
	 */
	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG;
	while (cp->cp_cpcr & CPM_CR_FLG);

	/* Install interrupt handler.
	 */
	cpm_install_handler(CPMVEC_I2C, cpm_iic_interrupt, (void *)iip);

	/* Register the I2C driver
	 */
	if (register_chrdev(CPM_I2C_CDEV_MAJOR,"i2c",&cpm_iic_fops))
		printk("unable to get major %d for I2C devs\n",	CPM_I2C_CDEV_MAJOR);

}

static int
cpm_iic_open(struct inode *ip, struct file *fp)
{
    i2c_setup_struct *i2c_setup;

    /* Check minor number.
     */
    if( MINOR(ip->i_rdev) > 0)
	 return -ENODEV;

    /* Alloc some memory for I2C setup struct
     */
    fp->private_data = kmalloc(sizeof(i2c_setup_struct), GFP_KERNEL);
    i2c_setup = (i2c_setup_struct *)(fp->private_data);
    if(!i2c_setup)
	return -ENOMEM;

    /* Set device address and internal address length to 0
     * and i2c clock freq. to 100kHz
     */
    i2c_setup->device_address = 0;
    i2c_setup->internal_address_len = 0;
    i2c_setup->clock_freq = 100000;
    
    /* Set pointer to file operations struct
     */
    fp->f_op = &cpm_iic_fops;

    return 0;
}

static int
cpm_iic_close(struct inode *ip, struct file *fp)
{
        /* Free space used by i2c setup struct
	 */
	kfree(fp->private_data);

	return 0;
}

/* Read from I2C.
 * This is a two step process if internal addresses is used.  First, we send 
 * the "dummy" write to set the internal address for the read.  Second, we 
 * perform the read operation.
 */
static ssize_t
cpm_iic_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
{
        i2c_setup_struct	*i2c_setup;
	loff_t	offset;
	u_char	*tb, *tb2, *rb, len, tmp_off[4];

	/* Get pointer to i2c setup data
	 */
	i2c_setup = (i2c_setup_struct *)(fp->private_data);

	/* Get pointer to transmit and receive buffer
	 */
	tb =  __va(tbdf[0].cbd_bufaddr);
	tb2 = __va(tbdf[1].cbd_bufaddr);
	rb =  __va(rbdf[0].cbd_bufaddr);

	/* Get file offset (internal address)
	 */
	offset = *ppos;

	tmp_off[0] = (char)(offset >> 24);
	tmp_off[1] = (char)((offset >> 16) % 0x100);
	tmp_off[2] = (char)((offset >> 8) % 0x100);
	tmp_off[3] = (char)(offset % 0x100);

	/* Enter critical section
	 */
	down(&bus_busy_mutex);
        if (signal_pending(current))
	{
	    up(&bus_busy_mutex);
	    return -ERESTARTSYS;
	}

	if(i2c_setup->internal_address_len)		/* Use internal address	*/
	{
	    *tb = i2c_setup->device_address & 0xfe;	/* Device address, write request */
	    tbdf[0].cbd_datlen = i2c_setup->internal_address_len + 1 ;	/* Length */

	    /* copy offset into transmit buffer
	     */
	     for(len=0; len < i2c_setup->internal_address_len; len++)
	         tb[1+len] = tmp_off[(4 - i2c_setup->internal_address_len) + len];
	    
	    *tb2 = i2c_setup->device_address | 0x01;	/* Device address, read request */
	    tbdf[1].cbd_datlen = count + 1;		/* Length */

	    tbdf[0].cbd_sc = BD_SC_READY | BD_IIC_START;
	    tbdf[1].cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
	}
	else						/* No internal address */
	{
	    *tb = i2c_setup->device_address | 0x01;	/* Device address, read request */
    	    tbdf[0].cbd_datlen = count + 1;		/* Length */

	    tbdf[0].cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
	}
	
	rbdf[0].cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP;
	
	i2c->i2c_i2cmr = 0x15;			/* Enable receive interrupt */
	i2c->i2c_i2cer = 0xff;			/* Clear event register */

	if(i2c_setup->clock_freq == 400000)	/* Make clock run at 400kHz */
	{
	    i2c->i2c_i2brg = I2BRG_400KHZ;
	    i2c->i2c_i2mod = I2MOD_400KHZ;
	}
	else					/* Make clock run at 100kHz */
	{
	    i2c->i2c_i2brg = I2BRG_100KHZ;
	    i2c->i2c_i2mod = I2MOD_100KHZ;
	}

	i2c->i2c_i2mod |= 0x01;			/* Chip errata, set enable here */
	i2c->i2c_i2com |= 0x80;			/* Start transmit */

	/* Wait for I2C receive interrupt or time out (1 second).
	*/
	if(interruptible_sleep_on_timeout(&i2c_interrupt_wait, 1*HZ)<=0)
	{
#ifdef DEBUG
	    printk("I2C read: Time out!\n");
#endif
	}

	i2c->i2c_i2mod &= ~0x01;		/* Chip errata, clear enable */

	if(signal_pending(current))
	{
	    up(&bus_busy_mutex);
	    return -ERESTARTSYS;
	}

	/* check for errors in first tx buffer
	 */
	if(tbdf[0].cbd_sc & (BD_SC_READY | BD_SC_NAK | BD_SC_UN | BD_SC_CL))
	{
#ifdef DEBUG
	    switch(tbdf[0].cbd_sc & (BD_SC_READY | BD_SC_NAK | BD_SC_UN | BD_SC_CL))
	    {
		case BD_SC_READY:
		    printk("I2C read complete but tx_buf ready!\n");
		    break;
		case BD_SC_NAK:
		    printk("I2C read: no acknowledge!\n");
		    break;
		case BD_SC_UN:
	    	    printk("I2C read: underrun!\n");
		    break;
		case BD_SC_CL:
		    printk("I2C read: collision!\n");
		    break;
	    }
#endif
	    up(&bus_busy_mutex);
	    return -EFAULT;
	}

	if(i2c_setup->internal_address_len)
	{
	    /* check for errors in second tx buffer
	     */
	    if(tbdf[1].cbd_sc & (BD_SC_READY | BD_SC_NAK | BD_SC_UN | BD_SC_CL))
	    {
#ifdef DEBUG
		switch(tbdf[1].cbd_sc & (BD_SC_READY | BD_SC_NAK | BD_SC_UN | BD_SC_CL))
		{
		    case BD_SC_READY:
			printk("I2C read complete but tx_buf ready!\n");
			break;
		    case BD_SC_NAK:
			printk("I2C read: no acknowledge!\n");
			break;
    		    case BD_SC_UN:
	    		printk("I2C read: underrun!\n");
			break;
		    case BD_SC_CL:
			printk("I2C read: collision!\n");
			break;
		}
#endif
		up(&bus_busy_mutex);
		return -EFAULT;
	    }
	}

	/* check for errors in rx buffer
	 */
	if (rbdf[0].cbd_sc & BD_SC_EMPTY)
	{
	    up(&bus_busy_mutex);
#ifdef DEBUG
	    printk("I2C read complete but rx_buf empty!");
#endif
    	    return -EFAULT;
	}
	
	if (copy_to_user(buf, rb, count))
	{
	    up(&bus_busy_mutex);
	    return -EFAULT;
	}

	/* Leave critical section
	 */
        up(&bus_busy_mutex);
	
	*ppos += count;
	return count;
}

/* I2C write funktion.
*/
static ssize_t
cpm_iic_write(struct file *fp, const char *buf, size_t count, loff_t *ppos)
{
	i2c_setup_struct 	*i2c_setup;
	loff_t	offset;
	u_char	*tb, len, tmp_off[4];

	/* Get pointer to i2c setup data
	 */
	i2c_setup = (i2c_setup_struct *)(fp->private_data);
	
	/* Get file offset (internal address)
	 */
	offset = *ppos;

	tmp_off[0] = (char)(offset >> 24);
	tmp_off[1] = (char)((offset >> 16) % 0x100);
	tmp_off[2] = (char)((offset >> 8) % 0x100);
	tmp_off[3] = (char)(offset % 0x100);


	/* Enter critical section
	 */
	down(&bus_busy_mutex);
        if(signal_pending(current))
	{
	    up(&bus_busy_mutex);
	    return -ERESTARTSYS;
	}

	/* Get pointer to transmit buffer
	 */
	tb = __va(tbdf[0].cbd_bufaddr);

	*tb = i2c_setup->device_address & 0xfe;	/* Set device address, write request */


	if(i2c_setup->internal_address_len)	/* Use internal address	*/
	{
            /* copy offset into transmit buffer
	     */
	    for(len=0; len < i2c_setup->internal_address_len; len++)
		tb[1+len] = tmp_off[(4 - i2c_setup->internal_address_len) + len];
	}

	/* copy data into transmit buffer
	 */
	if(copy_from_user(tb+i2c_setup->internal_address_len+1, buf, count))
	{
	    up(&bus_busy_mutex);
	    return -EFAULT;
	}

	tbdf[0].cbd_datlen = count + i2c_setup->internal_address_len + 1;	/* Data length */
	tbdf[0].cbd_sc =  BD_SC_READY | BD_SC_INTRPT | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;

	i2c->i2c_i2cmr = 0x16;			/* Enable transmit interrupt */
	i2c->i2c_i2cer = 0xff;			/* Clear event register */


	if(i2c_setup->clock_freq == 400000)	/* Make clock run at 400kHz */
	{
	    i2c->i2c_i2brg = I2BRG_400KHZ;
	    i2c->i2c_i2mod = I2MOD_400KHZ;
	}
	else					/* Make clock run at 100kHz */
	{
	    i2c->i2c_i2brg = I2BRG_100KHZ;
	    i2c->i2c_i2mod = I2MOD_100KHZ;
	}

	i2c->i2c_i2mod |= 0x01;			/* Chip errata, set enable here */
	i2c->i2c_i2com |= 0x80;			/* Start transmit */

	/* Wait for I2C transmit interrupt or time out (1 second).
	*/
	if(interruptible_sleep_on_timeout(&i2c_interrupt_wait, 1*HZ)<=0)
	{
#ifdef DEBUG
	    printk("I2C write: Time out!\n");
#endif
	}

	i2c->i2c_i2mod &= ~0x01;		/* Chip errata, clear enable */

	if (signal_pending(current))
	{
	    up(&bus_busy_mutex);
	    return -ERESTARTSYS;
	}

	/* check for errors in tx buffer
	 */
	if(tbdf[0].cbd_sc & (BD_SC_READY | BD_SC_NAK | BD_SC_UN | BD_SC_CL))
	{
#ifdef DEBUG
	    switch(tbdf[0].cbd_sc & (BD_SC_READY | BD_SC_NAK | BD_SC_UN | BD_SC_CL))
	    {
		case BD_SC_READY:
		    printk("I2C write complete but tx_buf ready!\n");
		    break;
		case BD_SC_NAK:
		    printk("I2C write: no acknowledge!\n");
		    break;
		case BD_SC_UN:
	    	    printk("I2C write: underrun!\n");
		    break;
		case BD_SC_CL:
		    printk("I2C write: collision!\n");
		    break;
	    }
#endif
	    up(&bus_busy_mutex);
	    return -EFAULT;
	}

	/* Leave critical section
	 */
	up(&bus_busy_mutex);

        *ppos += count;
	return count;
}

static int
cpm_iic_ioctl(struct inode *ip, struct file *fp, u_int cmd, ulong arg)
{
	int	retval = 0;
	i2c_setup_struct *i2c_setup;

	i2c_setup = (i2c_setup_struct *)(fp->private_data);

	switch(cmd)
	{
	    /* Set device address.
	     */
	    case 1:
		i2c_setup->device_address = (u_char)arg & 0xfe; 	/* Set device address, ignore LSB */
		break;

	    /* Set internal address length.
	     */
	    case 2:
	    	if((u_char)arg > 4)
		    retval = -EINVAL;
		else 
		    i2c_setup->internal_address_len = (u_char)arg;
		break;

	    /* Set the bus clock frequency.
	     */
	    case 3:
		if(((uint)arg != 100000) && ((uint)arg != 400000))
		    retval = -EINVAL;
		else
		    i2c_setup->clock_freq = (uint)arg;
		break;
		
	    default: retval = -ENOIOCTLCMD;
	}

	return retval;
}

static void
cpm_iic_interrupt(void *dev_id)
{
	/* Clear interrupt.
	*/
	i2c->i2c_i2cer = 0xff;

	/* Wake up process in wait queue
	*/
	wake_up_interruptible(&i2c_interrupt_wait);
}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Changes in the MPC8xx I2C driver
  2000-06-09 10:19 Changes in the MPC8xx I2C driver Kim Jørgensen
@ 2000-06-09 17:13 ` Dan Malek
  2000-08-07 16:39 ` I2C,SPI and QMC Frank Przybylski
  1 sibling, 0 replies; 6+ messages in thread
From: Dan Malek @ 2000-06-09 17:13 UTC (permalink / raw)
  To: Kim Jørgensen; +Cc: 'linuxppc-embedded@lists.linuxppc.org'


Kim Jørgensen wrote:

> I have made some changes in the MPC8xx I2C driver, mainly adding write
> support and making the driver re-entrant.

Looks pretty good.  I will add it to kernel sources.

> I don't use the minor number for the device address,

Did you investigate the Linux I2C implementation?  I never did, but
perhaps it would be worthwhile to make this look like that at least
to an application.

> I have removed all of the microcode relocation code in the driver, as I
> couldn't make the driver work with this code and I had no need for applying
> the patch.

That is fine.  I could never make it work either.  I have had some
discussions with others about this, but no solution yet.


> I made some clumsy code for converting offset to internal address, maybe
> some one can tell me how to make this in a simpler way?

The challenge is some devices need this address, others don't.  What
you have seems fine.  After we use it for a while maybe we can find
something better.

Thanks.


	-- Dan

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* I2C,SPI and QMC
  2000-06-09 10:19 Changes in the MPC8xx I2C driver Kim Jørgensen
  2000-06-09 17:13 ` Dan Malek
@ 2000-08-07 16:39 ` Frank Przybylski
  2000-08-07 17:42   ` Matthew Locke
  1 sibling, 1 reply; 6+ messages in thread
From: Frank Przybylski @ 2000-08-07 16:39 UTC (permalink / raw)
  Cc: 'linuxppc-embedded@lists.linuxppc.org'


Hi all,
I plan to use QMC on SCC1 plus SPI on a MPC855T / 860DT for an ISDN BRI
implementation. I also need I2C for other purposes.
Following the QMCSUPPLEMENT/AD manual from Motorola I found that one looses
either I2C using SCC1 for QMC/Ethernet or SPI using SCC2 for QMC/Ethernet.
I hoped that the I2C/SPI micro code patch would do the trick. But scanning this
mailing list archive I got aware of troubles with this, or even worse that the
patch has been removed from the kernel.
So my question goes like this:
 has anybody managed to use I2C, SPI and QMC on SCC1 altogether, or am I lost
without any hope?

TIA
      Frank

===============================================================================
Frank Przybylski,VAS GmbH,Gotenstr.6,20097 Hamburg,GERMANY,TEL:+49-40-238568-14
   mailto:Frank.Przybylski@vas-gmbh.de , visit us at http://www.vas-gmbh.de
===============================================================================

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: I2C,SPI and QMC
  2000-08-07 16:39 ` I2C,SPI and QMC Frank Przybylski
@ 2000-08-07 17:42   ` Matthew Locke
  2000-08-08 19:27     ` Dan Malek
  0 siblings, 1 reply; 6+ messages in thread
From: Matthew Locke @ 2000-08-07 17:42 UTC (permalink / raw)
  To: Frank Przybylski; +Cc: 'linuxppc-embedded@lists.linuxppc.org'


Frank Przybylski wrote:
>
> Hi all,
> I plan to use QMC on SCC1 plus SPI on a MPC855T / 860DT for an ISDN BRI
> implementation. I also need I2C for other purposes.
> Following the QMCSUPPLEMENT/AD manual from Motorola I found that one looses
> either I2C using SCC1 for QMC/Ethernet or SPI using SCC2 for QMC/Ethernet.
> I hoped that the I2C/SPI micro code patch would do the trick. But scanning this
> mailing list archive I got aware of troubles with this, or even worse that the
> patch has been removed from the kernel.
> So my question goes like this:
>  has anybody managed to use I2C, SPI and QMC on SCC1 altogether, or am I lost
> without any hope?
>

I have successfully used SPI with ethernet on SCC2 with the microcode
patch. However, I did that on a 823, I haven't tried it on the 855/860.
I think I have used the i2c driver with the microcode patch on a 860,
but don't quote me.  This was all on the Embedded Planet boards.


Matthew Locke
Montavista Software
http://www.mvista.com

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: I2C,SPI and QMC
  2000-08-07 17:42   ` Matthew Locke
@ 2000-08-08 19:27     ` Dan Malek
  2000-08-09  8:40       ` Frank Przybylski
  0 siblings, 1 reply; 6+ messages in thread
From: Dan Malek @ 2000-08-08 19:27 UTC (permalink / raw)
  To: Matthew Locke
  Cc: Frank Przybylski, 'linuxppc-embedded@lists.linuxppc.org'


Matthew Locke wrote:

> I have successfully used SPI with ethernet on SCC2 with the microcode
> patch.

Better than me :-)!  I left my attempt at microcode patches around
someplace, but was never able to make them work very well.

Depending upon your SPI or I2C requirements, you may just be able to
toggle the pins in software.  This is all I did.


	-- Dan

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: I2C,SPI and QMC
  2000-08-08 19:27     ` Dan Malek
@ 2000-08-09  8:40       ` Frank Przybylski
  0 siblings, 0 replies; 6+ messages in thread
From: Frank Przybylski @ 2000-08-09  8:40 UTC (permalink / raw)
  To: 'linuxppc-embedded@lists.linuxppc.org'; +Cc: Dan Malek, Matthew Locke


Thank you for your answers. As this is going to be a new hardware I wanted to be
on the secure side. So I'm going to try the patch with the software option on
the very same pins as a fall back option.

    Frank

Dan Malek wrote:
>
> Matthew Locke wrote:
>
> > I have successfully used SPI with ethernet on SCC2 with the microcode
> > patch.
>
> Better than me :-)!  I left my attempt at microcode patches around
> someplace, but was never able to make them work very well.
>
> Depending upon your SPI or I2C requirements, you may just be able to
> toggle the pins in software.  This is all I did.
>
>         -- Dan

--
===============================================================================
Frank Przybylski,VAS GmbH,Gotenstr.6,20097 Hamburg,GERMANY,TEL:+49-40-238568-14
   mailto:Frank.Przybylski@vas-gmbh.de , visit us at http://www.vas-gmbh.de
===============================================================================

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2000-08-09  8:40 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2000-06-09 10:19 Changes in the MPC8xx I2C driver Kim Jørgensen
2000-06-09 17:13 ` Dan Malek
2000-08-07 16:39 ` I2C,SPI and QMC Frank Przybylski
2000-08-07 17:42   ` Matthew Locke
2000-08-08 19:27     ` Dan Malek
2000-08-09  8:40       ` Frank Przybylski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).