Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.4-rc4 244 lines 6.4 kB view raw
1/* 2 * Pb1550 board support. 3 * 4 * Copyright (C) 2009-2011 Manuel Lauss 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include <linux/dma-mapping.h> 22#include <linux/init.h> 23#include <linux/interrupt.h> 24#include <linux/platform_device.h> 25#include <asm/mach-au1x00/au1000.h> 26#include <asm/mach-au1x00/au1xxx_dbdma.h> 27#include <asm/mach-au1x00/au1550nd.h> 28#include <asm/mach-au1x00/gpio.h> 29#include <asm/mach-db1x00/bcsr.h> 30#include "platform.h" 31 32const char *get_system_type(void) 33{ 34 return "PB1550"; 35} 36 37void __init board_setup(void) 38{ 39 u32 pin_func; 40 41 bcsr_init(PB1550_BCSR_PHYS_ADDR, 42 PB1550_BCSR_PHYS_ADDR + PB1550_BCSR_HEXLED_OFS); 43 44 alchemy_gpio2_enable(); 45 46 /* 47 * Enable PSC1 SYNC for AC'97. Normaly done in audio driver, 48 * but it is board specific code, so put it here. 49 */ 50 pin_func = au_readl(SYS_PINFUNC); 51 au_sync(); 52 pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1; 53 au_writel(pin_func, SYS_PINFUNC); 54 55 bcsr_write(BCSR_PCMCIA, 0); /* turn off PCMCIA power */ 56 57 printk(KERN_INFO "AMD Alchemy Pb1550 Board\n"); 58} 59 60/******************************************************************************/ 61 62static int pb1550_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin) 63{ 64 if ((slot < 12) || (slot > 13) || pin == 0) 65 return -1; 66 if (slot == 12) { 67 switch (pin) { 68 case 1: return AU1500_PCI_INTB; 69 case 2: return AU1500_PCI_INTC; 70 case 3: return AU1500_PCI_INTD; 71 case 4: return AU1500_PCI_INTA; 72 } 73 } 74 if (slot == 13) { 75 switch (pin) { 76 case 1: return AU1500_PCI_INTA; 77 case 2: return AU1500_PCI_INTB; 78 case 3: return AU1500_PCI_INTC; 79 case 4: return AU1500_PCI_INTD; 80 } 81 } 82 return -1; 83} 84 85static struct resource alchemy_pci_host_res[] = { 86 [0] = { 87 .start = AU1500_PCI_PHYS_ADDR, 88 .end = AU1500_PCI_PHYS_ADDR + 0xfff, 89 .flags = IORESOURCE_MEM, 90 }, 91}; 92 93static struct alchemy_pci_platdata pb1550_pci_pd = { 94 .board_map_irq = pb1550_map_pci_irq, 95}; 96 97static struct platform_device pb1550_pci_host = { 98 .dev.platform_data = &pb1550_pci_pd, 99 .name = "alchemy-pci", 100 .id = 0, 101 .num_resources = ARRAY_SIZE(alchemy_pci_host_res), 102 .resource = alchemy_pci_host_res, 103}; 104 105static struct resource au1550_psc2_res[] = { 106 [0] = { 107 .start = AU1550_PSC2_PHYS_ADDR, 108 .end = AU1550_PSC2_PHYS_ADDR + 0xfff, 109 .flags = IORESOURCE_MEM, 110 }, 111 [1] = { 112 .start = AU1550_PSC2_INT, 113 .end = AU1550_PSC2_INT, 114 .flags = IORESOURCE_IRQ, 115 }, 116 [2] = { 117 .start = AU1550_DSCR_CMD0_PSC2_TX, 118 .end = AU1550_DSCR_CMD0_PSC2_TX, 119 .flags = IORESOURCE_DMA, 120 }, 121 [3] = { 122 .start = AU1550_DSCR_CMD0_PSC2_RX, 123 .end = AU1550_DSCR_CMD0_PSC2_RX, 124 .flags = IORESOURCE_DMA, 125 }, 126}; 127 128static struct platform_device pb1550_i2c_dev = { 129 .name = "au1xpsc_smbus", 130 .id = 0, /* bus number */ 131 .num_resources = ARRAY_SIZE(au1550_psc2_res), 132 .resource = au1550_psc2_res, 133}; 134 135static struct mtd_partition pb1550_nand_parts[] = { 136 [0] = { 137 .name = "NAND FS 0", 138 .offset = 0, 139 .size = 8 * 1024 * 1024, 140 }, 141 [1] = { 142 .name = "NAND FS 1", 143 .offset = MTDPART_OFS_APPEND, 144 .size = MTDPART_SIZ_FULL, 145 }, 146}; 147 148static struct au1550nd_platdata pb1550_nand_pd = { 149 .parts = pb1550_nand_parts, 150 .num_parts = ARRAY_SIZE(pb1550_nand_parts), 151 .devwidth = 0, /* x8 NAND default, needs fixing up */ 152}; 153 154static struct resource pb1550_nand_res[] = { 155 [0] = { 156 .start = 0x20000000, 157 .end = 0x20000fff, 158 .flags = IORESOURCE_MEM, 159 }, 160}; 161 162static struct platform_device pb1550_nand_dev = { 163 .name = "au1550-nand", 164 .id = -1, 165 .resource = pb1550_nand_res, 166 .num_resources = ARRAY_SIZE(pb1550_nand_res), 167 .dev = { 168 .platform_data = &pb1550_nand_pd, 169 }, 170}; 171 172static void __init pb1550_nand_setup(void) 173{ 174 int boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | 175 ((bcsr_read(BCSR_STATUS) >> 6) & 0x1); 176 177 switch (boot_swapboot) { 178 case 0: 179 case 2: 180 case 8: 181 case 0xC: 182 case 0xD: 183 /* x16 NAND Flash */ 184 pb1550_nand_pd.devwidth = 1; 185 /* fallthrough */ 186 case 1: 187 case 9: 188 case 3: 189 case 0xE: 190 case 0xF: 191 /* x8 NAND, already set up */ 192 platform_device_register(&pb1550_nand_dev); 193 } 194} 195 196static int __init pb1550_dev_init(void) 197{ 198 int swapped; 199 200 irq_set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW); 201 irq_set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW); 202 irq_set_irq_type(AU1550_GPIO201_205_INT, IRQF_TRIGGER_HIGH); 203 204 /* enable both PCMCIA card irqs in the shared line */ 205 alchemy_gpio2_enable_int(201); 206 alchemy_gpio2_enable_int(202); 207 208 /* Pb1550, like all others, also has statuschange irqs; however they're 209 * wired up on one of the Au1550's shared GPIO201_205 line, which also 210 * services the PCMCIA card interrupts. So we ignore statuschange and 211 * use the GPIO201_205 exclusively for card interrupts, since a) pcmcia 212 * drivers are used to shared irqs and b) statuschange isn't really use- 213 * ful anyway. 214 */ 215 db1x_register_pcmcia_socket( 216 AU1000_PCMCIA_ATTR_PHYS_ADDR, 217 AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1, 218 AU1000_PCMCIA_MEM_PHYS_ADDR, 219 AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1, 220 AU1000_PCMCIA_IO_PHYS_ADDR, 221 AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1, 222 AU1550_GPIO201_205_INT, AU1550_GPIO0_INT, 0, 0, 0); 223 224 db1x_register_pcmcia_socket( 225 AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008000000, 226 AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1, 227 AU1000_PCMCIA_MEM_PHYS_ADDR + 0x008000000, 228 AU1000_PCMCIA_MEM_PHYS_ADDR + 0x008400000 - 1, 229 AU1000_PCMCIA_IO_PHYS_ADDR + 0x008000000, 230 AU1000_PCMCIA_IO_PHYS_ADDR + 0x008010000 - 1, 231 AU1550_GPIO201_205_INT, AU1550_GPIO1_INT, 0, 0, 1); 232 233 /* NAND setup */ 234 gpio_direction_input(206); /* GPIO206 high */ 235 pb1550_nand_setup(); 236 237 swapped = bcsr_read(BCSR_STATUS) & BCSR_STATUS_PB1550_SWAPBOOT; 238 db1x_register_norflash(128 * 1024 * 1024, 4, swapped); 239 platform_device_register(&pb1550_pci_host); 240 platform_device_register(&pb1550_i2c_dev); 241 242 return 0; 243} 244arch_initcall(pb1550_dev_init);