[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Help?? SATA problems when trying to add WD Sharespace support to kernel



Hi there,

I'm a n00b at kernel hacking, though I have about 10 years software experience and I've been running debian on ARM devices for a few years now. I'm trying to get a modern kernel to boot on a WD Sharespace at the moment and would appreciate some advice/help.

Background -

WD sell a 4TB NAS box called the sharespace. Inside it's running a WD customised (I think) version of the Marvell kernel tree, version 2.6.12, on a 500MHz feroceon core, 88F5281. It has 128MB RAM, 16MB of NOR flash, 4 SATA ports, gigabit ethernet and 3 usb ports. SATA is done by a Marvell 88SX7042 on the PCI bus.

I decided it was slow and limited and wanted to try and at least fix the limited part. Debian chroot images wouldn't work because the kernel was too old, or (in the case of sarge, I went back a way) the ABI was incompatible. So I embarked on the foolish errand of trying to make the current squeeze kernel boot on the box.

Thanks to some advice and a tutorial link from Martin M and some poking around with a multimeter I have made progress -

Serial access via a pulled apart nokia USB -> serial cable
Kernel for orion5x built on a sheevaplug because my attempt at cross compilation failed
uboot environment tweaked to read uImage from a hard disk
Kernel booting, RTC, USB, UART(s), NOR and ethernet initialised and loaded (modules for ehci and other devices built in to kernel)
PCI... mostly initialised, SATA not really working

That's the bit I need help on. I've attached my sharespace-setup.c file that handles the device initialisation, modelled on the other files in arch/arm/mach-orion5x with values taken from the Marvell/WD source, and the kernel console output and would be grateful for any advice on how to fix what is going on.

In short - everything seems to go fine until it tries to speak to the hard disk, where it recognises the drive and then fails to do... something -



[   28.126559] ata4: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
[   28.147053] ata4.00: ATA-6: ST9402115AS, 3.01, max UDMA/100
[   28.152616] ata4.00: 78140160 sectors, multi 0: LBA48 NCQ (depth 1)
[   28.177148] ata4.00: configured for UDMA/100
[   28.182020] scsi 3:0:0:0: Direct-Access     ATA      ST9402115AS      3.01 PQ: 0 ANSI: 5
[   28.191070] sd 3:0:0:0: [sda] 78140160 512-byte logical blocks: (40.0 GB/37.2 GiB)
[   28.199976] sd 3:0:0:0: [sda] Write Protect is off
[   28.205046] sd 3:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[   28.215561]  sda:
[   58.816573] ata4.00: exception Emask 0x0 SAct 0x1 SErr 0x0 action 0x6 frozen
[   58.823799] ata4.00: failed command: READ FPDMA QUEUED
[   58.828985] ata4.00: cmd 60/08:00:00:00:00/00:00:00:00:00/40 tag 0 ncq 4096 in
[   58.829002]          res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x4 (timeout)
[   58.843761] ata4.00: status: { DRDY }
[   58.847458] ata4: hard resetting link


Anyone seen this before? It goes on like that for a while, setting slower UDMA modes before finally admitting defeat.
Is there anything desperately wrong with what I've done so far?

The only weirdnesses I've encountered otherwise are -
1. The Marvell/WD source claims to have three PCI slots, but if I set the .nr_controllers field of the pci struct to 2 or 3 the machine just sits there after " Uncompressing Linux... done, booting the kernel" and does nothing, so I only initialise PCI 0

2. The kernel console output says that the ata controllers are using irq 44, which I can see further up is the irq for the (uninitialised) pci slots 1 and 2...
I've tried returning the slot 0 irq for the other slot and it doesn't help at all. Same console output.

Right, I've written a lot here and if you;ve read this far then thanks. This is most frustrating as it feels like the final hurdle before I can mount the root partition and run the second stage debootstrap...


Dave.
/*
 * WD Sharespace setup
 *
 * Maintainer:
 *
 * 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
#include <linux/irq.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/nand.h>
#include <linux/mv643xx_eth.h>
#include <linux/ethtool.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/i2c.h>
#include <linux/serial_reg.h>
#include <linux/ata_platform.h>
#include <asm/mach-types.h>
#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/pci.h>
#include <mach/orion5x.h>
#include "common.h"
#include "mpp.h"

/*
 * 16MB NOR flash Device bus boot chip select
 */

#define SHARESPACE_NOR_BOOT_BASE 0xff000000
#define SHARESPACE_NOR_BOOT_SIZE SZ_16M

/****************************************************************************
 * 16MiB NOR flash. The struct mtd_partition is not in the same order as the
 *     partitions on the device because we want to keep compatability with
 *     existing WD firmware.
 *
 * 0x00ca0000-0x00cc0000 : "Env-Var"
 * 0x00e80000-0x00f80000 : "Pre-RootFS"
 * 0x00cc0000-0x00e80000 : "Kernel"
 * 0x00000000-0x00ca0000 : "Full-RootFS"
 * 0x00f80000-0x01000000 : "U-Boot"
 *
 ***************************************************************************/
static struct mtd_partition sharespace_partitions[] = {
	{
		.name		= "U-Boot environment",
		.size		= 0x00020000,
		.offset		= 0x00ca0000,
		.mask_flags	= MTD_WRITEABLE,
	}, {
		.name		= "Pre-RootFS",
		.size		= 0x00100000,
		.offset		= 0x00e80000,
	}, {
		.name		= "Kernel",
		.size		= 0x001c0000,
		.offset		= 0x00cc0000,
	}, {
		.name		= "Full RootFS",
		.size		= 0x00ca0000,
		.offset		= 0x00000000,
	}, {
		.name		= "U-Boot",
		.size		= 0x00080000,
		.offset		= 0x00f80000,
		.mask_flags	= MTD_WRITEABLE,
	},
};

static struct physmap_flash_data sharespace_nor_flash_data = {
	.width		= 1,
	.parts		= sharespace_partitions,
	.nr_parts	= ARRAY_SIZE(sharespace_partitions)
};

static struct resource sharespace_nor_flash_resource = {
	.flags	= IORESOURCE_MEM,
	.start	= SHARESPACE_NOR_BOOT_BASE,
	.end	= SHARESPACE_NOR_BOOT_BASE + SHARESPACE_NOR_BOOT_SIZE - 1,
};

static struct platform_device sharespace_nor_flash = {
	.name		= "physmap-flash",
	.id		= 0,
	.dev		= { .platform_data = &sharespace_nor_flash_data, },
	.num_resources	= 1,
	.resource	= &sharespace_nor_flash_resource,
};

/*****************************************************************************
 * PCI Setup
 ****************************************************************************/

#define SHARESPACE_PCI_SLOT0_OFFS       7
#define SHARESPACE_PCI_SLOT0_IRQ_PIN    12
#define SHARESPACE_PCI_SLOT1_SLOT2_IRQ_PIN    13

void __init sharespace_pci_preinit(void)
{
	int pin;

	/*
	 * Configure PCI GPIO IRQ pins
	 */
	pin = SHARESPACE_PCI_SLOT0_IRQ_PIN;
	if (gpio_request(pin, "PCI Int0") == 0) {
		if (gpio_direction_input(pin) == 0) {
			set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
		} else {
			printk(KERN_ERR "sharespace_pci_preinit failed to "
					"set_irq_type pin %d\n", pin);
			gpio_free(pin);
		}
	} else {
		printk(KERN_ERR "sharespace_pci_preinit (slot 0) failed to gpio_request "
				"%d\n", pin);
        }
        
        pin = SHARESPACE_PCI_SLOT1_SLOT2_IRQ_PIN;
	if (gpio_request(pin, "PCI Int1") == 0) {
		if (gpio_direction_input(pin) == 0) {
			set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
		} else {
			printk(KERN_ERR "sharespace_pci_preinit failed to "
					"set_irq_type pin %d\n", pin);
			gpio_free(pin);
		}
	} else {
		printk(KERN_ERR "sharespace_pci_preinit (slot 0) failed to gpio_request "
				"%d\n", pin);
        }
}

static int __init sharespace_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
	int irq;

	/*
	 * Check for devices with hard-wired IRQs.
	 */
	irq = orion5x_pci_map_irq(dev, slot, pin);
	if (irq != -1)
	{
		printk("DAVE - sharespace returning mapped IRQ %d\n", irq); //this code not hit
		return irq; 
	}

	/*
	 * PCI IRQs are connected via GPIOs.
	 */
	switch (slot) { //- SHARESPACE_PCI_SLOT0_OFFS) { //this code is only ever hit with slot==0 and slot==1
	case 0:
		irq = gpio_to_irq(SHARESPACE_PCI_SLOT0_IRQ_PIN);
		printk("DAVE - sharespace IRQ PIN 0 - %d\n", irq);
		return irq;
	case 1:
	case 2:
		irq = gpio_to_irq(SHARESPACE_PCI_SLOT1_SLOT2_IRQ_PIN);
		printk("DAVE - sharespace IRQ PIN 1/2 - %d\n",irq);
		return irq;
	default:
		printk("DAVE - sharespace IRQ PIN miss on switch slot - %d\n",slot);
		return -1;
	}
}

