blob: 8fad46a76d1bb27565addc839818bf84dac2793e [file] [log] [blame]
/*
* arch/arm/mach-comcerto/board-c2krtsm.c
*
* Copyright (C) 2012 Mindspeed Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/serial_8250.h>
#include <linux/phy.h>
#include <linux/mtd/mtd.h>
#if defined(CONFIG_MTD_NAND_COMCERTO) || defined(CONFIG_MTD_NAND_COMCERTO_MODULE)
#include <linux/mtd/nand.h>
#endif
#include <linux/mtd/partitions.h>
#if defined(CONFIG_SPI_MSPD_LOW_SPEED) || defined(CONFIG_SPI_MSPD_HIGH_SPEED)
#include <linux/spi/spi.h>
#endif
#include <asm/sizes.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/io.h>
#include <asm/mach/flash.h>
#include <asm/mach/arch.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/dma.h>
#include <linux/dw_dmac.h>
#include <linux/clockchips.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <asm/smp_twd.h>
#include <asm/localtimer.h>
#include <asm/hardware/gic.h>
#include <asm/mach/time.h>
extern void platform_reserve(void);
extern void device_map_io (void);
extern void device_irq_init(void);
extern void device_init(void);
extern struct sys_timer comcerto_timer;
static void __init board_gpio_init(void)
{
#ifdef CONFIG_COMCERTO_PFE_UART_SUPPORT
writel((readl(COMCERTO_GPIO_PIN_SELECT_REG) & ~PFE_UART_GPIO) | PFE_UART_BUS, COMCERTO_GPIO_PIN_SELECT_REG);
#endif
#if defined(CONFIG_SPI_MSPD_LOW_SPEED) || defined(CONFIG_SPI2_MSPD_LOW_SPEED)
/* enable SPI pins */
writel((readl(COMCERTO_GPIO_PIN_SELECT_REG1) & ~(SPI_MUX_GPIO_1)) | (SPI_MUX_BUS_1), COMCERTO_GPIO_PIN_SELECT_REG1);
writel((readl(COMCERTO_GPIO_63_32_PIN_SELECT) & ~(SPI_MUX_GPIO_2)) | (SPI_MUX_BUS_2), COMCERTO_GPIO_63_32_PIN_SELECT);
#endif
#if defined(CONFIG_SPI_MSPD_HIGH_SPEED)
/* enable SPI pins */
writel((readl(COMCERTO_GPIO_PIN_SELECT_REG1) & ~(SPI_2_MUX_GPIO_1)) | (SPI_2_MUX_BUS_1), COMCERTO_GPIO_PIN_SELECT_REG1);
writel((readl(COMCERTO_GPIO_63_32_PIN_SELECT) & ~(SPI_2_MUX_GPIO_2)) | (SPI_2_MUX_BUS_2), COMCERTO_GPIO_63_32_PIN_SELECT);
#endif
#if defined(CONFIG_COMCERTO_I2C_SUPPORT)
writel((readl(COMCERTO_GPIO_PIN_SELECT_REG1) & ~I2C_GPIO) | I2C_BUS, COMCERTO_GPIO_PIN_SELECT_REG1);
#endif
#if defined(CONFIG_MTD_NAND_COMCERTO) || defined(CONFIG_MTD_NAND_COMCERTO_MODULE)
writel((readl(COMCERTO_GPIO_PIN_SELECT_REG1) & ~NAND_GPIO) | NAND_BUS, COMCERTO_GPIO_PIN_SELECT_REG1);
#endif
#if defined(CONFIG_MTD_COMCERTO_NOR)
writel((readl(COMCERTO_GPIO_PIN_SELECT_REG1) & ~NOR_GPIO) | NOR_BUS, COMCERTO_GPIO_PIN_SELECT_REG1);
#endif
}
/* --------------------------------------------------------------------
* NOR device
* -------------------------------------------------------------------- */
#if defined(CONFIG_MTD_COMCERTO_NOR)
static struct resource comcerto_nor_resources[] = {
{
.start = NORFLASH_MEMORY_PHY1,
.end = NORFLASH_MEMORY_PHY1 + SZ_64M - 1,
.flags = IORESOURCE_MEM,
},
};
static struct flash_platform_data comcerto_nor_data = {
.map_name = "cfi_probe",
.width = 2,
};
static struct platform_device comcerto_nor = {
.name = "comcertoflash",
.id = 0,
.num_resources = ARRAY_SIZE(comcerto_nor_resources),
.resource = comcerto_nor_resources,
.dev = {
.platform_data = &comcerto_nor_data,
},
};
#endif
/* --------------------------------------------------------------------
* DMAC controller
* -------------------------------------------------------------------- */
#if defined(CONFIG_COMCERTO_DW_DMA_SUPPORT)
static struct resource dw_dmac_resource[] = {
{
.start = DW_DMA_DMAC_BASEADDR,
.end = DW_DMA_DMAC_BASEADDR + 0x2C0,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_DMAC,
.flags = IORESOURCE_IRQ,
}
};
static struct dw_dma_platform_data dw_dmac_data = {
.nr_channels = 8,
};
static u64 dw_dmac_dma_mask = DMA_BIT_MASK(32);
static struct platform_device dw_dmac_device = {
.name = "dw_dmac",
.id = 0,
.dev = {
.dma_mask = &dw_dmac_dma_mask,
.platform_data = &dw_dmac_data,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
.resource = dw_dmac_resource,
.num_resources = ARRAY_SIZE(dw_dmac_resource),
};
#endif
/* --------------------------------------------------------------------
* SPI bus controller [FIXME]
* -------------------------------------------------------------------- */
#if defined(CONFIG_SPI_MSPD_LOW_SPEED) || defined(CONFIG_SPI_MSPD_HIGH_SPEED)
struct spi_controller_pdata {
int use_dma;
int num_chipselects;
int bus_num;
u32 max_freq;
};
struct spi_platform_data {
int type;
int dummy;
};
struct spi_platform_data spi_pdata = {
.type = 0,
.dummy = 0,
};
static struct spi_board_info comcerto_spi_board_info[] = {
{
/* FIXME: for chipselect-0 */
.modalias = "comcerto_spi1",
.chip_select = 0,
.max_speed_hz = 4*1000*1000,
.bus_num = 0,
.irq = -1,
.mode = SPI_MODE_3,
.platform_data = &spi_pdata,
},
{
/* FIXME: for chipselect-1 */
.modalias = "comcerto_spi2",
.chip_select = 1,
.max_speed_hz = 4*1000*1000,
.bus_num = 0,
.irq = -1,
.mode = SPI_MODE_3,
.platform_data = &spi_pdata,
},
{
.modalias = "comcerto_spi3",
.chip_select = 2,
.max_speed_hz = 4*1000*1000,
.bus_num = 0,
.irq = -1,
.mode = SPI_MODE_3,
.platform_data = &spi_pdata,
},
{
.modalias = "legerity",
.chip_select = 3,
.max_speed_hz = 4*1000*1000,
.bus_num = 0,
.irq = -1,
.mode = SPI_MODE_3,
.platform_data = &spi_pdata,
},
};
#endif
#if defined(CONFIG_SPI_MSPD_HIGH_SPEED)
struct spi_controller_pdata fast_spi_pdata = {
.use_dma = 1,
.num_chipselects = 2,
.bus_num = 1,
.max_freq = 60 * 1000 * 1000,
};
#if defined(CONFIG_SPI_MSPD_HIGH_SPEED) || defined(CONFIG_SPI2_MSPD_HIGH_SPEED)
static struct resource comcerto_fast_spi_resource[] = {
{
.start = COMCERTO_AXI_SPI_BASE,
.end = COMCERTO_AXI_SPI_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_SPI,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device comcerto_fast_spi = {
.name = "comcerto_spi",
.id = 1,
.num_resources = ARRAY_SIZE(comcerto_fast_spi_resource),
.resource = comcerto_fast_spi_resource,
#if defined(CONFIG_SPI_MSPD_HIGH_SPEED)
.dev = {
.platform_data = &fast_spi_pdata,
},
#endif
};
#endif
#if defined(CONFIG_SPI_MSPD_LOW_SPEED)
struct spi_controller_pdata ls_spi_pdata = {
.use_dma = 0,
.num_chipselects = 4,
.bus_num = 0,
.max_freq = 20 * 1000 * 1000,
};
#endif
#if defined(CONFIG_SPI_MSPD_LOW_SPEED) || defined(CONFIG_SPI2_MSPD_LOW_SPEED)
static struct resource comcerto_spi_resource[] = {
{
.start = COMCERTO_APB_SPI_BASE,
.end = COMCERTO_APB_SPI_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_SPI_LS,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device comcerto_spi = {
.name = "comcerto_spi",
.id = 0,
.num_resources = ARRAY_SIZE(comcerto_spi_resource),
.resource = comcerto_spi_resource,
#if defined(CONFIG_SPI_MSPD_LOW_SPEED)
.dev = {
.platform_data = &ls_spi_pdata,
},
#endif
};
#endif
/* --------------------------------------------------------------------
* I2C bus controller
* -------------------------------------------------------------------- */
#if defined(CONFIG_COMCERTO_I2C_SUPPORT)
static struct resource comcerto_i2c_resources[] = {
{
.start = COMCERTO_APB_I2C_BASE,
.end = COMCERTO_APB_I2C_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_I2C,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device comcerto_i2c = {
.name = "comcerto_i2c",
.id = -1,
.num_resources = ARRAY_SIZE(comcerto_i2c_resources),
.resource = comcerto_i2c_resources,
};
#endif
static struct comcerto_tdm_data comcerto_tdm_pdata = {
.fsoutput = 1, /* Generic Pad Control and Version ID Register[2] */
.fspolarity = 0, /* 28 FSYNC_FALL(RISE)_EDGE */
.fshwidth = 1, /* High_Phase_Width[10:0] */
.fslwidth = 0xFF, /* Low_Phase_Width[10:0] */
.clockhz = 2048000, /* INC_VALUE[29:0] According to the desired TDM clock output frequency, this field should be configured */
.clockout = 1, /* 0 -> set bit 21, clear bit 20 in COMCERTO_GPIO_IOCTRL_REG
(software control, clock input)
1 -> set bit 21 and 20 in COMCERTO_GPIO_IOCTRL_REG
(software control, clock output)
2 -> clear bit 21 in COMCERTO_GPIO_IOCTRL_REG (hardware control) */
.tdmmux = 0x1, /* TDM interface Muxing:0x0 - TDM block, 0x1 - ZDS block,
0x2 - GPIO[63:60] signals and 0x3 - MSIF block is selected */
#if 0
/* FIX ME - Need correct values for TDM_DR, TDM_DX, TDM_FS and TDM_CK */
.tdmck = 0x3F,
.tdmfs = 0x3F,
.tdmdx = 0x3F,
.tdmdr = 0x3F,
#endif
};
static struct platform_device comcerto_tdm_device = {
.name = "comcerto-tdm",
.id = 0,
.dev.platform_data = &comcerto_tdm_pdata,
.num_resources = 0,
.resource = NULL,
};
static struct resource comcerto_pfe_resources[] = {
{
.name = "apb",
.start = COMCERTO_APB_PFE_BASE,
.end = COMCERTO_APB_PFE_BASE + COMCERTO_APB_PFE_SIZE - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "axi",
.start = COMCERTO_AXI_PFE_BASE,
.end = COMCERTO_AXI_PFE_BASE + COMCERTO_AXI_PFE_SIZE - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "ddr",
.start = COMCERTO_PFE_DDR_BASE,
.end = COMCERTO_PFE_DDR_BASE + COMCERTO_PFE_DDR_SIZE - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "iram",
.start = COMCERTO_PFE_IRAM_BASE,
.end = COMCERTO_PFE_IRAM_BASE + COMCERTO_PFE_IRAM_SIZE - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "hif",
.start = IRQ_PFE_HIF,
.flags = IORESOURCE_IRQ,
},
};
static struct comcerto_pfe_platform_data comcerto_pfe_pdata = {
.comcerto_eth_pdata[0] = {
.name = GEM0_ITF_NAME,
.device_flags = CONFIG_COMCERTO_GEMAC,
.mii_config = CONFIG_COMCERTO_USE_RGMII,
.gemac_mode = GEMAC_SW_CONF | GEMAC_SW_FULL_DUPLEX | GEMAC_SW_SPEED_1G,
.phy_flags = GEMAC_PHY_RGMII_ADD_DELAY,
.bus_id = 0,
.phy_id = 0,
.gem_id = 0,
.mac_addr = (u8[])GEM0_MAC,
},
.comcerto_eth_pdata[1] = {
.name = GEM1_ITF_NAME,
.device_flags = CONFIG_COMCERTO_GEMAC,
.mii_config = CONFIG_COMCERTO_USE_RGMII,
.gemac_mode = GEMAC_SW_CONF | GEMAC_SW_FULL_DUPLEX | GEMAC_SW_SPEED_1G,
.phy_flags = GEMAC_NO_PHY,
.gem_id = 1,
.mac_addr = (u8[])GEM1_MAC,
},
.comcerto_eth_pdata[2] = {
.name = GEM2_ITF_NAME,
.device_flags = CONFIG_COMCERTO_GEMAC,
.mii_config = CONFIG_COMCERTO_USE_RGMII,
.gemac_mode = GEMAC_SW_CONF | GEMAC_SW_FULL_DUPLEX | GEMAC_SW_SPEED_1G,
.phy_flags = GEMAC_NO_PHY,
.gem_id = 2,
.mac_addr = (u8[])GEM2_MAC,
},
/**
* There is a single mdio bus coming out of C2K. And that's the one
* connected to GEM0. All PHY's, switchs will be connected to the same
* bus using different addresses. Typically .bus_id is always 0, only
* .phy_id will change in the different comcerto_eth_pdata[] structures above.
*/
.comcerto_mdio_pdata[0] = {
.enabled = 1,
.phy_mask = 0xFFFFFFFE,
.mdc_div = 96,
.irq = {
[0] = PHY_POLL,
},
},
};
static u64 comcerto_pfe_dma_mask = DMA_BIT_MASK(32);
static struct platform_device comcerto_pfe_device = {
.name = "pfe",
.id = 0,
.dev = {
.platform_data = &comcerto_pfe_pdata,
.dma_mask = &comcerto_pfe_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
.num_resources = ARRAY_SIZE(comcerto_pfe_resources),
.resource = comcerto_pfe_resources,
};
static struct platform_device *comcerto_devices[] __initdata = {
#if defined(CONFIG_MTD_COMCERTO_NOR)
&comcerto_nor,
#endif
#if defined(CONFIG_COMCERTO_I2C_SUPPORT)
&comcerto_i2c,
#endif
#if defined(CONFIG_SPI_MSPD_HIGH_SPEED)
&comcerto_fast_spi,
#endif
#if defined(CONFIG_SPI_MSPD_LOW_SPEED) || defined(CONFIG_SPI2_MSPD_LOW_SPEED)
&comcerto_spi,
#endif
#if defined(CONFIG_COMCERTO_DW_DMA_SUPPORT)
&dw_dmac_device,
#endif
&comcerto_tdm_device,
&comcerto_pfe_device,
};
/************************************************************************
* Expansion bus
*
************************************************************************/
/* This variable is used by comcerto-1000.c to initialize the expansion bus */
int comcerto_exp_values[5][7]= {
/* ENABLE, BASE, SEG_SZ, CFG, TMG1, TMG2, TMG3 */
{1, (EXP_BUS_REG_BASE_CS0 >> 12), ((EXP_BUS_REG_BASE_CS0 + EXP_CS0_SEG_SIZE - 1) >> 12), EXP_MEM_BUS_SIZE_16, 0x1A1A401F, 0x06060A04, 0x00000002}, /*TODO Values to check*/
{0, (EXP_BUS_REG_BASE_CS1 >> 12), ((EXP_BUS_REG_BASE_CS1 + EXP_CS1_SEG_SIZE - 1) >> 12), EXP_RDY_EN|EXP_MEM_BUS_SIZE_32, 0x1A1A401F, 0x06060A04, 0x00000002}, /*TODO Values to check*/
{0, (EXP_BUS_REG_BASE_CS2 >> 12), ((EXP_BUS_REG_BASE_CS2 + EXP_CS2_SEG_SIZE - 1) >> 12), EXP_STRB_MODE|EXP_ALE_MODE|EXP_MEM_BUS_SIZE_8, 0x1A10201A, 0x03080403, 0x0000002}, /*TODO Values to check*/
{0, (EXP_BUS_REG_BASE_CS3 >> 12), ((EXP_BUS_REG_BASE_CS3 + EXP_CS3_SEG_SIZE - 1) >> 12), EXP_STRB_MODE|EXP_ALE_MODE|EXP_MEM_BUS_SIZE_8, 0x1A10201A, 0x03080403, 0x0000002}, /*BT8370*/
{0, (EXP_BUS_REG_BASE_CS4 >> 12), ((EXP_BUS_REG_BASE_CS4 + EXP_CS4_SEG_SIZE - 1) >> 12), EXP_NAND_MODE|EXP_MEM_BUS_SIZE_8, 0x1A1A401F, 0x06060A04, 0x00000002}, /* NAND: TODO Values to check */
};
/************************************************************************
* Machine definition
*
************************************************************************/
static void __init platform_map_io(void)
{
device_map_io();
}
static void __init platform_irq_init(void)
{
device_irq_init();
}
static void __init platform_init(void)
{
device_init();
board_gpio_init();
#if defined(CONFIG_SPI_MSPD_LOW_SPEED) || defined(CONFIG_SPI_MSPD_HIGH_SPEED)
spi_register_board_info(comcerto_spi_board_info, ARRAY_SIZE(comcerto_spi_board_info));
#endif
platform_add_devices(comcerto_devices, ARRAY_SIZE(comcerto_devices));
}
MACHINE_START(COMCERTO, "Comcerto 2000 RTSM")
/* Mindspeed Technologies Inc. */
.atag_offset = COMCERTO_AXI_DDR_BASE + 0x100,
.reserve = platform_reserve,
.map_io = platform_map_io,
.init_irq = platform_irq_init,
.init_machine = platform_init,
.timer = &comcerto_timer,
MACHINE_END