From: Imre Kaloz Date: Tue, 28 Jun 2011 06:54:20 +0000 (+0000) Subject: [cns3xxx]: ethernet cleanup and sata fix - thanks, Chris X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=commitdiff_plain;hb=2f5d171c28b7ccc302525ebdf25b4ef2b59f7fab [cns3xxx]: ethernet cleanup and sata fix - thanks, Chris SVN-Revision: 27297 --- diff --git a/target/linux/cns3xxx/config-default b/target/linux/cns3xxx/config-default index 4aebd22fb6..02a88ced0b 100644 --- a/target/linux/cns3xxx/config-default +++ b/target/linux/cns3xxx/config-default @@ -12,10 +12,10 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_ARM=y CONFIG_ARM_GIC=y CONFIG_ARM_L1_CACHE_SHIFT=5 -# CONFIG_ARM_PATCH_PHYS_VIRT is not set CONFIG_ARM_THUMB=y CONFIG_ATA=y # CONFIG_ATA_SFF is not set +CONFIG_ATA_VERBOSE_ERROR=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=2 CONFIG_BLK_DEV_RAM_SIZE=32768 @@ -47,7 +47,6 @@ CONFIG_DWC_OTG_MODE=y CONFIG_EEPROM_AT24=y CONFIG_FRAME_POINTER=y # CONFIG_FSNOTIFY is not set -# CONFIG_FTMAC100 is not set CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y @@ -101,7 +100,6 @@ CONFIG_LEDS_GPIO=y CONFIG_M25PXX_USE_FAST_READ=y CONFIG_MACH_CNS3420VB=y CONFIG_MACH_GW2388=y -# CONFIG_MFD_MAX8997 is not set CONFIG_MIGHT_HAVE_PCI=y CONFIG_MMC=y CONFIG_MMC_BLOCK=y @@ -134,6 +132,7 @@ CONFIG_RD_GZIP=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1672=y CONFIG_SATA_AHCI=y +CONFIG_SATA_AHCI_CNS3XXX=y CONFIG_SATA_AHCI_PLATFORM=y CONFIG_SCSI=y # CONFIG_SCSI_MULTI_LUN is not set diff --git a/target/linux/cns3xxx/patches/051-cns3xxx_gigabit.patch b/target/linux/cns3xxx/patches/051-cns3xxx_gigabit.patch index 9fc5c0db22..ddc499e773 100644 --- a/target/linux/cns3xxx/patches/051-cns3xxx_gigabit.patch +++ b/target/linux/cns3xxx/patches/051-cns3xxx_gigabit.patch @@ -27,7 +27,7 @@ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o --- /dev/null +++ b/drivers/net/cns3xxx_eth.c -@@ -0,0 +1,1233 @@ +@@ -0,0 +1,1269 @@ +/* + * Cavium CNS3xxx Gigabit driver for Linux + * @@ -51,41 +51,71 @@ +#include +#include + -+#define DRV_NAME "cns3xxx_eth" ++#define DRV_NAME "cns3xxx_eth" + -+#define RX_DESCS 512 -+#define TX_DESCS 512 -+#define SKB_DMA_REALIGN ((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES) ++#define RX_DESCS 512 ++#define TX_DESCS 512 ++#define SKB_DMA_REALIGN ((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES) + +#define RX_POOL_ALLOC_SIZE (sizeof(struct rx_desc) * RX_DESCS) +#define TX_POOL_ALLOC_SIZE (sizeof(struct tx_desc) * TX_DESCS) -+#define REGS_SIZE 0x150 -+#define MAX_MRU 9500 -+ -+#define NAPI_WEIGHT 64 ++#define REGS_SIZE 336 ++#define MAX_MRU 9500 ++ ++#define NAPI_WEIGHT 64 ++ ++/* MDIO Defines */ ++#define MDIO_CMD_COMPLETE 0x00008000 ++#define MDIO_WRITE_COMMAND 0x00002000 ++#define MDIO_READ_COMMAND 0x00004000 ++#define MDIO_REG_OFFSET 8 ++#define MDIO_VALUE_OFFSET 16 ++ ++/* Descritor Defines */ ++#define END_OF_RING 0x40000000 ++#define FIRST_SEGMENT 0x20000000 ++#define LAST_SEGMENT 0x10000000 ++#define FORCE_ROUTE 0x04000000 ++#define IP_CHECKSUM 0x00040000 ++#define UDP_CHECKSUM 0x00020000 ++#define TCP_CHECKSUM 0x00010000 + +/* Port Config Defines */ -+#define PORT_DISABLE (1 << 18) ++#define PORT_DISABLE 0x00040000 ++#define PROMISC_OFFSET 29 ++ ++/* Global Config Defines */ ++#define UNKNOWN_VLAN_TO_CPU 0x02000000 ++#define ACCEPT_CRC_PACKET 0x00200000 ++#define CRC_STRIPPING 0x00100000 ++ ++/* VLAN Config Defines */ ++#define NIC_MODE 0x00008000 ++#define VLAN_UNAWARE 0x00000001 + +/* DMA AUTO Poll Defines */ -+#define TS_POLL_EN (1 << 5) -+#define TS_SUSPEND (1 << 4) -+#define FS_POLL_EN (1 << 1) -+#define FS_SUSPEND (1 << 0) ++#define TS_POLL_EN 0x00000020 ++#define TS_SUSPEND 0x00000010 ++#define FS_POLL_EN 0x00000002 ++#define FS_SUSPEND 0x00000001 ++ ++/* DMA Ring Control Defines */ ++#define QUEUE_THRESHOLD 0x000000f0 ++#define CLR_FS_STATE 0x80000000 + +struct tx_desc +{ -+ u32 sdp; // segment data pointer ++ u32 sdp; /* segment data pointer */ + + union { + struct { -+ u32 sdl:16; // segment data length ++ u32 sdl:16; /* segment data length */ + u32 tco:1; + u32 uco:1; + u32 ico:1; -+ u32 rsv_1:3; // reserve ++ u32 rsv_1:3; /* reserve */ + u32 pri:3; -+ u32 fp:1; // force priority ++ u32 fp:1; /* force priority */ + u32 fr:1; + u32 interrupt:1; + u32 lsd:1; @@ -125,16 +155,16 @@ + u32 config2; + }; + -+ u8 alignment[16]; // for alignment 32 byte ++ u8 alignment[16]; /* for 32 byte */ +}; + +struct rx_desc +{ -+ u32 sdp; // segment data pointer ++ u32 sdp; /* segment data pointer */ + + union { + struct { -+ u32 sdl:16; // segment data length ++ u32 sdl:16; /* segment data length */ + u32 l4f:1; + u32 ipf:1; + u32 prot:4; @@ -179,12 +209,12 @@ + u32 config2; + }; + -+ u8 alignment[16]; // for alignment 32 byte ++ u8 alignment[16]; /* for 32 byte alignment */ +}; + + +struct switch_regs { -+ u32 phy_control; /* 000 */ ++ u32 phy_control; + u32 phy_auto_addr; + u32 mac_glob_cfg; + u32 mac_cfg[4]; @@ -289,22 +319,22 @@ + u32 temp = 0; + + temp = __raw_readl(&mdio_regs->phy_control); -+ temp |= (1 << 15); /* Clear Command Complete bit */ ++ temp |= MDIO_CMD_COMPLETE; + __raw_writel(temp, &mdio_regs->phy_control); + udelay(10); + + if (write) { -+ temp = (cmd << 16); -+ temp |= (1 << 13); /* Write Command */ ++ temp = (cmd << MDIO_VALUE_OFFSET); ++ temp |= MDIO_WRITE_COMMAND; + } else { -+ temp = (1 << 14); /* Read Command */ ++ temp = MDIO_READ_COMMAND; + } -+ temp |= ((location & 0x1f) << 8); ++ temp |= ((location & 0x1f) << MDIO_REG_OFFSET); + temp |= (phy_id & 0x1f); + + __raw_writel(temp, &mdio_regs->phy_control); + -+ while (((__raw_readl(&mdio_regs->phy_control) & 0x8000) == 0) ++ while (((__raw_readl(&mdio_regs->phy_control) & MDIO_CMD_COMPLETE) == 0) + && cycles < 5000) { + udelay(1); + cycles++; @@ -317,13 +347,13 @@ + } + + temp = __raw_readl(&mdio_regs->phy_control); -+ temp |= (1 << 15); /* Clear Command Complete bit */ ++ temp |= MDIO_CMD_COMPLETE; + __raw_writel(temp, &mdio_regs->phy_control); + + if (write) + return 0; + -+ return ((temp >> 16) & 0xFFFF); ++ return ((temp >> MDIO_VALUE_OFFSET) & 0xFFFF); +} + +static int cns3xxx_mdio_read(struct mii_bus *bus, int phy_id, int location) @@ -430,13 +460,11 @@ + desc->sdp = dma_map_single(NULL, skb->data, + mtu, DMA_FROM_DEVICE); + if (dma_mapping_error(NULL, desc->sdp)) { -+ printk("failed to map\n"); + dev_kfree_skb(skb); + /* Failed to map, better luck next time */ + goto out;; + } + } else { -+ printk("failed to alloc\n"); + /* Failed to allocate skb, try again next time */ + goto out; + } @@ -446,9 +474,10 @@ + + if (++i == RX_DESCS) { + i = 0; -+ desc->config0 = 0x70000000 | mtu; ++ desc->config0 = END_OF_RING | FIRST_SEGMENT | ++ LAST_SEGMENT | mtu; + } else { -+ desc->config0 = 0x30000000 | mtu; ++ desc->config0 = FIRST_SEGMENT | LAST_SEGMENT | mtu; + } + } +out: @@ -555,8 +584,6 @@ + if (++i == RX_DESCS) i = 0; + next_desc = &(rx_ring)->desc[i]; + prefetch(next_desc); -+ prefetch(next_desc + 4); -+ prefetch(next_desc + 8); + + port_id = desc->sp; + if (port_id == 4) @@ -666,9 +693,13 @@ + tx_ring->buff_tab[index] = skb; + + if (index == TX_DESCS - 1) { -+ tx_desc->config0 = 0x74070000 | len; ++ tx_desc->config0 = END_OF_RING | FIRST_SEGMENT | LAST_SEGMENT | ++ FORCE_ROUTE | IP_CHECKSUM | UDP_CHECKSUM | ++ TCP_CHECKSUM | len; + } else { -+ tx_desc->config0 = 0x34070000 | len; ++ tx_desc->config0 = FIRST_SEGMENT | LAST_SEGMENT | ++ FORCE_ROUTE | IP_CHECKSUM | UDP_CHECKSUM | ++ TCP_CHECKSUM | len; + } + + return NETDEV_TX_OK; @@ -725,14 +756,15 @@ + struct _rx_ring *rx_ring = sw->rx_ring; + struct _tx_ring *tx_ring = sw->tx_ring; + -+ __raw_writel(0x0, &sw->regs->fs_dma_ctrl0); -+ __raw_writel(0x11, &sw->regs->dma_auto_poll_cfg); -+ __raw_writel(0x000000f0, &sw->regs->dma_ring_ctrl); -+ __raw_writel(0x800000f0, &sw->regs->dma_ring_ctrl); ++ __raw_writel(0, &sw->regs->fs_dma_ctrl0); ++ __raw_writel(TS_SUSPEND | FS_SUSPEND, &sw->regs->dma_auto_poll_cfg); ++ __raw_writel(QUEUE_THRESHOLD, &sw->regs->dma_ring_ctrl); ++ __raw_writel(CLR_FS_STATE | QUEUE_THRESHOLD, &sw->regs->dma_ring_ctrl); + -+ __raw_writel(0x000000f0, &sw->regs->dma_ring_ctrl); ++ __raw_writel(QUEUE_THRESHOLD, &sw->regs->dma_ring_ctrl); + -+ if (!(rx_dma_pool = dma_pool_create(DRV_NAME, NULL, RX_POOL_ALLOC_SIZE, 32, 0))) ++ if (!(rx_dma_pool = dma_pool_create(DRV_NAME, NULL, ++ RX_POOL_ALLOC_SIZE, 32, 0))) + return -ENOMEM; + + if (!(rx_ring->desc = dma_pool_alloc(rx_dma_pool, GFP_KERNEL, @@ -766,7 +798,8 @@ + __raw_writel(rx_ring->phys_addr, &sw->regs->fs_desc_ptr0); + __raw_writel(rx_ring->phys_addr, &sw->regs->fs_desc_base_addr0); + -+ if (!(tx_dma_pool = dma_pool_create(DRV_NAME, NULL, TX_POOL_ALLOC_SIZE, 32, 0))) ++ if (!(tx_dma_pool = dma_pool_create(DRV_NAME, NULL, ++ TX_POOL_ALLOC_SIZE, 32, 0))) + return -ENOMEM; + + if (!(tx_ring->desc = dma_pool_alloc(tx_dma_pool, GFP_KERNEL, @@ -849,7 +882,7 @@ + __raw_writel(temp, &sw->regs->mac_cfg[2]); + + temp = __raw_readl(&sw->regs->dma_auto_poll_cfg); -+ temp &= ~(0x11); ++ temp &= ~(TS_SUSPEND | FS_SUSPEND); + __raw_writel(temp, &sw->regs->dma_auto_poll_cfg); + + __raw_writel((TS_POLL_EN | FS_POLL_EN), &sw->regs->dma_auto_poll_cfg); @@ -889,8 +922,8 @@ + temp |= (PORT_DISABLE); + __raw_writel(temp, &sw->regs->mac_cfg[2]); + -+ temp = 0x11; -+ __raw_writel(temp, &sw->regs->dma_auto_poll_cfg); ++ __raw_writel(TS_SUSPEND | FS_SUSPEND, ++ &sw->regs->dma_auto_poll_cfg); + } + + netif_carrier_off(dev); @@ -907,14 +940,14 @@ + + if (dev->flags & IFF_PROMISC) { + if (port->id == 3) -+ temp |= ((1 << 2) << 29); ++ temp |= ((1 << 2) << PROMISC_OFFSET); + else -+ temp |= ((1 << port->id) << 29); ++ temp |= ((1 << port->id) << PROMISC_OFFSET); + } else { + if (port->id == 3) -+ temp &= ~((1 << 2) << 29); ++ temp &= ~((1 << 2) << PROMISC_OFFSET); + else -+ temp &= ~((1 << port->id) << 29); ++ temp &= ~((1 << port->id) << PROMISC_OFFSET); + } + __raw_writel(temp, &sw->regs->mac_glob_cfg); +} @@ -1007,15 +1040,16 @@ + sw->mtu = new_mtu; + + /* Disable DMA */ -+ temp = 0x11; -+ __raw_writel(temp, &sw->regs->dma_auto_poll_cfg); ++ __raw_writel(TS_SUSPEND | FS_SUSPEND, &sw->regs->dma_auto_poll_cfg); + + for (i = 0; i < RX_DESCS; i++) { + desc = &(rx_ring)->desc[i]; -+ /* Check if we own it, if we do, it will get set correctly when it is re-used */ ++ /* Check if we own it, if we do, it will get set correctly ++ * when it is re-used */ + if (!desc->cown) { + skb = rx_ring->buff_tab[i]; -+ dma_unmap_single(NULL, desc->sdp, desc->sdl, DMA_FROM_DEVICE); ++ dma_unmap_single(NULL, desc->sdp, desc->sdl, ++ DMA_FROM_DEVICE); + dev_kfree_skb(skb); + + if ((skb = dev_alloc_skb(new_mtu))) { @@ -1034,15 +1068,17 @@ + rx_ring->buff_tab[i] = skb; + + if (i == RX_DESCS - 1) -+ desc->config0 = 0x70000000 | new_mtu; ++ desc->config0 = END_OF_RING | FIRST_SEGMENT | ++ LAST_SEGMENT | new_mtu; + else -+ desc->config0 = 0x30000000 | new_mtu; ++ desc->config0 = FIRST_SEGMENT | ++ LAST_SEGMENT | new_mtu; + } + } + + /* Re-ENABLE DMA */ + temp = __raw_readl(&sw->regs->dma_auto_poll_cfg); -+ temp &= ~(0x11); ++ temp &= ~(TS_SUSPEND | FS_SUSPEND); + __raw_writel(temp, &sw->regs->dma_auto_poll_cfg); + + __raw_writel((TS_POLL_EN | FS_POLL_EN), &sw->regs->dma_auto_poll_cfg); @@ -1105,11 +1141,11 @@ + __raw_writel(temp, &sw->regs->mac_cfg[2]); + + temp = __raw_readl(&sw->regs->vlan_cfg); -+ temp |= ((1 << 15) | (1 << 0)); ++ temp |= NIC_MODE | VLAN_UNAWARE; + __raw_writel(temp, &sw->regs->vlan_cfg); + -+ temp = 0x02300000; -+ __raw_writel(temp, &sw->regs->mac_glob_cfg); ++ __raw_writel(UNKNOWN_VLAN_TO_CPU | ACCEPT_CRC_PACKET | ++ CRC_STRIPPING, &sw->regs->mac_glob_cfg); + + if (!(sw->rx_ring = kmalloc(sizeof(struct _rx_ring), GFP_KERNEL))) { + err = -ENOMEM; diff --git a/target/linux/cns3xxx/patches/100-laguna_support.patch b/target/linux/cns3xxx/patches/100-laguna_support.patch index 574b8b3918..416b939457 100644 --- a/target/linux/cns3xxx/patches/100-laguna_support.patch +++ b/target/linux/cns3xxx/patches/100-laguna_support.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/arch/arm/mach-cns3xxx/laguna.c -@@ -0,0 +1,671 @@ +@@ -0,0 +1,761 @@ +/* + * Gateworks Corporation Laguna Platform + * @@ -201,11 +201,91 @@ + .name = "user2", /* Red Led */ + .gpio = 114, + .active_low = 1, ++ },{ ++ .name = "pwr1", /* Green Led */ ++ .gpio = 116, ++ .active_low = 1, ++ },{ ++ .name = "pwr2", /* Yellow Led */ ++ .gpio = 117, ++ .active_low = 1, ++ },{ ++ .name = "txd1", /* Green Led */ ++ .gpio = 118, ++ .active_low = 1, ++ },{ ++ .name = "txd2", /* Yellow Led */ ++ .gpio = 119, ++ .active_low = 1, ++ },{ ++ .name = "rxd1", /* Green Led */ ++ .gpio = 120, ++ .active_low = 1, ++ },{ ++ .name = "rxd2", /* Yellow Led */ ++ .gpio = 121, ++ .active_low = 1, ++ },{ ++ .name = "ser1", /* Green Led */ ++ .gpio = 122, ++ .active_low = 1, ++ },{ ++ .name = "ser2", /* Yellow Led */ ++ .gpio = 123, ++ .active_low = 1, ++ },{ ++ .name = "enet1", /* Green Led */ ++ .gpio = 124, ++ .active_low = 1, ++ },{ ++ .name = "enet2", /* Yellow Led */ ++ .gpio = 125, ++ .active_low = 1, ++ },{ ++ .name = "sig1_1", /* Green Led */ ++ .gpio = 126, ++ .active_low = 1, ++ },{ ++ .name = "sig1_2", /* Yellow Led */ ++ .gpio = 127, ++ .active_low = 1, ++ },{ ++ .name = "sig2_1", /* Green Led */ ++ .gpio = 128, ++ .active_low = 1, ++ },{ ++ .name = "sig2_2", /* Yellow Led */ ++ .gpio = 129, ++ .active_low = 1, ++ },{ ++ .name = "sig3_1", /* Green Led */ ++ .gpio = 130, ++ .active_low = 1, ++ },{ ++ .name = "sig3_2", /* Yellow Led */ ++ .gpio = 131, ++ .active_low = 1, ++ },{ ++ .name = "net1", /*Green Led */ ++ .gpio = 109, ++ .active_low = 1, ++ },{ ++ .name = "net2", /* Red Led */ ++ .gpio = 110, ++ .active_low = 1, ++ },{ ++ .name = "mod1", /* Green Led */ ++ .gpio = 111, ++ .active_low = 1, ++ },{ ++ .name = "mod2", /* Red Led */ ++ .gpio = 112, ++ .active_low = 1, + }, +}; + +static struct gpio_led_platform_data laguna_gpio_leds_data = { -+ .num_leds = 2, ++ .num_leds = 22, + .leds = laguna_gpio_leds, +}; + @@ -446,6 +526,12 @@ + +static struct pca953x_platform_data laguna_pca_data = { + .gpio_base = 100, ++ .irq_base = -1, ++}; ++ ++static struct pca953x_platform_data laguna_pca2_data = { ++ .gpio_base = 116, ++ .irq_base = -1, +}; + +static struct i2c_board_info __initdata laguna_i2c_devices[] = { @@ -453,6 +539,9 @@ + I2C_BOARD_INFO("pca9555", 0x23), + .platform_data = &laguna_pca_data, + },{ ++ I2C_BOARD_INFO("pca9555", 0x27), ++ .platform_data = &laguna_pca2_data, ++ },{ + I2C_BOARD_INFO("gsp", 0x29), + },{ + I2C_BOARD_INFO ("24c08",0x50), @@ -548,7 +637,8 @@ + if (laguna_net_data.ports) + platform_device_register(&laguna_net_device); + -+ if (laguna_info.config_bitmap & (SATA0_LOAD | SATA1_LOAD)) ++ if ((laguna_info.config_bitmap & SATA0_LOAD) || ++ (laguna_info.config_bitmap & SATA1_LOAD)) + cns3xxx_ahci_init(); + + if (laguna_info.config_bitmap & (PCIE0_LOAD)) @@ -640,9 +730,9 @@ + spi_register_board_info(laguna_spi_devices, ARRAY_SIZE(laguna_spi_devices)); + } + -+ if (laguna_info.config_bitmap & (SPI0_LOAD | SPI1_LOAD)) { ++ if ((laguna_info.config_bitmap & SPI0_LOAD) || ++ (laguna_info.config_bitmap & SPI1_LOAD)) + platform_device_register(&laguna_spi_controller); -+ } + + /* + * Do any model specific setup not known by the bitmap by matching @@ -650,13 +740,13 @@ + */ + + if (strncmp(laguna_info.model, "GW2388", 6) == 0) { -+ platform_device_register(&laguna_gpio_leds_device); ++ laguna_gpio_leds_data.num_leds = 2; + } else if (strncmp(laguna_info.model, "GW2380", 6) == 0) { + laguna_gpio_leds[0].gpio = 107; + laguna_gpio_leds[1].gpio = 106; + laguna_gpio_leds_data.num_leds = 2; -+ platform_device_register(&laguna_gpio_leds_device); + } ++ platform_device_register(&laguna_gpio_leds_device); + } else { + // Do some defaults here, not sure what yet + } diff --git a/target/linux/cns3xxx/patches/106-cns3xxx_sata_support.patch b/target/linux/cns3xxx/patches/106-cns3xxx_sata_support.patch new file mode 100644 index 0000000000..ce96f0ea4c --- /dev/null +++ b/target/linux/cns3xxx/patches/106-cns3xxx_sata_support.patch @@ -0,0 +1,190 @@ +--- a/arch/arm/mach-cns3xxx/devices.c ++++ b/arch/arm/mach-cns3xxx/devices.c +@@ -41,7 +41,7 @@ static struct resource cns3xxx_ahci_reso + static u64 cns3xxx_ahci_dmamask = DMA_BIT_MASK(32); + + static struct platform_device cns3xxx_ahci_pdev = { +- .name = "ahci", ++ .name = "ahci-cns3xxx", + .id = 0, + .resource = cns3xxx_ahci_resource, + .num_resources = ARRAY_SIZE(cns3xxx_ahci_resource), +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -83,6 +83,17 @@ config SATA_AHCI_PLATFORM + + If unsure, say N. + ++config SATA_AHCI_CNS3XXX ++ bool "AHCI Support on the Cavium Networks CNS3xxx SOC" ++ depends on ARCH_CNS3XXX ++ depends on SATA_AHCI_PLATFORM ++ help ++ This option enables AHCI platform driver to support CNS3xxx ++ System-on-Chip devices. This is only needed when using CNS3xxx AHCI ++ controller. ++ ++ If unsure, say N. ++ + config SATA_FSL + tristate "Freescale 3.0Gbps SATA support" + depends on FSL_SOC +--- a/drivers/ata/Makefile ++++ b/drivers/ata/Makefile +@@ -4,7 +4,10 @@ obj-$(CONFIG_ATA) += libata.o + # non-SFF interface + obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o + obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o +-obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o ++obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platforms.o libahci.o ++ahci_platforms-y += ahci_platform.o ++ahci_platforms-$(CONFIG_SATA_AHCI_CNS3XXX) += ahci_cns3xxx.o ++ + obj-$(CONFIG_SATA_FSL) += sata_fsl.o + obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o + obj-$(CONFIG_SATA_SIL24) += sata_sil24.o +--- /dev/null ++++ b/drivers/ata/ahci_cns3xxx.c +@@ -0,0 +1,52 @@ ++/* ++ * AHCI support for CNS3xxx SoC ++ * ++ * Copyright 2010 MontaVista Software, LLC. ++ * Copyright 2010 Cavium Networks ++ * ++ * Authors: Anton Vorontsov ++ * Mac Lin ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include "ahci.h" ++ ++/* ++ * TODO: move cns3xxx_ahci_init to here after cns3xxx_pwr*() calls are ++ * thread-safe ++ */ ++ ++static int cns3xxx_ahci_softreset(struct ata_link *link, unsigned int *class, ++ unsigned long deadline) ++{ ++ int pmp = sata_srst_pmp(link); ++ int ret; ++ ++ ret = ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready); ++ if (pmp && ret) ++ return ahci_do_softreset(link, class, 0, deadline, ++ ahci_check_ready); ++ return ret; ++} ++ ++static struct ata_port_operations cns3xxx_ahci_ops = { ++ .inherits = &ahci_ops, ++ .softreset = cns3xxx_ahci_softreset, ++}; ++ ++static const struct ata_port_info cns3xxx_ata_port_info = { ++ .flags = AHCI_FLAG_COMMON, ++ .pio_mask = ATA_PIO4, ++ .udma_mask = ATA_UDMA6, ++ .port_ops = &cns3xxx_ahci_ops, ++}; ++ ++struct ahci_platform_data cns3xxx_ahci_platform_data = { ++ .ata_port_info = &cns3xxx_ata_port_info, ++}; ++ +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -19,9 +19,11 @@ + #include + #include + #include ++#include + #include + #include + #include "ahci.h" ++#include "ahci_platform.h" + + static struct scsi_host_template ahci_platform_sht = { + AHCI_SHT("ahci_platform"), +@@ -29,6 +31,7 @@ static struct scsi_host_template ahci_pl + + static int __init ahci_probe(struct platform_device *pdev) + { ++ const struct platform_device_id *platid = platform_get_device_id(pdev); + struct device *dev = &pdev->dev; + struct ahci_platform_data *pdata = dev->platform_data; + struct ata_port_info pi = { +@@ -46,6 +49,9 @@ static int __init ahci_probe(struct plat + int i; + int rc; + ++ if (!pdata && platid && platid->driver_data) ++ pdata = (void *)platid->driver_data; ++ + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(dev, "no mmio space\n"); +@@ -171,17 +177,28 @@ static int __devexit ahci_remove(struct + return 0; + } + ++static const struct platform_device_id ahci_platform_ids[] = { ++ { "ahci", }, ++#ifdef CONFIG_SATA_AHCI_CNS3XXX ++ { "ahci-cns3xxx", (kernel_ulong_t)&cns3xxx_ahci_platform_data}, ++#endif ++ { }, ++}; ++MODULE_DEVICE_TABLE(platform, ahci_platform_ids); ++ + static struct platform_driver ahci_driver = { +- .remove = __devexit_p(ahci_remove), + .driver = { + .name = "ahci", + .owner = THIS_MODULE, + }, ++ .probe = ahci_probe, ++ .remove = __devexit_p(ahci_remove), ++ .id_table = ahci_platform_ids, + }; + + static int __init ahci_init(void) + { +- return platform_driver_probe(&ahci_driver, ahci_probe); ++ return platform_driver_register(&ahci_driver); + } + module_init(ahci_init); + +@@ -194,4 +211,3 @@ module_exit(ahci_exit); + MODULE_DESCRIPTION("AHCI SATA platform driver"); + MODULE_AUTHOR("Anton Vorontsov "); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("platform:ahci"); +--- /dev/null ++++ b/drivers/ata/ahci_platform.h +@@ -0,0 +1,19 @@ ++/* ++ * Copyright 2010 MontaVista Software, LLC. ++ * Copyright 2010 Cavium Networks ++ * ++ * Authors: Anton Vorontsov ++ * Mac Lin ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef _DRIVERS_SATA_AHCI_PLATFORMS_H ++#define _DRIVERS_SATA_AHCI_PLATFORMS_H ++ ++extern struct ahci_platform_data cns3xxx_ahci_platform_data; ++ ++#endif /*_DRIVERS_SATA_AHCI_PLATFORMS_H*/ ++