summaryrefslogtreecommitdiffstats
path: root/arch/mips/alchemy/devboards/db1550.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-14 23:39:05 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-14 23:39:05 +0200
commita5ef3f7dcba17e79c21afec38188c4c6a0baf995 (patch)
tree1961e2e8c2d30dd7a21b93fa7e70dc62f892651d /arch/mips/alchemy/devboards/db1550.c
parentMerge branch 'modules-next' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff)
parentMerge tag 'disintegrate-mips-20121009' of git://git.infradead.org/users/dhowe... (diff)
downloadlinux-a5ef3f7dcba17e79c21afec38188c4c6a0baf995.tar.xz
linux-a5ef3f7dcba17e79c21afec38188c4c6a0baf995.zip
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS update from Ralf Baechle: "Cleanups and fixes for breakage that occured earlier during this merge phase. Also a few patches that didn't make the first pull request. Of those is the Alchemy work that merges code for many of the SOCs and evaluation boards thus among other code shrinkage, reduces the number of MIPS defconfigs by 5." * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (22 commits) MIPS: SNI: Switch RM400 serial to SCCNXP driver MIPS: Remove unused empty_bad_pmd_table[] declaration. MIPS: MT: Remove kspd. MIPS: Malta: Fix section mismatch. MIPS: asm-offset.c: Delete unused irq_cpustat_t struct offsets. MIPS: Alchemy: Merge PB1100/1500 support into DB1000 code. MIPS: Alchemy: merge PB1550 support into DB1550 code MIPS: Alchemy: Single kernel for DB1200/1300/1550 MIPS: Optimize TLB refill for RI/XI configurations. MIPS: proc: Cleanup printing of ASEs. MIPS: Hardwire detection of DSP ASE Rev 2 for systems, as required. MIPS: Add detection of DSP ASE Revision 2. MIPS: Optimize pgd_init and pmd_init MIPS: perf: Add perf functionality for BMIPS5000 MIPS: perf: Split the Kconfig option CONFIG_MIPS_MT_SMP MIPS: perf: Remove unnecessary #ifdef MIPS: perf: Add cpu feature bit for PCI (performance counter interrupt) MIPS: perf: Change the "mips_perf_event" table unsupported indicator. MIPS: Align swapper_pg_dir to 64K for better TLB Refill code. vmlinux.lds.h: Allow architectures to add sections to the front of .bss ...
Diffstat (limited to 'arch/mips/alchemy/devboards/db1550.c')
-rw-r--r--arch/mips/alchemy/devboards/db1550.c192
1 files changed, 149 insertions, 43 deletions
diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c
index 9eb79062f46e..5a9ae6095428 100644
--- a/arch/mips/alchemy/devboards/db1550.c
+++ b/arch/mips/alchemy/devboards/db1550.c
@@ -1,5 +1,5 @@
/*
- * Alchemy Db1550 board support
+ * Alchemy Db1550/Pb1550 board support
*
* (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
*/
@@ -17,34 +17,29 @@
#include <linux/pm.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
+#include <asm/bootinfo.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1xxx_eth.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-au1x00/au1xxx_psc.h>
#include <asm/mach-au1x00/au1550_spi.h>
+#include <asm/mach-au1x00/au1550nd.h>
#include <asm/mach-db1x00/bcsr.h>
#include <prom.h>
#include "platform.h"
-
-const char *get_system_type(void)
-{
- return "DB1550";
-}
-
static void __init db1550_hw_setup(void)
{
void __iomem *base;
- alchemy_gpio_direction_output(203, 0); /* red led on */
-
/* complete SPI setup: link psc0_intclk to a 48MHz source,
- * and assign GPIO16 to PSC0_SYNC1 (SPI cs# line)
+ * and assign GPIO16 to PSC0_SYNC1 (SPI cs# line) as well as PSC1_SYNC
+ * for AC97 on PB1550.
*/
base = (void __iomem *)SYS_CLKSRC;
__raw_writel(__raw_readl(base) | 0x000001e0, base);
base = (void __iomem *)SYS_PINFUNC;
- __raw_writel(__raw_readl(base) | 1, base);
+ __raw_writel(__raw_readl(base) | 1 | SYS_PF_PSC1_S1, base);
wmb();
/* reset the AC97 codec now, the reset time in the psc-ac97 driver
@@ -57,23 +52,27 @@ static void __init db1550_hw_setup(void)
wmb();
__raw_writel(PSC_AC97RST_RST, base + PSC_AC97RST_OFFSET);
wmb();
-
- alchemy_gpio_direction_output(202, 0); /* green led on */
}
-void __init board_setup(void)
+int __init db1550_board_setup(void)
{
unsigned short whoami;
bcsr_init(DB1550_BCSR_PHYS_ADDR,
DB1550_BCSR_PHYS_ADDR + DB1550_BCSR_HEXLED_OFS);
- whoami = bcsr_read(BCSR_WHOAMI);
- printk(KERN_INFO "Alchemy/AMD DB1550 Board, CPLD Rev %d"
- " Board-ID %d Daughtercard ID %d\n",
+ whoami = bcsr_read(BCSR_WHOAMI); /* PB1550 hexled offset differs */
+ if ((BCSR_WHOAMI_BOARD(whoami) == BCSR_WHOAMI_PB1550_SDR) ||
+ (BCSR_WHOAMI_BOARD(whoami) == BCSR_WHOAMI_PB1550_DDR))
+ bcsr_init(PB1550_BCSR_PHYS_ADDR,
+ PB1550_BCSR_PHYS_ADDR + PB1550_BCSR_HEXLED_OFS);
+
+ pr_info("Alchemy/AMD %s Board, CPLD Rev %d Board-ID %d " \
+ "Daughtercard ID %d\n", get_system_type(),
(whoami >> 4) & 0xf, (whoami >> 8) & 0xf, whoami & 0xf);
db1550_hw_setup();
+ return 0;
}
/*****************************************************************************/
@@ -194,6 +193,39 @@ static struct platform_device db1550_nand_dev = {
}
};
+static struct au1550nd_platdata pb1550_nand_pd = {
+ .parts = db1550_nand_parts,
+ .num_parts = ARRAY_SIZE(db1550_nand_parts),
+ .devwidth = 0, /* x8 NAND default, needs fixing up */
+};
+
+static struct platform_device pb1550_nand_dev = {
+ .name = "au1550-nand",
+ .id = -1,
+ .resource = db1550_nand_res,
+ .num_resources = ARRAY_SIZE(db1550_nand_res),
+ .dev = {
+ .platform_data = &pb1550_nand_pd,
+ },
+};
+
+static void __init pb1550_nand_setup(void)
+{
+ int boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) |
+ ((bcsr_read(BCSR_STATUS) >> 6) & 0x1);
+
+ gpio_direction_input(206); /* de-assert NAND CS# */
+ switch (boot_swapboot) {
+ case 0: case 2: case 8: case 0xC: case 0xD:
+ /* x16 NAND Flash */
+ pb1550_nand_pd.devwidth = 1;
+ /* fallthrough */
+ case 1: case 3: case 9: case 0xE: case 0xF:
+ /* x8 NAND, already set up */
+ platform_device_register(&pb1550_nand_dev);
+ }
+}
+
/**********************************************************************/
static struct resource au1550_psc0_res[] = {
@@ -394,6 +426,29 @@ static int db1550_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
return -1;
}
+static int pb1550_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
+{
+ if ((slot < 12) || (slot > 13) || pin == 0)
+ return -1;
+ if (slot == 12) {
+ switch (pin) {
+ case 1: return AU1500_PCI_INTB;
+ case 2: return AU1500_PCI_INTC;
+ case 3: return AU1500_PCI_INTD;
+ case 4: return AU1500_PCI_INTA;
+ }
+ }
+ if (slot == 13) {
+ switch (pin) {
+ case 1: return AU1500_PCI_INTA;
+ case 2: return AU1500_PCI_INTB;
+ case 3: return AU1500_PCI_INTC;
+ case 4: return AU1500_PCI_INTD;
+ }
+ }
+ return -1;
+}
+
static struct resource alchemy_pci_host_res[] = {
[0] = {
.start = AU1500_PCI_PHYS_ADDR,
@@ -417,7 +472,6 @@ static struct platform_device db1550_pci_host_dev = {
/**********************************************************************/
static struct platform_device *db1550_devs[] __initdata = {
- &db1550_nand_dev,
&db1550_i2c_dev,
&db1550_ac97_dev,
&db1550_spi_dev,
@@ -430,15 +484,16 @@ static struct platform_device *db1550_devs[] __initdata = {
};
/* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */
-static int __init db1550_pci_init(void)
+int __init db1550_pci_setup(int id)
{
+ if (id)
+ db1550_pci_pd.board_map_irq = pb1550_map_pci_irq;
return platform_device_register(&db1550_pci_host_dev);
}
-arch_initcall(db1550_pci_init);
-static int __init db1550_dev_init(void)
+static void __init db1550_devices(void)
{
- int swapped;
+ alchemy_gpio_direction_output(203, 0); /* red led on */
irq_set_irq_type(AU1550_GPIO0_INT, IRQ_TYPE_EDGE_BOTH); /* CD0# */
irq_set_irq_type(AU1550_GPIO1_INT, IRQ_TYPE_EDGE_BOTH); /* CD1# */
@@ -447,6 +502,75 @@ static int __init db1550_dev_init(void)
irq_set_irq_type(AU1550_GPIO21_INT, IRQ_TYPE_LEVEL_LOW); /* STSCHG0# */
irq_set_irq_type(AU1550_GPIO22_INT, IRQ_TYPE_LEVEL_LOW); /* STSCHG1# */
+ db1x_register_pcmcia_socket(
+ AU1000_PCMCIA_ATTR_PHYS_ADDR,
+ AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+ AU1000_PCMCIA_MEM_PHYS_ADDR,
+ AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1,
+ AU1000_PCMCIA_IO_PHYS_ADDR,
+ AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1,
+ AU1550_GPIO3_INT, AU1550_GPIO0_INT,
+ /*AU1550_GPIO21_INT*/0, 0, 0);
+
+ db1x_register_pcmcia_socket(
+ AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
+ AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
+ AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004000000,
+ AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004400000 - 1,
+ AU1000_PCMCIA_IO_PHYS_ADDR + 0x004000000,
+ AU1000_PCMCIA_IO_PHYS_ADDR + 0x004010000 - 1,
+ AU1550_GPIO5_INT, AU1550_GPIO1_INT,
+ /*AU1550_GPIO22_INT*/0, 0, 1);
+
+ platform_device_register(&db1550_nand_dev);
+
+ alchemy_gpio_direction_output(202, 0); /* green led on */
+}
+
+static void __init pb1550_devices(void)
+{
+ irq_set_irq_type(AU1550_GPIO0_INT, IRQ_TYPE_LEVEL_LOW);
+ irq_set_irq_type(AU1550_GPIO1_INT, IRQ_TYPE_LEVEL_LOW);
+ irq_set_irq_type(AU1550_GPIO201_205_INT, IRQ_TYPE_LEVEL_HIGH);
+
+ /* enable both PCMCIA card irqs in the shared line */
+ alchemy_gpio2_enable_int(201); /* socket 0 card irq */
+ alchemy_gpio2_enable_int(202); /* socket 1 card irq */
+
+ /* Pb1550, like all others, also has statuschange irqs; however they're
+ * wired up on one of the Au1550's shared GPIO201_205 line, which also
+ * services the PCMCIA card interrupts. So we ignore statuschange and
+ * use the GPIO201_205 exclusively for card interrupts, since a) pcmcia
+ * drivers are used to shared irqs and b) statuschange isn't really use-
+ * ful anyway.
+ */
+ db1x_register_pcmcia_socket(
+ AU1000_PCMCIA_ATTR_PHYS_ADDR,
+ AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
+ AU1000_PCMCIA_MEM_PHYS_ADDR,
+ AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1,
+ AU1000_PCMCIA_IO_PHYS_ADDR,
+ AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1,
+ AU1550_GPIO201_205_INT, AU1550_GPIO0_INT, 0, 0, 0);
+
+ db1x_register_pcmcia_socket(
+ AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008000000,
+ AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1,
+ AU1000_PCMCIA_MEM_PHYS_ADDR + 0x008000000,
+ AU1000_PCMCIA_MEM_PHYS_ADDR + 0x008400000 - 1,
+ AU1000_PCMCIA_IO_PHYS_ADDR + 0x008000000,
+ AU1000_PCMCIA_IO_PHYS_ADDR + 0x008010000 - 1,
+ AU1550_GPIO201_205_INT, AU1550_GPIO1_INT, 0, 0, 1);
+
+ pb1550_nand_setup();
+}
+
+int __init db1550_dev_setup(void)
+{
+ int swapped, id;
+
+ id = (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) != BCSR_WHOAMI_DB1550);
+
i2c_register_board_info(0, db1550_i2c_devs,
ARRAY_SIZE(db1550_i2c_devs));
spi_register_board_info(db1550_spi_devs,
@@ -467,29 +591,11 @@ static int __init db1550_dev_init(void)
(void __iomem *)KSEG1ADDR(AU1550_PSC2_PHYS_ADDR) + PSC_SEL_OFFSET);
wmb();
- db1x_register_pcmcia_socket(
- AU1000_PCMCIA_ATTR_PHYS_ADDR,
- AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
- AU1000_PCMCIA_MEM_PHYS_ADDR,
- AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1,
- AU1000_PCMCIA_IO_PHYS_ADDR,
- AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1,
- AU1550_GPIO3_INT, AU1550_GPIO0_INT,
- /*AU1550_GPIO21_INT*/0, 0, 0);
-
- db1x_register_pcmcia_socket(
- AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
- AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
- AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004000000,
- AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004400000 - 1,
- AU1000_PCMCIA_IO_PHYS_ADDR + 0x004000000,
- AU1000_PCMCIA_IO_PHYS_ADDR + 0x004010000 - 1,
- AU1550_GPIO5_INT, AU1550_GPIO1_INT,
- /*AU1550_GPIO22_INT*/0, 0, 1);
+ id ? pb1550_devices() : db1550_devices();
- swapped = bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1000_SWAPBOOT;
+ swapped = bcsr_read(BCSR_STATUS) &
+ (id ? BCSR_STATUS_PB1550_SWAPBOOT : BCSR_STATUS_DB1000_SWAPBOOT);
db1x_register_norflash(128 << 20, 4, swapped);
return platform_add_devices(db1550_devs, ARRAY_SIZE(db1550_devs));
}
-device_initcall(db1550_dev_init);