linux/arch/mips/bcm47xx/wgt634u.c
Linus Torvalds cebfa85eb8 Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle:
 "The MIPS bits for 3.8.  This also includes a bunch fixes that were
  sitting in the linux-mips.org git tree for a long time.  This pull
  request contains updates to several OCTEON drivers and the board
  support code for BCM47XX, BCM63XX, XLP, XLR, XLS, lantiq, Loongson1B,
  updates to the SSB bus support, MIPS kexec code and adds support for
  kdump.

  When pulling this, there are two expected merge conflicts in
  include/linux/bcma/bcma_driver_chipcommon.h which are trivial to
  resolve, just remove the conflict markers and keep both alternatives."

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (90 commits)
  MIPS: PMC-Sierra Yosemite: Remove support.
  VIDEO: Newport Fix console crashes
  MIPS: wrppmc: Fix build of PCI code.
  MIPS: IP22/IP28: Fix build of EISA code.
  MIPS: RB532: Fix build of prom code.
  MIPS: PowerTV: Fix build.
  MIPS: IP27: Correct fucked grammar in ops-bridge.c
  MIPS: Highmem: Fix build error if CONFIG_DEBUG_HIGHMEM is disabled
  MIPS: Fix potencial corruption
  MIPS: Fix for warning from FPU emulation code
  MIPS: Handle COP3 Unusable exception as COP1X for FP emulation
  MIPS: Fix poweroff failure when HOTPLUG_CPU configured.
  MIPS: MT: Fix build with CONFIG_UIDGID_STRICT_TYPE_CHECKS=y
  MIPS: Remove unused smvp.h
  MIPS/EDAC: Improve OCTEON EDAC support.
  MIPS: OCTEON: Add definitions for OCTEON memory contoller registers.
  MIPS: OCTEON: Add OCTEON family definitions to octeon-model.h
  ata: pata_octeon_cf: Use correct byte order for DMA in when built little-endian.
  MIPS/OCTEON/ata: Convert pata_octeon_cf.c to use device tree.
  MIPS: Remove usage of CEVT_R4K_LIB config option.
  ...
2012-12-14 14:27:45 -08:00

175 lines
4.3 KiB
C

/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
*/
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/leds.h>
#include <linux/mtd/physmap.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/gpio.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
/* GPIO definitions for the WGT634U */
#define WGT634U_GPIO_LED 3
#define WGT634U_GPIO_RESET 2
#define WGT634U_GPIO_TP1 7
#define WGT634U_GPIO_TP2 6
#define WGT634U_GPIO_TP3 5
#define WGT634U_GPIO_TP4 4
#define WGT634U_GPIO_TP5 1
static struct gpio_led wgt634u_leds[] = {
{
.name = "power",
.gpio = WGT634U_GPIO_LED,
.active_low = 1,
.default_trigger = "heartbeat",
},
};
static struct gpio_led_platform_data wgt634u_led_data = {
.num_leds = ARRAY_SIZE(wgt634u_leds),
.leds = wgt634u_leds,
};
static struct platform_device wgt634u_gpio_leds = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &wgt634u_led_data,
}
};
/* 8MiB flash. The struct mtd_partition matches original Netgear WGT634U
firmware. */
static struct mtd_partition wgt634u_partitions[] = {
{
.name = "cfe",
.offset = 0,
.size = 0x60000, /* 384k */
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{
.name = "config",
.offset = 0x60000,
.size = 0x20000 /* 128k */
},
{
.name = "linux",
.offset = 0x80000,
.size = 0x140000 /* 1280k */
},
{
.name = "jffs",
.offset = 0x1c0000,
.size = 0x620000 /* 6272k */
},
{
.name = "nvram",
.offset = 0x7e0000,
.size = 0x20000 /* 128k */
},
};
static struct physmap_flash_data wgt634u_flash_data = {
.parts = wgt634u_partitions,
.nr_parts = ARRAY_SIZE(wgt634u_partitions)
};
static struct resource wgt634u_flash_resource = {
.flags = IORESOURCE_MEM,
};
static struct platform_device wgt634u_flash = {
.name = "physmap-flash",
.id = 0,
.dev = { .platform_data = &wgt634u_flash_data, },
.resource = &wgt634u_flash_resource,
.num_resources = 1,
};
/* Platform devices */
static struct platform_device *wgt634u_devices[] __initdata = {
&wgt634u_flash,
&wgt634u_gpio_leds,
};
static irqreturn_t gpio_interrupt(int irq, void *ignored)
{
int state;
/* Interrupts are shared, check if the current one is
a GPIO interrupt. */
if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco,
SSB_CHIPCO_IRQ_GPIO))
return IRQ_NONE;
state = gpio_get_value(WGT634U_GPIO_RESET);
/* Interrupt are level triggered, revert the interrupt polarity
to clear the interrupt. */
ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << WGT634U_GPIO_RESET,
state ? 1 << WGT634U_GPIO_RESET : 0);
if (!state) {
printk(KERN_INFO "Reset button pressed");
ctrl_alt_del();
}
return IRQ_HANDLED;
}
static int __init wgt634u_init(void)
{
/* There is no easy way to detect that we are running on a WGT634U
* machine. Use the MAC address as an heuristic. Netgear Inc. has
* been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
*/
u8 *et0mac;
if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
return -ENODEV;
et0mac = bcm47xx_bus.ssb.sprom.et0mac;
if (et0mac[0] == 0x00 &&
((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
(et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
printk(KERN_INFO "WGT634U machine detected.\n");
if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
gpio_interrupt, IRQF_SHARED,
"WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
gpio_direction_input(WGT634U_GPIO_RESET);
ssb_gpio_intmask(&bcm47xx_bus.ssb,
1 << WGT634U_GPIO_RESET,
1 << WGT634U_GPIO_RESET);
ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
SSB_CHIPCO_IRQ_GPIO,
SSB_CHIPCO_IRQ_GPIO);
}
wgt634u_flash_data.width = mcore->pflash.buswidth;
wgt634u_flash_resource.start = mcore->pflash.window;
wgt634u_flash_resource.end = mcore->pflash.window
+ mcore->pflash.window_size
- 1;
return platform_add_devices(wgt634u_devices,
ARRAY_SIZE(wgt634u_devices));
} else
return -ENODEV;
}
module_init(wgt634u_init);