linux/arch/arm/mach-iop13xx/setup.c
Dan Williams 285f5fa7e9 [ARM] 3995/1: iop13xx: add iop13xx support
The iop348 processor integrates an Xscale (XSC3 512KB L2 Cache) core with a
Serial Attached SCSI (SAS) controller, multi-ported DDR2 memory
controller, 3 Application Direct Memory Access (DMA) controllers, a 133Mhz
PCI-X interface, a x8 PCI-Express interface, and other peripherals to form
a system-on-a-chip RAID subsystem engine.

The iop342 processor replaces the SAS controller with a second Xscale core
for dual core embedded applications.

The iop341 processor is the single core version of iop342.

This patch supports the two Intel customer reference platforms iq81340mc
for external storage and iq81340sc for direct attach (HBA) development.

The developer's manual is available here:
ftp://download.intel.com/design/iio/docs/31503701.pdf

Changelog:
* removed virtual addresses from resource definitions
* cleaned up some unnecessary #include's

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2006-12-07 17:20:21 +00:00

407 lines
9.7 KiB
C

/*
* iop13xx platform Initialization
* Copyright (c) 2005-2006, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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/serial_8250.h>
#ifdef CONFIG_MTD_PHYSMAP
#include <linux/mtd/physmap.h>
#endif
#include <asm/mach/map.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#define IOP13XX_UART_XTAL 33334000
#define IOP13XX_SETUP_DEBUG 0
#define PRINTK(x...) ((void)(IOP13XX_SETUP_DEBUG && printk(x)))
/* Standard IO mapping for all IOP13XX based systems
*/
static struct map_desc iop13xx_std_desc[] __initdata = {
{ /* mem mapped registers */
.virtual = IOP13XX_PMMR_VIRT_MEM_BASE,
.pfn = __phys_to_pfn(IOP13XX_PMMR_PHYS_MEM_BASE),
.length = IOP13XX_PMMR_SIZE,
.type = MT_DEVICE,
}, { /* PCIE IO space */
.virtual = IOP13XX_PCIE_LOWER_IO_VA,
.pfn = __phys_to_pfn(IOP13XX_PCIE_LOWER_IO_PA),
.length = IOP13XX_PCIX_IO_WINDOW_SIZE,
.type = MT_DEVICE,
}, { /* PCIX IO space */
.virtual = IOP13XX_PCIX_LOWER_IO_VA,
.pfn = __phys_to_pfn(IOP13XX_PCIX_LOWER_IO_PA),
.length = IOP13XX_PCIX_IO_WINDOW_SIZE,
.type = MT_DEVICE,
},
};
static struct resource iop13xx_uart0_resources[] = {
[0] = {
.start = IOP13XX_UART0_PHYS,
.end = IOP13XX_UART0_PHYS + 0x3f,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IOP13XX_UART0,
.end = IRQ_IOP13XX_UART0,
.flags = IORESOURCE_IRQ
}
};
static struct resource iop13xx_uart1_resources[] = {
[0] = {
.start = IOP13XX_UART1_PHYS,
.end = IOP13XX_UART1_PHYS + 0x3f,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IOP13XX_UART1,
.end = IRQ_IOP13XX_UART1,
.flags = IORESOURCE_IRQ
}
};
static struct plat_serial8250_port iop13xx_uart0_data[] = {
{
.membase = (char*)(IOP13XX_UART0_VIRT),
.mapbase = (IOP13XX_UART0_PHYS),
.irq = IRQ_IOP13XX_UART0,
.uartclk = IOP13XX_UART_XTAL,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_SKIP_TEST,
},
{ },
};
static struct plat_serial8250_port iop13xx_uart1_data[] = {
{
.membase = (char*)(IOP13XX_UART1_VIRT),
.mapbase = (IOP13XX_UART1_PHYS),
.irq = IRQ_IOP13XX_UART1,
.uartclk = IOP13XX_UART_XTAL,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_SKIP_TEST,
},
{ },
};
/* The ids are fixed up later in iop13xx_platform_init */
static struct platform_device iop13xx_uart0 = {
.name = "serial8250",
.id = 0,
.dev.platform_data = iop13xx_uart0_data,
.num_resources = 2,
.resource = iop13xx_uart0_resources,
};
static struct platform_device iop13xx_uart1 = {
.name = "serial8250",
.id = 0,
.dev.platform_data = iop13xx_uart1_data,
.num_resources = 2,
.resource = iop13xx_uart1_resources
};
static struct resource iop13xx_i2c_0_resources[] = {
[0] = {
.start = IOP13XX_I2C0_PHYS,
.end = IOP13XX_I2C0_PHYS + 0x18,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IOP13XX_I2C_0,
.end = IRQ_IOP13XX_I2C_0,
.flags = IORESOURCE_IRQ
}
};
static struct resource iop13xx_i2c_1_resources[] = {
[0] = {
.start = IOP13XX_I2C1_PHYS,
.end = IOP13XX_I2C1_PHYS + 0x18,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IOP13XX_I2C_1,
.end = IRQ_IOP13XX_I2C_1,
.flags = IORESOURCE_IRQ
}
};
static struct resource iop13xx_i2c_2_resources[] = {
[0] = {
.start = IOP13XX_I2C2_PHYS,
.end = IOP13XX_I2C2_PHYS + 0x18,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IOP13XX_I2C_2,
.end = IRQ_IOP13XX_I2C_2,
.flags = IORESOURCE_IRQ
}
};
/* I2C controllers. The IOP13XX uses the same block as the IOP3xx, so
* we just use the same device name.
*/
/* The ids are fixed up later in iop13xx_platform_init */
static struct platform_device iop13xx_i2c_0_controller = {
.name = "IOP3xx-I2C",
.id = 0,
.num_resources = 2,
.resource = iop13xx_i2c_0_resources
};
static struct platform_device iop13xx_i2c_1_controller = {
.name = "IOP3xx-I2C",
.id = 0,
.num_resources = 2,
.resource = iop13xx_i2c_1_resources
};
static struct platform_device iop13xx_i2c_2_controller = {
.name = "IOP3xx-I2C",
.id = 0,
.num_resources = 2,
.resource = iop13xx_i2c_2_resources
};
#ifdef CONFIG_MTD_PHYSMAP
/* PBI Flash Device
*/
static struct physmap_flash_data iq8134x_flash_data = {
.width = 2,
};
static struct resource iq8134x_flash_resource = {
.start = IQ81340_FLASHBASE,
.end = 0,
.flags = IORESOURCE_MEM,
};
static struct platform_device iq8134x_flash = {
.name = "physmap-flash",
.id = 0,
.dev = { .platform_data = &iq8134x_flash_data, },
.num_resources = 1,
.resource = &iq8134x_flash_resource,
};
static unsigned long iq8134x_probe_flash_size(void)
{
uint8_t __iomem *flash_addr = ioremap(IQ81340_FLASHBASE, PAGE_SIZE);
int i;
char query[3];
unsigned long size = 0;
int width = iq8134x_flash_data.width;
if (flash_addr) {
/* send CFI 'query' command */
writew(0x98, flash_addr);
/* check for CFI compliance */
for (i = 0; i < 3 * width; i += width)
query[i / width] = readb(flash_addr + (0x10 * width) + i);
/* read the size */
if (memcmp(query, "QRY", 3) == 0)
size = 1 << readb(flash_addr + (0x27 * width));
/* send CFI 'read array' command */
writew(0xff, flash_addr);
iounmap(flash_addr);
}
return size;
}
#endif
void __init iop13xx_map_io(void)
{
/* Initialize the Static Page Table maps */
iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc));
}
static int init_uart = 0;
static int init_i2c = 0;
void __init iop13xx_platform_init(void)
{
int i;
u32 uart_idx, i2c_idx, plat_idx;
struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES];
/* set the bases so we can read the device id */
iop13xx_set_atu_mmr_bases();
memset(iop13xx_devices, 0, sizeof(iop13xx_devices));
if (init_uart == IOP13XX_INIT_UART_DEFAULT) {
switch (iop13xx_dev_id()) {
/* enable both uarts on iop341 and iop342 */
case 0x3380:
case 0x3384:
case 0x3388:
case 0x338c:
case 0x3382:
case 0x3386:
case 0x338a:
case 0x338e:
init_uart |= IOP13XX_INIT_UART_0;
init_uart |= IOP13XX_INIT_UART_1;
break;
/* only enable uart 1 */
default:
init_uart |= IOP13XX_INIT_UART_1;
}
}
if (init_i2c == IOP13XX_INIT_I2C_DEFAULT) {
switch (iop13xx_dev_id()) {
/* enable all i2c units on iop341 and iop342 */
case 0x3380:
case 0x3384:
case 0x3388:
case 0x338c:
case 0x3382:
case 0x3386:
case 0x338a:
case 0x338e:
init_i2c |= IOP13XX_INIT_I2C_0;
init_i2c |= IOP13XX_INIT_I2C_1;
init_i2c |= IOP13XX_INIT_I2C_2;
break;
/* only enable i2c 1 and 2 */
default:
init_i2c |= IOP13XX_INIT_I2C_1;
init_i2c |= IOP13XX_INIT_I2C_2;
}
}
plat_idx = 0;
uart_idx = 0;
i2c_idx = 0;
/* uart 1 (if enabled) is ttyS0 */
if (init_uart & IOP13XX_INIT_UART_1) {
PRINTK("Adding uart1 to platform device list\n");
iop13xx_uart1.id = uart_idx++;
iop13xx_devices[plat_idx++] = &iop13xx_uart1;
}
if (init_uart & IOP13XX_INIT_UART_0) {
PRINTK("Adding uart0 to platform device list\n");
iop13xx_uart0.id = uart_idx++;
iop13xx_devices[plat_idx++] = &iop13xx_uart0;
}
for(i = 0; i < IQ81340_NUM_I2C; i++) {
if ((init_i2c & (1 << i)) && IOP13XX_SETUP_DEBUG)
printk("Adding i2c%d to platform device list\n", i);
switch(init_i2c & (1 << i)) {
case IOP13XX_INIT_I2C_0:
iop13xx_i2c_0_controller.id = i2c_idx++;
iop13xx_devices[plat_idx++] =
&iop13xx_i2c_0_controller;
break;
case IOP13XX_INIT_I2C_1:
iop13xx_i2c_1_controller.id = i2c_idx++;
iop13xx_devices[plat_idx++] =
&iop13xx_i2c_1_controller;
break;
case IOP13XX_INIT_I2C_2:
iop13xx_i2c_2_controller.id = i2c_idx++;
iop13xx_devices[plat_idx++] =
&iop13xx_i2c_2_controller;
break;
}
}
#ifdef CONFIG_MTD_PHYSMAP
iq8134x_flash_resource.end = iq8134x_flash_resource.start +
iq8134x_probe_flash_size();
if (iq8134x_flash_resource.end > iq8134x_flash_resource.start)
iop13xx_devices[plat_idx++] = &iq8134x_flash;
else
printk(KERN_ERR "%s: Failed to probe flash size\n", __FUNCTION__);
#endif
platform_add_devices(iop13xx_devices, plat_idx);
}
static int __init iop13xx_init_uart_setup(char *str)
{
if (str) {
while (*str != '\0') {
switch(*str) {
case '0':
init_uart |= IOP13XX_INIT_UART_0;
break;
case '1':
init_uart |= IOP13XX_INIT_UART_1;
break;
case ',':
case '=':
break;
default:
PRINTK("\"iop13xx_init_uart\" malformed"
" at character: \'%c\'", *str);
*(str + 1) = '\0';
init_uart = IOP13XX_INIT_UART_DEFAULT;
}
str++;
}
}
return 1;
}
static int __init iop13xx_init_i2c_setup(char *str)
{
if (str) {
while (*str != '\0') {
switch(*str) {
case '0':
init_i2c |= IOP13XX_INIT_I2C_0;
break;
case '1':
init_i2c |= IOP13XX_INIT_I2C_1;
break;
case '2':
init_i2c |= IOP13XX_INIT_I2C_2;
break;
case ',':
case '=':
break;
default:
PRINTK("\"iop13xx_init_i2c\" malformed"
" at character: \'%c\'", *str);
*(str + 1) = '\0';
init_i2c = IOP13XX_INIT_I2C_DEFAULT;
}
str++;
}
}
return 1;
}
__setup("iop13xx_init_uart", iop13xx_init_uart_setup);
__setup("iop13xx_init_i2c", iop13xx_init_i2c_setup);