PKGBUILDs/core/linux-kirkwood/archlinuxarm.patch

3989 lines
102 KiB
Diff
Raw Normal View History

2012-07-18 15:14:04 +00:00
diff -urN a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
--- a/arch/arm/mach-kirkwood/dockstar-setup.c 2012-05-20 18:29:13.000000000 -0400
+++ b/arch/arm/mach-kirkwood/dockstar-setup.c 2012-05-24 12:02:12.000000000 -0400
@@ -19,7 +19,6 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/kirkwood.h>
-#include <plat/mvsdio.h>
#include "common.h"
#include "mpp.h"
@@ -33,6 +32,10 @@
.offset = MTDPART_OFS_NXTBLK,
.size = SZ_4M
}, {
+ .name = "pogoplug",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_32M
+ }, {
.name = "root",
.offset = MTDPART_OFS_NXTBLK,
.size = MTDPART_SIZ_FULL
@@ -45,17 +48,17 @@
static struct gpio_led dockstar_led_pins[] = {
{
- .name = "dockstar:green:health",
+ .name = "status:green:health",
.default_trigger = "default-on",
.gpio = 46,
.active_low = 1,
},
{
- .name = "dockstar:orange:misc",
+ .name = "status:orange:fault",
.default_trigger = "none",
.gpio = 47,
.active_low = 1,
- },
+ }
};
static struct gpio_led_platform_data dockstar_led_data = {
@@ -73,8 +76,8 @@
static unsigned int dockstar_mpp_config[] __initdata = {
MPP29_GPIO, /* USB Power Enable */
- MPP46_GPIO, /* LED green */
- MPP47_GPIO, /* LED orange */
+ MPP47_GPIO, /* LED Orange */
+ MPP46_GPIO, /* LED Green */
0
};
diff -urN a/arch/arm/mach-kirkwood/goflexhome-setup.c b/arch/arm/mach-kirkwood/goflexhome-setup.c
--- a/arch/arm/mach-kirkwood/goflexhome-setup.c 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/mach-kirkwood/goflexhome-setup.c 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,123 @@
+/*
+ * arch/arm/mach-kirkwood/goflexhome-setup.c
+ *
+ * Seagate GoFlex Home Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition goflexhome_nand_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0,
+ .size = SZ_1M
+ }, {
+ .name = "uImage",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_2M + SZ_4M
+ }, {
+ .name = "root",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL
+ },
+};
+
+static struct mv643xx_eth_platform_data goflexhome_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mv_sata_platform_data goflexhome_sata_data = {
+ .n_ports = 1,
+};
+
+static struct gpio_led goflexhome_led_pins[] = {
+ {
+ .name = "status:green:health",
+ .default_trigger = "default-on",
+ .gpio = 46,
+ .active_low = 1,
+ },
+ {
+ .name = "status:orange:fault",
+ .default_trigger = "none",
+ .gpio = 47,
+ .active_low = 1,
+ },
+ {
+ .name = "status:white:misc",
+ .default_trigger = "none",
+ .gpio = 40,
+ .active_low = 0,
+ }
+};
+
+static struct gpio_led_platform_data goflexhome_led_data = {
+ .leds = goflexhome_led_pins,
+ .num_leds = ARRAY_SIZE(goflexhome_led_pins),
+};
+
+static struct platform_device goflexhome_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &goflexhome_led_data,
+ }
+};
+
+static unsigned int goflexhome_mpp_config[] __initdata = {
+ MPP29_GPIO, /* USB Power Enable */
+ MPP47_GPIO, /* LED Orange */
+ MPP46_GPIO, /* LED Green */
+ MPP40_GPIO, /* LED White */
+ 0
+};
+
+static void __init goflexhome_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+
+ /* setup gpio pin select */
+ kirkwood_mpp_conf(goflexhome_mpp_config);
+
+ kirkwood_uart0_init();
+ kirkwood_nand_init(ARRAY_AND_SIZE(goflexhome_nand_parts), 40);
+
+ if (gpio_request(29, "USB Power Enable") != 0 ||
+ gpio_direction_output(29, 1) != 0)
+ printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
+ kirkwood_ehci_init();
+ kirkwood_ge00_init(&goflexhome_ge00_data);
+ kirkwood_sata_init(&goflexhome_sata_data);
+
+ platform_device_register(&goflexhome_leds);
+}
+
+MACHINE_START(GOFLEXHOME, "Seagate GoFlex Home")
+ /* Maintainer: Peter Carmichael <peterjncarm@ovi.com> */
+ .atag_offset = 0x100,
+ .init_machine = goflexhome_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
+
diff -urN a/arch/arm/mach-kirkwood/goflexnet-setup.c b/arch/arm/mach-kirkwood/goflexnet-setup.c
--- a/arch/arm/mach-kirkwood/goflexnet-setup.c 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/mach-kirkwood/goflexnet-setup.c 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,176 @@
+/*
+ * arch/arm/mach-kirkwood/goflexnet-setup.c
+ *
+ * Seagate GoFlex Net Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition goflexnet_nand_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0,
+ .size = SZ_1M
+ }, {
+ .name = "uImage",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_4M
+ }, {
+ .name = "pogoplug",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_32M
+ }, {
+ .name = "root",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL
+ },
+};
+
+static struct mv643xx_eth_platform_data goflexnet_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mv_sata_platform_data goflexnet_sata_data = {
+ .n_ports = 2,
+};
+
+static struct gpio_led goflexnet_led_pins[] = {
+ {
+ .name = "status:green:health",
+ .default_trigger = "default-on",
+ .gpio = 46, // 0x4000
+ .active_low = 1,
+ },
+ {
+ .name = "status:orange:fault",
+ .default_trigger = "none",
+ .gpio = 47, // 0x8000
+ .active_low = 1,
+ },
+ {
+ .name = "status:white:left0",
+ .default_trigger = "none",
+ .gpio = 42, // 0x0400
+ .active_low = 0,
+ },
+ {
+ .name = "status:white:left1",
+ .default_trigger = "none",
+ .gpio = 43, // 0x0800
+ .active_low = 0,
+ },
+ {
+ .name = "status:white:left2",
+ .default_trigger = "none",
+ .gpio = 44, // 0x1000
+ .active_low = 0,
+ },
+ {
+ .name = "status:white:left3",
+ .default_trigger = "none",
+ .gpio = 45, // 0x2000
+ .active_low = 0,
+ },
+ {
+ .name = "status:white:right0",
+ .default_trigger = "none",
+ .gpio = 38, // 0x0040
+ .active_low = 0,
+ },
+ {
+ .name = "status:white:right1",
+ .default_trigger = "none",
+ .gpio = 39, // 0x0080
+ .active_low = 0,
+ },
+ {
+ .name = "status:white:right2",
+ .default_trigger = "none",
+ .gpio = 40, // 0x0100
+ .active_low = 0,
+ },
+ {
+ .name = "status:white:right3",
+ .default_trigger = "none",
+ .gpio = 41, // 0x0200
+ .active_low = 0,
+ }
+};
+
+static struct gpio_led_platform_data goflexnet_led_data = {
+ .leds = goflexnet_led_pins,
+ .num_leds = ARRAY_SIZE(goflexnet_led_pins),
+};
+
+static struct platform_device goflexnet_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &goflexnet_led_data,
+ }
+};
+
+static unsigned int goflexnet_mpp_config[] __initdata = {
+ MPP29_GPIO, /* USB Power Enable */
+ MPP47_GPIO, /* LED Orange */
+ MPP46_GPIO, /* LED Green */
+ MPP45_GPIO, /* LED Left Capacity 3 */
+ MPP44_GPIO, /* LED Left Capacity 2 */
+ MPP43_GPIO, /* LED Left Capacity 1 */
+ MPP42_GPIO, /* LED Left Capacity 0 */
+ MPP41_GPIO, /* LED Right Capacity 3 */
+ MPP40_GPIO, /* LED Right Capacity 2 */
+ MPP39_GPIO, /* LED Right Capacity 1 */
+ MPP38_GPIO, /* LED Right Capacity 0 */
+ 0
+};
+
+static void __init goflexnet_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+
+ /* setup gpio pin select */
+ kirkwood_mpp_conf(goflexnet_mpp_config);
+
+ kirkwood_uart0_init();
+ kirkwood_nand_init(ARRAY_AND_SIZE(goflexnet_nand_parts), 40);
+
+ if (gpio_request(29, "USB Power Enable") != 0 ||
+ gpio_direction_output(29, 1) != 0)
+ printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
+ kirkwood_ehci_init();
+ kirkwood_ge00_init(&goflexnet_ge00_data);
+ kirkwood_sata_init(&goflexnet_sata_data);
+
+ platform_device_register(&goflexnet_leds);
+}
+
+MACHINE_START(GOFLEXNET, "Seagate GoFlex Net")
+ /* Maintainer: Peter Carmichael <peterjncarm@ovi.com> */
+ .atag_offset = 0x100,
+ .init_machine = goflexnet_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
+
diff -urN a/arch/arm/mach-kirkwood/guruplug-setup.c b/arch/arm/mach-kirkwood/guruplug-setup.c
--- a/arch/arm/mach-kirkwood/guruplug-setup.c 2012-05-20 18:29:13.000000000 -0400
+++ b/arch/arm/mach-kirkwood/guruplug-setup.c 2012-05-24 12:02:12.000000000 -0400
@@ -57,22 +57,24 @@
static struct gpio_led guruplug_led_pins[] = {
{
- .name = "guruplug:red:health",
+ .name = "status:red:fault",
+ .default_trigger = "none",
.gpio = 46,
.active_low = 1,
},
{
- .name = "guruplug:green:health",
+ .name = "status:green:health",
+ .default_trigger = "default-on",
.gpio = 47,
.active_low = 1,
},
{
- .name = "guruplug:red:wmode",
+ .name = "status:red:wmode",
.gpio = 48,
.active_low = 1,
},
{
- .name = "guruplug:green:wmode",
+ .name = "status:green:wmode",
.gpio = 49,
.active_low = 1,
},
diff -urN a/arch/arm/mach-kirkwood/iconnect-setup.c b/arch/arm/mach-kirkwood/iconnect-setup.c
--- a/arch/arm/mach-kirkwood/iconnect-setup.c 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/mach-kirkwood/iconnect-setup.c 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,203 @@
+/*
+ * arch/arm/mach-kirkwood/iconnect-setup.c
+ *
+ * Iomega iConnect Wireless
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/ethtool.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <linux/i2c.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition iconnect_nand_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0,
+ .size = SZ_1M
+ }, {
+ .name = "uImage",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_1M + SZ_2M
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_32M,
+ }, {
+ .name = "data",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL
+ },
+};
+
+static struct mv643xx_eth_platform_data iconnect_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(11),
+};
+
+static struct gpio_led iconnect_led_pins[] = {
+ {
+ .name = "iconnect:led_level",
+ .default_trigger = "default-on",
+ .gpio = 41,
+ },
+ {
+ .name = "iconnect:blue:power",
+ .default_trigger = "default-on",
+ .gpio = 42,
+ },
+ {
+ .name = "iconnect:red:power",
+ .gpio = 43,
+ },
+ {
+ .name = "iconnect:blue:usb1",
+ .gpio = 44,
+ },
+ {
+ .name = "iconnect:blue:usb2",
+ .gpio = 45,
+ },
+ {
+ .name = "iconnect:blue:usb3",
+ .gpio = 46,
+ },
+ {
+ .name = "iconnect:blue:usb4",
+ .gpio = 47,
+ },
+ {
+ .name = "iconnect:blue:otb",
+ .gpio = 48,
+ },
+};
+
+static struct gpio_led_platform_data iconnect_led_data = {
+ .leds = iconnect_led_pins,
+ .num_leds = ARRAY_SIZE(iconnect_led_pins),
+};
+
+static struct platform_device iconnect_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &iconnect_led_data,
+ }
+};
+
+#define ICONNECT_GPIO_KEY_RESET 12
+#define ICONNECT_GPIO_KEY_OTB 35
+
+#define ICONNECT_SW_RESET 0x00
+#define ICONNECT_SW_OTB 0x01
+
+static struct gpio_keys_button iconnect_buttons[] = {
+ {
+ .type = EV_SW,
+ .code = ICONNECT_SW_RESET,
+ .gpio = ICONNECT_GPIO_KEY_RESET,
+ .desc = "Reset Button",
+ .active_low = 1,
+ .debounce_interval = 100,
+ },
+ {
+ .type = EV_SW,
+ .code = ICONNECT_SW_OTB,
+ .gpio = ICONNECT_GPIO_KEY_OTB,
+ .desc = "OTB Button",
+ .active_low = 1,
+ .debounce_interval = 100,
+ },
+};
+
+static struct gpio_keys_platform_data iconnect_button_data = {
+ .buttons = iconnect_buttons,
+ .nbuttons = ARRAY_SIZE(iconnect_buttons),
+};
+
+static struct platform_device iconnect_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &iconnect_button_data,
+ },
+};
+
+static unsigned int iconnect_mpp_config[] __initdata = {
+ MPP12_GPIO, /*Input for reset button*/
+ MPP35_GPIO, /*Input for OTB button*/
+ MPP41_GPIO,
+ MPP42_GPIO,
+ MPP43_GPIO,
+ MPP44_GPIO,
+ MPP45_GPIO,
+ MPP46_GPIO,
+ MPP47_GPIO,
+ MPP48_GPIO,
+ 0
+};
+
+static struct i2c_board_info __initdata iconnect_i2c_rtc = {
+ I2C_BOARD_INFO("lm63", 0x4c),
+};
+
+static void __init iconnect_init(void)
+{
+ u32 dev, rev;
+
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+ kirkwood_mpp_conf(iconnect_mpp_config);
+
+ kirkwood_nand_init(ARRAY_AND_SIZE(iconnect_nand_parts), 40);
+ kirkwood_ehci_init();
+
+ kirkwood_ge00_init(&iconnect_ge00_data);
+ kirkwood_pcie_id(&dev, &rev);
+
+ kirkwood_uart0_init();
+
+ platform_device_register(&iconnect_leds);
+ platform_device_register(&iconnect_button_device);
+
+ kirkwood_i2c_init();
+ i2c_register_board_info(0, &iconnect_i2c_rtc, 1);
+
+}
+
+static int __init iconnect_pci_init(void)
+{
+ if (machine_is_iconnect())
+ kirkwood_pcie_init(KW_PCIE0);
+
+ return 0;
+}
+subsys_initcall(iconnect_pci_init);
+
+
+MACHINE_START(ICONNECT, "Iomega iConnect Wireless")
+ .atag_offset = 0x100,
+ .init_machine = iconnect_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
diff -urN a/arch/arm/mach-kirkwood/ionics-stratus-setup.c b/arch/arm/mach-kirkwood/ionics-stratus-setup.c
--- a/arch/arm/mach-kirkwood/ionics-stratus-setup.c 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/mach-kirkwood/ionics-stratus-setup.c 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,136 @@
+/*
+ * arch/arm/mach-kirkwood/ionics-stratus-setup.c
+ *
+ * Ionics Stratus Board Setup arcNumber 4184
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition ionics_stratus_nand_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0,
+ .size = SZ_1M
+ }, {
+ .name = "uImage",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_4M
+ }, {
+ .name = "root",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL
+ },
+};
+
+static struct mv643xx_eth_platform_data ionics_stratus_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mvsdio_platform_data ionics_stratus_mvsdio_data = {
+ /* unfortunately the CD signal has not been connected */
+};
+
+static struct gpio_led ionics_stratus_led_pins[] = {
+ {
+ .name = "status:green:led1",
+ .default_trigger = "none",
+ .gpio = 44,
+ .active_low = 1,
+ },
+ {
+ .name = "status:green:led2",
+ .default_trigger = "none",
+ .gpio = 40,
+ .active_low = 1,
+ },
+ {
+ .name = "status:green:led3",
+ .default_trigger = "default-on",
+ .gpio = 36,
+ .active_low = 1,
+ },
+ {
+ .name = "status:green:led4",
+ .default_trigger = "default-on",
+ .gpio = 39,
+ .active_low = 1,
+ },
+
+};
+
+static struct gpio_led_platform_data ionics_stratus_led_data = {
+ .leds = ionics_stratus_led_pins,
+ .num_leds = ARRAY_SIZE(ionics_stratus_led_pins),
+};
+
+static struct platform_device ionics_stratus_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &ionics_stratus_led_data,
+ }
+};
+
+static unsigned int ionics_stratus_mpp_config[] __initdata = {
+ MPP21_GPIO, /* USB PORT 1 Pw Enable */
+ MPP32_GPIO, /* USB PORT 2 Pw Enable */
+ MPP48_GPIO, /* WIFI Power Down */
+ MPP49_GPIO, /* WIFI Host Wakeup */
+ MPP42_GPIO, /* WIFI MAC Wakeup */
+ MPP44_GPIO, /* LED 1 */
+ MPP40_GPIO, /* LED 2 */
+ MPP36_GPIO, /* LED 3 */
+ MPP39_GPIO, /* LED 4 */
+ MPP23_GPIO, /* BTN 1 */
+ MPP37_GPIO, /* BTN 2 */
+ MPP38_GPIO, /* BTN 3 */
+ 0
+};
+
+static void __init ionics_stratus_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+
+ /* setup gpio pin select */
+ kirkwood_mpp_conf(ionics_stratus_mpp_config);
+
+ kirkwood_uart0_init();
+ kirkwood_nand_init(ARRAY_AND_SIZE(ionics_stratus_nand_parts), 25);
+
+ kirkwood_ehci_init();
+
+ kirkwood_ge00_init(&ionics_stratus_ge00_data);
+ kirkwood_sdio_init(&ionics_stratus_mvsdio_data);
+
+ platform_device_register(&ionics_stratus_leds);
+}
+
+MACHINE_START(IONICS_STRATUS, "Ionics Plug Computer Plus - Stratus")
+ /* Maintainer: Mike Brown <mbrown@archlinuxarm.org> */
+ .atag_offset = 0x100,
+ .init_machine = ionics_stratus_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
diff -urN a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
--- a/arch/arm/mach-kirkwood/Kconfig 2012-05-20 18:29:13.000000000 -0400
+++ b/arch/arm/mach-kirkwood/Kconfig 2012-05-24 12:02:12.000000000 -0400
@@ -78,6 +78,54 @@
Say 'Y' here if you want your kernel to support the
Seagate FreeAgent DockStar.
+config MACH_GOFLEXNET
+ bool "Seagate GoFlex Net"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Seagate GoFlex Net.
+
+config MACH_GOFLEXHOME
+ bool "Seagate GoFlex Home"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Seagate GoFlex Home.
+
+config MACH_ICONNECT
+ bool "Iomega iConnect Wireless"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Iomega iConnect Wireless.
+
+config MACH_POGOPLUGV4
+ bool "Pogoplug Series 4"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Pogoplug Series 4.
+
+config MACH_POGO_E02
+ bool "CE Pogoplug E02"
+ help
+ Say 'Y' here if you want your kernel to support the
+ CloudEngines Pogoplug e02.
+
+config MACH_NAS6210
+ bool "RaidSonic ICY BOX IB-NAS6210"
+ help
+ Say 'Y' here if you want your kernel to support the
+ RaidSonic ICY BOX IB-NAS6210 device.
+
+config MACH_TOPKICK
+ bool "USI Topkick"
+ help
+ Say 'Y' here if you want your kernel to support the
+ USI Topkick.
+
+config MACH_IONICS_STRATUS
+ bool "Ionics Stratus"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Ionics Stratus.
+
config MACH_OPENRD
bool
diff -urN a/arch/arm/mach-kirkwood/Kconfig.orig b/arch/arm/mach-kirkwood/Kconfig.orig
--- a/arch/arm/mach-kirkwood/Kconfig.orig 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/mach-kirkwood/Kconfig.orig 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,149 @@
+if ARCH_KIRKWOOD
+
+menu "Marvell Kirkwood Implementations"
+
+config MACH_DB88F6281_BP
+ bool "Marvell DB-88F6281-BP Development Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell DB-88F6281-BP Development Board.
+
+config MACH_RD88F6192_NAS
+ bool "Marvell RD-88F6192-NAS Reference Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell RD-88F6192-NAS Reference Board.
+
+config MACH_RD88F6281
+ bool "Marvell RD-88F6281 Reference Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell RD-88F6281 Reference Board.
+
+config MACH_MV88F6281GTW_GE
+ bool "Marvell 88F6281 GTW GE Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell 88F6281 GTW GE Board.
+
+config MACH_SHEEVAPLUG
+ bool "Marvell SheevaPlug Reference Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell SheevaPlug Reference Board.
+
+config MACH_ESATA_SHEEVAPLUG
+ bool "Marvell eSATA SheevaPlug Reference Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell eSATA SheevaPlug Reference Board.
+
+config MACH_GURUPLUG
+ bool "Marvell GuruPlug Reference Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell GuruPlug Reference Board.
+
+config ARCH_KIRKWOOD_DT
+ bool "Marvell Kirkwood Flattened Device Tree"
+ select USE_OF
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell Kirkwood using flattened device tree.
+
+config MACH_DREAMPLUG_DT
+ bool "Marvell DreamPlug (Flattened Device Tree)"
+ select ARCH_KIRKWOOD_DT
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell DreamPlug (Flattened Device Tree).
+
+config MACH_TS219
+ bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
+ help
+ Say 'Y' here if you want your kernel to support the
+ QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and
+ TS-219P+ Turbo NAS devices.
+
+config MACH_TS41X
+ bool "QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo NAS"
+ help
+ Say 'Y' here if you want your kernel to support the
+ QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo
+ NAS devices.
+
+config MACH_DOCKSTAR
+ bool "Seagate FreeAgent DockStar"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Seagate FreeAgent DockStar.
+
+config MACH_OPENRD
+ bool
+
+config MACH_OPENRD_BASE
+ bool "Marvell OpenRD Base Board"
+ select MACH_OPENRD
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell OpenRD Base Board.
+
+config MACH_OPENRD_CLIENT
+ bool "Marvell OpenRD Client Board"
+ select MACH_OPENRD
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell OpenRD Client Board.
+
+config MACH_OPENRD_ULTIMATE
+ bool "Marvell OpenRD Ultimate Board"
+ select MACH_OPENRD
+ help
+ Say 'Y' here if you want your kernel to support the
+ Marvell OpenRD Ultimate Board.
+
+config MACH_NETSPACE_V2
+ bool "LaCie Network Space v2 NAS Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ LaCie Network Space v2 NAS.
+
+config MACH_INETSPACE_V2
+ bool "LaCie Internet Space v2 NAS Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ LaCie Internet Space v2 NAS.
+
+config MACH_NETSPACE_MAX_V2
+ bool "LaCie Network Space Max v2 NAS Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ LaCie Network Space Max v2 NAS.
+
+config MACH_D2NET_V2
+ bool "LaCie d2 Network v2 NAS Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ LaCie d2 Network v2 NAS.
+
+config MACH_NET2BIG_V2
+ bool "LaCie 2Big Network v2 NAS Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ LaCie 2Big Network v2 NAS.
+
+config MACH_NET5BIG_V2
+ bool "LaCie 5Big Network v2 NAS Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ LaCie 5Big Network v2 NAS.
+
+config MACH_T5325
+ bool "HP t5325 Thin Client"
+ help
+ Say 'Y' here if you want your kernel to support the
+ HP t5325 Thin Client.
+
+endmenu
+
+endif
diff -urN a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
--- a/arch/arm/mach-kirkwood/Makefile 2012-05-20 18:29:13.000000000 -0400
+++ b/arch/arm/mach-kirkwood/Makefile 2012-05-24 12:02:12.000000000 -0400
@@ -8,6 +8,14 @@
obj-$(CONFIG_MACH_ESATA_SHEEVAPLUG) += sheevaplug-setup.o
obj-$(CONFIG_MACH_GURUPLUG) += guruplug-setup.o
obj-$(CONFIG_MACH_DOCKSTAR) += dockstar-setup.o
+obj-$(CONFIG_MACH_GOFLEXNET) += goflexnet-setup.o
+obj-$(CONFIG_MACH_GOFLEXHOME) += goflexhome-setup.o
+obj-$(CONFIG_MACH_ICONNECT) += iconnect-setup.o
+obj-$(CONFIG_MACH_POGOPLUGV4) += pogoplugv4-setup.o
+obj-$(CONFIG_MACH_POGO_E02) += pogo_e02-setup.o
+obj-$(CONFIG_MACH_NAS6210) += nas6210-setup.o
+obj-$(CONFIG_MACH_TOPKICK) += topkick-setup.o
+obj-$(CONFIG_MACH_IONICS_STRATUS) += ionics-stratus-setup.o
obj-$(CONFIG_MACH_TS219) += ts219-setup.o tsx1x-common.o
obj-$(CONFIG_MACH_TS41X) += ts41x-setup.o tsx1x-common.o
obj-$(CONFIG_MACH_OPENRD) += openrd-setup.o
diff -urN a/arch/arm/mach-kirkwood/mpp.h b/arch/arm/mach-kirkwood/mpp.h
--- a/arch/arm/mach-kirkwood/mpp.h 2012-05-20 18:29:13.000000000 -0400
+++ b/arch/arm/mach-kirkwood/mpp.h 2012-05-24 12:02:12.000000000 -0400
@@ -102,7 +102,7 @@
#define MPP11_SATA0_ACTn MPP( 11, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP12_GPO MPP( 12, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP12_GPIO MPP( 12, 0x0, 1, 1, 0, 0, 0, 1, 0 )
+#define MPP12_GPIO MPP( 12, 0x0, 1, 1, 1, 1, 1, 1, 1 )
#define MPP12_SD_CLK MPP( 12, 0x1, 0, 0, 1, 1, 1, 1, 1 )
#define MPP12_AU_SPDIF0 MPP( 12, 0xa, 0, 0, 0, 0, 0, 0, 1 )
#define MPP12_SPI_MOSI MPP( 12, 0xb, 0, 0, 0, 0, 0, 0, 1 )
diff -urN a/arch/arm/mach-kirkwood/nas6210-setup.c b/arch/arm/mach-kirkwood/nas6210-setup.c
--- a/arch/arm/mach-kirkwood/nas6210-setup.c 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/mach-kirkwood/nas6210-setup.c 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,185 @@
+/*
+ * arch/arm/mach-kirkwood/nas6210-setup.c
+ *
+ * Raidsonic ICYBOX NAS6210 Board Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+#define NAS6210_GPIO_POWER_OFF 24
+
+static struct mtd_partition nas6210_nand_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0,
+ .size = SZ_1M
+ }, {
+ .name = "uImage",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 6*SZ_1M
+ }, {
+ .name = "root",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL
+ },
+};
+
+static struct mv643xx_eth_platform_data nas6210_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(8),
+};
+
+static struct mv_sata_platform_data nas6210_sata_data = {
+ .n_ports = 2,
+};
+
+static struct gpio_led nas6210_led_pins[] = {
+ {
+ .name = "status:green:power",
+ .default_trigger = "default-on",
+ .gpio = 25,
+ .active_low = 0,
+ },
+ {
+ .name = "status:red:power",
+ .default_trigger = "none",
+ .gpio = 22,
+ .active_low = 0,
+ },
+ {
+ .name = "status:red:usb_copy",
+ .default_trigger = "none",
+ .gpio = 27,
+ .active_low = 0,
+ },
+};
+
+static struct gpio_led_platform_data nas6210_led_data = {
+ .leds = nas6210_led_pins,
+ .num_leds = ARRAY_SIZE(nas6210_led_pins),
+};
+
+static struct platform_device nas6210_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &nas6210_led_data,
+ }
+};
+
+static struct gpio_keys_button nas6210_buttons[] = {
+ {
+ .code = KEY_COPY,
+ .gpio = 29,
+ .desc = "USB Copy",
+ .active_low = 1,
+ },
+ {
+ .code = KEY_RESTART,
+ .gpio = 28,
+ .desc = "Reset",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data nas6210_button_data = {
+ .buttons = nas6210_buttons,
+ .nbuttons = ARRAY_SIZE(nas6210_buttons),
+};
+
+static struct platform_device nas6210_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &nas6210_button_data,
+ }
+};
+
+static unsigned int nas6210_mpp_config[] __initdata = {
+ MPP0_NF_IO2,
+ MPP1_NF_IO3,
+ MPP2_NF_IO4,
+ MPP3_NF_IO5,
+ MPP4_NF_IO6,
+ MPP5_NF_IO7,
+ MPP18_NF_IO0,
+ MPP19_NF_IO1,
+ MPP22_GPIO, /* Power LED red */
+ MPP24_GPIO, /* Power off device */
+ MPP25_GPIO, /* Power LED green */
+ MPP27_GPIO, /* USB transfer LED */
+ MPP28_GPIO, /* Reset button */
+ MPP29_GPIO, /* USB Copy button */
+ 0
+};
+
+static void nas6210_power_off(void)
+{
+ gpio_set_value(NAS6210_GPIO_POWER_OFF, 1);
+}
+
+static void __init nas6210_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+ kirkwood_mpp_conf(nas6210_mpp_config);
+
+ kirkwood_nand_init(ARRAY_AND_SIZE(nas6210_nand_parts), 25);
+ kirkwood_ehci_init();
+ kirkwood_ge00_init(&nas6210_ge00_data);
+ kirkwood_sata_init(&nas6210_sata_data);
+ kirkwood_uart0_init();
+ platform_device_register(&nas6210_leds);
+ platform_device_register(&nas6210_button_device);
+ if (gpio_request(NAS6210_GPIO_POWER_OFF, "power-off") == 0 &&
+ gpio_direction_output(NAS6210_GPIO_POWER_OFF, 0) == 0)
+ pm_power_off = nas6210_power_off;
+ else
+ pr_err("nas6210: failed to configure power-off GPIO\n");
+}
+
+static int __init nas6210_pci_init(void)
+{
+ if (machine_is_nas6210()) {
+ u32 dev, rev;
+
+ kirkwood_pcie_id(&dev, &rev);
+ if (dev == MV88F6282_DEV_ID)
+ kirkwood_pcie_init(KW_PCIE1 | KW_PCIE0);
+ else
+ kirkwood_pcie_init(KW_PCIE0);
+ }
+
+ return 0;
+}
+subsys_initcall(nas6210_pci_init);
+
+MACHINE_START(NAS6210, "RaidSonic ICY BOX IB-NAS6210")
+ /* Maintainer: <gmbnomis at gmail dot com> */
+ .atag_offset = 0x100,
+ .init_machine = nas6210_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
diff -urN a/arch/arm/mach-kirkwood/pogo_e02-setup.c b/arch/arm/mach-kirkwood/pogo_e02-setup.c
--- a/arch/arm/mach-kirkwood/pogo_e02-setup.c 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/mach-kirkwood/pogo_e02-setup.c 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,114 @@
+/*
+ * arch/arm/mach-kirkwood/pogo_e02-setup.c
+ *
+ * CloudEngines Pogoplug E02 support
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition pogo_e02_nand_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0,
+ .size = SZ_1M
+ }, {
+ .name = "uImage",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_4M
+ }, {
+ .name = "pogoplug",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_32M
+ }, {
+ .name = "root",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL
+ },
+};
+
+static struct mv643xx_eth_platform_data pogo_e02_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct gpio_led pogo_e02_led_pins[] = {
+ {
+ .name = "status:green:health",
+ .default_trigger = "default-on",
+ .gpio = 48,
+ .active_low = 1,
+ },
+ {
+ .name = "status:orange:fault",
+ .default_trigger = "none",
+ .gpio = 49,
+ .active_low = 1,
+ }
+};
+
+static struct gpio_led_platform_data pogo_e02_led_data = {
+ .leds = pogo_e02_led_pins,
+ .num_leds = ARRAY_SIZE(pogo_e02_led_pins),
+};
+
+static struct platform_device pogo_e02_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &pogo_e02_led_data,
+ }
+};
+
+static unsigned int pogo_e02_mpp_config[] __initdata = {
+ MPP29_GPIO, /* USB Power Enable */
+ MPP48_GPIO, /* LED Green */
+ MPP49_GPIO, /* LED Orange */
+ 0
+};
+
+static void __init pogo_e02_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+
+ /* setup gpio pin select */
+ kirkwood_mpp_conf(pogo_e02_mpp_config);
+
+ kirkwood_uart0_init();
+ kirkwood_nand_init(ARRAY_AND_SIZE(pogo_e02_nand_parts), 25);
+
+ if (gpio_request(29, "USB Power Enable") != 0 ||
+ gpio_direction_output(29, 1) != 0)
+ printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
+ kirkwood_ehci_init();
+
+ kirkwood_ge00_init(&pogo_e02_ge00_data);
+
+ platform_device_register(&pogo_e02_leds);
+}
+
+MACHINE_START(POGO_E02, "Pogoplug E02")
+ .atag_offset = 0x100,
+ .init_machine = pogo_e02_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
diff -urN a/arch/arm/mach-kirkwood/pogoplugv4-setup.c b/arch/arm/mach-kirkwood/pogoplugv4-setup.c
--- a/arch/arm/mach-kirkwood/pogoplugv4-setup.c 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/mach-kirkwood/pogoplugv4-setup.c 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,194 @@
+/*
+ * arch/arm/mach-kirkwood/pogoplugv4-setup.c
+ *
+ * Pogoplug Series 4 Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/orion_spi.h>
+#include <linux/input.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+#define POGOPLUGV4_GPIO_USB_VBUS 10
+
+static struct mtd_partition ppv4_nand_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0,
+ .size = 2 * SZ_1M
+ }, {
+ .name = "uImage",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 3 * SZ_1M
+ }, {
+ .name = "uImage2",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = 3 * SZ_1M
+ }, {
+ .name = "failsafe",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_8M
+ }, {
+ .name = "root",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL
+ },
+};
+
+static struct mv643xx_eth_platform_data pogoplugv4_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mv_sata_platform_data pogoplugv4_sata_data = {
+ .n_ports = 1,
+};
+
+static struct gpio_keys_button pogoplugv4_button_pins[] = {
+ {
+ .code = KEY_EJECTCD,
+ .gpio = 29,
+ .desc = "Eject Button",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data pogoplugv4_button_data = {
+ .buttons = pogoplugv4_button_pins,
+ .nbuttons = ARRAY_SIZE(pogoplugv4_button_pins),
+};
+
+static struct platform_device pogoplugv4_buttons = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &pogoplugv4_button_data,
+ },
+};
+
+static struct gpio_led pogoplugv4_led_pins[] = {
+ {
+ .name = "status:green:health",
+ .default_trigger = "default-on",
+ .gpio = 22,
+ .active_low = 1,
+ },
+ {
+ .name = "status:red:fault",
+ .default_trigger = "none",
+ .gpio = 24,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data pogoplugv4_led_data = {
+ .leds = pogoplugv4_led_pins,
+ .num_leds = ARRAY_SIZE(pogoplugv4_led_pins),
+};
+
+static struct platform_device pogoplugv4_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &pogoplugv4_led_data,
+ }
+};
+
+static struct mvsdio_platform_data ppv4_mvsdio_data = {
+ .gpio_card_detect = 27,
+};
+
+static unsigned int ppv4_mpp_config[] __initdata = {
+ MPP27_GPIO, /* SD card detect */
+ MPP29_GPIO, /* Eject button */
+ MPP22_GPIO, /* Green LED */
+ MPP24_GPIO, /* Red LED */
+ MPP12_SD_CLK,
+ MPP13_SD_CMD,
+ MPP14_SD_D0,
+ MPP15_SD_D1,
+ MPP16_SD_D2,
+ MPP17_SD_D3,
+ 0
+};
+
+static const struct flash_platform_data pogoplugv4_spi_slave_data = {
+ .type = "m25p05-nonjedec",
+};
+
+static struct spi_board_info __initdata pogoplugv4_spi_slave_info[] = {
+ {
+ .modalias = "m25p05-nonjedec",
+ .platform_data = &pogoplugv4_spi_slave_data,
+ .irq = -1,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ },
+};
+
+static void __init pogoplugv4_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+ kirkwood_mpp_conf(ppv4_mpp_config);
+
+ orion_gpio_set_valid(POGOPLUGV4_GPIO_USB_VBUS, 1);
+ if (gpio_request(POGOPLUGV4_GPIO_USB_VBUS, "USB VBUS") != 0 ||
+ gpio_direction_output(POGOPLUGV4_GPIO_USB_VBUS, 1) != 0)
+ pr_err("POGOPLUGV4: failed to setup USB VBUS GPIO\n");
+
+ kirkwood_ehci_init();
+ kirkwood_ge00_init(&pogoplugv4_ge00_data);
+ kirkwood_sata_init(&pogoplugv4_sata_data);
+ spi_register_board_info(pogoplugv4_spi_slave_info,
+ ARRAY_SIZE(pogoplugv4_spi_slave_info));
+ kirkwood_spi_init();
+ kirkwood_uart0_init();
+ kirkwood_nand_init(ARRAY_AND_SIZE(ppv4_nand_parts), 25);
+ kirkwood_sdio_init(&ppv4_mvsdio_data);
+ platform_device_register(&pogoplugv4_leds);
+ platform_device_register(&pogoplugv4_buttons);
+}
+
+static int __init pogoplugv4_pci_init(void)
+{
+ if (machine_is_pogoplugv4())
+ kirkwood_pcie_init(KW_PCIE0);
+
+ return 0;
+}
+subsys_initcall(pogoplugv4_pci_init);
+
+MACHINE_START(POGOPLUGV4, "Pogoplug V4")
+ /* Maintainer: Kevin Mihelich <kevin@archlinuxarm.org> */
+ .atag_offset = 0x100,
+ .init_machine = pogoplugv4_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
diff -urN a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c 2012-05-20 18:29:13.000000000 -0400
+++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c 2012-05-24 12:05:49.000000000 -0400
@@ -43,7 +43,7 @@
.phy_addr = MV643XX_ETH_PHY_ADDR(0),
};
-static struct mv_sata_platform_data sheeva_esata_sata_data = {
+static struct mv_sata_platform_data esata_sheevaplug_sata_data = {
.n_ports = 2,
};
@@ -51,7 +51,7 @@
/* unfortunately the CD signal has not been connected */
};
-static struct mvsdio_platform_data sheeva_esata_mvsdio_data = {
+static struct mvsdio_platform_data esata_sheevaplug_mvsdio_data = {
.gpio_write_protect = 44, /* MPP44 used as SD write protect */
.gpio_card_detect = 47, /* MPP47 used as SD card detect */
};
@@ -64,7 +64,13 @@
.active_low = 1,
},
{
- .name = "plug:green:health",
+ .name = "status:green:health",
+ .default_trigger = "none",
+ .gpio = 48,
+ .active_low = 1,
+ },
+ {
+ .name = "status:blue:health",
.default_trigger = "default-on",
.gpio = 49,
.active_low = 1,
@@ -87,15 +93,18 @@
static unsigned int sheevaplug_mpp_config[] __initdata = {
MPP29_GPIO, /* USB Power Enable */
MPP46_GPIO, /* LED Red */
- MPP49_GPIO, /* LED */
+ MPP48_GPIO, /* LED Green */
+ MPP49_GPIO, /* LED Blue */
0
};
-static unsigned int sheeva_esata_mpp_config[] __initdata = {
+static unsigned int esata_sheevaplug_mpp_config[] __initdata = {
MPP29_GPIO, /* USB Power Enable */
MPP44_GPIO, /* SD Write Protect */
MPP47_GPIO, /* SD Card Detect */
- MPP49_GPIO, /* LED Green */
+ MPP46_GPIO, /* LED Red */
+ MPP48_GPIO, /* LED Green */
+ MPP49_GPIO, /* LED Blue */
0
};
@@ -108,7 +117,7 @@
/* setup gpio pin select */
if (machine_is_esata_sheevaplug())
- kirkwood_mpp_conf(sheeva_esata_mpp_config);
+ kirkwood_mpp_conf(esata_sheevaplug_mpp_config);
else
kirkwood_mpp_conf(sheevaplug_mpp_config);
@@ -124,11 +133,11 @@
/* honor lower power consumption for plugs with out eSATA */
if (machine_is_esata_sheevaplug())
- kirkwood_sata_init(&sheeva_esata_sata_data);
+ kirkwood_sata_init(&esata_sheevaplug_sata_data);
/* enable sd wp and sd cd on plugs with esata */
if (machine_is_esata_sheevaplug())
- kirkwood_sdio_init(&sheeva_esata_mvsdio_data);
+ kirkwood_sdio_init(&esata_sheevaplug_mvsdio_data);
else
kirkwood_sdio_init(&sheevaplug_mvsdio_data);
diff -urN a/arch/arm/mach-kirkwood/topkick-setup.c b/arch/arm/mach-kirkwood/topkick-setup.c
--- a/arch/arm/mach-kirkwood/topkick-setup.c 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/mach-kirkwood/topkick-setup.c 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,164 @@
+/*
+ * arch/arm/mach-kirkwood/topkick-setup.c
+ *
+ * USI Topkick Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition topkick_nand_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0,
+ .size = 0x180000
+ }, {
+ .name = "u-boot-env",
+ .offset = 0x180000,
+ .size = 128 * 1024
+ }, {
+ .name = "uImage",
+ .offset = 2 * 1024 * 1024,
+ .size = 6 * 1024 * 1024
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL
+ },
+};
+
+static struct mv643xx_eth_platform_data topkick_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mv_sata_platform_data topkick_sata_data = {
+ .n_ports = 1,
+};
+
+static struct mvsdio_platform_data topkick_mvsdio_data = {
+ .gpio_card_detect = 47, /* MPP47 used as SD card detect */
+};
+
+
+static struct gpio_led topkick_led_pins[] = {
+ {
+ .name = "status:blue:disk",
+ .default_trigger = "none",
+ .gpio = 21,
+ .active_low = 1,
+ },
+ {
+ .name = "status:red:fault",
+ .default_trigger = "none",
+ .gpio = 37,
+ .active_low = 1,
+ },
+ {
+ .name = "status:blue:health",
+ .default_trigger = "default-on",
+ .gpio = 38,
+ .active_low = 1,
+ },
+ {
+ .name = "status:green:misc",
+ .default_trigger = "none",
+ .gpio = 39,
+ .active_low = 1,
+ },
+ {
+ .name = "status:orange:misc",
+ .default_trigger = "none",
+ .gpio = 48,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data topkick_led_data = {
+ .leds = topkick_led_pins,
+ .num_leds = ARRAY_SIZE(topkick_led_pins),
+};
+
+static struct platform_device topkick_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &topkick_led_data,
+ }
+};
+
+static unsigned int topkick_mpp_config[] __initdata = {
+ MPP12_SD_CLK, /* SDIO Clock */
+ MPP13_SD_CMD, /* SDIO Cmd */
+ MPP14_SD_D0, /* SDIO Data 0 */
+ MPP15_SD_D1, /* SDIO Data 1 */
+ MPP16_SD_D2, /* SDIO Data 2 */
+ MPP17_SD_D3, /* SDIO Data 3 */
+ MPP21_GPIO, /* LED Blue SATA */
+ MPP35_GPIO, /* USB Power Enable */
+ MPP36_GPIO, /* SATA Power Enable */
+ MPP37_GPIO, /* LED Red System */
+ MPP38_GPIO, /* LED Blue System */
+ MPP39_GPIO, /* LED Green Misc/WiFi */
+ MPP43_GPIO, /* WOL Eth WOL */
+ MPP44_GPIO, /* SW GW Mode */
+ MPP45_GPIO, /* SW AP Mode */
+ MPP46_GPIO, /* SW Power Off */
+ MPP47_GPIO, /* SDIO Detect */
+ MPP48_GPIO, /* LED Orange Misc/WiFi */
+ 0
+};
+
+static void __init topkick_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+
+ /* setup gpio pin select */
+ kirkwood_mpp_conf(topkick_mpp_config);
+
+ kirkwood_uart0_init();
+ kirkwood_nand_init(ARRAY_AND_SIZE(topkick_nand_parts), 40);
+
+ if (gpio_request(35, "USB Power Enable") != 0 ||
+ gpio_direction_output(35, 1) != 0)
+ printk(KERN_ERR "can't set up GPIO 35 (USB Power Enable)\n");
+ if (gpio_request(36, "SATA Power Enable") != 0 ||
+ gpio_direction_output(36, 1) != 0)
+ printk(KERN_ERR "can't set up GPIO 36 (SATA Power Enable)\n");
+ kirkwood_ge00_init(&topkick_ge00_data);
+ kirkwood_ehci_init();
+ kirkwood_sata_init(&topkick_sata_data);
+ kirkwood_sdio_init(&topkick_mvsdio_data);
+
+ platform_device_register(&topkick_leds);
+}
+
+MACHINE_START(TOPKICK, "USI Topkick")
+ /* Maintainer: Mike Brown <mbrown@archlinuxarm.org> */
+ .atag_offset = 0x100,
+ .init_machine = topkick_init,
+ .map_io = kirkwood_map_io,
+ .init_early = kirkwood_init_early,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
diff -urN a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
--- a/arch/arm/plat-orion/common.c 2012-05-20 18:29:13.000000000 -0400
+++ b/arch/arm/plat-orion/common.c 2012-05-24 12:02:12.000000000 -0400
@@ -222,7 +222,9 @@
/*****************************************************************************
* GE00
****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge00_shared_data;
+struct mv643xx_eth_shared_platform_data orion_ge00_shared_data = {
+ .tx_csum_limit = 1600,
+};
static struct resource orion_ge00_shared_resources[] = {
{
diff -urN a/arch/arm/plat-orion/common.c.orig b/arch/arm/plat-orion/common.c.orig
--- a/arch/arm/plat-orion/common.c.orig 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/plat-orion/common.c.orig 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,936 @@
+/*
+ * arch/arm/plat-orion/common.c
+ *
+ * Marvell Orion SoC common setup code used by multiple mach-/common.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/serial_8250.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/mv643xx_i2c.h>
+#include <net/dsa.h>
+#include <linux/spi/orion_spi.h>
+#include <plat/orion_wdt.h>
+#include <plat/mv_xor.h>
+#include <plat/ehci-orion.h>
+#include <mach/bridge-regs.h>
+
+/* Fill in the resources structure and link it into the platform
+ device structure. There is always a memory region, and nearly
+ always an interrupt.*/
+static void fill_resources(struct platform_device *device,
+ struct resource *resources,
+ resource_size_t mapbase,
+ resource_size_t size,
+ unsigned int irq)
+{
+ device->resource = resources;
+ device->num_resources = 1;
+ resources[0].flags = IORESOURCE_MEM;
+ resources[0].start = mapbase;
+ resources[0].end = mapbase + size;
+
+ if (irq != NO_IRQ) {
+ device->num_resources++;
+ resources[1].flags = IORESOURCE_IRQ;
+ resources[1].start = irq;
+ resources[1].end = irq;
+ }
+}
+
+/*****************************************************************************
+ * UART
+ ****************************************************************************/
+static void __init uart_complete(
+ struct platform_device *orion_uart,
+ struct plat_serial8250_port *data,
+ struct resource *resources,
+ unsigned int membase,
+ resource_size_t mapbase,
+ unsigned int irq,
+ unsigned int uartclk)
+{
+ data->mapbase = mapbase;
+ data->membase = (void __iomem *)membase;
+ data->irq = irq;
+ data->uartclk = uartclk;
+ orion_uart->dev.platform_data = data;
+
+ fill_resources(orion_uart, resources, mapbase, 0xff, irq);
+ platform_device_register(orion_uart);
+}
+
+/*****************************************************************************
+ * UART0
+ ****************************************************************************/
+static struct plat_serial8250_port orion_uart0_data[] = {
+ {
+ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ }, {
+ },
+};
+
+static struct resource orion_uart0_resources[2];
+
+static struct platform_device orion_uart0 = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+};
+
+void __init orion_uart0_init(unsigned int membase,
+ resource_size_t mapbase,
+ unsigned int irq,
+ unsigned int uartclk)
+{
+ uart_complete(&orion_uart0, orion_uart0_data, orion_uart0_resources,
+ membase, mapbase, irq, uartclk);
+}
+
+/*****************************************************************************
+ * UART1
+ ****************************************************************************/
+static struct plat_serial8250_port orion_uart1_data[] = {
+ {
+ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ }, {
+ },
+};
+
+static struct resource orion_uart1_resources[2];
+
+static struct platform_device orion_uart1 = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM1,
+};
+
+void __init orion_uart1_init(unsigned int membase,
+ resource_size_t mapbase,
+ unsigned int irq,
+ unsigned int uartclk)
+{
+ uart_complete(&orion_uart1, orion_uart1_data, orion_uart1_resources,
+ membase, mapbase, irq, uartclk);
+}
+
+/*****************************************************************************
+ * UART2
+ ****************************************************************************/
+static struct plat_serial8250_port orion_uart2_data[] = {
+ {
+ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ }, {
+ },
+};
+
+static struct resource orion_uart2_resources[2];
+
+static struct platform_device orion_uart2 = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM2,
+};
+
+void __init orion_uart2_init(unsigned int membase,
+ resource_size_t mapbase,
+ unsigned int irq,
+ unsigned int uartclk)
+{
+ uart_complete(&orion_uart2, orion_uart2_data, orion_uart2_resources,
+ membase, mapbase, irq, uartclk);
+}
+
+/*****************************************************************************
+ * UART3
+ ****************************************************************************/
+static struct plat_serial8250_port orion_uart3_data[] = {
+ {
+ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ }, {
+ },
+};
+
+static struct resource orion_uart3_resources[2];
+
+static struct platform_device orion_uart3 = {
+ .name = "serial8250",
+ .id = 3,
+};
+
+void __init orion_uart3_init(unsigned int membase,
+ resource_size_t mapbase,
+ unsigned int irq,
+ unsigned int uartclk)
+{
+ uart_complete(&orion_uart3, orion_uart3_data, orion_uart3_resources,
+ membase, mapbase, irq, uartclk);
+}
+
+/*****************************************************************************
+ * SoC RTC
+ ****************************************************************************/
+static struct resource orion_rtc_resource[2];
+
+void __init orion_rtc_init(unsigned long mapbase,
+ unsigned long irq)
+{
+ orion_rtc_resource[0].start = mapbase;
+ orion_rtc_resource[0].end = mapbase + SZ_32 - 1;
+ orion_rtc_resource[0].flags = IORESOURCE_MEM;
+ orion_rtc_resource[1].start = irq;
+ orion_rtc_resource[1].end = irq;
+ orion_rtc_resource[1].flags = IORESOURCE_IRQ;
+
+ platform_device_register_simple("rtc-mv", -1, orion_rtc_resource, 2);
+}
+
+/*****************************************************************************
+ * GE
+ ****************************************************************************/
+static __init void ge_complete(
+ struct mv643xx_eth_shared_platform_data *orion_ge_shared_data,
+ int tclk,
+ struct resource *orion_ge_resource, unsigned long irq,
+ struct platform_device *orion_ge_shared,
+ struct mv643xx_eth_platform_data *eth_data,
+ struct platform_device *orion_ge)
+{
+ orion_ge_shared_data->t_clk = tclk;
+ orion_ge_resource->start = irq;
+ orion_ge_resource->end = irq;
+ eth_data->shared = orion_ge_shared;
+ orion_ge->dev.platform_data = eth_data;
+
+ platform_device_register(orion_ge_shared);
+ platform_device_register(orion_ge);
+}
+
+/*****************************************************************************
+ * GE00
+ ****************************************************************************/
+struct mv643xx_eth_shared_platform_data orion_ge00_shared_data;
+
+static struct resource orion_ge00_shared_resources[] = {
+ {
+ .name = "ge00 base",
+ }, {
+ .name = "ge00 err irq",
+ },
+};
+
+static struct platform_device orion_ge00_shared = {
+ .name = MV643XX_ETH_SHARED_NAME,
+ .id = 0,
+ .dev = {
+ .platform_data = &orion_ge00_shared_data,
+ },
+};
+
+static struct resource orion_ge00_resources[] = {
+ {
+ .name = "ge00 irq",
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device orion_ge00 = {
+ .name = MV643XX_ETH_NAME,
+ .id = 0,
+ .num_resources = 1,
+ .resource = orion_ge00_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
+ unsigned long mapbase,
+ unsigned long irq,
+ unsigned long irq_err,
+ int tclk)
+{
+ fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
+ mapbase + 0x2000, SZ_16K - 1, irq_err);
+ ge_complete(&orion_ge00_shared_data, tclk,
+ orion_ge00_resources, irq, &orion_ge00_shared,
+ eth_data, &orion_ge00);
+}
+
+/*****************************************************************************
+ * GE01
+ ****************************************************************************/
+struct mv643xx_eth_shared_platform_data orion_ge01_shared_data = {
+ .shared_smi = &orion_ge00_shared,
+};
+
+static struct resource orion_ge01_shared_resources[] = {
+ {
+ .name = "ge01 base",
+ }, {
+ .name = "ge01 err irq",
+ },
+};
+
+static struct platform_device orion_ge01_shared = {
+ .name = MV643XX_ETH_SHARED_NAME,
+ .id = 1,
+ .dev = {
+ .platform_data = &orion_ge01_shared_data,
+ },
+};
+
+static struct resource orion_ge01_resources[] = {
+ {
+ .name = "ge01 irq",
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device orion_ge01 = {
+ .name = MV643XX_ETH_NAME,
+ .id = 1,
+ .num_resources = 1,
+ .resource = orion_ge01_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
+ unsigned long mapbase,
+ unsigned long irq,
+ unsigned long irq_err,
+ int tclk)
+{
+ fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
+ mapbase + 0x2000, SZ_16K - 1, irq_err);
+ ge_complete(&orion_ge01_shared_data, tclk,
+ orion_ge01_resources, irq, &orion_ge01_shared,
+ eth_data, &orion_ge01);
+}
+
+/*****************************************************************************
+ * GE10
+ ****************************************************************************/
+struct mv643xx_eth_shared_platform_data orion_ge10_shared_data = {
+ .shared_smi = &orion_ge00_shared,
+};
+
+static struct resource orion_ge10_shared_resources[] = {
+ {
+ .name = "ge10 base",
+ }, {
+ .name = "ge10 err irq",
+ },
+};
+
+static struct platform_device orion_ge10_shared = {
+ .name = MV643XX_ETH_SHARED_NAME,
+ .id = 1,
+ .dev = {
+ .platform_data = &orion_ge10_shared_data,
+ },
+};
+
+static struct resource orion_ge10_resources[] = {
+ {
+ .name = "ge10 irq",
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device orion_ge10 = {
+ .name = MV643XX_ETH_NAME,
+ .id = 1,
+ .num_resources = 2,
+ .resource = orion_ge10_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
+ unsigned long mapbase,
+ unsigned long irq,
+ unsigned long irq_err,
+ int tclk)
+{
+ fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
+ mapbase + 0x2000, SZ_16K - 1, irq_err);
+ ge_complete(&orion_ge10_shared_data, tclk,
+ orion_ge10_resources, irq, &orion_ge10_shared,
+ eth_data, &orion_ge10);
+}
+
+/*****************************************************************************
+ * GE11
+ ****************************************************************************/
+struct mv643xx_eth_shared_platform_data orion_ge11_shared_data = {
+ .shared_smi = &orion_ge00_shared,
+};
+
+static struct resource orion_ge11_shared_resources[] = {
+ {
+ .name = "ge11 base",
+ }, {
+ .name = "ge11 err irq",
+ },
+};
+
+static struct platform_device orion_ge11_shared = {
+ .name = MV643XX_ETH_SHARED_NAME,
+ .id = 1,
+ .dev = {
+ .platform_data = &orion_ge11_shared_data,
+ },
+};
+
+static struct resource orion_ge11_resources[] = {
+ {
+ .name = "ge11 irq",
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device orion_ge11 = {
+ .name = MV643XX_ETH_NAME,
+ .id = 1,
+ .num_resources = 2,
+ .resource = orion_ge11_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
+ unsigned long mapbase,
+ unsigned long irq,
+ unsigned long irq_err,
+ int tclk)
+{
+ fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
+ mapbase + 0x2000, SZ_16K - 1, irq_err);
+ ge_complete(&orion_ge11_shared_data, tclk,
+ orion_ge11_resources, irq, &orion_ge11_shared,
+ eth_data, &orion_ge11);
+}
+
+/*****************************************************************************
+ * Ethernet switch
+ ****************************************************************************/
+static struct resource orion_switch_resources[] = {
+ {
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device orion_switch_device = {
+ .name = "dsa",
+ .id = 0,
+ .num_resources = 0,
+ .resource = orion_switch_resources,
+};
+
+void __init orion_ge00_switch_init(struct dsa_platform_data *d, int irq)
+{
+ int i;
+
+ if (irq != NO_IRQ) {
+ orion_switch_resources[0].start = irq;
+ orion_switch_resources[0].end = irq;
+ orion_switch_device.num_resources = 1;
+ }
+
+ d->netdev = &orion_ge00.dev;
+ for (i = 0; i < d->nr_chips; i++)
+ d->chip[i].mii_bus = &orion_ge00_shared.dev;
+ orion_switch_device.dev.platform_data = d;
+
+ platform_device_register(&orion_switch_device);
+}
+
+/*****************************************************************************
+ * I2C
+ ****************************************************************************/
+static struct mv64xxx_i2c_pdata orion_i2c_pdata = {
+ .freq_n = 3,
+ .timeout = 1000, /* Default timeout of 1 second */
+};
+
+static struct resource orion_i2c_resources[2];
+
+static struct platform_device orion_i2c = {
+ .name = MV64XXX_I2C_CTLR_NAME,
+ .id = 0,
+ .dev = {
+ .platform_data = &orion_i2c_pdata,
+ },
+};
+
+static struct mv64xxx_i2c_pdata orion_i2c_1_pdata = {
+ .freq_n = 3,
+ .timeout = 1000, /* Default timeout of 1 second */
+};
+
+static struct resource orion_i2c_1_resources[2];
+
+static struct platform_device orion_i2c_1 = {
+ .name = MV64XXX_I2C_CTLR_NAME,
+ .id = 1,
+ .dev = {
+ .platform_data = &orion_i2c_1_pdata,
+ },
+};
+
+void __init orion_i2c_init(unsigned long mapbase,
+ unsigned long irq,
+ unsigned long freq_m)
+{
+ orion_i2c_pdata.freq_m = freq_m;
+ fill_resources(&orion_i2c, orion_i2c_resources, mapbase,
+ SZ_32 - 1, irq);
+ platform_device_register(&orion_i2c);
+}
+
+void __init orion_i2c_1_init(unsigned long mapbase,
+ unsigned long irq,
+ unsigned long freq_m)
+{
+ orion_i2c_1_pdata.freq_m = freq_m;
+ fill_resources(&orion_i2c_1, orion_i2c_1_resources, mapbase,
+ SZ_32 - 1, irq);
+ platform_device_register(&orion_i2c_1);
+}
+
+/*****************************************************************************
+ * SPI
+ ****************************************************************************/
+static struct orion_spi_info orion_spi_plat_data;
+static struct resource orion_spi_resources;
+
+static struct platform_device orion_spi = {
+ .name = "orion_spi",
+ .id = 0,
+ .dev = {
+ .platform_data = &orion_spi_plat_data,
+ },
+};
+
+static struct orion_spi_info orion_spi_1_plat_data;
+static struct resource orion_spi_1_resources;
+
+static struct platform_device orion_spi_1 = {
+ .name = "orion_spi",
+ .id = 1,
+ .dev = {
+ .platform_data = &orion_spi_1_plat_data,
+ },
+};
+
+/* Note: The SPI silicon core does have interrupts. However the
+ * current Linux software driver does not use interrupts. */
+
+void __init orion_spi_init(unsigned long mapbase,
+ unsigned long tclk)
+{
+ orion_spi_plat_data.tclk = tclk;
+ fill_resources(&orion_spi, &orion_spi_resources,
+ mapbase, SZ_512 - 1, NO_IRQ);
+ platform_device_register(&orion_spi);
+}
+
+void __init orion_spi_1_init(unsigned long mapbase,
+ unsigned long tclk)
+{
+ orion_spi_1_plat_data.tclk = tclk;
+ fill_resources(&orion_spi_1, &orion_spi_1_resources,
+ mapbase, SZ_512 - 1, NO_IRQ);
+ platform_device_register(&orion_spi_1);
+}
+
+/*****************************************************************************
+ * Watchdog
+ ****************************************************************************/
+static struct orion_wdt_platform_data orion_wdt_data;
+
+static struct resource orion_wdt_resource =
+ DEFINE_RES_MEM(TIMER_VIRT_BASE, 0x28);
+
+static struct platform_device orion_wdt_device = {
+ .name = "orion_wdt",
+ .id = -1,
+ .dev = {
+ .platform_data = &orion_wdt_data,
+ },
+ .resource = &orion_wdt_resource,
+ .num_resources = 1,
+};
+
+void __init orion_wdt_init(unsigned long tclk)
+{
+ orion_wdt_data.tclk = tclk;
+ platform_device_register(&orion_wdt_device);
+}
+
+/*****************************************************************************
+ * XOR
+ ****************************************************************************/
+static u64 orion_xor_dmamask = DMA_BIT_MASK(32);
+
+void __init orion_xor_init_channels(
+ struct mv_xor_platform_data *orion_xor0_data,
+ struct platform_device *orion_xor0_channel,
+ struct mv_xor_platform_data *orion_xor1_data,
+ struct platform_device *orion_xor1_channel)
+{
+ /*
+ * two engines can't do memset simultaneously, this limitation
+ * satisfied by removing memset support from one of the engines.
+ */
+ dma_cap_set(DMA_MEMCPY, orion_xor0_data->cap_mask);
+ dma_cap_set(DMA_XOR, orion_xor0_data->cap_mask);
+ platform_device_register(orion_xor0_channel);
+
+ dma_cap_set(DMA_MEMCPY, orion_xor1_data->cap_mask);
+ dma_cap_set(DMA_MEMSET, orion_xor1_data->cap_mask);
+ dma_cap_set(DMA_XOR, orion_xor1_data->cap_mask);
+ platform_device_register(orion_xor1_channel);
+}
+
+/*****************************************************************************
+ * XOR0
+ ****************************************************************************/
+static struct resource orion_xor0_shared_resources[] = {
+ {
+ .name = "xor 0 low",
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "xor 0 high",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device orion_xor0_shared = {
+ .name = MV_XOR_SHARED_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(orion_xor0_shared_resources),
+ .resource = orion_xor0_shared_resources,
+};
+
+static struct resource orion_xor00_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv_xor_platform_data orion_xor00_data = {
+ .shared = &orion_xor0_shared,
+ .hw_id = 0,
+ .pool_size = PAGE_SIZE,
+};
+
+static struct platform_device orion_xor00_channel = {
+ .name = MV_XOR_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(orion_xor00_resources),
+ .resource = orion_xor00_resources,
+ .dev = {
+ .dma_mask = &orion_xor_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(64),
+ .platform_data = &orion_xor00_data,
+ },
+};
+
+static struct resource orion_xor01_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv_xor_platform_data orion_xor01_data = {
+ .shared = &orion_xor0_shared,
+ .hw_id = 1,
+ .pool_size = PAGE_SIZE,
+};
+
+static struct platform_device orion_xor01_channel = {
+ .name = MV_XOR_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(orion_xor01_resources),
+ .resource = orion_xor01_resources,
+ .dev = {
+ .dma_mask = &orion_xor_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(64),
+ .platform_data = &orion_xor01_data,
+ },
+};
+
+void __init orion_xor0_init(unsigned long mapbase_low,
+ unsigned long mapbase_high,
+ unsigned long irq_0,
+ unsigned long irq_1)
+{
+ orion_xor0_shared_resources[0].start = mapbase_low;
+ orion_xor0_shared_resources[0].end = mapbase_low + 0xff;
+ orion_xor0_shared_resources[1].start = mapbase_high;
+ orion_xor0_shared_resources[1].end = mapbase_high + 0xff;
+
+ orion_xor00_resources[0].start = irq_0;
+ orion_xor00_resources[0].end = irq_0;
+ orion_xor01_resources[0].start = irq_1;
+ orion_xor01_resources[0].end = irq_1;
+
+ platform_device_register(&orion_xor0_shared);
+
+ orion_xor_init_channels(&orion_xor00_data, &orion_xor00_channel,
+ &orion_xor01_data, &orion_xor01_channel);
+}
+
+/*****************************************************************************
+ * XOR1
+ ****************************************************************************/
+static struct resource orion_xor1_shared_resources[] = {
+ {
+ .name = "xor 1 low",
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "xor 1 high",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device orion_xor1_shared = {
+ .name = MV_XOR_SHARED_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(orion_xor1_shared_resources),
+ .resource = orion_xor1_shared_resources,
+};
+
+static struct resource orion_xor10_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv_xor_platform_data orion_xor10_data = {
+ .shared = &orion_xor1_shared,
+ .hw_id = 0,
+ .pool_size = PAGE_SIZE,
+};
+
+static struct platform_device orion_xor10_channel = {
+ .name = MV_XOR_NAME,
+ .id = 2,
+ .num_resources = ARRAY_SIZE(orion_xor10_resources),
+ .resource = orion_xor10_resources,
+ .dev = {
+ .dma_mask = &orion_xor_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(64),
+ .platform_data = &orion_xor10_data,
+ },
+};
+
+static struct resource orion_xor11_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv_xor_platform_data orion_xor11_data = {
+ .shared = &orion_xor1_shared,
+ .hw_id = 1,
+ .pool_size = PAGE_SIZE,
+};
+
+static struct platform_device orion_xor11_channel = {
+ .name = MV_XOR_NAME,
+ .id = 3,
+ .num_resources = ARRAY_SIZE(orion_xor11_resources),
+ .resource = orion_xor11_resources,
+ .dev = {
+ .dma_mask = &orion_xor_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(64),
+ .platform_data = &orion_xor11_data,
+ },
+};
+
+void __init orion_xor1_init(unsigned long mapbase_low,
+ unsigned long mapbase_high,
+ unsigned long irq_0,
+ unsigned long irq_1)
+{
+ orion_xor1_shared_resources[0].start = mapbase_low;
+ orion_xor1_shared_resources[0].end = mapbase_low + 0xff;
+ orion_xor1_shared_resources[1].start = mapbase_high;
+ orion_xor1_shared_resources[1].end = mapbase_high + 0xff;
+
+ orion_xor10_resources[0].start = irq_0;
+ orion_xor10_resources[0].end = irq_0;
+ orion_xor11_resources[0].start = irq_1;
+ orion_xor11_resources[0].end = irq_1;
+
+ platform_device_register(&orion_xor1_shared);
+
+ orion_xor_init_channels(&orion_xor10_data, &orion_xor10_channel,
+ &orion_xor11_data, &orion_xor11_channel);
+}
+
+/*****************************************************************************
+ * EHCI
+ ****************************************************************************/
+static struct orion_ehci_data orion_ehci_data;
+static u64 ehci_dmamask = DMA_BIT_MASK(32);
+
+
+/*****************************************************************************
+ * EHCI0
+ ****************************************************************************/
+static struct resource orion_ehci_resources[2];
+
+static struct platform_device orion_ehci = {
+ .name = "orion-ehci",
+ .id = 0,
+ .dev = {
+ .dma_mask = &ehci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &orion_ehci_data,
+ },
+};
+
+void __init orion_ehci_init(unsigned long mapbase,
+ unsigned long irq,
+ enum orion_ehci_phy_ver phy_version)
+{
+ orion_ehci_data.phy_version = phy_version;
+ fill_resources(&orion_ehci, orion_ehci_resources, mapbase, SZ_4K - 1,
+ irq);
+
+ platform_device_register(&orion_ehci);
+}
+
+/*****************************************************************************
+ * EHCI1
+ ****************************************************************************/
+static struct resource orion_ehci_1_resources[2];
+
+static struct platform_device orion_ehci_1 = {
+ .name = "orion-ehci",
+ .id = 1,
+ .dev = {
+ .dma_mask = &ehci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &orion_ehci_data,
+ },
+};
+
+void __init orion_ehci_1_init(unsigned long mapbase,
+ unsigned long irq)
+{
+ fill_resources(&orion_ehci_1, orion_ehci_1_resources,
+ mapbase, SZ_4K - 1, irq);
+
+ platform_device_register(&orion_ehci_1);
+}
+
+/*****************************************************************************
+ * EHCI2
+ ****************************************************************************/
+static struct resource orion_ehci_2_resources[2];
+
+static struct platform_device orion_ehci_2 = {
+ .name = "orion-ehci",
+ .id = 2,
+ .dev = {
+ .dma_mask = &ehci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &orion_ehci_data,
+ },
+};
+
+void __init orion_ehci_2_init(unsigned long mapbase,
+ unsigned long irq)
+{
+ fill_resources(&orion_ehci_2, orion_ehci_2_resources,
+ mapbase, SZ_4K - 1, irq);
+
+ platform_device_register(&orion_ehci_2);
+}
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct resource orion_sata_resources[2] = {
+ {
+ .name = "sata base",
+ }, {
+ .name = "sata irq",
+ },
+};
+
+static struct platform_device orion_sata = {
+ .name = "sata_mv",
+ .id = 0,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init orion_sata_init(struct mv_sata_platform_data *sata_data,
+ unsigned long mapbase,
+ unsigned long irq)
+{
+ orion_sata.dev.platform_data = sata_data;
+ fill_resources(&orion_sata, orion_sata_resources,
+ mapbase, 0x5000 - 1, irq);
+
+ platform_device_register(&orion_sata);
+}
+
+/*****************************************************************************
+ * Cryptographic Engines and Security Accelerator (CESA)
+ ****************************************************************************/
+static struct resource orion_crypto_resources[] = {
+ {
+ .name = "regs",
+ }, {
+ .name = "crypto interrupt",
+ }, {
+ .name = "sram",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device orion_crypto = {
+ .name = "mv_crypto",
+ .id = -1,
+};
+
+void __init orion_crypto_init(unsigned long mapbase,
+ unsigned long srambase,
+ unsigned long sram_size,
+ unsigned long irq)
+{
+ fill_resources(&orion_crypto, orion_crypto_resources,
+ mapbase, 0xffff, irq);
+ orion_crypto.num_resources = 3;
+ orion_crypto_resources[2].start = srambase;
+ orion_crypto_resources[2].end = srambase + sram_size - 1;
+
+ platform_device_register(&orion_crypto);
+}
diff -urN a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
--- a/drivers/mmc/core/core.c 2012-05-20 18:29:13.000000000 -0400
+++ b/drivers/mmc/core/core.c 2012-05-24 12:02:12.000000000 -0400
@@ -536,7 +536,7 @@
*/
limit_us = 3000000;
else
- limit_us = 100000;
+ limit_us = 200000;
/*
* SDHC cards always use these fixed values.
diff -urN a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
--- a/drivers/mmc/core/sd.c 2012-05-20 18:29:13.000000000 -0400
+++ b/drivers/mmc/core/sd.c 2012-05-24 12:02:12.000000000 -0400
@@ -389,6 +389,15 @@
return -ENOMEM;
}
+ /*
+ * Some SDHC cards, notably those with a Sandisk SD controller
+ * (also found in Kingston products) need a bit of slack
+ * before successfully handling the SWITCH command. So far,
+ * cards identifying themselves as "SD04G" and "SD08G" are
+ * affected
+ */
+ udelay(100);
+
err = mmc_sd_switch(card, 1, 0, 1, status);
if (err)
goto out;
diff -urN a/drivers/mmc/core/sd.c.orig b/drivers/mmc/core/sd.c.orig
--- a/drivers/mmc/core/sd.c.orig 1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/mmc/core/sd.c.orig 2012-05-24 12:02:12.000000000 -0400
@@ -0,0 +1,1245 @@
+/*
+ * linux/drivers/mmc/core/sd.c
+ *
+ * Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *
+ * 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 <linux/err.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include "core.h"
+#include "bus.h"
+#include "mmc_ops.h"
+#include "sd.h"
+#include "sd_ops.h"
+
+static const unsigned int tran_exp[] = {
+ 10000, 100000, 1000000, 10000000,
+ 0, 0, 0, 0
+};
+
+static const unsigned char tran_mant[] = {
+ 0, 10, 12, 13, 15, 20, 25, 30,
+ 35, 40, 45, 50, 55, 60, 70, 80,
+};
+
+static const unsigned int tacc_exp[] = {
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] = {
+ 0, 10, 12, 13, 15, 20, 25, 30,
+ 35, 40, 45, 50, 55, 60, 70, 80,
+};
+
+#define UNSTUFF_BITS(resp,start,size) \
+ ({ \
+ const int __size = size; \
+ const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
+ const int __off = 3 - ((start) / 32); \
+ const int __shft = (start) & 31; \
+ u32 __res; \
+ \
+ __res = resp[__off] >> __shft; \
+ if (__size + __shft > 32) \
+ __res |= resp[__off-1] << ((32 - __shft) % 32); \
+ __res & __mask; \
+ })
+
+/*
+ * Given the decoded CSD structure, decode the raw CID to our CID structure.
+ */
+void mmc_decode_cid(struct mmc_card *card)
+{
+ u32 *resp = card->raw_cid;
+
+ memset(&card->cid, 0, sizeof(struct mmc_cid));
+
+ /*
+ * SD doesn't currently have a version field so we will
+ * have to assume we can parse this.
+ */
+ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8);
+ card->cid.oemid = UNSTUFF_BITS(resp, 104, 16);
+ card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
+ card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
+ card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
+ card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
+ card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
+ card->cid.hwrev = UNSTUFF_BITS(resp, 60, 4);
+ card->cid.fwrev = UNSTUFF_BITS(resp, 56, 4);
+ card->cid.serial = UNSTUFF_BITS(resp, 24, 32);
+ card->cid.year = UNSTUFF_BITS(resp, 12, 8);
+ card->cid.month = UNSTUFF_BITS(resp, 8, 4);
+
+ card->cid.year += 2000; /* SD cards year offset */
+}
+
+/*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+static int mmc_decode_csd(struct mmc_card *card)
+{
+ struct mmc_csd *csd = &card->csd;
+ unsigned int e, m, csd_struct;
+ u32 *resp = card->raw_csd;
+
+ csd_struct = UNSTUFF_BITS(resp, 126, 2);
+
+ switch (csd_struct) {
+ case 0:
+ m = UNSTUFF_BITS(resp, 115, 4);
+ e = UNSTUFF_BITS(resp, 112, 3);
+ csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+ csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+ m = UNSTUFF_BITS(resp, 99, 4);
+ e = UNSTUFF_BITS(resp, 96, 3);
+ csd->max_dtr = tran_exp[e] * tran_mant[m];
+ csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
+
+ e = UNSTUFF_BITS(resp, 47, 3);
+ m = UNSTUFF_BITS(resp, 62, 12);
+ csd->capacity = (1 + m) << (e + 2);
+
+ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+ csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+ csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+ csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+ csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+ csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+
+ if (UNSTUFF_BITS(resp, 46, 1)) {
+ csd->erase_size = 1;
+ } else if (csd->write_blkbits >= 9) {
+ csd->erase_size = UNSTUFF_BITS(resp, 39, 7) + 1;
+ csd->erase_size <<= csd->write_blkbits - 9;
+ }
+ break;
+ case 1:
+ /*
+ * This is a block-addressed SDHC or SDXC card. Most
+ * interesting fields are unused and have fixed
+ * values. To avoid getting tripped by buggy cards,
+ * we assume those fixed values ourselves.
+ */
+ mmc_card_set_blockaddr(card);
+
+ csd->tacc_ns = 0; /* Unused */
+ csd->tacc_clks = 0; /* Unused */
+
+ m = UNSTUFF_BITS(resp, 99, 4);
+ e = UNSTUFF_BITS(resp, 96, 3);
+ csd->max_dtr = tran_exp[e] * tran_mant[m];
+ csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
+ csd->c_size = UNSTUFF_BITS(resp, 48, 22);
+
+ /* SDXC cards have a minimum C_SIZE of 0x00FFFF */
+ if (csd->c_size >= 0xFFFF)
+ mmc_card_set_ext_capacity(card);
+
+ m = UNSTUFF_BITS(resp, 48, 22);
+ csd->capacity = (1 + m) << 10;
+
+ csd->read_blkbits = 9;
+ csd->read_partial = 0;
+ csd->write_misalign = 0;
+ csd->read_misalign = 0;
+ csd->r2w_factor = 4; /* Unused */
+ csd->write_blkbits = 9;
+ csd->write_partial = 0;
+ csd->erase_size = 1;
+ break;
+ default:
+ pr_err("%s: unrecognised CSD structure version %d\n",
+ mmc_hostname(card->host), csd_struct);
+ return -EINVAL;
+ }
+
+ card->erase_size = csd->erase_size;
+
+ return 0;
+}
+
+/*
+ * Given a 64-bit response, decode to our card SCR structure.
+ */
+static int mmc_decode_scr(struct mmc_card *card)
+{
+ struct sd_scr *scr = &card->scr;
+ unsigned int scr_struct;
+ u32 resp[4];
+
+ resp[3] = card->raw_scr[1];
+ resp[2] = card->raw_scr[0];
+
+ scr_struct = UNSTUFF_BITS(resp, 60, 4);
+ if (scr_struct != 0) {
+ pr_err("%s: unrecognised SCR structure version %d\n",
+ mmc_hostname(card->host), scr_struct);
+ return -EINVAL;
+ }
+
+ scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
+ scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
+ if (scr->sda_vsn == SCR_SPEC_VER_2)
+ /* Check if Physical Layer Spec v3.0 is supported */
+ scr->sda_spec3 = UNSTUFF_BITS(resp, 47, 1);
+
+ if (UNSTUFF_BITS(resp, 55, 1))
+ card->erased_byte = 0xFF;
+ else
+ card->erased_byte = 0x0;
+
+ if (scr->sda_spec3)
+ scr->cmds = UNSTUFF_BITS(resp, 32, 2);
+ return 0;
+}
+
+/*
+ * Fetch and process SD Status register.
+ */
+static int mmc_read_ssr(struct mmc_card *card)
+{
+ unsigned int au, es, et, eo;
+ int err, i;
+ u32 *ssr;
+
+ if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
+ pr_warning("%s: card lacks mandatory SD Status "
+ "function.\n", mmc_hostname(card->host));
+ return 0;
+ }
+
+ ssr = kmalloc(64, GFP_KERNEL);
+ if (!ssr)
+ return -ENOMEM;
+
+ err = mmc_app_sd_status(card, ssr);
+ if (err) {
+ pr_warning("%s: problem reading SD Status "
+ "register.\n", mmc_hostname(card->host));
+ err = 0;
+ goto out;
+ }
+
+ for (i = 0; i < 16; i++)
+ ssr[i] = be32_to_cpu(ssr[i]);
+
+ /*
+ * UNSTUFF_BITS only works with four u32s so we have to offset the
+ * bitfield positions accordingly.
+ */
+ au = UNSTUFF_BITS(ssr, 428 - 384, 4);
+ if (au > 0 || au <= 9) {
+ card->ssr.au = 1 << (au + 4);
+ es = UNSTUFF_BITS(ssr, 408 - 384, 16);
+ et = UNSTUFF_BITS(ssr, 402 - 384, 6);
+ eo = UNSTUFF_BITS(ssr, 400 - 384, 2);
+ if (es && et) {
+ card->ssr.erase_timeout = (et * 1000) / es;
+ card->ssr.erase_offset = eo * 1000;
+ }
+ } else {
+ pr_warning("%s: SD Status: Invalid Allocation Unit "
+ "size.\n", mmc_hostname(card->host));
+ }
+out:
+ kfree(ssr);
+ return err;
+}
+
+/*
+ * Fetches and decodes switch information
+ */
+static int mmc_read_switch(struct mmc_card *card)
+{
+ int err;
+ u8 *status;
+
+ if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+ return 0;
+
+ if (!(card->csd.cmdclass & CCC_SWITCH)) {
+ pr_warning("%s: card lacks mandatory switch "
+ "function, performance might suffer.\n",
+ mmc_hostname(card->host));
+ return 0;
+ }
+
+ err = -EIO;
+
+ status = kmalloc(64, GFP_KERNEL);
+ if (!status) {
+ pr_err("%s: could not allocate a buffer for "
+ "switch capabilities.\n",
+ mmc_hostname(card->host));
+ return -ENOMEM;
+ }
+
+ /* Find out the supported Bus Speed Modes. */
+ err = mmc_sd_switch(card, 0, 0, 1, status);
+ if (err) {
+ /*
+ * If the host or the card can't do the switch,
+ * fail more gracefully.
+ */
+ if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
+ goto out;
+
+ pr_warning("%s: problem reading Bus Speed modes.\n",
+ mmc_hostname(card->host));
+ err = 0;
+
+ goto out;
+ }
+
+ if (status[13] & SD_MODE_HIGH_SPEED)
+ card->sw_caps.hs_max_dtr = HIGH_SPEED_MAX_DTR;
+
+ if (card->scr.sda_spec3) {
+ card->sw_caps.sd3_bus_mode = status[13];
+
+ /* Find out Driver Strengths supported by the card */
+ err = mmc_sd_switch(card, 0, 2, 1, status);
+ if (err) {
+ /*
+ * If the host or the card can't do the switch,
+ * fail more gracefully.
+ */
+ if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
+ goto out;
+
+ pr_warning("%s: problem reading "
+ "Driver Strength.\n",
+ mmc_hostname(card->host));
+ err = 0;
+
+ goto out;
+ }
+
+ card->sw_caps.sd3_drv_type = status[9];
+
+ /* Find out Current Limits supported by the card */
+ err = mmc_sd_switch(card, 0, 3, 1, status);
+ if (err) {
+ /*
+ * If the host or the card can't do the switch,
+ * fail more gracefully.
+ */
+ if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
+ goto out;
+
+ pr_warning("%s: problem reading "
+ "Current Limit.\n",
+ mmc_hostname(card->host));
+ err = 0;
+
+ goto out;
+ }
+
+ card->sw_caps.sd3_curr_limit = status[7];
+ }
+
+out:
+ kfree(status);
+
+ return err;
+}
+
+/*
+ * Test if the card supports high-speed mode and, if so, switch to it.
+ */
+int mmc_sd_switch_hs(struct mmc_card *card)
+{
+ int err;
+ u8 *status;
+
+ if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+ return 0;
+
+ if (!(card->csd.cmdclass & CCC_SWITCH))
+ return 0;
+
+ if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
+ return 0;
+
+ if (card->sw_caps.hs_max_dtr == 0)
+ return 0;
+
+ err = -EIO;
+
+ status = kmalloc(64, GFP_KERNEL);
+ if (!status) {
+ pr_err("%s: could not allocate a buffer for "
+ "switch capabilities.\n", mmc_hostname(card->host));
+ return -ENOMEM;
+ }
+
+ err = mmc_sd_switch(card, 1, 0, 1, status);
+ if (err)
+ goto out;
+
+ if ((status[16] & 0xF) != 1) {
+ pr_warning("%s: Problem switching card "
+ "into high-speed mode!\n",
+ mmc_hostname(card->host));
+ err = 0;
+ } else {
+ err = 1;
+ }
+
+out:
+ kfree(status);
+
+ return err;
+}
+
+static int sd_select_driver_type(struct mmc_card *card, u8 *status)
+{
+ int host_drv_type = SD_DRIVER_TYPE_B;
+ int card_drv_type = SD_DRIVER_TYPE_B;
+ int drive_strength;
+ int err;
+
+ /*
+ * If the host doesn't support any of the Driver Types A,C or D,
+ * or there is no board specific handler then default Driver
+ * Type B is used.
+ */
+ if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C
+ | MMC_CAP_DRIVER_TYPE_D)))
+ return 0;
+
+ if (!card->host->ops->select_drive_strength)
+ return 0;
+
+ if (card->host->caps & MMC_CAP_DRIVER_TYPE_A)
+ host_drv_type |= SD_DRIVER_TYPE_A;
+
+ if (card->host->caps & MMC_CAP_DRIVER_TYPE_C)
+ host_drv_type |= SD_DRIVER_TYPE_C;
+
+ if (card->host->caps & MMC_CAP_DRIVER_TYPE_D)
+ host_drv_type |= SD_DRIVER_TYPE_D;
+
+ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
+ card_drv_type |= SD_DRIVER_TYPE_A;
+
+ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
+ card_drv_type |= SD_DRIVER_TYPE_C;
+
+ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D)
+ card_drv_type |= SD_DRIVER_TYPE_D;
+
+ /*
+ * The drive strength that the hardware can support
+ * depends on the board design. Pass the appropriate
+ * information and let the hardware specific code
+ * return what is possible given the options
+ */
+ mmc_host_clk_hold(card->host);
+ drive_strength = card->host->ops->select_drive_strength(
+ card->sw_caps.uhs_max_dtr,
+ host_drv_type, card_drv_type);
+ mmc_host_clk_release(card->host);
+
+ err = mmc_sd_switch(card, 1, 2, drive_strength, status);
+ if (err)
+ return err;
+
+ if ((status[15] & 0xF) != drive_strength) {
+ pr_warning("%s: Problem setting drive strength!\n",
+ mmc_hostname(card->host));
+ return 0;
+ }
+
+ mmc_set_driver_type(card->host, drive_strength);
+
+ return 0;
+}
+
+static void sd_update_bus_speed_mode(struct mmc_card *card)
+{
+ /*
+ * If the host doesn't support any of the UHS-I modes, fallback on
+ * default speed.
+ */
+ if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))) {
+ card->sd_bus_speed = 0;
+ return;
+ }
+
+ if ((card->host->caps & MMC_CAP_UHS_SDR104) &&
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) {
+ card->sd_bus_speed = UHS_SDR104_BUS_SPEED;
+ } else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {
+ card->sd_bus_speed = UHS_DDR50_BUS_SPEED;
+ } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
+ MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
+ SD_MODE_UHS_SDR50)) {
+ card->sd_bus_speed = UHS_SDR50_BUS_SPEED;
+ } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {
+ card->sd_bus_speed = UHS_SDR25_BUS_SPEED;
+ } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
+ MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode &
+ SD_MODE_UHS_SDR12)) {
+ card->sd_bus_speed = UHS_SDR12_BUS_SPEED;
+ }
+}
+
+static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
+{
+ int err;
+ unsigned int timing = 0;
+
+ switch (card->sd_bus_speed) {
+ case UHS_SDR104_BUS_SPEED:
+ timing = MMC_TIMING_UHS_SDR104;
+ card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR;
+ break;
+ case UHS_DDR50_BUS_SPEED:
+ timing = MMC_TIMING_UHS_DDR50;
+ card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR;
+ break;
+ case UHS_SDR50_BUS_SPEED:
+ timing = MMC_TIMING_UHS_SDR50;
+ card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR;
+ break;
+ case UHS_SDR25_BUS_SPEED:
+ timing = MMC_TIMING_UHS_SDR25;
+ card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR;
+ break;
+ case UHS_SDR12_BUS_SPEED:
+ timing = MMC_TIMING_UHS_SDR12;
+ card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR;
+ break;
+ default:
+ return 0;
+ }
+
+ err = mmc_sd_switch(card, 1, 0, card->sd_bus_speed, status);
+ if (err)
+ return err;
+
+ if ((status[16] & 0xF) != card->sd_bus_speed)
+ pr_warning("%s: Problem setting bus speed mode!\n",
+ mmc_hostname(card->host));
+ else {
+ mmc_set_timing(card->host, timing);
+ mmc_set_clock(card->host, card->sw_caps.uhs_max_dtr);
+ }
+
+ return 0;
+}
+
+static int sd_set_current_limit(struct mmc_card *card, u8 *status)
+{
+ int current_limit = 0;
+ int err;
+
+ /*
+ * Current limit switch is only defined for SDR50, SDR104, and DDR50
+ * bus speed modes. For other bus speed modes, we set the default
+ * current limit of 200mA.
+ */
+ if ((card->sd_bus_speed == UHS_SDR50_BUS_SPEED) ||
+ (card->sd_bus_speed == UHS_SDR104_BUS_SPEED) ||
+ (card->sd_bus_speed == UHS_DDR50_BUS_SPEED)) {
+ if (card->host->caps & MMC_CAP_MAX_CURRENT_800) {
+ if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_800)
+ current_limit = SD_SET_CURRENT_LIMIT_800;
+ else if (card->sw_caps.sd3_curr_limit &
+ SD_MAX_CURRENT_600)
+ current_limit = SD_SET_CURRENT_LIMIT_600;
+ else if (card->sw_caps.sd3_curr_limit &
+ SD_MAX_CURRENT_400)
+ current_limit = SD_SET_CURRENT_LIMIT_400;
+ else if (card->sw_caps.sd3_curr_limit &
+ SD_MAX_CURRENT_200)
+ current_limit = SD_SET_CURRENT_LIMIT_200;
+ } else if (card->host->caps & MMC_CAP_MAX_CURRENT_600) {
+ if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_600)
+ current_limit = SD_SET_CURRENT_LIMIT_600;
+ else if (card->sw_caps.sd3_curr_limit &
+ SD_MAX_CURRENT_400)
+ current_limit = SD_SET_CURRENT_LIMIT_400;
+ else if (card->sw_caps.sd3_curr_limit &
+ SD_MAX_CURRENT_200)
+ current_limit = SD_SET_CURRENT_LIMIT_200;
+ } else if (card->host->caps & MMC_CAP_MAX_CURRENT_400) {
+ if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_400)
+ current_limit = SD_SET_CURRENT_LIMIT_400;
+ else if (card->sw_caps.sd3_curr_limit &
+ SD_MAX_CURRENT_200)
+ current_limit = SD_SET_CURRENT_LIMIT_200;
+ } else if (card->host->caps & MMC_CAP_MAX_CURRENT_200) {
+ if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_200)
+ current_limit = SD_SET_CURRENT_LIMIT_200;
+ }
+ } else
+ current_limit = SD_SET_CURRENT_LIMIT_200;
+
+ err = mmc_sd_switch(card, 1, 3, current_limit, status);
+ if (err)
+ return err;
+
+ if (((status[15] >> 4) & 0x0F) != current_limit)
+ pr_warning("%s: Problem setting current limit!\n",
+ mmc_hostname(card->host));
+
+ return 0;
+}
+
+/*
+ * UHS-I specific initialization procedure
+ */
+static int mmc_sd_init_uhs_card(struct mmc_card *card)
+{
+ int err;
+ u8 *status;
+
+ if (!card->scr.sda_spec3)
+ return 0;
+
+ if (!(card->csd.cmdclass & CCC_SWITCH))
+ return 0;
+
+ status = kmalloc(64, GFP_KERNEL);
+ if (!status) {
+ pr_err("%s: could not allocate a buffer for "
+ "switch capabilities.\n", mmc_hostname(card->host));
+ return -ENOMEM;
+ }
+
+ /* Set 4-bit bus width */
+ if ((card->host->caps & MMC_CAP_4_BIT_DATA) &&
+ (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+ err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
+ if (err)
+ goto out;
+
+ mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
+ }
+
+ /*
+ * Select the bus speed mode depending on host
+ * and card capability.
+ */
+ sd_update_bus_speed_mode(card);
+
+ /* Set the driver strength for the card */
+ err = sd_select_driver_type(card, status);
+ if (err)
+ goto out;
+
+ /* Set current limit for the card */
+ err = sd_set_current_limit(card, status);
+ if (err)
+ goto out;
+
+ /* Set bus speed mode of the card */
+ err = sd_set_bus_speed_mode(card, status);
+ if (err)
+ goto out;
+
+ /* SPI mode doesn't define CMD19 */
+ if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) {
+ mmc_host_clk_hold(card->host);
+ err = card->host->ops->execute_tuning(card->host,
+ MMC_SEND_TUNING_BLOCK);
+ mmc_host_clk_release(card->host);
+ }
+
+out:
+ kfree(status);
+
+ return err;
+}
+
+MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+ card->raw_cid[2], card->raw_cid[3]);
+MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+ card->raw_csd[2], card->raw_csd[3]);
+MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
+MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9);
+MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9);
+MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
+MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
+MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
+MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
+
+
+static struct attribute *sd_std_attrs[] = {
+ &dev_attr_cid.attr,
+ &dev_attr_csd.attr,
+ &dev_attr_scr.attr,
+ &dev_attr_date.attr,
+ &dev_attr_erase_size.attr,
+ &dev_attr_preferred_erase_size.attr,
+ &dev_attr_fwrev.attr,
+ &dev_attr_hwrev.attr,
+ &dev_attr_manfid.attr,
+ &dev_attr_name.attr,
+ &dev_attr_oemid.attr,
+ &dev_attr_serial.attr,
+ NULL,
+};
+
+static struct attribute_group sd_std_attr_group = {
+ .attrs = sd_std_attrs,
+};
+
+static const struct attribute_group *sd_attr_groups[] = {
+ &sd_std_attr_group,
+ NULL,
+};
+
+struct device_type sd_type = {
+ .groups = sd_attr_groups,
+};
+
+/*
+ * Fetch CID from card.
+ */
+int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
+{
+ int err;
+
+ /*
+ * Since we're changing the OCR value, we seem to
+ * need to tell some cards to go back to the idle
+ * state. We wait 1ms to give cards time to
+ * respond.
+ */
+ mmc_go_idle(host);
+
+ /*
+ * If SD_SEND_IF_COND indicates an SD 2.0
+ * compliant card and we should set bit 30
+ * of the ocr to indicate that we can handle
+ * block-addressed SDHC cards.
+ */
+ err = mmc_send_if_cond(host, ocr);
+ if (!err)
+ ocr |= SD_OCR_CCS;
+
+ /*
+ * If the host supports one of UHS-I modes, request the card
+ * to switch to 1.8V signaling level.
+ */
+ if (host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))
+ ocr |= SD_OCR_S18R;
+
+ /* If the host can supply more than 150mA, XPC should be set to 1. */
+ if (host->caps & (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
+ MMC_CAP_SET_XPC_180))
+ ocr |= SD_OCR_XPC;
+
+try_again:
+ err = mmc_send_app_op_cond(host, ocr, rocr);
+ if (err)
+ return err;
+
+ /*
+ * In case CCS and S18A in the response is set, start Signal Voltage
+ * Switch procedure. SPI mode doesn't support CMD11.
+ */
+ if (!mmc_host_is_spi(host) && rocr &&
+ ((*rocr & 0x41000000) == 0x41000000)) {
+ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, true);
+ if (err) {
+ ocr &= ~SD_OCR_S18R;
+ goto try_again;
+ }
+ }
+
+ if (mmc_host_is_spi(host))
+ err = mmc_send_cid(host, cid);
+ else
+ err = mmc_all_send_cid(host, cid);
+
+ return err;
+}
+
+int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card)
+{
+ int err;
+
+ /*
+ * Fetch CSD from card.
+ */
+ err = mmc_send_csd(card, card->raw_csd);
+ if (err)
+ return err;
+
+ err = mmc_decode_csd(card);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
+ bool reinit)
+{
+ int err;
+
+ if (!reinit) {
+ /*
+ * Fetch SCR from card.
+ */
+ err = mmc_app_send_scr(card, card->raw_scr);
+ if (err)
+ return err;
+
+ err = mmc_decode_scr(card);
+ if (err)
+ return err;
+
+ /*
+ * Fetch and process SD Status register.
+ */
+ err = mmc_read_ssr(card);
+ if (err)
+ return err;
+
+ /* Erase init depends on CSD and SSR */
+ mmc_init_erase(card);
+
+ /*
+ * Fetch switch information from card.
+ */
+ err = mmc_read_switch(card);
+ if (err)
+ return err;
+ }
+
+ /*
+ * For SPI, enable CRC as appropriate.
+ * This CRC enable is located AFTER the reading of the
+ * card registers because some SDHC cards are not able
+ * to provide valid CRCs for non-512-byte blocks.
+ */
+ if (mmc_host_is_spi(host)) {
+ err = mmc_spi_set_crc(host, use_spi_crc);
+ if (err)
+ return err;
+ }
+
+ /*
+ * Check if read-only switch is active.
+ */
+ if (!reinit) {
+ int ro = -1;
+
+ if (host->ops->get_ro) {
+ mmc_host_clk_hold(card->host);
+ ro = host->ops->get_ro(host);
+ mmc_host_clk_release(card->host);
+ }
+
+ if (ro < 0) {
+ pr_warning("%s: host does not "
+ "support reading read-only "
+ "switch. assuming write-enable.\n",
+ mmc_hostname(host));
+ } else if (ro > 0) {
+ mmc_card_set_readonly(card);
+ }
+ }
+
+ return 0;
+}
+
+unsigned mmc_sd_get_max_clock(struct mmc_card *card)
+{
+ unsigned max_dtr = (unsigned int)-1;
+
+ if (mmc_card_highspeed(card)) {
+ if (max_dtr > card->sw_caps.hs_max_dtr)
+ max_dtr = card->sw_caps.hs_max_dtr;
+ } else if (max_dtr > card->csd.max_dtr) {
+ max_dtr = card->csd.max_dtr;
+ }
+
+ return max_dtr;
+}
+
+void mmc_sd_go_highspeed(struct mmc_card *card)
+{
+ mmc_card_set_highspeed(card);
+ mmc_set_timing(card->host, MMC_TIMING_SD_HS);
+}
+
+/*
+ * Handle the detection and initialisation of a card.
+ *
+ * In the case of a resume, "oldcard" will contain the card
+ * we're trying to reinitialise.
+ */
+static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+ struct mmc_card *oldcard)
+{
+ struct mmc_card *card;
+ int err;
+ u32 cid[4];
+ u32 rocr = 0;
+
+ BUG_ON(!host);
+ WARN_ON(!host->claimed);
+
+ /* The initialization should be done at 3.3 V I/O voltage. */
+ mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
+
+ err = mmc_sd_get_cid(host, ocr, cid, &rocr);
+ if (err)
+ return err;
+
+ if (oldcard) {
+ if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
+ return -ENOENT;
+
+ card = oldcard;
+ } else {
+ /*
+ * Allocate card structure.
+ */
+ card = mmc_alloc_card(host, &sd_type);
+ if (IS_ERR(card))
+ return PTR_ERR(card);
+
+ card->type = MMC_TYPE_SD;
+ memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+ }
+
+ /*
+ * For native busses: get card RCA and quit open drain mode.
+ */
+ if (!mmc_host_is_spi(host)) {
+ err = mmc_send_relative_addr(host, &card->rca);
+ if (err)
+ return err;
+ }
+
+ if (!oldcard) {
+ err = mmc_sd_get_csd(host, card);
+ if (err)
+ return err;
+
+ mmc_decode_cid(card);
+ }
+
+ /*
+ * Select card, as all following commands rely on that.
+ */
+ if (!mmc_host_is_spi(host)) {
+ err = mmc_select_card(card);
+ if (err)
+ return err;
+ }
+
+ err = mmc_sd_setup_card(host, card, oldcard != NULL);
+ if (err)
+ goto free_card;
+
+ /* Initialization sequence for UHS-I cards */
+ if (rocr & SD_ROCR_S18A) {
+ err = mmc_sd_init_uhs_card(card);
+ if (err)
+ goto free_card;
+
+ /* Card is an ultra-high-speed card */
+ mmc_card_set_uhs(card);
+
+ /*
+ * Since initialization is now complete, enable preset
+ * value registers for UHS-I cards.
+ */
+ if (host->ops->enable_preset_value) {
+ mmc_host_clk_hold(card->host);
+ host->ops->enable_preset_value(host, true);
+ mmc_host_clk_release(card->host);
+ }
+ } else {
+ /*
+ * Attempt to change to high-speed (if supported)
+ */
+ err = mmc_sd_switch_hs(card);
+ if (err > 0)
+ mmc_sd_go_highspeed(card);
+ else if (err)
+ goto free_card;
+
+ /*
+ * Set bus speed.
+ */
+ mmc_set_clock(host, mmc_sd_get_max_clock(card));
+
+ /*
+ * Switch to wider bus (if supported).
+ */
+ if ((host->caps & MMC_CAP_4_BIT_DATA) &&
+ (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+ err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
+ if (err)
+ goto free_card;
+
+ mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
+ }
+ }
+
+ host->card = card;
+ return 0;
+
+free_card:
+ if (!oldcard)
+ mmc_remove_card(card);
+
+ return err;
+}
+
+/*
+ * Host is being removed. Free up the current card.
+ */
+static void mmc_sd_remove(struct mmc_host *host)
+{
+ BUG_ON(!host);
+ BUG_ON(!host->card);
+
+ mmc_remove_card(host->card);
+ host->card = NULL;
+}
+
+/*
+ * Card detection - card is alive.
+ */
+static int mmc_sd_alive(struct mmc_host *host)
+{
+ return mmc_send_status(host->card, NULL);
+}
+
+/*
+ * Card detection callback from host.
+ */
+static void mmc_sd_detect(struct mmc_host *host)
+{
+ int err;
+
+ BUG_ON(!host);
+ BUG_ON(!host->card);
+
+ mmc_claim_host(host);
+
+ /*
+ * Just check if our card has been removed.
+ */
+ err = _mmc_detect_card_removed(host);
+
+ mmc_release_host(host);
+
+ if (err) {
+ mmc_sd_remove(host);
+
+ mmc_claim_host(host);
+ mmc_detach_bus(host);
+ mmc_power_off(host);
+ mmc_release_host(host);
+ }
+}
+
+/*
+ * Suspend callback from host.
+ */
+static int mmc_sd_suspend(struct mmc_host *host)
+{
+ BUG_ON(!host);
+ BUG_ON(!host->card);
+
+ mmc_claim_host(host);
+ if (!mmc_host_is_spi(host))
+ mmc_deselect_cards(host);
+ host->card->state &= ~MMC_STATE_HIGHSPEED;
+ mmc_release_host(host);
+
+ return 0;
+}
+
+/*
+ * Resume callback from host.
+ *
+ * This function tries to determine if the same card is still present
+ * and, if so, restore all state to it.
+ */
+static int mmc_sd_resume(struct mmc_host *host)
+{
+ int err;
+
+ BUG_ON(!host);
+ BUG_ON(!host->card);
+
+ mmc_claim_host(host);
+ err = mmc_sd_init_card(host, host->ocr, host->card);
+ mmc_release_host(host);
+
+ return err;
+}
+
+static int mmc_sd_power_restore(struct mmc_host *host)
+{
+ int ret;
+
+ host->card->state &= ~MMC_STATE_HIGHSPEED;
+ mmc_claim_host(host);
+ ret = mmc_sd_init_card(host, host->ocr, host->card);
+ mmc_release_host(host);
+
+ return ret;
+}
+
+static const struct mmc_bus_ops mmc_sd_ops = {
+ .remove = mmc_sd_remove,
+ .detect = mmc_sd_detect,
+ .suspend = NULL,
+ .resume = NULL,
+ .power_restore = mmc_sd_power_restore,
+ .alive = mmc_sd_alive,
+};
+
+static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
+ .remove = mmc_sd_remove,
+ .detect = mmc_sd_detect,
+ .suspend = mmc_sd_suspend,
+ .resume = mmc_sd_resume,
+ .power_restore = mmc_sd_power_restore,
+ .alive = mmc_sd_alive,
+};
+
+static void mmc_sd_attach_bus_ops(struct mmc_host *host)
+{
+ const struct mmc_bus_ops *bus_ops;
+
+ if (!mmc_card_is_removable(host))
+ bus_ops = &mmc_sd_ops_unsafe;
+ else
+ bus_ops = &mmc_sd_ops;
+ mmc_attach_bus(host, bus_ops);
+}
+
+/*
+ * Starting point for SD card init.
+ */
+int mmc_attach_sd(struct mmc_host *host)
+{
+ int err;
+ u32 ocr;
+
+ BUG_ON(!host);
+ WARN_ON(!host->claimed);
+
+ /* Disable preset value enable if already set since last time */
+ if (host->ops->enable_preset_value) {
+ mmc_host_clk_hold(host);
+ host->ops->enable_preset_value(host, false);
+ mmc_host_clk_release(host);
+ }
+
+ err = mmc_send_app_op_cond(host, 0, &ocr);
+ if (err)
+ return err;
+
+ mmc_sd_attach_bus_ops(host);
+ if (host->ocr_avail_sd)
+ host->ocr_avail = host->ocr_avail_sd;
+
+ /*
+ * We need to get OCR a different way for SPI.
+ */
+ if (mmc_host_is_spi(host)) {
+ mmc_go_idle(host);
+
+ err = mmc_spi_read_ocr(host, 0, &ocr);
+ if (err)
+ goto err;
+ }
+
+ /*
+ * Sanity check the voltages that the card claims to
+ * support.
+ */
+ if (ocr & 0x7F) {
+ pr_warning("%s: card claims to support voltages "
+ "below the defined range. These will be ignored.\n",
+ mmc_hostname(host));
+ ocr &= ~0x7F;
+ }
+
+ if ((ocr & MMC_VDD_165_195) &&
+ !(host->ocr_avail_sd & MMC_VDD_165_195)) {
+ pr_warning("%s: SD card claims to support the "
+ "incompletely defined 'low voltage range'. This "
+ "will be ignored.\n", mmc_hostname(host));
+ ocr &= ~MMC_VDD_165_195;
+ }
+
+ host->ocr = mmc_select_voltage(host, ocr);
+
+ /*
+ * Can we support the voltage(s) of the card(s)?
+ */
+ if (!host->ocr) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ /*
+ * Detect and init the card.
+ */
+ err = mmc_sd_init_card(host, host->ocr, NULL);
+ if (err)
+ goto err;
+
+ mmc_release_host(host);
+ err = mmc_add_card(host->card);
+ mmc_claim_host(host);
+ if (err)
+ goto remove_card;
+
+ return 0;
+
+remove_card:
+ mmc_release_host(host);
+ mmc_remove_card(host->card);
+ host->card = NULL;
+ mmc_claim_host(host);
+err:
+ mmc_detach_bus(host);
+
+ pr_err("%s: error %d whilst initialising SD card\n",
+ mmc_hostname(host), err);
+
+ return err;
+}
+
diff -urN a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
--- a/drivers/mmc/host/mvsdio.c 2012-05-20 18:29:13.000000000 -0400
+++ b/drivers/mmc/host/mvsdio.c 2012-05-24 12:02:12.000000000 -0400
@@ -21,6 +21,7 @@
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/mmc/host.h>
+#include <linux/mmc/sd.h>
#include <asm/sizes.h>
#include <asm/unaligned.h>
@@ -148,6 +149,7 @@
dev_dbg(host->dev, "cmd %d (hw state 0x%04x)\n",
cmd->opcode, mvsd_read(MVSD_HW_STATE));
+ if (cmd->opcode == SD_SWITCH) mdelay(1); /* Voodoo */
cmdreg = MVSD_CMD_INDEX(cmd->opcode);