162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Alchemy Db1550/Pb1550 board support 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/clk.h> 962306a36Sopenharmony_ci#include <linux/dma-mapping.h> 1062306a36Sopenharmony_ci#include <linux/gpio.h> 1162306a36Sopenharmony_ci#include <linux/i2c.h> 1262306a36Sopenharmony_ci#include <linux/init.h> 1362306a36Sopenharmony_ci#include <linux/io.h> 1462306a36Sopenharmony_ci#include <linux/interrupt.h> 1562306a36Sopenharmony_ci#include <linux/mtd/mtd.h> 1662306a36Sopenharmony_ci#include <linux/mtd/platnand.h> 1762306a36Sopenharmony_ci#include <linux/platform_device.h> 1862306a36Sopenharmony_ci#include <linux/pm.h> 1962306a36Sopenharmony_ci#include <linux/spi/spi.h> 2062306a36Sopenharmony_ci#include <linux/spi/flash.h> 2162306a36Sopenharmony_ci#include <asm/bootinfo.h> 2262306a36Sopenharmony_ci#include <asm/mach-au1x00/au1000.h> 2362306a36Sopenharmony_ci#include <asm/mach-au1x00/gpio-au1000.h> 2462306a36Sopenharmony_ci#include <asm/mach-au1x00/au1xxx_eth.h> 2562306a36Sopenharmony_ci#include <asm/mach-au1x00/au1xxx_dbdma.h> 2662306a36Sopenharmony_ci#include <asm/mach-au1x00/au1xxx_psc.h> 2762306a36Sopenharmony_ci#include <asm/mach-au1x00/au1550_spi.h> 2862306a36Sopenharmony_ci#include <asm/mach-au1x00/au1550nd.h> 2962306a36Sopenharmony_ci#include <asm/mach-db1x00/bcsr.h> 3062306a36Sopenharmony_ci#include <prom.h> 3162306a36Sopenharmony_ci#include "platform.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic void __init db1550_hw_setup(void) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci void __iomem *base; 3662306a36Sopenharmony_ci unsigned long v; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci /* complete pin setup: assign GPIO16 to PSC0_SYNC1 (SPI cs# line) 3962306a36Sopenharmony_ci * as well as PSC1_SYNC for AC97 on PB1550. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci v = alchemy_rdsys(AU1000_SYS_PINFUNC); 4262306a36Sopenharmony_ci alchemy_wrsys(v | 1 | SYS_PF_PSC1_S1, AU1000_SYS_PINFUNC); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* reset the AC97 codec now, the reset time in the psc-ac97 driver 4562306a36Sopenharmony_ci * is apparently too short although it's ridiculous as it is. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci base = (void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR); 4862306a36Sopenharmony_ci __raw_writel(PSC_SEL_CLK_SERCLK | PSC_SEL_PS_AC97MODE, 4962306a36Sopenharmony_ci base + PSC_SEL_OFFSET); 5062306a36Sopenharmony_ci __raw_writel(PSC_CTRL_DISABLE, base + PSC_CTRL_OFFSET); 5162306a36Sopenharmony_ci wmb(); 5262306a36Sopenharmony_ci __raw_writel(PSC_AC97RST_RST, base + PSC_AC97RST_OFFSET); 5362306a36Sopenharmony_ci wmb(); 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ciint __init db1550_board_setup(void) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci unsigned short whoami; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci bcsr_init(DB1550_BCSR_PHYS_ADDR, 6162306a36Sopenharmony_ci DB1550_BCSR_PHYS_ADDR + DB1550_BCSR_HEXLED_OFS); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci whoami = bcsr_read(BCSR_WHOAMI); /* PB1550 hexled offset differs */ 6462306a36Sopenharmony_ci switch (BCSR_WHOAMI_BOARD(whoami)) { 6562306a36Sopenharmony_ci case BCSR_WHOAMI_PB1550_SDR: 6662306a36Sopenharmony_ci case BCSR_WHOAMI_PB1550_DDR: 6762306a36Sopenharmony_ci bcsr_init(PB1550_BCSR_PHYS_ADDR, 6862306a36Sopenharmony_ci PB1550_BCSR_PHYS_ADDR + PB1550_BCSR_HEXLED_OFS); 6962306a36Sopenharmony_ci break; 7062306a36Sopenharmony_ci case BCSR_WHOAMI_DB1550: 7162306a36Sopenharmony_ci break; 7262306a36Sopenharmony_ci default: 7362306a36Sopenharmony_ci return -ENODEV; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci pr_info("Alchemy/AMD %s Board, CPLD Rev %d Board-ID %d " \ 7762306a36Sopenharmony_ci "Daughtercard ID %d\n", get_system_type(), 7862306a36Sopenharmony_ci (whoami >> 4) & 0xf, (whoami >> 8) & 0xf, whoami & 0xf); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci db1550_hw_setup(); 8162306a36Sopenharmony_ci return 0; 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/*****************************************************************************/ 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic u64 au1550_all_dmamask = DMA_BIT_MASK(32); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic struct mtd_partition db1550_spiflash_parts[] = { 8962306a36Sopenharmony_ci { 9062306a36Sopenharmony_ci .name = "spi_flash", 9162306a36Sopenharmony_ci .offset = 0, 9262306a36Sopenharmony_ci .size = MTDPART_SIZ_FULL, 9362306a36Sopenharmony_ci }, 9462306a36Sopenharmony_ci}; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic struct flash_platform_data db1550_spiflash_data = { 9762306a36Sopenharmony_ci .name = "s25fl010", 9862306a36Sopenharmony_ci .parts = db1550_spiflash_parts, 9962306a36Sopenharmony_ci .nr_parts = ARRAY_SIZE(db1550_spiflash_parts), 10062306a36Sopenharmony_ci .type = "m25p10", 10162306a36Sopenharmony_ci}; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic struct spi_board_info db1550_spi_devs[] __initdata = { 10462306a36Sopenharmony_ci { 10562306a36Sopenharmony_ci /* TI TMP121AIDBVR temp sensor */ 10662306a36Sopenharmony_ci .modalias = "tmp121", 10762306a36Sopenharmony_ci .max_speed_hz = 2400000, 10862306a36Sopenharmony_ci .bus_num = 0, 10962306a36Sopenharmony_ci .chip_select = 0, 11062306a36Sopenharmony_ci .mode = SPI_MODE_0, 11162306a36Sopenharmony_ci }, 11262306a36Sopenharmony_ci { 11362306a36Sopenharmony_ci /* Spansion S25FL001D0FMA SPI flash */ 11462306a36Sopenharmony_ci .modalias = "m25p80", 11562306a36Sopenharmony_ci .max_speed_hz = 2400000, 11662306a36Sopenharmony_ci .bus_num = 0, 11762306a36Sopenharmony_ci .chip_select = 1, 11862306a36Sopenharmony_ci .mode = SPI_MODE_0, 11962306a36Sopenharmony_ci .platform_data = &db1550_spiflash_data, 12062306a36Sopenharmony_ci }, 12162306a36Sopenharmony_ci}; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic struct i2c_board_info db1550_i2c_devs[] __initdata = { 12462306a36Sopenharmony_ci { I2C_BOARD_INFO("24c04", 0x52),}, /* AT24C04-10 I2C eeprom */ 12562306a36Sopenharmony_ci { I2C_BOARD_INFO("ne1619", 0x2d),}, /* adm1025-compat hwmon */ 12662306a36Sopenharmony_ci { I2C_BOARD_INFO("wm8731", 0x1b),}, /* I2S audio codec WM8731 */ 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/**********************************************************************/ 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic void au1550_nand_cmd_ctrl(struct nand_chip *this, int cmd, 13262306a36Sopenharmony_ci unsigned int ctrl) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci unsigned long ioaddr = (unsigned long)this->legacy.IO_ADDR_W; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci ioaddr &= 0xffffff00; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci if (ctrl & NAND_CLE) { 13962306a36Sopenharmony_ci ioaddr += MEM_STNAND_CMD; 14062306a36Sopenharmony_ci } else if (ctrl & NAND_ALE) { 14162306a36Sopenharmony_ci ioaddr += MEM_STNAND_ADDR; 14262306a36Sopenharmony_ci } else { 14362306a36Sopenharmony_ci /* assume we want to r/w real data by default */ 14462306a36Sopenharmony_ci ioaddr += MEM_STNAND_DATA; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W = (void __iomem *)ioaddr; 14762306a36Sopenharmony_ci if (cmd != NAND_CMD_NONE) { 14862306a36Sopenharmony_ci __raw_writeb(cmd, this->legacy.IO_ADDR_W); 14962306a36Sopenharmony_ci wmb(); 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic int au1550_nand_device_ready(struct nand_chip *this) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1; 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic struct mtd_partition db1550_nand_parts[] = { 15962306a36Sopenharmony_ci { 16062306a36Sopenharmony_ci .name = "NAND FS 0", 16162306a36Sopenharmony_ci .offset = 0, 16262306a36Sopenharmony_ci .size = 8 * 1024 * 1024, 16362306a36Sopenharmony_ci }, 16462306a36Sopenharmony_ci { 16562306a36Sopenharmony_ci .name = "NAND FS 1", 16662306a36Sopenharmony_ci .offset = MTDPART_OFS_APPEND, 16762306a36Sopenharmony_ci .size = MTDPART_SIZ_FULL 16862306a36Sopenharmony_ci }, 16962306a36Sopenharmony_ci}; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistruct platform_nand_data db1550_nand_platdata = { 17262306a36Sopenharmony_ci .chip = { 17362306a36Sopenharmony_ci .nr_chips = 1, 17462306a36Sopenharmony_ci .chip_offset = 0, 17562306a36Sopenharmony_ci .nr_partitions = ARRAY_SIZE(db1550_nand_parts), 17662306a36Sopenharmony_ci .partitions = db1550_nand_parts, 17762306a36Sopenharmony_ci .chip_delay = 20, 17862306a36Sopenharmony_ci }, 17962306a36Sopenharmony_ci .ctrl = { 18062306a36Sopenharmony_ci .dev_ready = au1550_nand_device_ready, 18162306a36Sopenharmony_ci .cmd_ctrl = au1550_nand_cmd_ctrl, 18262306a36Sopenharmony_ci }, 18362306a36Sopenharmony_ci}; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic struct resource db1550_nand_res[] = { 18662306a36Sopenharmony_ci [0] = { 18762306a36Sopenharmony_ci .start = 0x20000000, 18862306a36Sopenharmony_ci .end = 0x200000ff, 18962306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 19062306a36Sopenharmony_ci }, 19162306a36Sopenharmony_ci}; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistatic struct platform_device db1550_nand_dev = { 19462306a36Sopenharmony_ci .name = "gen_nand", 19562306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(db1550_nand_res), 19662306a36Sopenharmony_ci .resource = db1550_nand_res, 19762306a36Sopenharmony_ci .id = -1, 19862306a36Sopenharmony_ci .dev = { 19962306a36Sopenharmony_ci .platform_data = &db1550_nand_platdata, 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci}; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic struct au1550nd_platdata pb1550_nand_pd = { 20462306a36Sopenharmony_ci .parts = db1550_nand_parts, 20562306a36Sopenharmony_ci .num_parts = ARRAY_SIZE(db1550_nand_parts), 20662306a36Sopenharmony_ci .devwidth = 0, /* x8 NAND default, needs fixing up */ 20762306a36Sopenharmony_ci}; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic struct platform_device pb1550_nand_dev = { 21062306a36Sopenharmony_ci .name = "au1550-nand", 21162306a36Sopenharmony_ci .id = -1, 21262306a36Sopenharmony_ci .resource = db1550_nand_res, 21362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(db1550_nand_res), 21462306a36Sopenharmony_ci .dev = { 21562306a36Sopenharmony_ci .platform_data = &pb1550_nand_pd, 21662306a36Sopenharmony_ci }, 21762306a36Sopenharmony_ci}; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic void __init pb1550_nand_setup(void) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci int boot_swapboot = (alchemy_rdsmem(AU1000_MEM_STSTAT) & (0x7 << 1)) | 22262306a36Sopenharmony_ci ((bcsr_read(BCSR_STATUS) >> 6) & 0x1); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci gpio_direction_input(206); /* de-assert NAND CS# */ 22562306a36Sopenharmony_ci switch (boot_swapboot) { 22662306a36Sopenharmony_ci case 0: case 2: case 8: case 0xC: case 0xD: 22762306a36Sopenharmony_ci /* x16 NAND Flash */ 22862306a36Sopenharmony_ci pb1550_nand_pd.devwidth = 1; 22962306a36Sopenharmony_ci fallthrough; 23062306a36Sopenharmony_ci case 1: case 3: case 9: case 0xE: case 0xF: 23162306a36Sopenharmony_ci /* x8 NAND, already set up */ 23262306a36Sopenharmony_ci platform_device_register(&pb1550_nand_dev); 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci/**********************************************************************/ 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic struct resource au1550_psc0_res[] = { 23962306a36Sopenharmony_ci [0] = { 24062306a36Sopenharmony_ci .start = AU1550_PSC0_PHYS_ADDR, 24162306a36Sopenharmony_ci .end = AU1550_PSC0_PHYS_ADDR + 0xfff, 24262306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 24362306a36Sopenharmony_ci }, 24462306a36Sopenharmony_ci [1] = { 24562306a36Sopenharmony_ci .start = AU1550_PSC0_INT, 24662306a36Sopenharmony_ci .end = AU1550_PSC0_INT, 24762306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 24862306a36Sopenharmony_ci }, 24962306a36Sopenharmony_ci [2] = { 25062306a36Sopenharmony_ci .start = AU1550_DSCR_CMD0_PSC0_TX, 25162306a36Sopenharmony_ci .end = AU1550_DSCR_CMD0_PSC0_TX, 25262306a36Sopenharmony_ci .flags = IORESOURCE_DMA, 25362306a36Sopenharmony_ci }, 25462306a36Sopenharmony_ci [3] = { 25562306a36Sopenharmony_ci .start = AU1550_DSCR_CMD0_PSC0_RX, 25662306a36Sopenharmony_ci .end = AU1550_DSCR_CMD0_PSC0_RX, 25762306a36Sopenharmony_ci .flags = IORESOURCE_DMA, 25862306a36Sopenharmony_ci }, 25962306a36Sopenharmony_ci}; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic void db1550_spi_cs_en(struct au1550_spi_info *spi, int cs, int pol) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci if (cs) 26462306a36Sopenharmony_ci bcsr_mod(BCSR_BOARD, 0, BCSR_BOARD_SPISEL); 26562306a36Sopenharmony_ci else 26662306a36Sopenharmony_ci bcsr_mod(BCSR_BOARD, BCSR_BOARD_SPISEL, 0); 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic struct au1550_spi_info db1550_spi_platdata = { 27062306a36Sopenharmony_ci .mainclk_hz = 48000000, /* PSC0 clock: max. 2.4MHz SPI clk */ 27162306a36Sopenharmony_ci .num_chipselect = 2, 27262306a36Sopenharmony_ci .activate_cs = db1550_spi_cs_en, 27362306a36Sopenharmony_ci}; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic struct platform_device db1550_spi_dev = { 27762306a36Sopenharmony_ci .dev = { 27862306a36Sopenharmony_ci .dma_mask = &au1550_all_dmamask, 27962306a36Sopenharmony_ci .coherent_dma_mask = DMA_BIT_MASK(32), 28062306a36Sopenharmony_ci .platform_data = &db1550_spi_platdata, 28162306a36Sopenharmony_ci }, 28262306a36Sopenharmony_ci .name = "au1550-spi", 28362306a36Sopenharmony_ci .id = 0, /* bus number */ 28462306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(au1550_psc0_res), 28562306a36Sopenharmony_ci .resource = au1550_psc0_res, 28662306a36Sopenharmony_ci}; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/**********************************************************************/ 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic struct resource au1550_psc1_res[] = { 29162306a36Sopenharmony_ci [0] = { 29262306a36Sopenharmony_ci .start = AU1550_PSC1_PHYS_ADDR, 29362306a36Sopenharmony_ci .end = AU1550_PSC1_PHYS_ADDR + 0xfff, 29462306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 29562306a36Sopenharmony_ci }, 29662306a36Sopenharmony_ci [1] = { 29762306a36Sopenharmony_ci .start = AU1550_PSC1_INT, 29862306a36Sopenharmony_ci .end = AU1550_PSC1_INT, 29962306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 30062306a36Sopenharmony_ci }, 30162306a36Sopenharmony_ci [2] = { 30262306a36Sopenharmony_ci .start = AU1550_DSCR_CMD0_PSC1_TX, 30362306a36Sopenharmony_ci .end = AU1550_DSCR_CMD0_PSC1_TX, 30462306a36Sopenharmony_ci .flags = IORESOURCE_DMA, 30562306a36Sopenharmony_ci }, 30662306a36Sopenharmony_ci [3] = { 30762306a36Sopenharmony_ci .start = AU1550_DSCR_CMD0_PSC1_RX, 30862306a36Sopenharmony_ci .end = AU1550_DSCR_CMD0_PSC1_RX, 30962306a36Sopenharmony_ci .flags = IORESOURCE_DMA, 31062306a36Sopenharmony_ci }, 31162306a36Sopenharmony_ci}; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cistatic struct platform_device db1550_ac97_dev = { 31462306a36Sopenharmony_ci .name = "au1xpsc_ac97", 31562306a36Sopenharmony_ci .id = 1, /* PSC ID */ 31662306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(au1550_psc1_res), 31762306a36Sopenharmony_ci .resource = au1550_psc1_res, 31862306a36Sopenharmony_ci}; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic struct resource au1550_psc2_res[] = { 32262306a36Sopenharmony_ci [0] = { 32362306a36Sopenharmony_ci .start = AU1550_PSC2_PHYS_ADDR, 32462306a36Sopenharmony_ci .end = AU1550_PSC2_PHYS_ADDR + 0xfff, 32562306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 32662306a36Sopenharmony_ci }, 32762306a36Sopenharmony_ci [1] = { 32862306a36Sopenharmony_ci .start = AU1550_PSC2_INT, 32962306a36Sopenharmony_ci .end = AU1550_PSC2_INT, 33062306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 33162306a36Sopenharmony_ci }, 33262306a36Sopenharmony_ci [2] = { 33362306a36Sopenharmony_ci .start = AU1550_DSCR_CMD0_PSC2_TX, 33462306a36Sopenharmony_ci .end = AU1550_DSCR_CMD0_PSC2_TX, 33562306a36Sopenharmony_ci .flags = IORESOURCE_DMA, 33662306a36Sopenharmony_ci }, 33762306a36Sopenharmony_ci [3] = { 33862306a36Sopenharmony_ci .start = AU1550_DSCR_CMD0_PSC2_RX, 33962306a36Sopenharmony_ci .end = AU1550_DSCR_CMD0_PSC2_RX, 34062306a36Sopenharmony_ci .flags = IORESOURCE_DMA, 34162306a36Sopenharmony_ci }, 34262306a36Sopenharmony_ci}; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic struct platform_device db1550_i2c_dev = { 34562306a36Sopenharmony_ci .name = "au1xpsc_smbus", 34662306a36Sopenharmony_ci .id = 0, /* bus number */ 34762306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(au1550_psc2_res), 34862306a36Sopenharmony_ci .resource = au1550_psc2_res, 34962306a36Sopenharmony_ci}; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/**********************************************************************/ 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_cistatic struct resource au1550_psc3_res[] = { 35462306a36Sopenharmony_ci [0] = { 35562306a36Sopenharmony_ci .start = AU1550_PSC3_PHYS_ADDR, 35662306a36Sopenharmony_ci .end = AU1550_PSC3_PHYS_ADDR + 0xfff, 35762306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 35862306a36Sopenharmony_ci }, 35962306a36Sopenharmony_ci [1] = { 36062306a36Sopenharmony_ci .start = AU1550_PSC3_INT, 36162306a36Sopenharmony_ci .end = AU1550_PSC3_INT, 36262306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 36362306a36Sopenharmony_ci }, 36462306a36Sopenharmony_ci [2] = { 36562306a36Sopenharmony_ci .start = AU1550_DSCR_CMD0_PSC3_TX, 36662306a36Sopenharmony_ci .end = AU1550_DSCR_CMD0_PSC3_TX, 36762306a36Sopenharmony_ci .flags = IORESOURCE_DMA, 36862306a36Sopenharmony_ci }, 36962306a36Sopenharmony_ci [3] = { 37062306a36Sopenharmony_ci .start = AU1550_DSCR_CMD0_PSC3_RX, 37162306a36Sopenharmony_ci .end = AU1550_DSCR_CMD0_PSC3_RX, 37262306a36Sopenharmony_ci .flags = IORESOURCE_DMA, 37362306a36Sopenharmony_ci }, 37462306a36Sopenharmony_ci}; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic struct platform_device db1550_i2s_dev = { 37762306a36Sopenharmony_ci .name = "au1xpsc_i2s", 37862306a36Sopenharmony_ci .id = 3, /* PSC ID */ 37962306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(au1550_psc3_res), 38062306a36Sopenharmony_ci .resource = au1550_psc3_res, 38162306a36Sopenharmony_ci}; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci/**********************************************************************/ 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic struct platform_device db1550_stac_dev = { 38662306a36Sopenharmony_ci .name = "ac97-codec", 38762306a36Sopenharmony_ci .id = 1, /* on PSC1 */ 38862306a36Sopenharmony_ci}; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic struct platform_device db1550_ac97dma_dev = { 39162306a36Sopenharmony_ci .name = "au1xpsc-pcm", 39262306a36Sopenharmony_ci .id = 1, /* on PSC3 */ 39362306a36Sopenharmony_ci}; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cistatic struct platform_device db1550_i2sdma_dev = { 39662306a36Sopenharmony_ci .name = "au1xpsc-pcm", 39762306a36Sopenharmony_ci .id = 3, /* on PSC3 */ 39862306a36Sopenharmony_ci}; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic struct platform_device db1550_sndac97_dev = { 40162306a36Sopenharmony_ci .name = "db1550-ac97", 40262306a36Sopenharmony_ci .dev = { 40362306a36Sopenharmony_ci .dma_mask = &au1550_all_dmamask, 40462306a36Sopenharmony_ci .coherent_dma_mask = DMA_BIT_MASK(32), 40562306a36Sopenharmony_ci }, 40662306a36Sopenharmony_ci}; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic struct platform_device db1550_sndi2s_dev = { 40962306a36Sopenharmony_ci .name = "db1550-i2s", 41062306a36Sopenharmony_ci .dev = { 41162306a36Sopenharmony_ci .dma_mask = &au1550_all_dmamask, 41262306a36Sopenharmony_ci .coherent_dma_mask = DMA_BIT_MASK(32), 41362306a36Sopenharmony_ci }, 41462306a36Sopenharmony_ci}; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci/**********************************************************************/ 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic int db1550_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci if ((slot < 11) || (slot > 13) || pin == 0) 42162306a36Sopenharmony_ci return -1; 42262306a36Sopenharmony_ci if (slot == 11) 42362306a36Sopenharmony_ci return (pin == 1) ? AU1550_PCI_INTC : 0xff; 42462306a36Sopenharmony_ci if (slot == 12) { 42562306a36Sopenharmony_ci switch (pin) { 42662306a36Sopenharmony_ci case 1: return AU1550_PCI_INTB; 42762306a36Sopenharmony_ci case 2: return AU1550_PCI_INTC; 42862306a36Sopenharmony_ci case 3: return AU1550_PCI_INTD; 42962306a36Sopenharmony_ci case 4: return AU1550_PCI_INTA; 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci if (slot == 13) { 43362306a36Sopenharmony_ci switch (pin) { 43462306a36Sopenharmony_ci case 1: return AU1550_PCI_INTA; 43562306a36Sopenharmony_ci case 2: return AU1550_PCI_INTB; 43662306a36Sopenharmony_ci case 3: return AU1550_PCI_INTC; 43762306a36Sopenharmony_ci case 4: return AU1550_PCI_INTD; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci return -1; 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cistatic int pb1550_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci if ((slot < 12) || (slot > 13) || pin == 0) 44662306a36Sopenharmony_ci return -1; 44762306a36Sopenharmony_ci if (slot == 12) { 44862306a36Sopenharmony_ci switch (pin) { 44962306a36Sopenharmony_ci case 1: return AU1500_PCI_INTB; 45062306a36Sopenharmony_ci case 2: return AU1500_PCI_INTC; 45162306a36Sopenharmony_ci case 3: return AU1500_PCI_INTD; 45262306a36Sopenharmony_ci case 4: return AU1500_PCI_INTA; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci if (slot == 13) { 45662306a36Sopenharmony_ci switch (pin) { 45762306a36Sopenharmony_ci case 1: return AU1500_PCI_INTA; 45862306a36Sopenharmony_ci case 2: return AU1500_PCI_INTB; 45962306a36Sopenharmony_ci case 3: return AU1500_PCI_INTC; 46062306a36Sopenharmony_ci case 4: return AU1500_PCI_INTD; 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci } 46362306a36Sopenharmony_ci return -1; 46462306a36Sopenharmony_ci} 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic struct resource alchemy_pci_host_res[] = { 46762306a36Sopenharmony_ci [0] = { 46862306a36Sopenharmony_ci .start = AU1500_PCI_PHYS_ADDR, 46962306a36Sopenharmony_ci .end = AU1500_PCI_PHYS_ADDR + 0xfff, 47062306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 47162306a36Sopenharmony_ci }, 47262306a36Sopenharmony_ci}; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic struct alchemy_pci_platdata db1550_pci_pd = { 47562306a36Sopenharmony_ci .board_map_irq = db1550_map_pci_irq, 47662306a36Sopenharmony_ci}; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cistatic struct platform_device db1550_pci_host_dev = { 47962306a36Sopenharmony_ci .dev.platform_data = &db1550_pci_pd, 48062306a36Sopenharmony_ci .name = "alchemy-pci", 48162306a36Sopenharmony_ci .id = 0, 48262306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(alchemy_pci_host_res), 48362306a36Sopenharmony_ci .resource = alchemy_pci_host_res, 48462306a36Sopenharmony_ci}; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci/**********************************************************************/ 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_cistatic struct platform_device *db1550_devs[] __initdata = { 48962306a36Sopenharmony_ci &db1550_i2c_dev, 49062306a36Sopenharmony_ci &db1550_ac97_dev, 49162306a36Sopenharmony_ci &db1550_spi_dev, 49262306a36Sopenharmony_ci &db1550_i2s_dev, 49362306a36Sopenharmony_ci &db1550_stac_dev, 49462306a36Sopenharmony_ci &db1550_ac97dma_dev, 49562306a36Sopenharmony_ci &db1550_i2sdma_dev, 49662306a36Sopenharmony_ci &db1550_sndac97_dev, 49762306a36Sopenharmony_ci &db1550_sndi2s_dev, 49862306a36Sopenharmony_ci}; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci/* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */ 50162306a36Sopenharmony_ciint __init db1550_pci_setup(int id) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci if (id) 50462306a36Sopenharmony_ci db1550_pci_pd.board_map_irq = pb1550_map_pci_irq; 50562306a36Sopenharmony_ci return platform_device_register(&db1550_pci_host_dev); 50662306a36Sopenharmony_ci} 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_cistatic void __init db1550_devices(void) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci alchemy_gpio_direction_output(203, 0); /* red led on */ 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci irq_set_irq_type(AU1550_GPIO0_INT, IRQ_TYPE_EDGE_BOTH); /* CD0# */ 51362306a36Sopenharmony_ci irq_set_irq_type(AU1550_GPIO1_INT, IRQ_TYPE_EDGE_BOTH); /* CD1# */ 51462306a36Sopenharmony_ci irq_set_irq_type(AU1550_GPIO3_INT, IRQ_TYPE_LEVEL_LOW); /* CARD0# */ 51562306a36Sopenharmony_ci irq_set_irq_type(AU1550_GPIO5_INT, IRQ_TYPE_LEVEL_LOW); /* CARD1# */ 51662306a36Sopenharmony_ci irq_set_irq_type(AU1550_GPIO21_INT, IRQ_TYPE_LEVEL_LOW); /* STSCHG0# */ 51762306a36Sopenharmony_ci irq_set_irq_type(AU1550_GPIO22_INT, IRQ_TYPE_LEVEL_LOW); /* STSCHG1# */ 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci db1x_register_pcmcia_socket( 52062306a36Sopenharmony_ci AU1000_PCMCIA_ATTR_PHYS_ADDR, 52162306a36Sopenharmony_ci AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1, 52262306a36Sopenharmony_ci AU1000_PCMCIA_MEM_PHYS_ADDR, 52362306a36Sopenharmony_ci AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1, 52462306a36Sopenharmony_ci AU1000_PCMCIA_IO_PHYS_ADDR, 52562306a36Sopenharmony_ci AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1, 52662306a36Sopenharmony_ci AU1550_GPIO3_INT, 0, 52762306a36Sopenharmony_ci /*AU1550_GPIO21_INT*/0, 0, 0); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci db1x_register_pcmcia_socket( 53062306a36Sopenharmony_ci AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000, 53162306a36Sopenharmony_ci AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1, 53262306a36Sopenharmony_ci AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004000000, 53362306a36Sopenharmony_ci AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004400000 - 1, 53462306a36Sopenharmony_ci AU1000_PCMCIA_IO_PHYS_ADDR + 0x004000000, 53562306a36Sopenharmony_ci AU1000_PCMCIA_IO_PHYS_ADDR + 0x004010000 - 1, 53662306a36Sopenharmony_ci AU1550_GPIO5_INT, 1, 53762306a36Sopenharmony_ci /*AU1550_GPIO22_INT*/0, 0, 1); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci platform_device_register(&db1550_nand_dev); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci alchemy_gpio_direction_output(202, 0); /* green led on */ 54262306a36Sopenharmony_ci} 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_cistatic void __init pb1550_devices(void) 54562306a36Sopenharmony_ci{ 54662306a36Sopenharmony_ci irq_set_irq_type(AU1550_GPIO0_INT, IRQ_TYPE_LEVEL_LOW); 54762306a36Sopenharmony_ci irq_set_irq_type(AU1550_GPIO1_INT, IRQ_TYPE_LEVEL_LOW); 54862306a36Sopenharmony_ci irq_set_irq_type(AU1550_GPIO201_205_INT, IRQ_TYPE_LEVEL_HIGH); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci /* enable both PCMCIA card irqs in the shared line */ 55162306a36Sopenharmony_ci alchemy_gpio2_enable_int(201); /* socket 0 card irq */ 55262306a36Sopenharmony_ci alchemy_gpio2_enable_int(202); /* socket 1 card irq */ 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci /* Pb1550, like all others, also has statuschange irqs; however they're 55562306a36Sopenharmony_ci * wired up on one of the Au1550's shared GPIO201_205 line, which also 55662306a36Sopenharmony_ci * services the PCMCIA card interrupts. So we ignore statuschange and 55762306a36Sopenharmony_ci * use the GPIO201_205 exclusively for card interrupts, since a) pcmcia 55862306a36Sopenharmony_ci * drivers are used to shared irqs and b) statuschange isn't really use- 55962306a36Sopenharmony_ci * ful anyway. 56062306a36Sopenharmony_ci */ 56162306a36Sopenharmony_ci db1x_register_pcmcia_socket( 56262306a36Sopenharmony_ci AU1000_PCMCIA_ATTR_PHYS_ADDR, 56362306a36Sopenharmony_ci AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1, 56462306a36Sopenharmony_ci AU1000_PCMCIA_MEM_PHYS_ADDR, 56562306a36Sopenharmony_ci AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1, 56662306a36Sopenharmony_ci AU1000_PCMCIA_IO_PHYS_ADDR, 56762306a36Sopenharmony_ci AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1, 56862306a36Sopenharmony_ci AU1550_GPIO201_205_INT, AU1550_GPIO0_INT, 0, 0, 0); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci db1x_register_pcmcia_socket( 57162306a36Sopenharmony_ci AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008000000, 57262306a36Sopenharmony_ci AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x008400000 - 1, 57362306a36Sopenharmony_ci AU1000_PCMCIA_MEM_PHYS_ADDR + 0x008000000, 57462306a36Sopenharmony_ci AU1000_PCMCIA_MEM_PHYS_ADDR + 0x008400000 - 1, 57562306a36Sopenharmony_ci AU1000_PCMCIA_IO_PHYS_ADDR + 0x008000000, 57662306a36Sopenharmony_ci AU1000_PCMCIA_IO_PHYS_ADDR + 0x008010000 - 1, 57762306a36Sopenharmony_ci AU1550_GPIO201_205_INT, AU1550_GPIO1_INT, 0, 0, 1); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci pb1550_nand_setup(); 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ciint __init db1550_dev_setup(void) 58362306a36Sopenharmony_ci{ 58462306a36Sopenharmony_ci int swapped, id; 58562306a36Sopenharmony_ci struct clk *c; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci id = (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) != BCSR_WHOAMI_DB1550); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci i2c_register_board_info(0, db1550_i2c_devs, 59062306a36Sopenharmony_ci ARRAY_SIZE(db1550_i2c_devs)); 59162306a36Sopenharmony_ci spi_register_board_info(db1550_spi_devs, 59262306a36Sopenharmony_ci ARRAY_SIZE(db1550_spi_devs)); 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci c = clk_get(NULL, "psc0_intclk"); 59562306a36Sopenharmony_ci if (!IS_ERR(c)) { 59662306a36Sopenharmony_ci clk_set_rate(c, 50000000); 59762306a36Sopenharmony_ci clk_prepare_enable(c); 59862306a36Sopenharmony_ci clk_put(c); 59962306a36Sopenharmony_ci } 60062306a36Sopenharmony_ci c = clk_get(NULL, "psc2_intclk"); 60162306a36Sopenharmony_ci if (!IS_ERR(c)) { 60262306a36Sopenharmony_ci clk_set_rate(c, db1550_spi_platdata.mainclk_hz); 60362306a36Sopenharmony_ci clk_prepare_enable(c); 60462306a36Sopenharmony_ci clk_put(c); 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci /* Audio PSC clock is supplied by codecs (PSC1, 3) FIXME: platdata!! */ 60862306a36Sopenharmony_ci __raw_writel(PSC_SEL_CLK_SERCLK, 60962306a36Sopenharmony_ci (void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET); 61062306a36Sopenharmony_ci wmb(); 61162306a36Sopenharmony_ci __raw_writel(PSC_SEL_CLK_SERCLK, 61262306a36Sopenharmony_ci (void __iomem *)KSEG1ADDR(AU1550_PSC3_PHYS_ADDR) + PSC_SEL_OFFSET); 61362306a36Sopenharmony_ci wmb(); 61462306a36Sopenharmony_ci /* SPI/I2C use internally supplied 50MHz source */ 61562306a36Sopenharmony_ci __raw_writel(PSC_SEL_CLK_INTCLK, 61662306a36Sopenharmony_ci (void __iomem *)KSEG1ADDR(AU1550_PSC0_PHYS_ADDR) + PSC_SEL_OFFSET); 61762306a36Sopenharmony_ci wmb(); 61862306a36Sopenharmony_ci __raw_writel(PSC_SEL_CLK_INTCLK, 61962306a36Sopenharmony_ci (void __iomem *)KSEG1ADDR(AU1550_PSC2_PHYS_ADDR) + PSC_SEL_OFFSET); 62062306a36Sopenharmony_ci wmb(); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci id ? pb1550_devices() : db1550_devices(); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci swapped = bcsr_read(BCSR_STATUS) & 62562306a36Sopenharmony_ci (id ? BCSR_STATUS_PB1550_SWAPBOOT : BCSR_STATUS_DB1000_SWAPBOOT); 62662306a36Sopenharmony_ci db1x_register_norflash(128 << 20, 4, swapped); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci return platform_add_devices(db1550_devs, ARRAY_SIZE(db1550_devs)); 62962306a36Sopenharmony_ci} 630