linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* IDE DMA Issue ppc
@ 2006-09-13 11:11 Akhilesh
  0 siblings, 0 replies; only message in thread
From: Akhilesh @ 2006-09-13 11:11 UTC (permalink / raw)
  To: linuxppc-embedded


[-- Attachment #1.1: Type: text/plain, Size: 610 bytes --]

Hi All,


I'm using IBM redwood6 stb025xx(ppc405gp) platform with 2.6.14 kernel. I'm trying to get DMA working for IDE interface (PIO is working). The problem I'm facing is that my DMA is completing and I'm getting a error in DMA status register that "A DMA  request from an external device is pending"

I'm attaching the console message along with the sample code of the driver. Please help me to resolve this issue. What I feel is that DMA is completing and IDE is not getting anything. ( IDE status register is giving 0x58).

Any pointers to same will be highly appreciated.


Regards,
Akhilesh

[-- Attachment #1.2: Type: text/html, Size: 1495 bytes --]

[-- Attachment #2: console.txt --]
[-- Type: text/plain, Size: 15322 bytes --]



IBM Set-Top-Box BIOS 1.50 (Feb-16-2004)

Platform support <Redwood6/STBx25xx 1.03 (Jun/24/2002)>


Initializing devices, please wait.....
                                         

 ------- System Info --------

 Processor speed = 252 MHz

 EBIU speed      = 63 MHz

 Amount of RAM   = 64 MBytes

DM9000 : dmfe_probe() : Checking DM9000 chip 

DM9000 : Chip Found ID : 90000a46 


 --- Device Configuration ---

 Power-On Test Devices:

   000  Disabled  System Memory [RAM]

 ----------------------------

 Boot Sources:

   001  Disabled  Application in Flash [FLASH]

   002  Enabled   Ethernet [ENET]

                  local=192.168.18.28  remote=192.168.18.101  hwaddr=bad0add00000

   003  Disabled  Serial Port 1 [S1]

                  Baud = 9600

 ----------------------------

Update Flash  : Disabled 

Automatic Boot: Disabled

 ----------------------------

  1 - Toggle Power-On Tests

  2 - Change a Boot Device

  3 - Change IP Addresses

  4 - Ping test

  5 - Change Baud Rate for S1 Boot

  6 - Toggle Update Flash

  7 - Toggle Automatic Boot

  B - Bootlogo Management

  D - Display Configuration

  S - Save Changes

  Z - Set Ethernet HW Address

  0 - Exit Menu and Boot Application

  C - Enable CHOIS Debug 

->0

DM900 : dmfe_init_dm9000 : initialising dm9000

Booting from [ENET] Ethernet...

Sending bootp request ...

 bootp packets sent = 1
DM900 : dmfe_send : hold frame collision, outbound frame.


Got bootp response from : 192.168.18.101

       My ip address is : 192.168.18.28


Loading file "zImage.treeboot" by TFTP for net boot ...

 block  268
 block 1440
Transfer completed, 897568 bytes received

Loaded successfully ...

Entry point at 0x500000 ...


loaded at:     00500000 005DC164

relocated to:  00400000 004DC164

board data at: 004DA124 004DA164

relocated to:  0040515C 0040519C

zimage at:     0040591D 004D9A6C

avail ram:     004DD000 02000000


Linux/PPC load: ip=on

Uncompressing Linux...done.

Now booting the kernel

Linux version 2.6.14 (root@localhost.localdomain) (gcc version 4.0.0 (DENX ELDK 4.0 4.0.0)) #258 Wed Sep 13 16:12:58 IST 2006

ocp: ocp_early_init()...

ocp: ocp_add_one_device()...

ocp: ocp_add_one_device()...done

ocp: ocp_add_one_device()...

ocp: ocp_add_one_device()...done

ocp: ocp_add_one_device()...

ocp: ocp_add_one_device()...done

ocp: ocp_add_one_device()...

ocp: ocp_add_one_device()...done

ocp: ocp_add_one_device()...

ocp: ocp_add_one_device()...done

ocp: ocp_add_one_device()...

ocp: ocp_add_one_device()...done

ocp: ocp_early_init()... done.

IBM Redwood6 (STBx25XX) Platform

Port by MontaVista Software, Inc. (source@mvista.com)

Built 1 zonelists

Kernel command line: ip=on

PID hash table entries: 256 (order: 8, 4096 bytes)

Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)

Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)

Memory: 30488k available (1452k kernel code, 344k data, 96k init, 0k highmem)

Mount-cache hash table entries: 512

NET: Registered protocol family 16

ocp: ocp_driver_init()...

ocp: ocp_driver_init()... done.

Adding platform devices 

Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing disabled

ttyS0 at MMIO 0x0 (irq = 22) is a 16550A

ttyS1 at MMIO 0x0 (irq = 20) is a 16550A

ttyS2 at MMIO 0x0 (irq = 21) is a 16550A

io scheduler noop registered

io scheduler anticipatory registered

io scheduler deadline registered

io scheduler cfq registered

RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize

loop: loaded (max 8 devices)

dm9000 Ethernet Driver

dm9000_set_io : byte_width 2

eth0: dm9000 at c3000000,c3000004 IRQ 26 MAC: ba:d0:ad:d0:00:00

Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2

ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx

NET: Registered protocol family 2

IP route cache hash table entries: 512 (order: -1, 2048 bytes)

TCP established hash table entries: 2048 (order: 1, 8192 bytes)

TCP bind hash table entries: 2048 (order: 1, 8192 bytes)

TCP: Hash tables configured (established 2048 bind 2048)

TCP reno registered

TCP bic registered

NET: Registered protocol family 1

inside stb04xxx_ide_init 

IBM STB025xx OCP IDE driver version 1.0 f2100000 

ide_redwood: waiting for drive ready......Drive spun up 

ocp_ide_setup_dma 

probing for hda: present=0, media=32, probetype=ATA

hda: probing with STATUS(0x51) instead of ALTSTATUS(0x00)

hda: WDC WD400EB-00CPF0, ATA DISK drive

probing for hdb: present=0, media=32, probetype=ATA

probing for hdb: present=0, media=32, probetype=ATAPI

hdb: probing with STATUS(0x01) instead of ALTSTATUS(0x00)

ocp_ide_tune_drive pio 4

got ocp_ide_dma_off_quietly

got ocp_ide_dma_check

redwood_config_drive_for_dma 22

ocp_ide_tune_drive pio 4

got ocp_ide_dma_on

ide0 at 0xc3004000-0xc3004007,0xc3006000 on irq 27

hda: max request size: 128KiB

ide_execute_command : 0x91

ide_execute_command : 0x10

ide_execute_command : 0xf8

hda: 78165360 sectors (40020 MB) w/2048KiB Cache, CHS=65535/16/63, (U)DMA

hda: cache flushes not supported

 hda:__ide_do_rw_disk : dma 1 lba48 0 LBA=0

got ocp_ide_dma_setup 

ide_execute_command : 0xc8

got ocp_ide_dma_begin 0x1000

DMA addr c0340000 340000 count 8 dmastat 0

got ocp_ide_dma_test_irq

got ocp_ide_dma_end 0 20000000

ide_dma_intr : stat 50

DMA complete stat 0 500000

 hda1

IDE probe finished 

eth0: link up, 100Mbps, full-duplex, lpa 0x41E1

Sending BOOTP and RARP requests . OK

IP-Config: Got BOOTP answer from 192.168.18.101, my address is 192.168.18.28

IP-Config: Complete:

      device=eth0, addr=192.168.18.28, mask=255.255.255.0, gw=192.168.18.1,

     host=192.168.18.28, domain=, nis-domain=(none),

     bootserver=192.168.18.101, rootserver=192.168.18.101, rootpath=/opt/eldk/ppc_4xx

Looking up port of RPC 100003/2 on 192.168.18.101

Looking up port of RPC 100005/1 on 192.168.18.101

VFS: Mounted root (nfs filesystem) readonly.

Freeing unused kernel memory: 96k init

modprobe: FATAL: Could not load /lib/modules/2.6.14/modules.dep: No such file or directory

modprobe: FATAL: Could not load /lib/modules/2.6.14/modules.dep: No such file or directory


INIT: version 2.85 booting
 Came here in rc.sysinit creating var\n
mounting 
ln: `/proc/mounts': File exists
		Welcome to DENX Embedded Linux Environment
		Press 'I' to enter interactive startup.
Building the cache [  OK  ]
 storage network audio done[  OK  ]
modprobe: FATAL: Could not load /lib/modules/2.6.14/modules.dep: No such file or directory

Cannot access the Hardware Clock via any known method.
Use the --debug option to see the details of our search for an access method.
Setting clock : Thu Jan  1 01:00:12 MET 1970 [  OK  ]
Setting hostname CHOISpad-110:  [  OK  ]
Mounting local filesystems:  [  OK  ]
Enabling swap space:  [  OK  ]

INIT: Entering runlevel: 3
Entering non-interactive startup
Bringing up loopback interface:  modprobe: FATAL: Could not load /lib/modules/2.6.14/modules.dep: No such file or directory

arping: socket: Address family not supported by protocol
Error, some other host already uses address 127.0.0.1.
[FAILED]
Starting system logger: [  OK  ]
Starting kernel logger: [  OK  ]
Starting portmap: [  OK  ]
Mounting NFS filesystems:  [  OK  ]
Mounting other filesystems:  [  OK  ]
Starting xinetd: [  OK  ]

DENX ELDK version 4.0 build 2006-01-11
Linux 2.6.14 on a ppc

CHOISpad-110 login: root
Last login: Thu Jan  1 01:00:19 on console
bash-3.00# 
bash-3.00# 
bash-3.00# 
bash-3.00# 
bash-3.00# 
bash-3.00# hdparm -t\b \b\b \b/dev/hda

/dev/hda:
 multcount    =  0 (off)
 I/O support  =  0 (default 16-bit)
 unmaskirq    =  1 (on)
 using_dma    =  1 (on)
 keepsettings =  0 (off)
 nowerr       =  0 (off)
 readonly     =  0 (off)
 readahead    = 256 (on)
 geometry     = 65535/16/63, sectors = 78165360, start = 0
bash-3.00# 
bash-3.00# 
bash-3.00# 
bash-3.00# 
bash-3.00# hdparm -t /dev/hda

/dev/hda:
 Timing buffered__ide_do_rw_disk : dma 1 lba48 0 LBA=0

 disk reads:  got ocp_ide_dma_setup 

ide_execute_command : 0xc8

got ocp_ide_dma_begin 0x1000

DMA addr c1238000 1238000 count 8 dmastat 0

DMA complete stat 20001000 0

hda: lost interrupt

got ocp_ide_dma_end 0 20000000

ide_dma_intr : stat 58

hda: dma_intr: status=0x58 { DriveReady SeekComplete DataRequest }

ide: failed opcode was: unknown

__ide_do_rw_disk : dma 1 lba48 0 LBA=0

got ocp_ide_dma_setup 

ide_execute_command : 0xc8

got ocp_ide_dma_begin 0x1000

DMA addr c1238000 1238000 count 8 dmastat 0

DMA complete stat 20001000 0

hda: lost interrupt

got ocp_ide_dma_end 0 20000000

ide_dma_intr : stat 58

hda: dma_intr: status=0x58 { DriveReady SeekComplete DataRequest }

ide: failed opcode was: unknown

ide_execute_command : 0x10

__ide_do_rw_disk : dma 1 lba48 0 LBA=0

got ocp_ide_dma_setup 

ide_execute_command : 0xc8

got ocp_ide_dma_begin 0x1000

DMA addr c1238000 1238000 count 8 dmastat 0

DMA complete stat 20001000 0

hda: lost interrupt

got ocp_ide_dma_end 0 20000000

ide_dma_intr : stat 58

hda: dma_intr: status=0x58 { DriveReady SeekComplete DataRequest }

ide: failed opcode was: unknown

__ide_do_rw_disk : dma 1 lba48 0 LBA=0

got ocp_ide_dma_setup 

ide_execute_command : 0xc8

got ocp_ide_dma_begin 0x1000

DMA addr c1238000 1238000 count 8 dmastat 0

DMA complete stat 20001000 0

hda: lost interrupt

got ocp_ide_dma_end 0 20000000

ide_dma_intr : stat 58

hda: dma_intr: status=0x58 { DriveReady SeekComplete DataRequest }

ide: failed opcode was: unknown

got ocp_ide_dma_off_quietly

ide0: reset: master: error (0x00?)

ide_execute_command : 0x91

ide_execute_command : 0x10

__ide_do_rw_disk : dma 1 lba48 0 LBA=0

got ocp_ide_dma_setup 

ide_execute_command : 0xc8

got ocp_ide_dma_begin 0x1000

DMA addr c1238000 1238000 count 8 dmastat 0

DMA complete stat 20001000 0

hda: lost interrupt

got ocp_ide_dma_end 0 20000000

ide_dma_intr : stat 58

hda: dma_intr: status=0x58 { DriveReady SeekComplete DataRequest }

ide: failed opcode was: unknown

__ide_do_rw_disk : dma 1 lba48 0 LBA=0

got ocp_ide_dma_setup 

ide_execute_command : 0xc8

got ocp_ide_dma_begin 0x1000

DMA addr c1238000 1238000 count 8 dmastat 0

DMA complete stat 20001000 0

hda: lost interrupt

got ocp_ide_dma_end 0 20000000

ide_dma_intr : stat 58

hda: dma_intr: status=0x58 { DriveReady SeekComplete DataRequest }

ide: failed opcode was: unknown

ide_execute_command : 0x10

__ide_do_rw_disk : dma 1 lba48 0 LBA=0

got ocp_ide_dma_setup 

ide_execute_command : 0xc8

got ocp_ide_dma_begin 0x1000

DMA addr c1238000 1238000 count 8 dmastat 0

DMA complete stat 20001000 0

hda: lost interrupt

got ocp_ide_dma_end 0 20000000

ide_dma_intr : stat 58

hda: dma_intr: status=0x58 { DriveReady SeekComplete DataRequest }

ide: failed opcode was: unknown

__ide_do_rw_disk : dma 1 lba48 0 LBA=0

got ocp_ide_dma_setup 

ide_execute_command : 0xc8

got ocp_ide_dma_begin 0x1000

DMA addr c1238000 1238000 count 8 dmastat 0

DMA complete stat 20001000 0

hda: lost interrupt

got ocp_ide_dma_end 0 20000000

ide_dma_intr : stat 58

hda: dma_intr: status=0x58 { DriveReady SeekComplete DataRequest }

ide: failed opcode was: unknown

got ocp_ide_dma_off_quietly

ide0: reset: master: error (0x00?)

end_request: I/O error, dev hda, sector 0

Buffer I/O error on device hda, logical block 0

end_request: I/O error, dev hda, sector 8

Buffer I/O error on device hda, logical block 1

end_request: I/O error, dev hda, sector 16

Buffer I/O error on device hda, logical block 2

end_request: I/O error, dev hda, sector 24

Buffer I/O error on device hda, logical block 3

end_request: I/O error, dev hda, sector 32

Buffer I/O error on device hda, logical block 4

end_request: I/O error, dev hda, sector 40

Buffer I/O error on device hda, logical block 5

end_request: I/O error, dev hda, sector 48

Buffer I/O error on device hda, logical block 6

end_request: I/O error, dev hda, sector 56

Buffer I/O error on device hda, logical block 7

end_request: I/O error, dev hda, sector 64

Buffer I/O error on device hda, logical block 8

end_request: I/O error, dev hda, sector 72

Buffer I/O error on device hda, logical block 9

end_request: I/O error, dev hda, sector 80

end_request: I/O error, dev hda, sector 88

end_request: I/O error, dev hda, sector 96

end_request: I/O error, dev hda, sector 104

end_request: I/O error, dev hda, sector 112

end_request: I/O error, dev hda, sector 120

end_request: I/O error, dev hda, sector 128

end_request: I/O error, dev hda, sector 136

end_request: I/O error, dev hda, sector 144

end_request: I/O error, dev hda, sector 152

end_request: I/O error, dev hda, sector 160

end_request: I/O error, dev hda, sector 168

end_request: I/O error, dev hda, sector 176

end_request: I/O error, dev hda, sector 184

end_request: I/O error, dev hda, sector 192

end_request: I/O error, dev hda, sector 200

end_request: I/O error, dev hda, sector 208

end_request: I/O error, dev hda, sector 216

end_request: I/O error, dev hda, sector 224

end_request: I/O error, dev hda, sector 232

end_request: I/O error, dev hda, sector 240

end_request: I/O error, dev hda, sector 248

end_request: I/O error, dev hda, sector 256

end_request: I/O error, dev hda, sector 264

end_request: I/O error, dev hda, sector 272

end_request: I/O error, dev hda, sector 280

end_request: I/O error, dev hda, sector 288

end_request: I/O error, dev hda, sector 296

end_request: I/O error, dev hda, sector 304

end_request: I/O error, dev hda, sector 312

end_request: I/O error, dev hda, sector 320

end_request: I/O error, dev hda, sector 328

end_request: I/O error, dev hda, sector 336

end_request: I/O error, dev hda, sector 344

end_request: I/O error, dev hda, sector 352

end_request: I/O error, dev hda, sector 360

end_request: I/O error, dev hda, sector 368

end_request: I/O error, dev hda, sector 376

end_request: I/O error, dev hda, sector 384

end_request: I/O error, dev hda, sector 392

end_request: I/O error, dev hda, sector 400

end_request: I/O error, dev hda, sector 408

end_request: I/O error, dev hda, sector 416

end_request: I/O error, dev hda, sector 424

end_request: I/O error, dev hda, sector 432

end_request: I/O error, dev hda, sector 440

end_request: I/O error, dev hda, sector 448

end_request: I/O error, dev hda, sector 456

end_request: I/O error, dev hda, sector 464

end_request: I/O error, dev hda, sector 472

end_request: I/O error, dev hda, sector 480

end_request: I/O error, dev hda, sector 488

end_request: I/O error, dev hda, sector 496

end_request: I/O error, dev hda, sector 504

end_request: I/O error, dev hda, sector 0

read() failed: Input/output error
bash-3.00# 

[-- Attachment #3: ibm_ocp_ide.c --]
[-- Type: application/octet-stream, Size: 16736 bytes --]

/*
*    IDE Driver Based on ocp_stbxxxx.c
*/

#include <linux/types.h>
#include <linux/hdreg.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <asm/ocp.h>
#include <asm/io.h>
#include <asm/scatterlist.h>
#include <asm/ppc4xx_dma.h>

#include "ide_modes.h"

#define IDEVR			"1.0"


#define TRUE  1
#define FALSE 0

#define IN_BYTE(p)             (byte)inb_p(p)
#define OUT_BYTE(b,p)          outb((b),(p))

typedef unsigned int ide_ioreg_t;

static int pio_mode[2] = { -1, -1 };

ppc_dma_ch_t dma_ch;

/* use DMA channel 2 for IDE DMA operations */
#define IDE_DMACH	2	/* 2nd DMA channel */
#define IDE_DMA_INT	6	/* IDE dma channel 2 interrupt */


//#define WMODE	1		/* default to DMA line mode */
#define PIOMODE	0
static volatile unsigned long dmastat;

/* Function Prototypes */
static void ocp_ide_tune_drive(ide_drive_t *, byte);
static byte ocp_ide_dma_2_pio(byte);
static int ocp_ide_tune_chipset(ide_drive_t *, byte);
static int ocp_ide_dma_on(ide_drive_t *drive);
static void ocp_dma_exec_cmd (ide_drive_t * const drive, u8 command);

static void
ocp_ide_tune_drive(ide_drive_t * drive, byte pio)
{
	pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
	printk("ocp_ide_tune_drive pio %d\n",pio);
}

static byte
ocp_ide_dma_2_pio(byte xfer_rate)
{
	switch (xfer_rate) {
	case XFER_UDMA_5:
	case XFER_UDMA_4:
	case XFER_UDMA_3:
	case XFER_UDMA_2:
	case XFER_UDMA_1:
	case XFER_UDMA_0:
	case XFER_MW_DMA_2:
	case XFER_PIO_4:
		return 4;
	case XFER_MW_DMA_1:
	case XFER_PIO_3:
		return 3;
	case XFER_SW_DMA_2:
	case XFER_PIO_2:
		return 2;
	case XFER_MW_DMA_0:
	case XFER_SW_DMA_1:
	case XFER_SW_DMA_0:
	case XFER_PIO_1:
	case XFER_PIO_0:
	case XFER_PIO_SLOW:
	default:
		return 0;
	}
}

static int
ocp_ide_tune_chipset(ide_drive_t * drive, byte speed)
{
	int err = 0;

	printk("ocp_ide_tune_chipset speed %d\n",speed);
	ocp_ide_tune_drive(drive, ocp_ide_dma_2_pio(speed));

	if (!drive->init_speed)
		drive->init_speed = speed;
	err = ide_config_drive_speed(drive, speed);
	drive->current_speed = speed;
	printk("ocp_ide_tune_chipset speed %d\n",speed);
	return err;
}

static int
redwood_config_drive_for_dma(ide_drive_t * drive)
{
	struct hd_driveid *id = drive->id;
	byte speed;

	/*
	 * Enable DMA on any drive that has multiword DMA
	 */
	if (id->field_valid & 2) {
		if (id->dma_mword & 0x0004) {
			speed = XFER_MW_DMA_2;
		} else if (id->dma_mword & 0x0002) {
			speed = XFER_MW_DMA_1;
		} else if (id->dma_mword & 1) {
			speed = XFER_MW_DMA_0;
		} else if (id->dma_1word & 0x0004) {
			speed = XFER_SW_DMA_2;
		} else {
			speed = XFER_PIO_0 +
			    ide_get_best_pio_mode(drive, 255, 5, NULL);
		}
	}
	printk("redwood_config_drive_for_dma %x\n",speed);
	ocp_ide_tune_drive(drive, ocp_ide_dma_2_pio(speed));
	return  ocp_ide_dma_on(drive);
}



int
ocp_ide_dma_intr(int irq, void *dev_id, struct pt_regs *regs)
{
	unsigned long flags;
	unsigned long tmp;
	
	local_irq_save(flags);
	//dmastat = ppc4xx_get_dma_status();
	dmastat = mfdcr(DCRN_DMASR);
#ifdef  WMODE
	if (dmastat & 0x1000) {
		//This should not happen at least in Word Mode, I have noticed this. Is it some timing problem ?
		printk
		    ("ocp_ide_dma_intr dma req pending from external device\n");
	}
#endif

	//mtdcr(DCRN_DMASR, ((u32)DMA_CH2_ERR | (u32)DMA_CS2 | (u32)DMA_TS2));
	mtdcr(DCRN_DMASR,0x22211120);

	/* disable DMA */
	/*uicdcr = mfdcr (DCRN_UIC_PR (UIC0));
	uicdcr &= ~(0x80000000ul >> IDE_DMA_INT);
	mtdcr (DCRN_UIC_PR(UIC0), uicdcr);
	mtdcr (DCRN_UIC_TR(UIC0),
        mfdcr (DCRN_UIC_TR (UIC0)) | (0x80000000ul >> IDE_DMA_INT));
	*/
	//ppc4xx_disable_dma_interrupt(IDE_DMACH);
	tmp = mfdcr(DCRN_DMASR);
	mtdcr (DCRN_UIC_SR(UIC0),(0x80000000ul >> IDE_DMA_INT));
	printk("GOT DMA interrupt %x %x\n",dmastat,tmp);
	local_irq_restore(flags);
	return 0;
	//ppc4xx_clr_dma_status(IDE_DMACH);
}

void
ibm25xx_ide_spinup(int index)
{
	int i,j;
	ide_ioreg_t *io_ports;

	printk("ide_redwood: waiting for drive ready..");
	io_ports = ide_hwifs[index].io_ports;

	/* wait until drive is not busy (it may be spinning up) */
	for (i = 0; i < 30; i++) {
		unsigned char stat;
		stat = inb_p(io_ports[7]);
		/* wait for !busy & ready */
		if ((stat & 0x80) == 0) {
			break;
		}
		for(j=0;j<10;j++)
			udelay(1000 * 100);	/* 1 second */
	}

	printk("..");

	/* select slave */
	outb_p(0xa0 | 0x10, io_ports[6]);

	for (i = 0; i < 30; i++) {
		unsigned char stat;
		stat = inb_p(io_ports[7]);
		/* wait for !busy & ready */
		if ((stat & 0x80) == 0) {
			break;
		}

		for(j=0;j<10;j++)
			udelay(1000 * 100);	/* 1 second */
	}

	printk("..");

	outb_p(0xa0, io_ports[6]);
	printk("Drive spun up \n");
}

static int ocp_ide_dma_off(ide_drive_t *drive){

	printk("got ocp_ide_dma_off\n");
	return 0;;
}
static int ocp_ide_dma_off_quietly(ide_drive_t *drive){
	printk("got ocp_ide_dma_off_quietly\n");
	return 0;
}
static int ocp_ide_dma_on(ide_drive_t *drive){
	ide_hwif_t *hwif = HWIF(drive);
	int i, reading = 0;
	struct request *rq = HWGROUP(drive)->rq;
	unsigned long flags;
	unsigned long length;


		printk("got ocp_ide_dma_on\n");
#if PIOMODE
		return 1;
#endif

		mtdcr(DCRN_DMACR2, 0);
		ppc4xx_clr_dma_status(IDE_DMACH);

		/*save_flags(flags);
		cli();
		if (request_irq (IDE_DMA_INT, &ocp_ide_dma_intr, SA_INTERRUPT,"IDE-DMA", hwif->hwgroup)) {
			printk("ide_redwood6: ide_request_irq failed int=%d\n", IDE_DMA_INT);
			//restore_flags(flags);
			//return 1;
		}
		restore_flags(flags);
		*/

		drive->using_dma = 1;
#ifdef WMODE
		mtdcr(DCRN_DCRXBCR, 0);
		mtdcr(DCRN_CICCR, mfdcr(DCRN_CICCR) | 0x00000400);
#else
		/* Configure CIC reg for line mode dma */
		mtdcr(DCRN_CICCR, mfdcr(DCRN_CICCR) & ~0x00000400);
#endif
		return 0;
}
static int ocp_ide_dma_check(ide_drive_t *drive){

	printk("got ocp_ide_dma_check\n");
	return redwood_config_drive_for_dma(drive);
}

static void ocp_ide_dma_begin(ide_drive_t *drive){
int i,reading=0,length;
struct request * const rq = HWGROUP(drive)->rq;
unsigned long control;

	if(rq_data_dir (rq) == READ) reading = 1;

	printk("got ocp_ide_dma_begin 0x%x\n",mfdcr(DCRN_DMASR));
	/* enable DMA */
	ppc4xx_enable_dma_interrupt(IDE_DMACH);
	/*dmastat = mfdcr(DCRN_DMASR);
	mtdcr(DCRN_DMASR,((u32)DMA_CH2_ERR | (u32)DMA_CS2 | (u32)DMA_TS2));
	*/
	mtdcr(DCRN_DMASR,0x22200120);
	/*Configure CIC reg for line mode DMA*/
#ifdef WMODE
	mtdcr(DCRN_CICCR,(mfdcr(DCRN_CICCR) | 0x00000400));
#else
	mtdcr(DCRN_CICCR,(mfdcr(DCRN_CICCR) & ~0x00000400));

#endif

	if(drive->media != ide_disk) {
		printk("ocp_ide_dma_begin : Invalid media \n");
		return;
	}
	if(ppc4xx_get_channel_config(IDE_DMACH,&dma_ch) & DMA_CHANNEL_BUSY){
			printk("DMA channel busy \n");
			return;
	}
	memset(rq->buffer,0,rq->current_nr_sectors*512);
	if(reading){
		
		dma_cache_inv((unsigned long) rq->buffer, rq->current_nr_sectors * 512);
#ifdef WMODE
		mtdcr(DCRN_DMASA2,(u32)0x00000000);// set src address for DMA channel 2
		mtdcr(DCRN_DMADA2,(u32)virt_to_bus(rq->buffer));//set dst address for DMA channel 2
		mtdcr(DCRN_DCRXBCR,0x00000000);
		control = 0xE600CB02;
#else
		mtdcr(DCRN_DMASA2,(u32)0xfce00000);// set src address for DMA channel 2
		mtdcr(DCRN_DMADA2,(u32)virt_to_bus(rq->buffer));//set dst address for DMA channel 2
		mtdcr(DCRN_DCRXBCR,0x90000000);
		control = 0xEE602b02;
#endif
	}
	else {
		dma_cache_wback_inv((unsigned long) rq->buffer, rq->current_nr_sectors * 512);

#ifdef WMODE
		mtdcr(DCRN_DMASA2,(u32)0x00000000);// set dst address for DMA channel 2
		mtdcr(DCRN_DMADA2,(u32)virt_to_bus(rq->buffer));// set src address for DMA channel 2
		mtdcr(DCRN_DCRXBCR,0x00000000);
		control = 0xC600CB02;
#else
		mtdcr(DCRN_DMADA2,(u32)0xfce00000);// set dst address for DMA channel 2
		mtdcr(DCRN_DMASA2,(u32)virt_to_bus(rq->buffer));// set src address for DMA channel 2
		mtdcr(DCRN_DCRXBCR,0xB0000000);
		control = 0xcd602b02;
#endif

	}

#ifdef WMODE
	length = (rq->current_nr_sectors *512)/2;
#else
	length = (rq->current_nr_sectors *512)/16;
#endif
	mtdcr(DCRN_DMACT2,length);

	/*control = mfdcr(DCRN_DMACR2);
	control |= DMA_CIE_ENABLE;	 Channel Interrupt Enable 
	*/
	control &= ~DMA_CIE_ENABLE;
	mtdcr(DCRN_DMACR2, control);
	//ppc4xx_enable_dma_interrupt(IDE_DMACH);
	
	printk("DMA addr %x %x count %d dmastat %x\n",rq->buffer,virt_to_bus(rq->buffer),rq->current_nr_sectors,dmastat);
	/* wait for dma to complete (channel 2 terminal count) */
	for (i = 0; i < 500000; i++) {
		if(i%1000 == 0)
			dmastat = mfdcr(DCRN_DMASR);
		if (dmastat & DMA_CS2)
			break;
	}
	printk("DMA complete stat %x %d\n",dmastat,i);
	mtdcr(DCRN_DCRXBCR,0x00000000);
	mtdcr(DCRN_DMACR2, 0x00000000);
	drive->waiting_for_dma = 0;
	//dmastat = 0;
}
static int ocp_ide_dma_end(ide_drive_t *drive){
unsigned int tmp = mfdcr(DCRN_DMASR);

	mtdcr (DCRN_UIC_SR(UIC0),(0x80000000ul >> IDE_DMA_INT));
	mtdcr(DCRN_DMASR,0x22200120);
	dmastat = mfdcr(DCRN_DMASR);
	printk("got ocp_ide_dma_end %x %x\n",dmastat,tmp);
	drive->waiting_for_dma = 0;
	/* disable DMA */
	//ppc4xx_disable_dma_interrupt(IDE_DMACH);

	return 0;
}
static int ocp_ide_dma_test_irq(ide_drive_t *drive){

	printk("got ocp_ide_dma_test_irq\n");
	return 1;	/* returns 1 if dma irq issued, 0 otherwise */
}
static int ocp_ide_dma_verbose(ide_drive_t *drive){

	printk("got ocp_ide_dma_verbose\n");
	return 1;
}
static int ocp_ide_dma_lostirq(ide_drive_t *drive){


	printk("got ocp_ide_dma_lostirq\n");
	return 1;
}
static int ocp_ide_dma_timeout(ide_drive_t *drive){

	printk("got ocp_ide_dma_timeout\n");
	return 1;
}
static void
ocp_dma_exec_cmd (ide_drive_t * const drive, u8 command){
ide_hwif_t *hwif = HWIF(drive);

	//hwif->OUTBSYNC(drive,command, IDE_COMMAND_REG);
	//printk("ide_dma_exec_cmd %x\n",command);
	ide_execute_command (drive, command,&ide_dma_intr, 2*WAIT_CMD, NULL);
}
static int ocp_ide_dma_setup(ide_drive_t * const drive){
	ide_hwif_t 	* const hwif = HWIF(drive);
	struct request * const rq = HWGROUP(drive)->rq;

	printk("got ocp_ide_dma_setup \n");
	/*if(rq->current_nr_sectors < 2){
		printk("request for less no of sectors %d\n",rq->current_nr_sectors);
		ide_map_sg(drive,rq);drive->waiting_for_dma=0; 
		return 1;
	}*/
	drive->waiting_for_dma = 1;
	return 0;
}	


static void
ocp_ide_setup_dma (ide_hwif_t * const hwif)
{
	printk("ocp_ide_setup_dma \n");


	hwif->dma = IDE_DMACH;
#ifdef WMODE
   /*Word Mode psc(11-12)=00,pwc(13-18)=000110, phc(19-21)=010, 22=1, 30=1  ----  0xCB02*/

	dma_ch.mode	=TM_S_MM;	  /* xfer from peripheral to mem */
	dma_ch.td	= DMA_TD;
	dma_ch.buffer_enable = FALSE;
	dma_ch.tce_enable = FALSE;
	dma_ch.etd_output = FALSE;
	dma_ch.pce = FALSE;
	dma_ch.pl = EXTERNAL_PERIPHERAL;    /* no op */
	dma_ch.pwidth = PW_16;
	dma_ch.dai = TRUE;
	dma_ch.sai = FALSE;
	dma_ch.psc = 0;                      /* set the max setup cycles */
	dma_ch.pwc = 6;                     /* set the max wait cycles  */
	dma_ch.phc = 2;                      /* set the max hold cycles  */
	dma_ch.cp = PRIORITY_LOW;
	dma_ch.int_enable = FALSE;
	dma_ch.ch_enable = FALSE;		/* No chaining */
	dma_ch.tcd_disable = TRUE;		/* No chaining */
#else
/*Line Mode psc(11-12)=00,pwc(13-18)=000001, phc(19-21)=010, 22=1, 30=1  ----  0x2B02*/

	dma_ch.mode	=DMA_MODE_MM_DEVATSRC;	  /* xfer from peripheral to mem */
	dma_ch.td	= DMA_TD;
	dma_ch.buffer_enable = FALSE;
	dma_ch.tce_enable = FALSE;
	dma_ch.etd_output = FALSE;
	dma_ch.pce = FALSE;
	dma_ch.pl = EXTERNAL_PERIPHERAL;    /* no op */
	dma_ch.pwidth = PW_64;		/* Line mode on stbs */
	dma_ch.dai = TRUE;
	dma_ch.sai = FALSE;
	dma_ch.psc = 0;                      /* set the max setup cycles */
	dma_ch.pwc = 1;                     /* set the max wait cycles  */
	dma_ch.phc = 2;                      /* set the max hold cycles  */
	dma_ch.cp = PRIORITY_LOW;
	dma_ch.int_enable = FALSE;
	dma_ch.ch_enable = FALSE;		/* No chaining */
	dma_ch.tcd_disable = TRUE;		/* No chaining */

#endif
	if (ppc4xx_init_dma_channel(IDE_DMACH, &dma_ch) != DMA_STATUS_GOOD){
		printk("ppc4xx_init_dma_channel failed\n");
        	return -EBUSY;
	}
	//ppc4xx_disable_dma_interrupt(IDE_DMACH);

	/*init CIC control register to enable IDE interface PIO mode*/
	mtdcr(DCRN_CICCR,(mfdcr(DCRN_CICCR) & 0xffff7bff) | 0x00000003);
	mtdcr(DCRN_DMACR2, 0);
	ppc4xx_clr_dma_status(IDE_DMACH);
	/* init CIC select2 reg to connect external DMA port 3 to internal
	 * DMA channel 2

	 */
	mtdcr(DCRN_DMAS2,(mfdcr(DCRN_DMAS2) & 0xfffffff0) | 0x00000002);


	hwif->autodma = 1;hwif->udma_four=0;
	hwif->drives[0].autotune = hwif->drives[1].autotune = IDE_TUNE_AUTO;
	hwif->drives[0].autodma  = hwif->drives[1].autodma  = hwif->autodma;

	hwif->atapi_dma  = 0;
	hwif->ultra_mask = hwif->udma_four ? 0x1f : 0x07;
	hwif->mwdma_mask = 0x07;
	hwif->swdma_mask = 0x00;

	/* set everything to something != NULL */
	hwif->ide_dma_host_off		 = &ocp_ide_dma_off_quietly;
	hwif->ide_dma_host_on  		 = &ocp_ide_dma_on;

	hwif->ide_dma_check		 = &ocp_ide_dma_check;
	hwif->ide_dma_off_quietly 	 = &ocp_ide_dma_off_quietly;
	hwif->ide_dma_on          	 = &ocp_ide_dma_on;

	hwif->dma_setup   		 = &ocp_ide_dma_setup;
	hwif->dma_exec_cmd 		 = &ocp_dma_exec_cmd;
	hwif->dma_start    		 = &ocp_ide_dma_begin;
	hwif->ide_dma_end 		 = &ocp_ide_dma_end;

	hwif->ide_dma_test_irq		 = &ocp_ide_dma_test_irq;

	hwif->ide_dma_lostirq 		 = &ocp_ide_dma_lostirq;
	hwif->ide_dma_timeout 		 = &ocp_ide_dma_timeout;
}
		
static int __init
stb025xx_ide_probe (struct ocp_device * const ocp)
{
	int                     err;
	unsigned int            uicdcr;
	volatile unsigned long	ide_regs;
	unsigned long           flags,ioaddr;
	ide_hwif_t             * const hwif = &ide_hwifs[0];
	unsigned char          * ip;
	int                     i;

	printk ("IBM STB025xx OCP IDE driver version %s %x \n", IDEVR,ocp->def->paddr);
	if (!request_region(REDWOOD_IDE_CMD, 0x10, "IDE"))
		return -EBUSY;

	if (!request_region(REDWOOD_IDE_CTRL, 2, "IDE")) {
		release_region(REDWOOD_IDE_CMD, 0x10);
		return -EBUSY;
	}

	ide_regs = ioaddr = (unsigned long) ioremap(REDWOOD_IDE_CMD, 0x10);

	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
		hwif->io_ports[i] = ioaddr;
		ioaddr += 2;
	}
	hwif->io_ports[IDE_CONTROL_OFFSET] =
	    (unsigned long) ioremap(REDWOOD_IDE_CTRL, 2);

	ocp_force_power_on (ocp);
	
	/* initialize */
	hwif->gendev.parent = &ocp->dev;
	ocp_set_drvdata (ocp, hwif);

	/* setup MMIO ops */
	default_hwif_mmiops (hwif);

	/* tell common code _not_ to mess with resources */
	hwif->mmio = 2;
	ide_set_hwifdata (hwif, (void *) ide_regs);
	
	hwif->chipset = ide_generic;
	hwif->irq     = IDE0_IRQ;
	hwif->noprobe = 0;
	hwif->hold    = 1;
	hwif->udma_four = 0;
	hwif->tuneproc  = &ocp_ide_tune_drive;
	hwif->speedproc = &ocp_ide_tune_chipset;
	hwif->drives[0].io_32bit = hwif->drives[1].io_32bit = 0;
	hwif->drives[0].unmask   = hwif->drives[1].unmask   = 1;
	pio_mode[0] = pio_mode[1] = -1;
	
	ibm25xx_ide_spinup(0);
	ocp_ide_setup_dma (hwif);
	probe_hwif_init (hwif);

	create_proc_ide_interfaces ();
	printk("IDE probe finished \n");
	return 0;
}

static void
stb025xx_ide_remove (struct ocp_device * const ocp)
{
	ide_hwif_t             * const hwif = ocp_get_drvdata (ocp);

	hwif->dmatable_cpu = NULL;
	hwif->dmatable_dma = 0;

	ide_unregister (hwif->index);
	ocp_force_power_off (ocp);
}


static struct ocp_device_id stb025xx_ide_ids[] __devinitdata =
{
        { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IDE},
        { .vendor = OCP_VENDOR_INVALID }
};

MODULE_DEVICE_TABLE (ocp, stb04xxx_ide_ids);

static struct ocp_driver stb025xx_ide_driver = {
	.name     = "ide",
	.id_table = stb025xx_ide_ids,
	.probe    = stb025xx_ide_probe,
	.remove   = __devexit_p (stb025xx_ide_remove),
#if defined(CONFIG_PM)
	.suspend  = NULL,
	.resume   = NULL,
#endif
};



int __init
stb025xx_ide_init (void)
{
	printk("inside stb04xxx_ide_init \n");
	return ocp_register_driver (&stb025xx_ide_driver);
}

static void __exit
stb025xx_ide_exit (void)
{
	printk("inside stb04xxx_ide_exit \n");
	ocp_unregister_driver (&stb025xx_ide_driver);
}

/* needs to be called after ide has been initialized */
late_initcall (stb025xx_ide_init);
module_exit (stb025xx_ide_exit);

MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("Akhilesh Soni <akhilesh@innomedia.soft.net>");
MODULE_DESCRIPTION ("driver for IBM OCP IDE on STB025xx");

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2006-09-13 11:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-13 11:11 IDE DMA Issue ppc Akhilesh

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).