static struct hw_pci sharespace_pci __initdata = {
	.nr_controllers	= 1,				//WD kernel code says 3, though 2 or 3 mean the box won't boot
	.preinit	= sharespace_pci_preinit,
	.swizzle	= pci_std_swizzle,
	.setup		= orion5x_pci_sys_setup,
	.scan		= orion5x_pci_sys_scan_bus,
	.map_irq	= sharespace_pci_map_irq,
};

static int __init sharespace_pci_init(void)
{
	printk("DAVE - sharespace_pci_init\n");
	if(machine_is_sharespace())
		pci_common_init(&sharespace_pci);
	return 0;
}

subsys_initcall(sharespace_pci_init);

/*****************************************************************************
 * RTC Setup
 ****************************************************************************/
#define SHARESPACE_RTC_GPIO  10

static struct i2c_board_info __initdata sharespace_i2c_rtc = {
        I2C_BOARD_INFO("pcf8563", 0x51),
};

/*****************************************************************************
 * Ethernet
 ****************************************************************************/

static struct mv643xx_eth_platform_data sharespace_eth_data = {
	.phy_addr	= MV643XX_ETH_PHY_ADDR(8), //0,8,16?
};

/*****************************************************************************
 * MPP Setup
 ****************************************************************************/
static struct orion5x_mpp_mode sharespace_mpp_modes[] __initdata = {
	{  0, MPP_GPIO },
	{  1, MPP_GPIO },		/* USB VBUS pin */
	{  2, MPP_GPIO },		// most of these are likely unused
	{  3, MPP_GPIO },
	{  4, MPP_GPIO },
	{  5, MPP_GPIO },
	{  6, MPP_GPIO },
	{  7, MPP_GPIO },
	{  8, MPP_GPIO },
	{  9, MPP_GPIO },
	{ 10, MPP_GPIO },		/* RTC int */
	{ 11, MPP_GPIO },		/* Unknown - According to Marvell/WD this is BOARD_DEV_REF_CLCK ?? */
	{ 12, MPP_GPIO },		/* PCI 0 */
	{ 13, MPP_GPIO },		/* PCI 1 - trying to activate kills boot ? */
	{ 14, MPP_GPIO },
	{ 15, MPP_GPIO },
	{ 16, MPP_UART },		/* UART1 RXD ?? */
	{ 17, MPP_UART },		/* UART1 TXD ?? */
	{ 18, MPP_UART },		/* UART1 RXD ?? */
	{ 19, MPP_UART },		/* UART1 TXD ?? */
	{ -1 },
};

