1f59c811fSManuel Lauss /* 2f59c811fSManuel Lauss * DBAu1000/1500/1100 board support 3f59c811fSManuel Lauss * 4f59c811fSManuel Lauss * Copyright 2000, 2008 MontaVista Software Inc. 5f59c811fSManuel Lauss * Author: MontaVista Software, Inc. <source@mvista.com> 6f59c811fSManuel Lauss * 7f59c811fSManuel Lauss * This program is free software; you can redistribute it and/or modify 8f59c811fSManuel Lauss * it under the terms of the GNU General Public License as published by 9f59c811fSManuel Lauss * the Free Software Foundation; either version 2 of the License, or 10f59c811fSManuel Lauss * (at your option) any later version. 11f59c811fSManuel Lauss * 12f59c811fSManuel Lauss * This program is distributed in the hope that it will be useful, 13f59c811fSManuel Lauss * but WITHOUT ANY WARRANTY; without even the implied warranty of 14f59c811fSManuel Lauss * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15f59c811fSManuel Lauss * GNU General Public License for more details. 16f59c811fSManuel Lauss * 17f59c811fSManuel Lauss * You should have received a copy of the GNU General Public License 18f59c811fSManuel Lauss * along with this program; if not, write to the Free Software 19f59c811fSManuel Lauss * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20f59c811fSManuel Lauss */ 21f59c811fSManuel Lauss 22f59c811fSManuel Lauss #include <linux/dma-mapping.h> 23f59c811fSManuel Lauss #include <linux/gpio.h> 24f59c811fSManuel Lauss #include <linux/init.h> 25f59c811fSManuel Lauss #include <linux/interrupt.h> 26f59c811fSManuel Lauss #include <linux/platform_device.h> 27f59c811fSManuel Lauss #include <linux/pm.h> 28f59c811fSManuel Lauss #include <asm/mach-au1x00/au1000.h> 29f59c811fSManuel Lauss #include <asm/mach-au1x00/au1000_dma.h> 30f59c811fSManuel Lauss #include <asm/mach-db1x00/bcsr.h> 31f59c811fSManuel Lauss #include <asm/reboot.h> 32f59c811fSManuel Lauss #include <prom.h> 33f59c811fSManuel Lauss #include "platform.h" 34f59c811fSManuel Lauss 35f59c811fSManuel Lauss #define F_SWAPPED (bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1000_SWAPBOOT) 36f59c811fSManuel Lauss 37f59c811fSManuel Lauss struct pci_dev; 38f59c811fSManuel Lauss 39f59c811fSManuel Lauss static const char *board_type_str(void) 40f59c811fSManuel Lauss { 41f59c811fSManuel Lauss switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) { 42f59c811fSManuel Lauss case BCSR_WHOAMI_DB1000: 43f59c811fSManuel Lauss return "DB1000"; 44f59c811fSManuel Lauss case BCSR_WHOAMI_DB1500: 45f59c811fSManuel Lauss return "DB1500"; 46f59c811fSManuel Lauss case BCSR_WHOAMI_DB1100: 47f59c811fSManuel Lauss return "DB1100"; 48f59c811fSManuel Lauss default: 49f59c811fSManuel Lauss return "(unknown)"; 50f59c811fSManuel Lauss } 51f59c811fSManuel Lauss } 52f59c811fSManuel Lauss 53f59c811fSManuel Lauss const char *get_system_type(void) 54f59c811fSManuel Lauss { 55f59c811fSManuel Lauss return board_type_str(); 56f59c811fSManuel Lauss } 57f59c811fSManuel Lauss 58f59c811fSManuel Lauss void __init board_setup(void) 59f59c811fSManuel Lauss { 60f59c811fSManuel Lauss /* initialize board register space */ 61f59c811fSManuel Lauss bcsr_init(DB1000_BCSR_PHYS_ADDR, 62f59c811fSManuel Lauss DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS); 63f59c811fSManuel Lauss 64f59c811fSManuel Lauss printk(KERN_INFO "AMD Alchemy %s Board\n", board_type_str()); 65f59c811fSManuel Lauss 66f59c811fSManuel Lauss #if defined(CONFIG_IRDA) && defined(CONFIG_AU1000_FIR) 67f59c811fSManuel Lauss { 68f59c811fSManuel Lauss u32 pin_func; 69f59c811fSManuel Lauss 70f59c811fSManuel Lauss /* Set IRFIRSEL instead of GPIO15 */ 71f59c811fSManuel Lauss pin_func = au_readl(SYS_PINFUNC) | SYS_PF_IRF; 72f59c811fSManuel Lauss au_writel(pin_func, SYS_PINFUNC); 73f59c811fSManuel Lauss /* Power off until the driver is in use */ 74f59c811fSManuel Lauss bcsr_mod(BCSR_RESETS, BCSR_RESETS_IRDA_MODE_MASK, 75f59c811fSManuel Lauss BCSR_RESETS_IRDA_MODE_OFF); 76f59c811fSManuel Lauss } 77f59c811fSManuel Lauss #endif 78f59c811fSManuel Lauss bcsr_write(BCSR_PCMCIA, 0); /* turn off PCMCIA power */ 79f59c811fSManuel Lauss 80f59c811fSManuel Lauss /* Enable GPIO[31:0] inputs */ 81f59c811fSManuel Lauss alchemy_gpio1_input_enable(); 82f59c811fSManuel Lauss } 83f59c811fSManuel Lauss 84f59c811fSManuel Lauss 85f59c811fSManuel Lauss static int db1500_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin) 86f59c811fSManuel Lauss { 87f59c811fSManuel Lauss if ((slot < 12) || (slot > 13) || pin == 0) 88f59c811fSManuel Lauss return -1; 89f59c811fSManuel Lauss if (slot == 12) 90f59c811fSManuel Lauss return (pin == 1) ? AU1500_PCI_INTA : 0xff; 91f59c811fSManuel Lauss if (slot == 13) { 92f59c811fSManuel Lauss switch (pin) { 93f59c811fSManuel Lauss case 1: return AU1500_PCI_INTA; 94f59c811fSManuel Lauss case 2: return AU1500_PCI_INTB; 95f59c811fSManuel Lauss case 3: return AU1500_PCI_INTC; 96f59c811fSManuel Lauss case 4: return AU1500_PCI_INTD; 97f59c811fSManuel Lauss } 98f59c811fSManuel Lauss } 99f59c811fSManuel Lauss return -1; 100f59c811fSManuel Lauss } 101f59c811fSManuel Lauss 102f59c811fSManuel Lauss static struct resource alchemy_pci_host_res[] = { 103f59c811fSManuel Lauss [0] = { 104f59c811fSManuel Lauss .start = AU1500_PCI_PHYS_ADDR, 105f59c811fSManuel Lauss .end = AU1500_PCI_PHYS_ADDR + 0xfff, 106f59c811fSManuel Lauss .flags = IORESOURCE_MEM, 107f59c811fSManuel Lauss }, 108f59c811fSManuel Lauss }; 109f59c811fSManuel Lauss 110f59c811fSManuel Lauss static struct alchemy_pci_platdata db1500_pci_pd = { 111f59c811fSManuel Lauss .board_map_irq = db1500_map_pci_irq, 112f59c811fSManuel Lauss }; 113f59c811fSManuel Lauss 114f59c811fSManuel Lauss static struct platform_device db1500_pci_host_dev = { 115f59c811fSManuel Lauss .dev.platform_data = &db1500_pci_pd, 116f59c811fSManuel Lauss .name = "alchemy-pci", 117f59c811fSManuel Lauss .id = 0, 118f59c811fSManuel Lauss .num_resources = ARRAY_SIZE(alchemy_pci_host_res), 119f59c811fSManuel Lauss .resource = alchemy_pci_host_res, 120f59c811fSManuel Lauss }; 121f59c811fSManuel Lauss 122f59c811fSManuel Lauss static int __init db1500_pci_init(void) 123f59c811fSManuel Lauss { 124f59c811fSManuel Lauss if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1500) 125f59c811fSManuel Lauss return platform_device_register(&db1500_pci_host_dev); 126f59c811fSManuel Lauss return 0; 127f59c811fSManuel Lauss } 128f59c811fSManuel Lauss /* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */ 129f59c811fSManuel Lauss arch_initcall(db1500_pci_init); 130f59c811fSManuel Lauss 131f59c811fSManuel Lauss 132f59c811fSManuel Lauss static struct resource au1100_lcd_resources[] = { 133f59c811fSManuel Lauss [0] = { 134f59c811fSManuel Lauss .start = AU1100_LCD_PHYS_ADDR, 135f59c811fSManuel Lauss .end = AU1100_LCD_PHYS_ADDR + 0x800 - 1, 136f59c811fSManuel Lauss .flags = IORESOURCE_MEM, 137f59c811fSManuel Lauss }, 138f59c811fSManuel Lauss [1] = { 139f59c811fSManuel Lauss .start = AU1100_LCD_INT, 140f59c811fSManuel Lauss .end = AU1100_LCD_INT, 141f59c811fSManuel Lauss .flags = IORESOURCE_IRQ, 142f59c811fSManuel Lauss } 143f59c811fSManuel Lauss }; 144f59c811fSManuel Lauss 145f59c811fSManuel Lauss static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32); 146f59c811fSManuel Lauss 147f59c811fSManuel Lauss static struct platform_device au1100_lcd_device = { 148f59c811fSManuel Lauss .name = "au1100-lcd", 149f59c811fSManuel Lauss .id = 0, 150f59c811fSManuel Lauss .dev = { 151f59c811fSManuel Lauss .dma_mask = &au1100_lcd_dmamask, 152f59c811fSManuel Lauss .coherent_dma_mask = DMA_BIT_MASK(32), 153f59c811fSManuel Lauss }, 154f59c811fSManuel Lauss .num_resources = ARRAY_SIZE(au1100_lcd_resources), 155f59c811fSManuel Lauss .resource = au1100_lcd_resources, 156f59c811fSManuel Lauss }; 157f59c811fSManuel Lauss 158f59c811fSManuel Lauss static struct resource alchemy_ac97c_res[] = { 159f59c811fSManuel Lauss [0] = { 160f59c811fSManuel Lauss .start = AU1000_AC97_PHYS_ADDR, 161f59c811fSManuel Lauss .end = AU1000_AC97_PHYS_ADDR + 0xfff, 162f59c811fSManuel Lauss .flags = IORESOURCE_MEM, 163f59c811fSManuel Lauss }, 164f59c811fSManuel Lauss [1] = { 165f59c811fSManuel Lauss .start = DMA_ID_AC97C_TX, 166f59c811fSManuel Lauss .end = DMA_ID_AC97C_TX, 167f59c811fSManuel Lauss .flags = IORESOURCE_DMA, 168f59c811fSManuel Lauss }, 169f59c811fSManuel Lauss [2] = { 170f59c811fSManuel Lauss .start = DMA_ID_AC97C_RX, 171f59c811fSManuel Lauss .end = DMA_ID_AC97C_RX, 172f59c811fSManuel Lauss .flags = IORESOURCE_DMA, 173f59c811fSManuel Lauss }, 174f59c811fSManuel Lauss }; 175f59c811fSManuel Lauss 176f59c811fSManuel Lauss static struct platform_device alchemy_ac97c_dev = { 177f59c811fSManuel Lauss .name = "alchemy-ac97c", 178f59c811fSManuel Lauss .id = -1, 179f59c811fSManuel Lauss .resource = alchemy_ac97c_res, 180f59c811fSManuel Lauss .num_resources = ARRAY_SIZE(alchemy_ac97c_res), 181f59c811fSManuel Lauss }; 182f59c811fSManuel Lauss 183f59c811fSManuel Lauss static struct platform_device alchemy_ac97c_dma_dev = { 184f59c811fSManuel Lauss .name = "alchemy-pcm-dma", 185f59c811fSManuel Lauss .id = 0, 186f59c811fSManuel Lauss }; 187f59c811fSManuel Lauss 188f59c811fSManuel Lauss static struct platform_device db1x00_codec_dev = { 189f59c811fSManuel Lauss .name = "ac97-codec", 190f59c811fSManuel Lauss .id = -1, 191f59c811fSManuel Lauss }; 192f59c811fSManuel Lauss 193f59c811fSManuel Lauss static struct platform_device db1x00_audio_dev = { 194f59c811fSManuel Lauss .name = "db1000-audio", 195f59c811fSManuel Lauss }; 196f59c811fSManuel Lauss 197f59c811fSManuel Lauss static struct platform_device *db1x00_devs[] = { 198f59c811fSManuel Lauss &db1x00_codec_dev, 199f59c811fSManuel Lauss &alchemy_ac97c_dma_dev, 200f59c811fSManuel Lauss &alchemy_ac97c_dev, 201f59c811fSManuel Lauss &db1x00_audio_dev, 202f59c811fSManuel Lauss }; 203f59c811fSManuel Lauss 204f59c811fSManuel Lauss static struct platform_device *db1100_devs[] = { 205f59c811fSManuel Lauss &au1100_lcd_device, 206f59c811fSManuel Lauss }; 207f59c811fSManuel Lauss 208f59c811fSManuel Lauss static int __init db1000_dev_init(void) 209f59c811fSManuel Lauss { 210f59c811fSManuel Lauss int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)); 211f59c811fSManuel Lauss int c0, c1, d0, d1, s0, s1; 212f59c811fSManuel Lauss 213f59c811fSManuel Lauss if (board == BCSR_WHOAMI_DB1500) { 214f59c811fSManuel Lauss c0 = AU1500_GPIO2_INT; 215f59c811fSManuel Lauss c1 = AU1500_GPIO5_INT; 216f59c811fSManuel Lauss d0 = AU1500_GPIO0_INT; 217f59c811fSManuel Lauss d1 = AU1500_GPIO3_INT; 218f59c811fSManuel Lauss s0 = AU1500_GPIO1_INT; 219f59c811fSManuel Lauss s1 = AU1500_GPIO4_INT; 220f59c811fSManuel Lauss } else if (board == BCSR_WHOAMI_DB1100) { 221f59c811fSManuel Lauss c0 = AU1100_GPIO2_INT; 222f59c811fSManuel Lauss c1 = AU1100_GPIO5_INT; 223f59c811fSManuel Lauss d0 = AU1100_GPIO0_INT; 224f59c811fSManuel Lauss d1 = AU1100_GPIO3_INT; 225f59c811fSManuel Lauss s0 = AU1100_GPIO1_INT; 226f59c811fSManuel Lauss s1 = AU1100_GPIO4_INT; 227f59c811fSManuel Lauss platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs)); 228f59c811fSManuel Lauss } else if (board == BCSR_WHOAMI_DB1000) { 229f59c811fSManuel Lauss c0 = AU1000_GPIO2_INT; 230f59c811fSManuel Lauss c1 = AU1000_GPIO5_INT; 231f59c811fSManuel Lauss d0 = AU1000_GPIO0_INT; 232f59c811fSManuel Lauss d1 = AU1000_GPIO3_INT; 233f59c811fSManuel Lauss s0 = AU1000_GPIO1_INT; 234f59c811fSManuel Lauss s1 = AU1000_GPIO4_INT; 235f59c811fSManuel Lauss } else 236f59c811fSManuel Lauss return 0; /* unknown board, no further dev setup to do */ 237f59c811fSManuel Lauss 238f59c811fSManuel Lauss irq_set_irq_type(d0, IRQ_TYPE_EDGE_BOTH); 239f59c811fSManuel Lauss irq_set_irq_type(d1, IRQ_TYPE_EDGE_BOTH); 240f59c811fSManuel Lauss irq_set_irq_type(c0, IRQ_TYPE_LEVEL_LOW); 241f59c811fSManuel Lauss irq_set_irq_type(c1, IRQ_TYPE_LEVEL_LOW); 242f59c811fSManuel Lauss irq_set_irq_type(s0, IRQ_TYPE_LEVEL_LOW); 243f59c811fSManuel Lauss irq_set_irq_type(s1, IRQ_TYPE_LEVEL_LOW); 244f59c811fSManuel Lauss 245f59c811fSManuel Lauss db1x_register_pcmcia_socket( 246f59c811fSManuel Lauss AU1000_PCMCIA_ATTR_PHYS_ADDR, 247f59c811fSManuel Lauss AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1, 248f59c811fSManuel Lauss AU1000_PCMCIA_MEM_PHYS_ADDR, 249f59c811fSManuel Lauss AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1, 250f59c811fSManuel Lauss AU1000_PCMCIA_IO_PHYS_ADDR, 251f59c811fSManuel Lauss AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1, 252f59c811fSManuel Lauss c0, d0, /*s0*/0, 0, 0); 253f59c811fSManuel Lauss 254f59c811fSManuel Lauss db1x_register_pcmcia_socket( 255f59c811fSManuel Lauss AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000, 256f59c811fSManuel Lauss AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1, 257f59c811fSManuel Lauss AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004000000, 258f59c811fSManuel Lauss AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004400000 - 1, 259f59c811fSManuel Lauss AU1000_PCMCIA_IO_PHYS_ADDR + 0x004000000, 260f59c811fSManuel Lauss AU1000_PCMCIA_IO_PHYS_ADDR + 0x004010000 - 1, 261f59c811fSManuel Lauss c1, d1, /*s1*/0, 0, 1); 262f59c811fSManuel Lauss 263f59c811fSManuel Lauss platform_add_devices(db1x00_devs, ARRAY_SIZE(db1x00_devs)); 264f59c811fSManuel Lauss db1x_register_norflash(32 << 20, 4 /* 32bit */, F_SWAPPED); 265f59c811fSManuel Lauss return 0; 266f59c811fSManuel Lauss } 267f59c811fSManuel Lauss device_initcall(db1000_dev_init); 268