wgt634u.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
  7. */
  8. #include <linux/platform_device.h>
  9. #include <linux/module.h>
  10. #include <linux/leds.h>
  11. #include <linux/mtd/physmap.h>
  12. #include <linux/ssb/ssb.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/reboot.h>
  15. #include <linux/gpio.h>
  16. #include <asm/mach-bcm47xx/bcm47xx.h>
  17. /* GPIO definitions for the WGT634U */
  18. #define WGT634U_GPIO_LED 3
  19. #define WGT634U_GPIO_RESET 2
  20. #define WGT634U_GPIO_TP1 7
  21. #define WGT634U_GPIO_TP2 6
  22. #define WGT634U_GPIO_TP3 5
  23. #define WGT634U_GPIO_TP4 4
  24. #define WGT634U_GPIO_TP5 1
  25. static struct gpio_led wgt634u_leds[] = {
  26. {
  27. .name = "power",
  28. .gpio = WGT634U_GPIO_LED,
  29. .active_low = 1,
  30. .default_trigger = "heartbeat",
  31. },
  32. };
  33. static struct gpio_led_platform_data wgt634u_led_data = {
  34. .num_leds = ARRAY_SIZE(wgt634u_leds),
  35. .leds = wgt634u_leds,
  36. };
  37. static struct platform_device wgt634u_gpio_leds = {
  38. .name = "leds-gpio",
  39. .id = -1,
  40. .dev = {
  41. .platform_data = &wgt634u_led_data,
  42. }
  43. };
  44. /* 8MiB flash. The struct mtd_partition matches original Netgear WGT634U
  45. firmware. */
  46. static struct mtd_partition wgt634u_partitions[] = {
  47. {
  48. .name = "cfe",
  49. .offset = 0,
  50. .size = 0x60000, /* 384k */
  51. .mask_flags = MTD_WRITEABLE /* force read-only */
  52. },
  53. {
  54. .name = "config",
  55. .offset = 0x60000,
  56. .size = 0x20000 /* 128k */
  57. },
  58. {
  59. .name = "linux",
  60. .offset = 0x80000,
  61. .size = 0x140000 /* 1280k */
  62. },
  63. {
  64. .name = "jffs",
  65. .offset = 0x1c0000,
  66. .size = 0x620000 /* 6272k */
  67. },
  68. {
  69. .name = "nvram",
  70. .offset = 0x7e0000,
  71. .size = 0x20000 /* 128k */
  72. },
  73. };
  74. static struct physmap_flash_data wgt634u_flash_data = {
  75. .parts = wgt634u_partitions,
  76. .nr_parts = ARRAY_SIZE(wgt634u_partitions)
  77. };
  78. static struct resource wgt634u_flash_resource = {
  79. .flags = IORESOURCE_MEM,
  80. };
  81. static struct platform_device wgt634u_flash = {
  82. .name = "physmap-flash",
  83. .id = 0,
  84. .dev = { .platform_data = &wgt634u_flash_data, },
  85. .resource = &wgt634u_flash_resource,
  86. .num_resources = 1,
  87. };
  88. /* Platform devices */
  89. static struct platform_device *wgt634u_devices[] __initdata = {
  90. &wgt634u_flash,
  91. &wgt634u_gpio_leds,
  92. };
  93. static irqreturn_t gpio_interrupt(int irq, void *ignored)
  94. {
  95. int state;
  96. /* Interrupts are shared, check if the current one is
  97. a GPIO interrupt. */
  98. if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco,
  99. SSB_CHIPCO_IRQ_GPIO))
  100. return IRQ_NONE;
  101. state = gpio_get_value(WGT634U_GPIO_RESET);
  102. /* Interrupt are level triggered, revert the interrupt polarity
  103. to clear the interrupt. */
  104. gpio_polarity(WGT634U_GPIO_RESET, state);
  105. if (!state) {
  106. printk(KERN_INFO "Reset button pressed");
  107. ctrl_alt_del();
  108. }
  109. return IRQ_HANDLED;
  110. }
  111. static int __init wgt634u_init(void)
  112. {
  113. /* There is no easy way to detect that we are running on a WGT634U
  114. * machine. Use the MAC address as an heuristic. Netgear Inc. has
  115. * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
  116. */
  117. u8 *et0mac = ssb_bcm47xx.sprom.et0mac;
  118. if (et0mac[0] == 0x00 &&
  119. ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
  120. (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
  121. struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
  122. printk(KERN_INFO "WGT634U machine detected.\n");
  123. if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
  124. gpio_interrupt, IRQF_SHARED,
  125. "WGT634U GPIO", &ssb_bcm47xx.chipco)) {
  126. gpio_direction_input(WGT634U_GPIO_RESET);
  127. gpio_intmask(WGT634U_GPIO_RESET, 1);
  128. ssb_chipco_irq_mask(&ssb_bcm47xx.chipco,
  129. SSB_CHIPCO_IRQ_GPIO,
  130. SSB_CHIPCO_IRQ_GPIO);
  131. }
  132. wgt634u_flash_data.width = mcore->flash_buswidth;
  133. wgt634u_flash_resource.start = mcore->flash_window;
  134. wgt634u_flash_resource.end = mcore->flash_window
  135. + mcore->flash_window_size
  136. - 1;
  137. return platform_add_devices(wgt634u_devices,
  138. ARRAY_SIZE(wgt634u_devices));
  139. } else
  140. return -ENODEV;
  141. }
  142. module_init(wgt634u_init);