Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * arch/arm/mach-orion5x/dns323-setup.c
0003  *
0004  * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
0005  *
0006  * Support for HW Rev C1:
0007  *
0008  * Copyright (C) 2010 Benjamin Herrenschmidt <benh@kernel.crashing.org>
0009  *
0010  * This program is free software; you can redistribute it and/or modify
0011  * it under the terms of the GNU Lesser General Public License as
0012  * published by the Free Software Foundation; either version 2 of the
0013  * License, or (at your option) any later version.
0014  *
0015  */
0016 #include <linux/gpio.h>
0017 #include <linux/kernel.h>
0018 #include <linux/init.h>
0019 #include <linux/delay.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/pci.h>
0022 #include <linux/irq.h>
0023 #include <linux/mtd/physmap.h>
0024 #include <linux/mv643xx_eth.h>
0025 #include <linux/leds.h>
0026 #include <linux/gpio_keys.h>
0027 #include <linux/input.h>
0028 #include <linux/i2c.h>
0029 #include <linux/ata_platform.h>
0030 #include <linux/phy.h>
0031 #include <linux/marvell_phy.h>
0032 #include <asm/mach-types.h>
0033 #include <asm/mach/arch.h>
0034 #include <asm/mach/pci.h>
0035 #include <asm/system_info.h>
0036 #include <plat/orion-gpio.h>
0037 #include "orion5x.h"
0038 #include "common.h"
0039 #include "mpp.h"
0040 
0041 /* Rev A1 and B1 */
0042 #define DNS323_GPIO_LED_RIGHT_AMBER 1
0043 #define DNS323_GPIO_LED_LEFT_AMBER  2
0044 #define DNS323_GPIO_SYSTEM_UP       3
0045 #define DNS323_GPIO_LED_POWER1      4
0046 #define DNS323_GPIO_LED_POWER2      5
0047 #define DNS323_GPIO_OVERTEMP        6
0048 #define DNS323_GPIO_RTC         7
0049 #define DNS323_GPIO_POWER_OFF       8
0050 #define DNS323_GPIO_KEY_POWER       9
0051 #define DNS323_GPIO_KEY_RESET       10
0052 
0053 /* Rev C1 */
0054 #define DNS323C_GPIO_KEY_POWER      1
0055 #define DNS323C_GPIO_POWER_OFF      2
0056 #define DNS323C_GPIO_LED_RIGHT_AMBER    8
0057 #define DNS323C_GPIO_LED_LEFT_AMBER 9
0058 #define DNS323C_GPIO_LED_POWER      17
0059 #define DNS323C_GPIO_FAN_BIT1       18
0060 #define DNS323C_GPIO_FAN_BIT0       19
0061 
0062 /* Exposed to userspace, do not change */
0063 enum {
0064     DNS323_REV_A1,  /* 0 */
0065     DNS323_REV_B1,  /* 1 */
0066     DNS323_REV_C1,  /* 2 */
0067 };
0068 
0069 
0070 /****************************************************************************
0071  * PCI setup
0072  */
0073 
0074 static int __init dns323_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
0075 {
0076     int irq;
0077 
0078     /*
0079      * Check for devices with hard-wired IRQs.
0080      */
0081     irq = orion5x_pci_map_irq(dev, slot, pin);
0082     if (irq != -1)
0083         return irq;
0084 
0085     return -1;
0086 }
0087 
0088 static struct hw_pci dns323_pci __initdata = {
0089     .nr_controllers = 2,
0090     .setup      = orion5x_pci_sys_setup,
0091     .scan       = orion5x_pci_sys_scan_bus,
0092     .map_irq    = dns323_pci_map_irq,
0093 };
0094 
0095 static int __init dns323_pci_init(void)
0096 {
0097     /* Rev B1 and C1 doesn't really use its PCI bus, and initialising PCI
0098      * gets in the way of initialising the SATA controller.
0099      */
0100     if (machine_is_dns323() && system_rev == DNS323_REV_A1)
0101         pci_common_init(&dns323_pci);
0102 
0103     return 0;
0104 }
0105 
0106 subsys_initcall(dns323_pci_init);
0107 
0108 /****************************************************************************
0109  * 8MiB NOR flash (Spansion S29GL064M90TFIR4)
0110  *
0111  * Layout as used by D-Link:
0112  *  0x00000000-0x00010000 : "MTD1"
0113  *  0x00010000-0x00020000 : "MTD2"
0114  *  0x00020000-0x001a0000 : "Linux Kernel"
0115  *  0x001a0000-0x007d0000 : "File System"
0116  *  0x007d0000-0x00800000 : "u-boot"
0117  */
0118 
0119 #define DNS323_NOR_BOOT_BASE 0xf4000000
0120 #define DNS323_NOR_BOOT_SIZE SZ_8M
0121 
0122 static struct mtd_partition dns323_partitions[] = {
0123     {
0124         .name   = "MTD1",
0125         .size   = 0x00010000,
0126         .offset = 0,
0127     }, {
0128         .name   = "MTD2",
0129         .size   = 0x00010000,
0130         .offset = 0x00010000,
0131     }, {
0132         .name   = "Linux Kernel",
0133         .size   = 0x00180000,
0134         .offset = 0x00020000,
0135     }, {
0136         .name   = "File System",
0137         .size   = 0x00630000,
0138         .offset = 0x001A0000,
0139     }, {
0140         .name   = "u-boot",
0141         .size   = 0x00030000,
0142         .offset = 0x007d0000,
0143     },
0144 };
0145 
0146 static struct physmap_flash_data dns323_nor_flash_data = {
0147     .width      = 1,
0148     .parts      = dns323_partitions,
0149     .nr_parts   = ARRAY_SIZE(dns323_partitions)
0150 };
0151 
0152 static struct resource dns323_nor_flash_resource = {
0153     .flags      = IORESOURCE_MEM,
0154     .start      = DNS323_NOR_BOOT_BASE,
0155     .end        = DNS323_NOR_BOOT_BASE + DNS323_NOR_BOOT_SIZE - 1,
0156 };
0157 
0158 static struct platform_device dns323_nor_flash = {
0159     .name       = "physmap-flash",
0160     .id     = 0,
0161     .dev        = {
0162         .platform_data  = &dns323_nor_flash_data,
0163     },
0164     .resource   = &dns323_nor_flash_resource,
0165     .num_resources  = 1,
0166 };
0167 
0168 /****************************************************************************
0169  * Ethernet
0170  */
0171 
0172 static struct mv643xx_eth_platform_data dns323_eth_data = {
0173     .phy_addr = MV643XX_ETH_PHY_ADDR(8),
0174 };
0175 
0176 /* dns323_parse_hex_*() taken from tsx09-common.c; should a common copy of these
0177  * functions be kept somewhere?
0178  */
0179 static int __init dns323_parse_hex_nibble(char n)
0180 {
0181     if (n >= '0' && n <= '9')
0182         return n - '0';
0183 
0184     if (n >= 'A' && n <= 'F')
0185         return n - 'A' + 10;
0186 
0187     if (n >= 'a' && n <= 'f')
0188         return n - 'a' + 10;
0189 
0190     return -1;
0191 }
0192 
0193 static int __init dns323_parse_hex_byte(const char *b)
0194 {
0195     int hi;
0196     int lo;
0197 
0198     hi = dns323_parse_hex_nibble(b[0]);
0199     lo = dns323_parse_hex_nibble(b[1]);
0200 
0201     if (hi < 0 || lo < 0)
0202         return -1;
0203 
0204     return (hi << 4) | lo;
0205 }
0206 
0207 static int __init dns323_read_mac_addr(void)
0208 {
0209     u_int8_t addr[6];
0210     int i;
0211     char *mac_page;
0212 
0213     /* MAC address is stored as a regular ol' string in /dev/mtdblock4
0214      * (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80).
0215      */
0216     mac_page = ioremap(DNS323_NOR_BOOT_BASE + 0x7d0000 + 196480, 1024);
0217     if (!mac_page)
0218         return -ENOMEM;
0219 
0220     /* Sanity check the string we're looking at */
0221     for (i = 0; i < 5; i++) {
0222         if (*(mac_page + (i * 3) + 2) != ':') {
0223             goto error_fail;
0224         }
0225     }
0226 
0227     for (i = 0; i < 6; i++) {
0228         int byte;
0229 
0230         byte = dns323_parse_hex_byte(mac_page + (i * 3));
0231         if (byte < 0) {
0232             goto error_fail;
0233         }
0234 
0235         addr[i] = byte;
0236     }
0237 
0238     iounmap(mac_page);
0239     printk("DNS-323: Found ethernet MAC address: %pM\n", addr);
0240 
0241     memcpy(dns323_eth_data.mac_addr, addr, 6);
0242 
0243     return 0;
0244 
0245 error_fail:
0246     iounmap(mac_page);
0247     return -EINVAL;
0248 }
0249 
0250 /****************************************************************************
0251  * GPIO LEDs (simple - doesn't use hardware blinking support)
0252  */
0253 
0254 static struct gpio_led dns323ab_leds[] = {
0255     {
0256         .name = "power:blue",
0257         .gpio = DNS323_GPIO_LED_POWER2,
0258         .default_trigger = "default-on",
0259     }, {
0260         .name = "right:amber",
0261         .gpio = DNS323_GPIO_LED_RIGHT_AMBER,
0262         .active_low = 1,
0263     }, {
0264         .name = "left:amber",
0265         .gpio = DNS323_GPIO_LED_LEFT_AMBER,
0266         .active_low = 1,
0267     },
0268 };
0269 
0270 
0271 static struct gpio_led dns323c_leds[] = {
0272     {
0273         .name = "power:blue",
0274         .gpio = DNS323C_GPIO_LED_POWER,
0275         .default_trigger = "timer",
0276         .active_low = 1,
0277     }, {
0278         .name = "right:amber",
0279         .gpio = DNS323C_GPIO_LED_RIGHT_AMBER,
0280         .active_low = 1,
0281     }, {
0282         .name = "left:amber",
0283         .gpio = DNS323C_GPIO_LED_LEFT_AMBER,
0284         .active_low = 1,
0285     },
0286 };
0287 
0288 
0289 static struct gpio_led_platform_data dns323ab_led_data = {
0290     .num_leds   = ARRAY_SIZE(dns323ab_leds),
0291     .leds       = dns323ab_leds,
0292     .gpio_blink_set = orion_gpio_led_blink_set,
0293 };
0294 
0295 static struct gpio_led_platform_data dns323c_led_data = {
0296     .num_leds   = ARRAY_SIZE(dns323c_leds),
0297     .leds       = dns323c_leds,
0298     .gpio_blink_set = orion_gpio_led_blink_set,
0299 };
0300 
0301 static struct platform_device dns323_gpio_leds = {
0302     .name       = "leds-gpio",
0303     .id     = -1,
0304     .dev        = {
0305         .platform_data  = &dns323ab_led_data,
0306     },
0307 };
0308 
0309 /****************************************************************************
0310  * GPIO Attached Keys
0311  */
0312 
0313 static struct gpio_keys_button dns323ab_buttons[] = {
0314     {
0315         .code       = KEY_RESTART,
0316         .gpio       = DNS323_GPIO_KEY_RESET,
0317         .desc       = "Reset Button",
0318         .active_low = 1,
0319     }, {
0320         .code       = KEY_POWER,
0321         .gpio       = DNS323_GPIO_KEY_POWER,
0322         .desc       = "Power Button",
0323         .active_low = 1,
0324     },
0325 };
0326 
0327 static struct gpio_keys_platform_data dns323ab_button_data = {
0328     .buttons    = dns323ab_buttons,
0329     .nbuttons   = ARRAY_SIZE(dns323ab_buttons),
0330 };
0331 
0332 static struct gpio_keys_button dns323c_buttons[] = {
0333     {
0334         .code       = KEY_POWER,
0335         .gpio       = DNS323C_GPIO_KEY_POWER,
0336         .desc       = "Power Button",
0337         .active_low = 1,
0338     },
0339 };
0340 
0341 static struct gpio_keys_platform_data dns323c_button_data = {
0342     .buttons    = dns323c_buttons,
0343     .nbuttons   = ARRAY_SIZE(dns323c_buttons),
0344 };
0345 
0346 static struct platform_device dns323_button_device = {
0347     .name       = "gpio-keys",
0348     .id     = -1,
0349     .num_resources  = 0,
0350     .dev        = {
0351         .platform_data  = &dns323ab_button_data,
0352     },
0353 };
0354 
0355 /*****************************************************************************
0356  * SATA
0357  */
0358 static struct mv_sata_platform_data dns323_sata_data = {
0359        .n_ports        = 2,
0360 };
0361 
0362 /****************************************************************************
0363  * General Setup
0364  */
0365 static unsigned int dns323a_mpp_modes[] __initdata = {
0366     MPP0_PCIE_RST_OUTn,
0367     MPP1_GPIO,      /* right amber LED (sata ch0) */
0368     MPP2_GPIO,      /* left amber LED (sata ch1) */
0369     MPP3_UNUSED,
0370     MPP4_GPIO,      /* power button LED */
0371     MPP5_GPIO,      /* power button LED */
0372     MPP6_GPIO,      /* GMT G751-2f overtemp */
0373     MPP7_GPIO,      /* M41T80 nIRQ/OUT/SQW */
0374     MPP8_GPIO,      /* triggers power off */
0375     MPP9_GPIO,      /* power button switch */
0376     MPP10_GPIO,     /* reset button switch */
0377     MPP11_UNUSED,
0378     MPP12_UNUSED,
0379     MPP13_UNUSED,
0380     MPP14_UNUSED,
0381     MPP15_UNUSED,
0382     MPP16_UNUSED,
0383     MPP17_UNUSED,
0384     MPP18_UNUSED,
0385     MPP19_UNUSED,
0386     0,
0387 };
0388 
0389 static unsigned int dns323b_mpp_modes[] __initdata = {
0390     MPP0_UNUSED,
0391     MPP1_GPIO,      /* right amber LED (sata ch0) */
0392     MPP2_GPIO,      /* left amber LED (sata ch1) */
0393     MPP3_GPIO,      /* system up flag */
0394     MPP4_GPIO,      /* power button LED */
0395     MPP5_GPIO,      /* power button LED */
0396     MPP6_GPIO,      /* GMT G751-2f overtemp */
0397     MPP7_GPIO,      /* M41T80 nIRQ/OUT/SQW */
0398     MPP8_GPIO,      /* triggers power off */
0399     MPP9_GPIO,      /* power button switch */
0400     MPP10_GPIO,     /* reset button switch */
0401     MPP11_UNUSED,
0402     MPP12_SATA_LED,
0403     MPP13_SATA_LED,
0404     MPP14_SATA_LED,
0405     MPP15_SATA_LED,
0406     MPP16_UNUSED,
0407     MPP17_UNUSED,
0408     MPP18_UNUSED,
0409     MPP19_UNUSED,
0410     0,
0411 };
0412 
0413 static unsigned int dns323c_mpp_modes[] __initdata = {
0414     MPP0_GPIO,      /* ? input */
0415     MPP1_GPIO,      /* input power switch (0 = pressed) */
0416     MPP2_GPIO,      /* output power off */
0417     MPP3_UNUSED,        /* ? output */
0418     MPP4_UNUSED,        /* ? output */
0419     MPP5_UNUSED,        /* ? output */
0420     MPP6_UNUSED,        /* ? output */
0421     MPP7_UNUSED,        /* ? output */
0422     MPP8_GPIO,      /* i/o right amber LED */
0423     MPP9_GPIO,      /* i/o left amber LED */
0424     MPP10_GPIO,     /* input */
0425     MPP11_UNUSED,
0426     MPP12_SATA_LED,
0427     MPP13_SATA_LED,
0428     MPP14_SATA_LED,
0429     MPP15_SATA_LED,
0430     MPP16_UNUSED,
0431     MPP17_GPIO,     /* power button LED */
0432     MPP18_GPIO,     /* fan speed bit 0 */
0433     MPP19_GPIO,     /* fan speed bit 1 */
0434     0,
0435 };
0436 
0437 /* Rev C1 Fan speed notes:
0438  *
0439  * The fan is controlled by 2 GPIOs on this board. The settings
0440  * of the bits is as follow:
0441  *
0442  *  GPIO 18    GPIO 19    Fan
0443  *
0444  *    0          0        stopped
0445  *    0          1        low speed
0446  *    1          0        high speed
0447  *    1          1        don't do that (*)
0448  *
0449  * (*) I think the two bits control two feed-in resistors into a fixed
0450  *     PWN circuit, setting both bits will basically go a 'bit' faster
0451  *     than high speed, but d-link doesn't do it and you may get out of
0452  *     HW spec so don't do it.
0453  */
0454 
0455 /*
0456  * On the DNS-323 A1 and B1 the following devices are attached via I2C:
0457  *
0458  *  i2c addr | chip        | description
0459  *  0x3e     | GMT G760Af  | fan speed PWM controller
0460  *  0x48     | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible)
0461  *  0x68     | ST M41T80   | RTC w/ alarm
0462  */
0463 static struct i2c_board_info __initdata dns323ab_i2c_devices[] = {
0464     {
0465         I2C_BOARD_INFO("g760a", 0x3e),
0466     }, {
0467         I2C_BOARD_INFO("lm75", 0x48),
0468     }, {
0469         I2C_BOARD_INFO("m41t80", 0x68),
0470     },
0471 };
0472 
0473 /*
0474  * On the DNS-323 C1 the following devices are attached via I2C:
0475  *
0476  *  i2c addr | chip        | description
0477  *  0x48     | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible)
0478  *  0x68     | ST M41T80   | RTC w/ alarm
0479  */
0480 static struct i2c_board_info __initdata dns323c_i2c_devices[] = {
0481     {
0482         I2C_BOARD_INFO("lm75", 0x48),
0483     }, {
0484         I2C_BOARD_INFO("m41t80", 0x68),
0485     },
0486 };
0487 
0488 /* DNS-323 rev. A specific power off method */
0489 static void dns323a_power_off(void)
0490 {
0491     pr_info("DNS-323: Triggering power-off...\n");
0492     gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
0493 }
0494 
0495 /* DNS-323 rev B specific power off method */
0496 static void dns323b_power_off(void)
0497 {
0498     pr_info("DNS-323: Triggering power-off...\n");
0499     /* Pin has to be changed to 1 and back to 0 to do actual power off. */
0500     gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
0501     mdelay(100);
0502     gpio_set_value(DNS323_GPIO_POWER_OFF, 0);
0503 }
0504 
0505 /* DNS-323 rev. C specific power off method */
0506 static void dns323c_power_off(void)
0507 {
0508     pr_info("DNS-323: Triggering power-off...\n");
0509     gpio_set_value(DNS323C_GPIO_POWER_OFF, 1);
0510 }
0511 
0512 static int dns323c_phy_fixup(struct phy_device *phy)
0513 {
0514     phy->dev_flags |= MARVELL_PHY_M1118_DNS323_LEDS;
0515 
0516     return 0;
0517 }
0518 
0519 static int __init dns323_identify_rev(void)
0520 {
0521     u32 dev, rev, i, reg;
0522 
0523     pr_debug("DNS-323: Identifying board ... \n");
0524 
0525     /* Rev A1 has a 5181 */
0526     orion5x_pcie_id(&dev, &rev);
0527     if (dev == MV88F5181_DEV_ID) {
0528         pr_debug("DNS-323: 5181 found, board is A1\n");
0529         return DNS323_REV_A1;
0530     }
0531     pr_debug("DNS-323: 5182 found, board is B1 or C1, checking PHY...\n");
0532 
0533     /* Rev B1 and C1 both have 5182, let's poke at the eth PHY. This is
0534      * a bit gross but we want to do that without links into the eth
0535      * driver so let's poke at it directly. We default to rev B1 in
0536      * case the accesses fail
0537      */
0538 
0539 #define ETH_SMI_REG     (ORION5X_ETH_VIRT_BASE + 0x2000 + 0x004)
0540 #define  SMI_BUSY       0x10000000
0541 #define  SMI_READ_VALID     0x08000000
0542 #define  SMI_OPCODE_READ    0x04000000
0543 #define  SMI_OPCODE_WRITE   0x00000000
0544 
0545     for (i = 0; i < 1000; i++) {
0546         reg = readl(ETH_SMI_REG);
0547         if (!(reg & SMI_BUSY))
0548             break;
0549     }
0550     if (i >= 1000) {
0551         pr_warn("DNS-323: Timeout accessing PHY, assuming rev B1\n");
0552         return DNS323_REV_B1;
0553     }
0554     writel((3 << 21)    /* phy ID reg */ |
0555            (8 << 16)    /* phy addr */ |
0556            SMI_OPCODE_READ, ETH_SMI_REG);
0557     for (i = 0; i < 1000; i++) {
0558         reg = readl(ETH_SMI_REG);
0559         if (reg & SMI_READ_VALID)
0560             break;
0561     }
0562     if (i >= 1000) {
0563         pr_warn("DNS-323: Timeout reading PHY, assuming rev B1\n");
0564         return DNS323_REV_B1;
0565     }
0566     pr_debug("DNS-323: Ethernet PHY ID 0x%x\n", reg & 0xffff);
0567 
0568     /* Note: the Marvell tools mask the ID with 0x3f0 before comparison
0569      * but I don't see that making a difference here, at least with
0570      * any known Marvell PHY ID
0571      */
0572     switch(reg & 0xfff0) {
0573     case 0x0cc0: /* MV88E1111 */
0574         return DNS323_REV_B1;
0575     case 0x0e10: /* MV88E1118 */
0576         return DNS323_REV_C1;
0577     default:
0578         pr_warn("DNS-323: Unknown PHY ID 0x%04x, assuming rev B1\n",
0579             reg & 0xffff);
0580     }
0581     return DNS323_REV_B1;
0582 }
0583 
0584 static void __init dns323_init(void)
0585 {
0586     /* Setup basic Orion functions. Need to be called early. */
0587     orion5x_init();
0588 
0589     /* Identify revision */
0590     system_rev = dns323_identify_rev();
0591     pr_info("DNS-323: Identified HW revision %c1\n", 'A' + system_rev);
0592 
0593     /* Just to be tricky, the 5182 has a completely different
0594      * set of MPP modes to the 5181.
0595      */
0596     switch(system_rev) {
0597     case DNS323_REV_A1:
0598         orion5x_mpp_conf(dns323a_mpp_modes);
0599         writel(0, MPP_DEV_CTRL);        /* DEV_D[31:16] */
0600         break;
0601     case DNS323_REV_B1:
0602         orion5x_mpp_conf(dns323b_mpp_modes);
0603         break;
0604     case DNS323_REV_C1:
0605         orion5x_mpp_conf(dns323c_mpp_modes);
0606         break;
0607     }
0608 
0609     /* setup flash mapping
0610      * CS3 holds a 8 MB Spansion S29GL064M90TFIR4
0611      */
0612     mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
0613                     ORION_MBUS_DEVBUS_BOOT_ATTR,
0614                     DNS323_NOR_BOOT_BASE,
0615                     DNS323_NOR_BOOT_SIZE);
0616     platform_device_register(&dns323_nor_flash);
0617 
0618     /* Sort out LEDs, Buttons and i2c devices */
0619     switch(system_rev) {
0620     case DNS323_REV_A1:
0621         /* The 5181 power LED is active low and requires
0622          * DNS323_GPIO_LED_POWER1 to also be low.
0623          */
0624          dns323ab_leds[0].active_low = 1;
0625          gpio_request(DNS323_GPIO_LED_POWER1, "Power Led Enable");
0626          gpio_direction_output(DNS323_GPIO_LED_POWER1, 0);
0627         fallthrough;
0628     case DNS323_REV_B1:
0629         i2c_register_board_info(0, dns323ab_i2c_devices,
0630                 ARRAY_SIZE(dns323ab_i2c_devices));
0631         break;
0632     case DNS323_REV_C1:
0633         /* Hookup LEDs & Buttons */
0634         dns323_gpio_leds.dev.platform_data = &dns323c_led_data;
0635         dns323_button_device.dev.platform_data = &dns323c_button_data;
0636 
0637         /* Hookup i2c devices and fan driver */
0638         i2c_register_board_info(0, dns323c_i2c_devices,
0639                 ARRAY_SIZE(dns323c_i2c_devices));
0640         platform_device_register_simple("dns323c-fan", 0, NULL, 0);
0641 
0642         /* Register fixup for the PHY LEDs */
0643         if (!IS_BUILTIN(CONFIG_PHYLIB))
0644             break;
0645         phy_register_fixup_for_uid(MARVELL_PHY_ID_88E1118,
0646                        MARVELL_PHY_ID_MASK,
0647                        dns323c_phy_fixup);
0648     }
0649 
0650     platform_device_register(&dns323_gpio_leds);
0651     platform_device_register(&dns323_button_device);
0652 
0653     /*
0654      * Configure peripherals.
0655      */
0656     if (dns323_read_mac_addr() < 0)
0657         printk("DNS-323: Failed to read MAC address\n");
0658     orion5x_ehci0_init();
0659     orion5x_eth_init(&dns323_eth_data);
0660     orion5x_i2c_init();
0661     orion5x_uart0_init();
0662 
0663     /* Remaining GPIOs */
0664     switch(system_rev) {
0665     case DNS323_REV_A1:
0666         /* Poweroff GPIO */
0667         if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 ||
0668             gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)
0669             pr_err("DNS-323: failed to setup power-off GPIO\n");
0670         pm_power_off = dns323a_power_off;
0671         break;
0672     case DNS323_REV_B1:
0673         /* 5182 built-in SATA init */
0674         orion5x_sata_init(&dns323_sata_data);
0675 
0676         /* The DNS323 rev B1 has flag to indicate the system is up.
0677          * Without this flag set, power LED will flash and cannot be
0678          * controlled via leds-gpio.
0679          */
0680         if (gpio_request(DNS323_GPIO_SYSTEM_UP, "SYS_READY") == 0)
0681             gpio_direction_output(DNS323_GPIO_SYSTEM_UP, 1);
0682 
0683         /* Poweroff GPIO */
0684         if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 ||
0685             gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)
0686             pr_err("DNS-323: failed to setup power-off GPIO\n");
0687         pm_power_off = dns323b_power_off;
0688         break;
0689     case DNS323_REV_C1:
0690         /* 5182 built-in SATA init */
0691         orion5x_sata_init(&dns323_sata_data);
0692 
0693         /* Poweroff GPIO */
0694         if (gpio_request(DNS323C_GPIO_POWER_OFF, "POWEROFF") != 0 ||
0695             gpio_direction_output(DNS323C_GPIO_POWER_OFF, 0) != 0)
0696             pr_err("DNS-323: failed to setup power-off GPIO\n");
0697         pm_power_off = dns323c_power_off;
0698 
0699         /* Now, -this- should theoretically be done by the sata_mv driver
0700          * once I figure out what's going on there. Maybe the behaviour
0701          * of the LEDs should be somewhat passed via the platform_data.
0702          * for now, just whack the register and make the LEDs happy
0703          *
0704          * Note: AFAIK, rev B1 needs the same treatment but I'll let
0705          * somebody else test it.
0706          */
0707         writel(0x5, ORION5X_SATA_VIRT_BASE + 0x2c);
0708         break;
0709     }
0710 }
0711 
0712 /* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
0713 MACHINE_START(DNS323, "D-Link DNS-323")
0714     /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
0715     .atag_offset    = 0x100,
0716     .nr_irqs    = ORION5X_NR_IRQS,
0717     .init_machine   = dns323_init,
0718     .map_io     = orion5x_map_io,
0719     .init_early = orion5x_init_early,
0720     .init_irq   = orion5x_init_irq,
0721     .init_time  = orion5x_timer_init,
0722     .fixup      = tag_fixup_mem32,
0723     .restart    = orion5x_restart,
0724 MACHINE_END