0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
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
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
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
0063 enum {
0064 DNS323_REV_A1,
0065 DNS323_REV_B1,
0066 DNS323_REV_C1,
0067 };
0068
0069
0070
0071
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
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
0098
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
0110
0111
0112
0113
0114
0115
0116
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
0170
0171
0172 static struct mv643xx_eth_platform_data dns323_eth_data = {
0173 .phy_addr = MV643XX_ETH_PHY_ADDR(8),
0174 };
0175
0176
0177
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
0214
0215
0216 mac_page = ioremap(DNS323_NOR_BOOT_BASE + 0x7d0000 + 196480, 1024);
0217 if (!mac_page)
0218 return -ENOMEM;
0219
0220
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
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
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
0357
0358 static struct mv_sata_platform_data dns323_sata_data = {
0359 .n_ports = 2,
0360 };
0361
0362
0363
0364
0365 static unsigned int dns323a_mpp_modes[] __initdata = {
0366 MPP0_PCIE_RST_OUTn,
0367 MPP1_GPIO,
0368 MPP2_GPIO,
0369 MPP3_UNUSED,
0370 MPP4_GPIO,
0371 MPP5_GPIO,
0372 MPP6_GPIO,
0373 MPP7_GPIO,
0374 MPP8_GPIO,
0375 MPP9_GPIO,
0376 MPP10_GPIO,
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,
0392 MPP2_GPIO,
0393 MPP3_GPIO,
0394 MPP4_GPIO,
0395 MPP5_GPIO,
0396 MPP6_GPIO,
0397 MPP7_GPIO,
0398 MPP8_GPIO,
0399 MPP9_GPIO,
0400 MPP10_GPIO,
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,
0415 MPP1_GPIO,
0416 MPP2_GPIO,
0417 MPP3_UNUSED,
0418 MPP4_UNUSED,
0419 MPP5_UNUSED,
0420 MPP6_UNUSED,
0421 MPP7_UNUSED,
0422 MPP8_GPIO,
0423 MPP9_GPIO,
0424 MPP10_GPIO,
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,
0432 MPP18_GPIO,
0433 MPP19_GPIO,
0434 0,
0435 };
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
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
0475
0476
0477
0478
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
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
0496 static void dns323b_power_off(void)
0497 {
0498 pr_info("DNS-323: Triggering power-off...\n");
0499
0500 gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
0501 mdelay(100);
0502 gpio_set_value(DNS323_GPIO_POWER_OFF, 0);
0503 }
0504
0505
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
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
0534
0535
0536
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) |
0555 (8 << 16) |
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
0569
0570
0571
0572 switch(reg & 0xfff0) {
0573 case 0x0cc0:
0574 return DNS323_REV_B1;
0575 case 0x0e10:
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
0587 orion5x_init();
0588
0589
0590 system_rev = dns323_identify_rev();
0591 pr_info("DNS-323: Identified HW revision %c1\n", 'A' + system_rev);
0592
0593
0594
0595
0596 switch(system_rev) {
0597 case DNS323_REV_A1:
0598 orion5x_mpp_conf(dns323a_mpp_modes);
0599 writel(0, MPP_DEV_CTRL);
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
0610
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
0619 switch(system_rev) {
0620 case DNS323_REV_A1:
0621
0622
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
0634 dns323_gpio_leds.dev.platform_data = &dns323c_led_data;
0635 dns323_button_device.dev.platform_data = &dns323c_button_data;
0636
0637
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
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
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
0664 switch(system_rev) {
0665 case DNS323_REV_A1:
0666
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
0674 orion5x_sata_init(&dns323_sata_data);
0675
0676
0677
0678
0679
0680 if (gpio_request(DNS323_GPIO_SYSTEM_UP, "SYS_READY") == 0)
0681 gpio_direction_output(DNS323_GPIO_SYSTEM_UP, 1);
0682
0683
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
0691 orion5x_sata_init(&dns323_sata_data);
0692
0693
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
0700
0701
0702
0703
0704
0705
0706
0707 writel(0x5, ORION5X_SATA_VIRT_BASE + 0x2c);
0708 break;
0709 }
0710 }
0711
0712
0713 MACHINE_START(DNS323, "D-Link DNS-323")
0714
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