/*****************************************************************************
 * General Setup
 ****************************************************************************/
 
static void __init sharespace_init(void)
{
	/*
	 * Setup basic Orion functions. Need to be called early.
	 */

	orion5x_init();
	
	orion5x_mpp_conf(sharespace_mpp_modes);
	//writel(0, MPP_DEV_CTRL);		/* DEV_D[31:16] *//* I have no idea what this does, other devices do it. Commented as it makes zero difference */
	
	/*
	 * Device initialisation
	 */
	 
	orion5x_uart0_init();
	orion5x_uart1_init();
	orion5x_ehci0_init();
	orion5x_eth_init(&sharespace_eth_data);
	orion5x_i2c_init();

	orion5x_setup_dev_boot_win(SHARESPACE_NOR_BOOT_BASE,
				   SHARESPACE_NOR_BOOT_SIZE);
	platform_device_register(&sharespace_nor_flash);
	
	/* Get RTC IRQ and register the chip*/
	if (gpio_request(SHARESPACE_RTC_GPIO, "rtc") == 0) {
		if (gpio_direction_input(SHARESPACE_RTC_GPIO) == 0)
		{
			printk("DAVE - gpio got\n");
			sharespace_i2c_rtc.irq = gpio_to_irq(SHARESPACE_RTC_GPIO);
		}
                else
                {
                	printk("DAVE - gpio free\n");
			gpio_free(SHARESPACE_RTC_GPIO);
		}
	}
	if (sharespace_i2c_rtc.irq == 0)
		pr_warning("sharespace_init: failed to get RTC IRQ\n");

	i2c_register_board_info(0, &sharespace_i2c_rtc, 1);

	printk("END DAVE SOURCE\n");
}

MACHINE_START(SHARESPACE, "WD Sharespace")
	.phys_io	= ORION5X_REGS_PHYS_BASE,
	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
	.boot_params	= 0x00000100,
	.init_machine	= sharespace_init,
	.map_io		= orion5x_map_io,
	.init_irq	= orion5x_init_irq,
	.timer		= &orion5x_timer,
	.fixup		= tag_fixup_mem32,
MACHINE_END

Reply to: