diff options
Diffstat (limited to 'arch')
460 files changed, 16456 insertions, 13689 deletions
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile index 21cf624d732..ea098f3b629 100644 --- a/arch/alpha/lib/Makefile +++ b/arch/alpha/lib/Makefile @@ -36,7 +36,6 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \ $(ev6-y)csum_ipv6_magic.o \ $(ev6-y)clear_page.o \ $(ev6-y)copy_page.o \ - strcasecmp.o \ fpreg.o \ callback_srm.o srm_puts.o srm_printk.o diff --git a/arch/alpha/lib/strcasecmp.c b/arch/alpha/lib/strcasecmp.c deleted file mode 100644 index 4e57a216fea..00000000000 --- a/arch/alpha/lib/strcasecmp.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * linux/arch/alpha/lib/strcasecmp.c - */ - -#include <linux/string.h> - - -/* We handle nothing here except the C locale. Since this is used in - only one place, on strings known to contain only 7 bit ASCII, this - is ok. */ - -int strcasecmp(const char *a, const char *b) -{ - int ca, cb; - - do { - ca = *a++ & 0xff; - cb = *b++ & 0xff; - if (ca >= 'A' && ca <= 'Z') - ca += 'a' - 'A'; - if (cb >= 'A' && cb <= 'Z') - cb += 'a' - 'A'; - } while (ca == cb && ca != '\0'); - - return ca - cb; -} diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c index a9bc5b52218..5972df2b9af 100644 --- a/arch/arm/common/sharpsl_pm.c +++ b/arch/arm/common/sharpsl_pm.c @@ -766,10 +766,10 @@ static void sharpsl_apm_get_power_status(struct apm_power_info *info) } static struct pm_ops sharpsl_pm_ops = { - .pm_disk_mode = PM_DISK_FIRMWARE, .prepare = pxa_pm_prepare, .enter = corgi_pxa_pm_enter, .finish = pxa_pm_finish, + .valid = pm_valid_only_mem, }; static int __init sharpsl_pm_probe(struct platform_device *pdev) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index b49bfda53d7..ff8db29e989 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -201,7 +201,6 @@ error: static struct pm_ops at91_pm_ops ={ - .pm_disk_mode = 0, .valid = at91_pm_valid_state, .prepare = at91_pm_prepare, .enter = at91_pm_enter, diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index 49efe903dac..0383ab33427 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -698,10 +698,10 @@ static struct irqaction omap_wakeup_irq = { static struct pm_ops omap_pm_ops ={ - .pm_disk_mode = 0, .prepare = omap_pm_prepare, .enter = omap_pm_enter, .finish = omap_pm_finish, + .valid = pm_valid_only_mem, }; static int __init omap_pm_init(void) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index d7eee99b7e3..6f4a5436d0c 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -370,10 +370,10 @@ static int omap2_pm_finish(suspend_state_t state) } static struct pm_ops omap_pm_ops = { - .pm_disk_mode = 0, .prepare = omap2_pm_prepare, .enter = omap2_pm_enter, .finish = omap2_pm_finish, + .valid = pm_valid_only_mem, }; int __init omap2_pm_init(void) diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c index 3649cd3dfc9..2a137f33f75 100644 --- a/arch/arm/mach-pnx4008/pm.c +++ b/arch/arm/mach-pnx4008/pm.c @@ -107,50 +107,19 @@ static int pnx4008_pm_enter(suspend_state_t state) case PM_SUSPEND_MEM: pnx4008_suspend(); break; - case PM_SUSPEND_DISK: - return -ENOTSUPP; - default: - return -EINVAL; } return 0; } -/* - * Called after processes are frozen, but before we shut down devices. - */ -static int pnx4008_pm_prepare(suspend_state_t state) -{ - switch (state) { - case PM_SUSPEND_STANDBY: - case PM_SUSPEND_MEM: - break; - - case PM_SUSPEND_DISK: - return -ENOTSUPP; - break; - - default: - return -EINVAL; - break; - } - return 0; -} - -/* - * Called after devices are re-setup, but before processes are thawed. - */ -static int pnx4008_pm_finish(suspend_state_t state) +static int pnx4008_pm_valid(suspend_state_t state) { - return 0; + return (state == PM_SUSPEND_STANDBY) || + (state == PM_SUSPEND_MEM); } -/* - * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. - */ static struct pm_ops pnx4008_pm_ops = { - .prepare = pnx4008_pm_prepare, .enter = pnx4008_pm_enter, - .finish = pnx4008_pm_finish, + .valid = pnx4008_pm_valid, }; static int __init pnx4008_pm_init(void) diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index b4d8276d605..6bf15ae7384 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -223,14 +223,11 @@ int pxa_pm_finish(suspend_state_t state) EXPORT_SYMBOL_GPL(pxa_pm_finish); -/* - * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. - */ static struct pm_ops pxa_pm_ops = { - .pm_disk_mode = PM_DISK_FIRMWARE, .prepare = pxa_pm_prepare, .enter = pxa_pm_enter, .finish = pxa_pm_finish, + .valid = pm_valid_only_mem, }; static int __init pxa_pm_init(void) diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index 786c8534231..d674cf34315 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -59,9 +59,6 @@ static int sa11x0_pm_enter(suspend_state_t state) unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE]; struct timespec delta, rtc; - if (state != PM_SUSPEND_MEM) - return -EINVAL; - /* preserve current time */ rtc.tv_sec = RCNR; rtc.tv_nsec = 0; @@ -134,12 +131,9 @@ unsigned long sleep_phys_sp(void *sp) return virt_to_phys(sp); } -/* - * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. - */ static struct pm_ops sa11x0_pm_ops = { - .pm_disk_mode = PM_DISK_FIRMWARE, .enter = sa11x0_pm_enter, + .valid = pm_valid_only_mem, }; static int __init sa11x0_pm_init(void) diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c index ecf68d61190..c6b03f8ab26 100644 --- a/arch/arm/plat-s3c24xx/pm.c +++ b/arch/arm/plat-s3c24xx/pm.c @@ -511,11 +511,6 @@ static int s3c2410_pm_enter(suspend_state_t state) return -EINVAL; } - if (state != PM_SUSPEND_MEM) { - printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n"); - return -EINVAL; - } - /* check if we have anything to wake-up with... bad things seem * to happen if you suspend with no wakeup (system will often * require a full power-cycle) @@ -617,30 +612,9 @@ static int s3c2410_pm_enter(suspend_state_t state) return 0; } -/* - * Called after processes are frozen, but before we shut down devices. - */ -static int s3c2410_pm_prepare(suspend_state_t state) -{ - return 0; -} - -/* - * Called after devices are re-setup, but before processes are thawed. - */ -static int s3c2410_pm_finish(suspend_state_t state) -{ - return 0; -} - -/* - * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. - */ static struct pm_ops s3c2410_pm_ops = { - .pm_disk_mode = PM_DISK_FIRMWARE, - .prepare = s3c2410_pm_prepare, .enter = s3c2410_pm_enter, - .finish = s3c2410_pm_finish, + .valid = pm_valid_only_mem, }; /* s3c2410_pm_init diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index ce4013aee59..3ec76586877 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -57,9 +57,6 @@ config ARCH_HAS_ILOG2_U64 bool default n -config GENERIC_BUST_SPINLOCK - bool - config GENERIC_HWEIGHT bool default y @@ -68,6 +65,11 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_BUG + bool + default y + depends on BUG + source "init/Kconfig" menu "System Type and features" @@ -106,6 +108,9 @@ choice config BOARD_ATSTK1000 bool "ATSTK1000 evaluation board" select BOARD_ATSTK1002 if CPU_AT32AP7000 + +config BOARD_ATNGW100 + bool "ATNGW100 Network Gateway" endchoice choice @@ -116,6 +121,8 @@ config LOADER_U_BOOT bool "U-Boot (or similar) bootloader" endchoice +source "arch/avr32/mach-at32ap/Kconfig" + config LOAD_ADDRESS hex default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile index 7b842e98efe..6115fc1f0cf 100644 --- a/arch/avr32/Makefile +++ b/arch/avr32/Makefile @@ -27,6 +27,7 @@ head-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/head.o head-y += arch/avr32/kernel/head.o core-$(CONFIG_PLATFORM_AT32AP) += arch/avr32/mach-at32ap/ core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/ +core-$(CONFIG_BOARD_ATNGW100) += arch/avr32/boards/atngw100/ core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/ core-y += arch/avr32/kernel/ core-y += arch/avr32/mm/ diff --git a/arch/avr32/boards/atngw100/Makefile b/arch/avr32/boards/atngw100/Makefile new file mode 100644 index 00000000000..c740aa11675 --- /dev/null +++ b/arch/avr32/boards/atngw100/Makefile @@ -0,0 +1 @@ +obj-y += setup.o flash.o diff --git a/arch/avr32/boards/atngw100/flash.c b/arch/avr32/boards/atngw100/flash.c new file mode 100644 index 00000000000..f9b32a8eab9 --- /dev/null +++ b/arch/avr32/boards/atngw100/flash.c @@ -0,0 +1,95 @@ +/* + * ATNGW100 board-specific flash initialization + * + * Copyright (C) 2005-2006 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/mtd/physmap.h> + +#include <asm/arch/smc.h> + +static struct smc_config flash_config __initdata = { + .ncs_read_setup = 0, + .nrd_setup = 40, + .ncs_write_setup = 0, + .nwe_setup = 10, + + .ncs_read_pulse = 80, + .nrd_pulse = 40, + .ncs_write_pulse = 65, + .nwe_pulse = 55, + + .read_cycle = 120, + .write_cycle = 120, + + .bus_width = 2, + .nrd_controlled = 1, + .nwe_controlled = 1, + .byte_write = 1, +}; + +static struct mtd_partition flash_parts[] = { + { + .name = "u-boot", + .offset = 0x00000000, + .size = 0x00020000, /* 128 KiB */ + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "root", + .offset = 0x00020000, + .size = 0x007d0000, + }, + { + .name = "env", + .offset = 0x007f0000, + .size = 0x00010000, + .mask_flags = MTD_WRITEABLE, + }, +}; + +static struct physmap_flash_data flash_data = { + .width = 2, + .nr_parts = ARRAY_SIZE(flash_parts), + .parts = flash_parts, +}; + +static struct resource flash_resource = { + .start = 0x00000000, + .end = 0x007fffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device flash_device = { + .name = "physmap-flash", + .id = 0, + .resource = &flash_resource, + .num_resources = 1, + .dev = { + .platform_data = &flash_data, + }, +}; + +/* This needs to be called after the SMC has been initialized */ +static int __init atngw100_flash_init(void) +{ + int ret; + + ret = smc_set_configuration(0, &flash_config); + if (ret < 0) { + printk(KERN_ERR "atngw100: failed to set NOR flash timing\n"); + return ret; + } + + platform_device_register(&flash_device); + + return 0; +} +device_initcall(atngw100_flash_init); diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c new file mode 100644 index 00000000000..9bc37d4f668 --- /dev/null +++ b/arch/avr32/boards/atngw100/setup.c @@ -0,0 +1,124 @@ +/* + * Board-specific setup code for the ATNGW100 Network Gateway + * + * Copyright (C) 2005-2006 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/clk.h> +#include <linux/etherdevice.h> +#include <linux/init.h> +#include <linux/linkage.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/spi/spi.h> + +#include <asm/io.h> +#include <asm/setup.h> + +#include <asm/arch/at32ap7000.h> +#include <asm/arch/board.h> +#include <asm/arch/init.h> + +/* Initialized by bootloader-specific startup code. */ +struct tag *bootloader_tags __initdata; + +struct eth_addr { + u8 addr[6]; +}; +static struct eth_addr __initdata hw_addr[2]; +static struct eth_platform_data __initdata eth_data[2]; + +static struct spi_board_info spi0_board_info[] __initdata = { + { + .modalias = "mtd_dataflash", + .max_speed_hz = 10000000, + .chip_select = 0, + }, +}; + +/* + * The next two functions should go away as the boot loader is + * supposed to initialize the macb address registers with a valid + * ethernet address. But we need to keep it around for a while until + * we can be reasonably sure the boot loader does this. + * + * The phy_id is ignored as the driver will probe for it. + */ +static int __init parse_tag_ethernet(struct tag *tag) +{ + int i; + + i = tag->u.ethernet.mac_index; + if (i < ARRAY_SIZE(hw_addr)) + memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, + sizeof(hw_addr[i].addr)); + + return 0; +} +__tagtable(ATAG_ETHERNET, parse_tag_ethernet); + +static void __init set_hw_addr(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + const u8 *addr; + void __iomem *regs; + struct clk *pclk; + + if (!res) + return; + if (pdev->id >= ARRAY_SIZE(hw_addr)) + return; + + addr = hw_addr[pdev->id].addr; + if (!is_valid_ether_addr(addr)) + return; + + /* + * Since this is board-specific code, we'll cheat and use the + * physical address directly as we happen to know that it's + * the same as the virtual address. + */ + regs = (void __iomem __force *)res->start; + pclk = clk_get(&pdev->dev, "pclk"); + if (!pclk) + return; + + clk_enable(pclk); + __raw_writel((addr[3] << 24) | (addr[2] << 16) + | (addr[1] << 8) | addr[0], regs + 0x98); + __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); + clk_disable(pclk); + clk_put(pclk); +} + +struct platform_device *at32_usart_map[1]; +unsigned int at32_nr_usarts = 1; + +void __init setup_board(void) +{ + at32_map_usart(1, 0); /* USART 1: /dev/ttyS0, DB9 */ + at32_setup_serial_console(0); +} + +static int __init atngw100_init(void) +{ + /* + * ATNGW100 uses 16-bit SDRAM interface, so we don't need to + * reserve any pins for it. + */ + + at32_add_system_devices(); + + at32_add_device_usart(0); + + set_hw_addr(at32_add_device_eth(0, ð_data[0])); + set_hw_addr(at32_add_device_eth(1, ð_data[1])); + + at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); + + return 0; +} +postcore_initcall(atngw100_init); diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index 5974768a59e..abe6ca203fa 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -33,7 +33,7 @@ struct eth_addr { static struct eth_addr __initdata hw_addr[2]; static struct eth_platform_data __initdata eth_data[2]; -extern struct lcdc_platform_data atstk1000_fb0_data; +static struct lcdc_platform_data atstk1000_fb0_data; static struct spi_board_info spi0_board_info[] __initdata = { { @@ -148,6 +148,8 @@ static int __init atstk1002_init(void) set_hw_addr(at32_add_device_eth(0, ð_data[0])); at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); + atstk1000_fb0_data.fbmem_start = fbmem_start; + atstk1000_fb0_data.fbmem_size = fbmem_size; at32_add_device_lcdc(0, &atstk1000_fb0_data); return 0; diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c index 272c011802a..2bc4b88d7ed 100644 --- a/arch/avr32/boards/atstk1000/setup.c +++ b/arch/avr32/boards/atstk1000/setup.c @@ -18,33 +18,3 @@ /* Initialized by bootloader-specific startup code. */ struct tag *bootloader_tags __initdata; - -struct lcdc_platform_data __initdata atstk1000_fb0_data; - -void __init board_setup_fbmem(unsigned long fbmem_start, - unsigned long fbmem_size) -{ - if (!fbmem_size) - return; - - if (!fbmem_start) { - void *fbmem; - - fbmem = alloc_bootmem_low_pages(fbmem_size); - fbmem_start = __pa(fbmem); - } else { - pg_data_t *pgdat; - - for_each_online_pgdat(pgdat) { - if (fbmem_start >= pgdat->bdata->node_boot_start - && fbmem_start <= pgdat->bdata->node_low_pfn) - reserve_bootmem_node(pgdat, fbmem_start, - fbmem_size); - } - } - - printk("%luKiB framebuffer memory at address 0x%08lx\n", - fbmem_size >> 10, fbmem_start); - atstk1000_fb0_data.fbmem_start = fbmem_start; - atstk1000_fb0_data.fbmem_size = fbmem_size; -} diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig new file mode 100644 index 00000000000..c254ffcfa45 --- /dev/null +++ b/arch/avr32/configs/atngw100_defconfig @@ -0,0 +1,1085 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.21-rc6 +# Thu Apr 12 16:35:07 2007 +# +CONFIG_AVR32=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_TIME=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +# CONFIG_BASE_FULL is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=1 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# System Type and features +# +CONFIG_SUBARCH_AVR32B=y +CONFIG_MMU=y +CONFIG_PERFORMANCE_COUNTERS=y +CONFIG_PLATFORM_AT32AP=y +CONFIG_CPU_AT32AP7000=y +# CONFIG_BOARD_ATSTK1000 is not set +CONFIG_BOARD_ATNGW100=y +CONFIG_LOADER_U_BOOT=y + +# +# Atmel AVR32 AP options +# +# CONFIG_AP7000_32_BIT_SMC is not set +CONFIG_AP7000_16_BIT_SMC=y +# CONFIG_AP7000_8_BIT_SMC is not set +CONFIG_LOAD_ADDRESS=0x10000000 +CONFIG_ENTRY_ADDRESS=0x90000000 +CONFIG_PHYS_OFFSET=0x10000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +# CONFIG_HAVE_ARCH_BOOTMEM_NODE is not set +# CONFIG_ARCH_HAVE_MEMORY_PRESENT is not set +# CONFIG_NEED_NODE_MEMMAP_SIZE is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +# CONFIG_ARCH_SPARSEMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +# CONFIG_OWNERSHIP_TRACE is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_CMDLINE="" + +# +# Bus options +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +# CONFIG_IP_PIMSM_V2 is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +# CONFIG_IPV6_MIP6 is not set +CONFIG_INET6_XFRM_TUNNEL=y +CONFIG_INET6_TUNNEL=y +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +CONFIG_NF_CONNTRACK_ENABLED=m +CONFIG_NF_CONNTRACK_SUPPORT=y +# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CT_ACCT=y +CONFIG_NF_CONNTRACK_MARK=y +# CONFIG_NF_CONNTRACK_EVENTS is not set +CONFIG_NF_CT_PROTO_GRE=m +# CONFIG_NF_CT_PROTO_SCTP is not set +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NETFILTER_XTABLES=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +# CONFIG_IP_NF_TARGET_ULOG is not set +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_NF_NAT_SIP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +CONFIG_NET_CLS_ROUTE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x80000000 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_DATAFLASH=y +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNPACPI is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# Misc devices +# + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_NETLINK is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +# CONFIG_ATA is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_MACB=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +CONFIG_SLHC=m +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_ATMEL=y +# CONFIG_SPI_BITBANG is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# Auxiliary Display support +# + +# +# Virtualization +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=850 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_FRAME_POINTER=y +# CONFIG_FORCED_INLINING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_KPROBES is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c index 2e72fd2699d..2714cf6452b 100644 --- a/arch/avr32/kernel/cpu.c +++ b/arch/avr32/kernel/cpu.c @@ -209,16 +209,17 @@ static const char *mmu_types[] = { void __init setup_processor(void) { unsigned long config0, config1; + unsigned long features; unsigned cpu_id, cpu_rev, arch_id, arch_rev, mmu_type; unsigned tmp; - config0 = sysreg_read(CONFIG0); /* 0x0000013e; */ - config1 = sysreg_read(CONFIG1); /* 0x01f689a2; */ - cpu_id = config0 >> 24; - cpu_rev = (config0 >> 16) & 0xff; - arch_id = (config0 >> 13) & 0x07; - arch_rev = (config0 >> 10) & 0x07; - mmu_type = (config0 >> 7) & 0x03; + config0 = sysreg_read(CONFIG0); + config1 = sysreg_read(CONFIG1); + cpu_id = SYSREG_BFEXT(PROCESSORID, config0); + cpu_rev = SYSREG_BFEXT(PROCESSORREVISION, config0); + arch_id = SYSREG_BFEXT(AT, config0); + arch_rev = SYSREG_BFEXT(AR, config0); + mmu_type = SYSREG_BFEXT(MMUT, config0); boot_cpu_data.arch_type = arch_id; boot_cpu_data.cpu_type = cpu_id; @@ -226,16 +227,16 @@ void __init setup_processor(void) boot_cpu_data.cpu_revision = cpu_rev; boot_cpu_data.tlb_config = mmu_type; - tmp = (config1 >> 13) & 0x07; + tmp = SYSREG_BFEXT(ILSZ, config1); if (tmp) { - boot_cpu_data.icache.ways = 1 << ((config1 >> 10) & 0x07); - boot_cpu_data.icache.sets = 1 << ((config1 >> 16) & 0x0f); + boot_cpu_data.icache.ways = 1 << SYSREG_BFEXT(IASS, config1); + boot_cpu_data.icache.sets = 1 << SYSREG_BFEXT(ISET, config1); boot_cpu_data.icache.linesz = 1 << (tmp + 1); } - tmp = (config1 >> 3) & 0x07; + tmp = SYSREG_BFEXT(DLSZ, config1); if (tmp) { - boot_cpu_data.dcache.ways = 1 << (config1 & 0x07); - boot_cpu_data.dcache.sets = 1 << ((config1 >> 6) & 0x0f); + boot_cpu_data.dcache.ways = 1 << SYSREG_BFEXT(DASS, config1); + boot_cpu_data.dcache.sets = 1 << SYSREG_BFEXT(DSET, config1); boot_cpu_data.dcache.linesz = 1 << (tmp + 1); } @@ -250,16 +251,39 @@ void __init setup_processor(void) cpu_names[cpu_id], cpu_id, cpu_rev, arch_names[arch_id], arch_rev); printk ("CPU: MMU configuration: %s\n", mmu_types[mmu_type]); + printk ("CPU: features:"); - if (config0 & (1 << 6)) - printk(" fpu"); - if (config0 & (1 << 5)) - printk(" java"); - if (config0 & (1 << 4)) - printk(" perfctr"); - if (config0 & (1 << 3)) + features = 0; + if (config0 & SYSREG_BIT(CONFIG0_R)) { + features |= AVR32_FEATURE_RMW; + printk(" rmw"); + } + if (config0 & SYSREG_BIT(CONFIG0_D)) { + features |= AVR32_FEATURE_DSP; + printk(" dsp"); + } + if (config0 & SYSREG_BIT(CONFIG0_S)) { + features |= AVR32_FEATURE_SIMD; + printk(" simd"); + } + if (config0 & SYSREG_BIT(CONFIG0_O)) { + features |= AVR32_FEATURE_OCD; printk(" ocd"); + } + if (config0 & SYSREG_BIT(CONFIG0_P)) { + features |= AVR32_FEATURE_PCTR; + printk(" perfctr"); + } + if (config0 & SYSREG_BIT(CONFIG0_J)) { + features |= AVR32_FEATURE_JAVA; + printk(" java"); + } + if (config0 & SYSREG_BIT(CONFIG0_F)) { + features |= AVR32_FEATURE_FPU; + printk(" fpu"); + } printk("\n"); + boot_cpu_data.features = features; } #ifdef CONFIG_PROC_FS diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index eeb66792bc3..42657f1703b 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -100,55 +100,49 @@ dtlb_miss_write: .global tlb_miss_common tlb_miss_common: - mfsr r0, SYSREG_PTBR - mfsr r1, SYSREG_TLBEAR + mfsr r0, SYSREG_TLBEAR + mfsr r1, SYSREG_PTBR /* Is it the vmalloc space? */ - bld r1, 31 + bld r0, 31 brcs handle_vmalloc_miss /* First level lookup */ pgtbl_lookup: - lsr r2, r1, PGDIR_SHIFT - ld.w r0, r0[r2 << 2] - bld r0, _PAGE_BIT_PRESENT + lsr r2, r0, PGDIR_SHIFT + ld.w r3, r1[r2 << 2] + bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT + bld r3, _PAGE_BIT_PRESENT brcc page_table_not_present - /* TODO: Check access rights on page table if necessary */ - /* Translate to virtual address in P1. */ - andl r0, 0xf000 - sbr r0, 31 + andl r3, 0xf000 + sbr r3, 31 /* Second level lookup */ - lsl r1, (32 - PGDIR_SHIFT) - lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT - add r2, r0, r1 << 2 - ld.w r1, r2[0] - bld r1, _PAGE_BIT_PRESENT + ld.w r2, r3[r1 << 2] + mfsr r0, SYSREG_TLBARLO + bld r2, _PAGE_BIT_PRESENT brcc page_not_present /* Mark the page as accessed */ - sbr r1, _PAGE_BIT_ACCESSED - st.w r2[0], r1 + sbr r2, _PAGE_BIT_ACCESSED + st.w r3[r1 << 2], r2 /* Drop software flags */ - andl r1, _PAGE_FLAGS_HARDWARE_MASK & 0xffff - mtsr SYSREG_TLBELO, r1 + andl r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff + mtsr SYSREG_TLBELO, r2 /* Figure out which entry we want to replace */ - mfsr r0, SYSREG_TLBARLO + mfsr r1, SYSREG_MMUCR clz r2, r0 brcc 1f - mov r1, -1 /* All entries have been accessed, */ - mtsr SYSREG_TLBARLO, r1 /* so reset TLBAR */ - mov r2, 0 /* and start at 0 */ -1: mfsr r1, SYSREG_MMUCR - lsl r2, 14 - andl r1, 0x3fff, COH - or r1, r2 - mtsr SYSREG_MMUCR, r1 + mov r3, -1 /* All entries have been accessed, */ + mov r2, 0 /* so start at 0 */ + mtsr SYSREG_TLBARLO, r3 /* and reset TLBAR */ +1: bfins r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE + mtsr SYSREG_MMUCR, r1 tlbw tlbmiss_restore @@ -156,8 +150,8 @@ pgtbl_lookup: handle_vmalloc_miss: /* Simply do the lookup in init's page table */ - mov r0, lo(swapper_pg_dir) - orh r0, hi(swapper_pg_dir) + mov r1, lo(swapper_pg_dir) + orh r1, hi(swapper_pg_dir) rjmp pgtbl_lookup @@ -340,12 +334,34 @@ do_bus_error_read: do_nmi_ll: sub sp, 4 stmts --sp, r0-lr - /* FIXME: Make sure RAR_NMI and RSR_NMI are pushed instead of *_EX */ - rcall save_full_context_ex + mfsr r9, SYSREG_RSR_NMI + mfsr r8, SYSREG_RAR_NMI + bfextu r0, r9, MODE_SHIFT, 3 + brne 2f + +1: pushm r8, r9 /* PC and SR */ mfsr r12, SYSREG_ECR mov r11, sp rcall do_nmi - rjmp bad_return + popm r8-r9 + mtsr SYSREG_RAR_NMI, r8 + tst r0, r0 + mtsr SYSREG_RSR_NMI, r9 + brne 3f + + ldmts sp++, r0-lr + sub sp, -4 /* skip r12_orig */ + rete + +2: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR) + stdsp sp[4], r10 /* replace saved SP */ + rjmp 1b + +3: popm lr + sub sp, -4 /* skip sp */ + popm r0-r12 + sub sp, -4 /* skip r12_orig */ + rete handle_address_fault: sub sp, 4 @@ -630,9 +646,12 @@ irq_level\level: rcall do_IRQ lddsp r4, sp[REG_SR] - andh r4, (MODE_MASK >> 16), COH + bfextu r4, r4, SYSREG_M0_OFFSET, 3 + cp.w r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET + breq 2f + cp.w r4, MODE_USER >> SYSREG_M0_OFFSET #ifdef CONFIG_PREEMPT - brne 2f + brne 3f #else brne 1f #endif @@ -649,9 +668,18 @@ irq_level\level: sub sp, -4 /* ignore r12_orig */ rete +2: get_thread_info r0 + ld.w r1, r0[TI_flags] + bld r1, TIF_CPU_GOING_TO_SLEEP #ifdef CONFIG_PREEMPT -2: - get_thread_info r0 + brcc 3f +#else + brcc 1b +#endif + sub r1, pc, . - cpu_idle_skip_sleep + stdsp sp[REG_PC], r1 +#ifdef CONFIG_PREEMPT +3: get_thread_info r0 ld.w r2, r0[TI_preempt_count] cp.w r2, 0 brne 1b @@ -662,12 +690,32 @@ irq_level\level: bld r4, SYSREG_GM_OFFSET brcs 1b rcall preempt_schedule_irq - rjmp 1b #endif + rjmp 1b .endm .section .irq.text,"ax",@progbits +.global cpu_idle_sleep +cpu_idle_sleep: + mask_interrupts + get_thread_info r8 + ld.w r9, r8[TI_flags] + bld r9, TIF_NEED_RESCHED + brcs cpu_idle_enable_int_and_exit + sbr r9, TIF_CPU_GOING_TO_SLEEP + st.w r8[TI_flags], r9 + unmask_interrupts + sleep 0 +cpu_idle_skip_sleep: + mask_interrupts + ld.w r9, r8[TI_flags] + cbr r9, TIF_CPU_GOING_TO_SLEEP + st.w r8[TI_flags], r9 +cpu_idle_enable_int_and_exit: + unmask_interrupts + retal r12 + .global irq_level0 .global irq_level1 .global irq_level2 diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c index b599eae6457..1167fe9cf6c 100644 --- a/arch/avr32/kernel/module.c +++ b/arch/avr32/kernel/module.c @@ -12,10 +12,11 @@ * published by the Free Software Foundation. */ -#include <linux/moduleloader.h> -#include <linux/module.h> -#include <linux/kernel.h> +#include <linux/bug.h> #include <linux/elf.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleloader.h> #include <linux/vmalloc.h> void *module_alloc(unsigned long size) @@ -315,10 +316,10 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, vfree(module->arch.syminfo); module->arch.syminfo = NULL; - return 0; + return module_bug_finalize(hdr, sechdrs, module); } void module_arch_cleanup(struct module *module) { - + module_bug_cleanup(module); } diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 0b4325946a4..4e4181ed1c6 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c @@ -11,6 +11,7 @@ #include <linux/fs.h> #include <linux/ptrace.h> #include <linux/reboot.h> +#include <linux/uaccess.h> #include <linux/unistd.h> #include <asm/sysreg.h> @@ -19,6 +20,8 @@ void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); +extern void cpu_idle_sleep(void); + /* * This file handles the architecture-dependent parts of process handling.. */ @@ -27,9 +30,8 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { - /* TODO: Enter sleep mode */ while (!need_resched()) - cpu_relax(); + cpu_idle_sleep(); preempt_enable_no_resched(); schedule(); preempt_disable(); @@ -114,39 +116,178 @@ void release_thread(struct task_struct *dead_task) /* do nothing */ } +static void dump_mem(const char *str, const char *log_lvl, + unsigned long bottom, unsigned long top) +{ + unsigned long p; + int i; + + printk("%s%s(0x%08lx to 0x%08lx)\n", log_lvl, str, bottom, top); + + for (p = bottom & ~31; p < top; ) { + printk("%s%04lx: ", log_lvl, p & 0xffff); + + for (i = 0; i < 8; i++, p += 4) { + unsigned int val; + + if (p < bottom || p >= top) + printk(" "); + else { + if (__get_user(val, (unsigned int __user *)p)) { + printk("\n"); + goto out; + } + printk("%08x ", val); + } + } + printk("\n"); + } + +out: + return; +} + +static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p) +{ + return (p > (unsigned long)tinfo) + && (p < (unsigned long)tinfo + THREAD_SIZE - 3); +} + +#ifdef CONFIG_FRAME_POINTER +static void show_trace_log_lvl(struct task_struct *tsk, unsigned long *sp, + struct pt_regs *regs, const char *log_lvl) +{ + unsigned long lr, fp; + struct thread_info *tinfo; + + if (regs) + fp = regs->r7; + else if (tsk == current) + asm("mov %0, r7" : "=r"(fp)); + else + fp = tsk->thread.cpu_context.r7; + + /* + * Walk the stack as long as the frame pointer (a) is within + * the kernel stack of the task, and (b) it doesn't move + * downwards. + */ + tinfo = task_thread_info(tsk); + printk("%sCall trace:\n", log_lvl); + while (valid_stack_ptr(tinfo, fp)) { + unsigned long new_fp; + + lr = *(unsigned long *)fp; +#ifdef CONFIG_KALLSYMS + printk("%s [<%08lx>] ", log_lvl, lr); +#else + printk(" [<%08lx>] ", lr); +#endif + print_symbol("%s\n", lr); + + new_fp = *(unsigned long *)(fp + 4); + if (new_fp <= fp) + break; + fp = new_fp; + } + printk("\n"); +} +#else +static void show_trace_log_lvl(struct task_struct *tsk, unsigned long *sp, + struct pt_regs *regs, const char *log_lvl) +{ + unsigned long addr; + + printk("%sCall trace:\n", log_lvl); + + while (!kstack_end(sp)) { + addr = *sp++; + if (kernel_text_address(addr)) { +#ifdef CONFIG_KALLSYMS + printk("%s [<%08lx>] ", log_lvl, addr); +#else + printk(" [<%08lx>] ", addr); +#endif + print_symbol("%s\n", addr); + } + } + printk("\n"); +} +#endif + +void show_stack_log_lvl(struct task_struct *tsk, unsigned long sp, + struct pt_regs *regs, const char *log_lvl) +{ + struct thread_info *tinfo; + + if (sp == 0) { + if (tsk) + sp = tsk->thread.cpu_context.ksp; + else + sp = (unsigned long)&tinfo; + } + if (!tsk) + tsk = current; + + tinfo = task_thread_info(tsk); + + if (valid_stack_ptr(tinfo, sp)) { + dump_mem("Stack: ", log_lvl, sp, + THREAD_SIZE + (unsigned long)tinfo); + show_trace_log_lvl(tsk, (unsigned long *)sp, regs, log_lvl); + } +} + +void show_stack(struct task_struct *tsk, unsigned long *stack) +{ + show_stack_log_lvl(tsk, (unsigned long)stack, NULL, ""); +} + +void dump_stack(void) +{ + unsigned long stack; + + show_trace_log_lvl(current, &stack, NULL, ""); +} +EXPORT_SYMBOL(dump_stack); + static const char *cpu_modes[] = { "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1", "Interrupt level 2", "Interrupt level 3", "Exception", "NMI" }; -void show_regs(struct pt_regs *regs) +void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl) { unsigned long sp = regs->sp; unsigned long lr = regs->lr; unsigned long mode = (regs->sr & MODE_MASK) >> MODE_SHIFT; - if (!user_mode(regs)) + if (!user_mode(regs)) { sp = (unsigned long)regs + FRAME_SIZE_FULL; - print_symbol("PC is at %s\n", instruction_pointer(regs)); - print_symbol("LR is at %s\n", lr); - printk("pc : [<%08lx>] lr : [<%08lx>] %s\n" - "sp : %08lx r12: %08lx r11: %08lx\n", - instruction_pointer(regs), - lr, print_tainted(), sp, regs->r12, regs->r11); - printk("r10: %08lx r9 : %08lx r8 : %08lx\n", - regs->r10, regs->r9, regs->r8); - printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", - regs->r7, regs->r6, regs->r5, regs->r4); - printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", - regs->r3, regs->r2, regs->r1, regs->r0); - printk("Flags: %c%c%c%c%c\n", + printk("%s", log_lvl); + print_symbol("PC is at %s\n", instruction_pointer(regs)); + printk("%s", log_lvl); + print_symbol("LR is at %s\n", lr); + } + + printk("%spc : [<%08lx>] lr : [<%08lx>] %s\n" + "%ssp : %08lx r12: %08lx r11: %08lx\n", + log_lvl, instruction_pointer(regs), lr, print_tainted(), + log_lvl, sp, regs->r12, regs->r11); + printk("%sr10: %08lx r9 : %08lx r8 : %08lx\n", + log_lvl, regs->r10, regs->r9, regs->r8); + printk("%sr7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", + log_lvl, regs->r7, regs->r6, regs->r5, regs->r4); + printk("%sr3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", + log_lvl, regs->r3, regs->r2, regs->r1, regs->r0); + printk("%sFlags: %c%c%c%c%c\n", log_lvl, regs->sr & SR_Q ? 'Q' : 'q', regs->sr & SR_V ? 'V' : 'v', regs->sr & SR_N ? 'N' : 'n', regs->sr & SR_Z ? 'Z' : 'z', regs->sr & SR_C ? 'C' : 'c'); - printk("Mode bits: %c%c%c%c%c%c%c%c%c\n", + printk("%sMode bits: %c%c%c%c%c%c%c%c%c\n", log_lvl, regs->sr & SR_H ? 'H' : 'h', regs->sr & SR_R ? 'R' : 'r', regs->sr & SR_J ? 'J' : 'j', @@ -156,9 +297,21 @@ void show_regs(struct pt_regs *regs) regs->sr & SR_I1M ? '1' : '.', regs->sr & SR_I0M ? '0' : '.', regs->sr & SR_GM ? 'G' : 'g'); - printk("CPU Mode: %s\n", cpu_modes[mode]); + printk("%sCPU Mode: %s\n", log_lvl, cpu_modes[mode]); + printk("%sProcess: %s [%d] (task: %p thread: %p)\n", + log_lvl, current->comm, current->pid, current, + task_thread_info(current)); +} + +void show_regs(struct pt_regs *regs) +{ + unsigned long sp = regs->sp; + + if (!user_mode(regs)) + sp = (unsigned long)regs + FRAME_SIZE_FULL; - show_trace(NULL, (unsigned long *)sp, regs); + show_regs_log_lvl(regs, ""); + show_trace_log_lvl(current, (unsigned long *)sp, regs, ""); } EXPORT_SYMBOL(show_regs); diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index a1a7c3c3f52..b279d66acf5 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c @@ -8,12 +8,14 @@ #include <linux/clk.h> #include <linux/init.h> +#include <linux/initrd.h> #include <linux/sched.h> #include <linux/console.h> #include <linux/ioport.h> #include <linux/bootmem.h> #include <linux/fs.h> #include <linux/module.h> +#include <linux/pfn.h> #include <linux/root_dev.h> #include <linux/cpu.h> #include <linux/kernel.h> @@ -30,13 +32,6 @@ extern int root_mountflags; /* - * Bootloader-provided information about physical memory - */ -struct tag_mem_range *mem_phys; -struct tag_mem_range *mem_reserved; -struct tag_mem_range *mem_ramdisk; - -/* * Initialize loops_per_jiffy as 5000000 (500MIPS). * Better make it too large than too small... */ @@ -48,48 +43,193 @@ EXPORT_SYMBOL(boot_cpu_data); static char __initdata command_line[COMMAND_LINE_SIZE]; /* - * Should be more than enough, but if you have a _really_ complex - * setup, you might need to increase the size of this... + * Standard memory resources */ -static struct tag_mem_range __initdata mem_range_cache[32]; -static unsigned mem_range_next_free; +static struct resource __initdata kernel_data = { + .name = "Kernel data", + .start = 0, + .end = 0, + .flags = IORESOURCE_MEM, +}; +static struct resource __initdata kernel_code = { + .name = "Kernel code", + .start = 0, + .end = 0, + .flags = IORESOURCE_MEM, + .sibling = &kernel_data, +}; /* - * Standard memory resources + * Available system RAM and reserved regions as singly linked + * lists. These lists are traversed using the sibling pointer in + * struct resource and are kept sorted at all times. */ -static struct resource mem_res[] = { - { - .name = "Kernel code", - .start = 0, - .end = 0, - .flags = IORESOURCE_MEM - }, - { - .name = "Kernel data", - .start = 0, - .end = 0, - .flags = IORESOURCE_MEM, - }, -}; +static struct resource *__initdata system_ram; +static struct resource *__initdata reserved = &kernel_code; + +/* + * We need to allocate these before the bootmem allocator is up and + * running, so we need this "cache". 32 entries are probably enough + * for all but the most insanely complex systems. + */ +static struct resource __initdata res_cache[32]; +static unsigned int __initdata res_cache_next_free; + +static void __init resource_init(void) +{ + struct resource *mem, *res; + struct resource *new; + + kernel_code.start = __pa(init_mm.start_code); + + for (mem = system_ram; mem; mem = mem->sibling) { + new = alloc_bootmem_low(sizeof(struct resource)); + memcpy(new, mem, sizeof(struct resource)); + + new->sibling = NULL; + if (request_resource(&iomem_resource, new)) + printk(KERN_WARNING "Bad RAM resource %08x-%08x\n", + mem->start, mem->end); + } + + for (res = reserved; res; res = res->sibling) { + new = alloc_bootmem_low(sizeof(struct resource)); + memcpy(new, res, sizeof(struct resource)); + + new->sibling = NULL; + if (insert_resource(&iomem_resource, new)) + printk(KERN_WARNING + "Bad reserved resource %s (%08x-%08x)\n", + res->name, res->start, res->end); + } +} + +static void __init +add_physical_memory(resource_size_t start, resource_size_t end) +{ + struct resource *new, *next, **pprev; + + for (pprev = &system_ram, next = system_ram; next; + pprev = &next->sibling, next = next->sibling) { + if (end < next->start) + break; + if (start <= next->end) { + printk(KERN_WARNING + "Warning: Physical memory map is broken\n"); + printk(KERN_WARNING + "Warning: %08x-%08x overlaps %08x-%08x\n", + start, end, next->start, next->end); + return; + } + } + + if (res_cache_next_free >= ARRAY_SIZE(res_cache)) { + printk(KERN_WARNING + "Warning: Failed to add physical memory %08x-%08x\n", + start, end); + return; + } + + new = &res_cache[res_cache_next_free++]; + new->start = start; + new->end = end; + new->name = "System RAM"; + new->flags = IORESOURCE_MEM; + + *pprev = new; +} + +static int __init +add_reserved_region(resource_size_t start, resource_size_t end, + const char *name) +{ + struct resource *new, *next, **pprev; + + if (end < start) + return -EINVAL; + + if (res_cache_next_free >= ARRAY_SIZE(res_cache)) + return -ENOMEM; + + for (pprev = &reserved, next = reserved; next; + pprev = &next->sibling, next = next->sibling) { + if (end < next->start) + break; + if (start <= next->end) + return -EBUSY; + } + + new = &res_cache[res_cache_next_free++]; + new->start = start; + new->end = end; + new->name = name; + new->flags = IORESOURCE_MEM; + + *pprev = new; + + return 0; +} + +static unsigned long __init +find_free_region(const struct resource *mem, resource_size_t size, + resource_size_t align) +{ + struct resource *res; + unsigned long target; + + target = ALIGN(mem->start, align); + for (res = reserved; res; res = res->sibling) { + if ((target + size) <= res->start) + break; + if (target <= res->end) + target = ALIGN(res->end + 1, align); + } + + if ((target + size) > (mem->end + 1)) + return mem->end + 1; + + return target; +} + +static int __init +alloc_reserved_region(resource_size_t *start, resource_size_t size, + resource_size_t align, const char *name) +{ + struct resource *mem; + resource_size_t target; + int ret; + + for (mem = system_ram; mem; mem = mem->sibling) { + target = find_free_region(mem, size, align); + if (target <= mem->end) { + ret = add_reserved_region(target, target + size - 1, + name); + if (!ret) + *start = target; + return ret; + } + } -#define kernel_code mem_res[0] -#define kernel_data mem_res[1] + return -ENOMEM; +} /* * Early framebuffer allocation. Works as follows: * - If fbmem_size is zero, nothing will be allocated or reserved. * - If fbmem_start is zero when setup_bootmem() is called, - * fbmem_size bytes will be allocated from the bootmem allocator. + * a block of fbmem_size bytes will be reserved before bootmem + * initialization. It will be aligned to the largest page size + * that fbmem_size is a multiple of. * - If fbmem_start is nonzero, an area of size fbmem_size will be - * reserved at the physical address fbmem_start if necessary. If - * the area isn't in a memory region known to the kernel, it will - * be left alone. + * reserved at the physical address fbmem_start if possible. If + * it collides with other reserved memory, a different block of + * same size will be allocated, just as if fbmem_start was zero. * * Board-specific code may use these variables to set up platform data * for the framebuffer driver if fbmem_size is nonzero. */ -static unsigned long __initdata fbmem_start; -static unsigned long __initdata fbmem_size; +resource_size_t __initdata fbmem_start; +resource_size_t __initdata fbmem_size; /* * "fbmem=xxx[kKmM]" allocates the specified amount of boot memory for @@ -103,48 +243,42 @@ static unsigned long __initdata fbmem_size; */ static int __init early_parse_fbmem(char *p) { + int ret; + unsigned long align; + fbmem_size = memparse(p, &p); - if (*p == '@') + if (*p == '@') { fbmem_start = memparse(p, &p); - return 0; -} -early_param("fbmem", early_parse_fbmem); - -static inline void __init resource_init(void) -{ - struct tag_mem_range *region; - - kernel_code.start = __pa(init_mm.start_code); - kernel_code.end = __pa(init_mm.end_code - 1); - kernel_data.start = __pa(init_mm.end_code); - kernel_data.end = __pa(init_mm.brk - 1); - - for (region = mem_phys; region; region = region->next) { - struct resource *res; - unsigned long phys_start, phys_end; - - if (region->size == 0) - continue; - - phys_start = region->addr; - phys_end = phys_start + region->size - 1; - - res = alloc_bootmem_low(sizeof(*res)); - res->name = "System RAM"; - res->start = phys_start; - res->end = phys_end; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; - - request_resource (&iomem_resource, res); + ret = add_reserved_region(fbmem_start, + fbmem_start + fbmem_size - 1, + "Framebuffer"); + if (ret) { + printk(KERN_WARNING + "Failed to reserve framebuffer memory\n"); + fbmem_start = 0; + } + } - if (kernel_code.start >= res->start && - kernel_code.end <= res->end) - request_resource (res, &kernel_code); - if (kernel_data.start >= res->start && - kernel_data.end <= res->end) - request_resource (res, &kernel_data); + if (!fbmem_start) { + if ((fbmem_size & 0x000fffffUL) == 0) + align = 0x100000; /* 1 MiB */ + else if ((fbmem_size & 0x0000ffffUL) == 0) + align = 0x10000; /* 64 KiB */ + else + align = 0x1000; /* 4 KiB */ + + ret = alloc_reserved_region(&fbmem_start, fbmem_size, + align, "Framebuffer"); + if (ret) { + printk(KERN_WARNING + "Failed to allocate framebuffer memory\n"); + fbmem_size = 0; + } } + + return 0; } +early_param("fbmem", early_parse_fbmem); static int __init parse_tag_core(struct tag *tag) { @@ -157,11 +291,9 @@ static int __init parse_tag_core(struct tag *tag) } __tagtable(ATAG_CORE, parse_tag_core); -static int __init parse_tag_mem_range(struct tag *tag, - struct tag_mem_range **root) +static int __init parse_tag_mem(struct tag *tag) { - struct tag_mem_range *cur, **pprev; - struct tag_mem_range *new; + unsigned long start, end; /* * Ignore zero-sized entries. If we're running standalone, the @@ -171,34 +303,53 @@ static int __init parse_tag_mem_range(struct tag *tag, if (tag->u.mem_range.size == 0) return 0; - /* - * Copy the data so the bootmem init code doesn't need to care - * about it. - */ - if (mem_range_next_free >= ARRAY_SIZE(mem_range_cache)) - panic("Physical memory map too complex!\n"); + start = tag->u.mem_range.addr; + end = tag->u.mem_range.addr + tag->u.mem_range.size - 1; + + add_physical_memory(start, end); + return 0; +} +__tagtable(ATAG_MEM, parse_tag_mem); + +static int __init parse_tag_rdimg(struct tag *tag) +{ +#ifdef CONFIG_INITRD + struct tag_mem_range *mem = &tag->u.mem_range; + int ret; - new = &mem_range_cache[mem_range_next_free++]; - *new = tag->u.mem_range; + if (initrd_start) { + printk(KERN_WARNING + "Warning: Only the first initrd image will be used\n"); + return 0; + } - pprev = root; - cur = *root; - while (cur) { - pprev = &cur->next; - cur = cur->next; + ret = add_reserved_region(mem->start, mem->start + mem->size - 1, + "initrd"); + if (ret) { + printk(KERN_WARNING + "Warning: Failed to reserve initrd memory\n"); + return ret; } - *pprev = new; - new->next = NULL; + initrd_start = (unsigned long)__va(mem->addr); + initrd_end = initrd_start + mem->size; +#else + printk(KERN_WARNING "RAM disk image present, but " + "no initrd support in kernel, ignoring\n"); +#endif return 0; } +__tagtable(ATAG_RDIMG, parse_tag_rdimg); -static int __init parse_tag_mem(struct tag *tag) +static int __init parse_tag_rsvd_mem(struct tag *tag) { - return parse_tag_mem_range(tag, &mem_phys); + struct tag_mem_range *mem = &tag->u.mem_range; + + return add_reserved_region(mem->addr, mem->addr + mem->size - 1, + "Reserved"); } -__tagtable(ATAG_MEM, parse_tag_mem); +__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem); static int __init parse_tag_cmdline(struct tag *tag) { @@ -207,12 +358,6 @@ static int __init parse_tag_cmdline(struct tag *tag) } __tagtable(ATAG_CMDLINE, parse_tag_cmdline); -static int __init parse_tag_rdimg(struct tag *tag) -{ - return parse_tag_mem_range(tag, &mem_ramdisk); -} -__tagtable(ATAG_RDIMG, parse_tag_rdimg); - static int __init parse_tag_clock(struct tag *tag) { /* @@ -223,12 +368,6 @@ static int __init parse_tag_clock(struct tag *tag) } __tagtable(ATAG_CLOCK, parse_tag_clock); -static int __init parse_tag_rsvd_mem(struct tag *tag) -{ - return parse_tag_mem_range(tag, &mem_reserved); -} -__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem); - /* * Scan the tag table for this tag, and call its parse function. The * tag table is built by the linker from all the __tagtable @@ -260,10 +399,137 @@ static void __init parse_tags(struct tag *t) t->hdr.tag); } +/* + * Find a free memory region large enough for storing the + * bootmem bitmap. + */ +static unsigned long __init +find_bootmap_pfn(const struct resource *mem) +{ + unsigned long bootmap_pages, bootmap_len; + unsigned long node_pages = PFN_UP(mem->end - mem->start + 1); + unsigned long bootmap_start; + + bootmap_pages = bootmem_bootmap_pages(node_pages); + bootmap_len = bootmap_pages << PAGE_SHIFT; + + /* + * Find a large enough region without reserved pages for + * storing the bootmem bitmap. We can take advantage of the + * fact that all lists have been sorted. + * + * We have to check that we don't collide with any reserved + * regions, which includes the kernel image and any RAMDISK + * images. + */ + bootmap_start = find_free_region(mem, bootmap_len, PAGE_SIZE); + + return bootmap_start >> PAGE_SHIFT; +} + +#define MAX_LOWMEM HIGHMEM_START +#define MAX_LOWMEM_PFN PFN_DOWN(MAX_LOWMEM) + +static void __init setup_bootmem(void) +{ + unsigned bootmap_size; + unsigned long first_pfn, bootmap_pfn, pages; + unsigned long max_pfn, max_low_pfn; + unsigned node = 0; + struct resource *res; + + printk(KERN_INFO "Physical memory:\n"); + for (res = system_ram; res; res = res->sibling) + printk(" %08x-%08x\n", res->start, res->end); + printk(KERN_INFO "Reserved memory:\n"); + for (res = reserved; res; res = res->sibling) + printk(" %08x-%08x: %s\n", + res->start, res->end, res->name); + + nodes_clear(node_online_map); + + if (system_ram->sibling) + printk(KERN_WARNING "Only using first memory bank\n"); + + for (res = system_ram; res; res = NULL) { + first_pfn = PFN_UP(res->start); + max_low_pfn = max_pfn = PFN_DOWN(res->end + 1); + bootmap_pfn = find_bootmap_pfn(res); + if (bootmap_pfn > max_pfn) + panic("No space for bootmem bitmap!\n"); + + if (max_low_pfn > MAX_LOWMEM_PFN) { + max_low_pfn = MAX_LOWMEM_PFN; +#ifndef CONFIG_HIGHMEM + /* + * Lowmem is memory that can be addressed + * directly through P1/P2 + */ + printk(KERN_WARNING + "Node %u: Only %ld MiB of memory will be used.\n", + node, MAX_LOWMEM >> 20); + printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); +#else +#error HIGHMEM is not supported by AVR32 yet +#endif + } + + /* Initialize the boot-time allocator with low memory only. */ + bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn, + first_pfn, max_low_pfn); + + /* + * Register fully available RAM pages with the bootmem + * allocator. + */ + pages = max_low_pfn - first_pfn; + free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn), + PFN_PHYS(pages)); + + /* Reserve space for the bootmem bitmap... */ + reserve_bootmem_node(NODE_DATA(node), + PFN_PHYS(bootmap_pfn), + bootmap_size); + + /* ...and any other reserved regions. */ + for (res = reserved; res; res = res->sibling) { + if (res->start > PFN_PHYS(max_pfn)) + break; + + /* + * resource_init will complain about partial + * overlaps, so we'll just ignore such + * resources for now. + */ + if (res->start >= PFN_PHYS(first_pfn) + && res->end < PFN_PHYS(max_pfn)) + reserve_bootmem_node( + NODE_DATA(node), res->start, + res->end - res->start + 1); + } + + node_set_online(node); + } +} + void __init setup_arch (char **cmdline_p) { struct clk *cpu_clk; + init_mm.start_code = (unsigned long)_text; + init_mm.end_code = (unsigned long)_etext; + init_mm.end_data = (unsigned long)_edata; + init_mm.brk = (unsigned long)_end; + + /* + * Include .init section to make allocations easier. It will + * be removed before the resource is actually requested. + */ + kernel_code.start = __pa(__init_begin); + kernel_code.end = __pa(init_mm.end_code - 1); + kernel_data.start = __pa(init_mm.end_code); + kernel_data.end = __pa(init_mm.brk - 1); + parse_tags(bootloader_tags); setup_processor(); @@ -289,24 +555,16 @@ void __init setup_arch (char **cmdline_p) ((cpu_hz + 500) / 1000) % 1000); } - init_mm.start_code = (unsigned long) &_text; - init_mm.end_code = (unsigned long) &_etext; - init_mm.end_data = (unsigned long) &_edata; - init_mm.brk = (unsigned long) &_end; - strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; parse_early_param(); setup_bootmem(); - board_setup_fbmem(fbmem_start, fbmem_size); - #ifdef CONFIG_VT conswitchp = &dummy_con; #endif paging_init(); - resource_init(); } diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c index c10833f2ee0..7014a3571ec 100644 --- a/arch/avr32/kernel/time.c +++ b/arch/avr32/kernel/time.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2006 Atmel Corporation + * Copyright (C) 2004-2007 Atmel Corporation * * Based on MIPS implementation arch/mips/kernel/time.c * Copyright 2001 MontaVista Software Inc. @@ -20,18 +20,25 @@ #include <linux/init.h> #include <linux/profile.h> #include <linux/sysdev.h> +#include <linux/err.h> #include <asm/div64.h> #include <asm/sysreg.h> #include <asm/io.h> #include <asm/sections.h> -static cycle_t read_cycle_count(void) +/* how many counter cycles in a jiffy? */ +static u32 cycles_per_jiffy; + +/* the count value for the next timer interrupt */ +static u32 expirelo; + +cycle_t __weak read_cycle_count(void) { return (cycle_t)sysreg_read(COUNT); } -static struct clocksource clocksource_avr32 = { +struct clocksource __weak clocksource_avr32 = { .name = "avr32", .rating = 350, .read = read_cycle_count, @@ -40,12 +47,20 @@ static struct clocksource clocksource_avr32 = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +irqreturn_t __weak timer_interrupt(int irq, void *dev_id); + +struct irqaction timer_irqaction = { + .handler = timer_interrupt, + .flags = IRQF_DISABLED, + .name = "timer", +}; + /* * By default we provide the null RTC ops */ static unsigned long null_rtc_get_time(void) { - return mktime(2004, 1, 1, 0, 0, 0); + return mktime(2007, 1, 1, 0, 0, 0); } static int null_rtc_set_time(unsigned long sec) @@ -56,23 +71,14 @@ static int null_rtc_set_time(unsigned long sec) static unsigned long (*rtc_get_time)(void) = null_rtc_get_time; static int (*rtc_set_time)(unsigned long) = null_rtc_set_time; -/* how many counter cycles in a jiffy? */ -static unsigned long cycles_per_jiffy; - -/* cycle counter value at the previous timer interrupt */ -static unsigned int timerhi, timerlo; - -/* the count value for the next timer interrupt */ -static unsigned int expirelo; - static void avr32_timer_ack(void) { - unsigned int count; + u32 count; /* Ack this timer interrupt and set the next one */ expirelo += cycles_per_jiffy; + /* setting COMPARE to 0 stops the COUNT-COMPARE */ if (expirelo == 0) { - printk(KERN_DEBUG "expirelo == 0\n"); sysreg_write(COMPARE, expirelo + 1); } else { sysreg_write(COMPARE, expirelo); @@ -86,27 +92,56 @@ static void avr32_timer_ack(void) } } -static unsigned int avr32_hpt_read(void) +int __weak avr32_hpt_init(void) { - return sysreg_read(COUNT); + int ret; + unsigned long mult, shift, count_hz; + + count_hz = clk_get_rate(boot_cpu_data.clk); + shift = clocksource_avr32.shift; + mult = clocksource_hz2mult(count_hz, shift); + clocksource_avr32.mult = mult; + + { + u64 tmp; + + tmp = TICK_NSEC; + tmp <<= shift; + tmp += mult / 2; + do_div(tmp, mult); + + cycles_per_jiffy = tmp; + } + + ret = setup_irq(0, &timer_irqaction); + if (ret) { + pr_debug("timer: could not request IRQ 0: %d\n", ret); + return -ENODEV; + } + + printk(KERN_INFO "timer: AT32AP COUNT-COMPARE at irq 0, " + "%lu.%03lu MHz\n", + ((count_hz + 500) / 1000) / 1000, + ((count_hz + 500) / 1000) % 1000); + + return 0; } /* * Taken from MIPS c0_hpt_timer_init(). * - * Why is it so complicated, and what is "count"? My assumption is - * that `count' specifies the "reference cycle", i.e. the cycle since - * reset that should mean "zero". The reason COUNT is written twice is - * probably to make sure we don't get any timer interrupts while we - * are messing with the counter. + * The reason COUNT is written twice is probably to make sure we don't get any + * timer interrupts while we are messing with the counter. */ -static void avr32_hpt_init(unsigned int count) +int __weak avr32_hpt_start(void) { - count = sysreg_read(COUNT) - count; + u32 count = sysreg_read(COUNT); expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy; sysreg_write(COUNT, expirelo - cycles_per_jiffy); sysreg_write(COMPARE, expirelo); sysreg_write(COUNT, count); + + return 0; } /* @@ -115,26 +150,18 @@ static void avr32_hpt_init(unsigned int count) * * In UP mode, it is invoked from the (global) timer_interrupt. */ -static void local_timer_interrupt(int irq, void *dev_id) +void local_timer_interrupt(int irq, void *dev_id) { if (current->pid) profile_tick(CPU_PROFILING); update_process_times(user_mode(get_irq_regs())); } -static irqreturn_t -timer_interrupt(int irq, void *dev_id) +irqreturn_t __weak timer_interrupt(int irq, void *dev_id) { - unsigned int count; - /* ack timer interrupt and try to set next interrupt */ - count = avr32_hpt_read(); avr32_timer_ack(); - /* Update timerhi/timerlo for intra-jiffy calibration */ - timerhi += count < timerlo; /* Wrap around */ - timerlo = count; - /* * Call the generic timer interrupt handler */ @@ -153,60 +180,37 @@ timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction timer_irqaction = { - .handler = timer_interrupt, - .flags = IRQF_DISABLED, - .name = "timer", -}; - void __init time_init(void) { - unsigned long mult, shift, count_hz; int ret; + /* + * Make sure we don't get any COMPARE interrupts before we can + * handle them. + */ + sysreg_write(COMPARE, 0); + xtime.tv_sec = rtc_get_time(); xtime.tv_nsec = 0; set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - printk("Before time_init: count=%08lx, compare=%08lx\n", - (unsigned long)sysreg_read(COUNT), - (unsigned long)sysreg_read(COMPARE)); - - count_hz = clk_get_rate(boot_cpu_data.clk); - shift = clocksource_avr32.shift; - mult = clocksource_hz2mult(count_hz, shift); - clocksource_avr32.mult = mult; - - printk("Cycle counter: mult=%lu, shift=%lu\n", mult, shift); - - { - u64 tmp; - - tmp = TICK_NSEC; - tmp <<= shift; - tmp += mult / 2; - do_div(tmp, mult); - - cycles_per_jiffy = tmp; + ret = avr32_hpt_init(); + if (ret) { + pr_debug("timer: failed setup: %d\n", ret); + return; } - /* This sets up the high precision timer for the first interrupt. */ - avr32_hpt_init(avr32_hpt_read()); - - printk("After time_init: count=%08lx, compare=%08lx\n", - (unsigned long)sysreg_read(COUNT), - (unsigned long)sysreg_read(COMPARE)); - ret = clocksource_register(&clocksource_avr32); if (ret) - printk(KERN_ERR - "timer: could not register clocksource: %d\n", ret); + pr_debug("timer: could not register clocksource: %d\n", ret); - ret = setup_irq(0, &timer_irqaction); - if (ret) - printk("timer: could not request IRQ 0: %d\n", ret); + ret = avr32_hpt_start(); + if (ret) { + pr_debug("timer: failed starting: %d\n", ret); + return; + } } static struct sysdev_class timer_class = { diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index adc01a12d15..4f0382d8483 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -5,158 +5,25 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#undef DEBUG -#include <linux/sched.h> + +#include <linux/bug.h> #include <linux/init.h> -#include <linux/module.h> #include <linux/kallsyms.h> +#include <linux/module.h> #include <linux/notifier.h> +#include <linux/sched.h> +#include <linux/uaccess.h> -#include <asm/traps.h> -#include <asm/sysreg.h> #include <asm/addrspace.h> -#include <asm/ocd.h> #include <asm/mmu_context.h> -#include <asm/uaccess.h> - -static void dump_mem(const char *str, unsigned long bottom, unsigned long top) -{ - unsigned long p; - int i; - - printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top); - - for (p = bottom & ~31; p < top; ) { - printk("%04lx: ", p & 0xffff); - - for (i = 0; i < 8; i++, p += 4) { - unsigned int val; - - if (p < bottom || p >= top) - printk(" "); - else { - if (__get_user(val, (unsigned int __user *)p)) { - printk("\n"); - goto out; - } - printk("%08x ", val); - } - } - printk("\n"); - } - -out: - return; -} - -static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p) -{ - return (p > (unsigned long)tinfo) - && (p < (unsigned long)tinfo + THREAD_SIZE - 3); -} - -#ifdef CONFIG_FRAME_POINTER -static inline void __show_trace(struct task_struct *tsk, unsigned long *sp, - struct pt_regs *regs) -{ - unsigned long lr, fp; - struct thread_info *tinfo; - - tinfo = (struct thread_info *) - ((unsigned long)sp & ~(THREAD_SIZE - 1)); - - if (regs) - fp = regs->r7; - else if (tsk == current) - asm("mov %0, r7" : "=r"(fp)); - else - fp = tsk->thread.cpu_context.r7; - - /* - * Walk the stack as long as the frame pointer (a) is within - * the kernel stack of the task, and (b) it doesn't move - * downwards. - */ - while (valid_stack_ptr(tinfo, fp)) { - unsigned long new_fp; - - lr = *(unsigned long *)fp; - printk(" [<%08lx>] ", lr); - print_symbol("%s\n", lr); - - new_fp = *(unsigned long *)(fp + 4); - if (new_fp <= fp) - break; - fp = new_fp; - } - printk("\n"); -} -#else -static inline void __show_trace(struct task_struct *tsk, unsigned long *sp, - struct pt_regs *regs) -{ - unsigned long addr; - - while (!kstack_end(sp)) { - addr = *sp++; - if (kernel_text_address(addr)) { - printk(" [<%08lx>] ", addr); - print_symbol("%s\n", addr); - } - } -} -#endif - -void show_trace(struct task_struct *tsk, unsigned long *sp, - struct pt_regs *regs) -{ - if (regs && - (((regs->sr & MODE_MASK) == MODE_EXCEPTION) || - ((regs->sr & MODE_MASK) == MODE_USER))) - return; - - printk ("Call trace:"); -#ifdef CONFIG_KALLSYMS - printk("\n"); -#endif - - __show_trace(tsk, sp, regs); - printk("\n"); -} - -void show_stack(struct task_struct *tsk, unsigned long *sp) -{ - unsigned long stack; - - if (!tsk) - tsk = current; - if (sp == 0) { - if (tsk == current) { - register unsigned long *real_sp __asm__("sp"); - sp = real_sp; - } else { - sp = (unsigned long *)tsk->thread.cpu_context.ksp; - } - } - - stack = (unsigned long)sp; - dump_mem("Stack: ", stack, - THREAD_SIZE + (unsigned long)tsk->thread_info); - show_trace(tsk, sp, NULL); -} - -void dump_stack(void) -{ - show_stack(NULL, NULL); -} -EXPORT_SYMBOL(dump_stack); +#include <asm/ocd.h> +#include <asm/sysreg.h> +#include <asm/traps.h> ATOMIC_NOTIFIER_HEAD(avr32_die_chain); int register_die_notifier(struct notifier_block *nb) { - pr_debug("register_die_notifier: %p\n", nb); - return atomic_notifier_chain_register(&avr32_die_chain, nb); } EXPORT_SYMBOL(register_die_notifier); @@ -169,93 +36,103 @@ EXPORT_SYMBOL(unregister_die_notifier); static DEFINE_SPINLOCK(die_lock); -void __die(const char *str, struct pt_regs *regs, unsigned long err, - const char *file, const char *func, unsigned long line) +void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) { - struct task_struct *tsk = current; static int die_counter; console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); - printk(KERN_ALERT "%s", str); - if (file && func) - printk(" in %s:%s, line %ld", file, func, line); - printk("[#%d]:\n", ++die_counter); - print_modules(); - show_regs(regs); - printk("Process %s (pid: %d, stack limit = 0x%p)\n", - tsk->comm, tsk->pid, tsk->thread_info + 1); - - if (!user_mode(regs) || in_interrupt()) { - dump_mem("Stack: ", regs->sp, - THREAD_SIZE + (unsigned long)tsk->thread_info); + printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n" KERN_EMERG, + str, err, ++die_counter); +#ifdef CONFIG_PREEMPT + printk("PREEMPT "); +#endif +#ifdef CONFIG_FRAME_POINTER + printk("FRAME_POINTER "); +#endif + if (current_cpu_data.features & AVR32_FEATURE_OCD) { + unsigned long did = __mfdr(DBGREG_DID); + printk("chip: 0x%03lx:0x%04lx rev %lu\n", + (did >> 1) & 0x7ff, + (did >> 12) & 0x7fff, + (did >> 28) & 0xf); + } else { + printk("cpu: arch %u r%u / core %u r%u\n", + current_cpu_data.arch_type, + current_cpu_data.arch_revision, + current_cpu_data.cpu_type, + current_cpu_data.cpu_revision); } + print_modules(); + show_regs_log_lvl(regs, KERN_EMERG); + show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG); bust_spinlocks(0); spin_unlock_irq(&die_lock); - do_exit(SIGSEGV); + + if (in_interrupt()) + panic("Fatal exception in interrupt"); + + if (panic_on_oops) + panic("Fatal exception"); + + do_exit(err); } -void __die_if_kernel(const char *str, struct pt_regs *regs, unsigned long err, - const char *file, const char *func, unsigned long line) +void _exception(long signr, struct pt_regs *regs, int code, + unsigned long addr) { + siginfo_t info; + if (!user_mode(regs)) - __die(str, regs, err, file, func, line); -} + die("Unhandled exception in kernel mode", regs, signr); + + memset(&info, 0, sizeof(info)); + info.si_signo = signr; + info.si_code = code; + info.si_addr = (void __user *)addr; + force_sig_info(signr, &info, current); -asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs) -{ -#ifdef CONFIG_SUBARCH_AVR32B /* - * The exception entry always saves RSR_EX. For NMI, this is - * wrong; it should be RSR_NMI + * Init gets no signals that it doesn't have a handler for. + * That's all very well, but if it has caused a synchronous + * exception and we ignore the resulting signal, it will just + * generate the same exception over and over again and we get + * nowhere. Better to kill it and let the kernel panic. */ - regs->sr = sysreg_read(RSR_NMI); -#endif + if (is_init(current)) { + __sighandler_t handler; + + spin_lock_irq(¤t->sighand->siglock); + handler = current->sighand->action[signr-1].sa.sa_handler; + spin_unlock_irq(¤t->sighand->siglock); + if (handler == SIG_DFL) { + /* init has generated a synchronous exception + and it doesn't have a handler for the signal */ + printk(KERN_CRIT "init has generated signal %ld " + "but has no handler for it\n", signr); + do_exit(signr); + } + } +} - printk("NMI taken!!!!\n"); - die("NMI", regs, ecr); - BUG(); +asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs) +{ + printk(KERN_ALERT "Got Non-Maskable Interrupt, dumping regs\n"); + show_regs_log_lvl(regs, KERN_ALERT); + show_stack_log_lvl(current, regs->sp, regs, KERN_ALERT); } asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs) { - printk("Unable to handle critical exception %lu at pc = %08lx!\n", - ecr, regs->pc); - die("Oops", regs, ecr); - BUG(); + die("Critical exception", regs, SIGKILL); } asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs) { - siginfo_t info; - - die_if_kernel("Oops: Address exception in kernel mode", regs, ecr); - -#ifdef DEBUG - if (ecr == ECR_ADDR_ALIGN_X) - pr_debug("Instruction Address Exception at pc = %08lx\n", - regs->pc); - else if (ecr == ECR_ADDR_ALIGN_R) - pr_debug("Data Address Exception (Read) at pc = %08lx\n", - regs->pc); - else if (ecr == ECR_ADDR_ALIGN_W) - pr_debug("Data Address Exception (Write) at pc = %08lx\n", - regs->pc); - else - BUG(); - - show_regs(regs); -#endif - - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRALN; - info.si_addr = (void __user *)regs->pc; - - force_sig_info(SIGBUS, &info, current); + _exception(SIGBUS, regs, BUS_ADRALN, regs->pc); } /* This way of handling undefined instructions is stolen from ARM */ @@ -280,7 +157,8 @@ static int do_cop_absent(u32 insn) { int cop_nr; u32 cpucr; - if ( (insn & 0xfdf00000) == 0xf1900000 ) + + if ((insn & 0xfdf00000) == 0xf1900000) /* LDC0 */ cop_nr = 0; else @@ -292,136 +170,91 @@ static int do_cop_absent(u32 insn) sysreg_write(CPUCR, cpucr); cpucr = sysreg_read(CPUCR); - if ( !(cpucr & (1 << (24 + cop_nr))) ){ - printk("Coprocessor #%i not found!\n", cop_nr); - return -1; - } + if (!(cpucr & (1 << (24 + cop_nr)))) + return -ENODEV; return 0; } -#ifdef CONFIG_BUG -#ifdef CONFIG_DEBUG_BUGVERBOSE -static inline void do_bug_verbose(struct pt_regs *regs, u32 insn) -{ - char *file; - u16 line; - char c; - - if (__get_user(line, (u16 __user *)(regs->pc + 2))) - return; - if (__get_user(file, (char * __user *)(regs->pc + 4)) - || (unsigned long)file < PAGE_OFFSET - || __get_user(c, file)) - file = "<bad filename>"; - - printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line); -} -#else -static inline void do_bug_verbose(struct pt_regs *regs, u32 insn) +int is_valid_bugaddr(unsigned long pc) { + unsigned short opcode; + + if (pc < PAGE_OFFSET) + return 0; + if (probe_kernel_address((u16 *)pc, opcode)) + return 0; + return opcode == AVR32_BUG_OPCODE; } -#endif -#endif asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs) { u32 insn; struct undef_hook *hook; - siginfo_t info; void __user *pc; + long code; - if (!user_mode(regs)) - goto kernel_trap; + if (!user_mode(regs) && (ecr == ECR_ILLEGAL_OPCODE)) { + enum bug_trap_type type; + + type = report_bug(regs->pc); + switch (type) { + case BUG_TRAP_TYPE_NONE: + break; + case BUG_TRAP_TYPE_WARN: + regs->pc += 2; + return; + case BUG_TRAP_TYPE_BUG: + die("Kernel BUG", regs, SIGKILL); + } + } local_irq_enable(); - pc = (void __user *)instruction_pointer(regs); - if (__get_user(insn, (u32 __user *)pc)) - goto invalid_area; + if (user_mode(regs)) { + pc = (void __user *)instruction_pointer(regs); + if (get_user(insn, (u32 __user *)pc)) + goto invalid_area; - if (ecr == ECR_COPROC_ABSENT) { - if (do_cop_absent(insn) == 0) + if (ecr == ECR_COPROC_ABSENT && !do_cop_absent(insn)) return; - } - spin_lock_irq(&undef_lock); - list_for_each_entry(hook, &undef_hook, node) { - if ((insn & hook->insn_mask) == hook->insn_val) { - if (hook->fn(regs, insn) == 0) { - spin_unlock_irq(&undef_lock); - return; + spin_lock_irq(&undef_lock); + list_for_each_entry(hook, &undef_hook, node) { + if ((insn & hook->insn_mask) == hook->insn_val) { + if (hook->fn(regs, insn) == 0) { + spin_unlock_irq(&undef_lock); + return; + } } } + spin_unlock_irq(&undef_lock); } - spin_unlock_irq(&undef_lock); - -invalid_area: -#ifdef DEBUG - printk("Illegal instruction at pc = %08lx\n", regs->pc); - if (regs->pc < TASK_SIZE) { - unsigned long ptbr, pgd, pte, *p; - - ptbr = sysreg_read(PTBR); - p = (unsigned long *)ptbr; - pgd = p[regs->pc >> 22]; - p = (unsigned long *)((pgd & 0x1ffff000) | 0x80000000); - pte = p[(regs->pc >> 12) & 0x3ff]; - printk("page table: 0x%08lx -> 0x%08lx -> 0x%08lx\n", ptbr, pgd, pte); - } -#endif - - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_addr = (void __user *)regs->pc; switch (ecr) { - case ECR_ILLEGAL_OPCODE: - case ECR_UNIMPL_INSTRUCTION: - info.si_code = ILL_ILLOPC; - break; case ECR_PRIVILEGE_VIOLATION: - info.si_code = ILL_PRVOPC; + code = ILL_PRVOPC; break; case ECR_COPROC_ABSENT: - info.si_code = ILL_COPROC; + code = ILL_COPROC; break; default: - BUG(); + code = ILL_ILLOPC; + break; } - force_sig_info(SIGILL, &info, current); + _exception(SIGILL, regs, code, regs->pc); return; -kernel_trap: -#ifdef CONFIG_BUG - if (__kernel_text_address(instruction_pointer(regs))) { - insn = *(u16 *)instruction_pointer(regs); - if (insn == AVR32_BUG_OPCODE) { - do_bug_verbose(regs, insn); - die("Kernel BUG", regs, 0); - return; - } - } -#endif - - die("Oops: Illegal instruction in kernel code", regs, ecr); +invalid_area: + _exception(SIGSEGV, regs, SEGV_MAPERR, regs->pc); } asmlinkage void do_fpe(unsigned long ecr, struct pt_regs *regs) { - siginfo_t info; - - printk("Floating-point exception at pc = %08lx\n", regs->pc); - - /* We have no FPU... */ - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_addr = (void __user *)regs->pc; - info.si_code = ILL_COPROC; - - force_sig_info(SIGILL, &info, current); + /* We have no FPU yet */ + _exception(SIGILL, regs, ILL_COPROC, regs->pc); } diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.c index ef13b7c7893..7ad20cfb48a 100644 --- a/arch/avr32/kernel/vmlinux.lds.c +++ b/arch/avr32/kernel/vmlinux.lds.c @@ -26,6 +26,12 @@ SECTIONS _sinittext = .; *(.text.reset) *(.init.text) + /* + * .exit.text is discarded at runtime, not + * link time, to deal with references from + * __bug_table + */ + *(.exit.text) _einittext = .; . = ALIGN(4); __tagtable_begin = .; @@ -86,6 +92,8 @@ SECTIONS __stop___ex_table = .; } + BUG_TABLE + RODATA . = ALIGN(8192); @@ -126,7 +134,6 @@ SECTIONS * thrown away, as cleanup code is never called unless it's a module. */ /DISCARD/ : { - *(.exit.text) *(.exit.data) *(.exitcall.exit) } diff --git a/arch/avr32/mach-at32ap/Kconfig b/arch/avr32/mach-at32ap/Kconfig new file mode 100644 index 00000000000..eb307838457 --- /dev/null +++ b/arch/avr32/mach-at32ap/Kconfig @@ -0,0 +1,31 @@ +if PLATFORM_AT32AP + +menu "Atmel AVR32 AP options" + +choice + prompt "AT32AP7000 static memory bus width" + depends on CPU_AT32AP7000 + default AP7000_16_BIT_SMC + help + Define the width of the AP7000 external static memory interface. + This is used to determine how to mangle the address and/or data + when doing little-endian port access. + + The current code can only support a single external memory bus + width for all chip selects, excluding the flash (which is using + raw access and is thus not affected by any of this.) + +config AP7000_32_BIT_SMC + bool "32 bit" + +config AP7000_16_BIT_SMC + bool "16 bit" + +config AP7000_8_BIT_SMC + bool "8 bit" + +endchoice + +endmenu + +endif # PLATFORM_AT32AP diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile index b21bea9af8b..f1d395724ac 100644 --- a/arch/avr32/mach-at32ap/Makefile +++ b/arch/avr32/mach-at32ap/Makefile @@ -1,2 +1,3 @@ obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o +obj-$(CONFIG_CPU_AT32AP7000) += time-tc.o diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 472703f90c2..56db45b99a0 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -18,6 +18,7 @@ #include <asm/arch/sm.h> #include "clock.h" +#include "hmatrix.h" #include "pio.h" #include "sm.h" @@ -416,7 +417,15 @@ struct platform_device at32_sm_device = { .resource = sm_resource, .num_resources = ARRAY_SIZE(sm_resource), }; -DEV_CLK(pclk, at32_sm, pbb, 0); +static struct clk at32_sm_pclk = { + .name = "pclk", + .dev = &at32_sm_device.dev, + .parent = &pbb_clk, + .mode = pbb_clk_mode, + .get_rate = pbb_clk_get_rate, + .users = 1, + .index = 0, +}; static struct resource intc0_resource[] = { PBMEM(0xfff00400), @@ -442,6 +451,7 @@ static struct clk hramc_clk = { .mode = hsb_clk_mode, .get_rate = hsb_clk_get_rate, .users = 1, + .index = 3, }; static struct resource smc0_resource[] = { @@ -467,6 +477,57 @@ static struct clk pico_clk = { }; /* -------------------------------------------------------------------- + * HMATRIX + * -------------------------------------------------------------------- */ + +static struct clk hmatrix_clk = { + .name = "hmatrix_clk", + .parent = &pbb_clk, + .mode = pbb_clk_mode, + .get_rate = pbb_clk_get_rate, + .index = 2, + .users = 1, +}; +#define HMATRIX_BASE ((void __iomem *)0xfff00800) + +#define hmatrix_readl(reg) \ + __raw_readl((HMATRIX_BASE) + HMATRIX_##reg) +#define hmatrix_writel(reg,value) \ + __raw_writel((value), (HMATRIX_BASE) + HMATRIX_##reg) + +/* + * Set bits in the HMATRIX Special Function Register (SFR) used by the + * External Bus Interface (EBI). This can be used to enable special + * features like CompactFlash support, NAND Flash support, etc. on + * certain chipselects. + */ +static inline void set_ebi_sfr_bits(u32 mask) +{ + u32 sfr; + + clk_enable(&hmatrix_clk); + sfr = hmatrix_readl(SFR4); + sfr |= mask; + hmatrix_writel(SFR4, sfr); + clk_disable(&hmatrix_clk); +} + +/* -------------------------------------------------------------------- + * System Timer/Counter (TC) + * -------------------------------------------------------------------- */ +static struct resource at32_systc0_resource[] = { + PBMEM(0xfff00c00), + IRQ(22), +}; +struct platform_device at32_systc0_device = { + .name = "systc", + .id = 0, + .resource = at32_systc0_resource, + .num_resources = ARRAY_SIZE(at32_systc0_resource), +}; +DEV_CLK(pclk, at32_systc0, pbb, 3); + +/* -------------------------------------------------------------------- * PIO * -------------------------------------------------------------------- */ @@ -514,6 +575,8 @@ void __init at32_add_system_devices(void) platform_device_register(&smc0_device); platform_device_register(&pdc_device); + platform_device_register(&at32_systc0_device); + platform_device_register(&pio0_device); platform_device_register(&pio1_device); platform_device_register(&pio2_device); @@ -950,6 +1013,7 @@ struct clk *at32_clock_list[] = { &pbb_clk, &at32_sm_pclk, &at32_intc0_pclk, + &hmatrix_clk, &ebi_clk, &hramc_clk, &smc0_pclk, @@ -962,6 +1026,7 @@ struct clk *at32_clock_list[] = { &pio2_mck, &pio3_mck, &pio4_mck, + &at32_systc0_pclk, &atmel_usart0_usart, &atmel_usart1_usart, &atmel_usart2_usart, @@ -1024,6 +1089,9 @@ void __init at32_clock_init(void) for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) { struct clk *clk = at32_clock_list[i]; + if (clk->users == 0) + continue; + if (clk->mode == &cpu_clk_mode) cpu_mask |= 1 << clk->index; else if (clk->mode == &hsb_clk_mode) diff --git a/arch/avr32/mach-at32ap/hmatrix.h b/arch/avr32/mach-at32ap/hmatrix.h new file mode 100644 index 00000000000..d10bfb60d68 --- /dev/null +++ b/arch/avr32/mach-at32ap/hmatrix.h @@ -0,0 +1,182 @@ +/* + * Register definitions for High-Speed Bus Matrix + */ +#ifndef __HMATRIX_H +#define __HMATRIX_H + +/* HMATRIX register offsets */ +#define HMATRIX_MCFG0 0x0000 +#define HMATRIX_MCFG1 0x0004 +#define HMATRIX_MCFG2 0x0008 +#define HMATRIX_MCFG3 0x000c +#define HMATRIX_MCFG4 0x0010 +#define HMATRIX_MCFG5 0x0014 +#define HMATRIX_MCFG6 0x0018 +#define HMATRIX_MCFG7 0x001c +#define HMATRIX_MCFG8 0x0020 +#define HMATRIX_MCFG9 0x0024 +#define HMATRIX_MCFG10 0x0028 +#define HMATRIX_MCFG11 0x002c +#define HMATRIX_MCFG12 0x0030 +#define HMATRIX_MCFG13 0x0034 +#define HMATRIX_MCFG14 0x0038 +#define HMATRIX_MCFG15 0x003c +#define HMATRIX_SCFG0 0x0040 +#define HMATRIX_SCFG1 0x0044 +#define HMATRIX_SCFG2 0x0048 +#define HMATRIX_SCFG3 0x004c +#define HMATRIX_SCFG4 0x0050 +#define HMATRIX_SCFG5 0x0054 +#define HMATRIX_SCFG6 0x0058 +#define HMATRIX_SCFG7 0x005c +#define HMATRIX_SCFG8 0x0060 +#define HMATRIX_SCFG9 0x0064 +#define HMATRIX_SCFG10 0x0068 +#define HMATRIX_SCFG11 0x006c +#define HMATRIX_SCFG12 0x0070 +#define HMATRIX_SCFG13 0x0074 +#define HMATRIX_SCFG14 0x0078 +#define HMATRIX_SCFG15 0x007c +#define HMATRIX_PRAS0 0x0080 +#define HMATRIX_PRBS0 0x0084 +#define HMATRIX_PRAS1 0x0088 +#define HMATRIX_PRBS1 0x008c +#define HMATRIX_PRAS2 0x0090 +#define HMATRIX_PRBS2 0x0094 +#define HMATRIX_PRAS3 0x0098 +#define HMATRIX_PRBS3 0x009c +#define HMATRIX_PRAS4 0x00a0 +#define HMATRIX_PRBS4 0x00a4 +#define HMATRIX_PRAS5 0x00a8 +#define HMATRIX_PRBS5 0x00ac +#define HMATRIX_PRAS6 0x00b0 +#define HMATRIX_PRBS6 0x00b4 +#define HMATRIX_PRAS7 0x00b8 +#define HMATRIX_PRBS7 0x00bc +#define HMATRIX_PRAS8 0x00c0 +#define HMATRIX_PRBS8 0x00c4 +#define HMATRIX_PRAS9 0x00c8 +#define HMATRIX_PRBS9 0x00cc +#define HMATRIX_PRAS10 0x00d0 +#define HMATRIX_PRBS10 0x00d4 +#define HMATRIX_PRAS11 0x00d8 +#define HMATRIX_PRBS11 0x00dc +#define HMATRIX_PRAS12 0x00e0 +#define HMATRIX_PRBS12 0x00e4 +#define HMATRIX_PRAS13 0x00e8 +#define HMATRIX_PRBS13 0x00ec +#define HMATRIX_PRAS14 0x00f0 +#define HMATRIX_PRBS14 0x00f4 +#define HMATRIX_PRAS15 0x00f8 +#define HMATRIX_PRBS15 0x00fc +#define HMATRIX_MRCR 0x0100 +#define HMATRIX_SFR0 0x0110 +#define HMATRIX_SFR1 0x0114 +#define HMATRIX_SFR2 0x0118 +#define HMATRIX_SFR3 0x011c +#define HMATRIX_SFR4 0x0120 +#define HMATRIX_SFR5 0x0124 +#define HMATRIX_SFR6 0x0128 +#define HMATRIX_SFR7 0x012c +#define HMATRIX_SFR8 0x0130 +#define HMATRIX_SFR9 0x0134 +#define HMATRIX_SFR10 0x0138 +#define HMATRIX_SFR11 0x013c +#define HMATRIX_SFR12 0x0140 +#define HMATRIX_SFR13 0x0144 +#define HMATRIX_SFR14 0x0148 +#define HMATRIX_SFR15 0x014c + +/* Bitfields in MCFGx */ +#define HMATRIX_ULBT_OFFSET 0 +#define HMATRIX_ULBT_SIZE 3 + +/* Bitfields in SCFGx */ +#define HMATRIX_SLOT_CYCLE_OFFSET 0 +#define HMATRIX_SLOT_CYCLE_SIZE 8 +#define HMATRIX_DEFMSTR_TYPE_OFFSET 16 +#define HMATRIX_DEFMSTR_TYPE_SIZE 2 +#define HMATRIX_FIXED_DEFMSTR_OFFSET 18 +#define HMATRIX_FIXED_DEFMSTR_SIZE 4 +#define HMATRIX_ARBT_OFFSET 24 +#define HMATRIX_ARBT_SIZE 2 + +/* Bitfields in PRASx */ +#define HMATRIX_M0PR_OFFSET 0 +#define HMATRIX_M0PR_SIZE 4 +#define HMATRIX_M1PR_OFFSET 4 +#define HMATRIX_M1PR_SIZE 4 +#define HMATRIX_M2PR_OFFSET 8 +#define HMATRIX_M2PR_SIZE 4 +#define HMATRIX_M3PR_OFFSET 12 +#define HMATRIX_M3PR_SIZE 4 +#define HMATRIX_M4PR_OFFSET 16 +#define HMATRIX_M4PR_SIZE 4 +#define HMATRIX_M5PR_OFFSET 20 +#define HMATRIX_M5PR_SIZE 4 +#define HMATRIX_M6PR_OFFSET 24 +#define HMATRIX_M6PR_SIZE 4 +#define HMATRIX_M7PR_OFFSET 28 +#define HMATRIX_M7PR_SIZE 4 + +/* Bitfields in PRBSx */ +#define HMATRIX_M8PR_OFFSET 0 +#define HMATRIX_M8PR_SIZE 4 +#define HMATRIX_M9PR_OFFSET 4 +#define HMATRIX_M9PR_SIZE 4 +#define HMATRIX_M10PR_OFFSET 8 +#define HMATRIX_M10PR_SIZE 4 +#define HMATRIX_M11PR_OFFSET 12 +#define HMATRIX_M11PR_SIZE 4 +#define HMATRIX_M12PR_OFFSET 16 +#define HMATRIX_M12PR_SIZE 4 +#define HMATRIX_M13PR_OFFSET 20 +#define HMATRIX_M13PR_SIZE 4 +#define HMATRIX_M14PR_OFFSET 24 +#define HMATRIX_M14PR_SIZE 4 +#define HMATRIX_M15PR_OFFSET 28 +#define HMATRIX_M15PR_SIZE 4 + +/* Bitfields in SFR4 */ +#define HMATRIX_CS1A_OFFSET 1 +#define HMATRIX_CS1A_SIZE 1 +#define HMATRIX_CS3A_OFFSET 3 +#define HMATRIX_CS3A_SIZE 1 +#define HMATRIX_CS4A_OFFSET 4 +#define HMATRIX_CS4A_SIZE 1 +#define HMATRIX_CS5A_OFFSET 5 +#define HMATRIX_CS5A_SIZE 1 +#define HMATRIX_DBPUC_OFFSET 8 +#define HMATRIX_DBPUC_SIZE 1 + +/* Constants for ULBT */ +#define HMATRIX_ULBT_INFINITE 0 +#define HMATRIX_ULBT_SINGLE 1 +#define HMATRIX_ULBT_FOUR_BEAT 2 +#define HMATRIX_ULBT_EIGHT_BEAT 3 +#define HMATRIX_ULBT_SIXTEEN_BEAT 4 + +/* Constants for DEFMSTR_TYPE */ +#define HMATRIX_DEFMSTR_TYPE_NO_DEFAULT 0 +#define HMATRIX_DEFMSTR_TYPE_LAST_DEFAULT 1 +#define HMATRIX_DEFMSTR_TYPE_FIXED_DEFAULT 2 + +/* Constants for ARBT */ +#define HMATRIX_ARBT_ROUND_ROBIN 0 +#define HMATRIX_ARBT_FIXED_PRIORITY 1 + +/* Bit manipulation macros */ +#define HMATRIX_BIT(name) \ + (1 << HMATRIX_##name##_OFFSET) +#define HMATRIX_BF(name,value) \ + (((value) & ((1 << HMATRIX_##name##_SIZE) - 1)) \ + << HMATRIX_##name##_OFFSET) +#define HMATRIX_BFEXT(name,value) \ + (((value) >> HMATRIX_##name##_OFFSET) \ + & ((1 << HMATRIX_##name##_SIZE) - 1)) +#define HMATRIX_BFINS(name,value,old) \ + (((old) & ~(((1 << HMATRIX_##name##_SIZE) - 1) \ + << HMATRIX_##name##_OFFSET)) \ + | HMATRIX_BF(name,value)) + +#endif /* __HMATRIX_H */ diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c index 7691721928a..5e22a750632 100644 --- a/arch/avr32/mach-at32ap/hsmc.c +++ b/arch/avr32/mach-at32ap/hsmc.c @@ -75,12 +75,35 @@ int smc_set_configuration(int cs, const struct smc_config *config) return -EINVAL; } + switch (config->nwait_mode) { + case 0: + mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_DISABLED); + break; + case 1: + mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_RESERVED); + break; + case 2: + mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_FROZEN); + break; + case 3: + mode |= HSMC_BF(EXNW_MODE, HSMC_EXNW_MODE_READY); + break; + default: + return -EINVAL; + } + + if (config->tdf_cycles) { + mode |= HSMC_BF(TDF_CYCLES, config->tdf_cycles); + } + if (config->nrd_controlled) mode |= HSMC_BIT(READ_MODE); if (config->nwe_controlled) mode |= HSMC_BIT(WRITE_MODE); if (config->byte_write) mode |= HSMC_BIT(BAT); + if (config->tdf_mode) + mode |= HSMC_BIT(TDF_MODE); pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n", cs, setup, pulse, cycle, mode); diff --git a/arch/avr32/mach-at32ap/time-tc.c b/arch/avr32/mach-at32ap/time-tc.c new file mode 100644 index 00000000000..e3070bdd4bb --- /dev/null +++ b/arch/avr32/mach-at32ap/time-tc.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * Based on MIPS implementation arch/mips/kernel/time.c + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/clk.h> +#include <linux/clocksource.h> +#include <linux/time.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/kernel_stat.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/profile.h> +#include <linux/sysdev.h> +#include <linux/err.h> + +#include <asm/div64.h> +#include <asm/sysreg.h> +#include <asm/io.h> +#include <asm/sections.h> + +#include <asm/arch/time.h> + +/* how many counter cycles in a jiffy? */ +static u32 cycles_per_jiffy; + +/* the count value for the next timer interrupt */ +static u32 expirelo; + +/* the I/O registers of the TC module */ +static void __iomem *ioregs; + +cycle_t read_cycle_count(void) +{ + return (cycle_t)timer_read(ioregs, 0, CV); +} + +struct clocksource clocksource_avr32 = { + .name = "avr32", + .rating = 342, + .read = read_cycle_count, + .mask = CLOCKSOURCE_MASK(16), + .shift = 16, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void avr32_timer_ack(void) +{ + u16 count = expirelo; + + /* Ack this timer interrupt and set the next one, use a u16 + * variable so it will wrap around correctly */ + count += cycles_per_jiffy; + expirelo = count; + timer_write(ioregs, 0, RC, expirelo); + + /* Check to see if we have missed any timer interrupts */ + count = timer_read(ioregs, 0, CV); + if ((count - expirelo) < 0x7fff) { + expirelo = count + cycles_per_jiffy; + timer_write(ioregs, 0, RC, expirelo); + } +} + +u32 avr32_hpt_read(void) +{ + return timer_read(ioregs, 0, CV); +} + +static int avr32_timer_calc_div_and_set_jiffies(struct clk *pclk) +{ + unsigned int cycles_max = (clocksource_avr32.mask + 1) / 2; + unsigned int divs[] = { 4, 8, 16, 32 }; + int divs_size = sizeof(divs) / sizeof(*divs); + int i = 0; + unsigned long count_hz; + unsigned long shift; + unsigned long mult; + int clock_div = -1; + u64 tmp; + + shift = clocksource_avr32.shift; + + do { + count_hz = clk_get_rate(pclk) / divs[i]; + mult = clocksource_hz2mult(count_hz, shift); + clocksource_avr32.mult = mult; + + tmp = TICK_NSEC; + tmp <<= shift; + tmp += mult / 2; + do_div(tmp, mult); + + cycles_per_jiffy = tmp; + } while (cycles_per_jiffy > cycles_max && ++i < divs_size); + + clock_div = i + 1; + + if (clock_div > divs_size) { + pr_debug("timer: could not calculate clock divider\n"); + return -EFAULT; + } + + /* Set the clock divider */ + timer_write(ioregs, 0, CMR, TIMER_BF(CMR_TCCLKS, clock_div)); + + return 0; +} + +int avr32_hpt_init(unsigned int count) +{ + struct resource *regs; + struct clk *pclk; + int irq = -1; + int ret = 0; + + ret = -ENXIO; + + irq = platform_get_irq(&at32_systc0_device, 0); + if (irq < 0) { + pr_debug("timer: could not get irq\n"); + goto out_error; + } + + pclk = clk_get(&at32_systc0_device.dev, "pclk"); + if (IS_ERR(pclk)) { + pr_debug("timer: could not get clk: %ld\n", PTR_ERR(pclk)); + goto out_error; + } + clk_enable(pclk); + + regs = platform_get_resource(&at32_systc0_device, IORESOURCE_MEM, 0); + if (!regs) { + pr_debug("timer: could not get resource\n"); + goto out_error_clk; + } + + ioregs = ioremap(regs->start, regs->end - regs->start + 1); + if (!ioregs) { + pr_debug("timer: could not get ioregs\n"); + goto out_error_clk; + } + + ret = avr32_timer_calc_div_and_set_jiffies(pclk); + if (ret) + goto out_error_io; + + ret = setup_irq(irq, &timer_irqaction); + if (ret) { + pr_debug("timer: could not request irq %d: %d\n", + irq, ret); + goto out_error_io; + } + + expirelo = (timer_read(ioregs, 0, CV) / cycles_per_jiffy + 1) + * cycles_per_jiffy; + + /* Enable clock and interrupts on RC compare */ + timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_CLKEN)); + timer_write(ioregs, 0, IER, TIMER_BIT(IER_CPCS)); + /* Set cycles to first interrupt */ + timer_write(ioregs, 0, RC, expirelo); + + printk(KERN_INFO "timer: AT32AP system timer/counter at 0x%p irq %d\n", + ioregs, irq); + + return 0; + +out_error_io: + iounmap(ioregs); +out_error_clk: + clk_put(pclk); +out_error: + return ret; +} + +int avr32_hpt_start(void) +{ + timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_SWTRG)); + return 0; +} + +irqreturn_t timer_interrupt(int irq, void *dev_id) +{ + unsigned int sr = timer_read(ioregs, 0, SR); + + if (sr & TIMER_BIT(SR_CPCS)) { + /* ack timer interrupt and try to set next interrupt */ + avr32_timer_ack(); + + /* + * Call the generic timer interrupt handler + */ + write_seqlock(&xtime_lock); + do_timer(1); + write_sequnlock(&xtime_lock); + + /* + * In UP mode, we call local_timer_interrupt() to do profiling + * and process accounting. + * + * SMP is not supported yet. + */ + local_timer_interrupt(irq, dev_id); + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c index 678557260a3..146ebdbdc30 100644 --- a/arch/avr32/mm/fault.c +++ b/arch/avr32/mm/fault.c @@ -16,26 +16,8 @@ #include <asm/kdebug.h> #include <asm/mmu_context.h> #include <asm/sysreg.h> -#include <asm/uaccess.h> #include <asm/tlb.h> - -#ifdef DEBUG -static void dump_code(unsigned long pc) -{ - char *p = (char *)pc; - char val; - int i; - - - printk(KERN_DEBUG "Code:"); - for (i = 0; i < 16; i++) { - if (__get_user(val, p + i)) - break; - printk(" %02x", val); - } - printk("\n"); -} -#endif +#include <asm/uaccess.h> #ifdef CONFIG_KPROBES ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); @@ -68,17 +50,19 @@ static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, } #endif +int exception_trace = 1; + /* * This routine handles page faults. It determines the address and the * problem, and then passes it off to one of the appropriate routines. * * ecr is the Exception Cause Register. Possible values are: - * 5: Page not found (instruction access) * 6: Protection fault (instruction access) - * 12: Page not found (read access) - * 13: Page not found (write access) - * 14: Protection fault (read access) - * 15: Protection fault (write access) + * 15: Protection fault (read access) + * 16: Protection fault (write access) + * 20: Page not found (instruction access) + * 24: Page not found (read access) + * 28: Page not found (write access) */ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) { @@ -88,7 +72,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) const struct exception_table_entry *fixup; unsigned long address; unsigned long page; - int writeaccess = 0; + int writeaccess; + long signr; + int code; if (notify_page_fault(DIE_PAGE_FAULT, regs, ecr, SIGSEGV) == NOTIFY_STOP) @@ -99,6 +85,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) tsk = current; mm = tsk->mm; + signr = SIGSEGV; + code = SEGV_MAPERR; + /* * If we're in an interrupt or have no user context, we must * not take the fault... @@ -125,7 +114,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) * can handle it... */ good_area: - //pr_debug("good area: vm_flags = 0x%lx\n", vma->vm_flags); + code = SEGV_ACCERR; + writeaccess = 0; + switch (ecr) { case ECR_PROTECTION_X: case ECR_TLB_MISS_X: @@ -176,46 +167,24 @@ survive: * map. Fix it, but check if it's kernel or user first... */ bad_area: - pr_debug("Bad area [%s:%u]: addr %08lx, ecr %lu\n", - tsk->comm, tsk->pid, address, ecr); - up_read(&mm->mmap_sem); if (user_mode(regs)) { - /* Hmm...we have to pass address and ecr somehow... */ - /* tsk->thread.address = address; - tsk->thread.error_code = ecr; */ -#ifdef DEBUG - show_regs(regs); - dump_code(regs->pc); - - page = sysreg_read(PTBR); - printk("ptbr = %08lx", page); - if (page) { - page = ((unsigned long *)page)[address >> 22]; - printk(" pgd = %08lx", page); - if (page & _PAGE_PRESENT) { - page &= PAGE_MASK; - address &= 0x003ff000; - page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT]; - printk(" pte = %08lx\n", page); - } - } -#endif - pr_debug("Sending SIGSEGV to PID %d...\n", - tsk->pid); - force_sig(SIGSEGV, tsk); + if (exception_trace) + printk("%s%s[%d]: segfault at %08lx pc %08lx " + "sp %08lx ecr %lu\n", + is_init(tsk) ? KERN_EMERG : KERN_INFO, + tsk->comm, tsk->pid, address, regs->pc, + regs->sp, ecr); + _exception(SIGSEGV, regs, code, address); return; } no_context: - pr_debug("No context\n"); - /* Are we prepared to handle this kernel fault? */ fixup = search_exception_tables(regs->pc); if (fixup) { regs->pc = fixup->fixup; - pr_debug("Found fixup at %08lx\n", fixup->fixup); return; } @@ -230,7 +199,6 @@ no_context: printk(KERN_ALERT "Unable to handle kernel paging request"); printk(" at virtual address %08lx\n", address); - printk(KERN_ALERT "pc = %08lx\n", regs->pc); page = sysreg_read(PTBR); printk(KERN_ALERT "ptbr = %08lx", page); @@ -241,20 +209,20 @@ no_context: page &= PAGE_MASK; address &= 0x003ff000; page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT]; - printk(" pte = %08lx\n", page); + printk(" pte = %08lx", page); } } - die("\nOops", regs, ecr); - do_exit(SIGKILL); + printk("\n"); + die("Kernel access of bad area", regs, signr); + return; /* * We ran out of memory, or some other thing happened to us * that made us unable to handle the page fault gracefully. */ out_of_memory: - printk("Out of memory\n"); up_read(&mm->mmap_sem); - if (current->pid == 1) { + if (is_init(current)) { yield(); down_read(&mm->mmap_sem); goto survive; @@ -267,21 +235,20 @@ out_of_memory: do_sigbus: up_read(&mm->mmap_sem); - /* - * Send a sigbus, regardless of whether we were in kernel or - * user mode. - */ - /* address, error_code, trap_no, ... */ -#ifdef DEBUG - show_regs(regs); - dump_code(regs->pc); -#endif - pr_debug("Sending SIGBUS to PID %d...\n", tsk->pid); - force_sig(SIGBUS, tsk); - /* Kernel mode? Handle exceptions or die */ + signr = SIGBUS; + code = BUS_ADRERR; if (!user_mode(regs)) goto no_context; + + if (exception_trace) + printk("%s%s[%d]: bus error at %08lx pc %08lx " + "sp %08lx ecr %lu\n", + is_init(tsk) ? KERN_EMERG : KERN_INFO, + tsk->comm, tsk->pid, address, regs->pc, + regs->sp, ecr); + + _exception(SIGBUS, regs, BUS_ADRERR, address); } asmlinkage void do_bus_error(unsigned long addr, int write_access, @@ -292,8 +259,7 @@ asmlinkage void do_bus_error(unsigned long addr, int write_access, addr, write_access ? "write" : "read"); printk(KERN_INFO "DTLB dump:\n"); dump_dtlb(); - die("Bus Error", regs, write_access); - do_exit(SIGKILL); + die("Bus Error", regs, SIGKILL); } /* diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c index 70da6894acc..82cf70854b9 100644 --- a/arch/avr32/mm/init.c +++ b/arch/avr32/mm/init.c @@ -10,11 +10,9 @@ #include <linux/mm.h> #include <linux/swap.h> #include <linux/init.h> -#include <linux/initrd.h> #include <linux/mmzone.h> #include <linux/bootmem.h> #include <linux/pagemap.h> -#include <linux/pfn.h> #include <linux/nodemask.h> #include <asm/page.h> @@ -78,242 +76,6 @@ void show_mem(void) printk ("%d pages swap cached\n", cached); } -static void __init print_memory_map(const char *what, - struct tag_mem_range *mem) -{ - printk ("%s:\n", what); - for (; mem; mem = mem->next) { - printk (" %08lx - %08lx\n", - (unsigned long)mem->addr, - (unsigned long)(mem->addr + mem->size)); - } -} - -#define MAX_LOWMEM HIGHMEM_START -#define MAX_LOWMEM_PFN PFN_DOWN(MAX_LOWMEM) - -/* - * Sort a list of memory regions in-place by ascending address. - * - * We're using bubble sort because we only have singly linked lists - * with few elements. - */ -static void __init sort_mem_list(struct tag_mem_range **pmem) -{ - int done; - struct tag_mem_range **a, **b; - - if (!*pmem) - return; - - do { - done = 1; - a = pmem, b = &(*pmem)->next; - while (*b) { - if ((*a)->addr > (*b)->addr) { - struct tag_mem_range *tmp; - tmp = (*b)->next; - (*b)->next = *a; - *a = *b; - *b = tmp; - done = 0; - } - a = &(*a)->next; - b = &(*a)->next; - } - } while (!done); -} - -/* - * Find a free memory region large enough for storing the - * bootmem bitmap. - */ -static unsigned long __init -find_bootmap_pfn(const struct tag_mem_range *mem) -{ - unsigned long bootmap_pages, bootmap_len; - unsigned long node_pages = PFN_UP(mem->size); - unsigned long bootmap_addr = mem->addr; - struct tag_mem_range *reserved = mem_reserved; - struct tag_mem_range *ramdisk = mem_ramdisk; - unsigned long kern_start = virt_to_phys(_stext); - unsigned long kern_end = virt_to_phys(_end); - - bootmap_pages = bootmem_bootmap_pages(node_pages); - bootmap_len = bootmap_pages << PAGE_SHIFT; - - /* - * Find a large enough region without reserved pages for - * storing the bootmem bitmap. We can take advantage of the - * fact that all lists have been sorted. - * - * We have to check explicitly reserved regions as well as the - * kernel image and any RAMDISK images... - * - * Oh, and we have to make sure we don't overwrite the taglist - * since we're going to use it until the bootmem allocator is - * fully up and running. - */ - while (1) { - if ((bootmap_addr < kern_end) && - ((bootmap_addr + bootmap_len) > kern_start)) - bootmap_addr = kern_end; - - while (reserved && - (bootmap_addr >= (reserved->addr + reserved->size))) - reserved = reserved->next; - - if (reserved && - ((bootmap_addr + bootmap_len) >= reserved->addr)) { - bootmap_addr = reserved->addr + reserved->size; - continue; - } - - while (ramdisk && - (bootmap_addr >= (ramdisk->addr + ramdisk->size))) - ramdisk = ramdisk->next; - - if (!ramdisk || - ((bootmap_addr + bootmap_len) < ramdisk->addr)) - break; - - bootmap_addr = ramdisk->addr + ramdisk->size; - } - - if ((PFN_UP(bootmap_addr) + bootmap_len) >= (mem->addr + mem->size)) - return ~0UL; - - return PFN_UP(bootmap_addr); -} - -void __init setup_bootmem(void) -{ - unsigned bootmap_size; - unsigned long first_pfn, bootmap_pfn, pages; - unsigned long max_pfn, max_low_pfn; - unsigned long kern_start = virt_to_phys(_stext); - unsigned long kern_end = virt_to_phys(_end); - unsigned node = 0; - struct tag_mem_range *bank, *res; - - sort_mem_list(&mem_phys); - sort_mem_list(&mem_reserved); - - print_memory_map("Physical memory", mem_phys); - print_memory_map("Reserved memory", mem_reserved); - - nodes_clear(node_online_map); - - if (mem_ramdisk) { -#ifdef CONFIG_BLK_DEV_INITRD - initrd_start = (unsigned long)__va(mem_ramdisk->addr); - initrd_end = initrd_start + mem_ramdisk->size; - - print_memory_map("RAMDISK images", mem_ramdisk); - if (mem_ramdisk->next) - printk(KERN_WARNING - "Warning: Only the first RAMDISK image " - "will be used\n"); - sort_mem_list(&mem_ramdisk); -#else - printk(KERN_WARNING "RAM disk image present, but " - "no initrd support in kernel!\n"); -#endif - } - - if (mem_phys->next) - printk(KERN_WARNING "Only using first memory bank\n"); - - for (bank = mem_phys; bank; bank = NULL) { - first_pfn = PFN_UP(bank->addr); - max_low_pfn = max_pfn = PFN_DOWN(bank->addr + bank->size); - bootmap_pfn = find_bootmap_pfn(bank); - if (bootmap_pfn > max_pfn) - panic("No space for bootmem bitmap!\n"); - - if (max_low_pfn > MAX_LOWMEM_PFN) { - max_low_pfn = MAX_LOWMEM_PFN; -#ifndef CONFIG_HIGHMEM - /* - * Lowmem is memory that can be addressed - * directly through P1/P2 - */ - printk(KERN_WARNING - "Node %u: Only %ld MiB of memory will be used.\n", - node, MAX_LOWMEM >> 20); - printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); -#else -#error HIGHMEM is not supported by AVR32 yet -#endif - } - - /* Initialize the boot-time allocator with low memory only. */ - bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn, - first_pfn, max_low_pfn); - - printk("Node %u: bdata = %p, bdata->node_bootmem_map = %p\n", - node, NODE_DATA(node)->bdata, - NODE_DATA(node)->bdata->node_bootmem_map); - - /* - * Register fully available RAM pages with the bootmem - * allocator. - */ - pages = max_low_pfn - first_pfn; - free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn), - PFN_PHYS(pages)); - - /* - * Reserve space for the kernel image (if present in - * this node)... - */ - if ((kern_start >= PFN_PHYS(first_pfn)) && - (kern_start < PFN_PHYS(max_pfn))) { - printk("Node %u: Kernel image %08lx - %08lx\n", - node, kern_start, kern_end); - reserve_bootmem_node(NODE_DATA(node), kern_start, - kern_end - kern_start); - } - - /* ...the bootmem bitmap... */ - reserve_bootmem_node(NODE_DATA(node), - PFN_PHYS(bootmap_pfn), - bootmap_size); - - /* ...any RAMDISK images... */ - for (res = mem_ramdisk; res; res = res->next) { - if (res->addr > PFN_PHYS(max_pfn)) - break; - - if (res->addr >= PFN_PHYS(first_pfn)) { - printk("Node %u: RAMDISK %08lx - %08lx\n", - node, - (unsigned long)res->addr, - (unsigned long)(res->addr + res->size)); - reserve_bootmem_node(NODE_DATA(node), - res->addr, res->size); - } - } - - /* ...and any other reserved regions. */ - for (res = mem_reserved; res; res = res->next) { - if (res->addr > PFN_PHYS(max_pfn)) - break; - - if (res->addr >= PFN_PHYS(first_pfn)) { - printk("Node %u: Reserved %08lx - %08lx\n", - node, - (unsigned long)res->addr, - (unsigned long)(res->addr + res->size)); - reserve_bootmem_node(NODE_DATA(node), - res->addr, res->size); - } - } - - node_set_online(node); - } -} - /* * paging_init() sets up the page tables * diff --git a/arch/i386/defconfig b/arch/i386/defconfig index f4efd66e1ee..c96911c37ae 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -692,7 +692,6 @@ CONFIG_SATA_SIL=y CONFIG_SATA_VIA=y # CONFIG_SATA_VITESSE is not set # CONFIG_SATA_INIC162X is not set -CONFIG_SATA_INTEL_COMBINED=y CONFIG_SATA_ACPI=y # CONFIG_PATA_ALI is not set # CONFIG_PATA_AMD is not set diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c index a7d22d9f3d7..8f7efd38254 100644 --- a/arch/i386/kernel/acpi/earlyquirk.c +++ b/arch/i386/kernel/acpi/earlyquirk.c @@ -23,10 +23,13 @@ static int __init nvidia_hpet_check(struct acpi_table_header *header) static int __init check_bridge(int vendor, int device) { #ifdef CONFIG_ACPI + static int warned; /* According to Nvidia all timer overrides are bogus unless HPET is enabled. */ if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) { - if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) { + if (!warned && acpi_table_parse(ACPI_SIG_HPET, + nvidia_hpet_check)) { + warned = 1; acpi_skip_timer_override = 1; printk(KERN_INFO "Nvidia board " "detected. Ignoring ACPI " diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c index 424e9257c9a..f26077a773d 100644 --- a/arch/ia64/hp/sim/simeth.c +++ b/arch/ia64/hp/sim/simeth.c @@ -427,7 +427,6 @@ make_new_skb(struct net_device *dev) printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name); return NULL; } - nskb->dev = dev; skb_reserve(nskb, 2); /* Align IP on 16 byte boundaries */ @@ -474,7 +473,7 @@ simeth_rx(struct net_device *dev) * XXX Fix me * Should really do a csum+copy here */ - memcpy(skb->data, frame, len); + skb_copy_to_linear_data(skb, frame, len); #endif skb->protocol = eth_type_trans(skb, dev); diff --git a/arch/ia64/lib/csum_partial_copy.c b/arch/ia64/lib/csum_partial_copy.c index 503dfe6d145..118daf5a063 100644 --- a/arch/ia64/lib/csum_partial_copy.c +++ b/arch/ia64/lib/csum_partial_copy.c @@ -128,6 +128,8 @@ csum_partial_copy_from_user(const void __user *src, void *dst, return (__force __wsum)result; } +EXPORT_SYMBOL(csum_partial_copy_from_user); + __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) { diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c index c8173db0d84..5419acb89a8 100644 --- a/arch/ia64/sn/kernel/xpnet.c +++ b/arch/ia64/sn/kernel/xpnet.c @@ -233,7 +233,7 @@ xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg) "%lu)\n", skb->data, &msg->data, (size_t) msg->embedded_bytes); - memcpy(skb->data, &msg->data, (size_t) msg->embedded_bytes); + skb_copy_to_linear_data(skb, &msg->data, (size_t)msg->embedded_bytes); } else { dev_dbg(xpnet, "transferring buffer to the skb->data area;\n\t" "bte_copy(0x%p, 0x%p, %hu)\n", (void *)msg->buf_pa, @@ -264,17 +264,16 @@ xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg) dev_dbg(xpnet, "<skb->head=0x%p skb->data=0x%p skb->tail=0x%p " "skb->end=0x%p skb->len=%d\n", (void *) skb->head, - (void *) skb->data, (void *) skb->tail, (void *) skb->end, + (void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb), skb->len); - skb->dev = xpnet_device; skb->protocol = eth_type_trans(skb, xpnet_device); skb->ip_summed = CHECKSUM_UNNECESSARY; dev_dbg(xpnet, "passing skb to network layer; \n\tskb->head=0x%p " "skb->data=0x%p skb->tail=0x%p skb->end=0x%p skb->len=%d\n", - (void *) skb->head, (void *) skb->data, (void *) skb->tail, - (void *) skb->end, skb->len); + (void *)skb->head, (void *)skb->data, skb_tail_pointer(skb), + skb_end_pointer(skb), skb->len); xpnet_device->last_rx = jiffies; @@ -476,7 +475,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) dev_dbg(xpnet, ">skb->head=0x%p skb->data=0x%p skb->tail=0x%p " "skb->end=0x%p skb->len=%d\n", (void *) skb->head, - (void *) skb->data, (void *) skb->tail, (void *) skb->end, + (void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb), skb->len); @@ -498,7 +497,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) /* get the beginning of the first cacheline and end of last */ start_addr = ((u64) skb->data & ~(L1_CACHE_BYTES - 1)); - end_addr = L1_CACHE_ALIGN((u64) skb->tail); + end_addr = L1_CACHE_ALIGN((u64)skb_tail_pointer(skb)); /* calculate how many bytes to embed in the XPC message */ embedded_bytes = 0; @@ -567,14 +566,15 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) msg->version = XPNET_VERSION_EMBED; dev_dbg(xpnet, "calling memcpy(0x%p, 0x%p, 0x%lx)\n", &msg->data, skb->data, (size_t) embedded_bytes); - memcpy(&msg->data, skb->data, (size_t) embedded_bytes); + skb_copy_from_linear_data(skb, &msg->data, + (size_t)embedded_bytes); } else { msg->version = XPNET_VERSION; } msg->magic = XPNET_MAGIC; msg->size = end_addr - start_addr; msg->leadin_ignore = (u64) skb->data - start_addr; - msg->tailout_ignore = end_addr - (u64) skb->tail; + msg->tailout_ignore = end_addr - (u64)skb_tail_pointer(skb); msg->buf_pa = __pa(start_addr); dev_dbg(xpnet, "sending XPC message to %d:%d\nmsg->buf_pa=" diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c78b14380b3..130d825e543 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -10,7 +10,6 @@ menu "Machine selection" config ZONE_DMA bool - default y choice prompt "System type" @@ -165,7 +164,7 @@ config MIPS_COBALT select HW_HAS_PCI select I8259 select IRQ_CPU - select MIPS_GT64111 + select PCI_GT64XXX_PCI0 select SYS_HAS_CPU_NEVADA select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL @@ -207,7 +206,7 @@ config MIPS_EV64120 depends on EXPERIMENTAL select DMA_NONCOHERENT select HW_HAS_PCI - select MIPS_GT64120 + select PCI_GT64XXX_PCI0 select SYS_HAS_CPU_R5000 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL @@ -245,7 +244,7 @@ config LASAT select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select HW_HAS_PCI - select MIPS_GT64120 + select PCI_GT64XXX_PCI0 select MIPS_NILE4 select R5000_CPU_SCACHE select SYS_HAS_CPU_R5000 @@ -263,7 +262,7 @@ config MIPS_ATLAS select HW_HAS_PCI select MIPS_BOARDS_GEN select MIPS_BONITO64 - select MIPS_GT64120 + select PCI_GT64XXX_PCI0 select MIPS_MSC select RM7000_CPU_SCACHE select SWAP_IO_SPACE @@ -296,7 +295,7 @@ config MIPS_MALTA select MIPS_BOARDS_GEN select MIPS_BONITO64 select MIPS_CPU_SCACHE - select MIPS_GT64120 + select PCI_GT64XXX_PCI0 select MIPS_MSC select SWAP_IO_SPACE select SYS_HAS_CPU_MIPS32_R1 @@ -340,7 +339,7 @@ config WR_PPMC select BOOT_ELF32 select DMA_NONCOHERENT select HW_HAS_PCI - select MIPS_GT64120 + select PCI_GT64XXX_PCI0 select SWAP_IO_SPACE select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2 @@ -398,7 +397,7 @@ config MOMENCO_OCELOT select HW_HAS_PCI select IRQ_CPU select IRQ_CPU_RM7K - select MIPS_GT64120 + select PCI_GT64XXX_PCI0 select RM7000_CPU_SCACHE select SWAP_IO_SPACE select SYS_HAS_CPU_RM7000 @@ -501,10 +500,8 @@ config DDB5477 ether port USB, AC97, PCI, etc. config MACH_VR41XX - bool "NEC VR41XX-based machines" + bool "NEC VR4100 series based machines" select SYS_HAS_CPU_VR41XX - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL select GENERIC_HARDIRQS_NO__DO_IRQ config PMC_YOSEMITE @@ -779,6 +776,7 @@ config TOSHIBA_JMR3927 select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_BIG_ENDIAN select TOSHIBA_BOARDS + select GENERIC_HARDIRQS_NO__DO_IRQ config TOSHIBA_RBTX4927 bool "Toshiba TBTX49[23]7 board" @@ -922,6 +920,7 @@ config SYS_HAS_EARLY_PRINTK config GENERIC_ISA_DMA bool + select ZONE_DMA config I8259 bool @@ -945,6 +944,7 @@ config MIPS_DISABLE_OBSOLETE_IDE config GENERIC_ISA_DMA_SUPPORT_BROKEN bool + select ZONE_DMA # # Endianess selection. Sufficiently obscure so many users don't know what to @@ -999,10 +999,7 @@ config DDB5XXX_COMMON config MIPS_BOARDS_GEN bool -config MIPS_GT64111 - bool - -config MIPS_GT64120 +config PCI_GT64XXX_PCI0 bool config MIPS_TX3927 diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 92bca6ad6ab..f2f742df32c 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -530,25 +530,29 @@ cflags-$(CONFIG_SGI_IP32) += -Iinclude/asm-mips/mach-ip32 load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 # -# Sibyte SB1250 SOC +# Sibyte SB1250/BCM1480 SOC # # This is a LIB so that it links at the end, and initcalls are later # the sequence; but it is built as an object so that modules don't get # removed (as happens, even if they have __initcall/module_init) # core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/ +core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/common/ cflags-$(CONFIG_SIBYTE_BCM112X) += -Iinclude/asm-mips/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ +core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/common/ cflags-$(CONFIG_SIBYTE_SB1250) += -Iinclude/asm-mips/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/bcm1480/ +core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/common/ cflags-$(CONFIG_SIBYTE_BCM1x55) += -Iinclude/asm-mips/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/bcm1480/ +core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/common/ cflags-$(CONFIG_SIBYTE_BCM1x80) += -Iinclude/asm-mips/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c index 42f0eda1d51..2f0e4c08eb0 100644 --- a/arch/mips/basler/excite/excite_setup.c +++ b/arch/mips/basler/excite/excite_setup.c @@ -63,7 +63,7 @@ volatile void __iomem * const ocd_base = (void *) (EXCITE_ADDR_OCD); volatile void __iomem * const titan_base = (void *) (EXCITE_ADDR_TITAN); /* Protect access to shared GPI registers */ -spinlock_t titan_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(titan_lock); int titan_irqflags; diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile index b36dd8f538f..de017c11f9b 100644 --- a/arch/mips/cobalt/Makefile +++ b/arch/mips/cobalt/Makefile @@ -4,5 +4,6 @@ obj-y := irq.o reset.o setup.o +obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_EARLY_PRINTK) += console.o obj-$(CONFIG_MTD_PHYSMAP) += mtd.o diff --git a/arch/mips/cobalt/console.c b/arch/mips/cobalt/console.c index ca56b415b8a..0485d51f721 100644 --- a/arch/mips/cobalt/console.c +++ b/arch/mips/cobalt/console.c @@ -1,13 +1,11 @@ /* * (C) P. Horton 2006 */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/console.h> #include <linux/serial_reg.h> + #include <asm/addrspace.h> -#include <asm/mach-cobalt/cobalt.h> + +#include <cobalt.h> void prom_putchar(char c) { diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c index fe93b846923..950ad1e8be4 100644 --- a/arch/mips/cobalt/irq.c +++ b/arch/mips/cobalt/irq.c @@ -17,7 +17,7 @@ #include <asm/irq_cpu.h> #include <asm/gt64120.h> -#include <asm/mach-cobalt/cobalt.h> +#include <cobalt.h> /* * We have two types of interrupts that we handle, ones that come in through diff --git a/arch/mips/cobalt/pci.c b/arch/mips/cobalt/pci.c new file mode 100644 index 00000000000..d91027f43de --- /dev/null +++ b/arch/mips/cobalt/pci.c @@ -0,0 +1,47 @@ +/* + * Register PCI controller. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 2004, 05 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) + * + */ +#include <linux/init.h> +#include <linux/pci.h> + +#include <asm/gt64120.h> + +extern struct pci_ops gt64xxx_pci0_ops; + +static struct resource cobalt_mem_resource = { + .start = GT_DEF_PCI0_MEM0_BASE, + .end = GT_DEF_PCI0_MEM0_BASE + GT_DEF_PCI0_MEM0_SIZE - 1, + .name = "PCI memory", + .flags = IORESOURCE_MEM, +}; + +static struct resource cobalt_io_resource = { + .start = 0x1000, + .end = GT_DEF_PCI0_IO_SIZE - 1, + .name = "PCI I/O", + .flags = IORESOURCE_IO, +}; + +static struct pci_controller cobalt_pci_controller = { + .pci_ops = >64xxx_pci0_ops, + .mem_resource = &cobalt_mem_resource, + .io_resource = &cobalt_io_resource, + .io_offset = 0 - GT_DEF_PCI0_IO_BASE, +}; + +static int __init cobalt_pci_init(void) +{ + register_pci_controller(&cobalt_pci_controller); + + return 0; +} + +arch_initcall(cobalt_pci_init); diff --git a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c index 753dfccae6f..43cca21fdbc 100644 --- a/arch/mips/cobalt/reset.c +++ b/arch/mips/cobalt/reset.c @@ -8,15 +8,12 @@ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv) */ -#include <linux/sched.h> -#include <linux/mm.h> -#include <asm/cacheflush.h> +#include <linux/jiffies.h> + #include <asm/io.h> -#include <asm/processor.h> #include <asm/reboot.h> -#include <asm/system.h> -#include <asm/mipsregs.h> -#include <asm/mach-cobalt/cobalt.h> + +#include <cobalt.h> void cobalt_machine_halt(void) { diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c index 88d34f11385..d0dd81790f7 100644 --- a/arch/mips/cobalt/setup.c +++ b/arch/mips/cobalt/setup.c @@ -19,12 +19,10 @@ #include <asm/bootinfo.h> #include <asm/time.h> #include <asm/io.h> -#include <asm/irq.h> -#include <asm/processor.h> #include <asm/reboot.h> #include <asm/gt64120.h> -#include <asm/mach-cobalt/cobalt.h> +#include <cobalt.h> extern void cobalt_machine_restart(char *command); extern void cobalt_machine_halt(void); @@ -63,22 +61,6 @@ void __init plat_timer_setup(struct irqaction *irq) GT_WRITE(GT_INTRMASK_OFS, GT_INTR_T0EXP_MSK | GT_READ(GT_INTRMASK_OFS)); } -extern struct pci_ops gt64111_pci_ops; - -static struct resource cobalt_mem_resource = { - .start = GT_DEF_PCI0_MEM0_BASE, - .end = GT_DEF_PCI0_MEM0_BASE + GT_DEF_PCI0_MEM0_SIZE - 1, - .name = "PCI memory", - .flags = IORESOURCE_MEM -}; - -static struct resource cobalt_io_resource = { - .start = 0x1000, - .end = 0xffff, - .name = "PCI I/O", - .flags = IORESOURCE_IO -}; - /* * Cobalt doesn't have PS/2 keyboard/mouse interfaces, * keyboard conntroller is never used. @@ -111,14 +93,6 @@ static struct resource cobalt_reserved_resources[] = { }, }; -static struct pci_controller cobalt_pci_controller = { - .pci_ops = >64111_pci_ops, - .mem_resource = &cobalt_mem_resource, - .mem_offset = 0, - .io_resource = &cobalt_io_resource, - .io_offset = 0 - GT_DEF_PCI0_IO_BASE, -}; - void __init plat_mem_setup(void) { static struct uart_port uart; @@ -146,10 +120,6 @@ void __init plat_mem_setup(void) printk("Cobalt board ID: %d\n", cobalt_board_id); -#ifdef CONFIG_PCI - register_pci_controller(&cobalt_pci_controller); -#endif - if (cobalt_board_id > COBALT_BRD_ID_RAQ1) { #ifdef CONFIG_SERIAL_8250 uart.line = 0; diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig index 21a094752da..068e48ec709 100644 --- a/arch/mips/configs/jmr3927_defconfig +++ b/arch/mips/configs/jmr3927_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.20 -# Tue Feb 20 21:47:34 2007 +# Linux kernel version: 2.6.21-rc3 +# Thu Mar 15 00:40:40 2007 # CONFIG_MIPS=y @@ -70,7 +70,7 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_TIME=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_DMA_NONCOHERENT=y CONFIG_DMA_NEED_PCI_MAP_STATE=y CONFIG_CPU_BIG_ENDIAN=y @@ -138,12 +138,12 @@ CONFIG_ZONE_DMA_FLAG=1 # CONFIG_HZ_48 is not set # CONFIG_HZ_100 is not set # CONFIG_HZ_128 is not set -# CONFIG_HZ_250 is not set +CONFIG_HZ_250=y # CONFIG_HZ_256 is not set -CONFIG_HZ_1000=y +# CONFIG_HZ_1000 is not set # CONFIG_HZ_1024 is not set CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_HZ=1000 +CONFIG_HZ=250 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set @@ -175,14 +175,15 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_SYSFS_DEPRECATED=y -CONFIG_RELAY=y +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_EMBEDDED=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y +# CONFIG_HOTPLUG is not set CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y @@ -217,11 +218,11 @@ CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y -CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_AS is not set # CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_DEFAULT_IOSCHED="cfq" # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -233,12 +234,10 @@ CONFIG_MMU=y # # PCCARD (PCMCIA/CardBus) support # -# CONFIG_PCCARD is not set # # PCI Hotplug Support # -# CONFIG_HOTPLUG_PCI is not set # # Executable file formats @@ -250,10 +249,7 @@ CONFIG_TRAD_SIGNALS=y # # Power management options # -CONFIG_PM=y -# CONFIG_PM_LEGACY is not set -# CONFIG_PM_DEBUG is not set -# CONFIG_PM_SYSFS_DEPRECATED is not set +# CONFIG_PM is not set # # Networking @@ -267,12 +263,7 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y -CONFIG_XFRM=y -CONFIG_XFRM_USER=y -# CONFIG_XFRM_SUB_POLICY is not set -CONFIG_XFRM_MIGRATE=y -CONFIG_NET_KEY=y -CONFIG_NET_KEY_MIGRATE=y +# CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set @@ -290,19 +281,18 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_TCP_MD5SIG=y +# CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set -CONFIG_NETWORK_SECMARK=y +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -343,13 +333,7 @@ CONFIG_NETWORK_SECMARK=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -CONFIG_IEEE80211=y -# CONFIG_IEEE80211_DEBUG is not set -CONFIG_IEEE80211_CRYPT_WEP=y -CONFIG_IEEE80211_CRYPT_CCMP=y -CONFIG_IEEE80211_SOFTMAC=y -# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set -CONFIG_WIRELESS_EXT=y +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -360,14 +344,12 @@ CONFIG_WIRELESS_EXT=y # CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y # CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker # -CONFIG_CONNECTOR=y -CONFIG_PROC_EVENTS=y +# CONFIG_CONNECTOR is not set # # Memory Technology Devices (MTD) @@ -396,16 +378,13 @@ CONFIG_PROC_EVENTS=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -CONFIG_CDROM_PKTCDVD=y -CONFIG_CDROM_PKTCDVD_BUFFERS=8 -# CONFIG_CDROM_PKTCDVD_WCACHE is not set -CONFIG_ATA_OVER_ETH=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set # # Misc devices # -CONFIG_SGI_IOC4=y +# CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set # @@ -416,7 +395,7 @@ CONFIG_SGI_IOC4=y # # SCSI device support # -CONFIG_RAID_ATTRS=y +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_NETLINK is not set @@ -462,26 +441,13 @@ CONFIG_NETDEVICES=y # # PHY device support # -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -CONFIG_MARVELL_PHY=y -CONFIG_DAVICOM_PHY=y -CONFIG_QSEMI_PHY=y -CONFIG_LXT_PHY=y -CONFIG_CICADA_PHY=y -CONFIG_VITESSE_PHY=y -CONFIG_SMSC_PHY=y -# CONFIG_BROADCOM_PHY is not set -# CONFIG_FIXED_PHY is not set +# CONFIG_PHYLIB is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set +CONFIG_MII=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set @@ -493,7 +459,27 @@ CONFIG_NET_ETHERNET=y # # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +CONFIG_TC35815=y +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_SC92031 is not set # # Ethernet (1000 Mbit) @@ -509,20 +495,21 @@ CONFIG_NET_ETHERNET=y # CONFIG_SKGE is not set # CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set -CONFIG_QLA3XXX=y +# CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set # # Ethernet (10000 Mbit) # # CONFIG_CHELSIO_T1 is not set -CONFIG_CHELSIO_T3=y +# CONFIG_CHELSIO_T3 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set -CONFIG_NETXEN_NIC=y +# CONFIG_NETXEN_NIC is not set # # Token Ring devices @@ -566,10 +553,7 @@ CONFIG_INPUT=y # # Userland interfaces # -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set @@ -587,21 +571,13 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # # Hardware I/O ports # -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_PCIPS2 is not set -# CONFIG_SERIO_LIBPS2 is not set -CONFIG_SERIO_RAW=y +# CONFIG_SERIO is not set # CONFIG_GAMEPORT is not set # # Character devices # -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_VT is not set CONFIG_SERIAL_NONSTANDARD=y # CONFIG_COMPUTONE is not set # CONFIG_ROCKETPORT is not set @@ -609,7 +585,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_DIGIEPCA is not set # CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set -CONFIG_MOXA_SMARTIO_NEW=y +# CONFIG_MOXA_SMARTIO_NEW is not set # CONFIG_ISI is not set # CONFIG_SYNCLINKMP is not set # CONFIG_SYNCLINK_GT is not set @@ -629,11 +605,12 @@ CONFIG_MOXA_SMARTIO_NEW=y # Non-8250 serial port support # CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_TXX9=y CONFIG_HAS_TXX9_SERIAL=y CONFIG_SERIAL_TXX9_NR_UARTS=6 -# CONFIG_SERIAL_TXX9_CONSOLE is not set -# CONFIG_SERIAL_TXX9_STDSERIAL is not set +CONFIG_SERIAL_TXX9_CONSOLE=y +CONFIG_SERIAL_TXX9_STDSERIAL=y # CONFIG_SERIAL_JSM is not set # CONFIG_UNIX98_PTYS is not set CONFIG_LEGACY_PTYS=y @@ -685,6 +662,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_HWMON_VID is not set # +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -697,51 +679,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Graphics support # -# CONFIG_FIRMWARE_EDID is not set -CONFIG_FB=y -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -# CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_TILEBLITTING is not set -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_NVIDIA is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_S3 is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_SMIVGX is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_FB is not set # # Sound @@ -864,7 +803,7 @@ CONFIG_INOTIFY_USER=y CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -CONFIG_FUSE_FS=y +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -889,14 +828,13 @@ CONFIG_SYSFS=y # CONFIG_TMPFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -CONFIG_CONFIGFS_FS=y +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems # # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set -# CONFIG_ECRYPT_FS is not set # CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set @@ -944,10 +882,7 @@ CONFIG_MSDOS_PARTITION=y # # Distributed Lock Manager # -CONFIG_DLM=y -CONFIG_DLM_TCP=y -# CONFIG_DLM_SCTP is not set -# CONFIG_DLM_DEBUG is not set +# CONFIG_DLM is not set # # Profiling support @@ -972,65 +907,22 @@ CONFIG_CMDLINE="" # # Security options # -CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # # Cryptographic options # -CONFIG_CRYPTO=y -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_XCBC=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_WP512=y -CONFIG_CRYPTO_TGR192=y -CONFIG_CRYPTO_GF128MUL=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_PCBC=y -CONFIG_CRYPTO_LRW=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_FCRYPT=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_TWOFISH_COMMON=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_CAST5=y -CONFIG_CRYPTO_CAST6=y -CONFIG_CRYPTO_TEA=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_KHAZAD=y -CONFIG_CRYPTO_ANUBIS=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CAMELLIA=y - -# -# Hardware crypto devices -# +# CONFIG_CRYPTO is not set # # Library routines # CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set -CONFIG_CRC16=y +# CONFIG_CRC16 is not set CONFIG_CRC32=y -CONFIG_LIBCRC32C=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y +# CONFIG_LIBCRC32C is not set CONFIG_PLIST=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y diff --git a/arch/mips/gt64120/wrppmc/pci.c b/arch/mips/gt64120/wrppmc/pci.c index 2fbe93467f7..0d5289bc180 100644 --- a/arch/mips/gt64120/wrppmc/pci.c +++ b/arch/mips/gt64120/wrppmc/pci.c @@ -13,7 +13,7 @@ #include <linux/kernel.h> #include <asm/gt64120.h> -extern struct pci_ops gt64120_pci_ops; +extern struct pci_ops gt64xxx_pci0_ops; static struct resource pci0_io_resource = { .name = "pci_0 io", @@ -30,7 +30,7 @@ static struct resource pci0_mem_resource = { }; static struct pci_controller hose_0 = { - .pci_ops = >64120_pci_ops, + .pci_ops = >64xxx_pci0_ops, .io_resource = &pci0_io_resource, .mem_resource = &pci0_mem_resource, }; diff --git a/arch/mips/jmr3927/common/prom.c b/arch/mips/jmr3927/common/prom.c index aa481b774c4..5398813e50e 100644 --- a/arch/mips/jmr3927/common/prom.c +++ b/arch/mips/jmr3927/common/prom.c @@ -41,16 +41,6 @@ #include <asm/bootinfo.h> -extern int prom_argc; -extern char **prom_argv, **prom_envp; - -typedef struct -{ - char *name; -/* char *val; */ -}t_env_var; - - char * __init prom_getcmdline(void) { return &(arcs_cmdline[0]); @@ -60,6 +50,8 @@ void __init prom_init_cmdline(void) { char *cp; int actr; + int prom_argc = fw_arg0; + char **prom_argv = (char **) fw_arg1; actr = 1; /* Always ignore argv[0] */ diff --git a/arch/mips/jmr3927/common/puts.c b/arch/mips/jmr3927/common/puts.c index 1c1cad9cd07..c611ab49788 100644 --- a/arch/mips/jmr3927/common/puts.c +++ b/arch/mips/jmr3927/common/puts.c @@ -32,137 +32,29 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/types.h> -#include <asm/jmr3927/txx927.h> #include <asm/jmr3927/tx3927.h> -#include <asm/jmr3927/jmr3927.h> #define TIMEOUT 0xffffff -#define SLOW_DOWN - -static const char digits[16] = "0123456789abcdef"; - -#ifdef SLOW_DOWN -#define slow_down() { int k; for (k=0; k<10000; k++); } -#else -#define slow_down() -#endif void -putch(const unsigned char c) +prom_putchar(char c) { int i = 0; do { - slow_down(); i++; - if (i>TIMEOUT) { + if (i>TIMEOUT) break; - } } while (!(tx3927_sioptr(1)->cisr & TXx927_SICISR_TXALS)); tx3927_sioptr(1)->tfifo = c; return; } -unsigned char getch(void) -{ - int i = 0; - int dicr; - char c; - - /* diable RX int. */ - dicr = tx3927_sioptr(1)->dicr; - tx3927_sioptr(1)->dicr = 0; - - do { - slow_down(); - i++; - if (i>TIMEOUT) { - break; - } - } while (tx3927_sioptr(1)->disr & TXx927_SIDISR_UVALID) - ; - c = tx3927_sioptr(1)->rfifo; - - /* clear RX int. status */ - tx3927_sioptr(1)->disr &= ~TXx927_SIDISR_RDIS; - /* enable RX int. */ - tx3927_sioptr(1)->dicr = dicr; - - return c; -} -void -do_jmr3927_led_set(char n) -{ - /* and with current leds */ - jmr3927_led_and_set(n); -} - void -puts(unsigned char *cp) +puts(const char *cp) { - int i = 0; - - while (*cp) { - do { - slow_down(); - i++; - if (i>TIMEOUT) { - break; - } - } while (!(tx3927_sioptr(1)->cisr & TXx927_SICISR_TXALS)); - tx3927_sioptr(1)->tfifo = *cp++; - } - putch('\r'); - putch('\n'); -} - -void -fputs(unsigned char *cp) -{ - int i = 0; - - while (*cp) { - do { - slow_down(); - i++; - if (i>TIMEOUT) { - break; - } - } while (!(tx3927_sioptr(1)->cisr & TXx927_SICISR_TXALS)); - tx3927_sioptr(1)->tfifo = *cp++; - } -} - - -void -put64(uint64_t ul) -{ - int cnt; - unsigned ch; - - cnt = 16; /* 16 nibbles in a 64 bit long */ - putch('0'); - putch('x'); - do { - cnt--; - ch = (unsigned char)(ul >> cnt * 4) & 0x0F; - putch(digits[ch]); - } while (cnt > 0); -} - -void -put32(unsigned u) -{ - int cnt; - unsigned ch; - - cnt = 8; /* 8 nibbles in a 32 bit long */ - putch('0'); - putch('x'); - do { - cnt--; - ch = (unsigned char)(u >> cnt * 4) & 0x0F; - putch(digits[ch]); - } while (cnt > 0); + while (*cp) + prom_putchar(*cp++); + prom_putchar('\r'); + prom_putchar('\n'); } diff --git a/arch/mips/jmr3927/rbhma3100/Makefile b/arch/mips/jmr3927/rbhma3100/Makefile index 18fe9a898cb..8d00ba460ce 100644 --- a/arch/mips/jmr3927/rbhma3100/Makefile +++ b/arch/mips/jmr3927/rbhma3100/Makefile @@ -3,5 +3,4 @@ # obj-y += init.o irq.o setup.o -obj-$(CONFIG_RUNTIME_DEBUG) += debug.o obj-$(CONFIG_KGDB) += kgdb_io.o diff --git a/arch/mips/jmr3927/rbhma3100/init.c b/arch/mips/jmr3927/rbhma3100/init.c index a55cb4572de..9169fab1773 100644 --- a/arch/mips/jmr3927/rbhma3100/init.c +++ b/arch/mips/jmr3927/rbhma3100/init.c @@ -28,20 +28,10 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/init.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/bootmem.h> - -#include <asm/addrspace.h> #include <asm/bootinfo.h> -#include <asm/mipsregs.h> #include <asm/jmr3927/jmr3927.h> -int prom_argc; -char **prom_argv, **prom_envp; extern void __init prom_init_cmdline(void); -extern char *prom_getenv(char *envname); -unsigned long mips_nofpu = 0; const char *get_system_type(void) { @@ -52,7 +42,7 @@ const char *get_system_type(void) ; } -extern void puts(unsigned char *cp); +extern void puts(const char *cp); void __init prom_init(void) { @@ -61,10 +51,6 @@ void __init prom_init(void) if ((tx3927_ccfgptr->ccfg & TX3927_CCFG_TLBOFF) == 0) puts("Warning: TX3927 TLB off\n"); #endif - prom_argc = fw_arg0; - prom_argv = (char **) fw_arg1; - prom_envp = (char **) fw_arg2; - mips_machgroup = MACH_GROUP_TOSHIBA; #ifdef CONFIG_TOSHIBA_JMR3927 diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c index 7d2c203cb40..1187b44a3dd 100644 --- a/arch/mips/jmr3927/rbhma3100/irq.c +++ b/arch/mips/jmr3927/rbhma3100/irq.c @@ -30,53 +30,21 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/init.h> - -#include <linux/errno.h> -#include <linux/irq.h> -#include <linux/kernel_stat.h> -#include <linux/signal.h> #include <linux/sched.h> #include <linux/types.h> #include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/timex.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/bitops.h> -#include <asm/irq_regs.h> #include <asm/io.h> #include <asm/mipsregs.h> #include <asm/system.h> -#include <asm/ptrace.h> #include <asm/processor.h> -#include <asm/jmr3927/irq.h> -#include <asm/debug.h> #include <asm/jmr3927/jmr3927.h> #if JMR3927_IRQ_END > NR_IRQS #error JMR3927_IRQ_END > NR_IRQS #endif -struct tb_irq_space* tb_irq_spaces; - -static int jmr3927_irq_base = -1; - -#ifdef CONFIG_PCI -static int jmr3927_gen_iack(void) -{ - /* generate ACK cycle */ -#ifdef __BIG_ENDIAN - return (tx3927_pcicptr->iiadp >> 24) & 0xff; -#else - return tx3927_pcicptr->iiadp & 0xff; -#endif -} -#endif - #define irc_dlevel 0 #define irc_elevel 1 @@ -87,89 +55,24 @@ static unsigned char irc_level[TX3927_NUM_IR] = { 6, 6, 6 /* TMR */ }; -static void jmr3927_irq_disable(unsigned int irq_nr); -static void jmr3927_irq_enable(unsigned int irq_nr); - -static void jmr3927_irq_ack(unsigned int irq) -{ - if (irq == JMR3927_IRQ_IRC_TMR0) - jmr3927_tmrptr->tisr = 0; /* ack interrupt */ - - jmr3927_irq_disable(irq); -} - -static void jmr3927_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - jmr3927_irq_enable(irq); -} - -static void jmr3927_irq_disable(unsigned int irq_nr) -{ - struct tb_irq_space* sp; - - for (sp = tb_irq_spaces; sp; sp = sp->next) { - if (sp->start_irqno <= irq_nr && - irq_nr < sp->start_irqno + sp->nr_irqs) { - if (sp->mask_func) - sp->mask_func(irq_nr - sp->start_irqno, - sp->space_id); - break; - } - } -} - -static void jmr3927_irq_enable(unsigned int irq_nr) -{ - struct tb_irq_space* sp; - - for (sp = tb_irq_spaces; sp; sp = sp->next) { - if (sp->start_irqno <= irq_nr && - irq_nr < sp->start_irqno + sp->nr_irqs) { - if (sp->unmask_func) - sp->unmask_func(irq_nr - sp->start_irqno, - sp->space_id); - break; - } - } -} - /* * CP0_STATUS is a thread's resource (saved/restored on context switch). - * So disable_irq/enable_irq MUST handle IOC/ISAC/IRC registers. + * So disable_irq/enable_irq MUST handle IOC/IRC registers. */ -static void mask_irq_isac(int irq_nr, int space_id) -{ - /* 0: mask */ - unsigned char imask = - jmr3927_isac_reg_in(JMR3927_ISAC_INTM_ADDR); - unsigned int bit = 1 << irq_nr; - jmr3927_isac_reg_out(imask & ~bit, JMR3927_ISAC_INTM_ADDR); - /* flush write buffer */ - (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); -} -static void unmask_irq_isac(int irq_nr, int space_id) -{ - /* 0: mask */ - unsigned char imask = jmr3927_isac_reg_in(JMR3927_ISAC_INTM_ADDR); - unsigned int bit = 1 << irq_nr; - jmr3927_isac_reg_out(imask | bit, JMR3927_ISAC_INTM_ADDR); - /* flush write buffer */ - (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); -} - -static void mask_irq_ioc(int irq_nr, int space_id) +static void mask_irq_ioc(unsigned int irq) { /* 0: mask */ + unsigned int irq_nr = irq - JMR3927_IRQ_IOC; unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); unsigned int bit = 1 << irq_nr; jmr3927_ioc_reg_out(imask & ~bit, JMR3927_IOC_INTM_ADDR); /* flush write buffer */ (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); } -static void unmask_irq_ioc(int irq_nr, int space_id) +static void unmask_irq_ioc(unsigned int irq) { /* 0: mask */ + unsigned int irq_nr = irq - JMR3927_IRQ_IOC; unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); unsigned int bit = 1 << irq_nr; jmr3927_ioc_reg_out(imask | bit, JMR3927_IOC_INTM_ADDR); @@ -177,8 +80,9 @@ static void unmask_irq_ioc(int irq_nr, int space_id) (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); } -static void mask_irq_irc(int irq_nr, int space_id) +static void mask_irq_irc(unsigned int irq) { + unsigned int irq_nr = irq - JMR3927_IRQ_IRC; volatile unsigned long *ilrp = &tx3927_ircptr->ilr[irq_nr / 2]; if (irq_nr & 1) *ilrp = (*ilrp & 0x00ff) | (irc_dlevel << 8); @@ -191,8 +95,9 @@ static void mask_irq_irc(int irq_nr, int space_id) (void)tx3927_ircptr->ssr; } -static void unmask_irq_irc(int irq_nr, int space_id) +static void unmask_irq_irc(unsigned int irq) { + unsigned int irq_nr = irq - JMR3927_IRQ_IRC; volatile unsigned long *ilrp = &tx3927_ircptr->ilr[irq_nr / 2]; if (irq_nr & 1) *ilrp = (*ilrp & 0x00ff) | (irc_level[irq_nr] << 8); @@ -203,98 +108,14 @@ static void unmask_irq_irc(int irq_nr, int space_id) tx3927_ircptr->imr = irc_elevel; } -struct tb_irq_space jmr3927_isac_irqspace = { - .next = NULL, - .start_irqno = JMR3927_IRQ_ISAC, - nr_irqs : JMR3927_NR_IRQ_ISAC, - .mask_func = mask_irq_isac, - .unmask_func = unmask_irq_isac, - .name = "ISAC", - .space_id = 0, - can_share : 0 -}; -struct tb_irq_space jmr3927_ioc_irqspace = { - .next = NULL, - .start_irqno = JMR3927_IRQ_IOC, - nr_irqs : JMR3927_NR_IRQ_IOC, - .mask_func = mask_irq_ioc, - .unmask_func = unmask_irq_ioc, - .name = "IOC", - .space_id = 0, - can_share : 1 -}; - -struct tb_irq_space jmr3927_irc_irqspace = { - .next = NULL, - .start_irqno = JMR3927_IRQ_IRC, - .nr_irqs = JMR3927_NR_IRQ_IRC, - .mask_func = mask_irq_irc, - .unmask_func = unmask_irq_irc, - .name = "on-chip", - .space_id = 0, - .can_share = 0 -}; - - -#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND -static int tx_branch_likely_bug_count = 0; -static int have_tx_branch_likely_bug = 0; - -static void tx_branch_likely_bug_fixup(void) -{ - struct pt_regs *regs = get_irq_regs(); - - /* TX39/49-BUG: Under this condition, the insn in delay slot - of the branch likely insn is executed (not nullified) even - the branch condition is false. */ - if (!have_tx_branch_likely_bug) - return; - if ((regs->cp0_epc & 0xfff) == 0xffc && - KSEGX(regs->cp0_epc) != KSEG0 && - KSEGX(regs->cp0_epc) != KSEG1) { - unsigned int insn = *(unsigned int*)(regs->cp0_epc - 4); - /* beql,bnel,blezl,bgtzl */ - /* bltzl,bgezl,blezall,bgezall */ - /* bczfl, bcztl */ - if ((insn & 0xf0000000) == 0x50000000 || - (insn & 0xfc0e0000) == 0x04020000 || - (insn & 0xf3fe0000) == 0x41020000) { - regs->cp0_epc -= 4; - tx_branch_likely_bug_count++; - printk(KERN_INFO - "fix branch-likery bug in %s (insn %08x)\n", - current->comm, insn); - } - } -} -#endif - -static void jmr3927_spurious(void) -{ - struct pt_regs * regs = get_irq_regs(); - -#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND - tx_branch_likely_bug_fixup(); -#endif - printk(KERN_WARNING "spurious interrupt (cause 0x%lx, pc 0x%lx, ra 0x%lx).\n", - regs->cp0_cause, regs->cp0_epc, regs->regs[31]); -} - asmlinkage void plat_irq_dispatch(void) { - struct pt_regs * regs = get_irq_regs(); + unsigned long cp0_cause = read_c0_cause(); int irq; -#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND - tx_branch_likely_bug_fixup(); -#endif - if ((regs->cp0_cause & CAUSEF_IP7) == 0) { -#if 0 - jmr3927_spurious(); -#endif + if ((cp0_cause & CAUSEF_IP7) == 0) return; - } - irq = (regs->cp0_cause >> CAUSEB_IP2) & 0x0f; + irq = (cp0_cause >> CAUSEB_IP2) & 0x0f; do_IRQ(irq + JMR3927_IRQ_IRC); } @@ -317,35 +138,6 @@ static struct irqaction ioc_action = { jmr3927_ioc_interrupt, 0, CPU_MASK_NONE, "IOC", NULL, NULL, }; -static irqreturn_t jmr3927_isac_interrupt(int irq, void *dev_id) -{ - unsigned char istat = jmr3927_isac_reg_in(JMR3927_ISAC_INTS2_ADDR); - int i; - - for (i = 0; i < JMR3927_NR_IRQ_ISAC; i++) { - if (istat & (1 << i)) { - irq = JMR3927_IRQ_ISAC + i; - do_IRQ(irq); - } - } - return IRQ_HANDLED; -} - -static struct irqaction isac_action = { - jmr3927_isac_interrupt, 0, CPU_MASK_NONE, "ISAC", NULL, NULL, -}; - - -static irqreturn_t jmr3927_isaerr_interrupt(int irq, void *dev_id) -{ - printk(KERN_WARNING "ISA error interrupt (irq 0x%x).\n", irq); - - return IRQ_HANDLED; -} -static struct irqaction isaerr_action = { - jmr3927_isaerr_interrupt, 0, CPU_MASK_NONE, "ISA error", NULL, NULL, -}; - static irqreturn_t jmr3927_pcierr_interrupt(int irq, void *dev_id) { printk(KERN_WARNING "PCI error interrupt (irq 0x%x).\n", irq); @@ -358,54 +150,19 @@ static struct irqaction pcierr_action = { jmr3927_pcierr_interrupt, 0, CPU_MASK_NONE, "PCI error", NULL, NULL, }; -int jmr3927_ether1_irq = 0; - -void jmr3927_irq_init(u32 irq_base); +static void __init jmr3927_irq_init(void); void __init arch_init_irq(void) { - /* look for io board's presence */ - int have_isac = jmr3927_have_isac(); - /* Now, interrupt control disabled, */ /* all IRC interrupts are masked, */ /* all IRC interrupt mode are Low Active. */ - if (have_isac) { - - /* ETHER1 (NE2000 compatible 10M-Ether) parameter setup */ - /* temporary enable interrupt control */ - tx3927_ircptr->cer = 1; - /* ETHER1 Int. Is High-Active. */ - if (tx3927_ircptr->ssr & (1 << 0)) - jmr3927_ether1_irq = JMR3927_IRQ_IRC_INT0; -#if 0 /* INT3 may be asserted by ether0 (even after reboot...) */ - else if (tx3927_ircptr->ssr & (1 << 3)) - jmr3927_ether1_irq = JMR3927_IRQ_IRC_INT3; -#endif - /* disable interrupt control */ - tx3927_ircptr->cer = 0; - - /* Ether1: High Active */ - if (jmr3927_ether1_irq) { - int ether1_irc = jmr3927_ether1_irq - JMR3927_IRQ_IRC; - tx3927_ircptr->cr[ether1_irc / 8] |= - TX3927_IRCR_HIGH << ((ether1_irc % 8) * 2); - } - } - /* mask all IOC interrupts */ jmr3927_ioc_reg_out(0, JMR3927_IOC_INTM_ADDR); /* setup IOC interrupt mode (SOFT:High Active, Others:Low Active) */ jmr3927_ioc_reg_out(JMR3927_IOC_INTF_SOFT, JMR3927_IOC_INTP_ADDR); - if (have_isac) { - /* mask all ISAC interrupts */ - jmr3927_isac_reg_out(0, JMR3927_ISAC_INTM_ADDR); - /* setup ISAC interrupt mode (ISAIRQ3,ISAIRQ5:Low Active ???) */ - jmr3927_isac_reg_out(JMR3927_ISAC_INTF_IRQ3|JMR3927_ISAC_INTF_IRQ5, JMR3927_ISAC_INTP_ADDR); - } - /* clear PCI Soft interrupts */ jmr3927_ioc_reg_out(0, JMR3927_IOC_INTS1_ADDR); /* clear PCI Reset interrupts */ @@ -415,21 +172,11 @@ void __init arch_init_irq(void) tx3927_ircptr->cer = TX3927_IRCER_ICE; tx3927_ircptr->imr = irc_elevel; - jmr3927_irq_init(NR_ISA_IRQS); - - /* setup irq space */ - add_tb_irq_space(&jmr3927_isac_irqspace); - add_tb_irq_space(&jmr3927_ioc_irqspace); - add_tb_irq_space(&jmr3927_irc_irqspace); + jmr3927_irq_init(); /* setup IOC interrupt 1 (PCI, MODEM) */ setup_irq(JMR3927_IRQ_IOCINT, &ioc_action); - if (have_isac) { - setup_irq(JMR3927_IRQ_ISACINT, &isac_action); - setup_irq(JMR3927_IRQ_ISAC_ISAER, &isaerr_action); - } - #ifdef CONFIG_PCI setup_irq(JMR3927_IRQ_IRC_PCI, &pcierr_action); #endif @@ -438,21 +185,28 @@ void __init arch_init_irq(void) set_c0_status(ST0_IM); /* IE bit is still 0. */ } -static struct irq_chip jmr3927_irq_controller = { - .name = "jmr3927_irq", - .ack = jmr3927_irq_ack, - .mask = jmr3927_irq_disable, - .mask_ack = jmr3927_irq_ack, - .unmask = jmr3927_irq_enable, - .end = jmr3927_irq_end, +static struct irq_chip jmr3927_irq_ioc = { + .name = "jmr3927_ioc", + .ack = mask_irq_ioc, + .mask = mask_irq_ioc, + .mask_ack = mask_irq_ioc, + .unmask = unmask_irq_ioc, }; -void jmr3927_irq_init(u32 irq_base) +static struct irq_chip jmr3927_irq_irc = { + .name = "jmr3927_irc", + .ack = mask_irq_irc, + .mask = mask_irq_irc, + .mask_ack = mask_irq_irc, + .unmask = unmask_irq_irc, +}; + +static void __init jmr3927_irq_init(void) { u32 i; - for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++) - set_irq_chip(i, &jmr3927_irq_controller); - - jmr3927_irq_base = irq_base; + for (i = JMR3927_IRQ_IRC; i < JMR3927_IRQ_IRC + JMR3927_NR_IRQ_IRC; i++) + set_irq_chip_and_handler(i, &jmr3927_irq_irc, handle_level_irq); + for (i = JMR3927_IRQ_IOC; i < JMR3927_IRQ_IOC + JMR3927_NR_IRQ_IOC; i++) + set_irq_chip_and_handler(i, &jmr3927_irq_ioc, handle_level_irq); } diff --git a/arch/mips/jmr3927/rbhma3100/kgdb_io.c b/arch/mips/jmr3927/rbhma3100/kgdb_io.c index 269a42deae0..2604f2c9a96 100644 --- a/arch/mips/jmr3927/rbhma3100/kgdb_io.c +++ b/arch/mips/jmr3927/rbhma3100/kgdb_io.c @@ -31,23 +31,12 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/types.h> -#include <asm/jmr3927/txx927.h> -#include <asm/jmr3927/tx3927.h> #include <asm/jmr3927/jmr3927.h> #define TIMEOUT 0xffffff -#define SLOW_DOWN - -static const char digits[16] = "0123456789abcdef"; - -#ifdef SLOW_DOWN -#define slow_down() { int k; for (k=0; k<10000; k++); } -#else -#define slow_down() -#endif static int remoteDebugInitialized = 0; +static void debugInit(int baud) int putDebugChar(unsigned char c) { @@ -103,20 +92,8 @@ unsigned char getDebugChar(void) return c; } -void debugInit(int baud) +static void debugInit(int baud) { - /* - volatile unsigned long lcr; - volatile unsigned long dicr; - volatile unsigned long disr; - volatile unsigned long cisr; - volatile unsigned long fcr; - volatile unsigned long flcr; - volatile unsigned long bgr; - volatile unsigned long tfifo; - volatile unsigned long rfifo; - */ - tx3927_sioptr(0)->lcr = 0x020; tx3927_sioptr(0)->dicr = 0; tx3927_sioptr(0)->disr = 0x4100; @@ -125,31 +102,4 @@ void debugInit(int baud) tx3927_sioptr(0)->flcr = 0x02; tx3927_sioptr(0)->bgr = ((JMR3927_BASE_BAUD + baud / 2) / baud) | TXx927_SIBGR_BCLK_T0; -#if 0 - /* - * Reset the UART. - */ - tx3927_sioptr(0)->fcr = TXx927_SIFCR_SWRST; - while (tx3927_sioptr(0)->fcr & TXx927_SIFCR_SWRST) - ; - - /* - * and set the speed of the serial port - * (currently hardwired to 9600 8N1 - */ - - tx3927_sioptr(0)->lcr = TXx927_SILCR_UMODE_8BIT | - TXx927_SILCR_USBL_1BIT | - TXx927_SILCR_SCS_IMCLK_BG; - tx3927_sioptr(0)->bgr = - ((JMR3927_BASE_BAUD + baud / 2) / baud) | - TXx927_SIBGR_BCLK_T0; - - /* HW RTS/CTS control */ - if (ser->flags & ASYNC_HAVE_CTS_LINE) - tx3927_sioptr(0)->flcr = TXx927_SIFLCR_RCS | TXx927_SIFLCR_TES | - TXx927_SIFLCR_RTSTL_MAX /* 15 */; - /* Enable RX/TX */ - tx3927_sioptr(0)->flcr &= ~(TXx927_SIFLCR_RSDE | TXx927_SIFLCR_TSDE); -#endif } diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index fc523bda068..d1ef2895d56 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c @@ -54,87 +54,18 @@ #include <asm/addrspace.h> #include <asm/time.h> -#include <asm/bcache.h> -#include <asm/irq.h> #include <asm/reboot.h> -#include <asm/gdb-stub.h> #include <asm/jmr3927/jmr3927.h> #include <asm/mipsregs.h> -#include <asm/traps.h> -extern void puts(unsigned char *cp); +extern void puts(const char *cp); /* Tick Timer divider */ #define JMR3927_TIMER_CCD 0 /* 1/2 */ #define JMR3927_TIMER_CLK (JMR3927_IMCLK / (2 << JMR3927_TIMER_CCD)) -unsigned char led_state = 0xf; - -struct { - struct resource ram0; - struct resource ram1; - struct resource pcimem; - struct resource iob; - struct resource ioc; - struct resource pciio; - struct resource jmy1394; - struct resource rom1; - struct resource rom0; - struct resource sio0; - struct resource sio1; -} jmr3927_resources = { - { - .start = 0, - .end = 0x01FFFFFF, - .name = "RAM0", - .flags = IORESOURCE_MEM - }, { - .start = 0x02000000, - .end = 0x03FFFFFF, - .name = "RAM1", - .flags = IORESOURCE_MEM - }, { - .start = 0x08000000, - .end = 0x07FFFFFF, - .name = "PCIMEM", - .flags = IORESOURCE_MEM - }, { - .start = 0x10000000, - .end = 0x13FFFFFF, - .name = "IOB" - }, { - .start = 0x14000000, - .end = 0x14FFFFFF, - .name = "IOC" - }, { - .start = 0x15000000, - .end = 0x15FFFFFF, - .name = "PCIIO" - }, { - .start = 0x1D000000, - .end = 0x1D3FFFFF, - .name = "JMY1394" - }, { - .start = 0x1E000000, - .end = 0x1E3FFFFF, - .name = "ROM1" - }, { - .start = 0x1FC00000, - .end = 0x1FFFFFFF, - .name = "ROM0" - }, { - .start = 0xFFFEF300, - .end = 0xFFFEF3FF, - .name = "SIO0" - }, { - .start = 0xFFFEF400, - .end = 0xFFFEF4FF, - .name = "SIO1" - }, -}; - /* don't enable - see errata */ -int jmr3927_ccfg_toeon = 0; +static int jmr3927_ccfg_toeon; static inline void do_reset(void) { @@ -173,9 +104,15 @@ static cycle_t jmr3927_hpt_read(void) return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr; } +static void jmr3927_timer_ack(void) +{ + jmr3927_tmrptr->tisr = 0; /* ack interrupt */ +} + static void __init jmr3927_time_init(void) { clocksource_mips.read = jmr3927_hpt_read; + mips_timer_ack = jmr3927_timer_ack; mips_hpt_frequency = JMR3927_TIMER_CLK; } @@ -190,9 +127,6 @@ void __init plat_timer_setup(struct irqaction *irq) setup_irq(JMR3927_IRQ_TICK, irq); } -#define USECS_PER_JIFFY (1000000/HZ) - -//#undef DO_WRITE_THROUGH #define DO_WRITE_THROUGH #define DO_ENABLE_CACHE @@ -224,12 +158,6 @@ void __init plat_mem_setup(void) /* Reboot on panic */ panic_timeout = 180; - { - unsigned int conf; - conf = read_c0_conf(); - } - -#if 1 /* cache setup */ { unsigned int conf; @@ -256,16 +184,14 @@ void __init plat_mem_setup(void) write_c0_conf(conf); write_c0_cache(0); } -#endif /* initialize board */ jmr3927_board_init(); argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "toeon")) != NULL) { - jmr3927_ccfg_toeon = 1; - } + if ((argptr = strstr(argptr, "toeon")) != NULL) + jmr3927_ccfg_toeon = 1; argptr = prom_getcmdline(); if ((argptr = strstr(argptr, "ip=")) == NULL) { argptr = prom_getcmdline(); @@ -281,7 +207,7 @@ void __init plat_mem_setup(void) memset(&req, 0, sizeof(req)); req.line = i; req.iotype = UPIO_MEM; - req.membase = (char *)TX3927_SIO_REG(i); + req.membase = (unsigned char __iomem *)TX3927_SIO_REG(i); req.mapbase = TX3927_SIO_REG(i); req.irq = i == 0 ? JMR3927_IRQ_IRC_SIO0 : JMR3927_IRQ_IRC_SIO1; @@ -303,65 +229,33 @@ void __init plat_mem_setup(void) static void tx3927_setup(void); -#ifdef CONFIG_PCI -unsigned long mips_pci_io_base; -unsigned long mips_pci_io_size; -unsigned long mips_pci_mem_base; -unsigned long mips_pci_mem_size; -/* for legacy I/O, PCI I/O PCI Bus address must be 0 */ -unsigned long mips_pci_io_pciaddr = 0; -#endif - static void __init jmr3927_board_init(void) { - char *argptr; - -#ifdef CONFIG_PCI - mips_pci_io_base = JMR3927_PCIIO; - mips_pci_io_size = JMR3927_PCIIO_SIZE; - mips_pci_mem_base = JMR3927_PCIMEM; - mips_pci_mem_size = JMR3927_PCIMEM_SIZE; -#endif - tx3927_setup(); - if (jmr3927_have_isac()) { - -#ifdef CONFIG_FB_E1355 - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "video=")) == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " video=e1355fb:crt16h"); - } -#endif - -#ifdef CONFIG_BLK_DEV_IDE - /* overrides PCI-IDE */ -#endif - } - /* SIO0 DTR on */ jmr3927_ioc_reg_out(0, JMR3927_IOC_DTR_ADDR); jmr3927_led_set(0); - - if (jmr3927_have_isac()) - jmr3927_io_led_set(0); printk("JMR-TX3927 (Rev %d) --- IOC(Rev %d) DIPSW:%d,%d,%d,%d\n", jmr3927_ioc_reg_in(JMR3927_IOC_BREV_ADDR) & JMR3927_REV_MASK, jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR) & JMR3927_REV_MASK, jmr3927_dipsw1(), jmr3927_dipsw2(), jmr3927_dipsw3(), jmr3927_dipsw4()); - if (jmr3927_have_isac()) - printk("JMI-3927IO2 --- ISAC(Rev %d) DIPSW:%01x\n", - jmr3927_isac_reg_in(JMR3927_ISAC_REV_ADDR) & JMR3927_REV_MASK, - jmr3927_io_dipsw()); } -void __init tx3927_setup(void) +static void __init tx3927_setup(void) { int i; +#ifdef CONFIG_PCI + unsigned long mips_pci_io_base = JMR3927_PCIIO; + unsigned long mips_pci_io_size = JMR3927_PCIIO_SIZE; + unsigned long mips_pci_mem_base = JMR3927_PCIMEM; + unsigned long mips_pci_mem_size = JMR3927_PCIMEM_SIZE; + /* for legacy I/O, PCI I/O PCI Bus address must be 0 */ + unsigned long mips_pci_io_pciaddr = 0; +#endif /* SDRAMC are configured by PROM */ @@ -475,10 +369,8 @@ void __init tx3927_setup(void) tx3927_pcicptr->mbas = ~(mips_pci_mem_size - 1); tx3927_pcicptr->mba = 0; tx3927_pcicptr->tlbmma = 0; -#ifndef JMR3927_INIT_INDIRECT_PCI /* Enable Direct mapping Address Space Decoder */ tx3927_pcicptr->lbc |= TX3927_PCIC_LBC_ILMDE | TX3927_PCIC_LBC_ILIDE; -#endif /* Clear All Local Bus Status */ tx3927_pcicptr->lbstat = TX3927_PCIC_LBIM_ALL; @@ -491,22 +383,15 @@ void __init tx3927_setup(void) /* PCIC Int => IRC IRQ10 */ tx3927_pcicptr->il = TX3927_IR_PCI; -#if 1 /* Target Control (per errata) */ tx3927_pcicptr->tc = TX3927_PCIC_TC_OF8E | TX3927_PCIC_TC_IF8E; -#endif /* Enable Bus Arbiter */ -#if 0 - tx3927_pcicptr->req_trace = 0x73737373; -#endif tx3927_pcicptr->pbapmc = TX3927_PCIC_PBAPMC_PBAEN; tx3927_pcicptr->pcicmd = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | -#if 1 PCI_COMMAND_IO | -#endif PCI_COMMAND_PARITY | PCI_COMMAND_SERR; } #endif /* CONFIG_PCI */ @@ -555,8 +440,6 @@ static int __init jmr3927_rtc_init(void) .flags = IORESOURCE_MEM, }; struct platform_device *dev; - if (!jmr3927_have_nvram()) - return -ENODEV; dev = platform_device_register_simple("ds1742", -1, &res, 1); return IS_ERR(dev) ? PTR_ERR(dev) : 0; } diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 222de465db7..761a779d5c4 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -102,7 +102,6 @@ void output_thread_info_defines(void) offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit); offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block); offset("#define TI_REGS ", struct thread_info, regs); - constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER); constant("#define _THREAD_SIZE ", THREAD_SIZE); constant("#define _THREAD_MASK ", THREAD_MASK); linefeed; diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index 9c79703979b..2345160e63f 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c @@ -328,8 +328,8 @@ void __init init_i8259_irqs (void) { int i; - request_resource(&ioport_resource, &pic1_io_resource); - request_resource(&ioport_resource, &pic2_io_resource); + insert_resource(&ioport_resource, &pic1_io_resource); + insert_resource(&ioport_resource, &pic2_io_resource); init_8259A(0); diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index 29eadd404fa..c6580018c94 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c @@ -17,6 +17,7 @@ */ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/sched.h> #include <linux/unistd.h> #include <linux/file.h> #include <linux/fs.h> @@ -198,7 +199,6 @@ void sp_work_handle_request(void) int cmd; char *vcwd; - mm_segment_t old_fs; int size; ret.retval = -1; @@ -241,8 +241,6 @@ void sp_work_handle_request(void) if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv, (int)&tz, 0,0)) == 0) ret.retval = tv.tv_sec; - - ret.errno = errno; break; case MTSP_SYSCALL_EXIT: @@ -279,7 +277,6 @@ void sp_work_handle_request(void) if (cmd >= 0) { ret.retval = sp_syscall(cmd, generic.arg0, generic.arg1, generic.arg2, generic.arg3); - ret.errno = errno; } else printk(KERN_WARNING "KSPD: Unknown SP syscall number %d\n", sc.cmd); diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index e6e3047151a..bfc8ca168f8 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -289,7 +289,7 @@ unsigned int rtlx_write_poll(int index) return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size); } -ssize_t rtlx_read(int index, void __user *buff, size_t count, int user) +ssize_t rtlx_read(int index, void __user *buff, size_t count) { size_t lx_write, fl = 0L; struct rtlx_channel *lx; @@ -331,9 +331,10 @@ out: return count; } -ssize_t rtlx_write(int index, const void __user *buffer, size_t count, int user) +ssize_t rtlx_write(int index, const void __user *buffer, size_t count) { struct rtlx_channel *rt; + unsigned long failed; size_t rt_read; size_t fl; @@ -363,7 +364,7 @@ ssize_t rtlx_write(int index, const void __user *buffer, size_t count, int user) } out: - count -= cailed; + count -= failed; smp_wmb(); rt->rt_write = (rt->rt_write + count) % rt->buffer_size; diff --git a/arch/mips/mips-boards/generic/display.c b/arch/mips/mips-boards/generic/display.c index f653946afc2..548dbe5ce7c 100644 --- a/arch/mips/mips-boards/generic/display.c +++ b/arch/mips/mips-boards/generic/display.c @@ -24,16 +24,16 @@ void mips_display_message(const char *str) { - static volatile unsigned int *display = NULL; + static unsigned int __iomem *display = NULL; int i; if (unlikely(display == NULL)) - display = (volatile unsigned int *)ioremap(ASCII_DISPLAY_POS_BASE, 16*sizeof(int)); + display = ioremap(ASCII_DISPLAY_POS_BASE, 16*sizeof(int)); for (i = 0; i <= 14; i=i+2) { if (*str) - display[i] = *str++; + writel(*str++, display + i); else - display[i] = ' '; + writel(' ', display + i); } } diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c index 3192a14698c..f98d60f7865 100644 --- a/arch/mips/mips-boards/generic/pci.c +++ b/arch/mips/mips-boards/generic/pci.c @@ -65,7 +65,7 @@ static struct resource msc_io_resource = { }; extern struct pci_ops bonito64_pci_ops; -extern struct pci_ops gt64120_pci_ops; +extern struct pci_ops gt64xxx_pci0_ops; extern struct pci_ops msc_pci_ops; static struct pci_controller bonito64_controller = { @@ -76,7 +76,7 @@ static struct pci_controller bonito64_controller = { }; static struct pci_controller gt64120_controller = { - .pci_ops = >64120_pci_ops, + .pci_ops = >64xxx_pci0_ops, .io_resource = >64120_io_resource, .mem_resource = >64120_mem_resource, }; diff --git a/arch/mips/mips-boards/generic/reset.c b/arch/mips/mips-boards/generic/reset.c index 0996ba368b2..7a1bb51f81e 100644 --- a/arch/mips/mips-boards/generic/reset.c +++ b/arch/mips/mips-boards/generic/reset.c @@ -39,24 +39,24 @@ static void atlas_machine_power_off(void); static void mips_machine_restart(char *command) { - volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int)); + unsigned int __iomem *softres_reg = ioremap(SOFTRES_REG, sizeof(unsigned int)); - *softres_reg = GORESET; + writew(GORESET, softres_reg); } static void mips_machine_halt(void) { - volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int)); + unsigned int __iomem *softres_reg = ioremap(SOFTRES_REG, sizeof(unsigned int)); - *softres_reg = GORESET; + writew(GORESET, softres_reg); } #if defined(CONFIG_MIPS_ATLAS) static void atlas_machine_power_off(void) { - volatile unsigned int *psustby_reg = (unsigned int *)ioremap(ATLAS_PSUSTBY_REG, sizeof(unsigned int)); + unsigned int __iomem *psustby_reg = ioremap(ATLAS_PSUSTBY_REG, sizeof(unsigned int)); - *psustby_reg = ATLAS_GOSTBY; + writew(ATLAS_GOSTBY, psustby_reg); } #endif diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c index 3c206bb1716..83d76025d61 100644 --- a/arch/mips/mips-boards/malta/malta_int.c +++ b/arch/mips/mips-boards/malta/malta_int.c @@ -42,8 +42,6 @@ #include <asm/mips-boards/msc01_pci.h> #include <asm/msc01_ic.h> -extern void mips_timer_interrupt(void); - static DEFINE_SPINLOCK(mips_irq_lock); static inline int mips_pcibios_iack(void) @@ -85,7 +83,7 @@ static inline int mips_pcibios_iack(void) dummy = BONITO_PCIMAP_CFG; iob(); /* sync */ - irq = *(volatile u32 *)(_pcictrl_bonito_pcicfg); + irq = readl((u32 *)_pcictrl_bonito_pcicfg); iob(); /* sync */ irq &= 0xff; BONITO_PCIMAP_CFG = 0; diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c index 56ea76679cd..7873932532a 100644 --- a/arch/mips/mips-boards/malta/malta_setup.c +++ b/arch/mips/mips-boards/malta/malta_setup.c @@ -145,7 +145,8 @@ void __init plat_mem_setup(void) #ifdef CONFIG_BLK_DEV_IDE /* Check PCI clock */ { - int jmpr = (*((volatile unsigned int *)ioremap(MALTA_JMPRS_REG, sizeof(unsigned int))) >> 2) & 0x07; + unsigned int __iomem *jmpr_p = (unsigned int *) ioremap(MALTA_JMPRS_REG, sizeof(unsigned int)); + int jmpr = (readw(jmpr_p) >> 2) & 0x07; static const int pciclocks[] __initdata = { 33, 20, 25, 30, 12, 16, 37, 10 }; @@ -179,7 +180,6 @@ void __init plat_mem_setup(void) }; #endif #endif - mips_reboot_setup(); board_time_init = mips_time_init; diff --git a/arch/mips/mips-boards/sim/Makefile b/arch/mips/mips-boards/sim/Makefile index 6aeebc9122f..dc0bfda1142 100644 --- a/arch/mips/mips-boards/sim/Makefile +++ b/arch/mips/mips-boards/sim/Makefile @@ -17,7 +17,8 @@ # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. # -obj-y := sim_setup.o sim_mem.o sim_time.o sim_int.o sim_cmdline.o +obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o \ + sim_cmdline.o obj-$(CONFIG_EARLY_PRINTK) += sim_console.o obj-$(CONFIG_SMP) += sim_smp.o diff --git a/arch/mips/mips-boards/sim/sim_platform.c b/arch/mips/mips-boards/sim/sim_platform.c new file mode 100644 index 00000000000..53210a8c5de --- /dev/null +++ b/arch/mips/mips-boards/sim/sim_platform.c @@ -0,0 +1,35 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 by Ralf Baechle (ralf@linux-mips.org) + */ +#include <linux/init.h> +#include <linux/if_ether.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> + +static char mipsnet_string[] = "mipsnet"; + +static struct platform_device eth1_device = { + .name = mipsnet_string, + .id = 0, +}; + +/* + * Create a platform device for the GPI port that receives the + * image data from the embedded camera. + */ +static int __init mipsnet_devinit(void) +{ + int err; + + err = platform_device_register(ð1_device); + if (err) + printk(KERN_ERR "%s: registration failed\n", mipsnet_string); + + return err; +} + +device_initcall(mipsnet_devinit); diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 4e8f1b68337..abf99b1eba1 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -96,7 +96,7 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr) kaddr = kmap_coherent(page, vmaddr); flush_data_cache_page((unsigned long)kaddr); - kunmap_coherent(kaddr); + kunmap_coherent(); } } diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index e9951c0e689..2d1c2c02482 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -177,7 +177,7 @@ void *kmap_coherent(struct page *page, unsigned long addr) #define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) -void kunmap_coherent(struct page *page) +void kunmap_coherent(void) { #ifndef CONFIG_MIPS_MT_SMTC unsigned int wired; @@ -210,7 +210,7 @@ void copy_user_highpage(struct page *to, struct page *from, if (cpu_has_dc_aliases) { vfrom = kmap_coherent(from, vaddr); copy_page(vto, vfrom); - kunmap_coherent(from); + kunmap_coherent(); } else { vfrom = kmap_atomic(from, KM_USER0); copy_page(vto, vfrom); @@ -233,7 +233,7 @@ void copy_to_user_page(struct vm_area_struct *vma, if (cpu_has_dc_aliases) { void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(vto, src, len); - kunmap_coherent(page); + kunmap_coherent(); } else memcpy(dst, src, len); if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) @@ -250,7 +250,7 @@ void copy_from_user_page(struct vm_area_struct *vma, void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(dst, vfrom, len); - kunmap_coherent(page); + kunmap_coherent(); } else memcpy(dst, src, len); } @@ -351,18 +351,15 @@ void __init paging_init(void) #endif kmap_coherent_init(); -#ifdef CONFIG_ISA - if (max_low_pfn >= MAX_DMA_PFN) - if (min_low_pfn >= MAX_DMA_PFN) { - zones_size[ZONE_DMA] = 0; - zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; - } else { - zones_size[ZONE_DMA] = MAX_DMA_PFN - min_low_pfn; - zones_size[ZONE_NORMAL] = max_low_pfn - MAX_DMA_PFN; - } +#ifdef CONFIG_ZONE_DMA + if (min_low_pfn < MAX_DMA_PFN && MAX_DMA_PFN <= max_low_pfn) { + zones_size[ZONE_DMA] = MAX_DMA_PFN - min_low_pfn; + zones_size[ZONE_NORMAL] = max_low_pfn - MAX_DMA_PFN; + } else if (max_low_pfn < MAX_DMA_PFN) + zones_size[ZONE_DMA] = max_low_pfn - min_low_pfn; else #endif - zones_size[ZONE_DMA] = max_low_pfn - min_low_pfn; + zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; #ifdef CONFIG_HIGHMEM zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn; diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index bf85995ca04..df487c063b1 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -8,8 +8,7 @@ obj-y += pci.o pci-dac.o # PCI bus host bridge specific code # obj-$(CONFIG_MIPS_BONITO64) += ops-bonito64.o -obj-$(CONFIG_MIPS_GT64111) += ops-gt64111.o -obj-$(CONFIG_MIPS_GT64120) += ops-gt64120.o +obj-$(CONFIG_PCI_GT64XXX_PCI0) += ops-gt64xxx_pci0.o obj-$(CONFIG_PCI_MARVELL) += ops-marvell.o obj-$(CONFIG_MIPS_MSC) += ops-msc.o obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o diff --git a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c index 6e72d213f4c..73d18503517 100644 --- a/arch/mips/pci/fixup-jmr3927.c +++ b/arch/mips/pci/fixup-jmr3927.c @@ -29,7 +29,6 @@ */ #include <linux/types.h> #include <linux/pci.h> -#include <linux/kernel.h> #include <linux/init.h> #include <asm/jmr3927/jmr3927.h> @@ -81,14 +80,8 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) /* Check OnBoard Ethernet (IDSEL=A24, DevNu=13) */ if (dev->bus->parent == NULL && - slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(24)) { - extern int jmr3927_ether1_irq; - /* check this irq line was reserved for ether1 */ - if (jmr3927_ether1_irq != JMR3927_IRQ_ETHER0) - irq = JMR3927_IRQ_ETHER0; - else - irq = 0; /* disable */ - } + slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(24)) + irq = JMR3927_IRQ_ETHER0; return irq; } diff --git a/arch/mips/pci/ops-gt64111.c b/arch/mips/pci/ops-gt64111.c deleted file mode 100644 index ecd3991bd0e..00000000000 --- a/arch/mips/pci/ops-gt64111.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1995, 1996, 1997, 2002 by Ralf Baechle - * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) - */ -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/init.h> - -#include <asm/pci.h> -#include <asm/io.h> -#include <asm/gt64120.h> - -#include <asm/mach-cobalt/cobalt.h> - -/* - * Device 31 on the GT64111 is used to generate PCI special - * cycles, so we shouldn't expected to find a device there ... - */ -static inline int pci_range_ck(struct pci_bus *bus, unsigned int devfn) -{ - if (bus->number == 0 && PCI_SLOT(devfn) < 31) - return 0; - - return -1; -} - -static int gt64111_pci_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * val) -{ - if (pci_range_ck(bus, devfn)) - return PCIBIOS_DEVICE_NOT_FOUND; - - switch (size) { - case 4: - PCI_CFG_SET(devfn, where); - *val = GT_READ(GT_PCI0_CFGDATA_OFS); - return PCIBIOS_SUCCESSFUL; - - case 2: - PCI_CFG_SET(devfn, (where & ~0x3)); - *val = GT_READ(GT_PCI0_CFGDATA_OFS) - >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; - - case 1: - PCI_CFG_SET(devfn, (where & ~0x3)); - *val = GT_READ(GT_PCI0_CFGDATA_OFS) - >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; - } - - return PCIBIOS_BAD_REGISTER_NUMBER; -} - -static int gt64111_pci_write_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 val) -{ - u32 tmp; - - if (pci_range_ck(bus, devfn)) - return PCIBIOS_DEVICE_NOT_FOUND; - - switch (size) { - case 4: - PCI_CFG_SET(devfn, where); - GT_WRITE(GT_PCI0_CFGDATA_OFS, val); - - return PCIBIOS_SUCCESSFUL; - - case 2: - PCI_CFG_SET(devfn, (where & ~0x3)); - tmp = GT_READ(GT_PCI0_CFGDATA_OFS); - tmp &= ~(0xffff << ((where & 0x3) * 8)); - tmp |= (val << ((where & 0x3) * 8)); - GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp); - - return PCIBIOS_SUCCESSFUL; - - case 1: - PCI_CFG_SET(devfn, (where & ~0x3)); - tmp = GT_READ(GT_PCI0_CFGDATA_OFS); - tmp &= ~(0xff << ((where & 0x3) * 8)); - tmp |= (val << ((where & 0x3) * 8)); - GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp); - - return PCIBIOS_SUCCESSFUL; - } - - return PCIBIOS_BAD_REGISTER_NUMBER; -} - -struct pci_ops gt64111_pci_ops = { - .read = gt64111_pci_read_config, - .write = gt64111_pci_write_config, -}; diff --git a/arch/mips/pci/ops-gt64120.c b/arch/mips/pci/ops-gt64xxx_pci0.c index 6335844d607..3d896c5f413 100644 --- a/arch/mips/pci/ops-gt64120.c +++ b/arch/mips/pci/ops-gt64xxx_pci0.c @@ -39,8 +39,8 @@ #define PCI_CFG_TYPE1_DEV_SHF 11 #define PCI_CFG_TYPE1_BUS_SHF 16 -static int gt64120_pcibios_config_access(unsigned char access_type, - struct pci_bus *bus, unsigned int devfn, int where, u32 * data) +static int gt64xxx_pci0_pcibios_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, int where, u32 * data) { unsigned char busnum = bus->number; u32 intr; @@ -100,13 +100,13 @@ static int gt64120_pcibios_config_access(unsigned char access_type, * We can't address 8 and 16 bit words directly. Instead we have to * read/write a 32bit word and mask/modify the data we actually want. */ -static int gt64120_pcibios_read(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * val) +static int gt64xxx_pci0_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) { u32 data = 0; - if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, - &data)) + if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, + where, &data)) return PCIBIOS_DEVICE_NOT_FOUND; if (size == 1) @@ -119,16 +119,16 @@ static int gt64120_pcibios_read(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_SUCCESSFUL; } -static int gt64120_pcibios_write(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 val) +static int gt64xxx_pci0_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) { u32 data = 0; if (size == 4) data = val; else { - if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, - where, &data)) + if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_READ, bus, + devfn, where, &data)) return PCIBIOS_DEVICE_NOT_FOUND; if (size == 1) @@ -139,14 +139,14 @@ static int gt64120_pcibios_write(struct pci_bus *bus, unsigned int devfn, (val << ((where & 3) << 3)); } - if (gt64120_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, - &data)) + if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, + where, &data)) return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_SUCCESSFUL; } -struct pci_ops gt64120_pci_ops = { - .read = gt64120_pcibios_read, - .write = gt64120_pcibios_write +struct pci_ops gt64xxx_pci0_ops = { + .read = gt64xxx_pci0_pcibios_read, + .write = gt64xxx_pci0_pcibios_write }; diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c index 42530a0b84b..aa698bd0d5e 100644 --- a/arch/mips/pci/ops-tx3927.c +++ b/arch/mips/pci/ops-tx3927.c @@ -40,7 +40,6 @@ #include <asm/addrspace.h> #include <asm/jmr3927/jmr3927.h> -#include <asm/debug.h> static inline int mkaddr(unsigned char bus, unsigned char dev_fn, unsigned char where) @@ -130,234 +129,3 @@ struct pci_ops jmr3927_pci_ops = { jmr3927_pci_read_config, jmr3927_pci_write_config, }; - - -#ifndef JMR3927_INIT_INDIRECT_PCI - -inline unsigned long tc_readl(volatile __u32 * addr) -{ - return readl(addr); -} - -inline void tc_writel(unsigned long data, volatile __u32 * addr) -{ - writel(data, addr); -} -#else - -unsigned long tc_readl(volatile __u32 * addr) -{ - unsigned long val; - - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr = - (unsigned long) CPHYSADDR(addr); - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_MEMREAD << PCI_IPCIBE_ICMD_SHIFT) | - PCI_IPCIBE_IBE_LONG; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - val = - le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr-> - ipcidata); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; - return val; -} - -void tc_writel(unsigned long data, volatile __u32 * addr) -{ - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata = - cpu_to_le32(data); - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr = - (unsigned long) CPHYSADDR(addr); - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_MEMWRITE << PCI_IPCIBE_ICMD_SHIFT) | - PCI_IPCIBE_IBE_LONG; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; -} - -unsigned char tx_ioinb(unsigned char *addr) -{ - unsigned long val; - __u32 ioaddr; - int offset; - int byte; - - ioaddr = (unsigned long) addr; - offset = ioaddr & 0x3; - byte = 0xf & ~(8 >> offset); - - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - val = - le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr-> - ipcidata); - val = val & 0xff; - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; - return val; -} - -void tx_iooutb(unsigned long data, unsigned char *addr) -{ - __u32 ioaddr; - int offset; - int byte; - - data = data | (data << 8) | (data << 16) | (data << 24); - ioaddr = (unsigned long) addr; - offset = ioaddr & 0x3; - byte = 0xf & ~(8 >> offset); - - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata = data; - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; -} - -unsigned short tx_ioinw(unsigned short *addr) -{ - unsigned long val; - __u32 ioaddr; - int offset; - int byte; - - ioaddr = (unsigned long) addr; - offset = ioaddr & 0x2; - byte = 3 << offset; - - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - val = - le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr-> - ipcidata); - val = val & 0xffff; - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; - return val; - -} - -void tx_iooutw(unsigned long data, unsigned short *addr) -{ - __u32 ioaddr; - int offset; - int byte; - - data = data | (data << 16); - ioaddr = (unsigned long) addr; - offset = ioaddr & 0x2; - byte = 3 << offset; - - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata = data; - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; -} - -unsigned long tx_ioinl(unsigned int *addr) -{ - unsigned long val; - __u32 ioaddr; - - ioaddr = (unsigned long) addr; - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | - PCI_IPCIBE_IBE_LONG; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - val = - le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr-> - ipcidata); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; - return val; -} - -void tx_iooutl(unsigned long data, unsigned int *addr) -{ - __u32 ioaddr; - - ioaddr = (unsigned long) addr; - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata = - cpu_to_le32(data); - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | - PCI_IPCIBE_IBE_LONG; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; -} - -void tx_insbyte(unsigned char *addr, void *buffer, unsigned int count) -{ - unsigned char *ptr = (unsigned char *) buffer; - - while (count--) { - *ptr++ = tx_ioinb(addr); - } -} - -void tx_insword(unsigned short *addr, void *buffer, unsigned int count) -{ - unsigned short *ptr = (unsigned short *) buffer; - - while (count--) { - *ptr++ = tx_ioinw(addr); - } -} - -void tx_inslong(unsigned int *addr, void *buffer, unsigned int count) -{ - unsigned long *ptr = (unsigned long *) buffer; - - while (count--) { - *ptr++ = tx_ioinl(addr); - } -} - -void tx_outsbyte(unsigned char *addr, void *buffer, unsigned int count) -{ - unsigned char *ptr = (unsigned char *) buffer; - - while (count--) { - tx_iooutb(*ptr++, addr); - } -} - -void tx_outsword(unsigned short *addr, void *buffer, unsigned int count) -{ - unsigned short *ptr = (unsigned short *) buffer; - - while (count--) { - tx_iooutw(*ptr++, addr); - } -} - -void tx_outslong(unsigned int *addr, void *buffer, unsigned int count) -{ - unsigned long *ptr = (unsigned long *) buffer; - - while (count--) { - tx_iooutl(*ptr++, addr); - } -} -#endif diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c index 88fb191ad2e..985784a3e6f 100644 --- a/arch/mips/pci/pci-lasat.c +++ b/arch/mips/pci/pci-lasat.c @@ -12,7 +12,7 @@ #include <asm/bootinfo.h> extern struct pci_ops nile4_pci_ops; -extern struct pci_ops gt64120_pci_ops; +extern struct pci_ops gt64xxx_pci0_ops; static struct resource lasat_pci_mem_resource = { .name = "LASAT PCI MEM", .start = 0x18000000, @@ -38,7 +38,7 @@ static int __init lasat_pci_setup(void) switch (mips_machtype) { case MACH_LASAT_100: - lasat_pci_controller.pci_ops = >64120_pci_ops; + lasat_pci_controller.pci_ops = >64xxx_pci0_ops; break; case MACH_LASAT_200: lasat_pci_controller.pci_ops = &nile4_pci_ops; diff --git a/arch/mips/pci/pci-ocelot.c b/arch/mips/pci/pci-ocelot.c index 2b9495dce6b..7f94f26d35a 100644 --- a/arch/mips/pci/pci-ocelot.c +++ b/arch/mips/pci/pci-ocelot.c @@ -81,7 +81,7 @@ static struct resource ocelot_io_resource = { }; static struct pci_controller ocelot_pci_controller = { - .pci_ops = gt64120_pci_ops; + .pci_ops = gt64xxx_pci0_ops; .mem_resource = &ocelot_mem_resource; .io_resource = &ocelot_io_resource; }; diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index de7cfc559dd..8108231f2e2 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -77,6 +77,13 @@ pcibios_align_resource(void *data, struct resource *res, void __init register_pci_controller(struct pci_controller *hose) { + if (request_resource(&iomem_resource, hose->mem_resource) < 0) + goto out; + if (request_resource(&ioport_resource, hose->io_resource) < 0) { + release_resource(hose->mem_resource); + goto out; + } + *hose_tail = hose; hose_tail = &hose->next; @@ -87,6 +94,11 @@ void __init register_pci_controller(struct pci_controller *hose) printk(KERN_WARNING "registering PCI controller with io_map_base unset\n"); } + return; + +out: + printk(KERN_WARNING + "Skipping PCI bus scan due to resource conflict\n"); } /* Most MIPS systems have straight-forward swizzling needs. */ @@ -121,11 +133,6 @@ static int __init pcibios_init(void) /* Scan all of the recorded PCI controllers. */ for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { - if (request_resource(&iomem_resource, hose->mem_resource) < 0) - goto out; - if (request_resource(&ioport_resource, hose->io_resource) < 0) - goto out_free_mem_resource; - if (!hose->iommu) PCI_DMA_BUS_IS_PHYS = 1; @@ -144,14 +151,6 @@ static int __init pcibios_init(void) need_domain_info = 1; } } - continue; - -out_free_mem_resource: - release_resource(hose->mem_resource); - -out: - printk(KERN_WARNING - "Skipping PCI bus scan due to resource conflict\n"); } if (!pci_probe_only) diff --git a/arch/mips/sgi-ip22/ip22-nvram.c b/arch/mips/sgi-ip22/ip22-nvram.c index fd29fd407ae..e19d60d5fcc 100644 --- a/arch/mips/sgi-ip22/ip22-nvram.c +++ b/arch/mips/sgi-ip22/ip22-nvram.c @@ -52,8 +52,7 @@ * national semiconductor nv ram chip the op code is 3 bits and * the address is 6/8 bits. */ -static inline void eeprom_cmd(volatile unsigned int *ctrl, unsigned cmd, - unsigned reg) +static inline void eeprom_cmd(unsigned int *ctrl, unsigned cmd, unsigned reg) { unsigned short ser_cmd; int i; @@ -61,33 +60,34 @@ static inline void eeprom_cmd(volatile unsigned int *ctrl, unsigned cmd, ser_cmd = cmd | (reg << (16 - BITS_IN_COMMAND)); for (i = 0; i < BITS_IN_COMMAND; i++) { if (ser_cmd & (1<<15)) /* if high order bit set */ - *ctrl |= EEPROM_DATO; + writel(readl(ctrl) | EEPROM_DATO, ctrl); else - *ctrl &= ~EEPROM_DATO; - *ctrl &= ~EEPROM_ECLK; - *ctrl |= EEPROM_ECLK; + writel(readl(ctrl) & ~EEPROM_DATO, ctrl); + writel(readl(ctrl) & ~EEPROM_ECLK, ctrl); + writel(readl(ctrl) | EEPROM_ECLK, ctrl); ser_cmd <<= 1; } - *ctrl &= ~EEPROM_DATO; /* see data sheet timing diagram */ + /* see data sheet timing diagram */ + writel(readl(ctrl) & ~EEPROM_DATO, ctrl); } -unsigned short ip22_eeprom_read(volatile unsigned int *ctrl, int reg) +unsigned short ip22_eeprom_read(unsigned int *ctrl, int reg) { unsigned short res = 0; int i; - *ctrl &= ~EEPROM_EPROT; + writel(readl(ctrl) & ~EEPROM_EPROT, ctrl); eeprom_cs_on(ctrl); eeprom_cmd(ctrl, EEPROM_READ, reg); /* clock the data ouf of serial mem */ for (i = 0; i < 16; i++) { - *ctrl &= ~EEPROM_ECLK; + writel(readl(ctrl) & ~EEPROM_ECLK, ctrl); delay(); - *ctrl |= EEPROM_ECLK; + writel(readl(ctrl) | EEPROM_ECLK, ctrl); delay(); res <<= 1; - if (*ctrl & EEPROM_DATI) + if (readl(ctrl) & EEPROM_DATI) res |= 1; } diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c index 20555473409..8e88a442b22 100644 --- a/arch/mips/sgi-ip22/ip22-time.c +++ b/arch/mips/sgi-ip22/ip22-time.c @@ -94,7 +94,7 @@ static int indy_rtc_set_time(unsigned long tim) static unsigned long dosample(void) { u32 ct0, ct1; - volatile u8 msb, lsb; + u8 msb, lsb; /* Start the counter. */ sgint->tcword = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | @@ -107,21 +107,21 @@ static unsigned long dosample(void) /* Latch and spin until top byte of counter2 is zero */ do { - sgint->tcword = SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT; - lsb = sgint->tcnt2; - msb = sgint->tcnt2; + writeb(SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT, &sgint->tcword); + lsb = readb(&sgint->tcnt2); + msb = readb(&sgint->tcnt2); ct1 = read_c0_count(); } while (msb); /* Stop the counter. */ - sgint->tcword = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | - SGINT_TCWORD_MSWST); + writeb(sgint->tcword, (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | + SGINT_TCWORD_MSWST)); /* * Return the difference, this is how far the r4k counter increments * for every 1/HZ seconds. We round off the nearest 1 MHz of master * clock (= 1000000 / HZ / 2). */ - /*return (ct1 - ct0 + (500000/HZ/2)) / (500000/HZ) * (500000/HZ);*/ + return (ct1 - ct0) / (500000/HZ) * (500000/HZ); } diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig index bdf24a7b549..e6b003ec671 100644 --- a/arch/mips/sibyte/Kconfig +++ b/arch/mips/sibyte/Kconfig @@ -2,6 +2,7 @@ config SIBYTE_SB1250 bool select HW_HAS_PCI select SIBYTE_ENABLE_LDT_IF_PCI + select SIBYTE_HAS_ZBUS_PROFILING select SIBYTE_SB1xxx_SOC select SYS_SUPPORTS_SMP @@ -34,6 +35,7 @@ config SIBYTE_BCM112X config SIBYTE_BCM1x80 bool select HW_HAS_PCI + select SIBYTE_HAS_ZBUS_PROFILING select SIBYTE_SB1xxx_SOC select SYS_SUPPORTS_SMP diff --git a/arch/mips/sibyte/common/Makefile b/arch/mips/sibyte/common/Makefile new file mode 100644 index 00000000000..8a06a4fb521 --- /dev/null +++ b/arch/mips/sibyte/common/Makefile @@ -0,0 +1,5 @@ +obj-y := + +obj-$(CONFIG_SIBYTE_TBPROF) += sb_tbprof.o + +EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c index ea0ca131a3c..4fcdaa8ba51 100644 --- a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c +++ b/arch/mips/sibyte/common/sb_tbprof.c @@ -31,14 +31,29 @@ #include <linux/vmalloc.h> #include <linux/fs.h> #include <linux/errno.h> -#include <linux/types.h> #include <linux/wait.h> - #include <asm/io.h> #include <asm/sibyte/sb1250.h> + +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) +#include <asm/sibyte/bcm1480_regs.h> +#include <asm/sibyte/bcm1480_scd.h> +#include <asm/sibyte/bcm1480_int.h> +#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) #include <asm/sibyte/sb1250_regs.h> #include <asm/sibyte/sb1250_scd.h> #include <asm/sibyte/sb1250_int.h> +#else +#error invalid SiByte UART configuation +#endif + +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) +#undef K_INT_TRACE_FREEZE +#define K_INT_TRACE_FREEZE K_BCM1480_INT_TRACE_FREEZE +#undef K_INT_PERF_CNT +#define K_INT_PERF_CNT K_BCM1480_INT_PERF_CNT +#endif + #include <asm/system.h> #include <asm/uaccess.h> @@ -118,7 +133,7 @@ static struct sbprof_tb sbp; : /* inputs */ \ : /* modifies */ "$8" ) -#define DEVNAME "bcm1250_tbprof" +#define DEVNAME "sb_tbprof" #define TB_FULL (sbp.next_tb_sample == MAX_TB_SAMPLES) @@ -132,6 +147,7 @@ static struct sbprof_tb sbp; * overflow. * * We map the interrupt for trace_buffer_freeze to handle it on CPU 0. + * */ static u64 tb_period; @@ -143,25 +159,36 @@ static void arm_tb(void) u64 tb_options = M_SCD_TRACE_CFG_FREEZE_FULL; /* - * Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to trigger - *start of trace. XXX vary sampling period + * Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to + * trigger start of trace. XXX vary sampling period */ __raw_writeq(0, IOADDR(A_SCD_PERF_CNT_1)); scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG)); /* - * Unfortunately, in Pass 2 we must clear all counters to knock down a - * previous interrupt request. This means that bus profiling requires - * ALL of the SCD perf counters. + * Unfortunately, in Pass 2 we must clear all counters to knock down + * a previous interrupt request. This means that bus profiling + * requires ALL of the SCD perf counters. */ +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) + __raw_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) | + /* keep counters 0,2,3,4,5,6,7 as is */ + V_SPC_CFG_SRC1(1), /* counter 1 counts cycles */ + IOADDR(A_BCM1480_SCD_PERF_CNT_CFG0)); + __raw_writeq( + M_SPC_CFG_ENABLE | /* enable counting */ + M_SPC_CFG_CLEAR | /* clear all counters */ + V_SPC_CFG_SRC1(1), /* counter 1 counts cycles */ + IOADDR(A_BCM1480_SCD_PERF_CNT_CFG1)); +#else __raw_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) | /* keep counters 0,2,3 as is */ M_SPC_CFG_ENABLE | /* enable counting */ M_SPC_CFG_CLEAR | /* clear all counters */ V_SPC_CFG_SRC1(1), /* counter 1 counts cycles */ IOADDR(A_SCD_PERF_CNT_CFG)); +#endif __raw_writeq(next, IOADDR(A_SCD_PERF_CNT_1)); - /* Reset the trace buffer */ __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); #if 0 && defined(M_SCD_TRACE_CFG_FORCECNT) @@ -190,38 +217,37 @@ static irqreturn_t sbprof_tb_intr(int irq, void *dev_id) /* Subscripts decrease to put bundle in the order */ /* t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi */ p[i - 1] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); - /* read t2 hi */ + /* read t2 hi */ p[i - 2] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); - /* read t2 lo */ + /* read t2 lo */ p[i - 3] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); - /* read t1 hi */ + /* read t1 hi */ p[i - 4] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); - /* read t1 lo */ + /* read t1 lo */ p[i - 5] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); - /* read t0 hi */ + /* read t0 hi */ p[i - 6] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); - /* read t0 lo */ + /* read t0 lo */ } if (!sbp.tb_enable) { pr_debug(DEVNAME ": tb_intr shutdown\n"); __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); sbp.tb_armed = 0; - wake_up(&sbp.tb_sync); + wake_up_interruptible(&sbp.tb_sync); } else { - arm_tb(); /* knock down current interrupt and get another one later */ + /* knock down current interrupt and get another one later */ + arm_tb(); } } else { /* No more trace buffer samples */ pr_debug(DEVNAME ": tb_intr full\n"); __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); sbp.tb_armed = 0; - if (!sbp.tb_enable) { - wake_up(&sbp.tb_sync); - } - wake_up(&sbp.tb_read); + if (!sbp.tb_enable) + wake_up_interruptible(&sbp.tb_sync); + wake_up_interruptible(&sbp.tb_read); } - return IRQ_HANDLED; } @@ -250,8 +276,8 @@ static int sbprof_zbprof_start(struct file *filp) sbp.next_tb_sample = 0; filp->f_pos = 0; - err = request_irq(K_INT_TRACE_FREEZE, sbprof_tb_intr, 0, - DEVNAME " trace freeze", &sbp); + err = request_irq (K_INT_TRACE_FREEZE, sbprof_tb_intr, 0, + DEVNAME " trace freeze", &sbp); if (err) return -EBUSY; @@ -263,23 +289,29 @@ static int sbprof_zbprof_start(struct file *filp) IOADDR(A_SCD_PERF_CNT_CFG)); /* - * We grab this interrupt to prevent others from trying to use it, even - * though we don't want to service the interrupts (they only feed into - * the trace-on-interrupt mechanism) + * We grab this interrupt to prevent others from trying to use + * it, even though we don't want to service the interrupts + * (they only feed into the trace-on-interrupt mechanism) */ - err = request_irq(K_INT_PERF_CNT, sbprof_pc_intr, 0, - DEVNAME " scd perfcnt", &sbp); - if (err) - goto out_free_irq; + if (request_irq(K_INT_PERF_CNT, sbprof_pc_intr, 0, DEVNAME " scd perfcnt", &sbp)) { + free_irq(K_INT_TRACE_FREEZE, &sbp); + return -EBUSY; + } /* - * I need the core to mask these, but the interrupt mapper to pass them - * through. I am exploiting my knowledge that cp0_status masks out - * IP[5]. krw + * I need the core to mask these, but the interrupt mapper to + * pass them through. I am exploiting my knowledge that + * cp0_status masks out IP[5]. krw */ +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) + __raw_writeq(K_BCM1480_INT_MAP_I3, + IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_L) + + ((K_BCM1480_INT_PERF_CNT & 0x3f) << 3))); +#else __raw_writeq(K_INT_MAP_I3, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + (K_INT_PERF_CNT << 3))); +#endif /* Initialize address traps */ __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_0)); @@ -298,7 +330,7 @@ static int sbprof_zbprof_start(struct file *filp) __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3)); /* Initialize Trace Event 0-7 */ - /* when interrupt */ + /* when interrupt */ __raw_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0)); __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1)); __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2)); @@ -324,24 +356,23 @@ static int sbprof_zbprof_start(struct file *filp) __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_7)); /* Now indicate the PERF_CNT interrupt as a trace-relevant interrupt */ +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) + __raw_writeq(1ULL << (K_BCM1480_INT_PERF_CNT & 0x3f), + IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_TRACE_L))); +#else __raw_writeq(1ULL << K_INT_PERF_CNT, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE))); - +#endif arm_tb(); pr_debug(DEVNAME ": done starting\n"); return 0; - -out_free_irq: - free_irq(K_INT_TRACE_FREEZE, &sbp); - - return err; } static int sbprof_zbprof_stop(void) { - int err; + int err = 0; pr_debug(DEVNAME ": stopping\n"); @@ -365,7 +396,7 @@ static int sbprof_zbprof_stop(void) pr_debug(DEVNAME ": done stopping\n"); - return 0; + return err; } static int sbprof_tb_open(struct inode *inode, struct file *filp) @@ -380,11 +411,9 @@ static int sbprof_tb_open(struct inode *inode, struct file *filp) return -EBUSY; memset(&sbp, 0, sizeof(struct sbprof_tb)); - sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES); if (!sbp.sbprof_tbbuf) return -ENOMEM; - memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES); init_waitqueue_head(&sbp.tb_sync); init_waitqueue_head(&sbp.tb_read); @@ -397,8 +426,9 @@ static int sbprof_tb_open(struct inode *inode, struct file *filp) static int sbprof_tb_release(struct inode *inode, struct file *filp) { - int minor = iminor(inode); + int minor; + minor = iminor(inode); if (minor != 0 || !sbp.open) return -ENODEV; @@ -419,10 +449,10 @@ static ssize_t sbprof_tb_read(struct file *filp, char *buf, size_t size, loff_t *offp) { int cur_sample, sample_off, cur_count, sample_left; - long cur_off = *offp; - char *dest = buf; - int count = 0; char *src; + int count = 0; + char *dest = buf; + long cur_off = *offp; if (!access_ok(VERIFY_WRITE, buf, size)) return -EFAULT; @@ -445,7 +475,6 @@ static ssize_t sbprof_tb_read(struct file *filp, char *buf, mutex_unlock(&sbp.lock); return err; } - pr_debug(DEVNAME ": read from sample %d, %d bytes\n", cur_sample, cur_count); size -= cur_count; @@ -461,45 +490,46 @@ static ssize_t sbprof_tb_read(struct file *filp, char *buf, dest += cur_count; count += cur_count; } - *offp = cur_off; mutex_unlock(&sbp.lock); return count; } -static long sbprof_tb_ioctl(struct file *filp, unsigned int command, - unsigned long arg) +static long sbprof_tb_ioctl(struct file *filp, + unsigned int command, + unsigned long arg) { - int error = 0; + int err = 0; switch (command) { case SBPROF_ZBSTART: mutex_lock(&sbp.lock); - error = sbprof_zbprof_start(filp); + err = sbprof_zbprof_start(filp); mutex_unlock(&sbp.lock); break; case SBPROF_ZBSTOP: mutex_lock(&sbp.lock); - error = sbprof_zbprof_stop(); + err = sbprof_zbprof_stop(); mutex_unlock(&sbp.lock); break; - case SBPROF_ZBWAITFULL: - error = wait_event_interruptible(sbp.tb_read, TB_FULL); - if (error) + case SBPROF_ZBWAITFULL: { + err = wait_event_interruptible(sbp.tb_read, TB_FULL); + if (err) break; - error = put_user(TB_FULL, (int *) arg); + err = put_user(TB_FULL, (int *) arg); break; + } default: - error = -EINVAL; + err = -EINVAL; break; } - return error; + return err; } static const struct file_operations sbprof_tb_fops = { @@ -544,8 +574,8 @@ static int __init sbprof_tb_init(void) sbp.open = 0; tb_period = zbbus_mhz * 10000LL; - pr_info(DEVNAME ": initialized - tb_period = %lld\n", tb_period); - + pr_info(DEVNAME ": initialized - tb_period = %lld\n", + (long long) tb_period); return 0; out_class: diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile index 04c0f1a7f61..df662c61473 100644 --- a/arch/mips/sibyte/sb1250/Makefile +++ b/arch/mips/sibyte/sb1250/Makefile @@ -1,6 +1,5 @@ obj-y := setup.o irq.o time.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_SIBYTE_TBPROF) += bcm1250_tbprof.o obj-$(CONFIG_SIBYTE_STANDALONE) += prom.o obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c index 8e8593b64f6..9ee208daa8b 100644 --- a/arch/mips/sni/pcimt.c +++ b/arch/mips/sni/pcimt.c @@ -91,7 +91,7 @@ static struct platform_device pcimt_serial8250_device = { }; static struct resource sni_io_resource = { - .start = 0x00001000UL, + .start = 0x00000000UL, .end = 0x03bfffffUL, .name = "PCIMT IO MEM", .flags = IORESOURCE_IO, @@ -132,107 +132,19 @@ static struct resource pcimt_io_resources[] = { }; static struct resource sni_mem_resource = { - .start = 0x10000000UL, - .end = 0xffffffffUL, + .start = 0x18000000UL, + .end = 0x1fbfffffUL, .name = "PCIMT PCI MEM", .flags = IORESOURCE_MEM }; -/* - * The RM200/RM300 has a few holes in it's PCI/EISA memory address space used - * for other purposes. Be paranoid and allocate all of the before the PCI - * code gets a chance to to map anything else there ... - * - * This leaves the following areas available: - * - * 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory - * 0x10100000 - 0x13ffffff ( 15MB) PCI/EISA/ISA Bus Memory - * 0x18000000 - 0x1fbfffff (124MB) PCI/EISA Bus Memory - * 0x1ff08000 - 0x1ffeffff (816kB) PCI/EISA Bus Memory - * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory - */ -static struct resource pcimt_mem_resources[] = { - { - .start = 0x100a0000, - .end = 0x100bffff, - .name = "Video RAM area", - .flags = IORESOURCE_BUSY - }, { - .start = 0x100c0000, - .end = 0x100fffff, - .name = "ISA Reserved", - .flags = IORESOURCE_BUSY - }, { - .start = 0x14000000, - .end = 0x17bfffff, - .name = "PCI IO", - .flags = IORESOURCE_BUSY - }, { - .start = 0x17c00000, - .end = 0x17ffffff, - .name = "Cache Replacement Area", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1a000000, - .end = 0x1a000003, - .name = "PCI INT Acknowledge", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1fc00000, - .end = 0x1fc7ffff, - .name = "Boot PROM", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1fc80000, - .end = 0x1fcfffff, - .name = "Diag PROM", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1fd00000, - .end = 0x1fdfffff, - .name = "X-Bus", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1fe00000, - .end = 0x1fefffff, - .name = "BIOS map", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1ff00000, - .end = 0x1ff7ffff, - .name = "NVRAM / EEPROM", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1fff0000, - .end = 0x1fffefff, - .name = "ASIC PCI", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1ffff000, - .end = 0x1fffffff, - .name = "MP Agent", - .flags = IORESOURCE_BUSY - }, { - .start = 0x20000000, - .end = 0x9fffffff, - .name = "Main Memory", - .flags = IORESOURCE_BUSY - } -}; - static void __init sni_pcimt_resource_init(void) { int i; /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++) - request_resource(&ioport_resource, pcimt_io_resources + i); - - /* request mem space for pcimt-specific devices */ - for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++) - request_resource(&sni_mem_resource, pcimt_mem_resources + i); - - ioport_resource.end = sni_io_resource.end; + request_resource(&sni_io_resource, pcimt_io_resources + i); } extern struct pci_ops sni_pcimt_ops; @@ -240,9 +152,10 @@ extern struct pci_ops sni_pcimt_ops; static struct pci_controller sni_controller = { .pci_ops = &sni_pcimt_ops, .mem_resource = &sni_mem_resource, - .mem_offset = 0x10000000UL, + .mem_offset = 0x00000000UL, .io_resource = &sni_io_resource, - .io_offset = 0x00000000UL + .io_offset = 0x00000000UL, + .io_map_base = SNI_PORT_BASE }; static void enable_pcimt_irq(unsigned int irq) @@ -363,15 +276,17 @@ void __init sni_pcimt_irq_init(void) void sni_pcimt_init(void) { - sni_pcimt_resource_init(); sni_pcimt_detect(); sni_pcimt_sc_init(); rtc_mips_get_time = mc146818_get_cmos_time; rtc_mips_set_time = mc146818_set_rtc_mmss; board_time_init = sni_cpu_time_init; + ioport_resource.end = sni_io_resource.end; #ifdef CONFIG_PCI + PCIBIOS_MIN_IO = 0x9000; register_pci_controller(&sni_controller); #endif + sni_pcimt_resource_init(); } static int __init snirm_pcimt_setup_devinit(void) diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c index 1dfc3f00bbd..00d151f4d12 100644 --- a/arch/mips/sni/pcit.c +++ b/arch/mips/sni/pcit.c @@ -43,7 +43,7 @@ static struct platform_device pcit_serial8250_device = { }; static struct plat_serial8250_port pcit_cplus_data[] = { - PORT(0x3f8, 4), + PORT(0x3f8, 0), PORT(0x2f8, 3), PORT(0x3e8, 4), PORT(0x2e8, 3), @@ -59,9 +59,9 @@ static struct platform_device pcit_cplus_serial8250_device = { }; static struct resource sni_io_resource = { - .start = 0x00001000UL, + .start = 0x00000000UL, .end = 0x03bfffffUL, - .name = "PCIT IO MEM", + .name = "PCIT IO", .flags = IORESOURCE_IO, }; @@ -92,6 +92,11 @@ static struct resource pcit_io_resources[] = { .name = "dma2", .flags = IORESOURCE_BUSY }, { + .start = 0xcf8, + .end = 0xcfb, + .name = "PCI config addr", + .flags = IORESOURCE_BUSY + }, { .start = 0xcfc, .end = 0xcff, .name = "PCI config data", @@ -100,107 +105,19 @@ static struct resource pcit_io_resources[] = { }; static struct resource sni_mem_resource = { - .start = 0x10000000UL, - .end = 0xffffffffUL, + .start = 0x18000000UL, + .end = 0x1fbfffffUL, .name = "PCIT PCI MEM", .flags = IORESOURCE_MEM }; -/* - * The RM200/RM300 has a few holes in it's PCI/EISA memory address space used - * for other purposes. Be paranoid and allocate all of the before the PCI - * code gets a chance to to map anything else there ... - * - * This leaves the following areas available: - * - * 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory - * 0x10100000 - 0x13ffffff ( 15MB) PCI/EISA/ISA Bus Memory - * 0x18000000 - 0x1fbfffff (124MB) PCI/EISA Bus Memory - * 0x1ff08000 - 0x1ffeffff (816kB) PCI/EISA Bus Memory - * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory - */ -static struct resource pcit_mem_resources[] = { - { - .start = 0x14000000, - .end = 0x17bfffff, - .name = "PCI IO", - .flags = IORESOURCE_BUSY - }, { - .start = 0x17c00000, - .end = 0x17ffffff, - .name = "Cache Replacement Area", - .flags = IORESOURCE_BUSY - }, { - .start = 0x180a0000, - .end = 0x180bffff, - .name = "Video RAM area", - .flags = IORESOURCE_BUSY - }, { - .start = 0x180c0000, - .end = 0x180fffff, - .name = "ISA Reserved", - .flags = IORESOURCE_BUSY - }, { - .start = 0x19000000, - .end = 0x1fbfffff, - .name = "PCI MEM", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1fc00000, - .end = 0x1fc7ffff, - .name = "Boot PROM", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1fc80000, - .end = 0x1fcfffff, - .name = "Diag PROM", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1fd00000, - .end = 0x1fdfffff, - .name = "X-Bus", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1fe00000, - .end = 0x1fefffff, - .name = "BIOS map", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1ff00000, - .end = 0x1ff7ffff, - .name = "NVRAM / EEPROM", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1fff0000, - .end = 0x1fffefff, - .name = "MAUI ASIC", - .flags = IORESOURCE_BUSY - }, { - .start = 0x1ffff000, - .end = 0x1fffffff, - .name = "MP Agent", - .flags = IORESOURCE_BUSY - }, { - .start = 0x20000000, - .end = 0x9fffffff, - .name = "Main Memory", - .flags = IORESOURCE_BUSY - } -}; - static void __init sni_pcit_resource_init(void) { int i; /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i < ARRAY_SIZE(pcit_io_resources); i++) - request_resource(&ioport_resource, pcit_io_resources + i); - - /* request mem space for pcimt-specific devices */ - for (i = 0; i < ARRAY_SIZE(pcit_mem_resources); i++) - request_resource(&sni_mem_resource, pcit_mem_resources + i); - - ioport_resource.end = sni_io_resource.end; + request_resource(&sni_io_resource, pcit_io_resources + i); } @@ -209,9 +126,10 @@ extern struct pci_ops sni_pcit_ops; static struct pci_controller sni_pcit_controller = { .pci_ops = &sni_pcit_ops, .mem_resource = &sni_mem_resource, - .mem_offset = 0x10000000UL, + .mem_offset = 0x00000000UL, .io_resource = &sni_io_resource, - .io_offset = 0x00000000UL + .io_offset = 0x00000000UL, + .io_map_base = SNI_PORT_BASE }; static void enable_pcit_irq(unsigned int irq) @@ -262,7 +180,7 @@ static void pcit_hwint0(void) int irq; clear_c0_status(IE_IRQ0); - irq = ffs((pending >> 16) & 0x7f); + irq = ffs((pending >> 16) & 0x3f); if (likely(irq > 0)) do_IRQ (irq + SNI_PCIT_INT_START - 1); @@ -289,6 +207,8 @@ static void sni_pcit_hwint_cplus(void) if (pending & C_IRQ0) pcit_hwint0(); + else if (pending & C_IRQ1) + do_IRQ (MIPS_CPU_IRQ_BASE + 3); else if (pending & C_IRQ2) do_IRQ (MIPS_CPU_IRQ_BASE + 4); else if (pending & C_IRQ3) @@ -317,21 +237,23 @@ void __init sni_pcit_cplus_irq_init(void) mips_cpu_irq_init(); for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) set_irq_chip(i, &pcit_irq_type); - *(volatile u32 *)SNI_PCIT_INT_REG = 0; + *(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000; sni_hwint = sni_pcit_hwint_cplus; change_c0_status(ST0_IM, IE_IRQ0); - setup_irq (SNI_PCIT_INT_START + 6, &sni_isa_irq); + setup_irq (MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq); } void sni_pcit_init(void) { - sni_pcit_resource_init(); rtc_mips_get_time = mc146818_get_cmos_time; rtc_mips_set_time = mc146818_set_rtc_mmss; board_time_init = sni_cpu_time_init; + ioport_resource.end = sni_io_resource.end; #ifdef CONFIG_PCI + PCIBIOS_MIN_IO = 0x9000; register_pci_controller(&sni_pcit_controller); #endif + sni_pcit_resource_init(); } static int __init snirm_pcit_setup_devinit(void) diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig index 92f41f6f934..8f4d3e74c23 100644 --- a/arch/mips/vr41xx/Kconfig +++ b/arch/mips/vr41xx/Kconfig @@ -1,6 +1,10 @@ -config CASIO_E55 - bool "Support for CASIO CASSIOPEIA E-10/15/55/65" +choice + prompt "Machine type" depends on MACH_VR41XX + default TANBAC_TB022X + +config CASIO_E55 + bool "CASIO CASSIOPEIA E-10/15/55/65" select DMA_NONCOHERENT select IRQ_CPU select ISA @@ -8,8 +12,7 @@ config CASIO_E55 select SYS_SUPPORTS_LITTLE_ENDIAN config IBM_WORKPAD - bool "Support for IBM WorkPad z50" - depends on MACH_VR41XX + bool "IBM WorkPad z50" select DMA_NONCOHERENT select IRQ_CPU select ISA @@ -17,26 +20,18 @@ config IBM_WORKPAD select SYS_SUPPORTS_LITTLE_ENDIAN config NEC_CMBVR4133 - bool "Support for NEC CMB-VR4133" - depends on MACH_VR41XX + bool "NEC CMB-VR4133" select DMA_NONCOHERENT select IRQ_CPU select HW_HAS_PCI select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN -config ROCKHOPPER - bool "Support for Rockhopper baseboard" - depends on NEC_CMBVR4133 - select I8259 - select HAVE_STD_PC_SERIAL_PORT - config TANBAC_TB022X - bool "Support for TANBAC VR4131 multichip module and TANBAC VR4131DIMM" - depends on MACH_VR41XX + bool "TANBAC VR4131 multichip module and TANBAC VR4131DIMM" select DMA_NONCOHERENT - select HW_HAS_PCI select IRQ_CPU + select HW_HAS_PCI select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN help @@ -46,40 +41,65 @@ config TANBAC_TB022X Please refer to <http://www.tanbac.co.jp/> about VR4131 multichip module and VR4131DIMM. -config TANBAC_TB0226 - bool "Support for TANBAC Mbase(TB0226)" +config VICTOR_MPC30X + bool "Victor MP-C303/304" + select DMA_NONCOHERENT + select IRQ_CPU + select HW_HAS_PCI + select PCI_VR41XX + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + +config ZAO_CAPCELLA + bool "ZAO Networks Capcella" + select DMA_NONCOHERENT + select IRQ_CPU + select HW_HAS_PCI + select PCI_VR41XX + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + +endchoice + +config ROCKHOPPER + bool "Support for Rockhopper base board" + depends on NEC_CMBVR4133 + select PCI_VR41XX + select I8259 + select HAVE_STD_PC_SERIAL_PORT + +choice + prompt "Base board type" depends on TANBAC_TB022X + default TANBAC_TB0287 + +config TANBAC_TB0219 + bool "TANBAC DIMM Evaluation Kit(TB0219)" select GPIO_VR41XX + select PCI_VR41XX + help + The TANBAC DIMM Evaluation Kit(TB0219) is a MIPS-based platform + manufactured by TANBAC. + Please refer to <http://www.tanbac.co.jp/> about DIMM Evaluation Kit. + +config TANBAC_TB0226 + bool "TANBAC Mbase(TB0226)" + select GPIO_VR41XX + select PCI_VR41XX help The TANBAC Mbase(TB0226) is a MIPS-based platform manufactured by TANBAC. Please refer to <http://www.tanbac.co.jp/> about Mbase. config TANBAC_TB0287 - bool "Support for TANBAC Mini-ITX DIMM base(TB0287)" - depends on TANBAC_TB022X + bool "TANBAC Mini-ITX DIMM base(TB0287)" + select PCI_VR41XX help The TANBAC Mini-ITX DIMM base(TB0287) is a MIPS-based platform manufactured by TANBAC. Please refer to <http://www.tanbac.co.jp/> about Mini-ITX DIMM base. -config VICTOR_MPC30X - bool "Support for Victor MP-C303/304" - depends on MACH_VR41XX - select DMA_NONCOHERENT - select HW_HAS_PCI - select IRQ_CPU - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_LITTLE_ENDIAN - -config ZAO_CAPCELLA - bool "Support for ZAO Networks Capcella" - depends on MACH_VR41XX - select DMA_NONCOHERENT - select HW_HAS_PCI - select IRQ_CPU - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_LITTLE_ENDIAN +endchoice config PCI_VR41XX bool "Add PCI control unit support of NEC VR4100 series" diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig index 782906b644d..eb2f9a3d515 100644 --- a/arch/parisc/configs/c3000_defconfig +++ b/arch/parisc/configs/c3000_defconfig @@ -435,7 +435,6 @@ CONFIG_SCSI_SATA_SIL=m # CONFIG_SCSI_SATA_ULI is not set CONFIG_SCSI_SATA_VIA=m # CONFIG_SCSI_SATA_VITESSE is not set -CONFIG_SCSI_SATA_INTEL_COMBINED=y # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6dfbd52694a..a54a9a2e36f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -11,6 +11,11 @@ config PPC64 This option selects whether a 32-bit or a 64-bit kernel will be built. +config PPC_PM_NEEDS_RTC_LIB + bool + select RTC_LIB + default y if PM + config PPC32 bool default y if !PPC64 @@ -89,7 +94,7 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER config ARCH_MAY_HAVE_PC_FDC bool - default y + default !PPC_PSERIES || PCI config PPC_OF def_bool y @@ -157,17 +162,20 @@ config PPC_83xx select FSL_SOC select 83xx select PPC_FPU + select WANT_DEVICE_TREE config PPC_85xx bool "Freescale 85xx" select E500 select FSL_SOC select 85xx + select WANT_DEVICE_TREE config PPC_86xx bool "Freescale 86xx" select 6xx select FSL_SOC + select FSL_PCIE select PPC_FPU select ALTIVEC help @@ -186,7 +194,6 @@ config 44x bool "AMCC 44x" select PPC_DCR_NATIVE - config E200 bool "Freescale e200" @@ -367,394 +374,7 @@ endmenu source "init/Kconfig" -menu "Platform support" - depends on PPC64 || CLASSIC32 - -choice - prompt "Machine type" - default PPC_MULTIPLATFORM - -config PPC_MULTIPLATFORM - bool "Generic desktop/server/laptop" - help - Select this option if configuring for an IBM pSeries or - RS/6000 machine, an Apple machine, or a PReP, CHRP, - Maple or Cell-based machine. - -config EMBEDDED6xx - bool "Embedded 6xx/7xx/7xxx-based board" - depends on PPC32 && (BROKEN||BROKEN_ON_SMP) - -config APUS - bool "Amiga-APUS" - depends on PPC32 && BROKEN - help - Select APUS if configuring for a PowerUP Amiga. - More information is available at: - <http://linux-apus.sourceforge.net/>. -endchoice - -config QUICC_ENGINE - bool - depends on PPC_MPC836x || PPC_MPC832x - default y - help - The QUICC Engine (QE) is a new generation of communications - coprocessors on Freescale embedded CPUs (akin to CPM in older chips). - Selecting this option means that you wish to build a kernel - for a machine with a QE coprocessor. - -config PPC_PSERIES - depends on PPC_MULTIPLATFORM && PPC64 - bool "IBM pSeries & new (POWER5-based) iSeries" - select MPIC - select PPC_I8259 - select PPC_RTAS - select RTAS_ERROR_LOGGING - select PPC_UDBG_16550 - select PPC_NATIVE - default y - -config PPC_ISERIES - bool "IBM Legacy iSeries" - depends on PPC_MULTIPLATFORM && PPC64 - select PPC_INDIRECT_IO - -config PPC_CHRP - bool "Common Hardware Reference Platform (CHRP) based machines" - depends on PPC_MULTIPLATFORM && PPC32 - select MPIC - select PPC_I8259 - select PPC_INDIRECT_PCI - select PPC_RTAS - select PPC_MPC106 - select PPC_UDBG_16550 - select PPC_NATIVE - default y - -config PPC_MPC52xx - bool - default n - -config PPC_MPC5200 - bool - select PPC_MPC52xx - default n - -config PPC_MPC5200_BUGFIX - bool "MPC5200 (L25R) bugfix support" - depends on PPC_MPC5200 - default n - help - Enable workarounds for original MPC5200 errata. This is not required - for MPC5200B based boards. - - It is safe to say 'Y' here - -config PPC_EFIKA - bool "bPlan Efika 5k2. MPC5200B based computer" - depends on PPC_MULTIPLATFORM && PPC32 - select PPC_RTAS - select RTAS_PROC - select PPC_MPC52xx - select PPC_NATIVE - default n - -config PPC_LITE5200 - bool "Freescale Lite5200 Eval Board" - depends on PPC_MULTIPLATFORM && PPC32 - select PPC_MPC5200 - default n - -config PPC_PMAC - bool "Apple PowerMac based machines" - depends on PPC_MULTIPLATFORM - select MPIC - select PPC_INDIRECT_PCI if PPC32 - select PPC_MPC106 if PPC32 - select PPC_NATIVE - default y - -config PPC_PMAC64 - bool - depends on PPC_PMAC && POWER4 - select MPIC - select U3_DART - select MPIC_BROKEN_U3 - select GENERIC_TBSYNC - select PPC_970_NAP - default y - -config PPC_PREP - bool "PowerPC Reference Platform (PReP) based machines" - depends on PPC_MULTIPLATFORM && PPC32 && BROKEN - select MPIC - select PPC_I8259 - select PPC_INDIRECT_PCI - select PPC_UDBG_16550 - select PPC_NATIVE - default n - -config PPC_MAPLE - depends on PPC_MULTIPLATFORM && PPC64 - bool "Maple 970FX Evaluation Board" - select MPIC - select U3_DART - select MPIC_BROKEN_U3 - select GENERIC_TBSYNC - select PPC_UDBG_16550 - select PPC_970_NAP - select PPC_NATIVE - select PPC_RTAS - select MMIO_NVRAM - select ATA_NONSTANDARD if ATA - default n - help - This option enables support for the Maple 970FX Evaluation Board. - For more information, refer to <http://www.970eval.com> - -config PPC_PASEMI - depends on PPC_MULTIPLATFORM && PPC64 - bool "PA Semi SoC-based platforms" - default n - select MPIC - select PPC_UDBG_16550 - select GENERIC_TBSYNC - select PPC_NATIVE - help - This option enables support for PA Semi's PWRficient line - of SoC processors, including PA6T-1682M - -config PPC_CELL - bool - default n - -config PPC_CELL_NATIVE - bool - select PPC_CELL - select PPC_DCR_MMIO - select PPC_OF_PLATFORM_PCI - select PPC_INDIRECT_IO - select PPC_NATIVE - select MPIC - default n - -config PPC_IBM_CELL_BLADE - bool "IBM Cell Blade" - depends on PPC_MULTIPLATFORM && PPC64 - select PPC_CELL_NATIVE - select PPC_RTAS - select MMIO_NVRAM - select PPC_UDBG_16550 - select UDBG_RTAS_CONSOLE - -config PPC_PS3 - bool "Sony PS3 (incomplete)" - depends on PPC_MULTIPLATFORM && PPC64 - select PPC_CELL - select USB_ARCH_HAS_OHCI - select USB_OHCI_LITTLE_ENDIAN - select USB_OHCI_BIG_ENDIAN_MMIO - select USB_ARCH_HAS_EHCI - select USB_EHCI_BIG_ENDIAN_MMIO - help - This option enables support for the Sony PS3 game console - and other platforms using the PS3 hypervisor. - Support for this platform is not yet complete, so - enabling this will not result in a bootable kernel on a - PS3 system. - -config PPC_CELLEB - bool "Toshiba's Cell Reference Set 'Celleb' Architecture" - depends on PPC_MULTIPLATFORM && PPC64 - select PPC_CELL - select PPC_OF_PLATFORM_PCI - select HAS_TXX9_SERIAL - select PPC_UDBG_BEAT - select USB_OHCI_BIG_ENDIAN_MMIO - select USB_EHCI_BIG_ENDIAN_MMIO - -config PPC_NATIVE - bool - depends on PPC_MULTIPLATFORM - help - Support for running natively on the hardware, i.e. without - a hypervisor. This option is not user-selectable but should - be selected by all platforms that need it. - -config UDBG_RTAS_CONSOLE - bool "RTAS based debug console" - depends on PPC_RTAS - default n - -config PPC_UDBG_BEAT - bool "BEAT based debug console" - depends on PPC_CELLEB - default n - -config XICS - depends on PPC_PSERIES - bool - default y - -config U3_DART - bool - depends on PPC_MULTIPLATFORM && PPC64 - default n - -config PPC_RTAS - bool - default n - -config RTAS_ERROR_LOGGING - bool - depends on PPC_RTAS - default n - -config RTAS_PROC - bool "Proc interface to RTAS" - depends on PPC_RTAS - default y - -config RTAS_FLASH - tristate "Firmware flash interface" - depends on PPC64 && RTAS_PROC - -config PPC_PMI - tristate "Support for PMI" - depends PPC_IBM_CELL_BLADE - help - PMI (Platform Management Interrupt) is a way to - communicate with the BMC (Baseboard Mangement Controller). - It is used in some IBM Cell blades. - default m - -config MMIO_NVRAM - bool - default n - -config MPIC_BROKEN_U3 - bool - depends on PPC_MAPLE - default y - -config IBMVIO - depends on PPC_PSERIES || PPC_ISERIES - bool - default y - -config IBMEBUS - depends on PPC_PSERIES - bool "Support for GX bus based adapters" - help - Bus device driver for GX bus based adapters. - -config PPC_MPC106 - bool - default n - -config PPC_970_NAP - bool - default n - -config PPC_INDIRECT_IO - bool - select GENERIC_IOMAP - default n - -config GENERIC_IOMAP - bool - default n - -source "drivers/cpufreq/Kconfig" - -config CPU_FREQ_PMAC - bool "Support for Apple PowerBooks" - depends on CPU_FREQ && ADB_PMU && PPC32 - select CPU_FREQ_TABLE - help - This adds support for frequency switching on Apple PowerBooks, - this currently includes some models of iBook & Titanium - PowerBook. - -config CPU_FREQ_PMAC64 - bool "Support for some Apple G5s" - depends on CPU_FREQ && PPC64 - select CPU_FREQ_TABLE - help - This adds support for frequency switching on Apple iMac G5, - and some of the more recent desktop G5 machines as well. - -config PPC601_SYNC_FIX - bool "Workarounds for PPC601 bugs" - depends on 6xx && (PPC_PREP || PPC_PMAC) - help - Some versions of the PPC601 (the first PowerPC chip) have bugs which - mean that extra synchronization instructions are required near - certain instructions, typically those that make major changes to the - CPU state. These extra instructions reduce performance slightly. - If you say N here, these extra instructions will not be included, - resulting in a kernel which will run faster but may not run at all - on some systems with the PPC601 chip. - - If in doubt, say Y here. - -config TAU - bool "On-chip CPU temperature sensor support" - depends on 6xx - help - G3 and G4 processors have an on-chip temperature sensor called the - 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die - temperature within 2-4 degrees Celsius. This option shows the current - on-die temperature in /proc/cpuinfo if the cpu supports it. - - Unfortunately, on some chip revisions, this sensor is very inaccurate - and in many cases, does not work at all, so don't assume the cpu - temp is actually what /proc/cpuinfo says it is. - -config TAU_INT - bool "Interrupt driven TAU driver (DANGEROUS)" - depends on TAU - ---help--- - The TAU supports an interrupt driven mode which causes an interrupt - whenever the temperature goes out of range. This is the fastest way - to get notified the temp has exceeded a range. With this option off, - a timer is used to re-check the temperature periodically. - - However, on some cpus it appears that the TAU interrupt hardware - is buggy and can cause a situation which would lead unexplained hard - lockups. - - Unless you are extending the TAU driver, or enjoy kernel/hardware - debugging, leave this option off. - -config TAU_AVERAGE - bool "Average high and low temp" - depends on TAU - ---help--- - The TAU hardware can compare the temperature to an upper and lower - bound. The default behavior is to show both the upper and lower - bound in /proc/cpuinfo. If the range is large, the temperature is - either changing a lot, or the TAU hardware is broken (likely on some - G4's). If the range is small (around 4 degrees), the temperature is - relatively stable. If you say Y here, a single temperature value, - halfway between the upper and lower bounds, will be reported in - /proc/cpuinfo. - - If in doubt, say N here. - -endmenu - -source arch/powerpc/platforms/embedded6xx/Kconfig -source arch/powerpc/platforms/4xx/Kconfig -source arch/powerpc/platforms/82xx/Kconfig -source arch/powerpc/platforms/83xx/Kconfig -source arch/powerpc/platforms/85xx/Kconfig -source arch/powerpc/platforms/86xx/Kconfig -source arch/powerpc/platforms/8xx/Kconfig -source arch/powerpc/platforms/cell/Kconfig -source arch/powerpc/platforms/ps3/Kconfig -source arch/powerpc/platforms/pasemi/Kconfig +source "arch/powerpc/platforms/Kconfig" menu "Kernel options" @@ -837,15 +457,6 @@ config CRASH_DUMP Don't change this unless you know what you are doing. -config EMBEDDEDBOOT - bool - depends on 8xx || 8260 - default y - -config PC_KEYBOARD - bool "PC PS/2 style Keyboard" - depends on 4xx || CPM2 - config PPCBUG_NVRAM bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC default y if PPC_PREP @@ -859,8 +470,6 @@ config IRQ_ALL_CPUS CPU. Generally saying Y is safe, although some problems have been reported with SMP Power Macintoshes with this option enabled. -source "arch/powerpc/platforms/pseries/Kconfig" - config NUMA bool "NUMA support" depends on PPC64 @@ -910,10 +519,10 @@ config PPC_64K_PAGES depends on PPC64 help This option changes the kernel logical page size to 64k. On machines - without processor support for 64k pages, the kernel will simulate - them by loading each individual 4k page on demand transparently, - while on hardware with such support, it will be used to map - normal application pages. + without processor support for 64k pages, the kernel will simulate + them by loading each individual 4k page on demand transparently, + while on hardware with such support, it will be used to map + normal application pages. config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" @@ -931,8 +540,6 @@ config PROC_DEVICETREE an image of the device tree that the kernel copies from Open Firmware or other boot firmware. If unsure, say Y here. -source "arch/powerpc/platforms/prep/Kconfig" - config CMDLINE_BOOL bool "Default bootloader kernel arguments" @@ -967,6 +574,29 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. +config WANT_DEVICE_TREE + bool + default n + +config DEVICE_TREE + string "Static device tree source file" + depends on WANT_DEVICE_TREE + help + This specifies the device tree source (.dts) file to be + compiled and included when building the bootwrapper. If a + relative filename is given, then it will be relative to + arch/powerpc/boot/dts. If you are not using the bootwrapper, + or do not need to build a dts into the bootwrapper, this + field is ignored. + + For example, this is required when building a cuImage target + for an older U-Boot, which cannot pass a device tree itself. + Such a kernel will not work with a newer U-Boot that tries to + pass a device tree (unless you tell it not to). If your U-Boot + does not mention a device tree in "help bootm", then use the + cuImage target and specify a device tree here. Otherwise, use + the uImage target and leave this field blank. + endmenu config ISA_DMA_API @@ -995,24 +625,17 @@ config GENERIC_ISA_DMA depends on PPC64 || POWER4 || 6xx && !CPM2 default y -config MPIC - bool - default n - -config MPIC_WEIRD - bool - default n - -config PPC_I8259 - bool - default n - config PPC_INDIRECT_PCI bool depends on PCI default y if 40x || 44x default n +config PPC_INDIRECT_PCI_BE + bool + depends PPC_INDIRECT_PCI + default n + config EISA bool @@ -1022,13 +645,18 @@ config SBUS config FSL_SOC bool +config FSL_PCIE + bool + depends on PPC_86xx + # Yes MCA RS/6000s exist but Linux-PPC does not currently support any config MCA bool config PCI bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ - || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 || PPC_PS3 + || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ + || MPC7448HPC2 || PPC_PS3 default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ && !PPC_85xx && !PPC_86xx default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS @@ -1228,12 +856,10 @@ source "fs/Kconfig" source "arch/powerpc/sysdev/qe_lib/Kconfig" -source "arch/powerpc/platforms/iseries/Kconfig" - source "lib/Kconfig" menu "Instrumentation Support" - depends on EXPERIMENTAL + depends on EXPERIMENTAL source "arch/powerpc/oprofile/Kconfig" diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index d39d13327e6..86aa3745af7 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -18,6 +18,15 @@ config DEBUG_STACK_USAGE This option will slow down process creation somewhat. +config DEBUG_PAGEALLOC + bool "Debug page memory allocations" + depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND + help + Unmap pages from the kernel linear mapping after free_pages(). + This results in a large slowdown, but helps to find certain types + of memory corruptions. + + config HCALL_STATS bool "Hypervisor call instrumentation" depends on PPC_PSERIES && DEBUG_FS @@ -132,8 +141,7 @@ config BOOTX_TEXT config SERIAL_TEXT_DEBUG bool "Support for early boot texts over serial port" - depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \ - PPC_GEN550 || PPC_MPC52xx + depends on 4xx config PPC_EARLY_DEBUG bool "Early debugging (dangerous)" diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index a00fe723655..794992025d8 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -102,9 +102,9 @@ CFLAGS += $(call cc-option,-mno-altivec) # kernel considerably. CFLAGS += $(call cc-option,-funit-at-a-time) -ifndef CONFIG_FSL_BOOKE -CFLAGS += -mstring -endif +# Never use string load/store instructions as they are +# often slow when they are implemented at all +CFLAGS += -mno-string ifeq ($(CONFIG_6xx),y) CFLAGS += -mcpu=powerpc @@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE) CPPFLAGS_vmlinux.lds := -Upowerpc -BOOT_TARGETS = zImage zImage.initrd uImage +BOOT_TARGETS = zImage zImage.initrd uImage cuImage PHONY += $(BOOT_TARGETS) @@ -166,6 +166,9 @@ define archhelp @echo ' *_defconfig - Select default config from arch/$(ARCH)/configs' endef +install: + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install + archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index 0734b2fc1d9..eec7af7e599 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore @@ -18,6 +18,9 @@ kernel-vmlinux.strip.c kernel-vmlinux.strip.gz mktree uImage +cuImage +cuImage.bin.gz +cuImage.elf zImage zImage.chrp zImage.coff diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index dc779407de1..3716594ea33 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -40,10 +40,11 @@ zliblinuxheader := zlib.h zconf.h zutil.h $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ $(addprefix $(obj)/,$(zlibheader)) -src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ - ns16550.c serial.c simple_alloc.c div64.S util.S $(zlib) -src-plat := of.c -src-boot := crt0.S $(src-wlib) $(src-plat) empty.c +src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ + ns16550.c serial.c simple_alloc.c div64.S util.S \ + gunzip_util.c elf_util.c $(zlib) devtree.c +src-plat := of.c cuboot-83xx.c cuboot-85xx.c +src-boot := $(src-wlib) $(src-plat) empty.c src-boot := $(addprefix $(obj)/, $(src-boot)) obj-boot := $(addsuffix .o, $(basename $(src-boot))) @@ -75,7 +76,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S @cp $< $@ clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ - empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint + empty.c zImage.coff.lds zImage.lds quiet_cmd_bootcc = BOOTCC $@ cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< @@ -84,23 +85,25 @@ quiet_cmd_bootas = BOOTAS $@ cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< quiet_cmd_bootar = BOOTAR $@ - cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $^; mv $@.$$$$ $@ + cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@ -$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c +$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c FORCE $(call if_changed_dep,bootcc) -$(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S +$(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE $(call if_changed_dep,bootas) -$(obj)/wrapper.a: $(obj-wlib) - $(call cmd,bootar) +$(obj)/wrapper.a: $(obj-wlib) FORCE + $(call if_changed,bootar) hostprogs-y := addnote addRamDisk hack-coff mktree -extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ +targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) +extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ $(obj)/zImage.lds $(obj)/zImage.coff.lds wrapper :=$(srctree)/$(src)/wrapper -wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) +wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \ + $(wrapper) FORCE ############# # Bits for building various flavours of zImage @@ -113,50 +116,10 @@ CROSSWRAP := -C "$(CROSS_COMPILE)" endif endif +# args (to if_changed): 1 = (this rule), 2 = platform, 3 = dts 4=dtb 5=initrd quiet_cmd_wrap = WRAP $@ - cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) vmlinux -quiet_cmd_wrap_initrd = WRAP $@ - cmd_wrap_initrd =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ - -i $(obj)/ramdisk.image.gz vmlinux - -$(obj)/zImage.chrp: vmlinux $(wrapperbits) - $(call cmd,wrap,chrp) - -$(obj)/zImage.initrd.chrp: vmlinux $(wrapperbits) - $(call cmd,wrap_initrd,chrp) - -$(obj)/zImage.pseries: vmlinux $(wrapperbits) - $(call cmd,wrap,pseries) - -$(obj)/zImage.initrd.pseries: vmlinux $(wrapperbits) - $(call cmd,wrap_initrd,pseries) - -$(obj)/zImage.pmac: vmlinux $(wrapperbits) - $(call cmd,wrap,pmac) - -$(obj)/zImage.initrd.pmac: vmlinux $(wrapperbits) - $(call cmd,wrap_initrd,pmac) - -$(obj)/zImage.coff: vmlinux $(wrapperbits) - $(call cmd,wrap,pmaccoff) - -$(obj)/zImage.initrd.coff: vmlinux $(wrapperbits) - $(call cmd,wrap_initrd,pmaccoff) - -$(obj)/zImage.miboot: vmlinux $(wrapperbits) - $(call cmd,wrap,miboot) - -$(obj)/zImage.initrd.miboot: vmlinux $(wrapperbits) - $(call cmd,wrap_initrd,miboot) - -$(obj)/zImage.ps3: vmlinux - $(STRIP) -s -R .comment $< -o $@ - -$(obj)/zImage.initrd.ps3: vmlinux - @echo " WARNING zImage.initrd.ps3 not supported (yet)" - -$(obj)/uImage: vmlinux $(wrapperbits) - $(call cmd,wrap,uboot) + cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ + $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux image-$(CONFIG_PPC_PSERIES) += zImage.pseries image-$(CONFIG_PPC_MAPLE) += zImage.pseries @@ -166,7 +129,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries image-$(CONFIG_PPC_CHRP) += zImage.chrp image-$(CONFIG_PPC_EFIKA) += zImage.chrp image-$(CONFIG_PPC_PMAC) += zImage.pmac -image-$(CONFIG_DEFAULT_UIMAGE) += uImage +image-$(CONFIG_DEFAULT_UIMAGE) += uImage cuImage # For 32-bit powermacs, build the COFF and miboot images # as well as the ELF images. @@ -174,16 +137,55 @@ ifeq ($(CONFIG_PPC32),y) image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot endif +initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-)) initrd-y := $(patsubst zImage%, zImage.initrd%, $(image-y)) +initrd-y := $(filter-out $(image-y), $(initrd-y)) +targets += $(image-y) $(initrd-y) + +$(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz + +# Don't put the ramdisk on the pattern rule; when its missing make will try +# the pattern rule with less dependencies that also matches (even with the +# hard dependency listed). +$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) + $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz) + +$(obj)/zImage.%: vmlinux $(wrapperbits) + $(call if_changed,wrap,$*) + +$(obj)/zImage.ps3: vmlinux + $(STRIP) -s -R .comment $< -o $@ + +$(obj)/zImage.initrd.ps3: vmlinux + @echo " WARNING zImage.initrd.ps3 not supported (yet)" + +$(obj)/uImage: vmlinux $(wrapperbits) + $(call if_changed,wrap,uboot) + +cuboot-plat-$(CONFIG_83xx) += 83xx +cuboot-plat-$(CONFIG_85xx) += 85xx +cuboot-plat-y += unknown-platform + +dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\ + ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE) + +$(obj)/cuImage: vmlinux $(wrapperbits) + $(call if_changed,wrap,cuboot-$(word 1,$(cuboot-plat-y)),$(dts)) $(obj)/zImage: $(addprefix $(obj)/, $(image-y)) @rm -f $@; ln $< $@ $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y)) @rm -f $@; ln $< $@ -install: $(CONFIGURE) $(image-y) +install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< -clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz) -clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz) -clean-files += $(image-) +# anything not in $(targets) +clean-files += $(image-) $(initrd-) zImage zImage.initrd \ + cuImage.elf cuImage.bin.gz + +# clean up files cached by wrapper +clean-kernel := vmlinux.strip vmlinux.bin +clean-kernel += $(addsuffix .gz,$(clean-kernel)) +# If not absolute clean-files are relative to $(obj). +clean-files += $(addprefix $(objtree)/, $(clean-kernel)) diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index 70e65b13e03..5a4215c4b01 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S @@ -16,8 +16,11 @@ _zimage_start_opd: .long _zimage_start, 0, 0, 0 + .weak _zimage_start .globl _zimage_start _zimage_start: + .globl _zimage_start_lib +_zimage_start_lib: /* Work out the offset between the address we were linked at and the address where we're running. */ bl 1f @@ -44,7 +47,7 @@ _zimage_start: addi r9,r9,4 bdnz 2b - /* Do a cache flush for our text, in case OF didn't */ + /* Do a cache flush for our text, in case the loader didn't */ 3: lis r9,_start@ha addi r9,r9,_start@l add r9,r0,r9 @@ -59,6 +62,34 @@ _zimage_start: sync isync - mr r6,r1 - b start + /* Clear the BSS */ + lis r9,__bss_start@ha + addi r9,r9,__bss_start@l + add r9,r0,r9 + lis r8,_end@ha + addi r8,r8,_end@l + add r8,r0,r8 + li r10,0 +5: stw r10,0(r9) + addi r9,r9,4 + cmplw cr0,r9,r8 + blt 5b + /* Possibly set up a custom stack */ +.weak _platform_stack_top + lis r8,_platform_stack_top@ha + addi r8,r8,_platform_stack_top@l + cmpwi r8,0 + beq 6f + add r8,r0,r8 + lwz r1,0(r8) + add r1,r0,r1 + li r0,0 + stwu r0,-16(r1) /* establish a stack frame */ +6: + + /* Call platform_init() */ + bl platform_init + + /* Call start */ + b start diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c new file mode 100644 index 00000000000..6cbc20afb4d --- /dev/null +++ b/arch/powerpc/boot/cuboot-83xx.c @@ -0,0 +1,68 @@ +/* + * Old U-boot compatibility for 83xx + * + * Author: Scott Wood <scottwood@freescale.com> + * + * Copyright (c) 2007 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include "ops.h" +#include "stdio.h" + +#define TARGET_83xx +#include "ppcboot.h" + +static bd_t bd; +extern char _end[]; +extern char _dtb_start[], _dtb_end[]; + +static void platform_fixups(void) +{ + void *soc; + + dt_fixup_memory(bd.bi_memstart, bd.bi_memsize); + dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr); + dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 4, bd.bi_busfreq); + + /* Unfortunately, the specific model number is encoded in the + * soc node name in existing dts files -- once that is fixed, + * this can do a simple path lookup. + */ + soc = find_node_by_devtype(NULL, "soc"); + if (soc) { + void *serial = NULL; + + setprop(soc, "bus-frequency", &bd.bi_busfreq, + sizeof(bd.bi_busfreq)); + + while ((serial = find_node_by_devtype(serial, "serial"))) { + if (get_parent(serial) != soc) + continue; + + setprop(serial, "clock-frequency", &bd.bi_busfreq, + sizeof(bd.bi_busfreq)); + } + } +} + +void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; + unsigned long avail_ram = end_of_ram - (unsigned long)_end; + + memcpy(&bd, (bd_t *)r3, sizeof(bd)); + loader_info.initrd_addr = r4; + loader_info.initrd_size = r4 ? r5 : 0; + loader_info.cmdline = (char *)r6; + loader_info.cmdline_len = r7 - r6; + + simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); + ft_init(_dtb_start, _dtb_end - _dtb_start, 32); + serial_console_init(); + platform_ops.fixups = platform_fixups; +} diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c new file mode 100644 index 00000000000..f88ba00ac12 --- /dev/null +++ b/arch/powerpc/boot/cuboot-85xx.c @@ -0,0 +1,69 @@ +/* + * Old U-boot compatibility for 85xx + * + * Author: Scott Wood <scottwood@freescale.com> + * + * Copyright (c) 2007 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include "ops.h" +#include "stdio.h" + +#define TARGET_85xx +#include "ppcboot.h" + +static bd_t bd; +extern char _end[]; +extern char _dtb_start[], _dtb_end[]; + +static void platform_fixups(void) +{ + void *soc; + + dt_fixup_memory(bd.bi_memstart, bd.bi_memsize); + dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr, + bd.bi_enet2addr); + dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 8, bd.bi_busfreq); + + /* Unfortunately, the specific model number is encoded in the + * soc node name in existing dts files -- once that is fixed, + * this can do a simple path lookup. + */ + soc = find_node_by_devtype(NULL, "soc"); + if (soc) { + void *serial = NULL; + + setprop(soc, "bus-frequency", &bd.bi_busfreq, + sizeof(bd.bi_busfreq)); + + while ((serial = find_node_by_devtype(serial, "serial"))) { + if (get_parent(serial) != soc) + continue; + + setprop(serial, "clock-frequency", &bd.bi_busfreq, + sizeof(bd.bi_busfreq)); + } + } +} + +void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; + unsigned long avail_ram = end_of_ram - (unsigned long)_end; + + memcpy(&bd, (bd_t *)r3, sizeof(bd)); + loader_info.initrd_addr = r4; + loader_info.initrd_size = r4 ? r5 : 0; + loader_info.cmdline = (char *)r6; + loader_info.cmdline_len = r7 - r6; + + simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); + ft_init(_dtb_start, _dtb_end - _dtb_start, 32); + serial_console_init(); + platform_ops.fixups = platform_fixups; +} diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c new file mode 100644 index 00000000000..c9951550ed2 --- /dev/null +++ b/arch/powerpc/boot/devtree.c @@ -0,0 +1,307 @@ +/* + * devtree.c - convenience functions for device tree manipulation + * Copyright 2007 David Gibson, IBM Corporation. + * Copyright (c) 2007 Freescale Semiconductor, Inc. + * + * Authors: David Gibson <david@gibson.dropbear.id.au> + * Scott Wood <scottwood@freescale.com> + * + * 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. + */ +#include <stdarg.h> +#include <stddef.h> +#include "types.h" +#include "string.h" +#include "stdio.h" +#include "ops.h" + +void dt_fixup_memory(u64 start, u64 size) +{ + void *root, *memory; + int naddr, nsize, i; + u32 memreg[4]; + + root = finddevice("/"); + if (getprop(root, "#address-cells", &naddr, sizeof(naddr)) < 0) + naddr = 2; + if (naddr < 1 || naddr > 2) + fatal("Can't cope with #address-cells == %d in /\n\r", naddr); + + if (getprop(root, "#size-cells", &nsize, sizeof(nsize)) < 0) + nsize = 1; + if (nsize < 1 || nsize > 2) + fatal("Can't cope with #size-cells == %d in /\n\r", nsize); + + i = 0; + if (naddr == 2) + memreg[i++] = start >> 32; + memreg[i++] = start & 0xffffffff; + if (nsize == 2) + memreg[i++] = size >> 32; + memreg[i++] = size & 0xffffffff; + + memory = finddevice("/memory"); + if (! memory) { + memory = create_node(NULL, "memory"); + setprop_str(memory, "device_type", "memory"); + } + + printf("Memory <- <0x%x", memreg[0]); + for (i = 1; i < (naddr + nsize); i++) + printf(" 0x%x", memreg[i]); + printf("> (%ldMB)\n\r", (unsigned long)(size >> 20)); + + setprop(memory, "reg", memreg, (naddr + nsize)*sizeof(u32)); +} + +#define MHZ(x) ((x + 500000) / 1000000) + +void dt_fixup_cpu_clocks(u32 cpu, u32 tb, u32 bus) +{ + void *devp = NULL; + + printf("CPU clock-frequency <- 0x%x (%dMHz)\n\r", cpu, MHZ(cpu)); + printf("CPU timebase-frequency <- 0x%x (%dMHz)\n\r", tb, MHZ(tb)); + if (bus > 0) + printf("CPU bus-frequency <- 0x%x (%dMHz)\n\r", bus, MHZ(bus)); + + while ((devp = find_node_by_devtype(devp, "cpu"))) { + setprop_val(devp, "clock-frequency", cpu); + setprop_val(devp, "timebase-frequency", tb); + if (bus > 0) + setprop_val(devp, "bus-frequency", bus); + } +} + +void dt_fixup_clock(const char *path, u32 freq) +{ + void *devp = finddevice(path); + + if (devp) { + printf("%s: clock-frequency <- %x (%dMHz)\n\r", path, freq, MHZ(freq)); + setprop_val(devp, "clock-frequency", freq); + } +} + +void __dt_fixup_mac_addresses(u32 startindex, ...) +{ + va_list ap; + u32 index = startindex; + void *devp; + const u8 *addr; + + va_start(ap, startindex); + while ((addr = va_arg(ap, const u8 *))) { + devp = find_node_by_prop_value(NULL, "linux,network-index", + (void*)&index, sizeof(index)); + + printf("ENET%d: local-mac-address <-" + " %02x:%02x:%02x:%02x:%02x:%02x\n\r", index, + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + if (devp) + setprop(devp, "local-mac-address", addr, 6); + + index++; + } + va_end(ap); +} + +#define MAX_ADDR_CELLS 4 +#define MAX_RANGES 8 + +static void get_reg_format(void *node, u32 *naddr, u32 *nsize) +{ + if (getprop(node, "#address-cells", naddr, 4) != 4) + *naddr = 2; + if (getprop(node, "#size-cells", nsize, 4) != 4) + *nsize = 1; +} + +static void copy_val(u32 *dest, u32 *src, int naddr) +{ + int pad = MAX_ADDR_CELLS - naddr; + + memset(dest, 0, pad * 4); + memcpy(dest + pad, src, naddr * 4); +} + +static int sub_reg(u32 *reg, u32 *sub) +{ + int i, borrow = 0; + + for (i = MAX_ADDR_CELLS - 1; i >= 0; i--) { + int prev_borrow = borrow; + borrow = reg[i] < sub[i] + prev_borrow; + reg[i] -= sub[i] + prev_borrow; + } + + return !borrow; +} + +static int add_reg(u32 *reg, u32 *add, int naddr) +{ + int i, carry = 0; + + for (i = MAX_ADDR_CELLS - 1; i >= MAX_ADDR_CELLS - naddr; i--) { + u64 tmp = (u64)reg[i] + add[i] + carry; + carry = tmp >> 32; + reg[i] = (u32)tmp; + } + + return !carry; +} + +/* It is assumed that if the first byte of reg fits in a + * range, then the whole reg block fits. + */ +static int compare_reg(u32 *reg, u32 *range, u32 *rangesize) +{ + int i; + u32 end; + + for (i = 0; i < MAX_ADDR_CELLS; i++) { + if (reg[i] < range[i]) + return 0; + if (reg[i] > range[i]) + break; + } + + for (i = 0; i < MAX_ADDR_CELLS; i++) { + end = range[i] + rangesize[i]; + + if (reg[i] < end) + break; + if (reg[i] > end) + return 0; + } + + return reg[i] != end; +} + +/* reg must be MAX_ADDR_CELLS */ +static int find_range(u32 *reg, u32 *ranges, int nregaddr, + int naddr, int nsize, int buflen) +{ + int nrange = nregaddr + naddr + nsize; + int i; + + for (i = 0; i + nrange <= buflen; i += nrange) { + u32 range_addr[MAX_ADDR_CELLS]; + u32 range_size[MAX_ADDR_CELLS]; + + copy_val(range_addr, ranges + i, naddr); + copy_val(range_size, ranges + i + nregaddr + naddr, nsize); + + if (compare_reg(reg, range_addr, range_size)) + return i; + } + + return -1; +} + +/* Currently only generic buses without special encodings are supported. + * In particular, PCI is not supported. Also, only the beginning of the + * reg block is tracked; size is ignored except in ranges. + */ +static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3]; + +static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, + unsigned long *size) +{ + u32 last_addr[MAX_ADDR_CELLS]; + u32 this_addr[MAX_ADDR_CELLS]; + void *parent; + u64 ret_addr, ret_size; + u32 naddr, nsize, prev_naddr; + int buflen, offset; + + parent = get_parent(node); + if (!parent) + return 0; + + get_reg_format(parent, &naddr, &nsize); + + if (nsize > 2) + return 0; + + offset = (naddr + nsize) * res; + + if (reglen < offset + naddr + nsize || + sizeof(dt_xlate_buf) < offset + naddr + nsize) + return 0; + + copy_val(last_addr, dt_xlate_buf + offset, naddr); + + ret_size = dt_xlate_buf[offset + naddr]; + if (nsize == 2) { + ret_size <<= 32; + ret_size |= dt_xlate_buf[offset + naddr + 1]; + } + + while ((node = get_parent(node))) { + prev_naddr = naddr; + + get_reg_format(node, &naddr, &nsize); + + buflen = getprop(node, "ranges", dt_xlate_buf, + sizeof(dt_xlate_buf)); + if (buflen < 0) + continue; + if (buflen > sizeof(dt_xlate_buf)) + return 0; + + offset = find_range(last_addr, dt_xlate_buf, prev_naddr, + naddr, nsize, buflen / 4); + + if (offset < 0) + return 0; + + copy_val(this_addr, dt_xlate_buf + offset, prev_naddr); + + if (!sub_reg(last_addr, this_addr)) + return 0; + + copy_val(this_addr, dt_xlate_buf + offset + prev_naddr, naddr); + + if (!add_reg(last_addr, this_addr, naddr)) + return 0; + } + + if (naddr > 2) + return 0; + + ret_addr = ((u64)last_addr[2] << 32) | last_addr[3]; + + if (sizeof(void *) == 4 && + (ret_addr >= 0x100000000ULL || ret_size > 0x100000000ULL || + ret_addr + ret_size > 0x100000000ULL)) + return 0; + + *addr = ret_addr; + if (size) + *size = ret_size; + + return 1; +} + +int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size) +{ + int reglen; + + reglen = getprop(node, "reg", dt_xlate_buf, sizeof(dt_xlate_buf)) / 4; + return dt_xlate(node, res, reglen, addr, size); +} + +int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr) +{ + + if (buflen > sizeof(dt_xlate_buf)) + return 0; + + memcpy(dt_xlate_buf, buf, buflen); + return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL); +} diff --git a/arch/powerpc/boot/dts/kuroboxHD.dts b/arch/powerpc/boot/dts/kuroboxHD.dts index b89791802e8..157dc98d398 100644 --- a/arch/powerpc/boot/dts/kuroboxHD.dts +++ b/arch/powerpc/boot/dts/kuroboxHD.dts @@ -29,7 +29,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts" cpus { linux,phandle = <2000>; - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; @@ -126,17 +125,17 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts" interrupt-parent = <4400>; interrupt-map-mask = <f800 0 0 7>; interrupt-map = < - /* IDSEL 0x11 - IRQ0 ETH */ + /* IDSEL 11 - IRQ0 ETH */ 5800 0 0 1 4400 0 1 5800 0 0 2 4400 1 1 5800 0 0 3 4400 2 1 5800 0 0 4 4400 3 1 - /* IDSEL 0x12 - IRQ1 IDE0 */ + /* IDSEL 12 - IRQ1 IDE0 */ 6000 0 0 1 4400 1 1 6000 0 0 2 4400 2 1 6000 0 0 3 4400 3 1 6000 0 0 4 4400 0 1 - /* IDSEL 0x14 - IRQ3 USB2.0 */ + /* IDSEL 14 - IRQ3 USB2.0 */ 7000 0 0 1 4400 3 1 7000 0 0 2 4400 3 1 7000 0 0 3 4400 3 1 diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts index 753102752d8..919eb29097d 100644 --- a/arch/powerpc/boot/dts/kuroboxHG.dts +++ b/arch/powerpc/boot/dts/kuroboxHG.dts @@ -29,7 +29,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts" cpus { linux,phandle = <2000>; - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; @@ -126,17 +125,17 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts" interrupt-parent = <4400>; interrupt-map-mask = <f800 0 0 7>; interrupt-map = < - /* IDSEL 0x11 - IRQ0 ETH */ + /* IDSEL 11 - IRQ0 ETH */ 5800 0 0 1 4400 0 1 5800 0 0 2 4400 1 1 5800 0 0 3 4400 2 1 5800 0 0 4 4400 3 1 - /* IDSEL 0x12 - IRQ1 IDE0 */ + /* IDSEL 12 - IRQ1 IDE0 */ 6000 0 0 1 4400 1 1 6000 0 0 2 4400 2 1 6000 0 0 3 4400 3 1 6000 0 0 4 4400 0 1 - /* IDSEL 0x14 - IRQ3 USB2.0 */ + /* IDSEL 14 - IRQ3 USB2.0 */ 7000 0 0 1 4400 3 1 7000 0 0 2 4400 3 1 7000 0 0 3 4400 3 1 diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts index c03103c6328..ba54c6b40a0 100644 --- a/arch/powerpc/boot/dts/lite5200.dts +++ b/arch/powerpc/boot/dts/lite5200.dts @@ -24,7 +24,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts index 3875ca9a9a6..2e003081b0d 100644 --- a/arch/powerpc/boot/dts/lite5200b.dts +++ b/arch/powerpc/boot/dts/lite5200b.dts @@ -24,7 +24,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts index 41d0720c590..6fa3754f293 100644 --- a/arch/powerpc/boot/dts/mpc7448hpc2.dts +++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts @@ -19,7 +19,6 @@ linux,phandle = <100>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells =<0>; linux,phandle = <200>; diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts index 260b2e44777..423eedcf634 100644 --- a/arch/powerpc/boot/dts/mpc8272ads.dts +++ b/arch/powerpc/boot/dts/mpc8272ads.dts @@ -17,7 +17,6 @@ linux,phandle = <100>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; linux,phandle = <200>; diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts index 6d721900d00..a1533cc07d0 100644 --- a/arch/powerpc/boot/dts/mpc8313erdb.dts +++ b/arch/powerpc/boot/dts/mpc8313erdb.dts @@ -16,7 +16,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts index 06b310698a0..c798491f4cd 100644 --- a/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts @@ -16,7 +16,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts new file mode 100644 index 00000000000..b55bced1593 --- /dev/null +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts @@ -0,0 +1,291 @@ +/* + * MPC832x RDB Device Tree Source + * + * Copyright 2007 Freescale Semiconductor 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. + */ + +/ { + model = "MPC8323ERDB"; + compatible = "MPC8323ERDB", "MPC832xRDB", "MPC83xxRDB"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,8323@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <4000>; // L1, 16K + i-cache-size = <4000>; // L1, 16K + timebase-frequency = <0>; + bus-frequency = <0>; + clock-frequency = <0>; + 32-bit; + }; + }; + + memory { + device_type = "memory"; + reg = <00000000 04000000>; + }; + + soc8323@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <0 e0000000 00100000>; + reg = <e0000000 00000200>; + bus-frequency = <0>; + + wdt@200 { + device_type = "watchdog"; + compatible = "mpc83xx_wdt"; + reg = <200 100>; + }; + + i2c@3000 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3000 100>; + interrupts = <e 8>; + interrupt-parent = <&pic>; + dfsrr; + }; + + serial@4500 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4500 100>; + clock-frequency = <0>; + interrupts = <9 8>; + interrupt-parent = <&pic>; + }; + + serial@4600 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4600 100>; + clock-frequency = <0>; + interrupts = <a 8>; + interrupt-parent = <&pic>; + }; + + crypto@30000 { + device_type = "crypto"; + model = "SEC2"; + compatible = "talitos"; + reg = <30000 7000>; + interrupts = <b 8>; + interrupt-parent = <&pic>; + /* Rev. 2.2 */ + num-channels = <1>; + channel-fifo-len = <18>; + exec-units-mask = <0000004c>; + descriptor-types-mask = <0122003f>; + }; + + pci@8500 { + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + /* IDSEL 0x10 AD16 (USB) */ + 8000 0 0 1 &pic 11 8 + + /* IDSEL 0x11 AD17 (Mini1)*/ + 8800 0 0 1 &pic 12 8 + 8800 0 0 2 &pic 13 8 + 8800 0 0 3 &pic 14 8 + 8800 0 0 4 &pic 30 8 + + /* IDSEL 0x12 AD18 (PCI/Mini2) */ + 9000 0 0 1 &pic 13 8 + 9000 0 0 2 &pic 14 8 + 9000 0 0 3 &pic 30 8 + 9000 0 0 4 &pic 11 8>; + + interrupt-parent = <&pic>; + interrupts = <42 8>; + bus-range = <0 0>; + ranges = <42000000 0 80000000 80000000 0 10000000 + 02000000 0 90000000 90000000 0 10000000 + 01000000 0 d0000000 d0000000 0 04000000>; + clock-frequency = <0>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <8500 100>; + compatible = "83xx"; + device_type = "pci"; + }; + + pic:pic@700 { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <700 100>; + built-in; + device_type = "ipic"; + }; + + par_io@1400 { + reg = <1400 100>; + device_type = "par_io"; + num-ports = <7>; + + ucc2pio:ucc_pin@02 { + pio-map = < + /* port pin dir open_drain assignment has_irq */ + 3 4 3 0 2 0 /* MDIO */ + 3 5 1 0 2 0 /* MDC */ + 3 15 2 0 1 0 /* RX_CLK (CLK16) */ + 3 17 2 0 1 0 /* TX_CLK (CLK3) */ + 0 12 1 0 1 0 /* TxD0 */ + 0 13 1 0 1 0 /* TxD1 */ + 0 14 1 0 1 0 /* TxD2 */ + 0 15 1 0 1 0 /* TxD3 */ + 0 16 2 0 1 0 /* RxD0 */ + 0 17 2 0 1 0 /* RxD1 */ + 0 18 2 0 1 0 /* RxD2 */ + 0 19 2 0 1 0 /* RxD3 */ + 0 1a 2 0 1 0 /* RX_ER */ + 0 1b 1 0 1 0 /* TX_ER */ + 0 1c 2 0 1 0 /* RX_DV */ + 0 1d 2 0 1 0 /* COL */ + 0 1e 1 0 1 0 /* TX_EN */ + 0 1f 2 0 1 0>; /* CRS */ + }; + ucc3pio:ucc_pin@03 { + pio-map = < + /* port pin dir open_drain assignment has_irq */ + 0 d 2 0 1 0 /* RX_CLK (CLK9) */ + 3 18 2 0 1 0 /* TX_CLK (CLK10) */ + 1 0 1 0 1 0 /* TxD0 */ + 1 1 1 0 1 0 /* TxD1 */ + 1 2 1 0 1 0 /* TxD2 */ + 1 3 1 0 1 0 /* TxD3 */ + 1 4 2 0 1 0 /* RxD0 */ + 1 5 2 0 1 0 /* RxD1 */ + 1 6 2 0 1 0 /* RxD2 */ + 1 7 2 0 1 0 /* RxD3 */ + 1 8 2 0 1 0 /* RX_ER */ + 1 9 1 0 1 0 /* TX_ER */ + 1 a 2 0 1 0 /* RX_DV */ + 1 b 2 0 1 0 /* COL */ + 1 c 1 0 1 0 /* TX_EN */ + 1 d 2 0 1 0>; /* CRS */ + }; + }; + }; + + qe@e0100000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "qe"; + model = "QE"; + ranges = <0 e0100000 00100000>; + reg = <e0100000 480>; + brg-frequency = <0>; + bus-frequency = <BCD3D80>; + + muram@10000 { + device_type = "muram"; + ranges = <0 00010000 00004000>; + + data-only@0 { + reg = <0 4000>; + }; + }; + + spi@4c0 { + device_type = "spi"; + compatible = "fsl_spi"; + reg = <4c0 40>; + interrupts = <2>; + interrupt-parent = <&qeic>; + mode = "cpu"; + }; + + spi@500 { + device_type = "spi"; + compatible = "fsl_spi"; + reg = <500 40>; + interrupts = <1>; + interrupt-parent = <&qeic>; + mode = "cpu"; + }; + + ucc@3000 { + device_type = "network"; + compatible = "ucc_geth"; + model = "UCC"; + device-id = <2>; + reg = <3000 200>; + interrupts = <21>; + interrupt-parent = <&qeic>; + mac-address = [ 00 04 9f ef 03 02 ]; + rx-clock = <20>; + tx-clock = <13>; + phy-handle = <&phy00>; + pio-handle = <&ucc2pio>; + }; + + ucc@2200 { + device_type = "network"; + compatible = "ucc_geth"; + model = "UCC"; + device-id = <3>; + reg = <2200 200>; + interrupts = <22>; + interrupt-parent = <&qeic>; + mac-address = [ 00 04 9f ef 03 01 ]; + rx-clock = <19>; + tx-clock = <1a>; + phy-handle = <&phy04>; + pio-handle = <&ucc3pio>; + }; + + mdio@3120 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3120 18>; + device_type = "mdio"; + compatible = "ucc_geth_phy"; + + phy00:ethernet-phy@00 { + interrupt-parent = <&pic>; + interrupts = <0>; + reg = <0>; + device_type = "ethernet-phy"; + interface = <3>; //ENET_100_MII + }; + phy04:ethernet-phy@04 { + interrupt-parent = <&pic>; + interrupts = <0>; + reg = <4>; + device_type = "ethernet-phy"; + interface = <3>; + }; + }; + + qeic:qeic@80 { + interrupt-controller; + device_type = "qeic"; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <80 80>; + built-in; + big-endian; + interrupts = <20 8 21 8>; //high:32 low:33 + interrupt-parent = <&pic>; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts index 61b550bf164..db0d0030327 100644 --- a/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts @@ -15,7 +15,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/arch/powerpc/boot/dts/mpc8349emitxgp.dts index b2e1a5ec377..f636528a3c7 100644 --- a/arch/powerpc/boot/dts/mpc8349emitxgp.dts +++ b/arch/powerpc/boot/dts/mpc8349emitxgp.dts @@ -15,7 +15,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts index e4b43c24bc0..07bcc5194d2 100644 --- a/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/arch/powerpc/boot/dts/mpc834x_mds.dts @@ -16,7 +16,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index 4fe45c02184..7f578eb5708 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts @@ -21,7 +21,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts index 3c0917fa791..f261d647ac8 100644 --- a/arch/powerpc/boot/dts/mpc8540ads.dts +++ b/arch/powerpc/boot/dts/mpc8540ads.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts index 2a1ae760ab3..5fdcb69554f 100644 --- a/arch/powerpc/boot/dts/mpc8541cds.dts +++ b/arch/powerpc/boot/dts/mpc8541cds.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts new file mode 100644 index 00000000000..6b084605bb4 --- /dev/null +++ b/arch/powerpc/boot/dts/mpc8544ds.dts @@ -0,0 +1,136 @@ +/* + * MPC8544 DS Device Tree Source + * + * Copyright 2007 Freescale Semiconductor 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. + */ + +/ { + model = "MPC8544DS"; + compatible = "MPC8544DS", "MPC85xxDS"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #cpus = <1>; + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,8544@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K + i-cache-size = <8000>; // L1, 32K + timebase-frequency = <0>; + bus-frequency = <0>; + clock-frequency = <0>; + 32-bit; + }; + }; + + memory { + device_type = "memory"; + reg = <00000000 00000000>; // Filled by U-Boot + }; + + soc8544@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <0 e0000000 00100000>; + reg = <e0000000 00100000>; // CCSRBAR 1M + bus-frequency = <0>; // Filled out by uboot. + + i2c@3000 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3000 100>; + interrupts = <1b 2>; + interrupt-parent = <&mpic>; + dfsrr; + }; + + mdio@24520 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "mdio"; + compatible = "gianfar"; + reg = <24520 20>; + phy0: ethernet-phy@0 { + interrupt-parent = <&mpic>; + interrupts = <3a 1>; + reg = <0>; + device_type = "ethernet-phy"; + }; + phy1: ethernet-phy@1 { + interrupt-parent = <&mpic>; + interrupts = <3a 1>; + reg = <1>; + device_type = "ethernet-phy"; + }; + }; + + ethernet@24000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <24000 1000>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <d 2 e 2 12 2>; + interrupt-parent = <&mpic>; + phy-handle = <&phy0>; + }; + + ethernet@26000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <26000 1000>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <f 2 10 2 11 2>; + interrupt-parent = <&mpic>; + phy-handle = <&phy1>; + }; + + serial@4500 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4500 100>; + clock-frequency = <0>; + interrupts = <1a 2>; + interrupt-parent = <&mpic>; + }; + + serial@4600 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4600 100>; + clock-frequency = <0>; + interrupts = <1a 2>; + interrupt-parent = <&mpic>; + }; + + mpic: pic@40000 { + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <40000 40000>; + built-in; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + big-endian; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts index 7eb5d81d5ee..b2b2200d042 100644 --- a/arch/powerpc/boot/dts/mpc8548cds.dts +++ b/arch/powerpc/boot/dts/mpc8548cds.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts index 5f9c102a0ab..68a4795720d 100644 --- a/arch/powerpc/boot/dts/mpc8555cds.dts +++ b/arch/powerpc/boot/dts/mpc8555cds.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts index 10502638b0e..1f2afe9291d 100644 --- a/arch/powerpc/boot/dts/mpc8560ads.dts +++ b/arch/powerpc/boot/dts/mpc8560ads.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts index bf49d8c997b..7361b36749c 100644 --- a/arch/powerpc/boot/dts/mpc8568mds.dts +++ b/arch/powerpc/boot/dts/mpc8568mds.dts @@ -21,7 +21,6 @@ #size-cells = <1>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts index 8a4995a85ba..260b264c869 100644 --- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts +++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts @@ -17,7 +17,6 @@ #size-cells = <1>; cpus { - #cpus = <2>; #address-cells = <1>; #size-cells = <0>; @@ -300,6 +299,30 @@ }; }; + + pci@9000 { + compatible = "86xx"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <9000 1000>; + bus-range = <0 ff>; + ranges = <02000000 0 a0000000 a0000000 0 20000000 + 01000000 0 00000000 e3000000 0 00100000>; + clock-frequency = <1fca055>; + interrupt-parent = <&mpic>; + interrupts = <19 2>; + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + /* IDSEL 0x0 */ + 0000 0 0 1 &mpic 44 1 + 0000 0 0 2 &mpic 45 1 + 0000 0 0 3 &mpic 46 1 + 0000 0 0 4 &mpic 47 1 + >; + }; + mpic: pic@40000 { clock-frequency = <0>; interrupt-controller; diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts index 2b56b5df451..c0d06fd1292 100644 --- a/arch/powerpc/boot/dts/mpc866ads.dts +++ b/arch/powerpc/boot/dts/mpc866ads.dts @@ -18,7 +18,6 @@ linux,phandle = <100>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; linux,phandle = <200>; diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts index faecd08c54d..110bf617060 100644 --- a/arch/powerpc/boot/dts/mpc885ads.dts +++ b/arch/powerpc/boot/dts/mpc885ads.dts @@ -18,7 +18,6 @@ linux,phandle = <100>; cpus { - #cpus = <1>; #address-cells = <1>; #size-cells = <0>; linux,phandle = <200>; diff --git a/arch/powerpc/boot/elf.h b/arch/powerpc/boot/elf.h index d4828fcf1cb..1941bc50d4c 100644 --- a/arch/powerpc/boot/elf.h +++ b/arch/powerpc/boot/elf.h @@ -146,4 +146,12 @@ typedef struct elf64_phdr { #define ELFOSABI_NONE 0 #define ELFOSABI_LINUX 3 +struct elf_info { + unsigned long loadsize; + unsigned long memsize; + unsigned long elfoffset; +}; +int parse_elf64(void *hdr, struct elf_info *info); +int parse_elf32(void *hdr, struct elf_info *info); + #endif /* _PPC_BOOT_ELF_H_ */ diff --git a/arch/powerpc/boot/elf_util.c b/arch/powerpc/boot/elf_util.c new file mode 100644 index 00000000000..7454aa4cc20 --- /dev/null +++ b/arch/powerpc/boot/elf_util.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) Paul Mackerras 1997. + * + * Updates for PPC64 by Todd Inglett, Dave Engebretsen & Peter Bergner. + * + * 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. + */ +#include <stdarg.h> +#include <stddef.h> +#include "elf.h" +#include "page.h" +#include "string.h" +#include "stdio.h" + +int parse_elf64(void *hdr, struct elf_info *info) +{ + Elf64_Ehdr *elf64 = hdr; + Elf64_Phdr *elf64ph; + unsigned int i; + + if (!(elf64->e_ident[EI_MAG0] == ELFMAG0 && + elf64->e_ident[EI_MAG1] == ELFMAG1 && + elf64->e_ident[EI_MAG2] == ELFMAG2 && + elf64->e_ident[EI_MAG3] == ELFMAG3 && + elf64->e_ident[EI_CLASS] == ELFCLASS64 && + elf64->e_ident[EI_DATA] == ELFDATA2MSB && + elf64->e_type == ET_EXEC && + elf64->e_machine == EM_PPC64)) + return 0; + + elf64ph = (Elf64_Phdr *)((unsigned long)elf64 + + (unsigned long)elf64->e_phoff); + for (i = 0; i < (unsigned int)elf64->e_phnum; i++, elf64ph++) + if (elf64ph->p_type == PT_LOAD) + break; + if (i >= (unsigned int)elf64->e_phnum) + return 0; + + info->loadsize = (unsigned long)elf64ph->p_filesz; + info->memsize = (unsigned long)elf64ph->p_memsz; + info->elfoffset = (unsigned long)elf64ph->p_offset; + + return 1; +} + +int parse_elf32(void *hdr, struct elf_info *info) +{ + Elf32_Ehdr *elf32 = hdr; + Elf32_Phdr *elf32ph; + unsigned int i; + + if (!(elf32->e_ident[EI_MAG0] == ELFMAG0 && + elf32->e_ident[EI_MAG1] == ELFMAG1 && + elf32->e_ident[EI_MAG2] == ELFMAG2 && + elf32->e_ident[EI_MAG3] == ELFMAG3 && + elf32->e_ident[EI_CLASS] == ELFCLASS32 && + elf32->e_ident[EI_DATA] == ELFDATA2MSB && + elf32->e_type == ET_EXEC && + elf32->e_machine == EM_PPC)) + return 0; + + elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff); + for (i = 0; i < elf32->e_phnum; i++, elf32ph++) + if (elf32ph->p_type == PT_LOAD) + break; + if (i >= elf32->e_phnum) + return 0; + + info->loadsize = elf32ph->p_filesz; + info->memsize = elf32ph->p_memsz; + info->elfoffset = elf32ph->p_offset; + return 1; +} diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c index c76c194715b..d00fbd92a45 100644 --- a/arch/powerpc/boot/flatdevtree.c +++ b/arch/powerpc/boot/flatdevtree.c @@ -29,12 +29,20 @@ #define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1)) +static char *ft_root_node(struct ft_cxt *cxt) +{ + return cxt->rgn[FT_STRUCT].start; +} + /* Routines for keeping node ptrs returned by ft_find_device current */ /* First entry not used b/c it would return 0 and be taken as NULL/error */ -static void *ft_node_add(struct ft_cxt *cxt, char *node) +static void *ft_get_phandle(struct ft_cxt *cxt, char *node) { unsigned int i; + if (!node) + return NULL; + for (i = 1; i < cxt->nodes_used; i++) /* already there? */ if (cxt->node_tbl[i] == node) return (void *)i; @@ -238,7 +246,7 @@ static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn, if (rgn == FT_STRUCT) ft_node_update_before(cxt, p, -nextra); } - *p -= nextra; + *pp -= nextra; cxt->rgn[rgn].start -= nextra; cxt->rgn[rgn].size += nextra; return 1; @@ -253,8 +261,14 @@ static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn, char *str, *next; enum ft_rgn_id r; - if (!cxt->isordered && !ft_reorder(cxt, nextra)) - return 0; + if (!cxt->isordered) { + unsigned long rgn_off = *pp - cxt->rgn[rgn].start; + + if (!ft_reorder(cxt, nextra)) + return 0; + + *pp = cxt->rgn[rgn].start + rgn_off; + } if (ft_shuffle(cxt, pp, rgn, nextra)) return 1; @@ -415,7 +429,7 @@ int ft_prop(struct ft_cxt *cxt, const char *name, const void *data, { int off, len; - off = lookup_string(cxt, name); + off = map_string(cxt, name); if (off == NO_STRING) return -1; @@ -590,7 +604,7 @@ int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size) void ft_begin_tree(struct ft_cxt *cxt) { - cxt->p = cxt->rgn[FT_STRUCT].start; + cxt->p = ft_root_node(cxt); } void ft_end_tree(struct ft_cxt *cxt) @@ -636,8 +650,21 @@ void *ft_find_device(struct ft_cxt *cxt, const char *srch_path) /* require absolute path */ if (srch_path[0] != '/') return NULL; - node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path); - return ft_node_add(cxt, node); + node = ft_find_descendent(cxt, ft_root_node(cxt), srch_path); + return ft_get_phandle(cxt, node); +} + +void *ft_find_device_rel(struct ft_cxt *cxt, const void *top, + const char *srch_path) +{ + char *node; + + node = ft_node_ph2node(cxt, top); + if (node == NULL) + return NULL; + + node = ft_find_descendent(cxt, node, srch_path); + return ft_get_phandle(cxt, node); } void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path) @@ -701,23 +728,18 @@ void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path) return NULL; } -void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) +void *__ft_get_parent(struct ft_cxt *cxt, void *node) { - void *node; int d; struct ft_atom atom; char *p; - node = ft_node_ph2node(cxt, phandle); - if (node == NULL) - return NULL; - for (d = 0; cxt->genealogy[d] != NULL; ++d) if (cxt->genealogy[d] == node) - return cxt->genealogy[d > 0 ? d - 1 : 0]; + return d > 0 ? cxt->genealogy[d - 1] : NULL; /* have to do it the hard way... */ - p = cxt->rgn[FT_STRUCT].start; + p = ft_root_node(cxt); d = 0; while ((p = ft_next(cxt, p, &atom)) != NULL) { switch (atom.tag) { @@ -726,7 +748,7 @@ void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) if (node == atom.data) { /* found it */ cxt->genealogy[d + 1] = NULL; - return d > 0 ? cxt->genealogy[d - 1] : node; + return d > 0 ? cxt->genealogy[d - 1] : NULL; } ++d; break; @@ -738,41 +760,131 @@ void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) return NULL; } -int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, - void *buf, const unsigned int buflen) +void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) { - struct ft_atom atom; - void *node; - char *p; - int depth; - unsigned int size; - - node = ft_node_ph2node(cxt, phandle); + void *node = ft_node_ph2node(cxt, phandle); if (node == NULL) - return -1; + return NULL; - depth = 0; - p = (char *)node; + node = __ft_get_parent(cxt, node); + return ft_get_phandle(cxt, node); +} - while ((p = ft_next(cxt, p, &atom)) != NULL) { +static const void *__ft_get_prop(struct ft_cxt *cxt, void *node, + const char *propname, unsigned int *len) +{ + struct ft_atom atom; + int depth = 0; + + while ((node = ft_next(cxt, node, &atom)) != NULL) { switch (atom.tag) { case OF_DT_BEGIN_NODE: ++depth; break; + case OF_DT_PROP: - if ((depth != 1) || strcmp(atom.name, propname)) + if (depth != 1 || strcmp(atom.name, propname)) break; - size = min(atom.size, buflen); - memcpy(buf, atom.data, size); - return atom.size; + + if (len) + *len = atom.size; + + return atom.data; + case OF_DT_END_NODE: if (--depth <= 0) - return -1; + return NULL; } } + + return NULL; +} + +int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, + void *buf, const unsigned int buflen) +{ + const void *data; + unsigned int size; + + void *node = ft_node_ph2node(cxt, phandle); + if (!node) + return -1; + + data = __ft_get_prop(cxt, node, propname, &size); + if (data) { + unsigned int clipped_size = min(size, buflen); + memcpy(buf, data, clipped_size); + return size; + } + return -1; } +void *__ft_find_node_by_prop_value(struct ft_cxt *cxt, void *prev, + const char *propname, const char *propval, + unsigned int proplen) +{ + struct ft_atom atom; + char *p = ft_root_node(cxt); + char *next; + int past_prev = prev ? 0 : 1; + int depth = -1; + + while ((next = ft_next(cxt, p, &atom)) != NULL) { + const void *data; + unsigned int size; + + switch (atom.tag) { + case OF_DT_BEGIN_NODE: + depth++; + + if (prev == p) { + past_prev = 1; + break; + } + + if (!past_prev || depth < 1) + break; + + data = __ft_get_prop(cxt, p, propname, &size); + if (!data || size != proplen) + break; + if (memcmp(data, propval, size)) + break; + + return p; + + case OF_DT_END_NODE: + if (depth-- == 0) + return NULL; + + break; + } + + p = next; + } + + return NULL; +} + +void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev, + const char *propname, const char *propval, + int proplen) +{ + void *node = NULL; + + if (prev) { + node = ft_node_ph2node(cxt, prev); + + if (!node) + return NULL; + } + + node = __ft_find_node_by_prop_value(cxt, node, propname, + propval, proplen); + return ft_get_phandle(cxt, node); +} + int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, const void *buf, const unsigned int buflen) { @@ -849,19 +961,26 @@ int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname) return -1; } -void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path) +void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name) { struct ft_atom atom; char *p, *next; int depth = 0; - p = cxt->rgn[FT_STRUCT].start; + if (parent) { + p = ft_node_ph2node(cxt, parent); + if (!p) + return NULL; + } else { + p = ft_root_node(cxt); + } + while ((next = ft_next(cxt, p, &atom)) != NULL) { switch (atom.tag) { case OF_DT_BEGIN_NODE: ++depth; - if (depth == 1 && strcmp(atom.name, path) == 0) - /* duplicate node path, return error */ + if (depth == 1 && strcmp(atom.name, name) == 0) + /* duplicate node name, return error */ return NULL; break; case OF_DT_END_NODE: @@ -870,7 +989,7 @@ void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path) break; /* end of node, insert here */ cxt->p = p; - ft_begin_node(cxt, path); + ft_begin_node(cxt, name); ft_end_node(cxt); return p; } diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h index b9cd9f61f35..cb26325d72d 100644 --- a/arch/powerpc/boot/flatdevtree.h +++ b/arch/powerpc/boot/flatdevtree.h @@ -97,10 +97,17 @@ int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size); void ft_dump_blob(const void *bphp); void ft_merge_blob(struct ft_cxt *cxt, void *blob); void *ft_find_device(struct ft_cxt *cxt, const char *srch_path); +void *ft_find_device_rel(struct ft_cxt *cxt, const void *top, + const char *srch_path); void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path); int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, void *buf, const unsigned int buflen); int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, const void *buf, const unsigned int buflen); +void *ft_get_parent(struct ft_cxt *cxt, const void *phandle); +void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev, + const char *propname, const char *propval, + int proplen); +void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name); #endif /* FLATDEVTREE_H */ diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c index 04da38fa477..4341e6558c1 100644 --- a/arch/powerpc/boot/flatdevtree_misc.c +++ b/arch/powerpc/boot/flatdevtree_misc.c @@ -16,24 +16,43 @@ static struct ft_cxt cxt; -static void *ft_finddevice(const char *name) +static void *fdtm_finddevice(const char *name) { return ft_find_device(&cxt, name); } -static int ft_getprop(const void *phandle, const char *propname, void *buf, - const int buflen) +static int fdtm_getprop(const void *phandle, const char *propname, + void *buf, const int buflen) { return ft_get_prop(&cxt, phandle, propname, buf, buflen); } -static int ft_setprop(const void *phandle, const char *propname, - const void *buf, const int buflen) +static int fdtm_setprop(const void *phandle, const char *propname, + const void *buf, const int buflen) { return ft_set_prop(&cxt, phandle, propname, buf, buflen); } -static unsigned long ft_finalize(void) +static void *fdtm_get_parent(const void *phandle) +{ + return ft_get_parent(&cxt, phandle); +} + +static void *fdtm_create_node(const void *phandle, const char *name) +{ + return ft_create_node(&cxt, phandle, name); +} + +static void *fdtm_find_node_by_prop_value(const void *prev, + const char *propname, + const char *propval, + int proplen) +{ + return ft_find_node_by_prop_value(&cxt, prev, propname, + propval, proplen); +} + +static unsigned long fdtm_finalize(void) { ft_end_tree(&cxt); return (unsigned long)cxt.bph; @@ -41,10 +60,13 @@ static unsigned long ft_finalize(void) int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device) { - dt_ops.finddevice = ft_finddevice; - dt_ops.getprop = ft_getprop; - dt_ops.setprop = ft_setprop; - dt_ops.finalize = ft_finalize; + dt_ops.finddevice = fdtm_finddevice; + dt_ops.getprop = fdtm_getprop; + dt_ops.setprop = fdtm_setprop; + dt_ops.get_parent = fdtm_get_parent; + dt_ops.create_node = fdtm_create_node; + dt_ops.find_node_by_prop_value = fdtm_find_node_by_prop_value; + dt_ops.finalize = fdtm_finalize; return ft_open(&cxt, dt_blob, max_size, max_find_device, platform_ops.realloc); diff --git a/arch/powerpc/boot/gunzip_util.c b/arch/powerpc/boot/gunzip_util.c new file mode 100644 index 00000000000..df8ab07e9ff --- /dev/null +++ b/arch/powerpc/boot/gunzip_util.c @@ -0,0 +1,206 @@ +/* + * Copyright 2007 David Gibson, IBM Corporation. + * Based on earlier work, Copyright (C) Paul Mackerras 1997. + * + * 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. + */ + +#include <stddef.h> +#include "string.h" +#include "stdio.h" +#include "ops.h" +#include "gunzip_util.h" + +#define HEAD_CRC 2 +#define EXTRA_FIELD 4 +#define ORIG_NAME 8 +#define COMMENT 0x10 +#define RESERVED 0xe0 + +/** + * gunzip_start - prepare to decompress gzip data + * @state: decompressor state structure to be initialized + * @src: buffer containing gzip compressed or uncompressed data + * @srclen: size in bytes of the buffer at src + * + * If the buffer at @src contains a gzip header, this function + * initializes zlib to decompress the data, storing the decompression + * state in @state. The other functions in this file can then be used + * to decompress data from the gzipped stream. + * + * If the buffer at @src does not contain a gzip header, it is assumed + * to contain uncompressed data. The buffer information is recorded + * in @state and the other functions in this file will simply copy + * data from the uncompressed data stream at @src. + * + * Any errors, such as bad compressed data, cause an error to be + * printed an the platform's exit() function to be called. + */ +void gunzip_start(struct gunzip_state *state, void *src, int srclen) +{ + char *hdr = src; + int hdrlen = 0; + + memset(state, 0, sizeof(*state)); + + /* Check for gzip magic number */ + if ((hdr[0] == 0x1f) && (hdr[1] == 0x8b)) { + /* gzip data, initialize zlib parameters */ + int r, flags; + + state->s.workspace = state->scratch; + if (zlib_inflate_workspacesize() > sizeof(state->scratch)) + fatal("insufficient scratch space for gunzip\n\r"); + + /* skip header */ + hdrlen = 10; + flags = hdr[3]; + if (hdr[2] != Z_DEFLATED || (flags & RESERVED) != 0) + fatal("bad gzipped data\n\r"); + if ((flags & EXTRA_FIELD) != 0) + hdrlen = 12 + hdr[10] + (hdr[11] << 8); + if ((flags & ORIG_NAME) != 0) + while (hdr[hdrlen++] != 0) + ; + if ((flags & COMMENT) != 0) + while (hdr[hdrlen++] != 0) + ; + if ((flags & HEAD_CRC) != 0) + hdrlen += 2; + if (hdrlen >= srclen) + fatal("gunzip_start: ran out of data in header\n\r"); + + r = zlib_inflateInit2(&state->s, -MAX_WBITS); + if (r != Z_OK) + fatal("inflateInit2 returned %d\n\r", r); + } + + state->s.next_in = src + hdrlen; + state->s.avail_in = srclen - hdrlen; +} + +/** + * gunzip_partial - extract bytes from a gzip data stream + * @state: gzip state structure previously initialized by gunzip_start() + * @dst: buffer to store extracted data + * @dstlen: maximum number of bytes to extract + * + * This function extracts at most @dstlen bytes from the data stream + * previously associated with @state by gunzip_start(), decompressing + * if necessary. Exactly @dstlen bytes are extracted unless the data + * stream doesn't contain enough bytes, in which case the entire + * remainder of the stream is decompressed. + * + * Returns the actual number of bytes extracted. If any errors occur, + * such as a corrupted compressed stream, an error is printed an the + * platform's exit() function is called. + */ +int gunzip_partial(struct gunzip_state *state, void *dst, int dstlen) +{ + int len; + + if (state->s.workspace) { + /* gunzipping */ + int r; + + state->s.next_out = dst; + state->s.avail_out = dstlen; + r = zlib_inflate(&state->s, Z_FULL_FLUSH); + if (r != Z_OK && r != Z_STREAM_END) + fatal("inflate returned %d msg: %s\n\r", r, state->s.msg); + len = state->s.next_out - (unsigned char *)dst; + } else { + /* uncompressed image */ + len = min(state->s.avail_in, (unsigned)dstlen); + memcpy(dst, state->s.next_in, len); + state->s.next_in += len; + state->s.avail_in -= len; + } + return len; +} + +/** + * gunzip_exactly - extract a fixed number of bytes from a gzip data stream + * @state: gzip state structure previously initialized by gunzip_start() + * @dst: buffer to store extracted data + * @dstlen: number of bytes to extract + * + * This function extracts exactly @dstlen bytes from the data stream + * previously associated with @state by gunzip_start(), decompressing + * if necessary. + * + * If there are less @dstlen bytes available in the data stream, or if + * any other errors occur, such as a corrupted compressed stream, an + * error is printed an the platform's exit() function is called. + */ +void gunzip_exactly(struct gunzip_state *state, void *dst, int dstlen) +{ + int len; + + len = gunzip_partial(state, dst, dstlen); + if (len < dstlen) + fatal("\n\rgunzip_exactly: ran out of data!" + " Wanted %d, got %d.\n\r", dstlen, len); +} + +/** + * gunzip_discard - discard bytes from a gzip data stream + * @state: gzip state structure previously initialized by gunzip_start() + * @len: number of bytes to discard + * + * This function extracts, then discards exactly @len bytes from the + * data stream previously associated with @state by gunzip_start(). + * Subsequent gunzip_partial(), gunzip_exactly() or gunzip_finish() + * calls will extract the data following the discarded bytes in the + * data stream. + * + * If there are less @len bytes available in the data stream, or if + * any other errors occur, such as a corrupted compressed stream, an + * error is printed an the platform's exit() function is called. + */ +void gunzip_discard(struct gunzip_state *state, int len) +{ + static char discard_buf[128]; + + while (len > sizeof(discard_buf)) { + gunzip_exactly(state, discard_buf, sizeof(discard_buf)); + len -= sizeof(discard_buf); + } + + if (len > 0) + gunzip_exactly(state, discard_buf, len); +} + +/** + * gunzip_finish - extract all remaining bytes from a gzip data stream + * @state: gzip state structure previously initialized by gunzip_start() + * @dst: buffer to store extracted data + * @dstlen: maximum number of bytes to extract + * + * This function extracts all remaining data, or at most @dstlen + * bytes, from the stream previously associated with @state by + * gunzip_start(). zlib is then shut down, so it is an error to use + * any of the functions in this file on @state until it is + * re-initialized with another call to gunzip_start(). + * + * If any errors occur, such as a corrupted compressed stream, an + * error is printed an the platform's exit() function is called. + */ +int gunzip_finish(struct gunzip_state *state, void *dst, int dstlen) +{ + int len; + + if (state->s.workspace) { + len = gunzip_partial(state, dst, dstlen); + zlib_inflateEnd(&state->s); + } else { + /* uncompressed image */ + len = min(state->s.avail_in, (unsigned)dstlen); + memcpy(dst, state->s.next_in, len); + } + + return len; +} diff --git a/arch/powerpc/boot/gunzip_util.h b/arch/powerpc/boot/gunzip_util.h new file mode 100644 index 00000000000..b3dfa6e87b3 --- /dev/null +++ b/arch/powerpc/boot/gunzip_util.h @@ -0,0 +1,45 @@ +/* + * Decompression convenience functions + * + * Copyright 2007 David Gibson, IBM Corporation. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ +#ifndef _PPC_BOOT_GUNZIP_UTIL_H_ +#define _PPC_BOOT_GUNZIP_UTIL_H_ + +#include "zlib.h" + +/* + * These functions are designed to make life easy for decompressing + * kernel images, initrd images or any other gzip compressed image, + * particularly if its useful to decompress part of the image (e.g. to + * examine headers) before decompressing the remainder. + * + * To use: + * - declare a gunzip_state structure + * - use gunzip_start() to initialize the state, associating it + * with a stream of compressed data + * - use gunzip_partial(), gunzip_exactly() and gunzip_discard() + * in any combination to extract pieces of data from the stream + * - Finally use gunzip_finish() to extract the tail of the + * compressed stream and wind up zlib + */ + +/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */ +#define GUNZIP_SCRATCH_SIZE 46912 + +struct gunzip_state { + z_stream s; + char scratch[46912]; +}; + +void gunzip_start(struct gunzip_state *state, void *src, int srclen); +int gunzip_partial(struct gunzip_state *state, void *dst, int dstlen); +void gunzip_exactly(struct gunzip_state *state, void *dst, int len); +void gunzip_discard(struct gunzip_state *state, int len); +int gunzip_finish(struct gunzip_state *state, void *dst, int len); + +#endif /* _PPC_BOOT_GUNZIP_UTIL_H_ */ diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 6f6b50d238b..56b56a8d4b2 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c @@ -14,11 +14,10 @@ #include "page.h" #include "string.h" #include "stdio.h" -#include "zlib.h" #include "ops.h" +#include "gunzip_util.h" #include "flatdevtree.h" - -extern void flush_cache(void *, unsigned long); +#include "reg.h" extern char _start[]; extern char __bss_start[]; @@ -30,304 +29,173 @@ extern char _initrd_end[]; extern char _dtb_start[]; extern char _dtb_end[]; +static struct gunzip_state gzstate; + struct addr_range { - unsigned long addr; + void *addr; unsigned long size; - unsigned long memsize; }; -static struct addr_range vmlinux; -static struct addr_range vmlinuz; -static struct addr_range initrd; - -static unsigned long elfoffset; -static int is_64bit; - -/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */ -static char scratch[46912]; -static char elfheader[256]; typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *); #undef DEBUG -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) +static struct addr_range prep_kernel(void) { - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) { - printf("bad gzipped data\n\r"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - printf("gunzip: ran out of data in header\n\r"); - exit(); - } + char elfheader[256]; + void *vmlinuz_addr = _vmlinux_start; + unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start; + void *addr = 0; + struct elf_info ei; + int len; - if (zlib_inflate_workspacesize() > sizeof(scratch)) { - printf("gunzip needs more mem\n"); - exit(); - } - memset(&s, 0, sizeof(s)); - s.workspace = scratch; - r = zlib_inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf("inflateInit2 returned %d\n\r", r); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = zlib_inflate(&s, Z_FULL_FLUSH); - if (r != Z_OK && r != Z_STREAM_END) { - printf("inflate returned %d msg: %s\n\r", r, s.msg); - exit(); + /* gunzip the ELF header of the kernel */ + gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size); + gunzip_exactly(&gzstate, elfheader, sizeof(elfheader)); + + if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei)) + fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r"); + + if (platform_ops.image_hdr) + platform_ops.image_hdr(elfheader); + + /* We need to alloc the memsize: gzip will expand the kernel + * text/data, then possible rubbish we don't care about. But + * the kernel bss must be claimed (it will be zero'd by the + * kernel itself) + */ + printf("Allocating 0x%lx bytes for kernel ...\n\r", ei.memsize); + + if (platform_ops.vmlinux_alloc) { + addr = platform_ops.vmlinux_alloc(ei.memsize); + } else { + if ((unsigned long)_start < ei.memsize) + fatal("Insufficient memory for kernel at address 0!" + " (_start=%p)\n\r", _start); } - *lenp = s.next_out - (unsigned char *) dst; - zlib_inflateEnd(&s); -} -static int is_elf64(void *hdr) -{ - Elf64_Ehdr *elf64 = hdr; - Elf64_Phdr *elf64ph; - unsigned int i; - - if (!(elf64->e_ident[EI_MAG0] == ELFMAG0 && - elf64->e_ident[EI_MAG1] == ELFMAG1 && - elf64->e_ident[EI_MAG2] == ELFMAG2 && - elf64->e_ident[EI_MAG3] == ELFMAG3 && - elf64->e_ident[EI_CLASS] == ELFCLASS64 && - elf64->e_ident[EI_DATA] == ELFDATA2MSB && - elf64->e_type == ET_EXEC && - elf64->e_machine == EM_PPC64)) - return 0; - - elf64ph = (Elf64_Phdr *)((unsigned long)elf64 + - (unsigned long)elf64->e_phoff); - for (i = 0; i < (unsigned int)elf64->e_phnum; i++, elf64ph++) - if (elf64ph->p_type == PT_LOAD) - break; - if (i >= (unsigned int)elf64->e_phnum) - return 0; - - elfoffset = (unsigned long)elf64ph->p_offset; - vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset; - vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset; - - is_64bit = 1; - return 1; -} + /* Finally, gunzip the kernel */ + printf("gunzipping (0x%p <- 0x%p:0x%p)...", addr, + vmlinuz_addr, vmlinuz_addr+vmlinuz_size); + /* discard up to the actual load data */ + gunzip_discard(&gzstate, ei.elfoffset - sizeof(elfheader)); + len = gunzip_finish(&gzstate, addr, ei.loadsize); + if (len != ei.loadsize) + fatal("ran out of data! only got 0x%x of 0x%lx bytes.\n\r", + len, ei.loadsize); + printf("done 0x%x bytes\n\r", len); -static int is_elf32(void *hdr) -{ - Elf32_Ehdr *elf32 = hdr; - Elf32_Phdr *elf32ph; - unsigned int i; - - if (!(elf32->e_ident[EI_MAG0] == ELFMAG0 && - elf32->e_ident[EI_MAG1] == ELFMAG1 && - elf32->e_ident[EI_MAG2] == ELFMAG2 && - elf32->e_ident[EI_MAG3] == ELFMAG3 && - elf32->e_ident[EI_CLASS] == ELFCLASS32 && - elf32->e_ident[EI_DATA] == ELFDATA2MSB && - elf32->e_type == ET_EXEC && - elf32->e_machine == EM_PPC)) - return 0; - - elf32 = (Elf32_Ehdr *)elfheader; - elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff); - for (i = 0; i < elf32->e_phnum; i++, elf32ph++) - if (elf32ph->p_type == PT_LOAD) - break; - if (i >= elf32->e_phnum) - return 0; - - elfoffset = elf32ph->p_offset; - vmlinux.size = elf32ph->p_filesz + elf32ph->p_offset; - vmlinux.memsize = elf32ph->p_memsz + elf32ph->p_offset; - return 1; + flush_cache(addr, ei.loadsize); + + return (struct addr_range){addr, ei.memsize}; } -static void prep_kernel(unsigned long a1, unsigned long a2) +static struct addr_range prep_initrd(struct addr_range vmlinux, void *chosen, + unsigned long initrd_addr, + unsigned long initrd_size) { - int len; - - vmlinuz.addr = (unsigned long)_vmlinux_start; - vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); - - /* gunzip the ELF header of the kernel */ - if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { - len = vmlinuz.size; - gunzip(elfheader, sizeof(elfheader), - (unsigned char *)vmlinuz.addr, &len); - } else - memcpy(elfheader, (const void *)vmlinuz.addr, - sizeof(elfheader)); - - if (!is_elf64(elfheader) && !is_elf32(elfheader)) { - printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r"); - exit(); + /* If we have an image attached to us, it overrides anything + * supplied by the loader. */ + if (_initrd_end > _initrd_start) { + printf("Attached initrd image at 0x%p-0x%p\n\r", + _initrd_start, _initrd_end); + initrd_addr = (unsigned long)_initrd_start; + initrd_size = _initrd_end - _initrd_start; + } else if (initrd_size > 0) { + printf("Using loader supplied ramdisk at 0x%lx-0x%lx\n\r", + initrd_addr, initrd_addr + initrd_size); } - if (platform_ops.image_hdr) - platform_ops.image_hdr(elfheader); - /* We need to alloc the memsize plus the file offset since gzip - * will expand the header (file offset), then the kernel, then - * possible rubbish we don't care about. But the kernel bss must - * be claimed (it will be zero'd by the kernel itself) - */ - printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize); - vmlinux.addr = (unsigned long)malloc(vmlinux.memsize); - if (vmlinux.addr == 0) { - printf("Can't allocate memory for kernel image !\n\r"); - exit(); - } + /* If there's no initrd at all, we're done */ + if (! initrd_size) + return (struct addr_range){0, 0}; /* - * Now find the initrd - * - * First see if we have an image attached to us. If so - * allocate memory for it and copy it there. + * If the initrd is too low it will be clobbered when the + * kernel relocates to its final location. In this case, + * allocate a safer place and move it. */ - initrd.size = (unsigned long)(_initrd_end - _initrd_start); - initrd.memsize = initrd.size; - if (initrd.size > 0) { + if (initrd_addr < vmlinux.size) { + void *old_addr = (void *)initrd_addr; + printf("Allocating 0x%lx bytes for initrd ...\n\r", - initrd.size); - initrd.addr = (unsigned long)malloc((u32)initrd.size); - if (initrd.addr == 0) { - printf("Can't allocate memory for initial " - "ramdisk !\n\r"); - exit(); - } - printf("initial ramdisk moving 0x%lx <- 0x%lx " - "(0x%lx bytes)\n\r", initrd.addr, - (unsigned long)_initrd_start, initrd.size); - memmove((void *)initrd.addr, (void *)_initrd_start, - initrd.size); - printf("initrd head: 0x%lx\n\r", - *((unsigned long *)initrd.addr)); - } else if (a2 != 0) { - /* Otherwise, see if yaboot or another loader gave us an initrd */ - initrd.addr = a1; - initrd.memsize = initrd.size = a2; - printf("Using loader supplied initrd at 0x%lx (0x%lx bytes)\n\r", - initrd.addr, initrd.size); + initrd_size); + initrd_addr = (unsigned long)malloc(initrd_size); + if (! initrd_addr) + fatal("Can't allocate memory for initial " + "ramdisk !\n\r"); + printf("Relocating initrd 0x%lx <- 0x%p (0x%lx bytes)\n\r", + initrd_addr, old_addr, initrd_size); + memmove((void *)initrd_addr, old_addr, initrd_size); } - /* Eventually gunzip the kernel */ - if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { - printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", - vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); - len = vmlinuz.size; - gunzip((void *)vmlinux.addr, vmlinux.memsize, - (unsigned char *)vmlinuz.addr, &len); - printf("done 0x%lx bytes\n\r", len); - } else { - memmove((void *)vmlinux.addr,(void *)vmlinuz.addr, - vmlinuz.size); - } + printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd_addr)); - /* Skip over the ELF header */ -#ifdef DEBUG - printf("... skipping 0x%lx bytes of ELF header\n\r", - elfoffset); -#endif - vmlinux.addr += elfoffset; + /* Tell the kernel initrd address via device tree */ + setprop_val(chosen, "linux,initrd-start", (u32)(initrd_addr)); + setprop_val(chosen, "linux,initrd-end", (u32)(initrd_addr+initrd_size)); - flush_cache((void *)vmlinux.addr, vmlinux.size); + return (struct addr_range){(void *)initrd_addr, initrd_size}; } /* A buffer that may be edited by tools operating on a zImage binary so as to * edit the command line passed to vmlinux (by setting /chosen/bootargs). * The buffer is put in it's own section so that tools may locate it easier. */ -static char builtin_cmdline[COMMAND_LINE_SIZE] +static char cmdline[COMMAND_LINE_SIZE] __attribute__((__section__("__builtin_cmdline"))); -static void get_cmdline(char *buf, int size) +static void prep_cmdline(void *chosen) { - void *devp; - int len = strlen(builtin_cmdline); - - buf[0] = '\0'; - - if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */ - len = min(len, size-1); - strncpy(buf, builtin_cmdline, len); - buf[len] = '\0'; - } - else if ((devp = finddevice("/chosen"))) - getprop(devp, "bootargs", buf, size); -} + if (cmdline[0] == '\0') + getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1); -static void set_cmdline(char *buf) -{ - void *devp; + printf("\n\rLinux/PowerPC load: %s", cmdline); + /* If possible, edit the command line */ + if (console_ops.edit_cmdline) + console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE); + printf("\n\r"); - if ((devp = finddevice("/chosen"))) - setprop(devp, "bootargs", buf, strlen(buf) + 1); + /* Put the command line back into the devtree for the kernel */ + setprop_str(chosen, "bootargs", cmdline); } struct platform_ops platform_ops; struct dt_ops dt_ops; struct console_ops console_ops; +struct loader_info loader_info; -void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) +void start(void) { + struct addr_range vmlinux, initrd; kernel_entry_t kentry; - char cmdline[COMMAND_LINE_SIZE]; unsigned long ft_addr = 0; + void *chosen; - memset(__bss_start, 0, _end - __bss_start); - memset(&platform_ops, 0, sizeof(platform_ops)); - memset(&dt_ops, 0, sizeof(dt_ops)); - memset(&console_ops, 0, sizeof(console_ops)); + /* Do this first, because malloc() could clobber the loader's + * command line. Only use the loader command line if a + * built-in command line wasn't set by an external tool */ + if ((loader_info.cmdline_len > 0) && (cmdline[0] == '\0')) + memmove(cmdline, loader_info.cmdline, + min(loader_info.cmdline_len, COMMAND_LINE_SIZE-1)); - if (platform_init(promptr, _dtb_start, _dtb_end)) - exit(); if (console_ops.open && (console_ops.open() < 0)) exit(); if (platform_ops.fixups) platform_ops.fixups(); printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", - _start, sp); + _start, get_sp()); - prep_kernel(a1, a2); + /* Ensure that the device tree has a /chosen node */ + chosen = finddevice("/chosen"); + if (!chosen) + chosen = create_node(NULL, "chosen"); - /* If cmdline came from zimage wrapper or if we can edit the one - * in the dt, print it out and edit it, if possible. - */ - if ((strlen(builtin_cmdline) > 0) || console_ops.edit_cmdline) { - get_cmdline(cmdline, COMMAND_LINE_SIZE); - printf("\n\rLinux/PowerPC load: %s", cmdline); - if (console_ops.edit_cmdline) - console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE); - printf("\n\r"); - set_cmdline(cmdline); - } + vmlinux = prep_kernel(); + initrd = prep_initrd(vmlinux, chosen, + loader_info.initrd_addr, loader_info.initrd_size); + prep_cmdline(chosen); printf("Finalizing device tree..."); if (dt_ops.finalize) @@ -335,7 +203,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) if (ft_addr) printf(" flat tree at 0x%lx\n\r", ft_addr); else - printf(" using OF tree (promptr=%p)\n\r", promptr); + printf(" using OF tree (promptr=%p)\n\r", loader_info.promptr); if (console_ops.close) console_ops.close(); @@ -344,10 +212,9 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) if (ft_addr) kentry(ft_addr, 0, NULL); else - /* XXX initrd addr/size should be passed in properties */ - kentry(initrd.addr, initrd.size, promptr); + kentry((unsigned long)initrd.addr, initrd.size, + loader_info.promptr); - /* console closed so printf below may not work */ - printf("Error: Linux kernel returned to zImage boot wrapper!\n\r"); - exit(); + /* console closed so printf in fatal below may not work */ + fatal("Error: Linux kernel returned to zImage boot wrapper!\n\r"); } diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c index 1ffe72e35cd..f8f1b2f3141 100644 --- a/arch/powerpc/boot/ns16550.c +++ b/arch/powerpc/boot/ns16550.c @@ -55,10 +55,15 @@ static u8 ns16550_tstc(void) int ns16550_console_init(void *devp, struct serial_console_data *scdp) { int n; + unsigned long reg_phys; n = getprop(devp, "virtual-reg", ®_base, sizeof(reg_base)); - if (n != sizeof(reg_base)) - return -1; + if (n != sizeof(reg_base)) { + if (!dt_xlate_reg(devp, 0, ®_phys, NULL)) + return -1; + + reg_base = (void *)reg_phys; + } n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift)); if (n != sizeof(reg_shift)) diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c index 0182f384f3e..d16ee3e3f86 100644 --- a/arch/powerpc/boot/of.c +++ b/arch/powerpc/boot/of.c @@ -173,7 +173,7 @@ static void *claim(unsigned long virt, unsigned long size, unsigned long align) return (void *) virt; } -static void *of_try_claim(u32 size) +static void *of_try_claim(unsigned long size) { unsigned long addr = 0; @@ -208,6 +208,16 @@ static void of_image_hdr(const void *hdr) } } +static void *of_vmlinux_alloc(unsigned long size) +{ + void *p = malloc(size); + + if (!p) + fatal("Can't allocate memory for kernel image!\n\r"); + + return p; +} + static void of_exit(void) { call_prom("exit", 0, 0); @@ -256,11 +266,12 @@ static void of_console_write(char *buf, int len) call_prom("write", 3, 1, of_stdout_handle, buf, len); } -int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) +void platform_init(unsigned long a1, unsigned long a2, void *promptr) { platform_ops.image_hdr = of_image_hdr; platform_ops.malloc = of_try_claim; platform_ops.exit = of_exit; + platform_ops.vmlinux_alloc = of_vmlinux_alloc; dt_ops.finddevice = of_finddevice; dt_ops.getprop = of_getprop; @@ -270,5 +281,9 @@ int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) console_ops.write = of_console_write; prom = (int (*)(void *))promptr; - return 0; + loader_info.promptr = promptr; + if (a1 && a2 && a2 != 0xdeadbeef) { + loader_info.initrd_addr = a1; + loader_info.initrd_size = a2; + } } diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 8abb6516bb7..73bd47a3a07 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h @@ -11,7 +11,9 @@ #ifndef _PPC_BOOT_OPS_H_ #define _PPC_BOOT_OPS_H_ +#include <stddef.h> #include "types.h" +#include "string.h" #define COMMAND_LINE_SIZE 512 #define MAX_PATH_LEN 256 @@ -21,10 +23,11 @@ struct platform_ops { void (*fixups)(void); void (*image_hdr)(const void *); - void * (*malloc)(u32 size); + void * (*malloc)(unsigned long size); void (*free)(void *ptr); void * (*realloc)(void *ptr, unsigned long size); void (*exit)(void); + void * (*vmlinux_alloc)(unsigned long size); }; extern struct platform_ops platform_ops; @@ -35,6 +38,12 @@ struct dt_ops { const int buflen); int (*setprop)(const void *phandle, const char *name, const void *buf, const int buflen); + void *(*get_parent)(const void *phandle); + /* The node must not already exist. */ + void *(*create_node)(const void *parent, const char *name); + void *(*find_node_by_prop_value)(const void *prev, + const char *propname, + const char *propval, int proplen); unsigned long (*finalize)(void); }; extern struct dt_ops dt_ops; @@ -58,13 +67,23 @@ struct serial_console_data { void (*close)(void); }; -int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end); +struct loader_info { + void *promptr; + unsigned long initrd_addr, initrd_size; + char *cmdline; + int cmdline_len; +}; +extern struct loader_info loader_info; + +void start(void); int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); int serial_console_init(void); int ns16550_console_init(void *devp, struct serial_console_data *scdp); -void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, - u32 max_allocs); - +void *simple_alloc_init(char *base, unsigned long heap_size, + unsigned long granularity, unsigned long max_allocs); +extern void flush_cache(void *, unsigned long); +int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size); +int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr); static inline void *finddevice(const char *name) { @@ -76,12 +95,76 @@ static inline int getprop(void *devp, const char *name, void *buf, int buflen) return (dt_ops.getprop) ? dt_ops.getprop(devp, name, buf, buflen) : -1; } -static inline int setprop(void *devp, const char *name, void *buf, int buflen) +static inline int setprop(void *devp, const char *name, + const void *buf, int buflen) { return (dt_ops.setprop) ? dt_ops.setprop(devp, name, buf, buflen) : -1; } +#define setprop_val(devp, name, val) \ + do { \ + typeof(val) x = (val); \ + setprop((devp), (name), &x, sizeof(x)); \ + } while (0) + +static inline int setprop_str(void *devp, const char *name, const char *buf) +{ + if (dt_ops.setprop) + return dt_ops.setprop(devp, name, buf, strlen(buf) + 1); + + return -1; +} + +static inline void *get_parent(const char *devp) +{ + return dt_ops.get_parent ? dt_ops.get_parent(devp) : NULL; +} + +static inline void *create_node(const void *parent, const char *name) +{ + return dt_ops.create_node ? dt_ops.create_node(parent, name) : NULL; +} + -static inline void *malloc(u32 size) +static inline void *find_node_by_prop_value(const void *prev, + const char *propname, + const char *propval, int proplen) +{ + if (dt_ops.find_node_by_prop_value) + return dt_ops.find_node_by_prop_value(prev, propname, + propval, proplen); + + return NULL; +} + +static inline void *find_node_by_prop_value_str(const void *prev, + const char *propname, + const char *propval) +{ + return find_node_by_prop_value(prev, propname, propval, + strlen(propval) + 1); +} + +static inline void *find_node_by_devtype(const void *prev, + const char *type) +{ + return find_node_by_prop_value_str(prev, "device_type", type); +} + +void dt_fixup_memory(u64 start, u64 size); +void dt_fixup_cpu_clocks(u32 cpufreq, u32 tbfreq, u32 busfreq); +void dt_fixup_clock(const char *path, u32 freq); +void __dt_fixup_mac_addresses(u32 startindex, ...); +#define dt_fixup_mac_addresses(...) \ + __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL) + + +static inline void *find_node_by_linuxphandle(const u32 linuxphandle) +{ + return find_node_by_prop_value(NULL, "linux,phandle", + (char *)&linuxphandle, sizeof(u32)); +} + +static inline void *malloc(unsigned long size) { return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL; } @@ -98,5 +181,11 @@ static inline void exit(void) platform_ops.exit(); for(;;); } +#define fatal(args...) { printf(args); exit(); } + + +#define BSS_STACK(size) \ + static char _bss_stack[size]; \ + void *_platform_stack_top = _bss_stack + sizeof(_bss_stack); #endif /* _PPC_BOOT_OPS_H_ */ diff --git a/arch/powerpc/boot/ppcboot.h b/arch/powerpc/boot/ppcboot.h new file mode 100644 index 00000000000..5290ff2c2b2 --- /dev/null +++ b/arch/powerpc/boot/ppcboot.h @@ -0,0 +1,108 @@ +/* + * This interface is used for compatibility with old U-boots *ONLY*. + * Please do not imitate or extend this. + */ + +/* + * (C) Copyright 2000, 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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 + */ + +#ifndef __PPCBOOT_H__ +#define __PPCBOOT_H__ + +/* + * Board information passed to kernel from PPCBoot + * + * include/asm-ppc/ppcboot.h + */ + +#include "types.h" + +typedef struct bd_info { + unsigned long bi_memstart; /* start of DRAM memory */ + unsigned long bi_memsize; /* size of DRAM memory in bytes */ + unsigned long bi_flashstart; /* start of FLASH memory */ + unsigned long bi_flashsize; /* size of FLASH memory */ + unsigned long bi_flashoffset; /* reserved area for startup monitor */ + unsigned long bi_sramstart; /* start of SRAM memory */ + unsigned long bi_sramsize; /* size of SRAM memory */ +#if defined(TARGET_8xx) || defined(TARGET_CPM2) || defined(TARGET_85xx) ||\ + defined(TARGET_83xx) + unsigned long bi_immr_base; /* base of IMMR register */ +#endif +#if defined(TARGET_PPC_MPC52xx) + unsigned long bi_mbar_base; /* base of internal registers */ +#endif + unsigned long bi_bootflags; /* boot / reboot flag (for LynxOS) */ + unsigned long bi_ip_addr; /* IP Address */ + unsigned char bi_enetaddr[6]; /* Ethernet address */ + unsigned short bi_ethspeed; /* Ethernet speed in Mbps */ + unsigned long bi_intfreq; /* Internal Freq, in MHz */ + unsigned long bi_busfreq; /* Bus Freq, in MHz */ +#if defined(TARGET_CPM2) + unsigned long bi_cpmfreq; /* CPM_CLK Freq, in MHz */ + unsigned long bi_brgfreq; /* BRG_CLK Freq, in MHz */ + unsigned long bi_sccfreq; /* SCC_CLK Freq, in MHz */ + unsigned long bi_vco; /* VCO Out from PLL, in MHz */ +#endif +#if defined(TARGET_PPC_MPC52xx) + unsigned long bi_ipbfreq; /* IPB Bus Freq, in MHz */ + unsigned long bi_pcifreq; /* PCI Bus Freq, in MHz */ +#endif + unsigned long bi_baudrate; /* Console Baudrate */ +#if defined(TARGET_4xx) + unsigned char bi_s_version[4]; /* Version of this structure */ + unsigned char bi_r_version[32]; /* Version of the ROM (IBM) */ + unsigned int bi_procfreq; /* CPU (Internal) Freq, in Hz */ + unsigned int bi_plb_busfreq; /* PLB Bus speed, in Hz */ + unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ + unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ +#endif +#if defined(TARGET_HYMOD) + hymod_conf_t bi_hymod_conf; /* hymod configuration information */ +#endif +#if defined(TARGET_EVB64260) || defined(TARGET_405EP) || defined(TARGET_44x) || \ + defined(TARGET_85xx) || defined(TARGET_83xx) + /* second onboard ethernet port */ + unsigned char bi_enet1addr[6]; +#define HAVE_ENET1ADDR +#endif +#if defined(TARGET_EVB64260) || defined(TARGET_440GX) || defined(TARGET_85xx) + /* third onboard ethernet ports */ + unsigned char bi_enet2addr[6]; +#define HAVE_ENET2ADDR +#endif +#if defined(TARGET_440GX) + /* fourth onboard ethernet ports */ + unsigned char bi_enet3addr[6]; +#define HAVE_ENET3ADDR +#endif +#if defined(TARGET_4xx) + unsigned int bi_opbfreq; /* OB clock in Hz */ + int bi_iic_fast[2]; /* Use fast i2c mode */ +#endif +#if defined(TARGET_440GX) + int bi_phynum[4]; /* phy mapping */ + int bi_phymode[4]; /* phy mode */ +#endif +} bd_t; + +#define bi_tbfreq bi_intfreq + +#endif /* __PPCBOOT_H__ */ diff --git a/arch/powerpc/boot/reg.h b/arch/powerpc/boot/reg.h new file mode 100644 index 00000000000..d3cd9ee98af --- /dev/null +++ b/arch/powerpc/boot/reg.h @@ -0,0 +1,22 @@ +#ifndef _PPC_BOOT_REG_H +#define _PPC_BOOT_REG_H +/* + * Copyright 2007 Davud Gibson, IBM Corporation. + * + * 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. + */ + +static inline u32 mfpvr(void) +{ + u32 pvr; + asm volatile ("mfpvr %0" : "=r"(pvr)); + return pvr; +} + +register void *__stack_pointer asm("r1"); +#define get_sp() (__stack_pointer) + +#endif /* _PPC_BOOT_REG_H */ diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c index cfe3a7505ba..65ec135d015 100644 --- a/arch/powerpc/boot/simple_alloc.c +++ b/arch/powerpc/boot/simple_alloc.c @@ -19,24 +19,24 @@ #define ENTRY_IN_USE 0x02 static struct alloc_info { - u32 flags; - u32 base; - u32 size; + unsigned long flags; + unsigned long base; + unsigned long size; } *alloc_tbl; -static u32 tbl_entries; -static u32 alloc_min; -static u32 next_base; -static u32 space_left; +static unsigned long tbl_entries; +static unsigned long alloc_min; +static unsigned long next_base; +static unsigned long space_left; /* * First time an entry is used, its base and size are set. * An entry can be freed and re-malloc'd but its base & size don't change. * Should be smart enough for needs of bootwrapper. */ -static void *simple_malloc(u32 size) +static void *simple_malloc(unsigned long size) { - u32 i; + unsigned long i; struct alloc_info *p = alloc_tbl; if (size == 0) @@ -67,13 +67,14 @@ err_out: static struct alloc_info *simple_find_entry(void *ptr) { - u32 i; + unsigned long i; struct alloc_info *p = alloc_tbl; for (i=0; i<tbl_entries; i++,p++) { if (!(p->flags & ENTRY_BEEN_USED)) break; - if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr)) + if ((p->flags & ENTRY_IN_USE) && + (p->base == (unsigned long)ptr)) return p; } return NULL; @@ -122,10 +123,10 @@ static void *simple_realloc(void *ptr, unsigned long size) * Returns addr of first byte after heap so caller can see if it took * too much space. If so, change args & try again. */ -void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, - u32 max_allocs) +void *simple_alloc_init(char *base, unsigned long heap_size, + unsigned long granularity, unsigned long max_allocs) { - u32 heap_base, tbl_size; + unsigned long heap_base, tbl_size; heap_size = _ALIGN_UP(heap_size, granularity); alloc_min = granularity; @@ -136,7 +137,7 @@ void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8); memset(alloc_tbl, 0, tbl_size); - heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min); + heap_base = _ALIGN_UP((unsigned long)alloc_tbl + tbl_size, alloc_min); next_base = heap_base; space_left = heap_size; diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h index 73b8a91bfb3..adffc58412d 100644 --- a/arch/powerpc/boot/stdio.h +++ b/arch/powerpc/boot/stdio.h @@ -7,11 +7,12 @@ #define EINVAL 22 /* Invalid argument */ #define ENOSPC 28 /* No space left on device */ -extern int printf(const char *fmt, ...); +extern int printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); #define fprintf(fmt, args...) printf(args) -extern int sprintf(char *buf, const char *fmt, ...); +extern int sprintf(char *buf, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); extern int vsprintf(char *buf, const char *fmt, va_list args); diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index 024e4d425c5..5cedd901201 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -29,6 +29,7 @@ initrd= dtb= dts= cacheit= +gzip=.gz # cross-compilation prefix CROSS= @@ -42,7 +43,7 @@ tmpdir=. usage() { echo 'Usage: wrapper [-o output] [-p platform] [-i initrd]' >&2 echo ' [-d devtree] [-s tree.dts] [-c] [-C cross-prefix]' >&2 - echo ' [-D datadir] [-W workingdir] [vmlinux]' >&2 + echo ' [-D datadir] [-W workingdir] [--no-gzip] [vmlinux]' >&2 exit 1 } @@ -91,6 +92,9 @@ while [ "$#" -gt 0 ]; do [ "$#" -gt 0 ] || usage tmpdir="$1" ;; + --no-gzip) + gzip= + ;; -?) usage ;; @@ -137,31 +141,44 @@ miboot|uboot) ksection=image isection=initrd ;; +cuboot*) + gzip= + ;; esac vmz="$tmpdir/`basename \"$kernel\"`.$ext" -if [ -z "$cacheit" -o ! -f "$vmz.gz" -o "$vmz.gz" -ot "$kernel" ]; then +if [ -z "$cacheit" -o ! -f "$vmz$gzip" -o "$vmz$gzip" -ot "$kernel" ]; then ${CROSS}objcopy $objflags "$kernel" "$vmz.$$" - gzip -f -9 "$vmz.$$" + + if [ -n "$gzip" ]; then + gzip -f -9 "$vmz.$$" + fi + if [ -n "$cacheit" ]; then - mv -f "$vmz.$$.gz" "$vmz.gz" + mv -f "$vmz.$$$gzip" "$vmz$gzip" else vmz="$vmz.$$" fi fi +vmz="$vmz$gzip" + case "$platform" in -uboot) - rm -f "$ofile" +uboot|cuboot*) version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \ cut -d' ' -f3` if [ -n "$version" ]; then version="-n Linux-$version" fi +esac + +case "$platform" in +uboot) + rm -f "$ofile" mkimage -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \ - $version -d "$vmz.gz" "$ofile" + $version -d "$vmz" "$ofile" if [ -z "$cacheit" ]; then - rm -f $vmz.gz + rm -f "$vmz" fi exit 0 ;; @@ -173,9 +190,9 @@ addsec() { --set-section-flags=$3=contents,alloc,load,readonly,data } -addsec $tmp "$vmz.gz" $ksection $object/empty.o +addsec $tmp "$vmz" $ksection $object/empty.o if [ -z "$cacheit" ]; then - rm -f "$vmz.gz" + rm -f "$vmz" fi if [ -n "$initrd" ]; then @@ -191,7 +208,7 @@ fi if [ "$platform" != "miboot" ]; then ${CROSS}ld -m elf32ppc -T $lds -o "$ofile" \ - $object/crt0.o $platformo $tmp $object/wrapper.a + $platformo $tmp $object/wrapper.a rm $tmp fi @@ -201,7 +218,19 @@ pseries|chrp) $object/addnote "$ofile" ;; pmaccoff) - ${CROSS}objcopy -O aixcoff-rs6000 --set-start 0x500000 "$ofile" + entry=`objdump -f "$ofile" | grep '^start address ' | \ + cut -d' ' -f3` + ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile" $object/hack-coff "$ofile" ;; +cuboot*) + base=`${CROSS}nm "$ofile" | grep ' _start$' | cut -d' ' -f1` + entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | \ + cut -d' ' -f3` + mv "$ofile" "$ofile".elf + ${CROSS}objcopy -O binary "$ofile".elf "$ofile".bin + gzip -f -9 "$ofile".bin + mkimage -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \ + $version -d "$ofile".bin.gz "$ofile" + ;; esac diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S index a360905e542..fe87a90ce7f 100644 --- a/arch/powerpc/boot/zImage.coff.lds.S +++ b/arch/powerpc/boot/zImage.coff.lds.S @@ -1,5 +1,6 @@ OUTPUT_ARCH(powerpc:common) -ENTRY(_start) +ENTRY(_zimage_start_opd) +EXTERN(_zimage_start_opd) SECTIONS { . = (5*1024*1024); diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S index 4be3c6414b0..f6e380fdb38 100644 --- a/arch/powerpc/boot/zImage.lds.S +++ b/arch/powerpc/boot/zImage.lds.S @@ -1,5 +1,6 @@ OUTPUT_ARCH(powerpc:common) ENTRY(_zimage_start) +EXTERN(_zimage_start) SECTIONS { . = (4*1024*1024); diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index cf7e316ad4f..6061e5f7696 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.21-rc3 -# Fri Mar 9 23:34:53 2007 +# Linux kernel version: 2.6.21-rc6 +# Mon Apr 23 20:46:48 2007 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -139,11 +139,31 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_PPC_PMAC is not set # CONFIG_PPC_MAPLE is not set # CONFIG_PPC_PASEMI is not set +CONFIG_PPC_CELLEB=y +CONFIG_PPC_PS3=y + +# +# PS3 Platform Options +# +# CONFIG_PS3_ADVANCED is not set +CONFIG_PS3_HTAB_SIZE=20 +# CONFIG_PS3_DYNAMIC_DMA is not set +CONFIG_PS3_USE_LPAR_ADDR=y +CONFIG_PS3_VUART=y +CONFIG_PS3_PS3AV=y +CONFIG_PS3_SYS_MANAGER=y CONFIG_PPC_CELL=y CONFIG_PPC_CELL_NATIVE=y CONFIG_PPC_IBM_CELL_BLADE=y -CONFIG_PPC_PS3=y -CONFIG_PPC_CELLEB=y + +# +# Cell Broadband Engine options +# +CONFIG_SPU_FS=m +CONFIG_SPU_BASE=y +CONFIG_CBE_RAS=y +CONFIG_CBE_THERM=m +CONFIG_CBE_CPUFREQ=m CONFIG_PPC_NATIVE=y CONFIG_UDBG_RTAS_CONSOLE=y CONFIG_PPC_UDBG_BEAT=y @@ -175,26 +195,6 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_MPIC=y # -# Cell Broadband Engine options -# -CONFIG_SPU_FS=m -CONFIG_SPU_BASE=y -CONFIG_CBE_RAS=y -CONFIG_CBE_THERM=m -CONFIG_CBE_CPUFREQ=m - -# -# PS3 Platform Options -# -# CONFIG_PS3_ADVANCED is not set -CONFIG_PS3_HTAB_SIZE=20 -# CONFIG_PS3_DYNAMIC_DMA is not set -CONFIG_PS3_USE_LPAR_ADDR=y -CONFIG_PS3_VUART=y -CONFIG_PS3_PS3AV=y -CONFIG_PS3_SYS_MANAGER=y - -# # Kernel options # # CONFIG_HZ_100 is not set @@ -534,7 +534,6 @@ CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_AEC62XX=y # CONFIG_BLK_DEV_ALI15X3 is not set @@ -561,11 +560,10 @@ CONFIG_BLK_DEV_SIIMAGE=y # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_TC86C001 is not set -CONFIG_BLK_DEV_IDE_CELLEB=y +CONFIG_BLK_DEV_CELLEB=y # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_HD is not set # @@ -937,7 +935,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set CONFIG_HVC_DRIVER=y CONFIG_HVC_RTAS=y -# CONFIG_HVC_BEAT is not set +CONFIG_HVC_BEAT=y # # IPMI @@ -1482,6 +1480,8 @@ CONFIG_NLS_ISO8859_15=m # Distributed Lock Manager # # CONFIG_DLM is not set +# CONFIG_UCC_SLOW is not set +# CONFIG_UCC_FAST is not set # # Library routines @@ -1540,6 +1540,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_FAULT_INJECTION is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_PAGEALLOC is not set CONFIG_DEBUGGER=y CONFIG_XMON=y CONFIG_XMON_DEFAULT=y diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 7724847f702..3ccf19d8da3 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -143,7 +143,7 @@ CONFIG_PPC_NATIVE=y CONFIG_U3_DART=y # CONFIG_PPC_RTAS is not set # CONFIG_MMIO_NVRAM is not set -CONFIG_MPIC_BROKEN_U3=y +CONFIG_MPIC_U3_HT_IRQS=y # CONFIG_PPC_MPC106 is not set CONFIG_PPC_970_NAP=y # CONFIG_PPC_INDIRECT_IO is not set diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index de97f2f0ae9..15366f0e489 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig @@ -146,7 +146,7 @@ CONFIG_PPC_RTAS=y CONFIG_RTAS_PROC=y # CONFIG_RTAS_FLASH is not set # CONFIG_MMIO_NVRAM is not set -CONFIG_MPIC_BROKEN_U3=y +CONFIG_MPIC_U3_HT_IRQS=y # CONFIG_PPC_MPC106 is not set CONFIG_PPC_970_NAP=y # CONFIG_PPC_INDIRECT_IO is not set diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/powerpc/configs/mpc832x_rdb_defconfig index 3d6c2d74350..56fc0a82445 100644 --- a/arch/mips/configs/pnx8550-v2pci_defconfig +++ b/arch/powerpc/configs/mpc832x_rdb_defconfig @@ -1,159 +1,51 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.20 -# Tue Feb 20 21:47:39 2007 +# Linux kernel version: 2.6.21-rc3 +# Mon Mar 12 17:32:19 2007 # -CONFIG_MIPS=y - -# -# Machine selection -# -CONFIG_ZONE_DMA=y -# CONFIG_MIPS_MTX1 is not set -# CONFIG_MIPS_BOSPORUS is not set -# CONFIG_MIPS_PB1000 is not set -# CONFIG_MIPS_PB1100 is not set -# CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_PB1550 is not set -# CONFIG_MIPS_PB1200 is not set -# CONFIG_MIPS_DB1000 is not set -# CONFIG_MIPS_DB1100 is not set -# CONFIG_MIPS_DB1500 is not set -# CONFIG_MIPS_DB1550 is not set -# CONFIG_MIPS_DB1200 is not set -# CONFIG_MIPS_MIRAGE is not set -# CONFIG_BASLER_EXCITE is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_MACH_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MACH_JAZZ is not set -# CONFIG_LASAT is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_WR_PPMC is not set -# CONFIG_MIPS_SIM is not set -# CONFIG_MOMENCO_JAGUAR_ATX is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_3 is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MIPS_XXS1500 is not set -# CONFIG_PNX8550_JBS is not set -# CONFIG_PNX8550_STB810 is not set -# CONFIG_DDB5477 is not set -# CONFIG_MACH_VR41XX is not set -# CONFIG_PMC_YOSEMITE is not set -# CONFIG_QEMU is not set -# CONFIG_MARKEINS is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP27 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SIBYTE_BIGSUR is not set -# CONFIG_SIBYTE_SWARM is not set -# CONFIG_SIBYTE_SENTOSA is not set -# CONFIG_SIBYTE_RHONE is not set -# CONFIG_SIBYTE_CARMEL is not set -# CONFIG_SIBYTE_PTSWARM is not set -# CONFIG_SIBYTE_LITTLESUR is not set -# CONFIG_SIBYTE_CRHINE is not set -# CONFIG_SIBYTE_CRHONE is not set -# CONFIG_SNI_RM is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_TOSHIBA_RBTX4938 is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_GENERIC_FIND_NEXT_BIT=y +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_ARCH_HAS_ILOG2_U32=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DMA_NEED_PCI_MAP_STATE=y -# CONFIG_CPU_BIG_ENDIAN is not set -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_PNX8550=y -CONFIG_SOC_PNX8550=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 - -# -# CPU selection -# -CONFIG_CPU_MIPS32_R1=y -# CONFIG_CPU_MIPS32_R2 is not set -# CONFIG_CPU_MIPS64_R1 is not set -# CONFIG_CPU_MIPS64_R2 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_RM9000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_MIPSR1=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y - -# -# Kernel type -# -CONFIG_32BIT=y -# CONFIG_64BIT is not set -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_16KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_MIPS_MT_DISABLED=y -# CONFIG_MIPS_MT_SMP is not set -# CONFIG_MIPS_MT_SMTC is not set -# CONFIG_MIPS_VPE_LOADER is not set -# CONFIG_64BIT_PHYS_ADDR is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_ARCH_FLATMEM_ENABLE=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -# CONFIG_HZ_48 is not set -# CONFIG_HZ_100 is not set -# CONFIG_HZ_128 is not set -CONFIG_HZ_250=y -# CONFIG_HZ_256 is not set -# CONFIG_HZ_1000 is not set -# CONFIG_HZ_1024 is not set -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_HZ=250 -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -# CONFIG_PREEMPT is not set -# CONFIG_KEXEC is not set -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_AUDIT_ARCH=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_82xx is not set +CONFIG_PPC_83xx=y +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_PPC_8xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_83xx=y +CONFIG_PPC_FPU=y +# CONFIG_PPC_DCR_NATIVE is not set +# CONFIG_PPC_DCR_MMIO is not set +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_SMP is not set CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -177,24 +69,23 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_TASKSTATS is not set # CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y +# CONFIG_IKCONFIG is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_EMBEDDED=y -# CONFIG_SYSCTL_SYSCALL is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_SYSCTL_SYSCALL=y +# CONFIG_KALLSYMS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_EPOLL=y +# CONFIG_EPOLL is not set CONFIG_SHMEM=y CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y @@ -207,10 +98,11 @@ CONFIG_BASE_SMALL=0 # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODULE_UNLOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y +# CONFIG_KMOD is not set # # Block layer @@ -232,13 +124,68 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_QUICC_ENGINE=y +CONFIG_PPC_GEN550=y +# CONFIG_WANT_EARLY_SERIAL is not set # -# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# Platform support +# +# CONFIG_MPC8313_RDB is not set +# CONFIG_MPC832x_MDS is not set +CONFIG_MPC832x_RDB=y +# CONFIG_MPC834x_MDS is not set +# CONFIG_MPC834x_ITX is not set +# CONFIG_MPC836x_MDS is not set +CONFIG_PPC_MPC832x=y +# CONFIG_MPIC is not set + # -CONFIG_HW_HAS_PCI=y +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MATH_EMULATION=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y CONFIG_PCI=y -CONFIG_MMU=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set # # PCCARD (PCMCIA/CardBus) support @@ -251,19 +198,18 @@ CONFIG_MMU=y # CONFIG_HOTPLUG_PCI is not set # -# Executable file formats +# Advanced setup # -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y +# CONFIG_ADVANCED_OPTIONS is not set # -# Power management options +# Default settings for advanced configuration options are used # -CONFIG_PM=y -# CONFIG_PM_LEGACY is not set -# CONFIG_PM_DEBUG is not set -# CONFIG_PM_SYSFS_DEPRECATED is not set +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 # # Networking @@ -280,25 +226,26 @@ CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set # CONFIG_XFRM_SUB_POLICY is not set -CONFIG_XFRM_MIGRATE=y +# CONFIG_XFRM_MIGRATE is not set # CONFIG_NET_KEY is not set CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_FIB_HASH=y CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_BOOTP is not set +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set +CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=m +# CONFIG_INET_TUNNEL is not set CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y @@ -307,100 +254,12 @@ CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_TCP_MD5SIG=y - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -CONFIG_IPV6=m -# CONFIG_IPV6_PRIVACY is not set -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_ROUTE_INFO=y -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_MIP6 is not set +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -CONFIG_IPV6_SIT=m -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_NETWORK_SECMARK is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set - -# -# Core Netfilter Configuration -# -# CONFIG_NETFILTER_NETLINK is not set -CONFIG_NF_CONNTRACK_ENABLED=m -CONFIG_NF_CONNTRACK_SUPPORT=y -# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set -CONFIG_NF_CONNTRACK=m -CONFIG_NF_CT_ACCT=y -CONFIG_NF_CONNTRACK_MARK=y -CONFIG_NF_CONNTRACK_EVENTS=y -CONFIG_NF_CT_PROTO_GRE=m -CONFIG_NF_CT_PROTO_SCTP=m -CONFIG_NF_CONNTRACK_AMANDA=m -CONFIG_NF_CONNTRACK_FTP=m -CONFIG_NF_CONNTRACK_H323=m -CONFIG_NF_CONNTRACK_IRC=m -# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set -CONFIG_NF_CONNTRACK_PPTP=m -CONFIG_NF_CONNTRACK_SANE=m -CONFIG_NF_CONNTRACK_SIP=m -CONFIG_NF_CONNTRACK_TFTP=m -CONFIG_NETFILTER_XTABLES=m -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -CONFIG_NETFILTER_XT_TARGET_MARK=m -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NFLOG=m -CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -CONFIG_NETFILTER_XT_MATCH_COMMENT=m -CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -CONFIG_NETFILTER_XT_MATCH_DCCP=m -# CONFIG_NETFILTER_XT_MATCH_DSCP is not set -CONFIG_NETFILTER_XT_MATCH_ESP=m -CONFIG_NETFILTER_XT_MATCH_HELPER=m -CONFIG_NETFILTER_XT_MATCH_LENGTH=m -CONFIG_NETFILTER_XT_MATCH_LIMIT=m -CONFIG_NETFILTER_XT_MATCH_MAC=m -CONFIG_NETFILTER_XT_MATCH_MARK=m -# CONFIG_NETFILTER_XT_MATCH_POLICY is not set -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set -CONFIG_NETFILTER_XT_MATCH_REALM=m -CONFIG_NETFILTER_XT_MATCH_SCTP=m -CONFIG_NETFILTER_XT_MATCH_STATE=m -# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set -CONFIG_NETFILTER_XT_MATCH_STRING=m -CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m - -# -# IP: Netfilter Configuration -# -CONFIG_NF_CONNTRACK_IPV4=m -CONFIG_NF_CONNTRACK_PROC_COMPAT=y -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set - -# -# IPv6: Netfilter Configuration (EXPERIMENTAL) -# -CONFIG_NF_CONNTRACK_IPV6=m -# CONFIG_IP6_NF_QUEUE is not set -# CONFIG_IP6_NF_IPTABLES is not set +# CONFIG_NETFILTER is not set # # DCCP Configuration (EXPERIMENTAL) @@ -432,7 +291,6 @@ CONFIG_NF_CONNTRACK_IPV6=m # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set -CONFIG_NET_CLS_ROUTE=y # # Network testing @@ -452,7 +310,7 @@ CONFIG_NET_CLS_ROUTE=y # CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y +# CONFIG_FW_LOADER is not set # CONFIG_SYS_HYPERVISOR is not set # @@ -478,6 +336,7 @@ CONFIG_FW_LOADER=y # # Block devices # +# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -490,87 +349,29 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_SIZE=32768 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # # Misc devices # -CONFIG_SGI_IOC4=m +# CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set # # ATA/ATAPI/MFM/RLL support # -CONFIG_IDE=y -CONFIG_IDE_MAX_HWIFS=4 -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=y -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_GENERIC is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -CONFIG_BLK_DEV_CMD64X=y -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_JMICRON is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set -CONFIG_BLK_DEV_IT8213=m -# CONFIG_BLK_DEV_IT821X is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -CONFIG_BLK_DEV_TC86C001=m -# CONFIG_IDE_ARM is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_BLK_DEV_HD is not set +# CONFIG_IDE is not set # # SCSI device support # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y -CONFIG_SCSI_TGT=m -CONFIG_SCSI_NETLINK=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # @@ -589,31 +390,26 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set -CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_SCAN_ASYNC is not set # # SCSI Transports # -CONFIG_SCSI_SPI_ATTRS=m -CONFIG_SCSI_FC_ATTRS=y -CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set # # SCSI low-level drivers # -CONFIG_ISCSI_TCP=m +# CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC94XX is not set @@ -623,8 +419,11 @@ CONFIG_AIC7XXX_DEBUG_MASK=0 # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set @@ -669,13 +468,19 @@ CONFIG_AIC7XXX_DEBUG_MASK=0 # CONFIG_I2O is not set # +# Macintosh device drivers +# +# CONFIG_MAC_EMUMOUSEBTN is not set +# CONFIG_WINDFARM is not set + +# # Network device support # CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set -CONFIG_TUN=m +# CONFIG_TUN is not set # # ARCnet devices @@ -696,44 +501,22 @@ CONFIG_MII=y # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_DM9000 is not set # # Tulip family network device support # # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_AMD8111_ETH is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_B44 is not set -# CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set -# CONFIG_EEPRO100 is not set -# CONFIG_E100 is not set -# CONFIG_FEALNX is not set -CONFIG_NATSEMI=y -# CONFIG_NE2K_PCI is not set -# CONFIG_8139CP is not set -CONFIG_8139TOO=y -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_8139_OLD_RX_RESET is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_SC92031 is not set +# CONFIG_NET_PCI is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set # CONFIG_DL2K is not set -# CONFIG_E1000 is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -742,9 +525,14 @@ CONFIG_8139TOO=y # CONFIG_SKGE is not set # CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set -# CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set +# CONFIG_GIANFAR is not set +CONFIG_UCC_GETH=y +CONFIG_UGETH_NAPI=y +# CONFIG_UGETH_MAGIC_PACKET is not set +# CONFIG_UGETH_FILTERING is not set +# CONFIG_UGETH_TX_ON_DEMOND is not set # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set @@ -752,11 +540,11 @@ CONFIG_8139TOO=y # Ethernet (10000 Mbit) # # CONFIG_CHELSIO_T1 is not set -CONFIG_CHELSIO_T3=m +# CONFIG_CHELSIO_T3 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set -CONFIG_NETXEN_NIC=m +# CONFIG_NETXEN_NIC is not set # # Token Ring devices @@ -774,17 +562,8 @@ CONFIG_NETXEN_NIC=m # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -CONFIG_PPP=m -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPP_MPPE=m -# CONFIG_PPPOE is not set +# CONFIG_PPP is not set # CONFIG_SLIP is not set -CONFIG_SLHC=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set @@ -810,29 +589,17 @@ CONFIG_INPUT=y # # Userland interfaces # -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set # # Input Device Drivers # -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -840,52 +607,33 @@ CONFIG_MOUSE_PS2=y # # Hardware I/O ports # -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_PCIPS2 is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO is not set # CONFIG_GAMEPORT is not set # # Character devices # -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -CONFIG_MOXA_SMARTIO_NEW=m -# CONFIG_ISI is not set -# CONFIG_SYNCLINKMP is not set -# CONFIG_SYNCLINK_GT is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers # -# CONFIG_SERIAL_8250 is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set # # Non-8250 serial port support # -CONFIG_SERIAL_PNX8XXX=y -CONFIG_SERIAL_PNX8XXX_CONSOLE=y +# CONFIG_SERIAL_UARTLITE is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_OF_PLATFORM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -898,13 +646,33 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Watchdog Cards # -# CONFIG_WATCHDOG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_83xx_WDT=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set CONFIG_HW_RANDOM=y -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set +# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -916,13 +684,13 @@ CONFIG_HW_RANDOM=y # # I2C support # -CONFIG_I2C=m -CONFIG_I2C_CHARDEV=m +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y # # I2C Algorithms # -CONFIG_I2C_ALGOBIT=m +# CONFIG_I2C_ALGOBIT is not set # CONFIG_I2C_ALGOPCF is not set # CONFIG_I2C_ALGOPCA is not set @@ -937,6 +705,7 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set @@ -961,6 +730,7 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set # CONFIG_SENSORS_MAX6875 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set @@ -1029,6 +799,11 @@ CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set # +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -1042,52 +817,9 @@ CONFIG_HWMON=y # # Graphics support # -CONFIG_FIRMWARE_EDID=y -CONFIG_FB=y -# CONFIG_FB_DDC is not set -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -# CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_TILEBLITTING is not set -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_NVIDIA is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_S3 is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_SMIVGX is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_FB is not set +# CONFIG_FB_IBM_GXT4500 is not set # # Sound @@ -1114,15 +846,25 @@ CONFIG_USB=y # CONFIG_USB_DEVICEFS=y # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_SUSPEND is not set # CONFIG_USB_OTG is not set # # USB Host Controller Drivers # -# CONFIG_USB_EHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set # CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_OHCI_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PPC_OF=y +CONFIG_USB_OHCI_HCD_PPC_OF_BE=y +# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set +CONFIG_USB_OHCI_HCD_PCI=y +CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y +CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y +CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_UHCI_HCD is not set # CONFIG_USB_SL811_HCD is not set @@ -1143,7 +885,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set # CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STORAGE_SDDR09 is not set @@ -1156,10 +897,13 @@ CONFIG_USB_STORAGE=y # # USB Input Devices # -CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -CONFIG_USB_HIDDEV=y +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set # CONFIG_USB_ACECAD is not set @@ -1218,8 +962,10 @@ CONFIG_USB_MON=y # CONFIG_USB_IDMOUSE is not set # CONFIG_USB_FTDI_ELAN is not set # CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # @@ -1301,11 +1047,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set -CONFIG_XFS_FS=m -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_SECURITY is not set -# CONFIG_XFS_POSIX_ACL is not set -# CONFIG_XFS_RT is not set +# CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set @@ -1314,8 +1056,8 @@ CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set # @@ -1338,14 +1080,14 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # Pseudo filesystems # CONFIG_PROC_FS=y -# CONFIG_PROC_KCORE is not set +CONFIG_PROC_KCORE=y CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -CONFIG_CONFIGFS_FS=m +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -1357,7 +1099,7 @@ CONFIG_CONFIGFS_FS=m # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -CONFIG_CRAMFS=y +# CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set @@ -1370,21 +1112,18 @@ CONFIG_CRAMFS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set -# CONFIG_NFS_V4 is not set +CONFIG_NFS_V4=y # CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=m -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set +# CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1394,15 +1133,31 @@ CONFIG_SMB_FS=m # # Partition Types # -# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set # # Native Language Support # CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set +CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set # CONFIG_NLS_CODEPAGE_850 is not set @@ -1419,14 +1174,14 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_869 is not set # CONFIG_NLS_CODEPAGE_936 is not set # CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set +CONFIG_NLS_CODEPAGE_932=y # CONFIG_NLS_CODEPAGE_949 is not set # CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set +CONFIG_NLS_ISO8859_8=y # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set # CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set +CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set # CONFIG_NLS_ISO8859_4 is not set @@ -1444,20 +1199,35 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Distributed Lock Manager # -CONFIG_DLM=m -CONFIG_DLM_TCP=y -# CONFIG_DLM_SCTP is not set -# CONFIG_DLM_DEBUG is not set +# CONFIG_DLM is not set # -# Profiling support +# QE Options +# +CONFIG_UCC_SLOW=y +CONFIG_UCC_FAST=y +CONFIG_UCC=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y + +# +# Instrumentation Support # # CONFIG_PROFILING is not set # # Kernel hacking # -CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set CONFIG_ENABLE_MUST_CHECK=y # CONFIG_MAGIC_SYSRQ is not set @@ -1466,9 +1236,10 @@ CONFIG_ENABLE_MUST_CHECK=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_LOG_BUF_SHIFT=14 -CONFIG_CROSSCOMPILE=y -CONFIG_CMDLINE="" -CONFIG_SYS_SUPPORTS_KGDB=y +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_SERIAL_TEXT_DEBUG is not set +# CONFIG_PPC_EARLY_DEBUG is not set # # Security options @@ -1481,26 +1252,25 @@ CONFIG_SYS_SUPPORTS_KGDB=y # CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=m -CONFIG_CRYPTO_HASH=m -CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_MANAGER=y # CONFIG_CRYPTO_HMAC is not set -CONFIG_CRYPTO_XCBC=m +# CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=m +# CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set -CONFIG_CRYPTO_GF128MUL=m +# CONFIG_CRYPTO_GF128MUL is not set CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_LRW=m -# CONFIG_CRYPTO_DES is not set -CONFIG_CRYPTO_FCRYPT=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set @@ -1508,33 +1278,15 @@ CONFIG_CRYPTO_FCRYPT=m # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set -CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_ANUBIS is not set # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set -CONFIG_CRYPTO_CRC32C=m -CONFIG_CRYPTO_CAMELLIA=m +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_TEST is not set # # Hardware crypto devices # - -# -# Library routines -# -CONFIG_BITREVERSE=y -CONFIG_CRC_CCITT=m -# CONFIG_CRC16 is not set -CONFIG_CRC32=y -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m -CONFIG_TEXTSEARCH=y -CONFIG_TEXTSEARCH_KMP=m -CONFIG_TEXTSEARCH_BM=m -CONFIG_TEXTSEARCH_FSM=m -CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y diff --git a/arch/powerpc/configs/mpc8544_ds_defconfig b/arch/powerpc/configs/mpc8544_ds_defconfig new file mode 100644 index 00000000000..b563513cc96 --- /dev/null +++ b/arch/powerpc/configs/mpc8544_ds_defconfig @@ -0,0 +1,1077 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.21-rc3 +# Mon Mar 19 17:18:49 2007 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_ARCH_HAS_ILOG2_U32=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_AUDIT_ARCH=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +CONFIG_PPC_85xx=y +# CONFIG_PPC_86xx is not set +# CONFIG_PPC_8xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_E200 is not set +CONFIG_85xx=y +CONFIG_E500=y +# CONFIG_PPC_DCR_NATIVE is not set +# CONFIG_PPC_DCR_MMIO is not set +CONFIG_BOOKE=y +CONFIG_FSL_BOOKE=y +# CONFIG_PHYS_64BIT is not set +# CONFIG_SPE is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_IPC_NS=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_HOTPLUG is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_BLOCK=y +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +# CONFIG_MPC8540_ADS is not set +# CONFIG_MPC8560_ADS is not set +# CONFIG_MPC85xx_CDS is not set +# CONFIG_MPC85xx_MDS is not set +CONFIG_MPC8544_DS=y +CONFIG_MPC85xx=y +CONFIG_PPC_INDIRECT_PCI_BE=y +CONFIG_MPIC=y + +# +# Kernel options +# +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_MATH_EMULATION=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_PROC_DEVICETREE=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="root=/dev/sda3 rw console=ttyS0,115200" +# CONFIG_PM is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ZONE_DMA=y +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set + +# +# PCCARD (PCMCIA/CardBus) support +# + +# +# PCI Hotplug Support +# + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=y +CONFIG_NET_IPGRE=y +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_ARPD=y +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set +CONFIG_FIB_RULES=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNPACPI is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=2 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# Misc devices +# + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_PATA_PLATFORM is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Macintosh device drivers +# +# CONFIG_MAC_EMUMOUSEBTN is not set +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +CONFIG_VITESSE_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_FIXED_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y + +# +# Ethernet (1000 Mbit) +# +CONFIG_GIANFAR=y +CONFIG_GFAR_NAPI=y + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_OF_PLATFORM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +CONFIG_NVRAM=y +CONFIG_GEN_RTC=y +CONFIG_GEN_RTC_X=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m +# CONFIG_DVB_CORE_ATTACH is not set + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# +# CONFIG_DVB_FE_CUSTOMISE is not set + +# +# DVB-S (satellite) frontends +# + +# +# DVB-T (terrestrial) frontends +# + +# +# DVB-C (cable) frontends +# + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# + +# +# Tuners/PLL support +# + +# +# Miscellaneous devices +# + +# +# Graphics support +# +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_FB is not set +# CONFIG_FB_IBM_GXT4500 is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# HID Devices +# +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# Auxiliary Display support +# + +# +# Virtualization +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_CRAMFS=y +CONFIG_VXFS_FS=m +CONFIG_HPFS_FS=m +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_ECB is not set +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index a8da0aea3b8..126b9f87df2 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -152,7 +152,7 @@ CONFIG_RTAS_ERROR_LOGGING=y CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=m CONFIG_MMIO_NVRAM=y -CONFIG_MPIC_BROKEN_U3=y +CONFIG_MPIC_U3_HT_IRQS=y CONFIG_IBMVIO=y # CONFIG_IBMEBUS is not set # CONFIG_PPC_MPC106 is not set diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 8120d428ebf..e0fa80eca36 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -25,8 +25,8 @@ obj-$(CONFIG_PPC_970_NAP) += idle_power4.o obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o procfs-$(CONFIG_PPC64) := proc_ppc64.o obj-$(CONFIG_PROC_FS) += $(procfs-y) -rtaspci-$(CONFIG_PPC64) := rtas_pci.o -obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y) +rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o +obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_LPARCFG) += lparcfg.o diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 4734b5de599..5c9ff7f5c44 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c @@ -241,7 +241,7 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr) if (user_mode(regs) && !access_ok(VERIFY_WRITE, p, size)) return -EFAULT; for (i = 0; i < size / sizeof(long); ++i) - if (__put_user(0, p+i)) + if (__put_user_inatomic(0, p+i)) return -EFAULT; return 1; } @@ -288,7 +288,8 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, } else { unsigned long pc = regs->nip ^ (swiz & 4); - if (__get_user(instr, (unsigned int __user *)pc)) + if (__get_user_inatomic(instr, + (unsigned int __user *)pc)) return -EFAULT; if (swiz == 0 && (flags & SW)) instr = cpu_to_le32(instr); @@ -324,27 +325,31 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, ((nb0 + 3) / 4) * sizeof(unsigned long)); for (i = 0; i < nb; ++i, ++p) - if (__get_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p))) + if (__get_user_inatomic(REG_BYTE(rptr, i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; if (nb0 > 0) { rptr = ®s->gpr[0]; addr += nb; for (i = 0; i < nb0; ++i, ++p) - if (__get_user(REG_BYTE(rptr, i ^ bswiz), - SWIZ_PTR(p))) + if (__get_user_inatomic(REG_BYTE(rptr, + i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; } } else { for (i = 0; i < nb; ++i, ++p) - if (__put_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p))) + if (__put_user_inatomic(REG_BYTE(rptr, i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; if (nb0 > 0) { rptr = ®s->gpr[0]; addr += nb; for (i = 0; i < nb0; ++i, ++p) - if (__put_user(REG_BYTE(rptr, i ^ bswiz), - SWIZ_PTR(p))) + if (__put_user_inatomic(REG_BYTE(rptr, + i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; } } @@ -398,7 +403,8 @@ int fix_alignment(struct pt_regs *regs) if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE)) pc ^= 4; - if (unlikely(__get_user(instr, (unsigned int __user *)pc))) + if (unlikely(__get_user_inatomic(instr, + (unsigned int __user *)pc))) return -EFAULT; if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE)) instr = cpu_to_le32(instr); @@ -474,16 +480,16 @@ int fix_alignment(struct pt_regs *regs) p = (unsigned long) addr; switch (nb) { case 8: - ret |= __get_user(data.v[0], SWIZ_PTR(p++)); - ret |= __get_user(data.v[1], SWIZ_PTR(p++)); - ret |= __get_user(data.v[2], SWIZ_PTR(p++)); - ret |= __get_user(data.v[3], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[0], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[1], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[2], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[3], SWIZ_PTR(p++)); case 4: - ret |= __get_user(data.v[4], SWIZ_PTR(p++)); - ret |= __get_user(data.v[5], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[4], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[5], SWIZ_PTR(p++)); case 2: - ret |= __get_user(data.v[6], SWIZ_PTR(p++)); - ret |= __get_user(data.v[7], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[6], SWIZ_PTR(p++)); + ret |= __get_user_inatomic(data.v[7], SWIZ_PTR(p++)); if (unlikely(ret)) return -EFAULT; } @@ -551,16 +557,16 @@ int fix_alignment(struct pt_regs *regs) p = (unsigned long) addr; switch (nb) { case 8: - ret |= __put_user(data.v[0], SWIZ_PTR(p++)); - ret |= __put_user(data.v[1], SWIZ_PTR(p++)); - ret |= __put_user(data.v[2], SWIZ_PTR(p++)); - ret |= __put_user(data.v[3], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[0], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[1], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[2], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[3], SWIZ_PTR(p++)); case 4: - ret |= __put_user(data.v[4], SWIZ_PTR(p++)); - ret |= __put_user(data.v[5], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[4], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[5], SWIZ_PTR(p++)); case 2: - ret |= __put_user(data.v[6], SWIZ_PTR(p++)); - ret |= __put_user(data.v[7], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[6], SWIZ_PTR(p++)); + ret |= __put_user_inatomic(data.v[7], SWIZ_PTR(p++)); } if (unlikely(ret)) return -EFAULT; diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 030d300cd71..0c5150c6917 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -77,7 +77,6 @@ int main(void) DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid)); #else /* CONFIG_PPC64 */ DEFINE(PGDIR, offsetof(struct thread_struct, pgdir)); - DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0)); DEFINE(PT_PTRACED, PT_PTRACED); @@ -140,6 +139,7 @@ int main(void) DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr)); DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset)); + DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); DEFINE(SLBSHADOW_STACKVSID, offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid)); diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 3678997339d..e7b684689e0 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -161,33 +161,33 @@ int btext_initialize(struct device_node *np) unsigned long address = 0; const u32 *prop; - prop = get_property(np, "linux,bootx-width", NULL); + prop = of_get_property(np, "linux,bootx-width", NULL); if (prop == NULL) - prop = get_property(np, "width", NULL); + prop = of_get_property(np, "width", NULL); if (prop == NULL) return -EINVAL; width = *prop; - prop = get_property(np, "linux,bootx-height", NULL); + prop = of_get_property(np, "linux,bootx-height", NULL); if (prop == NULL) - prop = get_property(np, "height", NULL); + prop = of_get_property(np, "height", NULL); if (prop == NULL) return -EINVAL; height = *prop; - prop = get_property(np, "linux,bootx-depth", NULL); + prop = of_get_property(np, "linux,bootx-depth", NULL); if (prop == NULL) - prop = get_property(np, "depth", NULL); + prop = of_get_property(np, "depth", NULL); if (prop == NULL) return -EINVAL; depth = *prop; pitch = width * ((depth + 7) / 8); - prop = get_property(np, "linux,bootx-linebytes", NULL); + prop = of_get_property(np, "linux,bootx-linebytes", NULL); if (prop == NULL) - prop = get_property(np, "linebytes", NULL); + prop = of_get_property(np, "linebytes", NULL); if (prop && *prop != 0xffffffffu) pitch = *prop; if (pitch == 1) pitch = 0x1000; - prop = get_property(np, "address", NULL); + prop = of_get_property(np, "address", NULL); if (prop) address = *prop; @@ -219,7 +219,7 @@ int __init btext_find_display(int allow_nonstdout) struct device_node *np = NULL; int rc = -ENODEV; - name = get_property(of_chosen, "linux,stdout-path", NULL); + name = of_get_property(of_chosen, "linux,stdout-path", NULL); if (name != NULL) { np = of_find_node_by_path(name); if (np != NULL) { @@ -236,7 +236,7 @@ int __init btext_find_display(int allow_nonstdout) return rc; for (np = NULL; (np = of_find_node_by_type(np, "display"));) { - if (get_property(np, "linux,opened", NULL)) { + if (of_get_property(np, "linux,opened", NULL)) { printk("trying %s ...\n", np->full_name); rc = btext_initialize(np); printk("result: %d\n", rc); diff --git a/arch/powerpc/kernel/cpu_setup_pa6t.S b/arch/powerpc/kernel/cpu_setup_pa6t.S index 4047be25c4d..d62cb9cae4e 100644 --- a/arch/powerpc/kernel/cpu_setup_pa6t.S +++ b/arch/powerpc/kernel/cpu_setup_pa6t.S @@ -34,7 +34,7 @@ _GLOBAL(__setup_cpu_pa6t) beqlr mfspr r0,SPRN_HID5 - ori r0,r0,0x30 + ori r0,r0,0x38 mtspr SPRN_HID5,r0 mfspr r0,SPRN_LPCR diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index e4006dc087c..9cb24d20f0f 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -389,6 +389,8 @@ static struct cpu_spec cpu_specs[] = { .pmc_type = PPC_PMC_PA6T, .cpu_setup = __setup_cpu_pa6t, .cpu_restore = __restore_cpu_pa6t, + .oprofile_cpu_type = "ppc64/pa6t", + .oprofile_type = PPC_OPROFILE_PA6T, .platform = "pa6t", }, { /* default match */ @@ -558,6 +560,18 @@ static struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_750cx, .platform = "ppc750", }, + { /* 750CL */ + .pvr_mask = 0xfffff0f0, + .pvr_value = 0x00087010, + .cpu_name = "750CL", + .cpu_features = CPU_FTRS_750CL, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", + }, { /* 745/755 */ .pvr_mask = 0xfffff000, .pvr_value = 0x00083000, diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index c03e829fee3..c29d1652a42 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -191,7 +191,6 @@ stack_ovf: 0: _GLOBAL(DoSyscall) - stw r0,THREAD+LAST_SYSCALL(r2) stw r3,ORIG_GPR3(r1) li r12,0 stw r12,RESULT(r1) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 97cedcd6c9b..1111fcec767 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -278,8 +278,12 @@ exception_marker: beq- 1f; \ ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ 1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ - bge- cr1,bad_stack; /* abort if it is */ \ - std r9,_CCR(r1); /* save CR in stackframe */ \ + bge- cr1,2f; /* abort if it is */ \ + b 3f; \ +2: li r1,(n); /* will be reloaded later */ \ + sth r1,PACA_TRAP_SAVE(r13); \ + b bad_stack; \ +3: std r9,_CCR(r1); /* save CR in stackframe */ \ std r11,_NIP(r1); /* save SRR0 in stackframe */ \ std r12,_MSR(r1); /* save SRR1 in stackframe */ \ std r10,0(r1); /* make stack chain pointer */ \ @@ -940,6 +944,8 @@ bad_stack: SAVE_2GPRS(7,r1) SAVE_10GPRS(12,r1) SAVE_10GPRS(22,r1) + lhz r12,PACA_TRAP_SAVE(r13) + std r12,_TRAP(r1) addi r11,r1,INT_FRAME_SIZE std r11,0(r1) li r12,0 @@ -1555,7 +1561,6 @@ _GLOBAL(generic_secondary_smp_init) /* turn on 64-bit mode */ bl .enable_64b_mode - isync /* Set up a paca value for this processor. Since we have the * physical cpu id in r24, we need to search the pacas to find @@ -1735,10 +1740,6 @@ _STATIC(__boot_from_prom) /* We never return */ trap -/* - * At this point, r3 contains the physical address we are running at, - * returned by prom_init() - */ _STATIC(__after_prom_start) /* @@ -1851,7 +1852,6 @@ __secondary_start_pmac_0: _GLOBAL(pmac_secondary_start) /* turn on 64-bit mode */ bl .enable_64b_mode - isync /* Copy some CPU settings from CPU 0 */ bl .__restore_cpu_ppc970 diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 82bd2f10770..9a8c9af43b2 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -2,36 +2,37 @@ * IBM PowerPC IBM eBus Infrastructure Support. * * Copyright (c) 2005 IBM Corporation + * Joachim Fenkes <fenkes@de.ibm.com> * Heiko J Schick <schickhj@de.ibm.com> - * + * * All rights reserved. * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. + * This source code is distributed under a dual license of GPL v2.0 and OpenIB + * BSD. * * OpenIB BSD License * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation * and/or other materials - * provided with the distribution. + * provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ @@ -43,19 +44,19 @@ #include <asm/ibmebus.h> #include <asm/abs_addr.h> -static struct ibmebus_dev ibmebus_bus_device = { /* fake "parent" device */ - .name = ibmebus_bus_device.ofdev.dev.bus_id, - .ofdev.dev.bus_id = "ibmebus", - .ofdev.dev.bus = &ibmebus_bus_type, +static struct device ibmebus_bus_device = { /* fake "parent" device */ + .bus_id = "ibmebus", }; +struct bus_type ibmebus_bus_type; + static void *ibmebus_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { void *mem; - + mem = kmalloc(size, flag); *dma_handle = (dma_addr_t)mem; @@ -63,7 +64,7 @@ static void *ibmebus_alloc_coherent(struct device *dev, } static void ibmebus_free_coherent(struct device *dev, - size_t size, void *vaddr, + size_t size, void *vaddr, dma_addr_t dma_handle) { kfree(vaddr); @@ -79,7 +80,7 @@ static dma_addr_t ibmebus_map_single(struct device *dev, static void ibmebus_unmap_single(struct device *dev, dma_addr_t dma_addr, - size_t size, + size_t size, enum dma_data_direction direction) { return; @@ -90,13 +91,13 @@ static int ibmebus_map_sg(struct device *dev, int nents, enum dma_data_direction direction) { int i; - + for (i = 0; i < nents; i++) { - sg[i].dma_address = (dma_addr_t)page_address(sg[i].page) + sg[i].dma_address = (dma_addr_t)page_address(sg[i].page) + sg[i].offset; sg[i].dma_length = sg[i].length; } - + return nents; } @@ -128,15 +129,15 @@ static int ibmebus_bus_probe(struct device *dev) struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver); const struct of_device_id *id; int error = -ENODEV; - + if (!ibmebusdrv->probe) return error; - + id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev); if (id) { error = ibmebusdrv->probe(ibmebusdev, id); } - + return error; } @@ -144,11 +145,11 @@ static int ibmebus_bus_remove(struct device *dev) { struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev); struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver); - + if (ibmebusdrv->remove) { return ibmebusdrv->remove(ibmebusdev); } - + return 0; } @@ -158,21 +159,12 @@ static void __devinit ibmebus_dev_release(struct device *dev) kfree(to_ibmebus_dev(dev)); } -static ssize_t ibmebusdev_show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%s\n", to_ibmebus_dev(dev)->name); -} -static DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, ibmebusdev_show_name, - NULL); - -static struct ibmebus_dev* __devinit ibmebus_register_device_common( +static int __devinit ibmebus_register_device_common( struct ibmebus_dev *dev, const char *name) { int err = 0; - dev->name = name; - dev->ofdev.dev.parent = &ibmebus_bus_device.ofdev.dev; + dev->ofdev.dev.parent = &ibmebus_bus_device; dev->ofdev.dev.bus = &ibmebus_bus_type; dev->ofdev.dev.release = ibmebus_dev_release; @@ -181,17 +173,15 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common( dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node); /* An ibmebusdev is based on a of_device. We have to change the - * bus type to use our own DMA mapping operations. - */ + * bus type to use our own DMA mapping operations. + */ if ((err = of_device_register(&dev->ofdev)) != 0) { printk(KERN_ERR "%s: failed to register device (%d).\n", __FUNCTION__, err); - return NULL; + return -ENODEV; } - - device_create_file(&dev->ofdev.dev, &dev_attr_name); - - return dev; + + return 0; } static struct ibmebus_dev* __devinit ibmebus_register_device_node( @@ -201,35 +191,35 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node( const char *loc_code; int length; - loc_code = get_property(dn, "ibm,loc-code", NULL); + loc_code = of_get_property(dn, "ibm,loc-code", NULL); if (!loc_code) { printk(KERN_WARNING "%s: node %s missing 'ibm,loc-code'\n", __FUNCTION__, dn->name ? dn->name : "<unknown>"); - return NULL; + return ERR_PTR(-EINVAL); } - + if (strlen(loc_code) == 0) { printk(KERN_WARNING "%s: 'ibm,loc-code' is invalid\n", __FUNCTION__); - return NULL; + return ERR_PTR(-EINVAL); } dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL); if (!dev) { - return NULL; + return ERR_PTR(-ENOMEM); } dev->ofdev.node = of_node_get(dn); - + length = strlen(loc_code); - memcpy(dev->ofdev.dev.bus_id, loc_code - + (length - min(length, BUS_ID_SIZE - 1)), + memcpy(dev->ofdev.dev.bus_id, loc_code + + (length - min(length, BUS_ID_SIZE - 1)), min(length, BUS_ID_SIZE - 1)); /* Register with generic device framework. */ - if (ibmebus_register_device_common(dev, dn->name) == NULL) { + if (ibmebus_register_device_common(dev, dn->name) != 0) { kfree(dev); - return NULL; + return ERR_PTR(-ENODEV); } return dev; @@ -238,17 +228,16 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node( static void ibmebus_probe_of_nodes(char* name) { struct device_node *dn = NULL; - + while ((dn = of_find_node_by_name(dn, name))) { - if (ibmebus_register_device_node(dn) == NULL) { + if (IS_ERR(ibmebus_register_device_node(dn))) { of_node_put(dn); - return; } } - + of_node_put(dn); - + return; } @@ -262,17 +251,21 @@ static void ibmebus_add_devices_by_id(struct of_device_id *idt) return; } -static int ibmebus_match_helper(struct device *dev, void *data) +static int ibmebus_match_name(struct device *dev, void *data) { - if (strcmp((char*)data, to_ibmebus_dev(dev)->name) == 0) + const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); + const char *name; + + name = of_get_property(ebus_dev->ofdev.node, "name", NULL); + + if (name && (strcmp(data, name) == 0)) return 1; - + return 0; } static int ibmebus_unregister_device(struct device *dev) { - device_remove_file(dev, &dev_attr_name); of_device_unregister(to_of_device(dev)); return 0; @@ -281,17 +274,16 @@ static int ibmebus_unregister_device(struct device *dev) static void ibmebus_remove_devices_by_id(struct of_device_id *idt) { struct device *dev; - + while (strlen(idt->name) > 0) { - while ((dev = bus_find_device(&ibmebus_bus_type, NULL, + while ((dev = bus_find_device(&ibmebus_bus_type, NULL, (void*)idt->name, - ibmebus_match_helper))) { + ibmebus_match_name))) { ibmebus_unregister_device(dev); } idt++; - } - + return; } @@ -307,30 +299,33 @@ int ibmebus_register_driver(struct ibmebus_driver *drv) if ((err = driver_register(&drv->driver) != 0)) return err; + /* remove all supported devices first, in case someone + * probed them manually before registering the driver */ + ibmebus_remove_devices_by_id(drv->id_table); ibmebus_add_devices_by_id(drv->id_table); - + return 0; } EXPORT_SYMBOL(ibmebus_register_driver); void ibmebus_unregister_driver(struct ibmebus_driver *drv) -{ +{ driver_unregister(&drv->driver); ibmebus_remove_devices_by_id(drv->id_table); } EXPORT_SYMBOL(ibmebus_unregister_driver); int ibmebus_request_irq(struct ibmebus_dev *dev, - u32 ist, + u32 ist, irq_handler_t handler, unsigned long irq_flags, const char * devname, void *dev_id) { unsigned int irq = irq_create_mapping(NULL, ist); - + if (irq == NO_IRQ) return -EINVAL; - + return request_irq(irq, handler, irq_flags, devname, dev_id); } @@ -339,56 +334,163 @@ EXPORT_SYMBOL(ibmebus_request_irq); void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id) { unsigned int irq = irq_find_mapping(NULL, ist); - + free_irq(irq, dev_id); } EXPORT_SYMBOL(ibmebus_free_irq); static int ibmebus_bus_match(struct device *dev, struct device_driver *drv) -{ +{ const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv); const struct of_device_id *ids = ebus_drv->id_table; const struct of_device_id *found_id; - + if (!ids) return 0; - + found_id = of_match_device(ids, &ebus_dev->ofdev); if (found_id) return 1; - + return 0; } +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); + const char *name = of_get_property(ebus_dev->ofdev.node, "name", NULL); + return sprintf(buf, "%s\n", name); +} + +static struct device_attribute ibmebus_dev_attrs[] = { + __ATTR_RO(name), + __ATTR_NULL +}; + +static int ibmebus_match_path(struct device *dev, void *data) +{ + int rc; + struct device_node *dn = + of_node_get(to_ibmebus_dev(dev)->ofdev.node); + + rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0)); + + of_node_put(dn); + return rc; +} + +static char *ibmebus_chomp(const char *in, size_t count) +{ + char *out = (char*)kmalloc(count + 1, GFP_KERNEL); + if (!out) + return NULL; + + memcpy(out, in, count); + out[count] = '\0'; + if (out[count - 1] == '\n') + out[count - 1] = '\0'; + + return out; +} + +static ssize_t ibmebus_store_probe(struct bus_type *bus, + const char *buf, size_t count) +{ + struct device_node *dn = NULL; + struct ibmebus_dev *dev; + char *path; + ssize_t rc; + + path = ibmebus_chomp(buf, count); + if (!path) + return -ENOMEM; + + if (bus_find_device(&ibmebus_bus_type, NULL, path, + ibmebus_match_path)) { + printk(KERN_WARNING "%s: %s has already been probed\n", + __FUNCTION__, path); + rc = -EINVAL; + goto out; + } + + if ((dn = of_find_node_by_path(path))) { + dev = ibmebus_register_device_node(dn); + of_node_put(dn); + rc = IS_ERR(dev) ? PTR_ERR(dev) : count; + } else { + printk(KERN_WARNING "%s: no such device node: %s\n", + __FUNCTION__, path); + rc = -ENODEV; + } + +out: + kfree(path); + return rc; +} + +static ssize_t ibmebus_store_remove(struct bus_type *bus, + const char *buf, size_t count) +{ + struct device *dev; + char *path; + + path = ibmebus_chomp(buf, count); + if (!path) + return -ENOMEM; + + if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path, + ibmebus_match_path))) { + ibmebus_unregister_device(dev); + + kfree(path); + return count; + } else { + printk(KERN_WARNING "%s: %s not on the bus\n", + __FUNCTION__, path); + + kfree(path); + return -ENODEV; + } +} + +static struct bus_attribute ibmebus_bus_attrs[] = { + __ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe), + __ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove), + __ATTR_NULL +}; + struct bus_type ibmebus_bus_type = { - .name = "ibmebus", - .match = ibmebus_bus_match, + .name = "ibmebus", + .match = ibmebus_bus_match, + .dev_attrs = ibmebus_dev_attrs, + .bus_attrs = ibmebus_bus_attrs }; EXPORT_SYMBOL(ibmebus_bus_type); static int __init ibmebus_bus_init(void) { int err; - + printk(KERN_INFO "IBM eBus Device Driver\n"); - + err = bus_register(&ibmebus_bus_type); if (err) { printk(KERN_ERR ":%s: failed to register IBM eBus.\n", __FUNCTION__); return err; } - - err = device_register(&ibmebus_bus_device.ofdev.dev); + + err = device_register(&ibmebus_bus_device); if (err) { - printk(KERN_WARNING "%s: device_register returned %i\n", + printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__, err); bus_unregister(&ibmebus_bus_type); return err; } - + return 0; } __initcall(ibmebus_bus_init); diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 95edad4faf2..c08ceca6277 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -47,6 +47,8 @@ static int novmerge = 0; static int novmerge = 1; #endif +static int protect4gb = 1; + static inline unsigned long iommu_num_pages(unsigned long vaddr, unsigned long slen) { @@ -58,6 +60,16 @@ static inline unsigned long iommu_num_pages(unsigned long vaddr, return npages; } +static int __init setup_protect4gb(char *str) +{ + if (strcmp(str, "on") == 0) + protect4gb = 1; + else if (strcmp(str, "off") == 0) + protect4gb = 0; + + return 1; +} + static int __init setup_iommu(char *str) { if (!strcmp(str, "novmerge")) @@ -67,6 +79,7 @@ static int __init setup_iommu(char *str) return 1; } +__setup("protect4gb=", setup_protect4gb); __setup("iommu=", setup_iommu); static unsigned long iommu_range_alloc(struct iommu_table *tbl, @@ -429,6 +442,9 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) { unsigned long sz; + unsigned long start_index, end_index; + unsigned long entries_per_4g; + unsigned long index; static int welcomed = 0; struct page *page; @@ -450,7 +466,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) #ifdef CONFIG_CRASH_DUMP if (ppc_md.tce_get) { - unsigned long index, tceval; + unsigned long tceval; unsigned long tcecount = 0; /* @@ -480,6 +496,23 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size); #endif + /* + * DMA cannot cross 4 GB boundary. Mark last entry of each 4 + * GB chunk as reserved. + */ + if (protect4gb) { + entries_per_4g = 0x100000000l >> IOMMU_PAGE_SHIFT; + + /* Mark the last bit before a 4GB boundary as used */ + start_index = tbl->it_offset | (entries_per_4g - 1); + start_index -= tbl->it_offset; + + end_index = tbl->it_size; + + for (index = start_index; index < end_index - 1; index += entries_per_4g) + __set_bit(index, tbl->it_map); + } + if (!welcomed) { printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", novmerge ? "disabled" : "enabled"); diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 10093082685..6c83fe229e6 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -394,7 +394,7 @@ EXPORT_SYMBOL(do_softirq); #ifdef CONFIG_PPC_MERGE static LIST_HEAD(irq_hosts); -static spinlock_t irq_big_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(irq_big_lock); static DEFINE_PER_CPU(unsigned int, irq_radix_reader); static unsigned int irq_radix_writer; struct irq_map_entry irq_map[NR_IRQS]; diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index dd2886f97e9..ef647e7a9dc 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -59,12 +59,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) } if (!ret) { - memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); + memcpy(p->ainsn.insn, p->addr, + MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); p->opcode = *p->addr; flush_icache_range((unsigned long)p->ainsn.insn, (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t)); } + p->ainsn.boostable = 0; return ret; } @@ -232,6 +234,38 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) return 1; ss_probe: + if (p->ainsn.boostable >= 0) { + unsigned int insn = *p->ainsn.insn; + + /* regs->nip is also adjusted if emulate_step returns 1 */ + ret = emulate_step(regs, insn); + if (ret > 0) { + /* + * Once this instruction has been boosted + * successfully, set the boostable flag + */ + if (unlikely(p->ainsn.boostable == 0)) + p->ainsn.boostable = 1; + + if (p->post_handler) + p->post_handler(p, regs, 0); + + kcb->kprobe_status = KPROBE_HIT_SSDONE; + reset_current_kprobe(); + preempt_enable_no_resched(); + return 1; + } else if (ret < 0) { + /* + * We don't allow kprobes on mtmsr(d)/rfi(d), etc. + * So, we should never get here... but, its still + * good to catch them, just in case... + */ + printk("Can't step on instruction %x\n", insn); + BUG(); + } else if (ret == 0) + /* This instruction can't be boosted */ + p->ainsn.boostable = -1; + } prepare_singlestep(p, regs); kcb->kprobe_status = KPROBE_HIT_SS; return 1; diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 325f490a10c..63dd2c3ad95 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -44,12 +44,12 @@ static int __init add_legacy_port(struct device_node *np, int want_index, int index; /* get clock freq. if present */ - clk = get_property(np, "clock-frequency", NULL); + clk = of_get_property(np, "clock-frequency", NULL); if (clk && *clk) clock = *clk; /* get default speed if present */ - spd = get_property(np, "current-speed", NULL); + spd = of_get_property(np, "current-speed", NULL); /* If we have a location index, then try to use it */ if (want_index >= 0 && want_index < MAX_LEGACY_SERIAL_PORTS) @@ -121,11 +121,11 @@ static int __init add_legacy_soc_port(struct device_node *np, /* We only support ports that have a clock frequency properly * encoded in the device-tree. */ - if (get_property(np, "clock-frequency", NULL) == NULL) + if (of_get_property(np, "clock-frequency", NULL) == NULL) return -1; /* if rtas uses this device, don't try to use it as well */ - if (get_property(np, "used-by-rtas", NULL) != NULL) + if (of_get_property(np, "used-by-rtas", NULL) != NULL) return -1; /* Get the address */ @@ -157,7 +157,7 @@ static int __init add_legacy_isa_port(struct device_node *np, DBG(" -> add_legacy_isa_port(%s)\n", np->full_name); /* Get the ISA port number */ - reg = get_property(np, "reg", NULL); + reg = of_get_property(np, "reg", NULL); if (reg == NULL) return -1; @@ -168,7 +168,7 @@ static int __init add_legacy_isa_port(struct device_node *np, /* Now look for an "ibm,aix-loc" property that gives us ordering * if any... */ - typep = get_property(np, "ibm,aix-loc", NULL); + typep = of_get_property(np, "ibm,aix-loc", NULL); /* If we have a location index, then use it */ if (typep && *typep == 'S') @@ -206,7 +206,7 @@ static int __init add_legacy_pci_port(struct device_node *np, * compatible UARTs on PCI need all sort of quirks (port offsets * etc...) that this code doesn't know about */ - if (get_property(np, "clock-frequency", NULL) == NULL) + if (of_get_property(np, "clock-frequency", NULL) == NULL) return -1; /* Get the PCI address. Assume BAR 0 */ @@ -232,7 +232,7 @@ static int __init add_legacy_pci_port(struct device_node *np, * we get to their "reg" property */ if (np != pci_dev) { - const u32 *reg = get_property(np, "reg", NULL); + const u32 *reg = of_get_property(np, "reg", NULL); if (reg && (*reg < 4)) index = lindex = *reg; } @@ -296,7 +296,7 @@ void __init find_legacy_serial_ports(void) DBG(" -> find_legacy_serial_port()\n"); /* Now find out if one of these is out firmware console */ - path = get_property(of_chosen, "linux,stdout-path", NULL); + path = of_get_property(of_chosen, "linux,stdout-path", NULL); if (path != NULL) { stdout = of_find_node_by_path(path); if (stdout) @@ -529,7 +529,7 @@ static int __init check_legacy_serial_console(void) } /* We are getting a weird phandle from OF ... */ /* ... So use the full path instead */ - name = get_property(of_chosen, "linux,stdout-path", NULL); + name = of_get_property(of_chosen, "linux,stdout-path", NULL); if (name == NULL) { DBG(" no linux,stdout-path !\n"); return -ENODEV; @@ -541,12 +541,12 @@ static int __init check_legacy_serial_console(void) } DBG("stdout is %s\n", prom_stdout->full_name); - name = get_property(prom_stdout, "name", NULL); + name = of_get_property(prom_stdout, "name", NULL); if (!name) { DBG(" stdout package has no name !\n"); goto not_found; } - spd = get_property(prom_stdout, "current-speed", NULL); + spd = of_get_property(prom_stdout, "current-speed", NULL); if (spd) speed = *spd; diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 89486b63128..c492cee90e0 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -130,30 +130,31 @@ static int iseries_lparcfg_data(struct seq_file *m, void *v) /* * Methods used to fetch LPAR data when running on a pSeries platform. */ -/* find a better place for this function... */ static void log_plpar_hcall_return(unsigned long rc, char *tag) { - if (rc == 0) /* success, return */ + switch(rc) { + case 0: return; -/* check for null tag ? */ - if (rc == H_HARDWARE) - printk(KERN_INFO - "plpar-hcall (%s) failed with hardware fault\n", tag); - else if (rc == H_FUNCTION) - printk(KERN_INFO - "plpar-hcall (%s) failed; function not allowed\n", tag); - else if (rc == H_AUTHORITY) - printk(KERN_INFO - "plpar-hcall (%s) failed; not authorized to this" - " function\n", tag); - else if (rc == H_PARAMETER) - printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n", - tag); - else - printk(KERN_INFO - "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n", - tag, rc); - + case H_HARDWARE: + printk(KERN_INFO "plpar-hcall (%s) " + "Hardware fault\n", tag); + return; + case H_FUNCTION: + printk(KERN_INFO "plpar-hcall (%s) " + "Function not allowed\n", tag); + return; + case H_AUTHORITY: + printk(KERN_INFO "plpar-hcall (%s) " + "Not authorized to this function\n", tag); + return; + case H_PARAMETER: + printk(KERN_INFO "plpar-hcall (%s) " + "Bad parameter(s)\n",tag); + return; + default: + printk(KERN_INFO "plpar-hcall (%s) " + "Unexpected rc(0x%lx)\n", tag, rc); + } } /* @@ -321,15 +322,16 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) struct device_node *rtas_node; const int *lrdrp = NULL; - rtas_node = find_path_device("/rtas"); + rtas_node = of_find_node_by_path("/rtas"); if (rtas_node) - lrdrp = get_property(rtas_node, "ibm,lrdr-capacity", NULL); + lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL); if (lrdrp == NULL) { partition_potential_processors = vdso_data->processorCount; } else { partition_potential_processors = *(lrdrp + 4); } + of_node_put(rtas_node); partition_active_processors = lparcfg_count_active_processors(); @@ -537,25 +539,27 @@ static int lparcfg_data(struct seq_file *m, void *v) seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); - rootdn = find_path_device("/"); + rootdn = of_find_node_by_path("/"); if (rootdn) { - tmp = get_property(rootdn, "model", NULL); + tmp = of_get_property(rootdn, "model", NULL); if (tmp) { model = tmp; /* Skip "IBM," - see platforms/iseries/dt.c */ if (firmware_has_feature(FW_FEATURE_ISERIES)) model += 4; } - tmp = get_property(rootdn, "system-id", NULL); + tmp = of_get_property(rootdn, "system-id", NULL); if (tmp) { system_id = tmp; /* Skip "IBM," - see platforms/iseries/dt.c */ if (firmware_has_feature(FW_FEATURE_ISERIES)) system_id += 4; } - lp_index_ptr = get_property(rootdn, "ibm,partition-no", NULL); + lp_index_ptr = of_get_property(rootdn, "ibm,partition-no", + NULL); if (lp_index_ptr) lp_index = *lp_index_ptr; + of_node_put(rootdn); } seq_printf(m, "serial_number=%s\n", system_id); seq_printf(m, "system_type=%s\n", model); diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index a24b09c2771..704375bda73 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -72,8 +72,8 @@ int default_machine_kexec_prepare(struct kimage *image) /* We also should not overwrite the tce tables */ for (node = of_find_node_by_type(NULL, "pci"); node != NULL; node = of_find_node_by_type(node, "pci")) { - basep = get_property(node, "linux,tce-base", NULL); - sizep = get_property(node, "linux,tce-size", NULL); + basep = of_get_property(node, "linux,tce-base", NULL); + sizep = of_get_property(node, "linux,tce-size", NULL); if (basep == NULL || sizep == NULL) continue; @@ -294,19 +294,19 @@ static unsigned long htab_base, kernel_end; static struct property htab_base_prop = { .name = "linux,htab-base", .length = sizeof(unsigned long), - .value = (unsigned char *)&htab_base, + .value = &htab_base, }; static struct property htab_size_prop = { .name = "linux,htab-size", .length = sizeof(unsigned long), - .value = (unsigned char *)&htab_size_bytes, + .value = &htab_size_bytes, }; static struct property kernel_end_prop = { .name = "linux,kernel-end", .length = sizeof(unsigned long), - .value = (unsigned char *)&kernel_end, + .value = &kernel_end, }; static void __init export_htab_values(void) @@ -335,7 +335,7 @@ static void __init export_htab_values(void) static struct property crashk_base_prop = { .name = "linux,crashkernel-base", .length = sizeof(unsigned long), - .value = (unsigned char *)&crashk_res.start, + .value = &crashk_res.start, }; static unsigned long crashk_size; @@ -343,7 +343,7 @@ static unsigned long crashk_size; static struct property crashk_size_prop = { .name = "linux,crashkernel-size", .length = sizeof(unsigned long), - .value = (unsigned char *)&crashk_size, + .value = &crashk_size, }; static void __init export_crashk_values(void) diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 412bea3cf81..98decf8ebff 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -734,10 +734,6 @@ _GLOBAL(abs) sub r3,r3,r4 blr -_GLOBAL(_get_SP) - mr r3,r1 /* Close enough */ - blr - /* * Create a kernel thread * kernel_thread(fn, arg, flags) diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index e921514e655..0c8ea7659d9 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -120,6 +120,117 @@ void of_device_unregister(struct of_device *ofdev) } +static ssize_t of_device_get_modalias(struct of_device *ofdev, + char *str, ssize_t len) +{ + const char *compat; + int cplen, i; + ssize_t tsize, csize, repend; + + /* Name & Type */ + csize = snprintf(str, len, "of:N%sT%s", + ofdev->node->name, ofdev->node->type); + + /* Get compatible property if any */ + compat = of_get_property(ofdev->node, "compatible", &cplen); + if (!compat) + return csize; + + /* Find true end (we tolerate multiple \0 at the end */ + for (i=(cplen-1); i>=0 && !compat[i]; i--) + cplen--; + if (!cplen) + return csize; + cplen++; + + /* Check space (need cplen+1 chars including final \0) */ + tsize = csize + cplen; + repend = tsize; + + if (csize>=len) /* @ the limit, all is already filled */ + return tsize; + + if (tsize>=len) { /* limit compat list */ + cplen = len-csize-1; + repend = len; + } + + /* Copy and do char replacement */ + memcpy(&str[csize+1], compat, cplen); + for (i=csize; i<repend; i++) { + char c = str[i]; + if (c=='\0') + str[i] = 'C'; + else if (c==' ') + str[i] = '_'; + } + + return tsize; +} + +int of_device_uevent(struct device *dev, + char **envp, int num_envp, char *buffer, int buffer_size) +{ + struct of_device *ofdev; + const char *compat; + int i = 0, length = 0, seen = 0, cplen, sl; + + if (!dev) + return -ENODEV; + + ofdev = to_of_device(dev); + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_NAME=%s", ofdev->node->name)) + return -ENOMEM; + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_TYPE=%s", ofdev->node->type)) + return -ENOMEM; + + /* Since the compatible field can contain pretty much anything + * it's not really legal to split it out with commas. We split it + * up using a number of environment variables instead. */ + + compat = of_get_property(ofdev->node, "compatible", &cplen); + while (compat && *compat && cplen > 0) { + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_COMPATIBLE_%d=%s", seen, compat)) + return -ENOMEM; + + sl = strlen (compat) + 1; + compat += sl; + cplen -= sl; + seen++; + } + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_COMPATIBLE_N=%d", seen)) + return -ENOMEM; + + /* modalias is trickier, we add it in 2 steps */ + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MODALIAS=")) + return -ENOMEM; + + sl = of_device_get_modalias(ofdev, &buffer[length-1], + buffer_size-length); + if (sl >= (buffer_size-length)) + return -ENOMEM; + + length += sl; + + envp[i] = NULL; + + return 0; +} + + EXPORT_SYMBOL(of_match_node); EXPORT_SYMBOL(of_match_device); EXPORT_SYMBOL(of_device_register); @@ -127,3 +238,4 @@ EXPORT_SYMBOL(of_device_unregister); EXPORT_SYMBOL(of_dev_get); EXPORT_SYMBOL(of_dev_put); EXPORT_SYMBOL(of_release_dev); +EXPORT_SYMBOL(of_device_uevent); diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index b7345176b39..908ed7926db 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -133,6 +133,7 @@ static int of_platform_device_resume(struct device * dev) struct bus_type of_platform_bus_type = { .name = "of_platform", .match = of_platform_bus_match, + .uevent = of_device_uevent, .probe = of_platform_device_probe, .remove = of_platform_device_remove, .suspend = of_platform_device_suspend, @@ -177,7 +178,7 @@ static void of_platform_make_bus_id(struct of_device *dev) * and 'D' for MMIO DCRs. */ #ifdef CONFIG_PPC_DCR - reg = get_property(node, "dcr-reg", NULL); + reg = of_get_property(node, "dcr-reg", NULL); if (reg) { #ifdef CONFIG_PPC_DCR_NATIVE snprintf(name, BUS_ID_SIZE, "d%x.%s", @@ -197,7 +198,7 @@ static void of_platform_make_bus_id(struct of_device *dev) /* * For MMIO, get the physical address */ - reg = get_property(node, "reg", NULL); + reg = of_get_property(node, "reg", NULL); if (reg) { addr = of_translate_address(node, reg); if (addr != OF_BAD_ADDR) { @@ -475,9 +476,6 @@ static struct of_platform_driver of_pci_phb_driver = { .name = "of-pci", .match_table = of_pci_phb_ids, .probe = of_pci_phb_probe, - .driver = { - .multithread_probe = 1, - }, }; static __init int of_pci_phb_init(void) diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index d8ef2e10050..f022862de34 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -637,7 +637,7 @@ make_one_node_map(struct device_node* node, u8 pci_bus) if (pci_bus >= pci_bus_count) return; - bus_range = get_property(node, "bus-range", &len); + bus_range = of_get_property(node, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, " "assuming it starts at 0\n", node->full_name); @@ -649,17 +649,20 @@ make_one_node_map(struct device_node* node, u8 pci_bus) struct pci_dev* dev; const unsigned int *class_code, *reg; - class_code = get_property(node, "class-code", NULL); + class_code = of_get_property(node, "class-code", NULL); if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) continue; - reg = get_property(node, "reg", NULL); + reg = of_get_property(node, "reg", NULL); if (!reg) continue; - dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff)); - if (!dev || !dev->subordinate) + dev = pci_get_bus_and_slot(pci_bus, ((reg[0] >> 8) & 0xff)); + if (!dev || !dev->subordinate) { + pci_dev_put(dev); continue; + } make_one_node_map(node, dev->subordinate->number); + pci_dev_put(dev); } } @@ -669,6 +672,7 @@ pcibios_make_OF_bus_map(void) int i; struct pci_controller* hose; struct property *map_prop; + struct device_node *dn; pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL); if (!pci_to_OF_bus_map) { @@ -690,12 +694,13 @@ pcibios_make_OF_bus_map(void) continue; make_one_node_map(node, hose->first_busno); } - map_prop = of_find_property(find_path_device("/"), - "pci-OF-bus-map", NULL); + dn = of_find_node_by_path("/"); + map_prop = of_find_property(dn, "pci-OF-bus-map", NULL); if (map_prop) { BUG_ON(pci_bus_count > map_prop->length); memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count); } + of_node_put(dn); #ifdef DEBUG printk("PCI->OF bus map:\n"); for (i=0; i<pci_bus_count; i++) { @@ -724,7 +729,7 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* * a fake root for all functions of a multi-function device, * we go down them as well. */ - class_code = get_property(node, "class-code", NULL); + class_code = of_get_property(node, "class-code", NULL); if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) && strcmp(node->name, "multifunc-device")) @@ -744,7 +749,7 @@ static struct device_node *scan_OF_for_pci_dev(struct device_node *parent, unsigned int psize; while ((np = of_get_next_child(parent, np)) != NULL) { - reg = get_property(np, "reg", &psize); + reg = of_get_property(np, "reg", &psize); if (reg == NULL || psize < 4) continue; if (((reg[0] >> 8) & 0xff) == devfn) @@ -859,7 +864,7 @@ pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn) if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child, find_OF_pci_device_filter, (void *)node)) return -ENODEV; - reg = get_property(node, "reg", NULL); + reg = of_get_property(node, "reg", NULL); if (!reg) return -ENODEV; *bus = (reg[0] >> 16) & 0xff; @@ -895,14 +900,14 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose, int rlen = 0, orig_rlen; int memno = 0; struct resource *res; - int np, na = prom_n_addr_cells(dev); + int np, na = of_n_addr_cells(dev); np = na + 5; /* First we try to merge ranges to fix a problem with some pmacs * that can have more than 3 ranges, fortunately using contiguous * addresses -- BenH */ - dt_ranges = get_property(dev, "ranges", &rlen); + dt_ranges = of_get_property(dev, "ranges", &rlen); if (!dt_ranges) return; /* Sanity check, though hopefully that never happens */ @@ -1006,14 +1011,19 @@ void __init pci_create_OF_bus_map(void) { struct property* of_prop; - + struct device_node *dn; + of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256); - if (of_prop && find_path_device("/")) { + if (!of_prop) + return; + dn = of_find_node_by_path("/"); + if (dn) { memset(of_prop, -1, sizeof(struct property) + 256); of_prop->name = "pci-OF-bus-map"; of_prop->length = 256; - of_prop->value = (unsigned char *)&of_prop[1]; - prom_add_property(find_path_device("/"), of_prop); + of_prop->value = &of_prop[1]; + prom_add_property(dn, of_prop); + of_node_put(dn); } } diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 7e97d71a5f8..60d7d4baa22 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -61,8 +61,7 @@ void iSeries_pcibios_init(void); LIST_HEAD(hose_list); -struct dma_mapping_ops *pci_dma_ops; -EXPORT_SYMBOL(pci_dma_ops); +static struct dma_mapping_ops *pci_dma_ops; int global_phb_number; /* Global phb counter */ @@ -70,6 +69,17 @@ int global_phb_number; /* Global phb counter */ struct pci_dev *ppc64_isabridge_dev = NULL; EXPORT_SYMBOL_GPL(ppc64_isabridge_dev); +void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) +{ + pci_dma_ops = dma_ops; +} + +struct dma_mapping_ops *get_pci_dma_ops(void) +{ + return pci_dma_ops; +} +EXPORT_SYMBOL(get_pci_dma_ops); + static void fixup_broken_pcnet32(struct pci_dev* dev) { if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { @@ -258,7 +268,7 @@ static u32 get_int_prop(struct device_node *np, const char *name, u32 def) const u32 *prop; int len; - prop = get_property(np, name, &len); + prop = of_get_property(np, name, &len); if (prop && len >= 4) return *prop; return def; @@ -291,7 +301,7 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) u32 i; int proplen; - addrs = get_property(node, "assigned-addresses", &proplen); + addrs = of_get_property(node, "assigned-addresses", &proplen); if (!addrs) return; DBG(" parse addresses (%d bytes) @ %p\n", proplen, addrs); @@ -333,7 +343,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return NULL; - type = get_property(node, "device_type", NULL); + type = of_get_property(node, "device_type", NULL); if (type == NULL) type = ""; @@ -397,7 +407,7 @@ void __devinit of_scan_bus(struct device_node *node, while ((child = of_get_next_child(node, child)) != NULL) { DBG(" * %s\n", child->full_name); - reg = get_property(child, "reg", ®len); + reg = of_get_property(child, "reg", ®len); if (reg == NULL || reglen < 20) continue; devfn = (reg[0] >> 8) & 0xff; @@ -430,13 +440,13 @@ void __devinit of_scan_pci_bridge(struct device_node *node, DBG("of_scan_pci_bridge(%s)\n", node->full_name); /* parse bus-range property */ - busrange = get_property(node, "bus-range", &len); + busrange = of_get_property(node, "bus-range", &len); if (busrange == NULL || len != 8) { printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n", node->full_name); return; } - ranges = get_property(node, "ranges", &len); + ranges = of_get_property(node, "ranges", &len); if (ranges == NULL) { printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", node->full_name); @@ -900,7 +910,7 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, unsigned int size; int rlen = 0; - range = get_property(isa_node, "ranges", &rlen); + range = of_get_property(isa_node, "ranges", &rlen); if (range == NULL || (rlen < sizeof(struct isa_range))) { printk(KERN_ERR "no ISA ranges or unexpected isa range size," "mapping 64k\n"); @@ -947,7 +957,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, int rlen = 0; int memno = 0; struct resource *res; - int np, na = prom_n_addr_cells(dev); + int np, na = of_n_addr_cells(dev); unsigned long pci_addr, cpu_phys_addr; np = na + 5; @@ -960,7 +970,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, * (size depending on dev->n_addr_cells) * cells 4+5 or 5+6: the size of the range */ - ranges = get_property(dev, "ranges", &rlen); + ranges = of_get_property(dev, "ranges", &rlen); if (ranges == NULL) return; hose->io_base_phys = 0; diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 68df018dae0..d7d36df9c05 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -40,7 +40,8 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data) { struct pci_controller *phb = data; - const int *type = get_property(dn, "ibm,pci-config-space-type", NULL); + const int *type = + of_get_property(dn, "ibm,pci-config-space-type", NULL); const u32 *regs; struct pci_dn *pdn; @@ -54,14 +55,14 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data) dn->data = pdn; pdn->node = dn; pdn->phb = phb; - regs = get_property(dn, "reg", NULL); + regs = of_get_property(dn, "reg", NULL); if (regs) { /* First register entry is addr (00BBSS00) */ pdn->busno = (regs[0] >> 16) & 0xff; pdn->devfn = (regs[0] >> 8) & 0xff; } if (firmware_has_feature(FW_FEATURE_ISERIES)) { - const u32 *busp = get_property(dn, "linux,subbus", NULL); + const u32 *busp = of_get_property(dn, "linux,subbus", NULL); if (busp) pdn->bussubno = *busp; } @@ -100,7 +101,7 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, u32 class; nextdn = NULL; - classp = get_property(dn, "class-code", NULL); + classp = of_get_property(dn, "class-code", NULL); class = classp ? *classp : 0; if (pre && ((ret = pre(dn, data)) != NULL)) diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index ecee596d28f..ff252aaead1 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -20,7 +20,6 @@ #include <asm/processor.h> #include <asm/uaccess.h> #include <asm/io.h> -#include <asm/ide.h> #include <asm/atomic.h> #include <asm/checksum.h> #include <asm/pgtable.h> @@ -84,8 +83,6 @@ EXPORT_SYMBOL(strncpy); EXPORT_SYMBOL(strcat); EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strcasecmp); -EXPORT_SYMBOL(strncasecmp); EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy_generic); diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index e53b2988d1b..e509aae2feb 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -305,9 +305,7 @@ struct task_struct *__switch_to(struct task_struct *prev, set_dabr(new->thread.dabr); __get_cpu_var(current_dabr) = new->thread.dabr; } - - flush_tlb_pending(); -#endif +#endif /* CONFIG_PPC64 */ new_thread = &new->thread; old_thread = ¤t->thread; @@ -402,11 +400,11 @@ static void printbits(unsigned long val, struct regbit *bits) } #ifdef CONFIG_PPC64 -#define REG "%016lX" +#define REG "%016lx" #define REGS_PER_LINE 4 #define LAST_VOLATILE 13 #else -#define REG "%08lX" +#define REG "%08lx" #define REGS_PER_LINE 8 #define LAST_VOLATILE 12 #endif @@ -421,7 +419,7 @@ void show_regs(struct pt_regs * regs) regs, regs->trap, print_tainted(), init_utsname()->release); printk("MSR: "REG" ", regs->msr); printbits(regs->msr, msr_bits); - printk(" CR: %08lX XER: %08lX\n", regs->ccr, regs->xer); + printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer); trap = TRAP(regs); if (trap == 0x300 || trap == 0x600) printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr); @@ -572,7 +570,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, kregs->nip = *((unsigned long *)ret_from_fork); #else kregs->nip = (unsigned long)ret_from_fork; - p->thread.last_syscall = -1; #endif return 0; @@ -823,6 +820,35 @@ out: return error; } +#ifdef CONFIG_IRQSTACKS +static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, + unsigned long nbytes) +{ + unsigned long stack_page; + unsigned long cpu = task_cpu(p); + + /* + * Avoid crashing if the stack has overflowed and corrupted + * task_cpu(p), which is in the thread_info struct. + */ + if (cpu < NR_CPUS && cpu_possible(cpu)) { + stack_page = (unsigned long) hardirq_ctx[cpu]; + if (sp >= stack_page + sizeof(struct thread_struct) + && sp <= stack_page + THREAD_SIZE - nbytes) + return 1; + + stack_page = (unsigned long) softirq_ctx[cpu]; + if (sp >= stack_page + sizeof(struct thread_struct) + && sp <= stack_page + THREAD_SIZE - nbytes) + return 1; + } + return 0; +} + +#else +#define valid_irq_stack(sp, p, nb) 0 +#endif /* CONFIG_IRQSTACKS */ + int validate_sp(unsigned long sp, struct task_struct *p, unsigned long nbytes) { @@ -832,19 +858,7 @@ int validate_sp(unsigned long sp, struct task_struct *p, && sp <= stack_page + THREAD_SIZE - nbytes) return 1; -#ifdef CONFIG_IRQSTACKS - stack_page = (unsigned long) hardirq_ctx[task_cpu(p)]; - if (sp >= stack_page + sizeof(struct thread_struct) - && sp <= stack_page + THREAD_SIZE - nbytes) - return 1; - - stack_page = (unsigned long) softirq_ctx[task_cpu(p)]; - if (sp >= stack_page + sizeof(struct thread_struct) - && sp <= stack_page + THREAD_SIZE - nbytes) - return 1; -#endif - - return 0; + return valid_irq_stack(sp, p, nbytes); } #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 8d52b23348b..caef555f2dc 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -390,18 +390,19 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, if (allnextpp) { pp->name = "name"; pp->length = sz; - pp->value = (unsigned char *)(pp + 1); + pp->value = pp + 1; *prev_pp = pp; prev_pp = &pp->next; memcpy(pp->value, ps, sz - 1); ((char *)pp->value)[sz - 1] = 0; - DBG("fixed up name for %s -> %s\n", pathp, pp->value); + DBG("fixed up name for %s -> %s\n", pathp, + (char *)pp->value); } } if (allnextpp) { *prev_pp = NULL; - np->name = get_property(np, "name", NULL); - np->type = get_property(np, "device_type", NULL); + np->name = of_get_property(np, "name", NULL); + np->type = of_get_property(np, "device_type", NULL); if (!np->name) np->name = "<NULL>"; @@ -719,6 +720,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) { unsigned long *lprop; + u32 *prop; unsigned long l; char *p; @@ -760,6 +762,22 @@ static int __init early_init_dt_scan_chosen(unsigned long node, crashk_res.end = crashk_res.start + *lprop - 1; #endif +#ifdef CONFIG_BLK_DEV_INITRD + DBG("Looking for initrd properties... "); + prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); + if (prop) { + initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4)); + prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); + if (prop) { + initrd_end = (unsigned long)__va(of_read_ulong(prop, l/4)); + initrd_below_start_ok = 1; + } else { + initrd_start = 0; + } + } + DBG("initrd_start=0x%lx initrd_end=0x%lx\n", initrd_start, initrd_end); +#endif /* CONFIG_BLK_DEV_INITRD */ + /* Retreive command line */ p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) @@ -926,6 +944,12 @@ static void __init early_reserve_mem(void) self_size = initial_boot_params->totalsize; lmb_reserve(self_base, self_size); +#ifdef CONFIG_BLK_DEV_INITRD + /* then reserve the initrd, if any */ + if (initrd_start && (initrd_end > initrd_start)) + lmb_reserve(__pa(initrd_start), initrd_end - initrd_start); +#endif /* CONFIG_BLK_DEV_INITRD */ + #ifdef CONFIG_PPC32 /* * Handle the case where we might be booting from an old kexec @@ -954,9 +978,6 @@ static void __init early_reserve_mem(void) size = *(reserve_map++); if (size == 0) break; - /* skip if the reservation is for the blob */ - if (base == self_base && size == self_size) - continue; DBG("reserving: %llx -> %llx\n", base, size); lmb_reserve(base, size); } @@ -1021,102 +1042,46 @@ void __init early_init_devtree(void *params) #undef printk -int -prom_n_addr_cells(struct device_node* np) +int of_n_addr_cells(struct device_node* np) { const int *ip; do { if (np->parent) np = np->parent; - ip = get_property(np, "#address-cells", NULL); + ip = of_get_property(np, "#address-cells", NULL); if (ip != NULL) return *ip; } while (np->parent); /* No #address-cells property for the root node, default to 1 */ return 1; } -EXPORT_SYMBOL(prom_n_addr_cells); +EXPORT_SYMBOL(of_n_addr_cells); -int -prom_n_size_cells(struct device_node* np) +int of_n_size_cells(struct device_node* np) { const int* ip; do { if (np->parent) np = np->parent; - ip = get_property(np, "#size-cells", NULL); + ip = of_get_property(np, "#size-cells", NULL); if (ip != NULL) return *ip; } while (np->parent); /* No #size-cells property for the root node, default to 1 */ return 1; } -EXPORT_SYMBOL(prom_n_size_cells); - -/** - * Construct and return a list of the device_nodes with a given name. - */ -struct device_node *find_devices(const char *name) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - if (np->name != 0 && strcasecmp(np->name, name) == 0) { - *prevp = np; - prevp = &np->next; - } - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_devices); - -/** - * Construct and return a list of the device_nodes with a given type. - */ -struct device_node *find_type_devices(const char *type) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - if (np->type != 0 && strcasecmp(np->type, type) == 0) { - *prevp = np; - prevp = &np->next; - } - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_type_devices); - -/** - * Returns all nodes linked together - */ -struct device_node *find_all_nodes(void) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - *prevp = np; - prevp = &np->next; - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_all_nodes); +EXPORT_SYMBOL(of_n_size_cells); /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ -int device_is_compatible(const struct device_node *device, const char *compat) +int of_device_is_compatible(const struct device_node *device, + const char *compat) { const char* cp; int cplen, l; - cp = get_property(device, "compatible", &cplen); + cp = of_get_property(device, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { @@ -1129,7 +1094,7 @@ int device_is_compatible(const struct device_node *device, const char *compat) return 0; } -EXPORT_SYMBOL(device_is_compatible); +EXPORT_SYMBOL(of_device_is_compatible); /** @@ -1143,51 +1108,13 @@ int machine_is_compatible(const char *compat) root = of_find_node_by_path("/"); if (root) { - rc = device_is_compatible(root, compat); + rc = of_device_is_compatible(root, compat); of_node_put(root); } return rc; } EXPORT_SYMBOL(machine_is_compatible); -/** - * Construct and return a list of the device_nodes with a given type - * and compatible property. - */ -struct device_node *find_compatible_devices(const char *type, - const char *compat) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - if (type != NULL - && !(np->type != 0 && strcasecmp(np->type, type) == 0)) - continue; - if (device_is_compatible(np, compat)) { - *prevp = np; - prevp = &np->next; - } - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_compatible_devices); - -/** - * Find the device_node with a given full_name. - */ -struct device_node *find_path_device(const char *path) -{ - struct device_node *np; - - for (np = allnodes; np != 0; np = np->allnext) - if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0) - return np; - return NULL; -} -EXPORT_SYMBOL(find_path_device); - /******* * * New implementation of the OF "find" APIs, return a refcounted @@ -1280,7 +1207,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, if (type != NULL && !(np->type != 0 && strcasecmp(np->type, type) == 0)) continue; - if (device_is_compatible(np, compatible) && of_node_get(np)) + if (of_device_is_compatible(np, compatible) && of_node_get(np)) break; } of_node_put(from); @@ -1527,8 +1454,8 @@ static int of_finish_dynamic_node(struct device_node *node) int err = 0; const phandle *ibm_phandle; - node->name = get_property(node, "name", NULL); - node->type = get_property(node, "device_type", NULL); + node->name = of_get_property(node, "name", NULL); + node->type = of_get_property(node, "device_type", NULL); if (!parent) { err = -ENODEV; @@ -1542,7 +1469,7 @@ static int of_finish_dynamic_node(struct device_node *node) return -ENODEV; /* fix up new node's linux_phandle field */ - if ((ibm_phandle = get_property(node, "ibm,phandle", NULL))) + if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) node->linux_phandle = *ibm_phandle; out: @@ -1605,13 +1532,13 @@ EXPORT_SYMBOL(of_find_property); * Find a property with a given name for a given node * and return the value. */ -const void *get_property(const struct device_node *np, const char *name, +const void *of_get_property(const struct device_node *np, const char *name, int *lenp) { struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; } -EXPORT_SYMBOL(get_property); +EXPORT_SYMBOL(of_get_property); /* * Add a property to a node @@ -1742,10 +1669,10 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist * fallback to "reg" property and assume no threads */ - intserv = get_property(np, "ibm,ppc-interrupt-server#s", + intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &plen); if (intserv == NULL) { - const u32 *reg = get_property(np, "reg", NULL); + const u32 *reg = of_get_property(np, "reg", NULL); if (reg == NULL) continue; if (*reg == hardid) { diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 4fb5938ce6d..e27d9d1b6e6 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -2035,39 +2035,50 @@ static void __init fixup_device_tree_maple(void) #endif #ifdef CONFIG_PPC_CHRP -/* Pegasos and BriQ lacks the "ranges" property in the isa node */ +/* + * Pegasos and BriQ lacks the "ranges" property in the isa node + * Pegasos needs decimal IRQ 14/15, not hexadecimal + */ static void __init fixup_device_tree_chrp(void) { - phandle isa; - u32 isa_ranges[6]; + phandle ph; + u32 prop[6]; u32 rloc = 0x01006000; /* IO space; PCI device = 12 */ char *name; int rc; name = "/pci@80000000/isa@c"; - isa = call_prom("finddevice", 1, 1, ADDR(name)); - if (!PHANDLE_VALID(isa)) { + ph = call_prom("finddevice", 1, 1, ADDR(name)); + if (!PHANDLE_VALID(ph)) { name = "/pci@ff500000/isa@6"; - isa = call_prom("finddevice", 1, 1, ADDR(name)); + ph = call_prom("finddevice", 1, 1, ADDR(name)); rloc = 0x01003000; /* IO space; PCI device = 6 */ } - if (!PHANDLE_VALID(isa)) - return; - - rc = prom_getproplen(isa, "ranges"); - if (rc != 0 && rc != PROM_ERROR) - return; - - prom_printf("Fixing up missing ISA range on Pegasos...\n"); + if (PHANDLE_VALID(ph)) { + rc = prom_getproplen(ph, "ranges"); + if (rc == 0 || rc == PROM_ERROR) { + prom_printf("Fixing up missing ISA range on Pegasos...\n"); + + prop[0] = 0x1; + prop[1] = 0x0; + prop[2] = rloc; + prop[3] = 0x0; + prop[4] = 0x0; + prop[5] = 0x00010000; + prom_setprop(ph, name, "ranges", prop, sizeof(prop)); + } + } - isa_ranges[0] = 0x1; - isa_ranges[1] = 0x0; - isa_ranges[2] = rloc; - isa_ranges[3] = 0x0; - isa_ranges[4] = 0x0; - isa_ranges[5] = 0x00010000; - prom_setprop(isa, name, "ranges", - isa_ranges, sizeof(isa_ranges)); + name = "/pci@80000000/ide@C,1"; + ph = call_prom("finddevice", 1, 1, ADDR(name)); + if (PHANDLE_VALID(ph)) { + prom_printf("Fixing up IDE interrupt on Pegasos...\n"); + prop[0] = 14; + prop[1] = 0x0; + prop[2] = 15; + prop[3] = 0x0; + prom_setprop(ph, name, "interrupts", prop, 4*sizeof(u32)); + } } #else #define fixup_device_tree_chrp() diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 91b443c9a48..aa40a530729 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -68,9 +68,9 @@ static void of_bus_default_count_cells(struct device_node *dev, int *addrc, int *sizec) { if (addrc) - *addrc = prom_n_addr_cells(dev); + *addrc = of_n_addr_cells(dev); if (sizec) - *sizec = prom_n_size_cells(dev); + *sizec = of_n_size_cells(dev); } static u64 of_bus_default_map(u32 *addr, const u32 *range, @@ -196,7 +196,7 @@ const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, return NULL; /* Get "reg" or "assigned-addresses" property */ - prop = get_property(dev, bus->addresses, &psize); + prop = of_get_property(dev, bus->addresses, &psize); if (prop == NULL) return NULL; psize /= 4; @@ -438,7 +438,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, * to translate addresses that aren't supposed to be translated in * the first place. --BenH. */ - ranges = get_property(parent, "ranges", &rlen); + ranges = of_get_property(parent, "ranges", &rlen); if (ranges == NULL || rlen == 0) { offset = of_read_number(addr, na); memset(addr, 0, pna * 4); @@ -578,7 +578,7 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size, return NULL; /* Get "reg" or "assigned-addresses" property */ - prop = get_property(dev, bus->addresses, &psize); + prop = of_get_property(dev, bus->addresses, &psize); if (prop == NULL) return NULL; psize /= 4; @@ -650,17 +650,17 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, /* busno is always one cell */ *busno = *(dma_window++); - prop = get_property(dn, "ibm,#dma-address-cells", NULL); + prop = of_get_property(dn, "ibm,#dma-address-cells", NULL); if (!prop) - prop = get_property(dn, "#address-cells", NULL); + prop = of_get_property(dn, "#address-cells", NULL); - cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); + cells = prop ? *(u32 *)prop : of_n_addr_cells(dn); *phys = of_read_number(dma_window, cells); dma_window += cells; - prop = get_property(dn, "ibm,#dma-size-cells", NULL); - cells = prop ? *(u32 *)prop : prom_n_size_cells(dn); + prop = of_get_property(dn, "ibm,#dma-size-cells", NULL); + cells = prop ? *(u32 *)prop : of_n_size_cells(dn); *size = of_read_number(dma_window, cells); } @@ -680,7 +680,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child) return NULL; do { - parp = get_property(child, "interrupt-parent", NULL); + parp = of_get_property(child, "interrupt-parent", NULL); if (parp == NULL) p = of_get_parent(child); else { @@ -691,7 +691,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child) } of_node_put(child); child = p; - } while (p && get_property(p, "#interrupt-cells", NULL) == NULL); + } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); return p; } @@ -716,7 +716,7 @@ void of_irq_map_init(unsigned int flags) struct device_node *np; for(np = NULL; (np = of_find_all_nodes(np)) != NULL;) { - if (get_property(np, "interrupt-controller", NULL) + if (of_get_property(np, "interrupt-controller", NULL) == NULL) continue; /* Skip /chosen/interrupt-controller */ @@ -755,7 +755,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, * is none, we are nice and just walk up the tree */ do { - tmp = get_property(ipar, "#interrupt-cells", NULL); + tmp = of_get_property(ipar, "#interrupt-cells", NULL); if (tmp != NULL) { intsize = *tmp; break; @@ -779,7 +779,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, */ old = of_node_get(ipar); do { - tmp = get_property(old, "#address-cells", NULL); + tmp = of_get_property(old, "#address-cells", NULL); tnode = of_get_parent(old); of_node_put(old); old = tnode; @@ -795,7 +795,8 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, /* Now check if cursor is an interrupt-controller and if it is * then we are done */ - if (get_property(ipar, "interrupt-controller", NULL) != NULL) { + if (of_get_property(ipar, "interrupt-controller", NULL) != + NULL) { DBG(" -> got it !\n"); memcpy(out_irq->specifier, intspec, intsize * sizeof(u32)); @@ -806,7 +807,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, } /* Now look for an interrupt-map */ - imap = get_property(ipar, "interrupt-map", &imaplen); + imap = of_get_property(ipar, "interrupt-map", &imaplen); /* No interrupt map, check for an interrupt parent */ if (imap == NULL) { DBG(" -> no map, getting parent\n"); @@ -816,7 +817,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, imaplen /= sizeof(u32); /* Look for a mask */ - imask = get_property(ipar, "interrupt-map-mask", NULL); + imask = of_get_property(ipar, "interrupt-map-mask", NULL); /* If we were passed no "reg" property and we attempt to parse * an interrupt-map, then #address-cells must be 0. @@ -863,15 +864,13 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, /* Get #interrupt-cells and #address-cells of new * parent */ - tmp = get_property(newpar, "#interrupt-cells", - NULL); + tmp = of_get_property(newpar, "#interrupt-cells", NULL); if (tmp == NULL) { DBG(" -> parent lacks #interrupt-cells !\n"); goto fail; } newintsize = *tmp; - tmp = get_property(newpar, "#address-cells", - NULL); + tmp = of_get_property(newpar, "#address-cells", NULL); newaddrsize = (tmp == NULL) ? 0 : *tmp; DBG(" -> newintsize=%d, newaddrsize=%d\n", @@ -928,7 +927,7 @@ static int of_irq_map_oldworld(struct device_node *device, int index, * everything together on these) */ while (device) { - ints = get_property(device, "AAPL,interrupts", &intlen); + ints = of_get_property(device, "AAPL,interrupts", &intlen); if (ints != NULL) break; device = device->parent; @@ -970,13 +969,13 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq return of_irq_map_oldworld(device, index, out_irq); /* Get the interrupts property */ - intspec = get_property(device, "interrupts", &intlen); + intspec = of_get_property(device, "interrupts", &intlen); if (intspec == NULL) return -EINVAL; intlen /= sizeof(u32); /* Get the reg property (if any) */ - addr = get_property(device, "reg", NULL); + addr = of_get_property(device, "reg", NULL); /* Look for the interrupt parent. */ p = of_irq_find_parent(device); @@ -984,7 +983,7 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq return -EINVAL; /* Get size of interrupt specifier */ - tmp = get_property(p, "#interrupt-cells", NULL); + tmp = of_get_property(p, "#interrupt-cells", NULL); if (tmp == NULL) { of_node_put(p); return -EINVAL; diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 6cbf2ae5d7a..190b7ed1dbf 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -450,7 +450,7 @@ static int ppc_rtas_sensors_show(struct seq_file *m, void *v) int llen, offs; sprintf (rstr, SENSOR_PREFIX"%04d", p->token); - loc = get_property(rtas_node, rstr, &llen); + loc = of_get_property(rtas_node, rstr, &llen); /* A sensor may have multiple instances */ for (j = 0, offs = 0; j <= p->quant; j++) { @@ -477,7 +477,7 @@ static int ppc_rtas_find_all_sensors(void) const unsigned int *utmp; int len, i; - utmp = get_property(rtas_node, "rtas-sensors", &len); + utmp = of_get_property(rtas_node, "rtas-sensors", &len); if (utmp == NULL) { printk (KERN_ERR "error: could not get rtas-sensors\n"); return 1; diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 9d0735a5456..21478079828 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -192,18 +192,19 @@ void rtas_progress(char *s, unsigned short hex) if (display_width == 0) { display_width = 0x10; - if ((root = find_path_device("/rtas"))) { - if ((p = get_property(root, + if ((root = of_find_node_by_path("/rtas"))) { + if ((p = of_get_property(root, "ibm,display-line-length", NULL))) display_width = *p; - if ((p = get_property(root, + if ((p = of_get_property(root, "ibm,form-feed", NULL))) form_feed = *p; - if ((p = get_property(root, + if ((p = of_get_property(root, "ibm,display-number-of-lines", NULL))) display_lines = *p; - row_width = get_property(root, + row_width = of_get_property(root, "ibm,display-truncation-length", NULL); + of_node_put(root); } display_character = rtas_token("display-character"); set_indicator = rtas_token("set-indicator"); @@ -298,7 +299,7 @@ int rtas_token(const char *service) const int *tokp; if (rtas.dev == NULL) return RTAS_UNKNOWN_SERVICE; - tokp = get_property(rtas.dev, service, NULL); + tokp = of_get_property(rtas.dev, service, NULL); return tokp ? *tokp : RTAS_UNKNOWN_SERVICE; } EXPORT_SYMBOL(rtas_token); @@ -832,12 +833,12 @@ void __init rtas_initialize(void) if (rtas.dev) { const u32 *basep, *entryp, *sizep; - basep = get_property(rtas.dev, "linux,rtas-base", NULL); - sizep = get_property(rtas.dev, "rtas-size", NULL); + basep = of_get_property(rtas.dev, "linux,rtas-base", NULL); + sizep = of_get_property(rtas.dev, "rtas-size", NULL); if (basep != NULL && sizep != NULL) { rtas.base = *basep; rtas.size = *sizep; - entryp = get_property(rtas.dev, + entryp = of_get_property(rtas.dev, "linux,rtas-entry", NULL); if (entryp == NULL) /* Ugh */ rtas.entry = rtas.base; diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index ace9f4c86e6..f2286822be0 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -60,7 +60,7 @@ static int of_device_available(struct device_node * dn) { const char *status; - status = get_property(dn, "status", NULL); + status = of_get_property(dn, "status", NULL); if (!status) return 1; @@ -177,7 +177,7 @@ struct pci_ops rtas_pci_ops = { int is_python(struct device_node *dev) { - const char *model = get_property(dev, "model", NULL); + const char *model = of_get_property(dev, "model", NULL); if (model && strstr(model, "Python")) return 1; @@ -247,7 +247,7 @@ static int phb_set_bus_ranges(struct device_node *dev, const int *bus_range; unsigned int len; - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { return 1; } @@ -274,7 +274,7 @@ int __devinit rtas_setup_phb(struct pci_controller *phb) return 0; } -unsigned long __init find_and_init_phbs(void) +void __init find_and_init_phbs(void) { struct device_node *node; struct pci_controller *phb; @@ -309,18 +309,16 @@ unsigned long __init find_and_init_phbs(void) if (of_chosen) { const int *prop; - prop = get_property(of_chosen, + prop = of_get_property(of_chosen, "linux,pci-probe-only", NULL); if (prop) pci_probe_only = *prop; - prop = get_property(of_chosen, + prop = of_get_property(of_chosen, "linux,pci-assign-all-buses", NULL); if (prop) pci_assign_all_buses = *prop; } - - return 0; } /* RPA-specific bits for removing PHBs */ diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 89cfaf49d3d..370803722e4 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -21,7 +21,6 @@ #include <linux/delay.h> #include <linux/initrd.h> #include <linux/platform_device.h> -#include <linux/ide.h> #include <linux/seq_file.h> #include <linux/ioport.h> #include <linux/console.h> @@ -304,26 +303,8 @@ struct seq_operations cpuinfo_op = { void __init check_for_initrd(void) { #ifdef CONFIG_BLK_DEV_INITRD - const unsigned int *prop; - int len; - - DBG(" -> check_for_initrd()\n"); - - if (of_chosen) { - prop = get_property(of_chosen, "linux,initrd-start", &len); - if (prop != NULL) { - initrd_start = (unsigned long) - __va(of_read_ulong(prop, len / 4)); - prop = get_property(of_chosen, - "linux,initrd-end", &len); - if (prop != NULL) { - initrd_end = (unsigned long) - __va(of_read_ulong(prop, len / 4)); - initrd_below_start_ok = 1; - } else - initrd_start = 0; - } - } + DBG(" -> check_for_initrd() initrd_start=0x%lx initrd_end=0x%lx\n", + initrd_start, initrd_end); /* If we were passed an initrd, set the ROOT_DEV properly if the values * look sensible. If not, clear initrd reference. @@ -371,11 +352,12 @@ void __init smp_setup_cpu_maps(void) const int *intserv; int j, len = sizeof(u32), nthreads = 1; - intserv = get_property(dn, "ibm,ppc-interrupt-server#s", &len); + intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", + &len); if (intserv) nthreads = len / sizeof(int); else { - intserv = get_property(dn, "reg", NULL); + intserv = of_get_property(dn, "reg", NULL); if (!intserv) intserv = &cpu; /* assume logical == phys */ } @@ -398,10 +380,10 @@ void __init smp_setup_cpu_maps(void) int num_addr_cell, num_size_cell, maxcpus; const unsigned int *ireg; - num_addr_cell = prom_n_addr_cells(dn); - num_size_cell = prom_n_size_cells(dn); + num_addr_cell = of_n_addr_cells(dn); + num_size_cell = of_n_size_cells(dn); - ireg = get_property(dn, "ibm,lrdr-capacity", NULL); + ireg = of_get_property(dn, "ibm,lrdr-capacity", NULL); if (!ireg) goto out; @@ -496,11 +478,39 @@ void probe_machine(void) printk(KERN_INFO "Using %s machine description\n", ppc_md.name); } +/* Match a class of boards, not a specific device configuration. */ int check_legacy_ioport(unsigned long base_port) { - if (ppc_md.check_legacy_ioport == NULL) - return 0; - return ppc_md.check_legacy_ioport(base_port); + struct device_node *parent, *np = NULL; + int ret = -ENODEV; + + switch(base_port) { + case I8042_DATA_REG: + np = of_find_node_by_type(NULL, "8042"); + break; + case FDC_BASE: /* FDC1 */ + np = of_find_node_by_type(NULL, "fdc"); + break; +#ifdef CONFIG_PPC_PREP + case _PIDXR: + case _PNPWRP: + case PNPBIOS_BASE: + /* implement me */ +#endif + default: + /* ipmi is supposed to fail here */ + break; + } + if (!np) + return ret; + parent = of_get_parent(np); + if (parent) { + if (strcmp(parent->type, "isa") == 0) + ret = 0; + of_node_put(parent); + } + of_node_put(np); + return ret; } EXPORT_SYMBOL(check_legacy_ioport); diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 44a6a3c47fe..35f8f443c14 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -92,7 +92,8 @@ unsigned long __init early_init(unsigned long dt_ptr) /* First zero the BSS -- use memset_io, some platforms don't have * caches on yet */ - memset_io((void __iomem *)PTRRELOC(&__bss_start), 0, _end - __bss_start); + memset_io((void __iomem *)PTRRELOC(&__bss_start), 0, + __bss_stop - __bss_start); /* * Identify the CPU type and fix up code sections @@ -195,18 +196,22 @@ EXPORT_SYMBOL(nvram_sync); #endif /* CONFIG_NVRAM */ -static struct cpu cpu_devices[NR_CPUS]; +static DEFINE_PER_CPU(struct cpu, cpu_devices); int __init ppc_init(void) { - int i; + int cpu; /* clear the progress line */ - if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); + if (ppc_md.progress) + ppc_md.progress(" ", 0xffff); /* register CPU devices */ - for_each_possible_cpu(i) - register_cpu(&cpu_devices[i], i); + for_each_possible_cpu(cpu) { + struct cpu *c = &per_cpu(cpu_devices, cpu); + c->hotpluggable = 1; + register_cpu(c, cpu); + } /* call platform init */ if (ppc_md.init != NULL) { diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 3733de30e84..22083ce3cc3 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -20,7 +20,6 @@ #include <linux/reboot.h> #include <linux/delay.h> #include <linux/initrd.h> -#include <linux/ide.h> #include <linux/seq_file.h> #include <linux/ioport.h> #include <linux/console.h> @@ -110,7 +109,7 @@ static void check_smt_enabled(void) dn = of_find_node_by_path("/options"); if (dn) { - smt_option = get_property(dn, "ibm,smt-enabled", NULL); + smt_option = of_get_property(dn, "ibm,smt-enabled", NULL); if (smt_option) { if (!strcmp(smt_option, "on")) @@ -305,10 +304,10 @@ static void __init initialize_cache_info(void) size = 0; lsize = cur_cpu_spec->dcache_bsize; - sizep = get_property(np, "d-cache-size", NULL); + sizep = of_get_property(np, "d-cache-size", NULL); if (sizep != NULL) size = *sizep; - lsizep = get_property(np, dc, NULL); + lsizep = of_get_property(np, dc, NULL); if (lsizep != NULL) lsize = *lsizep; if (sizep == 0 || lsizep == 0) @@ -322,10 +321,10 @@ static void __init initialize_cache_info(void) size = 0; lsize = cur_cpu_spec->icache_bsize; - sizep = get_property(np, "i-cache-size", NULL); + sizep = of_get_property(np, "i-cache-size", NULL); if (sizep != NULL) size = *sizep; - lsizep = get_property(np, ic, NULL); + lsizep = of_get_property(np, ic, NULL); if (lsizep != NULL) lsize = *lsizep; if (sizep == 0 || lsizep == 0) diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 924d692bc8f..d8e503b2e1a 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -428,10 +428,6 @@ void generic_mach_cpu_die(void) smp_wmb(); while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) cpu_relax(); - -#ifdef CONFIG_PPC64 - flush_tlb_pending(); -#endif cpu_set(cpu, cpu_online_map); local_irq_enable(); } diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index 673e8d9df7f..047246ad4f6 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c @@ -53,10 +53,6 @@ #include <asm/ppc-pci.h> #include <asm/syscalls.h> -/* readdir & getdents */ -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) -#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1)) - struct old_linux_dirent32 { u32 d_ino; u32 d_offset; diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index d57818aea08..933e214c33e 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -66,16 +66,17 @@ static int __init smt_setup(void) if (!cpu_has_feature(CPU_FTR_SMT)) return -ENODEV; - options = find_path_device("/options"); + options = of_find_node_by_path("/options"); if (!options) return -ENODEV; - val = get_property(options, "ibm,smt-snooze-delay", NULL); + val = of_get_property(options, "ibm,smt-snooze-delay", NULL); if (!smt_snooze_cmdline && val) { for_each_possible_cpu(cpu) per_cpu(smt_snooze_delay, cpu) = *val; } + of_node_put(options); return 0; } __initcall(smt_setup); @@ -189,12 +190,12 @@ SYSFS_PMCSETUP(purr, SPRN_PURR); SYSFS_PMCSETUP(spurr, SPRN_SPURR); SYSFS_PMCSETUP(dscr, SPRN_DSCR); -SYSFS_PMCSETUP(pa6t_pmc0, PA6T_SPRN_PMC0); -SYSFS_PMCSETUP(pa6t_pmc1, PA6T_SPRN_PMC1); -SYSFS_PMCSETUP(pa6t_pmc2, PA6T_SPRN_PMC2); -SYSFS_PMCSETUP(pa6t_pmc3, PA6T_SPRN_PMC3); -SYSFS_PMCSETUP(pa6t_pmc4, PA6T_SPRN_PMC4); -SYSFS_PMCSETUP(pa6t_pmc5, PA6T_SPRN_PMC5); +SYSFS_PMCSETUP(pa6t_pmc0, SPRN_PA6T_PMC0); +SYSFS_PMCSETUP(pa6t_pmc1, SPRN_PA6T_PMC1); +SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2); +SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3); +SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4); +SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5); static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra); diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index f6f0c6b07c4..7cedef8f5f7 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -834,7 +834,7 @@ static int __init get_freq(char *name, int cells, unsigned long *val) cpu = of_find_node_by_type(NULL, "cpu"); if (cpu) { - fp = get_property(cpu, name, NULL); + fp = of_get_property(cpu, name, NULL); if (fp) { found = 1; *val = of_read_ulong(fp, cells); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 17724fb2067..f7862224fe8 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -90,21 +90,11 @@ EXPORT_SYMBOL(unregister_die_notifier); * Trap & Exception support */ -static DEFINE_SPINLOCK(die_lock); - -int die(const char *str, struct pt_regs *regs, long err) -{ - static int die_counter; - - if (debugger(regs)) - return 1; - - console_verbose(); - spin_lock_irq(&die_lock); - bust_spinlocks(1); #ifdef CONFIG_PMAC_BACKLIGHT +static void pmac_backlight_unblank(void) +{ mutex_lock(&pmac_backlight_mutex); - if (machine_is(powermac) && pmac_backlight) { + if (pmac_backlight) { struct backlight_properties *props; props = &pmac_backlight->props; @@ -113,26 +103,67 @@ int die(const char *str, struct pt_regs *regs, long err) backlight_update_status(pmac_backlight); } mutex_unlock(&pmac_backlight_mutex); +} +#else +static inline void pmac_backlight_unblank(void) { } #endif - printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); + +int die(const char *str, struct pt_regs *regs, long err) +{ + static struct { + spinlock_t lock; + u32 lock_owner; + int lock_owner_depth; + } die = { + .lock = __SPIN_LOCK_UNLOCKED(die.lock), + .lock_owner = -1, + .lock_owner_depth = 0 + }; + static int die_counter; + unsigned long flags; + + if (debugger(regs)) + return 1; + + oops_enter(); + + if (die.lock_owner != raw_smp_processor_id()) { + console_verbose(); + spin_lock_irqsave(&die.lock, flags); + die.lock_owner = smp_processor_id(); + die.lock_owner_depth = 0; + bust_spinlocks(1); + if (machine_is(powermac)) + pmac_backlight_unblank(); + } else { + local_save_flags(flags); + } + + if (++die.lock_owner_depth < 3) { + printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); #ifdef CONFIG_PREEMPT - printk("PREEMPT "); + printk("PREEMPT "); #endif #ifdef CONFIG_SMP - printk("SMP NR_CPUS=%d ", NR_CPUS); + printk("SMP NR_CPUS=%d ", NR_CPUS); #endif #ifdef CONFIG_DEBUG_PAGEALLOC - printk("DEBUG_PAGEALLOC "); + printk("DEBUG_PAGEALLOC "); #endif #ifdef CONFIG_NUMA - printk("NUMA "); + printk("NUMA "); #endif - printk("%s\n", ppc_md.name ? "" : ppc_md.name); + printk("%s\n", ppc_md.name ? ppc_md.name : ""); + + print_modules(); + show_regs(regs); + } else { + printk("Recursive die() failure, output suppressed\n"); + } - print_modules(); - show_regs(regs); bust_spinlocks(0); - spin_unlock_irq(&die_lock); + die.lock_owner = -1; + spin_unlock_irqrestore(&die.lock, flags); if (kexec_should_crash(current) || kexec_sr_activated(smp_processor_id())) @@ -145,6 +176,7 @@ int die(const char *str, struct pt_regs *regs, long err) if (panic_on_oops) panic("Fatal exception"); + oops_exit(); do_exit(err); return 0; diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 2968ffeafdb..9eaefac5053 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -81,7 +81,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) struct iommu_table *tbl; unsigned long offset, size; - dma_window = get_property(dev->dev.archdata.of_node, + dma_window = of_get_property(dev->dev.archdata.of_node, "ibm,my-dma-window", NULL); if (!dma_window) return NULL; @@ -226,7 +226,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) return NULL; } - unit_address = get_property(of_node, "reg", NULL); + unit_address = of_get_property(of_node, "reg", NULL); if (unit_address == NULL) { printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__, @@ -246,7 +246,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) viodev->type = of_node->type; viodev->unit_address = *unit_address; if (firmware_has_feature(FW_FEATURE_ISERIES)) { - unit_address = get_property(of_node, + unit_address = of_get_property(of_node, "linux,unit_address", NULL); if (unit_address != NULL) viodev->unit_address = *unit_address; @@ -308,7 +308,7 @@ static int __init vio_bus_init(void) return err; } - node_vroot = find_devices("vdevice"); + node_vroot = of_find_node_by_name(NULL, "vdevice"); if (node_vroot) { struct device_node *of_node; @@ -322,6 +322,7 @@ static int __init vio_bus_init(void) __FUNCTION__, of_node); vio_register_device_node(of_node); } + of_node_put(node_vroot); } return 0; @@ -377,7 +378,7 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp, dn = dev->archdata.of_node; if (!dn) return -ENODEV; - cp = get_property(dn, "compatible", &length); + cp = of_get_property(dn, "compatible", &length); if (!cp) return -ENODEV; @@ -406,12 +407,12 @@ struct bus_type vio_bus_type = { * @which: The property/attribute to be extracted. * @length: Pointer to length of returned data size (unused if NULL). * - * Calls prom.c's get_property() to return the value of the + * Calls prom.c's of_get_property() to return the value of the * attribute specified by @which */ const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) { - return get_property(vdev->dev.archdata.of_node, which, length); + return of_get_property(vdev->dev.archdata.of_node, which, length); } EXPORT_SYMBOL(vio_get_attribute); @@ -443,7 +444,7 @@ struct vio_dev *vio_find_node(struct device_node *vnode) char kobj_name[BUS_ID_SIZE]; /* construct the kobject name from the device node */ - unit_address = get_property(vnode, "reg", NULL); + unit_address = of_get_property(vnode, "reg", NULL); if (!unit_address) return NULL; snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 4b1ba49fbd9..450258de7ca 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -7,13 +7,12 @@ EXTRA_CFLAGS += -mno-minimal-toc endif ifeq ($(CONFIG_PPC_MERGE),y) -obj-y := string.o strcase.o +obj-y := string.o obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o endif obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \ - memcpy_64.o usercopy_64.o mem_64.o string.o \ - strcase.o + memcpy_64.o usercopy_64.o mem_64.o string.o obj-$(CONFIG_QUICC_ENGINE) += rheap.o obj-$(CONFIG_XMON) += sstep.o obj-$(CONFIG_KPROBES) += sstep.o diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index a6b54cb97c4..25ec5378afa 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S @@ -24,7 +24,7 @@ _GLOBAL(__copy_tofrom_user) dcbt 0,r4 beq .Lcopy_page_4K andi. r6,r6,7 - mtcrf 0x01,r5 + PPC_MTOCRF 0x01,r5 blt cr1,.Lshort_copy bne .Ldst_unaligned .Ldst_aligned: @@ -135,7 +135,7 @@ _GLOBAL(__copy_tofrom_user) b .Ldo_tail .Ldst_unaligned: - mtcrf 0x01,r6 /* put #bytes to 8B bdry into cr7 */ + PPC_MTOCRF 0x01,r6 /* put #bytes to 8B bdry into cr7 */ subf r5,r6,r5 li r7,0 cmpldi r1,r5,16 @@ -150,7 +150,7 @@ _GLOBAL(__copy_tofrom_user) 2: bf cr7*4+1,3f 37: lwzx r0,r7,r4 83: stwx r0,r7,r3 -3: mtcrf 0x01,r5 +3: PPC_MTOCRF 0x01,r5 add r4,r6,r4 add r3,r6,r3 b .Ldst_aligned diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 80b482ca30d..79d0fa3a470 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c @@ -43,9 +43,11 @@ void __spin_yield(raw_spinlock_t *lock) if (firmware_has_feature(FW_FEATURE_ISERIES)) HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc, ((u64)holder_cpu << 32) | yield_count); +#ifdef CONFIG_PPC_SPLPAR else plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu), yield_count); +#endif } /* @@ -72,9 +74,11 @@ void __rw_yield(raw_rwlock_t *rw) if (firmware_has_feature(FW_FEATURE_ISERIES)) HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc, ((u64)holder_cpu << 32) | yield_count); +#ifdef CONFIG_PPC_SPLPAR else plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu), yield_count); +#endif } #endif diff --git a/arch/powerpc/lib/mem_64.S b/arch/powerpc/lib/mem_64.S index 68df20283ff..11ce045e21f 100644 --- a/arch/powerpc/lib/mem_64.S +++ b/arch/powerpc/lib/mem_64.S @@ -19,7 +19,7 @@ _GLOBAL(memset) rlwimi r4,r4,16,0,15 cmplw cr1,r5,r0 /* do we get that far? */ rldimi r4,r4,32,0 - mtcrf 1,r0 + PPC_MTOCRF 1,r0 mr r6,r3 blt cr1,8f beq+ 3f /* if already 8-byte aligned */ @@ -49,7 +49,7 @@ _GLOBAL(memset) bdnz 4b 5: srwi. r0,r5,3 clrlwi r5,r5,29 - mtcrf 1,r0 + PPC_MTOCRF 1,r0 beq 8f bf 29,6f std r4,0(r6) @@ -65,7 +65,7 @@ _GLOBAL(memset) std r4,0(r6) addi r6,r6,8 8: cmpwi r5,0 - mtcrf 1,r5 + PPC_MTOCRF 1,r5 beqlr+ bf 29,9f stw r4,0(r6) diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S index 7173ba98f42..3f131129d1c 100644 --- a/arch/powerpc/lib/memcpy_64.S +++ b/arch/powerpc/lib/memcpy_64.S @@ -12,7 +12,7 @@ .align 7 _GLOBAL(memcpy) std r3,48(r1) /* save destination pointer for return value */ - mtcrf 0x01,r5 + PPC_MTOCRF 0x01,r5 cmpldi cr1,r5,16 neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry andi. r6,r6,7 @@ -128,7 +128,7 @@ _GLOBAL(memcpy) b .Ldo_tail .Ldst_unaligned: - mtcrf 0x01,r6 # put #bytes to 8B bdry into cr7 + PPC_MTOCRF 0x01,r6 # put #bytes to 8B bdry into cr7 subf r5,r6,r5 li r7,0 cmpldi r1,r5,16 @@ -143,7 +143,7 @@ _GLOBAL(memcpy) 2: bf cr7*4+1,3f lwzx r0,r7,r4 stwx r0,r7,r3 -3: mtcrf 0x01,r5 +3: PPC_MTOCRF 0x01,r5 add r4,r6,r4 add r3,r6,r3 b .Ldst_aligned diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 7e8ded051b5..4aae0c38764 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -54,7 +54,7 @@ static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs) */ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) { - unsigned int opcode, rd; + unsigned int opcode, rs, rb, rd, spr; unsigned long int imm; opcode = instr >> 26; @@ -152,6 +152,49 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) regs->nip &= 0xffffffffUL; return 1; #endif + case 0x26: /* mfcr */ + regs->gpr[rd] = regs->ccr; + regs->gpr[rd] &= 0xffffffffUL; + goto mtspr_out; + case 0x2a6: /* mfspr */ + spr = (instr >> 11) & 0x3ff; + switch (spr) { + case 0x20: /* mfxer */ + regs->gpr[rd] = regs->xer; + regs->gpr[rd] &= 0xffffffffUL; + goto mtspr_out; + case 0x100: /* mflr */ + regs->gpr[rd] = regs->link; + goto mtspr_out; + case 0x120: /* mfctr */ + regs->gpr[rd] = regs->ctr; + goto mtspr_out; + } + break; + case 0x378: /* orx */ + rs = (instr >> 21) & 0x1f; + rb = (instr >> 11) & 0x1f; + if (rs == rb) { /* mr */ + rd = (instr >> 16) & 0x1f; + regs->gpr[rd] = regs->gpr[rs]; + goto mtspr_out; + } + break; + case 0x3a6: /* mtspr */ + spr = (instr >> 11) & 0x3ff; + switch (spr) { + case 0x20: /* mtxer */ + regs->xer = (regs->gpr[rd] & 0xffffffffUL); + goto mtspr_out; + case 0x100: /* mtlr */ + regs->link = regs->gpr[rd]; + goto mtspr_out; + case 0x120: /* mtctr */ + regs->ctr = regs->gpr[rd]; +mtspr_out: + regs->nip += 4; + return 1; + } } } return 0; diff --git a/arch/powerpc/lib/strcase.c b/arch/powerpc/lib/strcase.c deleted file mode 100644 index f8ec1eba3fd..00000000000 --- a/arch/powerpc/lib/strcase.c +++ /dev/null @@ -1,25 +0,0 @@ -#include <linux/types.h> -#include <linux/ctype.h> -#include <linux/string.h> - -int strcasecmp(const char *s1, const char *s2) -{ - int c1, c2; - - do { - c1 = tolower(*s1++); - c2 = tolower(*s2++); - } while (c1 == c2 && c1 != 0); - return c1 - c2; -} - -int strncasecmp(const char *s1, const char *s2, size_t n) -{ - int c1, c2; - - do { - c1 = tolower(*s1++); - c2 = tolower(*s2++); - } while ((--n > 0) && c1 == c2 && c1 != 0); - return c1 - c2; -} diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S index bd68df5fa78..ddceefc06ec 100644 --- a/arch/powerpc/mm/hash_low_32.S +++ b/arch/powerpc/mm/hash_low_32.S @@ -283,6 +283,7 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64) #define PTEG_SIZE 64 #define LG_PTEG_SIZE 6 #define LDPTEu lwzu +#define LDPTE lwz #define STPTE stw #define CMPPTE cmpw #define PTE_H 0x40 @@ -389,13 +390,30 @@ _GLOBAL(hash_page_patch_C) * and we know there is a definite (although small) speed * advantage to putting the PTE in the primary PTEG, we always * put the PTE in the primary PTEG. + * + * In addition, we skip any slot that is mapping kernel text in + * order to avoid a deadlock when not using BAT mappings if + * trying to hash in the kernel hash code itself after it has + * already taken the hash table lock. This works in conjunction + * with pre-faulting of the kernel text. + * + * If the hash table bucket is full of kernel text entries, we'll + * lockup here but that shouldn't happen */ - addis r4,r7,next_slot@ha + +1: addis r4,r7,next_slot@ha /* get next evict slot */ lwz r6,next_slot@l(r4) - addi r6,r6,PTE_SIZE + addi r6,r6,PTE_SIZE /* search for candidate */ andi. r6,r6,7*PTE_SIZE stw r6,next_slot@l(r4) add r4,r3,r6 + LDPTE r0,PTE_SIZE/2(r4) /* get PTE second word */ + clrrwi r0,r0,12 + lis r6,etext@h + ori r6,r6,etext@l /* get etext */ + tophys(r6,r6) + cmpl cr0,r0,r6 /* compare and try again */ + blt 1b #ifndef CONFIG_SMP /* Store PTE in PTEG */ diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index 9bc0a9c2b9b..e64ce3eec36 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -445,9 +445,12 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) htab_insert_pte: /* real page number in r5, PTE RPN value + index */ - rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + andis. r0,r31,_PAGE_4K_PFN@h + srdi r5,r31,PTE_RPN_SHIFT + bne- htab_special_pfn sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT add r5,r5,r25 +htab_special_pfn: sldi r5,r5,HW_PAGE_SHIFT /* Calculate primary group hash */ diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 6f1016acdbf..79aedaf36f2 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -505,7 +505,7 @@ static inline int tlb_batching_enabled(void) int enabled = 1; if (root) { - const char *model = get_property(root, "model", NULL); + const char *model = of_get_property(root, "model", NULL); if (model && !strcmp(model, "IBM,9076-N81")) enabled = 0; of_node_put(root); diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 3c7fe2c65b5..49618461def 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -100,6 +100,11 @@ unsigned int HPAGE_SHIFT; #ifdef CONFIG_PPC_64K_PAGES int mmu_ci_restrictions; #endif +#ifdef CONFIG_DEBUG_PAGEALLOC +static u8 *linear_map_hash_slots; +static unsigned long linear_map_hash_count; +static spinlock_t linear_map_hash_lock; +#endif /* CONFIG_DEBUG_PAGEALLOC */ /* There are definitions of page sizes arrays to be used when none * is provided by the firmware. @@ -152,11 +157,10 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, for (vaddr = vstart, paddr = pstart; vaddr < vend; vaddr += step, paddr += step) { - unsigned long vpn, hash, hpteg; + unsigned long hash, hpteg; unsigned long vsid = get_kernel_vsid(vaddr); unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff); - vpn = va >> shift; tmp_mode = mode; /* Make non-kernel text non-executable */ @@ -174,6 +178,10 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, if (ret < 0) break; +#ifdef CONFIG_DEBUG_PAGEALLOC + if ((paddr >> PAGE_SHIFT) < linear_map_hash_count) + linear_map_hash_slots[paddr >> PAGE_SHIFT] = ret | 0x80; +#endif /* CONFIG_DEBUG_PAGEALLOC */ } return ret < 0 ? ret : 0; } @@ -281,6 +289,7 @@ static void __init htab_init_page_sizes(void) memcpy(mmu_psize_defs, mmu_psize_defaults_gp, sizeof(mmu_psize_defaults_gp)); found: +#ifndef CONFIG_DEBUG_PAGEALLOC /* * Pick a size for the linear mapping. Currently, we only support * 16M, 1M and 4K which is the default @@ -289,6 +298,7 @@ static void __init htab_init_page_sizes(void) mmu_linear_psize = MMU_PAGE_16M; else if (mmu_psize_defs[MMU_PAGE_1M].shift) mmu_linear_psize = MMU_PAGE_1M; +#endif /* CONFIG_DEBUG_PAGEALLOC */ #ifdef CONFIG_PPC_64K_PAGES /* @@ -303,12 +313,14 @@ static void __init htab_init_page_sizes(void) if (mmu_psize_defs[MMU_PAGE_64K].shift) { mmu_virtual_psize = MMU_PAGE_64K; mmu_vmalloc_psize = MMU_PAGE_64K; + if (mmu_linear_psize == MMU_PAGE_4K) + mmu_linear_psize = MMU_PAGE_64K; if (cpu_has_feature(CPU_FTR_CI_LARGE_PAGE)) mmu_io_psize = MMU_PAGE_64K; else mmu_ci_restrictions = 1; } -#endif +#endif /* CONFIG_PPC_64K_PAGES */ printk(KERN_DEBUG "Page orders: linear mapping = %d, " "virtual = %d, io = %d\n", @@ -476,6 +488,13 @@ void __init htab_initialize(void) mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; +#ifdef CONFIG_DEBUG_PAGEALLOC + linear_map_hash_count = lmb_end_of_DRAM() >> PAGE_SHIFT; + linear_map_hash_slots = __va(lmb_alloc_base(linear_map_hash_count, + 1, lmb.rmo_size)); + memset(linear_map_hash_slots, 0, linear_map_hash_count); +#endif /* CONFIG_DEBUG_PAGEALLOC */ + /* On U3 based machines, we need to reserve the DART area and * _NOT_ map it to avoid cache paradoxes as it's remapped non * cacheable later on @@ -573,6 +592,27 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) return pp; } +/* + * Demote a segment to using 4k pages. + * For now this makes the whole process use 4k pages. + */ +void demote_segment_4k(struct mm_struct *mm, unsigned long addr) +{ +#ifdef CONFIG_PPC_64K_PAGES + if (mm->context.user_psize == MMU_PAGE_4K) + return; + mm->context.user_psize = MMU_PAGE_4K; + mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp; + get_paca()->context = mm->context; + slb_flush_and_rebolt(); +#ifdef CONFIG_SPE_BASE + spu_flush_all_slbs(mm); +#endif +#endif +} + +EXPORT_SYMBOL_GPL(demote_segment_4k); + /* Result code is: * 0 - handled * 1 - normal page fault @@ -665,15 +705,19 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) #ifndef CONFIG_PPC_64K_PAGES rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); #else + /* If _PAGE_4K_PFN is set, make sure this is a 4k segment */ + if (pte_val(*ptep) & _PAGE_4K_PFN) { + demote_segment_4k(mm, ea); + psize = MMU_PAGE_4K; + } + if (mmu_ci_restrictions) { /* If this PTE is non-cacheable, switch to 4k */ if (psize == MMU_PAGE_64K && (pte_val(*ptep) & _PAGE_NO_CACHE)) { if (user_region) { + demote_segment_4k(mm, ea); psize = MMU_PAGE_4K; - mm->context.user_psize = MMU_PAGE_4K; - mm->context.sllp = SLB_VSID_USER | - mmu_psize_defs[MMU_PAGE_4K].sllp; } else if (ea < VMALLOC_END) { /* * some driver did a non-cacheable mapping @@ -756,16 +800,8 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, if (mmu_ci_restrictions) { /* If this PTE is non-cacheable, switch to 4k */ if (mm->context.user_psize == MMU_PAGE_64K && - (pte_val(*ptep) & _PAGE_NO_CACHE)) { - mm->context.user_psize = MMU_PAGE_4K; - mm->context.sllp = SLB_VSID_USER | - mmu_psize_defs[MMU_PAGE_4K].sllp; - get_paca()->context = mm->context; - slb_flush_and_rebolt(); -#ifdef CONFIG_SPE_BASE - spu_flush_all_slbs(mm); -#endif - } + (pte_val(*ptep) & _PAGE_NO_CACHE)) + demote_segment_4k(mm, ea); } if (mm->context.user_psize == MMU_PAGE_64K) __hash_page_64K(ea, access, vsid, ptep, trap, local); @@ -825,3 +861,62 @@ void low_hash_fault(struct pt_regs *regs, unsigned long address) } bad_page_fault(regs, address, SIGBUS); } + +#ifdef CONFIG_DEBUG_PAGEALLOC +static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi) +{ + unsigned long hash, hpteg, vsid = get_kernel_vsid(vaddr); + unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff); + unsigned long mode = _PAGE_ACCESSED | _PAGE_DIRTY | + _PAGE_COHERENT | PP_RWXX | HPTE_R_N; + int ret; + + hash = hpt_hash(va, PAGE_SHIFT); + hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); + + ret = ppc_md.hpte_insert(hpteg, va, __pa(vaddr), + mode, HPTE_V_BOLTED, mmu_linear_psize); + BUG_ON (ret < 0); + spin_lock(&linear_map_hash_lock); + BUG_ON(linear_map_hash_slots[lmi] & 0x80); + linear_map_hash_slots[lmi] = ret | 0x80; + spin_unlock(&linear_map_hash_lock); +} + +static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi) +{ + unsigned long hash, hidx, slot, vsid = get_kernel_vsid(vaddr); + unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff); + + hash = hpt_hash(va, PAGE_SHIFT); + spin_lock(&linear_map_hash_lock); + BUG_ON(!(linear_map_hash_slots[lmi] & 0x80)); + hidx = linear_map_hash_slots[lmi] & 0x7f; + linear_map_hash_slots[lmi] = 0; + spin_unlock(&linear_map_hash_lock); + if (hidx & _PTEIDX_SECONDARY) + hash = ~hash; + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; + slot += hidx & _PTEIDX_GROUP_IX; + ppc_md.hpte_invalidate(slot, va, mmu_linear_psize, 0); +} + +void kernel_map_pages(struct page *page, int numpages, int enable) +{ + unsigned long flags, vaddr, lmi; + int i; + + local_irq_save(flags); + for (i = 0; i < numpages; i++, page++) { + vaddr = (unsigned long)page_address(page); + lmi = __pa(vaddr) >> PAGE_SHIFT; + if (lmi >= linear_map_hash_count) + continue; + if (enable) + kernel_map_linear_page(vaddr, lmi); + else + kernel_unmap_linear_page(vaddr, lmi); + } + local_irq_restore(flags); +} +#endif /* CONFIG_DEBUG_PAGEALLOC */ diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index f6ffaaa7a5b..8508f973d9c 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -316,12 +316,11 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, { if (pte_present(*ptep)) { /* We open-code pte_clear because we need to pass the right - * argument to hpte_update (huge / !huge) + * argument to hpte_need_flush (huge / !huge). Might not be + * necessary anymore if we make hpte_need_flush() get the + * page size from the slices */ - unsigned long old = pte_update(ptep, ~0UL); - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1); - flush_tlb_pending(); + pte_update(mm, addr & HPAGE_MASK, ptep, ~0UL, 1); } *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); } @@ -329,12 +328,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - unsigned long old = pte_update(ptep, ~0UL); - - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1); - *ptep = __pte(0); - + unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1); return __pte(old); } diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 0e53ca8f02f..5fce6ccecb8 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c @@ -115,6 +115,10 @@ void MMU_setup(void) if (strstr(cmd_line, "noltlbs")) { __map_without_ltlbs = 1; } +#ifdef CONFIG_DEBUG_PAGEALLOC + __map_without_bats = 1; + __map_without_ltlbs = 1; +#endif } /* diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index 716a2906a24..e3a1e8dc536 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -146,6 +146,10 @@ static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long rgnbase = rgn->region[i].base; unsigned long rgnsize = rgn->region[i].size; + if ((rgnbase == base) && (rgnsize == size)) + /* Already have this region, so we're done */ + return 0; + adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); if ( adjacent > 0 ) { rgn->region[i].base -= size; diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 52f397c108a..c4bcd754642 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -58,9 +58,6 @@ int init_bootmem_done; int mem_init_done; unsigned long memory_limit; -extern void hash_preload(struct mm_struct *mm, unsigned long ea, - unsigned long access, unsigned long trap); - int page_is_ram(unsigned long pfn) { unsigned long paddr = (pfn << PAGE_SHIFT); diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index bea2d21ac6f..9c4538bb04b 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h @@ -19,9 +19,14 @@ * 2 of the License, or (at your option) any later version. * */ +#include <linux/mm.h> #include <asm/tlbflush.h> #include <asm/mmu.h> +extern void hash_preload(struct mm_struct *mm, unsigned long ea, + unsigned long access, unsigned long trap); + + #ifdef CONFIG_PPC32 extern void mapin_ram(void); extern int map_page(unsigned long va, phys_addr_t pa, int flags); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index e86c37c82cf..b3a592b25ab 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -74,7 +74,7 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu) while ((cpu_node = of_find_node_by_type(cpu_node, "cpu")) != NULL) { /* Try interrupt server first */ - interrupt_server = get_property(cpu_node, + interrupt_server = of_get_property(cpu_node, "ibm,ppc-interrupt-server#s", &len); len = len / sizeof(u32); @@ -85,7 +85,7 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu) return cpu_node; } } else { - reg = get_property(cpu_node, "reg", &len); + reg = of_get_property(cpu_node, "reg", &len); if (reg && (len > 0) && (reg[0] == hw_cpuid)) return cpu_node; } @@ -97,7 +97,7 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu) /* must hold reference to node during call */ static const int *of_get_associativity(struct device_node *dev) { - return get_property(dev, "ibm,associativity", NULL); + return of_get_property(dev, "ibm,associativity", NULL); } /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa @@ -179,7 +179,7 @@ static int __init find_min_common_depth(void) * configuration (should be all 0's) and the second is for a normal * NUMA configuration. */ - ref_points = get_property(rtas_root, + ref_points = of_get_property(rtas_root, "ibm,associativity-reference-points", &len); if ((len >= 1) && ref_points) { @@ -201,8 +201,8 @@ static void __init get_n_mem_cells(int *n_addr_cells, int *n_size_cells) if (!memory) panic("numa.c: No memory nodes found!"); - *n_addr_cells = prom_n_addr_cells(memory); - *n_size_cells = prom_n_size_cells(memory); + *n_addr_cells = of_n_addr_cells(memory); + *n_size_cells = of_n_size_cells(memory); of_node_put(memory); } @@ -308,9 +308,9 @@ static void __init parse_drconf_memory(struct device_node *memory) int nid, default_nid = 0; unsigned int start, ai, flags; - lm = get_property(memory, "ibm,lmb-size", &ls); - dm = get_property(memory, "ibm,dynamic-memory", &ld); - aa = get_property(memory, "ibm,associativity-lookup-arrays", &la); + lm = of_get_property(memory, "ibm,lmb-size", &ls); + dm = of_get_property(memory, "ibm,dynamic-memory", &ld); + aa = of_get_property(memory, "ibm,associativity-lookup-arrays", &la); if (!lm || !dm || !aa || ls < sizeof(unsigned int) || ld < sizeof(unsigned int) || la < 2 * sizeof(unsigned int)) @@ -404,10 +404,10 @@ static int __init parse_numa_properties(void) const unsigned int *memcell_buf; unsigned int len; - memcell_buf = get_property(memory, + memcell_buf = of_get_property(memory, "linux,usable-memory", &len); if (!memcell_buf || len <= 0) - memcell_buf = get_property(memory, "reg", &len); + memcell_buf = of_get_property(memory, "reg", &len); if (!memcell_buf || len <= 0) continue; @@ -725,7 +725,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr) const unsigned int *memcell_buf; unsigned int len; - memcell_buf = get_property(memory, "reg", &len); + memcell_buf = of_get_property(memory, "reg", &len); if (!memcell_buf || len <= 0) continue; diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index c284bdac994..bca56037492 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -183,8 +183,8 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) * mem_init() sets high_memory so only do the check after that. */ if (mem_init_done && (p < virt_to_phys(high_memory))) { - printk("__ioremap(): phys addr "PHYS_FMT" is RAM lr %p\n", p, - __builtin_return_address(0)); + printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n", + (unsigned long long)p, __builtin_return_address(0)); return NULL; } @@ -266,9 +266,12 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) pg = pte_alloc_kernel(pd, va); if (pg != 0) { err = 0; - set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags))); - if (mem_init_done) - flush_HPTE(0, va, pmd_val(*pd)); + /* The PTE should never be already set nor present in the + * hash table + */ + BUG_ON(pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE)); + set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, + __pgprot(flags))); } return err; } @@ -279,16 +282,19 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) void __init mapin_ram(void) { unsigned long v, p, s, f; + int ktext; s = mmu_mapin_ram(); v = KERNELBASE + s; p = PPC_MEMSTART + s; for (; s < total_lowmem; s += PAGE_SIZE) { - if ((char *) v >= _stext && (char *) v < etext) - f = _PAGE_RAM_TEXT; - else - f = _PAGE_RAM; + ktext = ((char *) v >= _stext && (char *) v < etext); + f = ktext ?_PAGE_RAM_TEXT : _PAGE_RAM; map_page(v, p, f); +#ifdef CONFIG_PPC_STD_MMU_32 + if (ktext) + hash_preload(&init_mm, v, 0, 0x300); +#endif v += PAGE_SIZE; p += PAGE_SIZE; } @@ -445,3 +451,55 @@ exit: return ret; } +#ifdef CONFIG_DEBUG_PAGEALLOC + +static int __change_page_attr(struct page *page, pgprot_t prot) +{ + pte_t *kpte; + pmd_t *kpmd; + unsigned long address; + + BUG_ON(PageHighMem(page)); + address = (unsigned long)page_address(page); + + if (v_mapped_by_bats(address) || v_mapped_by_tlbcam(address)) + return 0; + if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) + return -EINVAL; + set_pte_at(&init_mm, address, kpte, mk_pte(page, prot)); + wmb(); + flush_HPTE(0, address, pmd_val(*kpmd)); + pte_unmap(kpte); + + return 0; +} + +/* + * Change the page attributes of an page in the linear mapping. + * + * THIS CONFLICTS WITH BAT MAPPINGS, DEBUG USE ONLY + */ +static int change_page_attr(struct page *page, int numpages, pgprot_t prot) +{ + int i, err = 0; + unsigned long flags; + + local_irq_save(flags); + for (i = 0; i < numpages; i++, page++) { + err = __change_page_attr(page, prot); + if (err) + break; + } + local_irq_restore(flags); + return err; +} + + +void kernel_map_pages(struct page *page, int numpages, int enable) +{ + if (PageHighMem(page)) + return; + + change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0)); +} +#endif /* CONFIG_DEBUG_PAGEALLOC */ diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index 7cceb2c44cb..05066674a7a 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -85,8 +85,10 @@ unsigned long __init mmu_mapin_ram(void) unsigned long max_size = (256<<20); unsigned long align; - if (__map_without_bats) + if (__map_without_bats) { + printk(KERN_DEBUG "RAM mapped without BATs\n"); return 0; + } /* Set up BAT2 and if necessary BAT3 to cover RAM. */ diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index b58baa65c4a..fd8d08c325e 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -120,17 +120,20 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) } /* - * Update the MMU hash table to correspond with a change to - * a Linux PTE. If wrprot is true, it is permissible to - * change the existing HPTE to read-only rather than removing it - * (if we remove it we should clear the _PTE_HPTEFLAGS bits). + * A linux PTE was changed and the corresponding hash table entry + * neesd to be flushed. This function will either perform the flush + * immediately or will batch it up if the current CPU has an active + * batch on it. + * + * Must be called from within some kind of spinlock/non-preempt region... */ -void hpte_update(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, unsigned long pte, int huge) +void hpte_need_flush(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, unsigned long pte, int huge) { struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); - unsigned long vsid; + unsigned long vsid, vaddr; unsigned int psize; + real_pte_t rpte; int i; i = batch->index; @@ -151,6 +154,26 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, } else psize = pte_pagesize_index(pte); + /* Build full vaddr */ + if (!is_kernel_addr(addr)) { + vsid = get_vsid(mm->context.id, addr); + WARN_ON(vsid == 0); + } else + vsid = get_kernel_vsid(addr); + vaddr = (vsid << 28 ) | (addr & 0x0fffffff); + rpte = __real_pte(__pte(pte), ptep); + + /* + * Check if we have an active batch on this CPU. If not, just + * flush now and return. For now, we don global invalidates + * in that case, might be worth testing the mm cpu mask though + * and decide to use local invalidates instead... + */ + if (!batch->active) { + flush_hash_page(vaddr, rpte, psize, 0); + return; + } + /* * This can happen when we are in the middle of a TLB batch and * we encounter memory pressure (eg copy_page_range when it tries @@ -162,47 +185,42 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, * batch */ if (i != 0 && (mm != batch->mm || batch->psize != psize)) { - flush_tlb_pending(); + __flush_tlb_pending(batch); i = 0; } if (i == 0) { batch->mm = mm; batch->psize = psize; } - if (!is_kernel_addr(addr)) { - vsid = get_vsid(mm->context.id, addr); - WARN_ON(vsid == 0); - } else - vsid = get_kernel_vsid(addr); - batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff); - batch->pte[i] = __real_pte(__pte(pte), ptep); + batch->pte[i] = rpte; + batch->vaddr[i] = vaddr; batch->index = ++i; if (i >= PPC64_TLB_BATCH_NR) - flush_tlb_pending(); + __flush_tlb_pending(batch); } +/* + * This function is called when terminating an mmu batch or when a batch + * is full. It will perform the flush of all the entries currently stored + * in a batch. + * + * Must be called from within some kind of spinlock/non-preempt region... + */ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) { - int i; - int cpu; cpumask_t tmp; - int local = 0; + int i, local = 0; - BUG_ON(in_interrupt()); - - cpu = get_cpu(); i = batch->index; - tmp = cpumask_of_cpu(cpu); + tmp = cpumask_of_cpu(smp_processor_id()); if (cpus_equal(batch->mm->cpu_vm_mask, tmp)) local = 1; - if (i == 1) flush_hash_page(batch->vaddr[0], batch->pte[0], batch->psize, local); else flush_hash_range(i, local); batch->index = 0; - put_cpu(); } void pte_free_finish(void) diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 4ccef2d5530..4b5f9528218 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile @@ -12,6 +12,6 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ oprofile-y := $(DRIVER_OBJS) common.o backtrace.o oprofile-$(CONFIG_PPC_CELL_NATIVE) += op_model_cell.o -oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o +oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o oprofile-$(CONFIG_6xx) += op_model_7450.o diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index fbd62eacfdf..1a7ef7e246d 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -160,6 +160,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case PPC_OPROFILE_POWER4: model = &op_model_power4; break; + case PPC_OPROFILE_PA6T: + model = &op_model_pa6t; + break; #endif #ifdef CONFIG_6xx case PPC_OPROFILE_G4: diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c index e08e1d7b3dc..626b29f3830 100644 --- a/arch/powerpc/oprofile/op_model_cell.c +++ b/arch/powerpc/oprofile/op_model_cell.c @@ -37,6 +37,7 @@ #include <asm/system.h> #include "../platforms/cell/interrupt.h" +#include "../platforms/cell/cbe_regs.h" #define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */ #define PPU_CYCLES_GRP_NUM 1 /* special group number for identifying @@ -130,7 +131,7 @@ static int pm_rtas_token; static u32 reset_value[NR_PHYS_CTRS]; static int num_counters; static int oprofile_running; -static spinlock_t virt_cntr_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(virt_cntr_lock); static u32 ctr_enabled; diff --git a/arch/powerpc/oprofile/op_model_pa6t.c b/arch/powerpc/oprofile/op_model_pa6t.c new file mode 100644 index 00000000000..e8a56b0adad --- /dev/null +++ b/arch/powerpc/oprofile/op_model_pa6t.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2006-2007 PA Semi, Inc + * + * Author: Shashi Rao, PA Semi + * + * Maintained by: Olof Johansson <olof@lixom.net> + * + * Based on arch/powerpc/oprofile/op_model_power4.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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/oprofile.h> +#include <linux/init.h> +#include <linux/smp.h> +#include <linux/percpu.h> +#include <asm/processor.h> +#include <asm/cputable.h> +#include <asm/oprofile_impl.h> +#include <asm/reg.h> + +static unsigned char oprofile_running; + +/* mmcr values are set in pa6t_reg_setup, used in pa6t_cpu_setup */ +static u64 mmcr0_val; +static u64 mmcr1_val; + +/* inited in pa6t_reg_setup */ +static u64 reset_value[OP_MAX_COUNTER]; + +static inline u64 ctr_read(unsigned int i) +{ + switch (i) { + case 0: + return mfspr(SPRN_PA6T_PMC0); + case 1: + return mfspr(SPRN_PA6T_PMC1); + case 2: + return mfspr(SPRN_PA6T_PMC2); + case 3: + return mfspr(SPRN_PA6T_PMC3); + case 4: + return mfspr(SPRN_PA6T_PMC4); + case 5: + return mfspr(SPRN_PA6T_PMC5); + default: + printk(KERN_ERR "ctr_read called with bad arg %u\n", i); + return 0; + } +} + +static inline void ctr_write(unsigned int i, u64 val) +{ + switch (i) { + case 0: + mtspr(SPRN_PA6T_PMC0, val); + break; + case 1: + mtspr(SPRN_PA6T_PMC1, val); + break; + case 2: + mtspr(SPRN_PA6T_PMC2, val); + break; + case 3: + mtspr(SPRN_PA6T_PMC3, val); + break; + case 4: + mtspr(SPRN_PA6T_PMC4, val); + break; + case 5: + mtspr(SPRN_PA6T_PMC5, val); + break; + default: + printk(KERN_ERR "ctr_write called with bad arg %u\n", i); + break; + } +} + + +/* precompute the values to stuff in the hardware registers */ +static void pa6t_reg_setup(struct op_counter_config *ctr, + struct op_system_config *sys, + int num_ctrs) +{ + int pmc; + + /* + * adjust the mmcr0.en[0-5] and mmcr0.inten[0-5] values obtained from the + * event_mappings file by turning off the counters that the user doesn't + * care about + * + * setup user and kernel profiling + */ + for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++) + if (!ctr[pmc].enabled) { + sys->mmcr0 &= ~(0x1UL << pmc); + sys->mmcr0 &= ~(0x1UL << (pmc+12)); + pr_debug("turned off counter %u\n", pmc); + } + + if (sys->enable_kernel) + sys->mmcr0 |= PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN; + else + sys->mmcr0 &= ~(PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN); + + if (sys->enable_user) + sys->mmcr0 |= PA6T_MMCR0_PREN; + else + sys->mmcr0 &= ~PA6T_MMCR0_PREN; + + /* + * The performance counter event settings are given in the mmcr0 and + * mmcr1 values passed from the user in the op_system_config + * structure (sys variable). + */ + mmcr0_val = sys->mmcr0; + mmcr1_val = sys->mmcr1; + pr_debug("mmcr0_val inited to %016lx\n", sys->mmcr0); + pr_debug("mmcr1_val inited to %016lx\n", sys->mmcr1); + + for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++) { + /* counters are 40 bit. Move to cputable at some point? */ + reset_value[pmc] = (0x1UL << 39) - ctr[pmc].count; + pr_debug("reset_value for pmc%u inited to 0x%lx\n", + pmc, reset_value[pmc]); + } +} + +/* configure registers on this cpu */ +static void pa6t_cpu_setup(struct op_counter_config *ctr) +{ + u64 mmcr0 = mmcr0_val; + u64 mmcr1 = mmcr1_val; + + /* Default is all PMCs off */ + mmcr0 &= ~(0x3FUL); + mtspr(SPRN_PA6T_MMCR0, mmcr0); + + /* program selected programmable events in */ + mtspr(SPRN_PA6T_MMCR1, mmcr1); + + pr_debug("setup on cpu %d, mmcr0 %016lx\n", smp_processor_id(), + mfspr(SPRN_PA6T_MMCR0)); + pr_debug("setup on cpu %d, mmcr1 %016lx\n", smp_processor_id(), + mfspr(SPRN_PA6T_MMCR1)); +} + +static void pa6t_start(struct op_counter_config *ctr) +{ + int i; + + /* Hold off event counting until rfid */ + u64 mmcr0 = mmcr0_val | PA6T_MMCR0_HANDDIS; + + for (i = 0; i < cur_cpu_spec->num_pmcs; i++) + if (ctr[i].enabled) + ctr_write(i, reset_value[i]); + else + ctr_write(i, 0UL); + + mtspr(SPRN_PA6T_MMCR0, mmcr0); + + oprofile_running = 1; + + pr_debug("start on cpu %d, mmcr0 %lx\n", smp_processor_id(), mmcr0); +} + +static void pa6t_stop(void) +{ + u64 mmcr0; + + /* freeze counters */ + mmcr0 = mfspr(SPRN_PA6T_MMCR0); + mmcr0 |= PA6T_MMCR0_FCM0; + mtspr(SPRN_PA6T_MMCR0, mmcr0); + + oprofile_running = 0; + + pr_debug("stop on cpu %d, mmcr0 %lx\n", smp_processor_id(), mmcr0); +} + +/* handle the perfmon overflow vector */ +static void pa6t_handle_interrupt(struct pt_regs *regs, + struct op_counter_config *ctr) +{ + unsigned long pc = mfspr(SPRN_PA6T_SIAR); + int is_kernel = is_kernel_addr(pc); + u64 val; + int i; + u64 mmcr0; + + /* disable perfmon counting until rfid */ + mmcr0 = mfspr(SPRN_PA6T_MMCR0); + mtspr(SPRN_PA6T_MMCR0, mmcr0 | PA6T_MMCR0_HANDDIS); + + /* Record samples. We've got one global bit for whether a sample + * was taken, so add it for any counter that triggered overflow. + */ + for (i = 0; i < cur_cpu_spec->num_pmcs; i++) { + val = ctr_read(i); + if (val & (0x1UL << 39)) { /* Overflow bit set */ + if (oprofile_running && ctr[i].enabled) { + if (mmcr0 & PA6T_MMCR0_SIARLOG) + oprofile_add_ext_sample(pc, regs, i, is_kernel); + ctr_write(i, reset_value[i]); + } else { + ctr_write(i, 0UL); + } + } + } + + /* Restore mmcr0 to a good known value since the PMI changes it */ + mmcr0 = mmcr0_val | PA6T_MMCR0_HANDDIS; + mtspr(SPRN_PA6T_MMCR0, mmcr0); +} + +struct op_powerpc_model op_model_pa6t = { + .reg_setup = pa6t_reg_setup, + .cpu_setup = pa6t_cpu_setup, + .start = pa6t_start, + .stop = pa6t_stop, + .handle_interrupt = pa6t_handle_interrupt, +}; diff --git a/arch/powerpc/platforms/4xx/Kconfig b/arch/powerpc/platforms/4xx/Kconfig index 2f2a13ed766..ded357c1741 100644 --- a/arch/powerpc/platforms/4xx/Kconfig +++ b/arch/powerpc/platforms/4xx/Kconfig @@ -3,278 +3,206 @@ config 4xx depends on 40x || 44x default y -config WANT_EARLY_SERIAL +config BOOKE bool - select SERIAL_8250 - default n - -menu "AMCC 4xx options" - depends on 4xx - -choice - prompt "Machine Type" - depends on 40x - default WALNUT - -config BUBINGA - bool "Bubinga" - select WANT_EARLY_SERIAL - help - This option enables support for the IBM 405EP evaluation board. - -config CPCI405 - bool "CPCI405" - help - This option enables support for the CPCI405 board. - -config EP405 - bool "EP405/EP405PC" - help - This option enables support for the EP405/EP405PC boards. - -config REDWOOD_5 - bool "Redwood-5" - help - This option enables support for the IBM STB04 evaluation board. - -config REDWOOD_6 - bool "Redwood-6" - help - This option enables support for the IBM STBx25xx evaluation board. - -config SYCAMORE - bool "Sycamore" - help - This option enables support for the IBM PPC405GPr evaluation board. - -config WALNUT - bool "Walnut" - help - This option enables support for the IBM PPC405GP evaluation board. - -config XILINX_ML300 - bool "Xilinx-ML300" - help - This option enables support for the Xilinx ML300 evaluation board. - -endchoice - -choice - prompt "Machine Type" depends on 44x - default EBONY - -config BAMBOO - bool "Bamboo" - select WANT_EARLY_SERIAL - help - This option enables support for the IBM PPC440EP evaluation board. - -config EBONY - bool "Ebony" - select WANT_EARLY_SERIAL - help - This option enables support for the IBM PPC440GP evaluation board. - -config LUAN - bool "Luan" - select WANT_EARLY_SERIAL - help - This option enables support for the IBM PPC440SP evaluation board. - -config OCOTEA - bool "Ocotea" - select WANT_EARLY_SERIAL - help - This option enables support for the IBM PPC440GX evaluation board. + default y -endchoice +menu "AMCC 40x options" + depends on 40x -config EP405PC - bool "EP405PC Support" - depends on EP405 +#config BUBINGA +# bool "Bubinga" +# depends on 40x +# default n +# select 405EP +# help +# This option enables support for the IBM 405EP evaluation board. + +#config CPCI405 +# bool "CPCI405" +# depends on 40x +# default n +# select 405GP +# help +# This option enables support for the CPCI405 board. + +#config EP405 +# bool "EP405/EP405PC" +# depends on 40x +# default n +# select 405GP +# help +# This option enables support for the EP405/EP405PC boards. + +#config EP405PC +# bool "EP405PC Support" +# depends on EP405 +# default y +# help +# This option enables support for the extra features of the EP405PC board. + +#config REDWOOD_5 +# bool "Redwood-5" +# depends on 40x +# default n +# select STB03xxx +# help +# This option enables support for the IBM STB04 evaluation board. + +#config REDWOOD_6 +# bool "Redwood-6" +# depends on 40x +# default n +# select STB03xxx +# help +# This option enables support for the IBM STBx25xx evaluation board. + +#config SYCAMORE +# bool "Sycamore" +# depends on 40x +# default n +# select 405GPR +# help +# This option enables support for the IBM PPC405GPr evaluation board. + +#config WALNUT +# bool "Walnut" +# depends on 40x +# default y +# select 405GP +# help +# This option enables support for the IBM PPC405GP evaluation board. + +#config XILINX_ML300 +# bool "Xilinx-ML300" +# depends on 40x +# default y +# select VIRTEX_II_PRO +# help +# This option enables support for the Xilinx ML300 evaluation board. +endmenu -# It's often necessary to know the specific 4xx processor type. -# Fortunately, it is impled (so far) from the board type, so we -# don't need to ask more redundant questions. +# 40x specific CPU modules, selected based on the board above. config NP405H bool - depends on ASH - default y + #depends on ASH -config 440EP +# OAK doesn't exist but wanted to keep this around for any future 403GCX boards +config 403GCX bool - depends on BAMBOO - select PPC_FPU - default y + #depends on OAK + select IBM405_ERR51 -config 440GP +config 405GP bool - depends on EBONY - default y + select IBM405_ERR77 + select IBM405_ERR51 -config 440GX +config 405EP bool - depends on OCOTEA - default y -config 440SP +config 405GPR bool - depends on LUAN - default y -config 440 +config VIRTEX_II_PRO bool - depends on 440GP || 440SP || 440EP - default y + select IBM405_ERR77 + select IBM405_ERR51 -config 440A +config STB03xxx bool - depends on 440GX - default y + select IBM405_ERR77 + select IBM405_ERR51 -config IBM440EP_ERR42 - bool - depends on 440EP - default y +# 40x errata/workaround config symbols, selected by the CPU models above # All 405-based cores up until the 405GPR and 405EP have this errata. config IBM405_ERR77 bool - depends on 40x && !403GCX && !405GPR && !405EP - default y # All 40x-based cores, up until the 405GPR and 405EP have this errata. config IBM405_ERR51 bool - depends on 40x && !405GPR && !405EP - default y -config BOOKE - bool +menu "AMCC 44x options" depends on 44x - default y - -config IBM_OCP - bool - depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT - default y -config XILINX_OCP - bool - depends on XILINX_ML300 - default y +#config BAMBOO +# bool "Bamboo" +# depends on 44x +# default n +# select 440EP +# help +# This option enables support for the IBM PPC440EP evaluation board. -config IBM_EMAC4 - bool - depends on 440GX || 440SP - default y - -config BIOS_FIXUP - bool - depends on BUBINGA || EP405 || SYCAMORE || WALNUT - default y - -# OAK doesn't exist but wanted to keep this around for any future 403GCX boards -config 403GCX - bool - depends on OAK - default y - -config 405EP - bool - depends on BUBINGA - default y - -config 405GP - bool - depends on CPCI405 || EP405 || WALNUT - default y - -config 405GPR - bool - depends on SYCAMORE +config EBONY + bool "Ebony" + depends on 44x default y + select 440GP + help + This option enables support for the IBM PPC440GP evaluation board. -config VIRTEX_II_PRO - bool - depends on XILINX_ML300 - default y +#config LUAN +# bool "Luan" +# depends on 44x +# default n +# select 440SP +# help +# This option enables support for the IBM PPC440SP evaluation board. + +#config OCOTEA +# bool "Ocotea" +# depends on 44x +# default n +# select 440GX +# help +# This option enables support for the IBM PPC440GX evaluation board. -config STB03xxx - bool - depends on REDWOOD_5 || REDWOOD_6 - default y +endmenu -config EMBEDDEDBOOT +# 44x specific CPU modules, selected based on the board above. +config 440EP bool - depends on EP405 || XILINX_ML300 - default y + select PPC_FPU + select IBM440EP_ERR42 -config IBM_OPENBIOS +config 440GP bool - depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT - default y + select IBM_NEW_EMAC_ZMII -config PPC4xx_DMA - bool "PPC4xx DMA controller support" - depends on 4xx - -config PPC4xx_EDMA +config 440GX bool - depends on !STB03xxx && PPC4xx_DMA - default y -config PPC_GEN550 +config 440SP bool - depends on 4xx - default y - -choice - prompt "TTYS0 device and default console" - depends on 40x - default UART0_TTYS0 - -config UART0_TTYS0 - bool "UART0" -config UART0_TTYS1 - bool "UART1" - -endchoice - -config SERIAL_SICC - bool "SICC Serial port support" - depends on STB03xxx - -config UART1_DFLT_CONSOLE +config 440A bool - depends on SERIAL_SICC && UART0_TTYS1 + depends on 440GX default y -config SERIAL_SICC_CONSOLE +# 44x errata/workaround config symbols, selected by the CPU models above +config IBM440EP_ERR42 bool - depends on SERIAL_SICC && UART0_TTYS1 - default y -endmenu +#config XILINX_OCP +# bool +# depends on XILINX_ML300 +# default y -menu "IBM 40x options" - depends on 40x - -config SERIAL_SICC - bool "SICC Serial port" - depends on STB03xxx - -config UART1_DFLT_CONSOLE - bool - depends on SERIAL_SICC && UART0_TTYS1 - default y +#config BIOS_FIXUP +# bool +# depends on BUBINGA || EP405 || SYCAMORE || WALNUT +# default y -config SERIAL_SICC_CONSOLE - bool - depends on SERIAL_SICC && UART0_TTYS1 - default y +#config PPC4xx_DMA +# bool "PPC4xx DMA controller support" +# depends on 4xx -endmenu +#config PPC4xx_EDMA +# bool +# depends on !STB03xxx && PPC4xx_DMA +# default y diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig new file mode 100644 index 00000000000..bc4aa4a80a1 --- /dev/null +++ b/arch/powerpc/platforms/52xx/Kconfig @@ -0,0 +1,35 @@ +config PPC_MPC52xx + bool + default n + +config PPC_MPC5200 + bool + select PPC_MPC52xx + default n + +config PPC_MPC5200_BUGFIX + bool "MPC5200 (L25R) bugfix support" + depends on PPC_MPC5200 + default n + help + Enable workarounds for original MPC5200 errata. This is not required + for MPC5200B based boards. + + It is safe to say 'Y' here + +config PPC_EFIKA + bool "bPlan Efika 5k2. MPC5200B based computer" + depends on PPC_MULTIPLATFORM && PPC32 + select PPC_RTAS + select RTAS_PROC + select PPC_MPC52xx + select PPC_NATIVE + default n + +config PPC_LITE5200 + bool "Freescale Lite5200 Eval Board" + depends on PPC_MULTIPLATFORM && PPC32 + select PPC_MPC5200 + default n + + diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 8de03411668..a6bba97314e 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c @@ -112,7 +112,7 @@ void __init efika_pcisetup(void) return; } - bus_range = get_property(pcictrl, "bus-range", &len); + bus_range = of_get_property(pcictrl, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING EFIKA_PLATFORM_NAME ": Can't get bus-range for %s\n", pcictrl->full_name); @@ -158,18 +158,17 @@ void __init efika_pcisetup(void) static void efika_show_cpuinfo(struct seq_file *m) { struct device_node *root; - const char *revision = NULL; - const char *codegendescription = NULL; - const char *codegenvendor = NULL; + const char *revision; + const char *codegendescription; + const char *codegenvendor; root = of_find_node_by_path("/"); if (!root) return; - revision = get_property(root, "revision", NULL); - codegendescription = - get_property(root, "CODEGEN,description", NULL); - codegenvendor = get_property(root, "CODEGEN,vendor", NULL); + revision = of_get_property(root, "revision", NULL); + codegendescription = of_get_property(root, "CODEGEN,description", NULL); + codegenvendor = of_get_property(root, "CODEGEN,vendor", NULL); if (codegendescription) seq_printf(m, "machine\t\t: %s\n", codegendescription); diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index cc3b40de21d..8e2646ac417 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c @@ -94,8 +94,8 @@ static void __init lite5200_setup_arch(void) np = of_find_node_by_type(NULL, "cpu"); if (np) { - unsigned int *fp = - (int *)get_property(np, "clock-frequency", NULL); + const unsigned int *fp = + of_get_property(np, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else @@ -108,9 +108,11 @@ static void __init lite5200_setup_arch(void) lite5200_setup_cpu(); /* Platorm specific */ #ifdef CONFIG_PCI - np = of_find_node_by_type(np, "pci"); - if (np) + np = of_find_node_by_type(NULL, "pci"); + if (np) { mpc52xx_add_bridge(np); + of_node_put(np); + } #endif #ifdef CONFIG_BLK_DEV_INITRD @@ -132,7 +134,7 @@ void lite5200_show_cpuinfo(struct seq_file *m) const char *model = NULL; if (np) - model = get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); seq_printf(m, "vendor\t\t: Freescale Semiconductor\n"); seq_printf(m, "machine\t\t: %s\n", model ? model : "unknown"); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index ed0cb694aea..2dd415ff55a 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -60,7 +60,7 @@ mpc52xx_find_ipb_freq(struct device_node *node) of_node_get(node); while (node) { - p_ipb_freq = get_property(node, "bus-frequency", NULL); + p_ipb_freq = of_get_property(node, "bus-frequency", NULL); if (p_ipb_freq) break; diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index faf161bdbc1..34d34a26d30 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c @@ -370,7 +370,7 @@ mpc52xx_add_bridge(struct device_node *node) return -EINVAL; } - bus_range = get_property(node, "bus-range", &len); + bus_range = of_get_property(node, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get %s bus-range, assume bus 0\n", node->full_name); diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig index 47d841ecf2e..de7fce9cb6e 100644 --- a/arch/powerpc/platforms/82xx/Kconfig +++ b/arch/powerpc/platforms/82xx/Kconfig @@ -1,21 +1,36 @@ -menu "Platform support" - depends on PPC_82xx - choice - prompt "Machine Type" - default MPC82xx_ADS + prompt "Machine Type" + depends on PPC_82xx + default MPC82xx_ADS config MPC82xx_ADS - bool "Freescale MPC82xx ADS" - select DEFAULT_UIMAGE - select PQ2ADS - select 8272 - select 8260 - select CPM2 - select FSL_SOC - help - This option enables support for the MPC8272 ADS board + bool "Freescale MPC82xx ADS" + select DEFAULT_UIMAGE + select PQ2ADS + select 8272 + select 8260 + select FSL_SOC + help + This option enables support for the MPC8272 ADS board endchoice -endmenu +config PQ2ADS + bool + default n + +config 8260 + bool + depends on 6xx + select CPM2 + help + The MPC8260 is a typical embedded CPU made by Freescale. Selecting + this option means that you wish to build a kernel for a machine with + an 8260 class CPU. + +config 8272 + bool + select 8260 + help + The MPC8272 CPM has a different internal dpram setup than other CPM2 + devices diff --git a/arch/powerpc/platforms/82xx/mpc82xx.c b/arch/powerpc/platforms/82xx/mpc82xx.c index 74e7892cdfc..cc9900d2e5e 100644 --- a/arch/powerpc/platforms/82xx/mpc82xx.c +++ b/arch/powerpc/platforms/82xx/mpc82xx.c @@ -55,17 +55,17 @@ static int __init get_freq(char *name, unsigned long *val) { struct device_node *cpu; - unsigned int *fp; + const unsigned int *fp; int found = 0; /* The cpu node should have timebase and clock frequency properties */ cpu = of_find_node_by_type(NULL, "cpu"); if (cpu) { - fp = (unsigned int *)get_property(cpu, name, NULL); + fp = of_get_property(cpu, name, NULL); if (fp) { found = 1; - *val = *fp++; + *val = *fp; } of_node_put(cpu); diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c index 7334c1a15b9..47cb09f0805 100644 --- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c +++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c @@ -456,7 +456,7 @@ void m82xx_pci_init_irq(void) iounmap(immap); return; } - irq_map = get_property(np, "interrupt-map", &size); + irq_map = of_get_property(np, "interrupt-map", &size); if ((!irq_map) || (size <= 7)) { printk(KERN_INFO "No interrupt-map property of pci node\n"); iounmap(immap); @@ -481,7 +481,7 @@ void m82xx_pci_init_irq(void) } pci_pic_node = of_node_get(np); /* PCI interrupt controller registers: status and mask */ - regs = get_property(np, "reg", &size); + regs = of_get_property(np, "reg", &size); if ((!regs) || (size <= 2)) { printk(KERN_INFO "No reg property in pci pic node\n"); iounmap(immap); @@ -521,20 +521,20 @@ void __init add_bridge(struct device_node *np) struct pci_controller *hose; struct resource r; const int *bus_range; - const void *ptr; + const uint *ptr; memset(&r, 0, sizeof(r)); if (of_address_to_resource(np, 0, &r)) { printk(KERN_INFO "No PCI reg property in device tree\n"); return; } - if (!(ptr = get_property(np, "clock-frequency", NULL))) { + if (!(ptr = of_get_property(np, "clock-frequency", NULL))) { printk(KERN_INFO "No clock-frequency property in PCI node"); return; } - pci_clk_frq = *(uint *) ptr; + pci_clk_frq = *ptr; of_node_put(np); - bus_range = get_property(np, "bus-range", &len); + bus_range = of_get_property(np, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", np->full_name); diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 713b31a16ce..19cafdf6df9 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -1,8 +1,6 @@ -menu "Platform support" - depends on PPC_83xx - choice prompt "Machine Type" + depends on PPC_83xx default MPC834x_MDS config MPC8313_RDB @@ -18,6 +16,13 @@ config MPC832x_MDS help This option enables support for the MPC832x MDS evaluation board. +config MPC832x_RDB + bool "Freescale MPC832x RDB" + select DEFAULT_UIMAGE + select QUICC_ENGINE + help + This option enables support for the MPC8323 RDB board. + config MPC834x_MDS bool "Freescale MPC834x MDS" select DEFAULT_UIMAGE @@ -57,7 +62,7 @@ config PPC_MPC832x bool select PPC_UDBG_16550 select PPC_INDIRECT_PCI - default y if MPC832x_MDS + default y if MPC832x_MDS || MPC832x_RDB config MPC834x bool @@ -70,5 +75,3 @@ config PPC_MPC836x select PPC_UDBG_16550 select PPC_INDIRECT_PCI default y if MPC836x_MDS - -endmenu diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index dfc970d0df1..31a91b53f52 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile @@ -4,6 +4,7 @@ obj-y := misc.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o +obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index 17e3a3c6d8b..fff09f5d6ed 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -41,7 +41,6 @@ #include <asm/qe_ic.h> #include "mpc83xx.h" -#include "mpc832x_mds.h" #undef DEBUG #ifdef DEBUG diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.h b/arch/powerpc/platforms/83xx/mpc832x_mds.h deleted file mode 100644 index a49588904f8..00000000000 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. - * - * Description: - * MPC832x MDS board specific header. - * - * 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. - * - */ - -#ifndef __MACH_MPC832x_MDS_H__ -#define __MACH_MPC832x_MDS_H__ - -extern u8 *get_bcsr(void); - -#endif /* __MACH_MPC832x_MDS_H__ */ diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c new file mode 100644 index 00000000000..6b71e9ffb11 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -0,0 +1,138 @@ +/* + * arch/powerpc/platforms/83xx/mpc832x_rdb.c + * + * Copyright (C) Freescale Semiconductor, Inc. 2007. All rights reserved. + * + * Description: + * MPC832x RDB board specific routines. + * This file is based on mpc832x_mds.c and mpc8313_rdb.c + * Author: Michael Barkowski <michael.barkowski@freescale.com> + * + * 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. + */ + +#include <linux/pci.h> + +#include <asm/of_platform.h> +#include <asm/time.h> +#include <asm/ipic.h> +#include <asm/udbg.h> +#include <asm/qe.h> +#include <asm/qe_ic.h> + +#include "mpc83xx.h" + +#undef DEBUG +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +/* ************************************************************************ + * + * Setup the architecture + * + */ +static void __init mpc832x_rdb_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc832x_rdb_setup_arch()", 0); + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_exclude_device = mpc83xx_exclude_device; +#endif + +#ifdef CONFIG_QUICC_ENGINE + qe_reset(); + + if ((np = of_find_node_by_name(np, "par_io")) != NULL) { + par_io_init(np); + of_node_put(np); + + for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;) + par_io_of_config(np); + } +#endif /* CONFIG_QUICC_ENGINE */ +} + +static struct of_device_id mpc832x_ids[] = { + { .type = "soc", }, + { .compatible = "soc", }, + { .type = "qe", }, + {}, +}; + +static int __init mpc832x_declare_of_platform_devices(void) +{ + if (!machine_is(mpc832x_rdb)) + return 0; + + /* Publish the QE devices */ + of_platform_bus_probe(NULL, mpc832x_ids, NULL); + + return 0; +} +device_initcall(mpc832x_declare_of_platform_devices); + +void __init mpc832x_rdb_init_IRQ(void) +{ + + struct device_node *np; + + np = of_find_node_by_type(NULL, "ipic"); + if (!np) + return; + + ipic_init(np, 0); + + /* Initialize the default interrupt mapping priorities, + * in case the boot rom changed something on us. + */ + ipic_set_default_priority(); + of_node_put(np); + +#ifdef CONFIG_QUICC_ENGINE + np = of_find_node_by_type(NULL, "qeic"); + if (!np) + return; + + qe_ic_init(np, 0); + of_node_put(np); +#endif /* CONFIG_QUICC_ENGINE */ +} + +/* + * Called very early, MMU is off, device-tree isn't unflattened + */ +static int __init mpc832x_rdb_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + return of_flat_dt_is_compatible(root, "MPC832xRDB"); +} + +define_machine(mpc832x_rdb) { + .name = "MPC832x RDB", + .probe = mpc832x_rdb_probe, + .setup_arch = mpc832x_rdb_setup_arch, + .init_IRQ = mpc832x_rdb_init_IRQ, + .get_irq = ipic_get_irq, + .restart = mpc83xx_restart, + .time_init = mpc83xx_time_init, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.h b/arch/powerpc/platforms/83xx/mpc834x_itx.h deleted file mode 100644 index 174ca4ef55f..00000000000 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * arch/powerpc/platforms/83xx/mpc834x_itx.h - * - * MPC834X ITX common board definitions - * - * Maintainer: Kumar Gala <galak@kernel.crashing.org> - * - * 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. - * - */ - -#ifndef __MACH_MPC83XX_ITX_H__ -#define __MACH_MPC83XX_ITX_H__ - -#define PIRQA MPC83xx_IRQ_EXT4 -#define PIRQB MPC83xx_IRQ_EXT5 -#define PIRQC MPC83xx_IRQ_EXT6 -#define PIRQD MPC83xx_IRQ_EXT7 - -#endif /* __MACH_MPC83XX_ITX_H__ */ diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index 9c365055514..774457d09e9 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c @@ -60,7 +60,7 @@ int __init add_bridge(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index e764c0aced8..629926e01e9 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -1,8 +1,6 @@ -menu "Platform support" - depends on PPC_85xx - choice prompt "Machine Type" + depends on PPC_85xx default MPC8540_ADS config MPC8540_ADS @@ -30,6 +28,12 @@ config MPC85xx_MDS help This option enables support for the MPC85xx MDS board +config MPC8544_DS + bool "Freescale MPC8544 DS" + select DEFAULT_UIMAGE + help + This option enables support for the MPC8544 DS board + endchoice config MPC8540 @@ -40,33 +44,15 @@ config MPC8540 config MPC8560 bool - select PPC_INDIRECT_PCI + select CPM2 default y if MPC8560_ADS config MPC85xx bool select PPC_UDBG_16550 select PPC_INDIRECT_PCI + select PPC_INDIRECT_PCI_BE + select MPIC select SERIAL_8250_SHARE_IRQ if SERIAL_8250 - default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS || MPC85xx_MDS - -config PPC_INDIRECT_PCI_BE - bool - depends on PPC_85xx - default y - -config MPIC - bool - default y - -config CPM2 - bool - depends on MPC8560 - default y - help - The CPM2 (Communications Processor Module) is a coprocessor on - embedded CPUs made by Motorola. Selecting this option means that - you wish to build a kernel for a machine with a CPM2 coprocessor - on it. - -endmenu + default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS \ + || MPC85xx_MDS || MPC8544_DS diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 4e63917ada9..4e02cbb14cf 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_PPC_85xx) += misc.o pci.o obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o +obj-$(CONFIG_MPC8544_DS) += mpc8544_ds.o obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c new file mode 100644 index 00000000000..2867f85e632 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c @@ -0,0 +1,144 @@ +/* + * MPC8544 DS Board Setup + * + * Author Xianghua Xiao (x.xiao@freescale.com) + * Copyright 2007 Freescale Semiconductor 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. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/kdev_t.h> +#include <linux/delay.h> +#include <linux/seq_file.h> + +#include <asm/system.h> +#include <asm/time.h> +#include <asm/machdep.h> +#include <asm/mpc85xx.h> +#include <mm/mmu_decl.h> +#include <asm/prom.h> +#include <asm/udbg.h> +#include <asm/mpic.h> +#include <asm/i8259.h> + +#include <sysdev/fsl_soc.h> +#include "mpc85xx.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) +#else +#define DBG(fmt, args...) +#endif + + +void __init mpc8544_ds_pic_init(void) +{ + struct mpic *mpic; + struct resource r; + struct device_node *np = NULL; +#ifdef CONFIG_PPC_I8259 + struct device_node *cascade_node = NULL; + int cascade_irq; +#endif + + np = of_find_node_by_type(np, "open-pic"); + + if (np == NULL) { + printk(KERN_ERR "Could not find open-pic node\n"); + return; + } + + if (of_address_to_resource(np, 0, &r)) { + printk(KERN_ERR "Failed to map mpic register space\n"); + of_node_put(np); + return; + } + + /* Alloc mpic structure and per isu has 16 INT entries. */ + mpic = mpic_alloc(np, r.start, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 16, 64, " OPENPIC "); + BUG_ON(mpic == NULL); + + /* + * 48 Internal Interrupts + */ + mpic_assign_isu(mpic, 0, r.start + 0x10200); + mpic_assign_isu(mpic, 1, r.start + 0x10400); + mpic_assign_isu(mpic, 2, r.start + 0x10600); + + /* + * 16 External interrupts + */ + mpic_assign_isu(mpic, 3, r.start + 0x10000); + + mpic_init(mpic); + +#ifdef CONFIG_PPC_I8259 + /* Initialize the i8259 controller */ + for_each_node_by_type(np, "interrupt-controller") + if (device_is_compatible(np, "chrp,iic")) { + cascade_node = np; + break; + } + + if (cascade_node == NULL) { + printk(KERN_DEBUG "Could not find i8259 PIC\n"); + return; + } + + cascade_irq = irq_of_parse_and_map(cascade_node, 0); + if (cascade_irq == NO_IRQ) { + printk(KERN_ERR "Failed to map cascade interrupt\n"); + return; + } + + DBG("mpc8544ds: cascade mapped to irq %d\n", cascade_irq); + + i8259_init(cascade_node, 0); + of_node_put(cascade_node); + + set_irq_chained_handler(cascade_irq, mpc8544_8259_cascade); +#endif /* CONFIG_PPC_I8259 */ +} + + +/* + * Setup the architecture + */ +static void __init mpc8544_ds_setup_arch(void) +{ + if (ppc_md.progress) + ppc_md.progress("mpc8544_ds_setup_arch()", 0); + + printk("MPC8544 DS board from Freescale Semiconductor\n"); +} + + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc8544_ds_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + return of_flat_dt_is_compatible(root, "MPC8544DS"); +} + +define_machine(mpc8544_ds) { + .name = "MPC8544 DS", + .probe = mpc8544_ds_probe, + .setup_arch = mpc8544_ds_setup_arch, + .init_IRQ = mpc8544_ds_pic_init, + .get_irq = mpic_get_irq, + .restart = mpc85xx_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 8ed034aeca5..5d27621f092 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -227,7 +227,7 @@ static void __init mpc85xx_ads_setup_arch(void) if (cpu != 0) { const unsigned int *fp; - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 4232686be44..7e71636f909 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -237,7 +237,7 @@ static void __init mpc85xx_cds_setup_arch(void) if (cpu != 0) { const unsigned int *fp; - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 81144d2ae45..54db4168995 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -80,7 +80,7 @@ static void __init mpc85xx_mds_setup_arch(void) np = of_find_node_by_type(NULL, "cpu"); if (np != NULL) { const unsigned int *fp = - get_property(np, "clock-frequency", NULL); + of_get_property(np, "clock-frequency", NULL); if (fp != NULL) loops_per_jiffy = *fp / HZ; else diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c index 05930eeb6e7..48f17e23d77 100644 --- a/arch/powerpc/platforms/85xx/pci.c +++ b/arch/powerpc/platforms/85xx/pci.c @@ -51,7 +51,7 @@ int __init add_bridge(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 0c70944d0e3..d1bcff50046 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -1,8 +1,6 @@ -menu "Platform Support" - depends on PPC_86xx - choice prompt "Machine Type" + depends on PPC_86xx default MPC8641_HPCN config MPC8641_HPCN @@ -14,20 +12,10 @@ config MPC8641_HPCN endchoice - config MPC8641 bool select PPC_INDIRECT_PCI + select PPC_INDIRECT_PCI_BE select PPC_UDBG_16550 + select MPIC default y if MPC8641_HPCN - -config MPIC - bool - default y - -config PPC_INDIRECT_PCI_BE - bool - depends on PPC_86xx - default y - -endmenu diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile index 476a6eeee71..418fd8f4d26 100644 --- a/arch/powerpc/platforms/86xx/Makefile +++ b/arch/powerpc/platforms/86xx/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_SMP) += mpc86xx_smp.o obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o -obj-$(CONFIG_PCI) += pci.o mpc86xx_pcie.o +obj-$(CONFIG_PCI) += pci.o diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index f42f801cf84..3d3d98f5bd4 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -349,7 +349,7 @@ mpc86xx_hpcn_setup_arch(void) if (np != 0) { const unsigned int *fp; - fp = get_property(np, "clock-frequency", NULL); + fp = of_get_property(np, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else @@ -384,7 +384,7 @@ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); seq_printf(m, "Machine\t\t: %s\n", model); of_node_put(root); diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c index 481e18ed5be..8235c562661 100644 --- a/arch/powerpc/platforms/86xx/pci.c +++ b/arch/powerpc/platforms/86xx/pci.c @@ -22,9 +22,9 @@ #include <asm/atomic.h> #include <asm/io.h> #include <asm/prom.h> -#include <asm/immap_86xx.h> #include <asm/pci-bridge.h> #include <sysdev/fsl_soc.h> +#include <sysdev/fsl_pcie.h> #include "mpc86xx.h" @@ -163,7 +163,7 @@ int __init add_bridge(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index beea6834bb7..39bb8c5ebe7 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig @@ -1,6 +1,3 @@ -menu "Platform support" - depends on PPC_8xx - config FADS bool @@ -9,6 +6,7 @@ config CPM1 choice prompt "8xx Machine Type" + depends on PPC_8xx depends on 8xx default MPC885ADS @@ -36,38 +34,36 @@ config MPC885ADS endchoice menu "Freescale Ethernet driver platform-specific options" - depends on (FS_ENET && MPC885ADS) - - config MPC8xx_SECOND_ETH - bool "Second Ethernet channel" - depends on MPC885ADS - default y - help - This enables support for second Ethernet on MPC885ADS and MPC86xADS boards. - The latter will use SCC1, for 885ADS you can select it below. - - choice - prompt "Second Ethernet channel" - depends on MPC8xx_SECOND_ETH - default MPC8xx_SECOND_ETH_FEC2 - - config MPC8xx_SECOND_ETH_FEC2 - bool "FEC2" - depends on MPC885ADS - help - Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2 - (often 2-nd UART) will not work if this is enabled. - - config MPC8xx_SECOND_ETH_SCC3 - bool "SCC3" - depends on MPC885ADS - help - Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1 - (often 1-nd UART) will not work if this is enabled. - - endchoice + depends on (FS_ENET && MPC885ADS) -endmenu + config MPC8xx_SECOND_ETH + bool "Second Ethernet channel" + depends on MPC885ADS + default y + help + This enables support for second Ethernet on MPC885ADS and MPC86xADS boards. + The latter will use SCC1, for 885ADS you can select it below. + + choice + prompt "Second Ethernet channel" + depends on MPC8xx_SECOND_ETH + default MPC8xx_SECOND_ETH_FEC2 + + config MPC8xx_SECOND_ETH_FEC2 + bool "FEC2" + depends on MPC885ADS + help + Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2 + (often 2-nd UART) will not work if this is enabled. + + config MPC8xx_SECOND_ETH_SCC3 + bool "SCC3" + depends on MPC885ADS + help + Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1 + (often 1-nd UART) will not work if this is enabled. + + endchoice endmenu @@ -98,7 +94,7 @@ config 8xx_CPU6 require workarounds for Linux (and most other OSes to work). If you get a BUG() very early in boot, this might fix the problem. For more details read the document entitled "MPC860 Family Device Errata - Reference" on Motorola's website. This option also incurs a + Reference" on Freescale's website. This option also incurs a performance hit. If in doubt, say N here. @@ -135,4 +131,3 @@ config UCODE_PATCH depends on !NO_UCODE_PATCH endmenu - diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index 9ed7125f015..0901dbada35 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c @@ -85,17 +85,17 @@ init_internal_rtc(void) static int __init get_freq(char *name, unsigned long *val) { struct device_node *cpu; - unsigned int *fp; + const unsigned int *fp; int found = 0; /* The cpu node should have timebase and clock frequency properties */ cpu = of_find_node_by_type(NULL, "cpu"); if (cpu) { - fp = (unsigned int *)get_property(cpu, name, NULL); + fp = of_get_property(cpu, name, NULL); if (fp) { found = 1; - *val = *fp++; + *val = *fp; } of_node_put(cpu); @@ -262,7 +262,7 @@ void mpc8xx_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); seq_printf(m, "Machine\t\t: %s\n", model); of_node_put(root); diff --git a/arch/powerpc/platforms/8xx/mpc86xads.h b/arch/powerpc/platforms/8xx/mpc86xads.h index b5d19dd0619..59bad2f9ae5 100644 --- a/arch/powerpc/platforms/8xx/mpc86xads.h +++ b/arch/powerpc/platforms/8xx/mpc86xads.h @@ -37,7 +37,7 @@ #define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET) #define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver -#define PCMCIA_MEM_ADDR (uint)0xff020000) +#define PCMCIA_MEM_ADDR ((uint)0xff020000) #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) /* Bits of interest in the BCSRs. diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c index ef52ce701b0..a35315af5c5 100644 --- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c @@ -247,7 +247,7 @@ void init_smc_ioports(struct fs_uart_platform_info *data) } } -int platform_device_skip(char *model, int id) +int platform_device_skip(const char *model, int id) { return 0; } @@ -260,7 +260,7 @@ static void __init mpc86xads_setup_arch(void) if (cpu != 0) { const unsigned int *fp; - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else diff --git a/arch/powerpc/platforms/8xx/mpc885ads.h b/arch/powerpc/platforms/8xx/mpc885ads.h index 30cbebfe84c..7c31aec284c 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads.h +++ b/arch/powerpc/platforms/8xx/mpc885ads.h @@ -37,7 +37,7 @@ #define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET) #define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver -#define PCMCIA_MEM_ADDR (uint)0xff020000) +#define PCMCIA_MEM_ADDR ((uint)0xff020000) #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) /* Bits of interest in the BCSRs. diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index c5fefdf66c0..a57b57785ac 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c @@ -322,7 +322,7 @@ void init_smc_ioports(struct fs_uart_platform_info *data) } } -int platform_device_skip(char *model, int id) +int platform_device_skip(const char *model, int id) { #ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3 const char *dev = "FEC"; @@ -346,7 +346,7 @@ static void __init mpc885ads_setup_arch(void) if (cpu != 0) { const unsigned int *fp; - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig new file mode 100644 index 00000000000..51e33347c14 --- /dev/null +++ b/arch/powerpc/platforms/Kconfig @@ -0,0 +1,259 @@ +menu "Platform support" + +choice + prompt "Machine type" + depends on PPC64 || CLASSIC32 + default PPC_MULTIPLATFORM + +config PPC_MULTIPLATFORM + bool "Generic desktop/server/laptop" + help + Select this option if configuring for an IBM pSeries or + RS/6000 machine, an Apple machine, or a PReP, CHRP, + Maple or Cell-based machine. + +config EMBEDDED6xx + bool "Embedded 6xx/7xx/7xxx-based board" + depends on PPC32 && (BROKEN||BROKEN_ON_SMP) + +config APUS + bool "Amiga-APUS" + depends on PPC32 && BROKEN + help + Select APUS if configuring for a PowerUP Amiga. + More information is available at: + <http://linux-apus.sourceforge.net/>. +endchoice + +source "arch/powerpc/platforms/pseries/Kconfig" +source "arch/powerpc/platforms/iseries/Kconfig" +source "arch/powerpc/platforms/chrp/Kconfig" +source "arch/powerpc/platforms/52xx/Kconfig" +source "arch/powerpc/platforms/powermac/Kconfig" +source "arch/powerpc/platforms/prep/Kconfig" +source "arch/powerpc/platforms/maple/Kconfig" +source "arch/powerpc/platforms/pasemi/Kconfig" +source "arch/powerpc/platforms/celleb/Kconfig" +source "arch/powerpc/platforms/ps3/Kconfig" +source "arch/powerpc/platforms/cell/Kconfig" +source "arch/powerpc/platforms/8xx/Kconfig" +source "arch/powerpc/platforms/82xx/Kconfig" +source "arch/powerpc/platforms/83xx/Kconfig" +source "arch/powerpc/platforms/85xx/Kconfig" +source "arch/powerpc/platforms/86xx/Kconfig" +source "arch/powerpc/platforms/embedded6xx/Kconfig" +#source "arch/powerpc/platforms/4xx/Kconfig + +config PPC_NATIVE + bool + depends on PPC_MULTIPLATFORM + help + Support for running natively on the hardware, i.e. without + a hypervisor. This option is not user-selectable but should + be selected by all platforms that need it. + +config UDBG_RTAS_CONSOLE + bool "RTAS based debug console" + depends on PPC_RTAS + default n + +config PPC_UDBG_BEAT + bool "BEAT based debug console" + depends on PPC_CELLEB + default n + +config XICS + depends on PPC_PSERIES + bool + default y + +config MPIC + bool + default n + +config MPIC_WEIRD + bool + default n + +config PPC_I8259 + bool + default n + +config U3_DART + bool + depends on PPC_MULTIPLATFORM && PPC64 + default n + +config PPC_RTAS + bool + default n + +config RTAS_ERROR_LOGGING + bool + depends on PPC_RTAS + default n + +config RTAS_PROC + bool "Proc interface to RTAS" + depends on PPC_RTAS + default y + +config RTAS_FLASH + tristate "Firmware flash interface" + depends on PPC64 && RTAS_PROC + +config PPC_PMI + tristate "Support for PMI" + depends PPC_IBM_CELL_BLADE + help + PMI (Platform Management Interrupt) is a way to + communicate with the BMC (Baseboard Mangement Controller). + It is used in some IBM Cell blades. + default m + +config MMIO_NVRAM + bool + default n + +config MPIC_U3_HT_IRQS + bool + depends on PPC_MAPLE + default y + +config IBMVIO + depends on PPC_PSERIES || PPC_ISERIES + bool + default y + +config IBMEBUS + depends on PPC_PSERIES + bool "Support for GX bus based adapters" + help + Bus device driver for GX bus based adapters. + +config PPC_MPC106 + bool + default n + +config PPC_970_NAP + bool + default n + +config PPC_INDIRECT_IO + bool + select GENERIC_IOMAP + default n + +config GENERIC_IOMAP + bool + default n + +source "drivers/cpufreq/Kconfig" + +menu "CPU Frequency drivers" + depends on CPU_FREQ + +config CPU_FREQ_PMAC + bool "Support for Apple PowerBooks" + depends on ADB_PMU && PPC32 + select CPU_FREQ_TABLE + help + This adds support for frequency switching on Apple PowerBooks, + this currently includes some models of iBook & Titanium + PowerBook. + +config CPU_FREQ_PMAC64 + bool "Support for some Apple G5s" + depends on PPC_PMAC && PPC64 + select CPU_FREQ_TABLE + help + This adds support for frequency switching on Apple iMac G5, + and some of the more recent desktop G5 machines as well. + +config PPC_PASEMI_CPUFREQ + bool "Support for PA Semi PWRficient" + depends on PPC_PASEMI + default y + select CPU_FREQ_TABLE + help + This adds the support for frequency switching on PA Semi + PWRficient processors. + +endmenu + +config PPC601_SYNC_FIX + bool "Workarounds for PPC601 bugs" + depends on 6xx && (PPC_PREP || PPC_PMAC) + help + Some versions of the PPC601 (the first PowerPC chip) have bugs which + mean that extra synchronization instructions are required near + certain instructions, typically those that make major changes to the + CPU state. These extra instructions reduce performance slightly. + If you say N here, these extra instructions will not be included, + resulting in a kernel which will run faster but may not run at all + on some systems with the PPC601 chip. + + If in doubt, say Y here. + +config TAU + bool "On-chip CPU temperature sensor support" + depends on CLASSIC32 + help + G3 and G4 processors have an on-chip temperature sensor called the + 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die + temperature within 2-4 degrees Celsius. This option shows the current + on-die temperature in /proc/cpuinfo if the cpu supports it. + + Unfortunately, on some chip revisions, this sensor is very inaccurate + and in many cases, does not work at all, so don't assume the cpu + temp is actually what /proc/cpuinfo says it is. + +config TAU_INT + bool "Interrupt driven TAU driver (DANGEROUS)" + depends on TAU + ---help--- + The TAU supports an interrupt driven mode which causes an interrupt + whenever the temperature goes out of range. This is the fastest way + to get notified the temp has exceeded a range. With this option off, + a timer is used to re-check the temperature periodically. + + However, on some cpus it appears that the TAU interrupt hardware + is buggy and can cause a situation which would lead unexplained hard + lockups. + + Unless you are extending the TAU driver, or enjoy kernel/hardware + debugging, leave this option off. + +config TAU_AVERAGE + bool "Average high and low temp" + depends on TAU + ---help--- + The TAU hardware can compare the temperature to an upper and lower + bound. The default behavior is to show both the upper and lower + bound in /proc/cpuinfo. If the range is large, the temperature is + either changing a lot, or the TAU hardware is broken (likely on some + G4's). If the range is small (around 4 degrees), the temperature is + relatively stable. If you say Y here, a single temperature value, + halfway between the upper and lower bounds, will be reported in + /proc/cpuinfo. + + If in doubt, say N here. + +config QUICC_ENGINE + bool + help + The QUICC Engine (QE) is a new generation of communications + coprocessors on Freescale embedded CPUs (akin to CPM in older chips). + Selecting this option means that you wish to build a kernel + for a machine with a QE coprocessor. + +config CPM2 + bool + default n + help + The CPM2 (Communications Processor Module) is a coprocessor on + embedded CPUs made by Freescale. Selecting this option means that + you wish to build a kernel for a machine with a CPM2 coprocessor + on it (826x, 827x, 8560). + +endmenu diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 06a85b70433..82551770917 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -1,3 +1,26 @@ +config PPC_CELL + bool + default n + +config PPC_CELL_NATIVE + bool + select PPC_CELL + select PPC_DCR_MMIO + select PPC_OF_PLATFORM_PCI + select PPC_INDIRECT_IO + select PPC_NATIVE + select MPIC + default n + +config PPC_IBM_CELL_BLADE + bool "IBM Cell Blade" + depends on PPC_MULTIPLATFORM && PPC64 + select PPC_CELL_NATIVE + select PPC_RTAS + select MMIO_NVRAM + select PPC_UDBG_16550 + select UDBG_RTAS_CONSOLE + menu "Cell Broadband Engine options" depends on PPC_CELL @@ -18,6 +41,7 @@ config SPU_BASE config CBE_RAS bool "RAS features for bare metal Cell BE" + depends on PPC_CELL_NATIVE default y config CBE_THERM diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c index a3850fd1e94..f9ac3fe3be9 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c @@ -25,9 +25,12 @@ #include <asm/hw_irq.h> #include <asm/io.h> +#include <asm/machdep.h> #include <asm/processor.h> #include <asm/prom.h> #include <asm/time.h> +#include <asm/pmi.h> +#include <asm/of_platform.h> #include "cbe_regs.h" @@ -68,6 +71,38 @@ static u64 MIC_Slow_Next_Timer_table[] = { * hardware specific functions */ +static struct of_device *pmi_dev; + +static int set_pmode_pmi(int cpu, unsigned int pmode) +{ + int ret; + pmi_message_t pmi_msg; +#ifdef DEBUG + u64 time; +#endif + + pmi_msg.type = PMI_TYPE_FREQ_CHANGE; + pmi_msg.data1 = cbe_cpu_to_node(cpu); + pmi_msg.data2 = pmode; + +#ifdef DEBUG + time = (u64) get_cycles(); +#endif + + pmi_send_message(pmi_dev, pmi_msg); + ret = pmi_msg.data2; + + pr_debug("PMI returned slow mode %d\n", ret); + +#ifdef DEBUG + time = (u64) get_cycles() - time; /* actual cycles (not cpu cycles!) */ + time = 1000000000 * time / CLOCK_TICK_RATE; /* time in ns (10^-9) */ + pr_debug("had to wait %lu ns for a transition\n", time); +#endif + return ret; +} + + static int get_pmode(int cpu) { int ret; @@ -79,7 +114,7 @@ static int get_pmode(int cpu) return ret; } -static int set_pmode(int cpu, unsigned int pmode) +static int set_pmode_reg(int cpu, unsigned int pmode) { struct cbe_pmd_regs __iomem *pmd_regs; struct cbe_mic_tm_regs __iomem *mic_tm_regs; @@ -120,37 +155,71 @@ static int set_pmode(int cpu, unsigned int pmode) return 0; } +static int set_pmode(int cpu, unsigned int slow_mode) { + if (pmi_dev) + return set_pmode_pmi(cpu, slow_mode); + else + return set_pmode_reg(cpu, slow_mode); +} + +static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg) +{ + struct cpufreq_policy policy; + u8 cpu; + u8 cbe_pmode_new; + + BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE); + + cpu = cbe_node_to_cpu(pmi_msg.data1); + cbe_pmode_new = pmi_msg.data2; + + cpufreq_get_policy(&policy, cpu); + + policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency); + policy.min = min(policy.min, policy.max); + + pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max); + cpufreq_set_policy(&policy); +} + +static struct pmi_handler cbe_pmi_handler = { + .type = PMI_TYPE_FREQ_CHANGE, + .handle_pmi_message = cbe_cpufreq_handle_pmi, +}; + + /* * cpufreq functions */ -static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy) +static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) { - u32 *max_freq; + const u32 *max_freqp; + u32 max_freq; int i, cur_pmode; struct device_node *cpu; cpu = of_get_cpu_node(policy->cpu, NULL); - if(!cpu) + if (!cpu) return -ENODEV; pr_debug("init cpufreq on CPU %d\n", policy->cpu); - max_freq = (u32*) get_property(cpu, "clock-frequency", NULL); + max_freqp = of_get_property(cpu, "clock-frequency", NULL); - if(!max_freq) + if (!max_freqp) return -EINVAL; - // we need the freq in kHz - *max_freq /= 1000; + /* we need the freq in kHz */ + max_freq = *max_freqp / 1000; - pr_debug("max clock-frequency is at %u kHz\n", *max_freq); + pr_debug("max clock-frequency is at %u kHz\n", max_freq); pr_debug("initializing frequency table\n"); - // initialize frequency table + /* initialize frequency table */ for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) { - cbe_freqs[i].frequency = *max_freq / cbe_freqs[i].index; + cbe_freqs[i].frequency = max_freq / cbe_freqs[i].index; pr_debug("%d: %d\n", i, cbe_freqs[i].frequency); } @@ -167,10 +236,10 @@ static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy) policy->cpus = cpu_sibling_map[policy->cpu]; #endif - cpufreq_frequency_table_get_attr (cbe_freqs, policy->cpu); + cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu); /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */ - return cpufreq_frequency_table_cpuinfo (policy, cbe_freqs); + return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs); } static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy) @@ -202,7 +271,7 @@ static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int target freqs.new = cbe_freqs[cbe_pmode_new].frequency; freqs.cpu = policy->cpu; - mutex_lock (&cbe_switch_mutex); + mutex_lock(&cbe_switch_mutex); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", @@ -233,11 +302,26 @@ static struct cpufreq_driver cbe_cpufreq_driver = { static int __init cbe_cpufreq_init(void) { + struct device_node *np; + + if (!machine_is(cell)) + return -ENODEV; + + np = of_find_node_by_type(NULL, "ibm,pmi"); + + pmi_dev = of_find_device_by_node(np); + + if (pmi_dev) + pmi_register_handler(pmi_dev, &cbe_pmi_handler); + return cpufreq_register_driver(&cbe_cpufreq_driver); } static void __exit cbe_cpufreq_exit(void) { + if (pmi_dev) + pmi_unregister_handler(pmi_dev, &cbe_pmi_handler); + cpufreq_unregister_driver(&cbe_cpufreq_driver); } diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index 9a0ee62691d..12c9674b4b1 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -14,6 +14,8 @@ #include <asm/pgtable.h> #include <asm/prom.h> #include <asm/ptrace.h> +#include <asm/of_device.h> +#include <asm/of_platform.h> #include "cbe_regs.h" @@ -27,6 +29,7 @@ static struct cbe_regs_map { struct device_node *cpu_node; + struct device_node *be_node; struct cbe_pmd_regs __iomem *pmd_regs; struct cbe_iic_regs __iomem *iic_regs; struct cbe_mic_tm_regs __iomem *mic_tm_regs; @@ -37,30 +40,43 @@ static int cbe_regs_map_count; static struct cbe_thread_map { struct device_node *cpu_node; + struct device_node *be_node; struct cbe_regs_map *regs; + unsigned int thread_id; + unsigned int cbe_id; } cbe_thread_map[NR_CPUS]; +static cpumask_t cbe_local_mask[MAX_CBE] = { [0 ... MAX_CBE-1] = CPU_MASK_NONE }; +static cpumask_t cbe_first_online_cpu = CPU_MASK_NONE; + static struct cbe_regs_map *cbe_find_map(struct device_node *np) { int i; struct device_node *tmp_np; - if (strcasecmp(np->type, "spe") == 0) { - if (np->data == NULL) { - /* walk up path until cpu node was found */ - tmp_np = np->parent; - while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0) - tmp_np = tmp_np->parent; + if (strcasecmp(np->type, "spe")) { + for (i = 0; i < cbe_regs_map_count; i++) + if (cbe_regs_maps[i].cpu_node == np || + cbe_regs_maps[i].be_node == np) + return &cbe_regs_maps[i]; + return NULL; + } - np->data = cbe_find_map(tmp_np); - } + if (np->data) return np->data; - } - for (i = 0; i < cbe_regs_map_count; i++) - if (cbe_regs_maps[i].cpu_node == np) - return &cbe_regs_maps[i]; - return NULL; + /* walk up path until cpu or be node was found */ + tmp_np = np; + do { + tmp_np = tmp_np->parent; + /* on a correct devicetree we wont get up to root */ + BUG_ON(!tmp_np); + } while (strcasecmp(tmp_np->type, "cpu") && + strcasecmp(tmp_np->type, "be")); + + np->data = cbe_find_map(tmp_np); + + return np->data; } struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) @@ -130,38 +146,105 @@ struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu) } EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs); -/* FIXME - * This is little more than a stub at the moment. It should be - * fleshed out so that it works for both SMT and non-SMT, no - * matter if the passed cpu is odd or even. - * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1. - * For SMT disabled, returns 0 for all cpus. - */ u32 cbe_get_hw_thread_id(int cpu) { - return (cpu & 1); + return cbe_thread_map[cpu].thread_id; } EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id); -void __init cbe_regs_init(void) +u32 cbe_cpu_to_node(int cpu) { - int i; - struct device_node *cpu; + return cbe_thread_map[cpu].cbe_id; +} +EXPORT_SYMBOL_GPL(cbe_cpu_to_node); - /* Build local fast map of CPUs */ - for_each_possible_cpu(i) - cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL); +u32 cbe_node_to_cpu(int node) +{ + return find_first_bit( (unsigned long *) &cbe_local_mask[node], sizeof(cpumask_t)); +} +EXPORT_SYMBOL_GPL(cbe_node_to_cpu); - /* Find maps for each device tree CPU */ - for_each_node_by_type(cpu, "cpu") { - struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++]; +static struct device_node *cbe_get_be_node(int cpu_id) +{ + struct device_node *np; + + for_each_node_by_type (np, "be") { + int len,i; + const phandle *cpu_handle; + + cpu_handle = of_get_property(np, "cpus", &len); + + for (i=0; i<len; i++) + if (of_find_node_by_phandle(cpu_handle[i]) == of_get_cpu_node(cpu_id, NULL)) + return np; + } + + return NULL; +} + +void __init cbe_fill_regs_map(struct cbe_regs_map *map) +{ + if(map->be_node) { + struct device_node *be, *np; + + be = map->be_node; + + for_each_node_by_type(np, "pervasive") + if (of_get_parent(np) == be) + map->pmd_regs = of_iomap(np, 0); + + for_each_node_by_type(np, "CBEA-Internal-Interrupt-Controller") + if (of_get_parent(np) == be) + map->iic_regs = of_iomap(np, 2); + for_each_node_by_type(np, "mic-tm") + if (of_get_parent(np) == be) + map->mic_tm_regs = of_iomap(np, 0); + } else { + struct device_node *cpu; /* That hack must die die die ! */ const struct address_prop { unsigned long address; unsigned int len; } __attribute__((packed)) *prop; + cpu = map->cpu_node; + + prop = of_get_property(cpu, "pervasive", NULL); + if (prop != NULL) + map->pmd_regs = ioremap(prop->address, prop->len); + + prop = of_get_property(cpu, "iic", NULL); + if (prop != NULL) + map->iic_regs = ioremap(prop->address, prop->len); + + prop = of_get_property(cpu, "mic-tm", NULL); + if (prop != NULL) + map->mic_tm_regs = ioremap(prop->address, prop->len); + } +} + + +void __init cbe_regs_init(void) +{ + int i; + unsigned int thread_id; + struct device_node *cpu; + + /* Build local fast map of CPUs */ + for_each_possible_cpu(i) { + cbe_thread_map[i].cpu_node = of_get_cpu_node(i, &thread_id); + cbe_thread_map[i].be_node = cbe_get_be_node(i); + cbe_thread_map[i].thread_id = thread_id; + } + + /* Find maps for each device tree CPU */ + for_each_node_by_type(cpu, "cpu") { + struct cbe_regs_map *map; + unsigned int cbe_id; + + cbe_id = cbe_regs_map_count++; + map = &cbe_regs_maps[cbe_id]; if (cbe_regs_map_count > MAX_CBE) { printk(KERN_ERR "cbe_regs: More BE chips than supported" @@ -170,22 +253,21 @@ void __init cbe_regs_init(void) return; } map->cpu_node = cpu; - for_each_possible_cpu(i) - if (cbe_thread_map[i].cpu_node == cpu) - cbe_thread_map[i].regs = map; - prop = get_property(cpu, "pervasive", NULL); - if (prop != NULL) - map->pmd_regs = ioremap(prop->address, prop->len); + for_each_possible_cpu(i) { + struct cbe_thread_map *thread = &cbe_thread_map[i]; - prop = get_property(cpu, "iic", NULL); - if (prop != NULL) - map->iic_regs = ioremap(prop->address, prop->len); + if (thread->cpu_node == cpu) { + thread->regs = map; + thread->cbe_id = cbe_id; + map->be_node = thread->be_node; + cpu_set(i, cbe_local_mask[cbe_id]); + if(thread->thread_id == 0) + cpu_set(i, cbe_first_online_cpu); + } + } - prop = (struct address_prop *)get_property(cpu, "mic-tm", - NULL); - if (prop != NULL) - map->mic_tm_regs = ioremap(prop->address, prop->len); + cbe_fill_regs_map(map); } } diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h index 440a7ecc66e..17d59714487 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -255,6 +255,11 @@ struct cbe_mic_tm_regs { extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); +/* some utility functions to deal with SMT */ +extern u32 cbe_get_hw_thread_id(int cpu); +extern u32 cbe_cpu_to_node(int cpu); +extern u32 cbe_node_to_cpu(int node); + /* Init this module early */ extern void cbe_regs_init(void); diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c index 70e0d968d30..f370f0fa6f4 100644 --- a/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/arch/powerpc/platforms/cell/cbe_thermal.c @@ -1,6 +1,31 @@ /* * thermal support for the cell processor * + * This module adds some sysfs attributes to cpu and spu nodes. + * Base for measurements are the digital thermal sensors (DTS) + * located on the chip. + * The accuracy is 2 degrees, starting from 65 up to 125 degrees celsius + * The attributes can be found under + * /sys/devices/system/cpu/cpuX/thermal + * /sys/devices/system/spu/spuX/thermal + * + * The following attributes are added for each node: + * temperature: + * contains the current temperature measured by the DTS + * throttle_begin: + * throttling begins when temperature is greater or equal to + * throttle_begin. Setting this value to 125 prevents throttling. + * throttle_end: + * throttling is being ceased, if the temperature is lower than + * throttle_end. Due to a delay between applying throttling and + * a reduced temperature this value should be less than throttle_begin. + * A value equal to throttle_begin provides only a very little hysteresis. + * throttle_full_stop: + * If the temperatrue is greater or equal to throttle_full_stop, + * full throttling is applied to the cpu or spu. This value should be + * greater than throttle_begin and throttle_end. Setting this value to + * 65 prevents the unit from running code at all. + * * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 * * Author: Christian Krafft <krafft@de.ibm.com> @@ -31,6 +56,26 @@ #include "cbe_regs.h" #include "spu_priv1_mmio.h" +#define TEMP_MIN 65 +#define TEMP_MAX 125 + +#define SYSDEV_PREFIX_ATTR(_prefix,_name,_mode) \ +struct sysdev_attribute attr_ ## _prefix ## _ ## _name = { \ + .attr = { .name = __stringify(_name), .mode = _mode }, \ + .show = _prefix ## _show_ ## _name, \ + .store = _prefix ## _store_ ## _name, \ +}; + +static inline u8 reg_to_temp(u8 reg_value) +{ + return ((reg_value & 0x3f) << 1) + TEMP_MIN; +} + +static inline u8 temp_to_reg(u8 temp) +{ + return ((temp - TEMP_MIN) >> 1) & 0x3f; +} + static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) { struct spu *spu; @@ -43,14 +88,14 @@ static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) /* returns the value for a given spu in a given register */ static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg) { - unsigned int *id; + const unsigned int *id; union spe_reg value; struct spu *spu; /* getting the id from the reg attribute will not work on future device-tree layouts * in future we should store the id to the spu struct and use it here */ spu = container_of(sysdev, struct spu, sysdev); - id = (unsigned int *)get_property(spu_devnode(spu), "reg", NULL); + id = of_get_property(spu_devnode(spu), "reg", NULL); value.val = in_be64(®->val); return value.spe[*id]; @@ -58,20 +103,81 @@ static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iom static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) { - int value; + u8 value; struct cbe_pmd_regs __iomem *pmd_regs; pmd_regs = get_pmd_regs(sysdev); value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1); - /* clear all other bits */ + + return sprintf(buf, "%d\n", reg_to_temp(value)); +} + +static ssize_t show_throttle(struct cbe_pmd_regs __iomem *pmd_regs, char *buf, int pos) +{ + u64 value; + + value = in_be64(&pmd_regs->tm_tpr.val); + /* access the corresponding byte */ + value >>= pos; value &= 0x3F; - /* temp is stored in steps of 2 degrees */ - value *= 2; - /* base temp is 65 degrees */ - value += 65; - return sprintf(buf, "%d\n", (int) value); + return sprintf(buf, "%d\n", reg_to_temp(value)); +} + +static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char *buf, size_t size, int pos) +{ + u64 reg_value; + int temp; + u64 new_value; + int ret; + + ret = sscanf(buf, "%u", &temp); + + if (ret != 1 || temp < TEMP_MIN || temp > TEMP_MAX) + return -EINVAL; + + new_value = temp_to_reg(temp); + + reg_value = in_be64(&pmd_regs->tm_tpr.val); + + /* zero out bits for new value */ + reg_value &= ~(0xffull << pos); + /* set bits to new value */ + reg_value |= new_value << pos; + + out_be64(&pmd_regs->tm_tpr.val, reg_value); + return size; +} + +static ssize_t spu_show_throttle_end(struct sys_device *sysdev, char *buf) +{ + return show_throttle(get_pmd_regs(sysdev), buf, 0); +} + +static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, char *buf) +{ + return show_throttle(get_pmd_regs(sysdev), buf, 8); +} + +static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, char *buf) +{ + return show_throttle(get_pmd_regs(sysdev), buf, 16); +} + +static ssize_t spu_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(get_pmd_regs(sysdev), buf, size, 0); +} + +static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(get_pmd_regs(sysdev), buf, size, 8); +} + +static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(get_pmd_regs(sysdev), buf, size, 16); } static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) @@ -82,16 +188,9 @@ static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); value = in_be64(&pmd_regs->ts_ctsr2); - /* access the corresponding byte */ - value >>= pos; - /* clear all other bits */ - value &= 0x3F; - /* temp is stored in steps of 2 degrees */ - value *= 2; - /* base temp is 65 degrees */ - value += 65; + value = (value >> pos) & 0x3f; - return sprintf(buf, "%d\n", (int) value); + return sprintf(buf, "%d\n", reg_to_temp(value)); } @@ -108,13 +207,52 @@ static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf) return ppe_show_temp(sysdev, buf, 0); } +static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, char *buf) +{ + return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32); +} + +static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, char *buf) +{ + return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40); +} + +static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, char *buf) +{ + return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48); +} + +static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32); +} + +static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40); +} + +static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size) +{ + return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48); +} + + static struct sysdev_attribute attr_spu_temperature = { .attr = {.name = "temperature", .mode = 0400 }, .show = spu_show_temp, }; +static SYSDEV_PREFIX_ATTR(spu, throttle_end, 0600); +static SYSDEV_PREFIX_ATTR(spu, throttle_begin, 0600); +static SYSDEV_PREFIX_ATTR(spu, throttle_full_stop, 0600); + + static struct attribute *spu_attributes[] = { &attr_spu_temperature.attr, + &attr_spu_throttle_end.attr, + &attr_spu_throttle_begin.attr, + &attr_spu_throttle_full_stop.attr, NULL, }; @@ -133,9 +271,16 @@ static struct sysdev_attribute attr_ppe_temperature1 = { .show = ppe_show_temp1, }; +static SYSDEV_PREFIX_ATTR(ppe, throttle_end, 0600); +static SYSDEV_PREFIX_ATTR(ppe, throttle_begin, 0600); +static SYSDEV_PREFIX_ATTR(ppe, throttle_full_stop, 0600); + static struct attribute *ppe_attributes[] = { &attr_ppe_temperature0.attr, &attr_ppe_temperature1.attr, + &attr_ppe_throttle_end.attr, + &attr_ppe_throttle_begin.attr, + &attr_ppe_throttle_full_stop.attr, NULL, }; diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 6666d037eb4..4fc4e92775d 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -261,7 +261,7 @@ static int iic_host_xlate(struct irq_host *h, struct device_node *ct, return -ENODEV; if (intsize != 1) return -ENODEV; - val = get_property(ct, "#interrupt-cells", NULL); + val = of_get_property(ct, "#interrupt-cells", NULL); if (val == NULL || *val != 1) return -ENODEV; @@ -327,7 +327,7 @@ static int __init setup_iic(void) if (!device_is_compatible(dn, "IBM,CBEA-Internal-Interrupt-Controller")) continue; - np = get_property(dn, "ibm,interrupt-server-ranges", NULL); + np = of_get_property(dn, "ibm,interrupt-server-ranges", NULL); if (np == NULL) { printk(KERN_WARNING "IIC: CPU association not found\n"); of_node_put(dn); diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c index 7c73128305e..d68d920eb2c 100644 --- a/arch/powerpc/platforms/cell/io-workarounds.c +++ b/arch/powerpc/platforms/cell/io-workarounds.c @@ -318,7 +318,7 @@ static int __init spider_pci_workaround_init(void) */ list_for_each_entry(phb, &hose_list, list_node) { struct device_node *np = phb->arch_data; - const char *model = get_property(np, "model", NULL); + const char *model = of_get_property(np, "model", NULL); /* If no model property or name isn't exactly "pci", skip */ if (model == NULL || strcmp(np->name, "pci")) diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 67d617b60a2..760caa76841 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -291,9 +291,9 @@ static int cell_iommu_find_ioc(int nid, unsigned long *base) const unsigned int *nidp; const unsigned long *tmp; - nidp = get_property(np, "node-id", NULL); + nidp = of_get_property(np, "node-id", NULL); if (nidp && *nidp == nid) { - tmp = get_property(np, "ioc-translation", NULL); + tmp = of_get_property(np, "ioc-translation", NULL); if (tmp) { *base = *tmp; of_node_put(np); @@ -430,7 +430,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np, struct iommu_window *window; const unsigned int *ioid; - ioid = get_property(np, "ioid", NULL); + ioid = of_get_property(np, "ioid", NULL); if (ioid == NULL) printk(KERN_WARNING "iommu: missing ioid for %s using 0\n", np->full_name); @@ -496,7 +496,7 @@ static void cell_dma_dev_setup(struct device *dev) struct dev_archdata *archdata = &dev->archdata; /* If we run without iommu, no need to do anything */ - if (pci_dma_ops == &dma_direct_ops) + if (get_pci_dma_ops() == &dma_direct_ops) return; /* Current implementation uses the first window available in that @@ -530,7 +530,7 @@ static int cell_of_bus_notify(struct notifier_block *nb, unsigned long action, return 0; /* We use the PCI DMA ops */ - dev->archdata.dma_ops = pci_dma_ops; + dev->archdata.dma_ops = get_pci_dma_ops(); cell_dma_dev_setup(dev); @@ -549,7 +549,7 @@ static int __init cell_iommu_get_window(struct device_node *np, unsigned long index; /* Use ibm,dma-window if available, else, hard code ! */ - dma_window = get_property(np, "ibm,dma-window", NULL); + dma_window = of_get_property(np, "ibm,dma-window", NULL); if (dma_window == NULL) { *base = 0; *size = 0x80000000u; @@ -646,7 +646,7 @@ static int __init cell_iommu_init_disabled(void) unsigned long base = 0, size; /* When no iommu is present, we use direct DMA ops */ - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); /* First make sure all IOC translation is turned off */ cell_disable_iommus(); @@ -734,7 +734,7 @@ static int __init cell_iommu_init(void) } /* Setup default PCI iommu ops */ - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); bail: /* Register callbacks on OF platform device addition/removal diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 0984c707169..3961a085b43 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c @@ -3,11 +3,13 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/smp.h> +#include <linux/reboot.h> #include <asm/reg.h> #include <asm/io.h> #include <asm/prom.h> #include <asm/machdep.h> +#include <asm/rtas.h> #include "ras.h" #include "cbe_regs.h" @@ -82,6 +84,164 @@ static int cbe_machine_check_handler(struct pt_regs *regs) return 0; } +struct ptcal_area { + struct list_head list; + int nid; + int order; + struct page *pages; +}; + +static LIST_HEAD(ptcal_list); + +static int ptcal_start_tok, ptcal_stop_tok; + +static int __init cbe_ptcal_enable_on_node(int nid, int order) +{ + struct ptcal_area *area; + int ret = -ENOMEM; + unsigned long addr; + +#ifdef CONFIG_CRASH_DUMP + rtas_call(ptcal_stop_tok, 1, 1, NULL, nid); +#endif + + area = kmalloc(sizeof(*area), GFP_KERNEL); + if (!area) + goto out_err; + + area->nid = nid; + area->order = order; + area->pages = alloc_pages_node(area->nid, GFP_KERNEL, area->order); + + if (!area->pages) + goto out_free_area; + + addr = __pa(page_address(area->pages)); + + ret = -EIO; + if (rtas_call(ptcal_start_tok, 3, 1, NULL, area->nid, + (unsigned int)(addr >> 32), + (unsigned int)(addr & 0xffffffff))) { + printk(KERN_ERR "%s: error enabling PTCAL on node %d!\n", + __FUNCTION__, nid); + goto out_free_pages; + } + + list_add(&area->list, &ptcal_list); + + return 0; + +out_free_pages: + __free_pages(area->pages, area->order); +out_free_area: + kfree(area); +out_err: + return ret; +} + +static int __init cbe_ptcal_enable(void) +{ + const u32 *size; + struct device_node *np; + int order, found_mic = 0; + + np = of_find_node_by_path("/rtas"); + if (!np) + return -ENODEV; + + size = of_get_property(np, "ibm,cbe-ptcal-size", NULL); + if (!size) + return -ENODEV; + + pr_debug("%s: enabling PTCAL, size = 0x%x\n", __FUNCTION__, *size); + order = get_order(*size); + of_node_put(np); + + /* support for malta device trees, with be@/mic@ nodes */ + for_each_node_by_type(np, "mic-tm") { + cbe_ptcal_enable_on_node(of_node_to_nid(np), order); + found_mic = 1; + } + + if (found_mic) + return 0; + + /* support for older device tree - use cpu nodes */ + for_each_node_by_type(np, "cpu") { + const u32 *nid = of_get_property(np, "node-id", NULL); + if (!nid) { + printk(KERN_ERR "%s: node %s is missing node-id?\n", + __FUNCTION__, np->full_name); + continue; + } + cbe_ptcal_enable_on_node(*nid, order); + found_mic = 1; + } + + return found_mic ? 0 : -ENODEV; +} + +static int cbe_ptcal_disable(void) +{ + struct ptcal_area *area, *tmp; + int ret = 0; + + pr_debug("%s: disabling PTCAL\n", __FUNCTION__); + + list_for_each_entry_safe(area, tmp, &ptcal_list, list) { + /* disable ptcal on this node */ + if (rtas_call(ptcal_stop_tok, 1, 1, NULL, area->nid)) { + printk(KERN_ERR "%s: error disabling PTCAL " + "on node %d!\n", __FUNCTION__, + area->nid); + ret = -EIO; + continue; + } + + /* ensure we can access the PTCAL area */ + memset(page_address(area->pages), 0, + 1 << (area->order + PAGE_SHIFT)); + + /* clean up */ + list_del(&area->list); + __free_pages(area->pages, area->order); + kfree(area); + } + + return ret; +} + +static int cbe_ptcal_notify_reboot(struct notifier_block *nb, + unsigned long code, void *data) +{ + return cbe_ptcal_disable(); +} + +static struct notifier_block cbe_ptcal_reboot_notifier = { + .notifier_call = cbe_ptcal_notify_reboot +}; + +int __init cbe_ptcal_init(void) +{ + int ret; + ptcal_start_tok = rtas_token("ibm,cbe-start-ptcal"); + ptcal_stop_tok = rtas_token("ibm,cbe-stop-ptcal"); + + if (ptcal_start_tok == RTAS_UNKNOWN_SERVICE + || ptcal_stop_tok == RTAS_UNKNOWN_SERVICE) + return -ENODEV; + + ret = register_reboot_notifier(&cbe_ptcal_reboot_notifier); + if (ret) { + printk(KERN_ERR "Can't disable PTCAL, so not enabling\n"); + return ret; + } + + return cbe_ptcal_enable(); +} + +arch_initcall(cbe_ptcal_init); + void __init cbe_ras_init(void) { unsigned long hid0; diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 36989c2eee6..54b96183cb6 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -71,7 +71,7 @@ static void cell_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); seq_printf(m, "machine\t\t: CHRP %s\n", model); of_node_put(root); } @@ -190,15 +190,6 @@ static int __init cell_probe(void) return 1; } -/* - * Cell has no legacy IO; anything calling this function has to - * fail or bad things will happen - */ -static int cell_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - define_machine(cell) { .name = "Cell", .probe = cell_probe, @@ -211,7 +202,6 @@ define_machine(cell) { .get_rtc_time = rtas_get_rtc_time, .set_rtc_time = rtas_set_rtc_time, .calibrate_decr = generic_calibrate_decr, - .check_legacy_ioport = cell_check_legacy_ioport, .progress = cell_progress, .init_IRQ = cell_init_irq, .pci_setup_phb = rtas_setup_phb, diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 21a9ebd4978..fb1f15797bb 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -254,25 +254,25 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic) } /* Now do the horrible hacks */ - tmp = get_property(pic->of_node, "#interrupt-cells", NULL); + tmp = of_get_property(pic->of_node, "#interrupt-cells", NULL); if (tmp == NULL) return NO_IRQ; intsize = *tmp; - imap = get_property(pic->of_node, "interrupt-map", &imaplen); + imap = of_get_property(pic->of_node, "interrupt-map", &imaplen); if (imap == NULL || imaplen < (intsize + 1)) return NO_IRQ; iic = of_find_node_by_phandle(imap[intsize]); if (iic == NULL) return NO_IRQ; imap += intsize + 1; - tmp = get_property(iic, "#interrupt-cells", NULL); + tmp = of_get_property(iic, "#interrupt-cells", NULL); if (tmp == NULL) return NO_IRQ; intsize = *tmp; /* Assume unit is last entry of interrupt specifier */ unit = imap[intsize - 1]; /* Ok, we have a unit, now let's try to get the node */ - tmp = get_property(iic, "ibm,interrupt-server-ranges", NULL); + tmp = of_get_property(iic, "ibm,interrupt-server-ranges", NULL); if (tmp == NULL) { of_node_put(iic); return NO_IRQ; diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index eba7a2641dc..fec51525252 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -36,12 +36,14 @@ #include <asm/xmon.h> const struct spu_management_ops *spu_management_ops; +EXPORT_SYMBOL_GPL(spu_management_ops); + const struct spu_priv1_ops *spu_priv1_ops; static struct list_head spu_list[MAX_NUMNODES]; static LIST_HEAD(spu_full_list); static DEFINE_MUTEX(spu_mutex); -static spinlock_t spu_list_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(spu_list_lock); EXPORT_SYMBOL_GPL(spu_priv1_ops); @@ -290,7 +292,6 @@ spu_irq_class_1(int irq, void *data) return stat ? IRQ_HANDLED : IRQ_NONE; } -EXPORT_SYMBOL_GPL(spu_irq_class_1_bottom); static irqreturn_t spu_irq_class_2(int irq, void *data) @@ -431,10 +432,11 @@ struct spu *spu_alloc_node(int node) spu = list_entry(spu_list[node].next, struct spu, list); list_del_init(&spu->list); pr_debug("Got SPU %d %d\n", spu->number, spu->node); - spu_init_channels(spu); } mutex_unlock(&spu_mutex); + if (spu) + spu_init_channels(spu); return spu; } EXPORT_SYMBOL_GPL(spu_alloc_node); @@ -461,108 +463,6 @@ void spu_free(struct spu *spu) } EXPORT_SYMBOL_GPL(spu_free); -static int spu_handle_mm_fault(struct spu *spu) -{ - struct mm_struct *mm = spu->mm; - struct vm_area_struct *vma; - u64 ea, dsisr, is_write; - int ret; - - ea = spu->dar; - dsisr = spu->dsisr; -#if 0 - if (!IS_VALID_EA(ea)) { - return -EFAULT; - } -#endif /* XXX */ - if (mm == NULL) { - return -EFAULT; - } - if (mm->pgd == NULL) { - return -EFAULT; - } - - down_read(&mm->mmap_sem); - vma = find_vma(mm, ea); - if (!vma) - goto bad_area; - if (vma->vm_start <= ea) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; -#if 0 - if (expand_stack(vma, ea)) - goto bad_area; -#endif /* XXX */ -good_area: - is_write = dsisr & MFC_DSISR_ACCESS_PUT; - if (is_write) { - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - } else { - if (dsisr & MFC_DSISR_ACCESS_DENIED) - goto bad_area; - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) - goto bad_area; - } - ret = 0; - switch (handle_mm_fault(mm, vma, ea, is_write)) { - case VM_FAULT_MINOR: - current->min_flt++; - break; - case VM_FAULT_MAJOR: - current->maj_flt++; - break; - case VM_FAULT_SIGBUS: - ret = -EFAULT; - goto bad_area; - case VM_FAULT_OOM: - ret = -ENOMEM; - goto bad_area; - default: - BUG(); - } - up_read(&mm->mmap_sem); - return ret; - -bad_area: - up_read(&mm->mmap_sem); - return -EFAULT; -} - -int spu_irq_class_1_bottom(struct spu *spu) -{ - u64 ea, dsisr, access, error = 0UL; - int ret = 0; - - ea = spu->dar; - dsisr = spu->dsisr; - if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) { - u64 flags; - - access = (_PAGE_PRESENT | _PAGE_USER); - access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; - local_irq_save(flags); - if (hash_page(ea, access, 0x300) != 0) - error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; - local_irq_restore(flags); - } - if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) { - if ((ret = spu_handle_mm_fault(spu)) != 0) - error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; - else - error &= ~CLASS1_ENABLE_STORAGE_FAULT_INTR; - } - spu->dar = 0UL; - spu->dsisr = 0UL; - if (!error) { - spu_restart_dma(spu); - } else { - spu->dma_callback(spu, SPE_EVENT_SPE_DATA_STORAGE); - } - return ret; -} - struct sysdev_class spu_sysdev_class = { set_kset_name("spu") }; @@ -636,12 +536,6 @@ static int spu_create_sysdev(struct spu *spu) return 0; } -static void spu_destroy_sysdev(struct spu *spu) -{ - sysfs_remove_device_from_node(&spu->sysdev, spu->node); - sysdev_unregister(&spu->sysdev); -} - static int __init create_spu(void *data) { struct spu *spu; @@ -693,58 +587,37 @@ out: return ret; } -static void destroy_spu(struct spu *spu) -{ - list_del_init(&spu->list); - list_del_init(&spu->full_list); - - spu_destroy_sysdev(spu); - spu_free_irqs(spu); - spu_destroy_spu(spu); - kfree(spu); -} - -static void cleanup_spu_base(void) -{ - struct spu *spu, *tmp; - int node; - - mutex_lock(&spu_mutex); - for (node = 0; node < MAX_NUMNODES; node++) { - list_for_each_entry_safe(spu, tmp, &spu_list[node], list) - destroy_spu(spu); - } - mutex_unlock(&spu_mutex); - sysdev_class_unregister(&spu_sysdev_class); -} -module_exit(cleanup_spu_base); - static int __init init_spu_base(void) { - int i, ret; + int i, ret = 0; + + for (i = 0; i < MAX_NUMNODES; i++) + INIT_LIST_HEAD(&spu_list[i]); if (!spu_management_ops) - return 0; + goto out; /* create sysdev class for spus */ ret = sysdev_class_register(&spu_sysdev_class); if (ret) - return ret; - - for (i = 0; i < MAX_NUMNODES; i++) - INIT_LIST_HEAD(&spu_list[i]); + goto out; ret = spu_enumerate_spus(create_spu); if (ret) { printk(KERN_WARNING "%s: Error initializing spus\n", __FUNCTION__); - cleanup_spu_base(); - return ret; + goto out_unregister_sysdev_class; } xmon_register_spus(&spu_full_list); + return 0; + + out_unregister_sysdev_class: + sysdev_class_unregister(&spu_sysdev_class); + out: + return ret; } module_init(init_spu_base); diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c index 6915b418ee7..4fd37ff1e21 100644 --- a/arch/powerpc/platforms/cell/spu_coredump.c +++ b/arch/powerpc/platforms/cell/spu_coredump.c @@ -26,19 +26,18 @@ #include <asm/spu.h> -static struct spu_coredump_calls spu_coredump_calls; +static struct spu_coredump_calls *spu_coredump_calls; static DEFINE_MUTEX(spu_coredump_mutex); int arch_notes_size(void) { long ret; - struct module *owner = spu_coredump_calls.owner; ret = -ENOSYS; mutex_lock(&spu_coredump_mutex); - if (owner && try_module_get(owner)) { - ret = spu_coredump_calls.arch_notes_size(); - module_put(owner); + if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) { + ret = spu_coredump_calls->arch_notes_size(); + module_put(spu_coredump_calls->owner); } mutex_unlock(&spu_coredump_mutex); return ret; @@ -46,36 +45,35 @@ int arch_notes_size(void) void arch_write_notes(struct file *file) { - struct module *owner = spu_coredump_calls.owner; - mutex_lock(&spu_coredump_mutex); - if (owner && try_module_get(owner)) { - spu_coredump_calls.arch_write_notes(file); - module_put(owner); + if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) { + spu_coredump_calls->arch_write_notes(file); + module_put(spu_coredump_calls->owner); } mutex_unlock(&spu_coredump_mutex); } int register_arch_coredump_calls(struct spu_coredump_calls *calls) { - if (spu_coredump_calls.owner) - return -EBUSY; + int ret = 0; + mutex_lock(&spu_coredump_mutex); - spu_coredump_calls.arch_notes_size = calls->arch_notes_size; - spu_coredump_calls.arch_write_notes = calls->arch_write_notes; - spu_coredump_calls.owner = calls->owner; + if (spu_coredump_calls) + ret = -EBUSY; + else + spu_coredump_calls = calls; mutex_unlock(&spu_coredump_mutex); - return 0; + return ret; } EXPORT_SYMBOL_GPL(register_arch_coredump_calls); void unregister_arch_coredump_calls(struct spu_coredump_calls *calls) { - BUG_ON(spu_coredump_calls.owner != calls->owner); + BUG_ON(spu_coredump_calls != calls); mutex_lock(&spu_coredump_mutex); - spu_coredump_calls.owner = NULL; + spu_coredump_calls = NULL; mutex_unlock(&spu_coredump_mutex); } EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls); diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index e34599f53d2..1d4562ae463 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c @@ -48,11 +48,11 @@ static u64 __init find_spu_unit_number(struct device_node *spe) { const unsigned int *prop; int proplen; - prop = get_property(spe, "unit-id", &proplen); + prop = of_get_property(spe, "unit-id", &proplen); if (proplen == 4) return (u64)*prop; - prop = get_property(spe, "reg", &proplen); + prop = of_get_property(spe, "reg", &proplen); if (proplen == 4) return (u64)*prop; @@ -76,12 +76,12 @@ static int __init spu_map_interrupts_old(struct spu *spu, int nid; /* Get the interrupt source unit from the device-tree */ - tmp = get_property(np, "isrc", NULL); + tmp = of_get_property(np, "isrc", NULL); if (!tmp) return -ENODEV; isrc = tmp[0]; - tmp = get_property(np->parent->parent, "node-id", NULL); + tmp = of_get_property(np->parent->parent, "node-id", NULL); if (!tmp) { printk(KERN_WARNING "%s: can't find node-id\n", __FUNCTION__); nid = spu->node; @@ -110,7 +110,7 @@ static void __iomem * __init spu_map_prop_old(struct spu *spu, } __attribute__((packed)) *prop; int proplen; - prop = get_property(n, name, &proplen); + prop = of_get_property(n, name, &proplen); if (prop == NULL || proplen != sizeof (struct address_prop)) return NULL; @@ -124,11 +124,11 @@ static int __init spu_map_device_old(struct spu *spu) int ret; ret = -ENODEV; - spu->name = get_property(node, "name", NULL); + spu->name = of_get_property(node, "name", NULL); if (!spu->name) goto out; - prop = get_property(node, "local-store", NULL); + prop = of_get_property(node, "local-store", NULL); if (!prop) goto out; spu->local_store_phys = *(unsigned long *)prop; @@ -139,7 +139,7 @@ static int __init spu_map_device_old(struct spu *spu) if (!spu->local_store) goto out; - prop = get_property(node, "problem", NULL); + prop = of_get_property(node, "problem", NULL); if (!prop) goto out_unmap; spu->problem_phys = *(unsigned long *)prop; @@ -226,7 +226,7 @@ static int __init spu_map_device(struct spu *spu) struct device_node *np = spu->devnode; int ret = -ENODEV; - spu->name = get_property(np, "name", NULL); + spu->name = of_get_property(np, "name", NULL); if (!spu->name) goto out; diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index 472217d19fa..2cd89c11af5 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -1,4 +1,4 @@ -obj-y += switch.o +obj-y += switch.o fault.o obj-$(CONFIG_SPU_FS) += spufs.o spufs-y += inode.o file.o context.o syscalls.o coredump.o diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c index 1898f0d3a8b..3322528fa6e 100644 --- a/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c @@ -350,6 +350,11 @@ static int spu_backing_send_mfc_command(struct spu_context *ctx, return ret; } +static void spu_backing_restart_dma(struct spu_context *ctx) +{ + /* nothing to do here */ +} + struct spu_context_ops spu_backing_ops = { .mbox_read = spu_backing_mbox_read, .mbox_stat_read = spu_backing_mbox_stat_read, @@ -376,4 +381,5 @@ struct spu_context_ops spu_backing_ops = { .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus, .get_mfc_free_elements = spu_backing_get_mfc_free_elements, .send_mfc_command = spu_backing_send_mfc_command, + .restart_dma = spu_backing_restart_dma, }; diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 04ad2e364e9..a87d9ca3dba 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c @@ -41,9 +41,10 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) goto out_free; } spin_lock_init(&ctx->mmio_lock); + spin_lock_init(&ctx->mapping_lock); kref_init(&ctx->kref); mutex_init(&ctx->state_mutex); - init_MUTEX(&ctx->run_sema); + mutex_init(&ctx->run_mutex); init_waitqueue_head(&ctx->ibox_wq); init_waitqueue_head(&ctx->wbox_wq); init_waitqueue_head(&ctx->stop_wq); @@ -51,6 +52,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) ctx->state = SPU_STATE_SAVED; ctx->ops = &spu_backing_ops; ctx->owner = get_task_mm(current); + INIT_LIST_HEAD(&ctx->rq); if (gang) spu_gang_add_ctx(gang, ctx); ctx->rt_priority = current->rt_priority; @@ -75,6 +77,7 @@ void destroy_spu_context(struct kref *kref) spu_fini_csa(&ctx->csa); if (ctx->gang) spu_gang_remove_ctx(ctx->gang, ctx); + BUG_ON(!list_empty(&ctx->rq)); kfree(ctx); } @@ -119,46 +122,6 @@ void spu_unmap_mappings(struct spu_context *ctx) } /** - * spu_acquire_exclusive - lock spu contex and protect against userspace access - * @ctx: spu contex to lock - * - * Note: - * Returns 0 and with the context locked on success - * Returns negative error and with the context _unlocked_ on failure. - */ -int spu_acquire_exclusive(struct spu_context *ctx) -{ - int ret = -EINVAL; - - spu_acquire(ctx); - /* - * Context is about to be freed, so we can't acquire it anymore. - */ - if (!ctx->owner) - goto out_unlock; - - if (ctx->state == SPU_STATE_SAVED) { - ret = spu_activate(ctx, 0); - if (ret) - goto out_unlock; - } else { - /* - * We need to exclude userspace access to the context. - * - * To protect against memory access we invalidate all ptes - * and make sure the pagefault handlers block on the mutex. - */ - spu_unmap_mappings(ctx); - } - - return 0; - - out_unlock: - spu_release(ctx); - return ret; -} - -/** * spu_acquire_runnable - lock spu contex and make sure it is in runnable state * @ctx: spu contex to lock * diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index 725e1956115..5d9ad5a0307 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c @@ -169,12 +169,12 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, struct spu_context *ctx; loff_t pos = 0; int sz, dfd, rc, total = 0; - const int bufsz = 4096; + const int bufsz = PAGE_SIZE; char *name; char fullname[80], *buf; struct elf_note en; - buf = kmalloc(bufsz, GFP_KERNEL); + buf = (void *)get_zeroed_page(GFP_KERNEL); if (!buf) return; @@ -187,9 +187,8 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, sz = spufs_coredump_read[i].size; ctx = ctx_info->ctx; - if (!ctx) { - return; - } + if (!ctx) + goto out; sprintf(fullname, "SPU/%d/%s", dfd, name); en.n_namesz = strlen(fullname) + 1; @@ -197,23 +196,25 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, en.n_type = NT_SPU; if (!spufs_dump_write(file, &en, sizeof(en))) - return; + goto out; if (!spufs_dump_write(file, fullname, en.n_namesz)) - return; + goto out; if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4))) - return; + goto out; do { rc = do_coredump_read(i, ctx, buf, bufsz, &pos); if (rc > 0) { if (!spufs_dump_write(file, buf, rc)) - return; + goto out; total += rc; } } while (rc == bufsz && total < sz); spufs_dump_seek(file, roundup((unsigned long)file->f_pos - total + sz, 4)); +out: + free_page((unsigned long)buf); } static void spufs_arch_write_notes(struct file *file) diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c new file mode 100644 index 00000000000..0f75c07e29d --- /dev/null +++ b/arch/powerpc/platforms/cell/spufs/fault.c @@ -0,0 +1,211 @@ +/* + * Low-level SPU handling + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * Author: Arnd Bergmann <arndb@de.ibm.com> + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/module.h> + +#include <asm/spu.h> +#include <asm/spu_csa.h> + +#include "spufs.h" + +/* + * This ought to be kept in sync with the powerpc specific do_page_fault + * function. Currently, there are a few corner cases that we haven't had + * to handle fortunately. + */ +static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr) +{ + struct vm_area_struct *vma; + unsigned long is_write; + int ret; + +#if 0 + if (!IS_VALID_EA(ea)) { + return -EFAULT; + } +#endif /* XXX */ + if (mm == NULL) { + return -EFAULT; + } + if (mm->pgd == NULL) { + return -EFAULT; + } + + down_read(&mm->mmap_sem); + vma = find_vma(mm, ea); + if (!vma) + goto bad_area; + if (vma->vm_start <= ea) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto bad_area; + if (expand_stack(vma, ea)) + goto bad_area; +good_area: + is_write = dsisr & MFC_DSISR_ACCESS_PUT; + if (is_write) { + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } else { + if (dsisr & MFC_DSISR_ACCESS_DENIED) + goto bad_area; + if (!(vma->vm_flags & (VM_READ | VM_EXEC))) + goto bad_area; + } + ret = 0; + switch (handle_mm_fault(mm, vma, ea, is_write)) { + case VM_FAULT_MINOR: + current->min_flt++; + break; + case VM_FAULT_MAJOR: + current->maj_flt++; + break; + case VM_FAULT_SIGBUS: + ret = -EFAULT; + goto bad_area; + case VM_FAULT_OOM: + ret = -ENOMEM; + goto bad_area; + default: + BUG(); + } + up_read(&mm->mmap_sem); + return ret; + +bad_area: + up_read(&mm->mmap_sem); + return -EFAULT; +} + +static void spufs_handle_dma_error(struct spu_context *ctx, + unsigned long ea, int type) +{ + if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) { + ctx->event_return |= type; + wake_up_all(&ctx->stop_wq); + } else { + siginfo_t info; + memset(&info, 0, sizeof(info)); + + switch (type) { + case SPE_EVENT_INVALID_DMA: + info.si_signo = SIGBUS; + info.si_code = BUS_OBJERR; + break; + case SPE_EVENT_SPE_DATA_STORAGE: + info.si_signo = SIGBUS; + info.si_addr = (void __user *)ea; + info.si_code = BUS_ADRERR; + break; + case SPE_EVENT_DMA_ALIGNMENT: + info.si_signo = SIGBUS; + /* DAR isn't set for an alignment fault :( */ + info.si_code = BUS_ADRALN; + break; + case SPE_EVENT_SPE_ERROR: + info.si_signo = SIGILL; + info.si_addr = (void __user *)(unsigned long) + ctx->ops->npc_read(ctx) - 4; + info.si_code = ILL_ILLOPC; + break; + } + if (info.si_signo) + force_sig_info(info.si_signo, &info, current); + } +} + +void spufs_dma_callback(struct spu *spu, int type) +{ + spufs_handle_dma_error(spu->ctx, spu->dar, type); +} +EXPORT_SYMBOL_GPL(spufs_dma_callback); + +/* + * bottom half handler for page faults, we can't do this from + * interrupt context, since we might need to sleep. + * we also need to give up the mutex so we can get scheduled + * out while waiting for the backing store. + * + * TODO: try calling hash_page from the interrupt handler first + * in order to speed up the easy case. + */ +int spufs_handle_class1(struct spu_context *ctx) +{ + u64 ea, dsisr, access; + unsigned long flags; + int ret; + + /* + * dar and dsisr get passed from the registers + * to the spu_context, to this function, but not + * back to the spu if it gets scheduled again. + * + * if we don't handle the fault for a saved context + * in time, we can still expect to get the same fault + * the immediately after the context restore. + */ + if (ctx->state == SPU_STATE_RUNNABLE) { + ea = ctx->spu->dar; + dsisr = ctx->spu->dsisr; + ctx->spu->dar= ctx->spu->dsisr = 0; + } else { + ea = ctx->csa.priv1.mfc_dar_RW; + dsisr = ctx->csa.priv1.mfc_dsisr_RW; + ctx->csa.priv1.mfc_dar_RW = 0; + ctx->csa.priv1.mfc_dsisr_RW = 0; + } + + if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) + return 0; + + pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea, + dsisr, ctx->state); + + /* we must not hold the lock when entering spu_handle_mm_fault */ + spu_release(ctx); + + access = (_PAGE_PRESENT | _PAGE_USER); + access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; + local_irq_save(flags); + ret = hash_page(ea, access, 0x300); + local_irq_restore(flags); + + /* hashing failed, so try the actual fault handler */ + if (ret) + ret = spu_handle_mm_fault(current->mm, ea, dsisr); + + spu_acquire(ctx); + /* + * If we handled the fault successfully and are in runnable + * state, restart the DMA. + * In case of unhandled error report the problem to user space. + */ + if (!ret) { + if (ctx->spu) + ctx->ops->restart_dma(ctx); + } else + spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); + + return ret; +} +EXPORT_SYMBOL_GPL(spufs_handle_class1); diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 505266a568d..d010b2464a9 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -44,9 +44,25 @@ spufs_mem_open(struct inode *inode, struct file *file) { struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); file->private_data = ctx; - ctx->local_store = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->local_store = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); + return 0; +} + +static int +spufs_mem_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->local_store = NULL; + spin_unlock(&ctx->mapping_lock); return 0; } @@ -149,6 +165,7 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) static const struct file_operations spufs_mem_fops = { .open = spufs_mem_open, + .release = spufs_mem_release, .read = spufs_mem_read, .write = spufs_mem_write, .llseek = generic_file_llseek, @@ -238,16 +255,33 @@ static int spufs_cntl_open(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; + spin_lock(&ctx->mapping_lock); file->private_data = ctx; - ctx->cntl = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->cntl = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return simple_attr_open(inode, file, spufs_cntl_get, spufs_cntl_set, "0x%08lx"); } +static int +spufs_cntl_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + simple_attr_close(inode, file); + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->cntl = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + static const struct file_operations spufs_cntl_fops = { .open = spufs_cntl_open, - .release = simple_attr_close, + .release = spufs_cntl_release, .read = simple_attr_read, .write = simple_attr_write, .mmap = spufs_cntl_mmap, @@ -723,12 +757,28 @@ static int spufs_signal1_open(struct inode *inode, struct file *file) { struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); file->private_data = ctx; - ctx->signal1 = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->signal1 = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } +static int +spufs_signal1_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->signal1 = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf, size_t len, loff_t *pos) { @@ -821,6 +871,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma) static const struct file_operations spufs_signal1_fops = { .open = spufs_signal1_open, + .release = spufs_signal1_release, .read = spufs_signal1_read, .write = spufs_signal1_write, .mmap = spufs_signal1_mmap, @@ -830,12 +881,28 @@ static int spufs_signal2_open(struct inode *inode, struct file *file) { struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); file->private_data = ctx; - ctx->signal2 = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->signal2 = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } +static int +spufs_signal2_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->signal2 = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf, size_t len, loff_t *pos) { @@ -932,6 +999,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma) static const struct file_operations spufs_signal2_fops = { .open = spufs_signal2_open, + .release = spufs_signal2_release, .read = spufs_signal2_read, .write = spufs_signal2_write, .mmap = spufs_signal2_mmap, @@ -1031,13 +1099,30 @@ static int spufs_mss_open(struct inode *inode, struct file *file) struct spu_context *ctx = i->i_ctx; file->private_data = i->i_ctx; - ctx->mss = inode->i_mapping; - smp_wmb(); + + spin_lock(&ctx->mapping_lock); + if (!i->i_openers++) + ctx->mss = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } +static int +spufs_mss_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->mss = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + static const struct file_operations spufs_mss_fops = { .open = spufs_mss_open, + .release = spufs_mss_release, .mmap = spufs_mss_mmap, }; @@ -1072,14 +1157,30 @@ static int spufs_psmap_open(struct inode *inode, struct file *file) struct spufs_inode_info *i = SPUFS_I(inode); struct spu_context *ctx = i->i_ctx; + spin_lock(&ctx->mapping_lock); file->private_data = i->i_ctx; - ctx->psmap = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->psmap = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } +static int +spufs_psmap_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->psmap = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + static const struct file_operations spufs_psmap_fops = { .open = spufs_psmap_open, + .release = spufs_psmap_release, .mmap = spufs_psmap_mmap, }; @@ -1126,12 +1227,27 @@ static int spufs_mfc_open(struct inode *inode, struct file *file) if (atomic_read(&inode->i_count) != 1) return -EBUSY; + spin_lock(&ctx->mapping_lock); file->private_data = ctx; - ctx->mfc = inode->i_mapping; - smp_wmb(); + if (!i->i_openers++) + ctx->mfc = inode->i_mapping; + spin_unlock(&ctx->mapping_lock); return nonseekable_open(inode, file); } +static int +spufs_mfc_release(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + spin_lock(&ctx->mapping_lock); + if (!--i->i_openers) + ctx->mfc = NULL; + spin_unlock(&ctx->mapping_lock); + return 0; +} + /* interrupt-level mfc callback function. */ void spufs_mfc_callback(struct spu *spu) { @@ -1313,7 +1429,10 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, if (ret) goto out; - spu_acquire_runnable(ctx, 0); + ret = spu_acquire_runnable(ctx, 0); + if (ret) + goto out; + if (file->f_flags & O_NONBLOCK) { ret = ctx->ops->send_mfc_command(ctx, &cmd); } else { @@ -1399,6 +1518,7 @@ static int spufs_mfc_fasync(int fd, struct file *file, int on) static const struct file_operations spufs_mfc_fops = { .open = spufs_mfc_open, + .release = spufs_mfc_release, .read = spufs_mfc_read, .write = spufs_mfc_write, .poll = spufs_mfc_poll, diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index ae42e03b8c8..428875c5e4e 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -296,6 +296,14 @@ static int spu_hw_send_mfc_command(struct spu_context *ctx, } } +static void spu_hw_restart_dma(struct spu_context *ctx) +{ + struct spu_priv2 __iomem *priv2 = ctx->spu->priv2; + + if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &ctx->spu->flags)) + out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); +} + struct spu_context_ops spu_hw_ops = { .mbox_read = spu_hw_mbox_read, .mbox_stat_read = spu_hw_mbox_stat_read, @@ -320,4 +328,5 @@ struct spu_context_ops spu_hw_ops = { .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus, .get_mfc_free_elements = spu_hw_get_mfc_free_elements, .send_mfc_command = spu_hw_send_mfc_command, + .restart_dma = spu_hw_restart_dma, }; diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 8079983ef94..13e4f70ec8c 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -36,6 +36,7 @@ #include <asm/prom.h> #include <asm/semaphore.h> #include <asm/spu.h> +#include <asm/spu_priv1.h> #include <asm/uaccess.h> #include "spufs.h" @@ -54,6 +55,7 @@ spufs_alloc_inode(struct super_block *sb) ei->i_gang = NULL; ei->i_ctx = NULL; + ei->i_openers = 0; return &ei->vfs_inode; } @@ -520,13 +522,14 @@ out: /* File system initialization */ enum { - Opt_uid, Opt_gid, Opt_err, + Opt_uid, Opt_gid, Opt_mode, Opt_err, }; static match_table_t spufs_tokens = { - { Opt_uid, "uid=%d" }, - { Opt_gid, "gid=%d" }, - { Opt_err, NULL }, + { Opt_uid, "uid=%d" }, + { Opt_gid, "gid=%d" }, + { Opt_mode, "mode=%o" }, + { Opt_err, NULL }, }; static int @@ -553,6 +556,11 @@ spufs_parse_options(char *options, struct inode *root) return 0; root->i_gid = option; break; + case Opt_mode: + if (match_octal(&args[0], &option)) + return 0; + root->i_mode = option | S_IFDIR; + break; default: return 0; } @@ -560,6 +568,11 @@ spufs_parse_options(char *options, struct inode *root) return 1; } +static void spufs_exit_isolated_loader(void) +{ + kfree(isolated_loader); +} + static void spufs_init_isolated_loader(void) { @@ -571,7 +584,7 @@ spufs_init_isolated_loader(void) if (!dn) return; - loader = get_property(dn, "loader", &size); + loader = of_get_property(dn, "loader", &size); if (!loader) return; @@ -653,6 +666,10 @@ static int __init spufs_init(void) { int ret; + ret = -ENODEV; + if (!spu_management_ops) + goto out; + ret = -ENOMEM; spufs_inode_cache = kmem_cache_create("spufs_inode_cache", sizeof(struct spufs_inode_info), 0, @@ -660,25 +677,29 @@ static int __init spufs_init(void) if (!spufs_inode_cache) goto out; - if (spu_sched_init() != 0) { - kmem_cache_destroy(spufs_inode_cache); - goto out; - } - ret = register_filesystem(&spufs_type); + ret = spu_sched_init(); if (ret) goto out_cache; + ret = register_filesystem(&spufs_type); + if (ret) + goto out_sched; ret = register_spu_syscalls(&spufs_calls); if (ret) goto out_fs; ret = register_arch_coredump_calls(&spufs_coredump_calls); if (ret) - goto out_fs; + goto out_syscalls; spufs_init_isolated_loader(); return 0; + +out_syscalls: + unregister_spu_syscalls(&spufs_calls); out_fs: unregister_filesystem(&spufs_type); +out_sched: + spu_sched_exit(); out_cache: kmem_cache_destroy(spufs_inode_cache); out: @@ -689,6 +710,7 @@ module_init(spufs_init); static void __exit spufs_exit(void) { spu_sched_exit(); + spufs_exit_isolated_loader(); unregister_arch_coredump_calls(&spufs_coredump_calls); unregister_spu_syscalls(&spufs_calls); unregister_filesystem(&spufs_type); diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index f95a611ca36..57626600b1a 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -18,27 +18,6 @@ void spufs_stop_callback(struct spu *spu) wake_up_all(&ctx->stop_wq); } -void spufs_dma_callback(struct spu *spu, int type) -{ - struct spu_context *ctx = spu->ctx; - - if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) { - ctx->event_return |= type; - wake_up_all(&ctx->stop_wq); - } else { - switch (type) { - case SPE_EVENT_DMA_ALIGNMENT: - case SPE_EVENT_SPE_DATA_STORAGE: - case SPE_EVENT_INVALID_DMA: - force_sig(SIGBUS, /* info, */ current); - break; - case SPE_EVENT_SPE_ERROR: - force_sig(SIGILL, /* info */ current); - break; - } - } -} - static inline int spu_stopped(struct spu_context *ctx, u32 * stat) { struct spu *spu; @@ -63,13 +42,18 @@ static int spu_setup_isolated(struct spu_context *ctx) const u32 status_loading = SPU_STATUS_RUNNING | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS; + ret = -ENODEV; if (!isolated_loader) - return -ENODEV; - - ret = spu_acquire_exclusive(ctx); - if (ret) goto out; + /* + * We need to exclude userspace access to the context. + * + * To protect against memory access we invalidate all ptes + * and make sure the pagefault handlers block on the mutex. + */ + spu_unmap_mappings(ctx); + mfc_cntl = &ctx->spu->priv2->mfc_control_RW; /* purge the MFC DMA queue to ensure no spurious accesses before we @@ -82,7 +66,7 @@ static int spu_setup_isolated(struct spu_context *ctx) printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n", __FUNCTION__); ret = -EIO; - goto out_unlock; + goto out; } cond_resched(); } @@ -119,12 +103,15 @@ static int spu_setup_isolated(struct spu_context *ctx) pr_debug("%s: isolated LOAD failed\n", __FUNCTION__); ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); ret = -EACCES; + goto out_drop_priv; + } - } else if (!(status & SPU_STATUS_ISOLATED_STATE)) { + if (!(status & SPU_STATUS_ISOLATED_STATE)) { /* This isn't allowed by the CBEA, but check anyway */ pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__); ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP); ret = -EINVAL; + goto out_drop_priv; } out_drop_priv: @@ -132,30 +119,19 @@ out_drop_priv: sr1 |= MFC_STATE1_PROBLEM_STATE_MASK; spu_mfc_sr1_set(ctx->spu, sr1); -out_unlock: - spu_release(ctx); out: return ret; } -static inline int spu_run_init(struct spu_context *ctx, u32 * npc) +static int spu_run_init(struct spu_context *ctx, u32 * npc) { - int ret; - unsigned long runcntl = SPU_RUNCNTL_RUNNABLE; - - ret = spu_acquire_runnable(ctx, 0); - if (ret) - return ret; - if (ctx->flags & SPU_CREATE_ISOLATE) { + unsigned long runcntl; + if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) { - /* Need to release ctx, because spu_setup_isolated will - * acquire it exclusively. - */ - spu_release(ctx); - ret = spu_setup_isolated(ctx); - if (!ret) - ret = spu_acquire_runnable(ctx, 0); + int ret = spu_setup_isolated(ctx); + if (ret) + return ret; } /* if userspace has set the runcntrl register (eg, to issue an @@ -164,16 +140,17 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc) (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); if (runcntl == 0) runcntl = SPU_RUNCNTL_RUNNABLE; + ctx->ops->runcntl_write(ctx, runcntl); } else { spu_start_tick(ctx); ctx->ops->npc_write(ctx, *npc); + ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); } - ctx->ops->runcntl_write(ctx, runcntl); - return ret; + return 0; } -static inline int spu_run_fini(struct spu_context *ctx, u32 * npc, +static int spu_run_fini(struct spu_context *ctx, u32 * npc, u32 * status) { int ret = 0; @@ -189,19 +166,27 @@ static inline int spu_run_fini(struct spu_context *ctx, u32 * npc, return ret; } -static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc, +static int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc, u32 *status) { int ret; - if ((ret = spu_run_fini(ctx, npc, status)) != 0) + ret = spu_run_fini(ctx, npc, status); + if (ret) return ret; - if (*status & (SPU_STATUS_STOPPED_BY_STOP | - SPU_STATUS_STOPPED_BY_HALT)) { + + if (*status & (SPU_STATUS_STOPPED_BY_STOP | SPU_STATUS_STOPPED_BY_HALT)) return *status; - } - if ((ret = spu_run_init(ctx, npc)) != 0) + + ret = spu_acquire_runnable(ctx, 0); + if (ret) + return ret; + + ret = spu_run_init(ctx, npc); + if (ret) { + spu_release(ctx); return ret; + } return 0; } @@ -253,17 +238,17 @@ int spu_process_callback(struct spu_context *ctx) { struct spu_syscall_block s; u32 ls_pointer, npc; - char *ls; + void __iomem *ls; long spu_ret; int ret; /* get syscall block from local store */ - npc = ctx->ops->npc_read(ctx); - ls = ctx->ops->get_ls(ctx); - ls_pointer = *(u32*)(ls + npc); + npc = ctx->ops->npc_read(ctx) & ~3; + ls = (void __iomem *)ctx->ops->get_ls(ctx); + ls_pointer = in_be32(ls + npc); if (ls_pointer > (LS_SIZE - sizeof(s))) return -EFAULT; - memcpy(&s, ls + ls_pointer, sizeof (s)); + memcpy_fromio(&s, ls + ls_pointer, sizeof(s)); /* do actual syscall without pinning the spu */ ret = 0; @@ -283,7 +268,7 @@ int spu_process_callback(struct spu_context *ctx) } /* write result, jump over indirect pointer */ - memcpy(ls + ls_pointer, &spu_ret, sizeof (spu_ret)); + memcpy_toio(ls + ls_pointer, &spu_ret, sizeof(spu_ret)); ctx->ops->npc_write(ctx, npc); ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); return ret; @@ -292,11 +277,8 @@ int spu_process_callback(struct spu_context *ctx) static inline int spu_process_events(struct spu_context *ctx) { struct spu *spu = ctx->spu; - u64 pte_fault = MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED; int ret = 0; - if (spu->dsisr & pte_fault) - ret = spu_irq_class_1_bottom(spu); if (spu->class_0_pending) ret = spu_irq_class_0_bottom(spu); if (!ret && signal_pending(current)) @@ -310,14 +292,21 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, int ret; u32 status; - if (down_interruptible(&ctx->run_sema)) + if (mutex_lock_interruptible(&ctx->run_mutex)) return -ERESTARTSYS; ctx->ops->master_start(ctx); ctx->event_return = 0; - ret = spu_run_init(ctx, npc); + + ret = spu_acquire_runnable(ctx, 0); if (ret) + return ret; + + ret = spu_run_init(ctx, npc); + if (ret) { + spu_release(ctx); goto out; + } do { ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status)); @@ -330,6 +319,10 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, break; status &= ~SPU_STATUS_STOPPED_BY_STOP; } + ret = spufs_handle_class1(ctx); + if (ret) + break; + if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { ret = spu_reacquire_runnable(ctx, npc, &status); if (ret) { @@ -363,6 +356,6 @@ out2: out: *event = ctx->event_return; - up(&ctx->run_sema); + mutex_unlock(&ctx->run_mutex); return ret; } diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 39823cec084..91030b8abdc 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -71,14 +71,27 @@ static inline int node_allowed(int node) void spu_start_tick(struct spu_context *ctx) { - if (ctx->policy == SCHED_RR) + if (ctx->policy == SCHED_RR) { + /* + * Make sure the exiting bit is cleared. + */ + clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags); + mb(); queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE); + } } void spu_stop_tick(struct spu_context *ctx) { - if (ctx->policy == SCHED_RR) + if (ctx->policy == SCHED_RR) { + /* + * While the work can be rearming normally setting this flag + * makes sure it does not rearm itself anymore. + */ + set_bit(SPU_SCHED_EXITING, &ctx->sched_flags); + mb(); cancel_delayed_work(&ctx->sched_work); + } } void spu_sched_tick(struct work_struct *work) @@ -86,7 +99,15 @@ void spu_sched_tick(struct work_struct *work) struct spu_context *ctx = container_of(work, struct spu_context, sched_work.work); struct spu *spu; - int rearm = 1; + int preempted = 0; + + /* + * If this context is being stopped avoid rescheduling from the + * scheduler tick because we would block on the state_mutex. + * The caller will yield the spu later on anyway. + */ + if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags)) + return; mutex_lock(&ctx->state_mutex); spu = ctx->spu; @@ -94,12 +115,19 @@ void spu_sched_tick(struct work_struct *work) int best = sched_find_first_bit(spu_prio->bitmap); if (best <= ctx->prio) { spu_deactivate(ctx); - rearm = 0; + preempted = 1; } } mutex_unlock(&ctx->state_mutex); - if (rearm) + if (preempted) { + /* + * We need to break out of the wait loop in spu_run manually + * to ensure this context gets put on the runqueue again + * ASAP. + */ + wake_up(&ctx->stop_wq); + } else spu_start_tick(ctx); } @@ -208,58 +236,40 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) * spu_add_to_rq - add a context to the runqueue * @ctx: context to add */ -static void spu_add_to_rq(struct spu_context *ctx) +static void __spu_add_to_rq(struct spu_context *ctx) { - spin_lock(&spu_prio->runq_lock); - list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]); - set_bit(ctx->prio, spu_prio->bitmap); - spin_unlock(&spu_prio->runq_lock); -} + int prio = ctx->prio; -/** - * spu_del_from_rq - remove a context from the runqueue - * @ctx: context to remove - */ -static void spu_del_from_rq(struct spu_context *ctx) -{ - spin_lock(&spu_prio->runq_lock); - list_del_init(&ctx->rq); - if (list_empty(&spu_prio->runq[ctx->prio])) - clear_bit(ctx->prio, spu_prio->bitmap); - spin_unlock(&spu_prio->runq_lock); + list_add_tail(&ctx->rq, &spu_prio->runq[prio]); + set_bit(prio, spu_prio->bitmap); } -/** - * spu_grab_context - remove one context from the runqueue - * @prio: priority of the context to be removed - * - * This function removes one context from the runqueue for priority @prio. - * If there is more than one context with the given priority the first - * task on the runqueue will be taken. - * - * Returns the spu_context it just removed. - * - * Must be called with spu_prio->runq_lock held. - */ -static struct spu_context *spu_grab_context(int prio) +static void __spu_del_from_rq(struct spu_context *ctx) { - struct list_head *rq = &spu_prio->runq[prio]; + int prio = ctx->prio; - if (list_empty(rq)) - return NULL; - return list_entry(rq->next, struct spu_context, rq); + if (!list_empty(&ctx->rq)) + list_del_init(&ctx->rq); + if (list_empty(&spu_prio->runq[prio])) + clear_bit(prio, spu_prio->bitmap); } static void spu_prio_wait(struct spu_context *ctx) { DEFINE_WAIT(wait); + spin_lock(&spu_prio->runq_lock); prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE); if (!signal_pending(current)) { + __spu_add_to_rq(ctx); + spin_unlock(&spu_prio->runq_lock); mutex_unlock(&ctx->state_mutex); schedule(); mutex_lock(&ctx->state_mutex); + spin_lock(&spu_prio->runq_lock); + __spu_del_from_rq(ctx); } + spin_unlock(&spu_prio->runq_lock); __set_current_state(TASK_RUNNING); remove_wait_queue(&ctx->stop_wq, &wait); } @@ -280,9 +290,14 @@ static void spu_reschedule(struct spu *spu) spin_lock(&spu_prio->runq_lock); best = sched_find_first_bit(spu_prio->bitmap); if (best < MAX_PRIO) { - struct spu_context *ctx = spu_grab_context(best); - if (ctx) - wake_up(&ctx->stop_wq); + struct list_head *rq = &spu_prio->runq[best]; + struct spu_context *ctx; + + BUG_ON(list_empty(rq)); + + ctx = list_entry(rq->next, struct spu_context, rq); + __spu_del_from_rq(ctx); + wake_up(&ctx->stop_wq); } spin_unlock(&spu_prio->runq_lock); } @@ -365,6 +380,12 @@ static struct spu *find_victim(struct spu_context *ctx) } spu_unbind_context(spu, victim); mutex_unlock(&victim->state_mutex); + /* + * We need to break out of the wait loop in spu_run + * manually to ensure this context gets put on the + * runqueue again ASAP. + */ + wake_up(&victim->stop_wq); return spu; } } @@ -377,7 +398,7 @@ static struct spu *find_victim(struct spu_context *ctx) * @ctx: spu context to schedule * @flags: flags (currently ignored) * - * Tries to find a free spu to run @ctx. If no free spu is availble + * Tries to find a free spu to run @ctx. If no free spu is available * add the context to the runqueue so it gets woken up once an spu * is available. */ @@ -402,9 +423,7 @@ int spu_activate(struct spu_context *ctx, unsigned long flags) return 0; } - spu_add_to_rq(ctx); spu_prio_wait(ctx); - spu_del_from_rq(ctx); } while (!signal_pending(current)); return -ERESTARTSYS; @@ -438,7 +457,6 @@ void spu_deactivate(struct spu_context *ctx) void spu_yield(struct spu_context *ctx) { struct spu *spu; - int need_yield = 0; if (mutex_trylock(&ctx->state_mutex)) { if ((spu = ctx->spu) != NULL) { @@ -447,13 +465,10 @@ void spu_yield(struct spu_context *ctx) pr_debug("%s: yielding SPU %d NODE %d\n", __FUNCTION__, spu->number, spu->node); spu_deactivate(ctx); - need_yield = 1; } } mutex_unlock(&ctx->state_mutex); } - if (unlikely(need_yield)) - yield(); } int __init spu_sched_init(void) diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 5c4e47d69d7..0a947fd7de5 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -41,7 +41,7 @@ struct spu_gang; /* ctx->sched_flags */ enum { - SPU_SCHED_WAKE = 0, /* currently unused */ + SPU_SCHED_EXITING = 0, }; struct spu_context { @@ -50,16 +50,17 @@ struct spu_context { spinlock_t mmio_lock; /* protects mmio access */ struct address_space *local_store; /* local store mapping. */ struct address_space *mfc; /* 'mfc' area mappings. */ - struct address_space *cntl; /* 'control' area mappings. */ - struct address_space *signal1; /* 'signal1' area mappings. */ - struct address_space *signal2; /* 'signal2' area mappings. */ - struct address_space *mss; /* 'mss' area mappings. */ - struct address_space *psmap; /* 'psmap' area mappings. */ + struct address_space *cntl; /* 'control' area mappings. */ + struct address_space *signal1; /* 'signal1' area mappings. */ + struct address_space *signal2; /* 'signal2' area mappings. */ + struct address_space *mss; /* 'mss' area mappings. */ + struct address_space *psmap; /* 'psmap' area mappings. */ + spinlock_t mapping_lock; u64 object_id; /* user space pointer for oprofile */ enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; struct mutex state_mutex; - struct semaphore run_sema; + struct mutex run_mutex; struct mm_struct *owner; @@ -140,6 +141,7 @@ struct spu_context_ops { struct spu_dma_info * info); void (*proxydma_info_read) (struct spu_context * ctx, struct spu_proxydma_info * info); + void (*restart_dma)(struct spu_context *ctx); }; extern struct spu_context_ops spu_hw_ops; @@ -149,6 +151,7 @@ struct spufs_inode_info { struct spu_context *i_ctx; struct spu_gang *i_gang; struct inode vfs_inode; + int i_openers; }; #define SPUFS_I(inode) \ container_of(inode, struct spufs_inode_info, vfs_inode) @@ -170,6 +173,9 @@ int put_spu_gang(struct spu_gang *gang); void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx); void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx); +/* fault handling */ +int spufs_handle_class1(struct spu_context *ctx); + /* context management */ static inline void spu_acquire(struct spu_context *ctx) { @@ -190,7 +196,6 @@ void spu_unmap_mappings(struct spu_context *ctx); void spu_forget(struct spu_context *ctx); int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags); void spu_acquire_saved(struct spu_context *ctx); -int spu_acquire_exclusive(struct spu_context *ctx); int spu_activate(struct spu_context *ctx, unsigned long flags); void spu_deactivate(struct spu_context *ctx); @@ -218,14 +223,13 @@ extern char *isolated_loader; prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \ if (condition) \ break; \ - if (!signal_pending(current)) { \ - spu_release(ctx); \ - schedule(); \ - spu_acquire(ctx); \ - continue; \ + if (signal_pending(current)) { \ + __ret = -ERESTARTSYS; \ + break; \ } \ - __ret = -ERESTARTSYS; \ - break; \ + spu_release(ctx); \ + schedule(); \ + spu_acquire(ctx); \ } \ finish_wait(&(wq), &__wait); \ __ret; \ diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index fd91c73de34..8347c4a3f89 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2084,6 +2084,10 @@ int spu_save(struct spu_state *prev, struct spu *spu) int rc; acquire_spu_lock(spu); /* Step 1. */ + prev->dar = spu->dar; + prev->dsisr = spu->dsisr; + spu->dar = 0; + spu->dsisr = 0; rc = __do_spu_save(prev, spu); /* Steps 2-53. */ release_spu_lock(spu); if (rc != 0 && rc != 2 && rc != 6) { @@ -2109,9 +2113,9 @@ int spu_restore(struct spu_state *new, struct spu *spu) acquire_spu_lock(spu); harvest(NULL, spu); - spu->dar = 0; - spu->dsisr = 0; spu->slb_replace = 0; + new->dar = 0; + new->dsisr = 0; spu->class_0_pending = 0; rc = __do_spu_restore(new, spu); release_spu_lock(spu); diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig new file mode 100644 index 00000000000..2db1e293433 --- /dev/null +++ b/arch/powerpc/platforms/celleb/Kconfig @@ -0,0 +1,9 @@ +config PPC_CELLEB + bool "Toshiba's Cell Reference Set 'Celleb' Architecture" + depends on PPC_MULTIPLATFORM && PPC64 + select PPC_CELL + select PPC_OF_PLATFORM_PCI + select HAS_TXX9_SERIAL + select PPC_UDBG_BEAT + select USB_OHCI_BIG_ENDIAN_MMIO + select USB_EHCI_BIG_ENDIAN_MMIO diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c index f63b94c6535..755d869d855 100644 --- a/arch/powerpc/platforms/celleb/iommu.c +++ b/arch/powerpc/platforms/celleb/iommu.c @@ -37,7 +37,7 @@ static int __init find_dma_window(u64 *io_space_id, u64 *ioid, const unsigned long *dma_window; for_each_node_by_type(dn, "ioif") { - dma_window = get_property(dn, "toshiba,dma-window", NULL); + dma_window = of_get_property(dn, "toshiba,dma-window", NULL); if (dma_window) { *io_space_id = (dma_window[0] >> 32) & 0xffffffffUL; *ioid = dma_window[0] & 0x7ffUL; @@ -80,7 +80,7 @@ static int celleb_of_bus_notify(struct notifier_block *nb, if (action != BUS_NOTIFY_ADD_DEVICE) return 0; - dev->archdata.dma_ops = pci_dma_ops; + dev->archdata.dma_ops = get_pci_dma_ops(); return 0; } @@ -95,7 +95,7 @@ static int __init celleb_init_iommu(void) return -ENODEV; celleb_init_direct_mapping(); - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier); return 0; diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c index 98de836dfed..d1adf34cd5e 100644 --- a/arch/powerpc/platforms/celleb/pci.c +++ b/arch/powerpc/platforms/celleb/pci.c @@ -309,13 +309,13 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node, goto error; } - name = get_property(node, "model", &rlen); + name = of_get_property(node, "model", &rlen); if (!name) { printk(KERN_ERR "PCI: model property not found.\n"); goto error; } - wi4 = get_property(node, "reg", &rlen); + wi4 = of_get_property(node, "reg", &rlen); if (wi4 == NULL) goto error; @@ -352,10 +352,10 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node, } pr_debug("PCI: res assigned 0x%016lx\n", (unsigned long)*res); - wi0 = get_property(node, "device-id", NULL); - wi1 = get_property(node, "vendor-id", NULL); - wi2 = get_property(node, "class-code", NULL); - wi3 = get_property(node, "revision-id", NULL); + wi0 = of_get_property(node, "device-id", NULL); + wi1 = of_get_property(node, "vendor-id", NULL); + wi2 = of_get_property(node, "class-code", NULL); + wi3 = of_get_property(node, "revision-id", NULL); celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff); celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff); @@ -376,7 +376,7 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node, celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr); - li = get_property(node, "interrupts", &rlen); + li = of_get_property(node, "interrupts", &rlen); val = li[0]; celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1); celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val); @@ -424,7 +424,7 @@ static int __devinit phb_set_bus_ranges(struct device_node *dev, const int *bus_range; unsigned int len; - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) return 1; @@ -451,7 +451,7 @@ int __devinit celleb_setup_phb(struct pci_controller *phb) struct device_node *node; unsigned int rlen; - name = get_property(dev, "name", &rlen); + name = of_get_property(dev, "name", &rlen); if (!name) return 1; diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c index 5f4d0d93323..596ab2a788d 100644 --- a/arch/powerpc/platforms/celleb/setup.c +++ b/arch/powerpc/platforms/celleb/setup.c @@ -67,7 +67,7 @@ static void celleb_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); /* using "CHRP" is to trick anaconda into installing FCx into Celleb */ seq_printf(m, "machine\t\t: %s %s\n", celleb_machine_type, model); of_node_put(root); @@ -128,15 +128,6 @@ static int __init celleb_probe(void) return 1; } -/* - * Cell has no legacy IO; anything calling this function has to - * fail or bad things will happen - */ -static int celleb_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - #ifdef CONFIG_KEXEC static void celleb_kexec_cpu_down(int crash, int secondary) { @@ -173,7 +164,6 @@ define_machine(celleb) { .get_rtc_time = beat_get_rtc_time, .set_rtc_time = beat_set_rtc_time, .calibrate_decr = generic_calibrate_decr, - .check_legacy_ioport = celleb_check_legacy_ioport, .progress = celleb_progress, .power_save = beat_power_save, .nvram_size = beat_nvram_get_size, diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig new file mode 100644 index 00000000000..d2c69053196 --- /dev/null +++ b/arch/powerpc/platforms/chrp/Kconfig @@ -0,0 +1,11 @@ +config PPC_CHRP + bool "Common Hardware Reference Platform (CHRP) based machines" + depends on PPC_MULTIPLATFORM && PPC32 + select MPIC + select PPC_I8259 + select PPC_INDIRECT_PCI + select PPC_RTAS + select PPC_MPC106 + select PPC_UDBG_16550 + select PPC_NATIVE + default y diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c index 0dd4a64757d..8efd4244701 100644 --- a/arch/powerpc/platforms/chrp/nvram.c +++ b/arch/powerpc/platforms/chrp/nvram.c @@ -74,7 +74,7 @@ void __init chrp_nvram_init(void) if (nvram == NULL) return; - nbytes_p = get_property(nvram, "#bytes", &proplen); + nbytes_p = of_get_property(nvram, "#bytes", &proplen); if (nbytes_p == NULL || proplen != sizeof(unsigned int)) return; diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index ddb4a116ea8..1469d6478f6 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -7,7 +7,6 @@ #include <linux/delay.h> #include <linux/string.h> #include <linux/init.h> -#include <linux/ide.h> #include <asm/io.h> #include <asm/pgtable.h> @@ -137,9 +136,11 @@ hydra_init(void) struct device_node *np; struct resource r; - np = find_devices("mac-io"); - if (np == NULL || of_address_to_resource(np, 0, &r)) + np = of_find_node_by_name(NULL, "mac-io"); + if (np == NULL || of_address_to_resource(np, 0, &r)) { + of_node_put(np); return 0; + } Hydra = ioremap(r.start, r.end-r.start); printk("Hydra Mac I/O at %llx\n", (unsigned long long)r.start); printk("Hydra Feature_Control was %x", @@ -186,10 +187,9 @@ setup_python(struct pci_controller *hose, struct device_node *dev) /* Marvell Discovery II based Pegasos 2 */ static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev) { - struct device_node *root = find_path_device("/"); + struct device_node *root = of_find_node_by_path("/"); struct device_node *rtas; - of_node_get(root); rtas = of_find_node_by_name (root, "rtas"); if (rtas) { hose->ops = &rtas_pci_ops; @@ -199,6 +199,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d " your firmware\n"); } pci_assign_all_buses = 1; + /* keep the reference to the root node */ } void __init @@ -211,14 +212,14 @@ chrp_find_bridges(void) const unsigned int *dma; const char *model, *machine; int is_longtrail = 0, is_mot = 0, is_pegasos = 0; - struct device_node *root = find_path_device("/"); + struct device_node *root = of_find_node_by_path("/"); struct resource r; /* * The PCI host bridge nodes on some machines don't have * properties to adequately identify them, so we have to * look at what sort of machine this is as well. */ - machine = get_property(root, "model", NULL); + machine = of_get_property(root, "model", NULL); if (machine != NULL) { is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0; is_mot = strncmp(machine, "MOT", 3) == 0; @@ -237,7 +238,7 @@ chrp_find_bridges(void) dev->full_name); continue; } - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s\n", dev->full_name); @@ -263,7 +264,7 @@ chrp_find_bridges(void) hose->first_busno = bus_range[0]; hose->last_busno = bus_range[1]; - model = get_property(dev, "model", NULL); + model = of_get_property(dev, "model", NULL); if (model == NULL) model = "<none>"; if (device_is_compatible(dev, "IBM,python")) { @@ -285,7 +286,8 @@ chrp_find_bridges(void) r.start + 0x000f8000, r.start + 0x000f8010); if (index == 0) { - dma = get_property(dev, "system-dma-base",&len); + dma = of_get_property(dev, "system-dma-base", + &len); if (dma && len >= sizeof(*dma)) { dma = (unsigned int *) (((unsigned long)dma) + @@ -303,12 +305,13 @@ chrp_find_bridges(void) /* check the first bridge for a property that we can use to set pci_dram_offset */ - dma = get_property(dev, "ibm,dma-ranges", &len); + dma = of_get_property(dev, "ibm,dma-ranges", &len); if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) { pci_dram_offset = dma[2] - dma[3]; printk("pci_dram_offset = %lx\n", pci_dram_offset); } } + of_node_put(root); } /* SL82C105 IDE Control/Status Register */ diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 117c9a0055b..1870038a8e0 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -28,7 +28,6 @@ #include <linux/adb.h> #include <linux/module.h> #include <linux/delay.h> -#include <linux/ide.h> #include <linux/console.h> #include <linux/seq_file.h> #include <linux/root_dev.h> @@ -111,9 +110,9 @@ void chrp_show_cpuinfo(struct seq_file *m) struct device_node *root; const char *model = ""; - root = find_path_device("/"); + root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); seq_printf(m, "machine\t\t: CHRP %s\n", model); /* longtrail (goldengate) stuff */ @@ -161,6 +160,7 @@ void chrp_show_cpuinfo(struct seq_file *m) gg2_cachetypes[(t>>2) & 3], gg2_cachemodes[t & 3]); } + of_node_put(root); } /* @@ -205,13 +205,15 @@ static void __init sio_init(void) { struct device_node *root; - if ((root = find_path_device("/")) && - !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) { + if ((root = of_find_node_by_path("/")) && + !strncmp(of_get_property(root, "model", NULL), + "IBM,LongTrail", 13)) { /* logical device 0 (KBC/Keyboard) */ sio_fixup_irq("keyboard", 0, 1, 2); /* select logical device 1 (KBC/Mouse) */ sio_fixup_irq("mouse", 1, 12, 2); } + of_node_put(root); } @@ -224,12 +226,12 @@ static void __init pegasos_set_l2cr(void) return; /* Enable L2 cache if needed */ - np = find_type_devices("cpu"); + np = of_find_node_by_type(NULL, "cpu"); if (np != NULL) { - const unsigned int *l2cr = get_property(np, "l2cr", NULL); + const unsigned int *l2cr = of_get_property(np, "l2cr", NULL); if (l2cr == NULL) { printk ("Pegasos l2cr : no cpu l2cr property found\n"); - return; + goto out; } if (!((*l2cr) & 0x80000000)) { printk ("Pegasos l2cr : L2 cache was not active, " @@ -238,6 +240,8 @@ static void __init pegasos_set_l2cr(void) _set_L2CR((*l2cr) | 0x80000000); } } +out: + of_node_put(np); } static void briq_restart(char *cmd) @@ -250,14 +254,14 @@ static void briq_restart(char *cmd) void __init chrp_setup_arch(void) { - struct device_node *root = find_path_device ("/"); + struct device_node *root = of_find_node_by_path("/"); const char *machine = NULL; /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000/HZ; if (root) - machine = get_property(root, "model", NULL); + machine = of_get_property(root, "model", NULL); if (machine && strncmp(machine, "Pegasos", 7) == 0) { _chrp_type = _CHRP_Pegasos; } else if (machine && strncmp(machine, "IBM", 3) == 0) { @@ -273,6 +277,7 @@ void __init chrp_setup_arch(void) /* Let's assume it is an IBM chrp if all else fails */ _chrp_type = _CHRP_IBM; } + of_node_put(root); printk("chrp type = %x [%s]\n", _chrp_type, chrp_names[_chrp_type]); rtas_initialize(); @@ -361,8 +366,8 @@ static void __init chrp_find_openpic(void) return; root = of_find_node_by_path("/"); if (root) { - opprop = get_property(root, "platform-open-pic", &oplen); - na = prom_n_addr_cells(root); + opprop = of_get_property(root, "platform-open-pic", &oplen); + na = of_n_addr_cells(root); } if (opprop && oplen >= na * sizeof(unsigned int)) { opaddr = opprop[na-1]; /* assume 32-bit */ @@ -378,7 +383,7 @@ static void __init chrp_find_openpic(void) printk(KERN_INFO "OpenPIC at %lx\n", opaddr); - iranges = get_property(np, "interrupt-ranges", &len); + iranges = of_get_property(np, "interrupt-ranges", &len); if (iranges == NULL) len = 0; /* non-distributed mpic */ else @@ -427,7 +432,7 @@ static void __init chrp_find_openpic(void) of_node_put(np); } -#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) +#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON) static struct irqaction xmon_irqaction = { .handler = xmon_irq, .mask = CPU_MASK_NONE, @@ -463,15 +468,16 @@ static void __init chrp_find_8259(void) * Also, Pegasos-type platforms don't have a proper node to start * from anyway */ - for (np = find_devices("pci"); np != NULL; np = np->next) { - const unsigned int *addrp = get_property(np, + for_each_node_by_name(np, "pci") { + const unsigned int *addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL); if (addrp == NULL) continue; - chrp_int_ack = addrp[prom_n_addr_cells(np)-1]; + chrp_int_ack = addrp[of_n_addr_cells(np)-1]; break; } + of_node_put(np); if (np == NULL) printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" " address, polling\n"); @@ -493,7 +499,7 @@ static void __init chrp_find_8259(void) void __init chrp_init_IRQ(void) { -#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) +#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON) struct device_node *kbd; #endif chrp_find_openpic(); @@ -510,13 +516,14 @@ void __init chrp_init_IRQ(void) if (_chrp_type == _CHRP_Pegasos) ppc_md.get_irq = i8259_irq; -#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) +#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON) /* see if there is a keyboard in the device tree with a parent of type "adb" */ - for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) + for_each_node_by_name(kbd, "keyboard") if (kbd->parent && kbd->parent->type && strcmp(kbd->parent->type, "adb") == 0) break; + of_node_put(kbd); if (kbd) setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction); #endif @@ -542,9 +549,9 @@ chrp_init2(void) /* Get the event scan rate for the rtas so we know how * often it expects a heartbeat. -- Cort */ - device = find_devices("rtas"); + device = of_find_node_by_name(NULL, "rtas"); if (device) - p = get_property(device, "rtas-event-scan-rate", NULL); + p = of_get_property(device, "rtas-event-scan-rate", NULL); if (p && *p) { /* * Arrange to call chrp_event_scan at least *p times @@ -571,6 +578,7 @@ chrp_init2(void) printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", *p, interval); } + of_node_put(device); if (ppc_md.progress) ppc_md.progress(" Have fun! ", 0x7777); diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 7d788902693..96d1e4b3c49 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -39,12 +39,17 @@ long __init chrp_time_init(void) struct resource r; int base; - rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); + rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00"); if (rtcs == NULL) - rtcs = find_compatible_devices("rtc", "ds1385-rtc"); - if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r)) + rtcs = of_find_compatible_node(NULL, "rtc", "ds1385-rtc"); + if (rtcs == NULL) + return 0; + if (of_address_to_resource(rtcs, 0, &r)) { + of_node_put(rtcs); return 0; - + } + of_node_put(rtcs); + base = r.start; nvram_as1 = 0; nvram_as0 = base; diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 3410bcbc9db..9557908ef54 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig @@ -2,78 +2,6 @@ choice prompt "Machine Type" depends on EMBEDDED6xx -config KATANA - bool "Artesyn-Katana" - help - Select KATANA if configuring an Artesyn KATANA 750i or 3750 - cPCI board. - -config WILLOW - bool "Cogent-Willow" - -config CPCI690 - bool "Force-CPCI690" - help - Select CPCI690 if configuring a Force CPCI690 cPCI board. - -config POWERPMC250 - bool "Force-PowerPMC250" - -config CHESTNUT - bool "IBM 750FX Eval board or 750GX Eval board" - help - Select CHESTNUT if configuring an IBM 750FX Eval Board or a - IBM 750GX Eval board. - -config SPRUCE - bool "IBM-Spruce" - select PPC_INDIRECT_PCI - -config HDPU - bool "Sky-HDPU" - help - Select HDPU if configuring a Sky Computers Compute Blade. - -config HDPU_FEATURES - depends on HDPU - tristate "HDPU-Features" - help - Select to enable HDPU enhanced features. - -config EV64260 - bool "Marvell-EV64260BP" - help - Select EV64260 if configuring a Marvell (formerly Galileo) - EV64260BP Evaluation platform. - -config LOPEC - bool "Motorola-LoPEC" - select PPC_I8259 - -config MVME5100 - bool "Motorola-MVME5100" - select PPC_INDIRECT_PCI - -config PPLUS - bool "Motorola-PowerPlus" - select PPC_I8259 - select PPC_INDIRECT_PCI - -config PRPMC750 - bool "Motorola-PrPMC750" - select PPC_INDIRECT_PCI - -config PRPMC800 - bool "Motorola-PrPMC800" - select PPC_INDIRECT_PCI - -config SANDPOINT - bool "Motorola-Sandpoint" - select PPC_I8259 - help - Select SANDPOINT if configuring for a Motorola Sandpoint X3 - (any flavor). - config LINKSTATION bool "Linkstation / Kurobox(HG) from Buffalo" select MPIC @@ -97,212 +25,24 @@ config MPC7448HPC2 help Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga) platform - -config RADSTONE_PPC7D - bool "Radstone Technology PPC7D board" - select PPC_I8259 - -config PAL4 - bool "SBS-Palomar4" - -config EST8260 - bool "EST8260" - ---help--- - The EST8260 is a single-board computer manufactured by Wind River - Systems, Inc. (formerly Embedded Support Tools Corp.) and based on - the MPC8260. Wind River Systems has a website at - <http://www.windriver.com/>, but the EST8260 cannot be found on it - and has probably been discontinued or rebadged. - -config SBC82xx - bool "SBC82xx" - ---help--- - SBC PowerQUICC II, single-board computer with MPC82xx CPU - Manufacturer: Wind River Systems, Inc. - Date of Release: May 2003 - End of Life: - - URL: <http://www.windriver.com/> - -config SBS8260 - bool "SBS8260" - -config RPX8260 - bool "RPXSUPER" - -config TQM8260 - bool "TQM8260" - ---help--- - MPC8260 based module, little larger than credit card, - up to 128 MB global + 64 MB local RAM, 32 MB Flash, - 32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet, - 2 x serial ports, ... - Manufacturer: TQ Components, www.tq-group.de - Date of Release: June 2001 - End of Life: not yet :-) - URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf> - -config ADS8272 - bool "ADS8272" - -config PQ2FADS - bool "Freescale-PQ2FADS" - help - Select PQ2FADS if you wish to configure for a Freescale - PQ2FADS board (-VR or -ZU). - -config EV64360 - bool "Marvell-EV64360BP" - help - Select EV64360 if configuring a Marvell EV64360BP Evaluation - platform. endchoice -config PQ2ADS - bool - depends on ADS8272 - default y - -config TQM8xxL - bool - depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L) - default y - -config 8260 - bool "CPM2 Support" if WILLOW - depends on 6xx - default y if TQM8260 || RPX8260 || EST8260 || SBS8260 || SBC82xx || PQ2FADS - help - The MPC8260 is a typical embedded CPU made by Motorola. Selecting - this option means that you wish to build a kernel for a machine with - an 8260 class CPU. - -config 8272 - bool - depends on 6xx - default y if ADS8272 - select 8260 - help - The MPC8272 CPM has a different internal dpram setup than other CPM2 - devices - -config CPM2 - bool - depends on 8260 || MPC8560 || MPC8555 - default y - help - The CPM2 (Communications Processor Module) is a coprocessor on - embedded CPUs made by Motorola. Selecting this option means that - you wish to build a kernel for a machine with a CPM2 coprocessor - on it (826x, 827x, 8560). - -config PPC_GEN550 - bool - depends on SANDPOINT || SPRUCE || PPLUS || \ - PRPMC750 || PRPMC800 || LOPEC || \ - (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \ - 83xx || LINKSTATION - default y - -config FORCE - bool - depends on 6xx && POWERPMC250 - default y - -config GT64260 - bool - depends on EV64260 || CPCI690 - default y - -config MV64360 # Really MV64360 & MV64460 - bool - depends on CHESTNUT || KATANA || RADSTONE_PPC7D || HDPU || EV64360 - default y - -config MV64X60 - bool - depends on (GT64260 || MV64360) - select PPC_INDIRECT_PCI - default y - config TSI108_BRIDGE bool depends on MPC7448HPC2 default y -menu "Set bridge options" - depends on MV64X60 - -config NOT_COHERENT_CACHE - bool "Turn off Cache Coherency" - default n - help - Some 64x60 bridges lock up when trying to enforce cache coherency. - When this option is selected, cache coherency will be turned off. - Note that this can cause other problems (e.g., stale data being - speculatively loaded via a cached mapping). Use at your own risk. - -config MV64X60_BASE - hex "Set bridge base used by firmware" - default "0xf1000000" - help - A firmware can leave the base address of the bridge's registers at - a non-standard location. If so, set this value to reflect the - address of that non-standard location. - -config MV64X60_NEW_BASE - hex "Set bridge base used by kernel" - default "0xf1000000" - help - If the current base address of the bridge's registers is not where - you want it, set this value to the address that you want it moved to. - -endmenu - -config NONMONARCH_SUPPORT - bool "Enable Non-Monarch Support" - depends on PRPMC800 - -config HARRIER - bool - depends on PRPMC800 - default y - -config EPIC_SERIAL_MODE - bool - depends on 6xx && (LOPEC || SANDPOINT) - default y - config MPC10X_BRIDGE bool - depends on POWERPMC250 || LOPEC || SANDPOINT || LINKSTATION + depends on LINKSTATION select PPC_INDIRECT_PCI default y config MPC10X_OPENPIC bool - depends on POWERPMC250 || LOPEC || SANDPOINT || LINKSTATION + depends on LINKSTATION default y config MPC10X_STORE_GATHERING bool "Enable MPC10x store gathering" depends on MPC10X_BRIDGE - -config SANDPOINT_ENABLE_UART1 - bool "Enable DUART mode on Sandpoint" - depends on SANDPOINT - help - If this option is enabled then the MPC824x processor will run - in DUART mode instead of UART mode. - -config HARRIER_STORE_GATHERING - bool "Enable Harrier store gathering" - depends on HARRIER - -config MVME5100_IPMC761_PRESENT - bool "MVME5100 configured with an IPMC761" - depends on MVME5100 - select PPC_I8259 - -config SPRUCE_BAUD_33M - bool "Spruce baud clock support" - depends on SPRUCE diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index 3f6c4114f90..b412f006a9c 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c @@ -58,11 +58,11 @@ static int __init add_bridge(struct device_node *dev) { int len; struct pci_controller *hose; - int *bus_range; + const int *bus_range; printk("Adding PCI host bridge %s\n", dev->full_name); - bus_range = (int *) get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); @@ -106,7 +106,7 @@ static void __init linkstation_init_IRQ(void) { struct mpic *mpic; struct device_node *dnp; - void *prop; + const u32 *prop; int size; phys_addr_t paddr; @@ -114,7 +114,7 @@ static void __init linkstation_init_IRQ(void) if (dnp == NULL) return; - prop = (struct device_node *)get_property(dnp, "reg", &size); + prop = of_get_property(dnp, "reg", &size); paddr = (phys_addr_t)of_translate_address(dnp, prop); mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, 4, 32, " EPIC "); diff --git a/arch/powerpc/platforms/embedded6xx/ls_uart.c b/arch/powerpc/platforms/embedded6xx/ls_uart.c index 0e837762cc5..d0bee9f19e4 100644 --- a/arch/powerpc/platforms/embedded6xx/ls_uart.c +++ b/arch/powerpc/platforms/embedded6xx/ls_uart.c @@ -110,8 +110,8 @@ static int __init ls_uarts_init(void) if (!avr) return -EINVAL; - avr_clock = *(u32*)get_property(avr, "clock-frequency", &len); - phys_addr = ((u32*)get_property(avr, "reg", &len))[0]; + avr_clock = *(u32*)of_get_property(avr, "clock-frequency", &len); + phys_addr = ((u32*)of_get_property(avr, "reg", &len))[0]; if (!avr_clock || !phys_addr) return -EINVAL; diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 3fcc85f60fb..c3f64ddb0be 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -25,7 +25,6 @@ #include <linux/console.h> #include <linux/delay.h> #include <linux/irq.h> -#include <linux/ide.h> #include <linux/seq_file.h> #include <linux/root_dev.h> #include <linux/serial.h> @@ -82,7 +81,7 @@ static void __init mpc7448_hpc2_setup_arch(void) if (cpu != 0) { const unsigned int *fp; - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else @@ -91,16 +90,6 @@ static void __init mpc7448_hpc2_setup_arch(void) } tsi108_csr_vir_base = get_vir_csrbase(); -#ifdef CONFIG_ROOT_NFS - ROOT_DEV = Root_NFS; -#else - ROOT_DEV = Root_HDA1; -#endif - -#ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = Root_RAM0; -#endif - /* setup PCI host bridge */ #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) @@ -143,7 +132,7 @@ static void __init mpc7448_hpc2_init_IRQ(void) tsi_pic = of_find_node_by_type(NULL, "open-pic"); if (tsi_pic) { unsigned int size; - const void *prop = get_property(tsi_pic, "reg", &size); + const void *prop = of_get_property(tsi_pic, "reg", &size); mpic_paddr = of_translate_address(tsi_pic, prop); } diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig index 54e6b3b6f26..46c3a8e7c3a 100644 --- a/arch/powerpc/platforms/iseries/Kconfig +++ b/arch/powerpc/platforms/iseries/Kconfig @@ -1,3 +1,7 @@ +config PPC_ISERIES + bool "IBM Legacy iSeries" + depends on PPC_MULTIPLATFORM && PPC64 + select PPC_INDIRECT_IO menu "iSeries device drivers" depends on PPC_ISERIES diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index d7a756d5135..3b6a9666c2c 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -171,7 +171,7 @@ void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn) { struct iommu_table *tbl; struct pci_dn *pdn = PCI_DN(dn); - const u32 *lsn = get_property(dn, "linux,logical-slot-number", NULL); + const u32 *lsn = of_get_property(dn, "linux,logical-slot-number", NULL); BUG_ON(lsn == NULL); @@ -194,5 +194,5 @@ void iommu_init_early_iSeries(void) ppc_md.tce_build = tce_build_iSeries; ppc_md.tce_free = tce_free_iSeries; - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); } diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 5225abfafd9..63b33675848 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -30,7 +30,6 @@ #include <linux/param.h> #include <linux/string.h> #include <linux/bootmem.h> -#include <linux/ide.h> #include <linux/irq.h> #include <linux/spinlock.h> @@ -337,6 +336,8 @@ unsigned int iSeries_get_irq(void) return irq; } +#ifdef CONFIG_PCI + static int iseries_irq_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { @@ -384,3 +385,4 @@ void __init iSeries_init_IRQ(void) "failed with rc 0x%x\n", ret); } +#endif /* CONFIG_PCI */ diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 4a06d9c3498..9c974227155 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -24,7 +24,6 @@ #include <linux/string.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/ide.h> #include <linux/pci.h> #include <asm/io.h> @@ -177,7 +176,7 @@ void __init iSeries_pci_final_fixup(void) struct pci_dn *pdn = PCI_DN(node); const u32 *agent; - agent = get_property(node, "linux,agent-id", NULL); + agent = of_get_property(node, "linux,agent-id", NULL); if ((pdn != NULL) && (agent != NULL)) { u8 irq = iSeries_allocate_IRQ(pdn->busno, 0, pdn->bussubno); @@ -755,7 +754,7 @@ void __init iSeries_pcibios_init(void) if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) continue; - busp = get_property(node, "bus-range", NULL); + busp = of_get_property(node, "bus-range", NULL); if (busp == NULL) continue; bus = *busp; diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index cce7e309340..7f5dcee814d 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -628,15 +628,6 @@ static void iseries_iounmap(volatile void __iomem *token) { } -/* - * iSeries has no legacy IO, anything calling this function has to - * fail or bad things will happen - */ -static int iseries_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - static int __init iseries_probe(void) { unsigned long root = of_get_flat_dt_root(); @@ -667,7 +658,6 @@ define_machine(iseries) { .calibrate_decr = generic_calibrate_decr, .progress = iSeries_progress, .probe = iseries_probe, - .check_legacy_ioport = iseries_check_legacy_ioport, .ioremap = iseries_ioremap, .iounmap = iseries_iounmap, /* XXX Implement enable_pmcs for iSeries */ diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index e2100ece9c6..2ca2d8a9de9 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -155,7 +155,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) node = of_find_node_by_path("/"); sysid = NULL; if (node != NULL) - sysid = get_property(node, "system-id", NULL); + sysid = of_get_property(node, "system-id", NULL); if (sysid == NULL) seq_printf(m, "SRLNBR=<UNKNOWN>\n"); diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig new file mode 100644 index 00000000000..f7c95eb5d8b --- /dev/null +++ b/arch/powerpc/platforms/maple/Kconfig @@ -0,0 +1,17 @@ +config PPC_MAPLE + depends on PPC_MULTIPLATFORM && PPC64 + bool "Maple 970FX Evaluation Board" + select MPIC + select U3_DART + select MPIC_U3_HT_IRQS + select GENERIC_TBSYNC + select PPC_UDBG_16550 + select PPC_970_NAP + select PPC_NATIVE + select PPC_RTAS + select MMIO_NVRAM + select ATA_NONSTANDARD if ATA + default n + help + This option enables support for the Maple 970FX Evaluation Board. + For more information, refer to <http://www.970eval.com> diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 73c59904697..b1d3b99c3f9 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -44,11 +44,11 @@ static int __init fixup_one_level_bus_range(struct device_node *node, int higher int len; /* For PCI<->PCI bridges or CardBus bridges, we go down */ - class_code = get_property(node, "class-code", NULL); + class_code = of_get_property(node, "class-code", NULL); if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) continue; - bus_range = get_property(node, "bus-range", &len); + bus_range = of_get_property(node, "bus-range", &len); if (bus_range != NULL && len > 2 * sizeof(int)) { if (bus_range[1] > higher) higher = bus_range[1]; @@ -77,7 +77,7 @@ static void __init fixup_bus_range(struct device_node *bridge) bridge->full_name); return; } - bus_range = (int *)prop->value; + bus_range = prop->value; bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); } @@ -454,7 +454,7 @@ static int __init add_bridge(struct device_node *dev) DBG("Adding PCI host bridge %s\n", dev->full_name); - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", dev->full_name); diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 82d3f9e28d7..2a30c5b2532 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -32,7 +32,6 @@ #include <linux/initrd.h> #include <linux/vt_kern.h> #include <linux/console.h> -#include <linux/ide.h> #include <linux/pci.h> #include <linux/adb.h> #include <linux/cuda.h> @@ -114,8 +113,8 @@ static void maple_restart(char *cmd) printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); goto fail; } - maple_nvram_offset = get_property(sp, "restart-addr", NULL); - maple_nvram_command = get_property(sp, "restart-value", NULL); + maple_nvram_offset = of_get_property(sp, "restart-addr", NULL); + maple_nvram_command = of_get_property(sp, "restart-value", NULL); of_node_put(sp); /* send command */ @@ -141,8 +140,8 @@ static void maple_power_off(void) printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); goto fail; } - maple_nvram_offset = get_property(sp, "power-off-addr", NULL); - maple_nvram_command = get_property(sp, "power-off-value", NULL); + maple_nvram_offset = of_get_property(sp, "power-off-addr", NULL); + maple_nvram_command = of_get_property(sp, "power-off-value", NULL); of_node_put(sp); /* send command */ @@ -249,8 +248,8 @@ static void __init maple_init_IRQ(void) /* Find address list in /platform-open-pic */ root = of_find_node_by_path("/"); - naddr = prom_n_addr_cells(root); - opprop = get_property(root, "platform-open-pic", &opplen); + naddr = of_n_addr_cells(root); + opprop = of_get_property(root, "platform-open-pic", &opplen); if (opprop != 0) { openpic_addr = of_read_number(opprop, naddr); has_isus = (opplen > naddr); @@ -261,11 +260,11 @@ static void __init maple_init_IRQ(void) BUG_ON(openpic_addr == 0); /* Check for a big endian MPIC */ - if (get_property(np, "big-endian", NULL) != NULL) + if (of_get_property(np, "big-endian", NULL) != NULL) flags |= MPIC_BIG_ENDIAN; /* XXX Maple specific bits */ - flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET; + flags |= MPIC_U3_HT_IRQS | MPIC_WANTS_RESET; /* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */ flags |= MPIC_BIG_ENDIAN; diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig index 68dc529dfd2..eb4dbc705b0 100644 --- a/arch/powerpc/platforms/pasemi/Kconfig +++ b/arch/powerpc/platforms/pasemi/Kconfig @@ -1,3 +1,15 @@ +config PPC_PASEMI + depends on PPC_MULTIPLATFORM && PPC64 + bool "PA Semi SoC-based platforms" + default n + select MPIC + select PPC_UDBG_16550 + select GENERIC_TBSYNC + select PPC_NATIVE + help + This option enables support for PA Semi's PWRficient line + of SoC processors, including PA6T-1682M + menu "PA Semi PWRficient options" depends on PPC_PASEMI @@ -7,4 +19,11 @@ config PPC_PASEMI_IOMMU help IOMMU support for PA6T-1682M +config PPC_PASEMI_MDIO + depends on PHYLIB + tristate "MDIO support via GPIO" + default y + help + Driver for MDIO via GPIO on PWRficient platforms + endmenu diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile index e657ccae90a..2cd2a4f26a4 100644 --- a/arch/powerpc/platforms/pasemi/Makefile +++ b/arch/powerpc/platforms/pasemi/Makefile @@ -1,2 +1,3 @@ obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o - +obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o +obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c new file mode 100644 index 00000000000..2a57d602368 --- /dev/null +++ b/arch/powerpc/platforms/pasemi/cpufreq.c @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2007 PA Semi, Inc + * + * Authors: Egor Martovetsky <egor@pasemi.com> + * Olof Johansson <olof@lixom.net> + * + * Maintained by: Olof Johansson <olof@lixom.net> + * + * Based on arch/powerpc/platforms/cell/cbe_cpufreq.c: + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/cpufreq.h> +#include <linux/timer.h> + +#include <asm/hw_irq.h> +#include <asm/io.h> +#include <asm/prom.h> + +#define SDCASR_REG 0x0100 +#define SDCASR_REG_STRIDE 0x1000 +#define SDCPWR_CFGA0_REG 0x0100 +#define SDCPWR_PWST0_REG 0x0000 +#define SDCPWR_GIZTIME_REG 0x0440 + +/* SDCPWR_GIZTIME_REG fields */ +#define SDCPWR_GIZTIME_GR 0x80000000 +#define SDCPWR_GIZTIME_LONGLOCK 0x000000ff + +/* Offset of ASR registers from SDC base */ +#define SDCASR_OFFSET 0x120000 + +static void __iomem *sdcpwr_mapbase; +static void __iomem *sdcasr_mapbase; + +static DEFINE_MUTEX(pas_switch_mutex); + +/* Current astate, is used when waking up from power savings on + * one core, in case the other core has switched states during + * the idle time. + */ +static int current_astate; + +/* We support 5(A0-A4) power states excluding turbo(A5-A6) modes */ +static struct cpufreq_frequency_table pas_freqs[] = { + {0, 0}, + {1, 0}, + {2, 0}, + {3, 0}, + {4, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr *pas_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +/* + * hardware specific functions + */ + +static int get_astate_freq(int astate) +{ + u32 ret; + ret = in_le32(sdcpwr_mapbase + SDCPWR_CFGA0_REG + (astate * 0x10)); + + return ret & 0x3f; +} + +static int get_cur_astate(int cpu) +{ + u32 ret; + + ret = in_le32(sdcpwr_mapbase + SDCPWR_PWST0_REG); + ret = (ret >> (cpu * 4)) & 0x7; + + return ret; +} + +static int get_gizmo_latency(void) +{ + u32 giztime, ret; + + giztime = in_le32(sdcpwr_mapbase + SDCPWR_GIZTIME_REG); + + /* just provide the upper bound */ + if (giztime & SDCPWR_GIZTIME_GR) + ret = (giztime & SDCPWR_GIZTIME_LONGLOCK) * 128000; + else + ret = (giztime & SDCPWR_GIZTIME_LONGLOCK) * 1000; + + return ret; +} + +static void set_astate(int cpu, unsigned int astate) +{ + u64 flags; + + /* Return if called before init has run */ + if (unlikely(!sdcasr_mapbase)) + return; + + local_irq_save(flags); + + out_le32(sdcasr_mapbase + SDCASR_REG + SDCASR_REG_STRIDE*cpu, astate); + + local_irq_restore(flags); +} + +void restore_astate(int cpu) +{ + set_astate(cpu, current_astate); +} + +/* + * cpufreq functions + */ + +static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + const u32 *max_freqp; + u32 max_freq; + int i, cur_astate; + struct resource res; + struct device_node *cpu, *dn; + int err = -ENODEV; + + cpu = of_get_cpu_node(policy->cpu, NULL); + + if (!cpu) + goto out; + + dn = of_find_compatible_node(NULL, "sdc", "1682m-sdc"); + if (!dn) + goto out; + err = of_address_to_resource(dn, 0, &res); + of_node_put(dn); + if (err) + goto out; + sdcasr_mapbase = ioremap(res.start + SDCASR_OFFSET, 0x2000); + if (!sdcasr_mapbase) { + err = -EINVAL; + goto out; + } + + dn = of_find_compatible_node(NULL, "gizmo", "1682m-gizmo"); + if (!dn) { + err = -ENODEV; + goto out_unmap_sdcasr; + } + err = of_address_to_resource(dn, 0, &res); + of_node_put(dn); + if (err) + goto out_unmap_sdcasr; + sdcpwr_mapbase = ioremap(res.start, 0x1000); + if (!sdcpwr_mapbase) { + err = -EINVAL; + goto out_unmap_sdcasr; + } + + pr_debug("init cpufreq on CPU %d\n", policy->cpu); + + max_freqp = of_get_property(cpu, "clock-frequency", NULL); + if (!max_freqp) { + err = -EINVAL; + goto out_unmap_sdcpwr; + } + + /* we need the freq in kHz */ + max_freq = *max_freqp / 1000; + + pr_debug("max clock-frequency is at %u kHz\n", max_freq); + pr_debug("initializing frequency table\n"); + + /* initialize frequency table */ + for (i=0; pas_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) { + pas_freqs[i].frequency = get_astate_freq(pas_freqs[i].index) * 100000; + pr_debug("%d: %d\n", i, pas_freqs[i].frequency); + } + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + + policy->cpuinfo.transition_latency = get_gizmo_latency(); + + cur_astate = get_cur_astate(policy->cpu); + pr_debug("current astate is at %d\n",cur_astate); + + policy->cur = pas_freqs[cur_astate].frequency; + policy->cpus = cpu_online_map; + + cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu); + + /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max + * are set correctly + */ + return cpufreq_frequency_table_cpuinfo(policy, pas_freqs); + +out_unmap_sdcpwr: + iounmap(sdcpwr_mapbase); + +out_unmap_sdcasr: + iounmap(sdcasr_mapbase); +out: + return err; +} + +static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy) +{ + if (sdcasr_mapbase) + iounmap(sdcasr_mapbase); + if (sdcpwr_mapbase) + iounmap(sdcpwr_mapbase); + + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + +static int pas_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, pas_freqs); +} + +static int pas_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_freqs freqs; + int pas_astate_new; + int i; + + cpufreq_frequency_table_target(policy, + pas_freqs, + target_freq, + relation, + &pas_astate_new); + + freqs.old = policy->cur; + freqs.new = pas_freqs[pas_astate_new].frequency; + freqs.cpu = policy->cpu; + + mutex_lock(&pas_switch_mutex); + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", + policy->cpu, + pas_freqs[pas_astate_new].frequency, + pas_freqs[pas_astate_new].index); + + current_astate = pas_astate_new; + + for_each_online_cpu(i) + set_astate(i, pas_astate_new); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + mutex_unlock(&pas_switch_mutex); + + return 0; +} + +static struct cpufreq_driver pas_cpufreq_driver = { + .name = "pas-cpufreq", + .owner = THIS_MODULE, + .flags = CPUFREQ_CONST_LOOPS, + .init = pas_cpufreq_cpu_init, + .exit = pas_cpufreq_cpu_exit, + .verify = pas_cpufreq_verify, + .target = pas_cpufreq_target, + .attr = pas_cpu_freqs_attr, +}; + +/* + * module init and destoy + */ + +static int __init pas_cpufreq_init(void) +{ + if (!machine_is_compatible("PA6T-1682M")) + return -ENODEV; + + return cpufreq_register_driver(&pas_cpufreq_driver); +} + +static void __exit pas_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&pas_cpufreq_driver); +} + +module_init(pas_cpufreq_init); +module_exit(pas_cpufreq_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>, Olof Johansson <olof@lixom.net>"); diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c new file mode 100644 index 00000000000..c91a33593bb --- /dev/null +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2006-2007 PA Semi, Inc + * + * Author: Olof Johansson, PA Semi + * + * Maintained by: Olof Johansson <olof@lixom.net> + * + * Based on drivers/net/fs_enet/mii-bitbang.c. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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/io.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/interrupt.h> +#include <linux/phy.h> +#include <linux/platform_device.h> +#include <asm/of_platform.h> + +#define DELAY 1 + +static void __iomem *gpio_regs; + +struct gpio_priv { + int mdc_pin; + int mdio_pin; +}; + +#define MDC_PIN(bus) (((struct gpio_priv *)bus->priv)->mdc_pin) +#define MDIO_PIN(bus) (((struct gpio_priv *)bus->priv)->mdio_pin) + +static inline void mdio_lo(struct mii_bus *bus) +{ + out_le32(gpio_regs+0x10, 1 << MDIO_PIN(bus)); +} + +static inline void mdio_hi(struct mii_bus *bus) +{ + out_le32(gpio_regs, 1 << MDIO_PIN(bus)); +} + +static inline void mdc_lo(struct mii_bus *bus) +{ + out_le32(gpio_regs+0x10, 1 << MDC_PIN(bus)); +} + +static inline void mdc_hi(struct mii_bus *bus) +{ + out_le32(gpio_regs, 1 << MDC_PIN(bus)); +} + +static inline void mdio_active(struct mii_bus *bus) +{ + out_le32(gpio_regs+0x20, (1 << MDC_PIN(bus)) | (1 << MDIO_PIN(bus))); +} + +static inline void mdio_tristate(struct mii_bus *bus) +{ + out_le32(gpio_regs+0x30, (1 << MDIO_PIN(bus))); +} + +static inline int mdio_read(struct mii_bus *bus) +{ + return !!(in_le32(gpio_regs+0x40) & (1 << MDIO_PIN(bus))); +} + +static void clock_out(struct mii_bus *bus, int bit) +{ + if (bit) + mdio_hi(bus); + else + mdio_lo(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + mdc_lo(bus); +} + +/* Utility to send the preamble, address, and register (common to read and write). */ +static void bitbang_pre(struct mii_bus *bus, int read, u8 addr, u8 reg) +{ + int i; + + /* CFE uses a really long preamble (40 bits). We'll do the same. */ + mdio_active(bus); + for (i = 0; i < 40; i++) { + clock_out(bus, 1); + } + + /* send the start bit (01) and the read opcode (10) or write (10) */ + clock_out(bus, 0); + clock_out(bus, 1); + + clock_out(bus, read); + clock_out(bus, !read); + + /* send the PHY address */ + for (i = 0; i < 5; i++) { + clock_out(bus, (addr & 0x10) != 0); + addr <<= 1; + } + + /* send the register address */ + for (i = 0; i < 5; i++) { + clock_out(bus, (reg & 0x10) != 0); + reg <<= 1; + } +} + +static int gpio_mdio_read(struct mii_bus *bus, int phy_id, int location) +{ + u16 rdreg; + int ret, i; + u8 addr = phy_id & 0xff; + u8 reg = location & 0xff; + + bitbang_pre(bus, 1, addr, reg); + + /* tri-state our MDIO I/O pin so we can read */ + mdio_tristate(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + mdc_lo(bus); + + /* read 16 bits of register data, MSB first */ + rdreg = 0; + for (i = 0; i < 16; i++) { + mdc_lo(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + mdc_lo(bus); + udelay(DELAY); + rdreg <<= 1; + rdreg |= mdio_read(bus); + } + + mdc_hi(bus); + udelay(DELAY); + mdc_lo(bus); + udelay(DELAY); + + ret = rdreg; + + return ret; +} + +static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 val) +{ + int i; + + u8 addr = phy_id & 0xff; + u8 reg = location & 0xff; + u16 value = val & 0xffff; + + bitbang_pre(bus, 0, addr, reg); + + /* send the turnaround (10) */ + mdc_lo(bus); + mdio_hi(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + mdc_lo(bus); + mdio_lo(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + + /* write 16 bits of register data, MSB first */ + for (i = 0; i < 16; i++) { + mdc_lo(bus); + if (value & 0x8000) + mdio_hi(bus); + else + mdio_lo(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + value <<= 1; + } + + /* + * Tri-state the MDIO line. + */ + mdio_tristate(bus); + mdc_lo(bus); + udelay(DELAY); + mdc_hi(bus); + udelay(DELAY); + return 0; +} + +static int gpio_mdio_reset(struct mii_bus *bus) +{ + /*nothing here - dunno how to reset it*/ + return 0; +} + + +static int __devinit gpio_mdio_probe(struct of_device *ofdev, + const struct of_device_id *match) +{ + struct device *dev = &ofdev->dev; + struct device_node *np = ofdev->node; + struct device_node *gpio_np; + struct mii_bus *new_bus; + struct resource res; + struct gpio_priv *priv; + const unsigned int *prop; + int err = 0; + int i; + + gpio_np = of_find_compatible_node(NULL, "gpio", "1682m-gpio"); + + if (!gpio_np) + return -ENODEV; + + err = of_address_to_resource(gpio_np, 0, &res); + of_node_put(gpio_np); + + if (err) + return -EINVAL; + + if (!gpio_regs) + gpio_regs = ioremap(res.start, 0x100); + + if (!gpio_regs) + return -EPERM; + + priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); + + if (new_bus == NULL) + return -ENOMEM; + + new_bus->name = "pasemi gpio mdio bus", + new_bus->read = &gpio_mdio_read, + new_bus->write = &gpio_mdio_write, + new_bus->reset = &gpio_mdio_reset, + + prop = of_get_property(np, "reg", NULL); + new_bus->id = *prop; + new_bus->priv = priv; + + new_bus->phy_mask = 0; + + new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); + for(i = 0; i < PHY_MAX_ADDR; ++i) + new_bus->irq[i] = irq_create_mapping(NULL, 10); + + + prop = of_get_property(np, "mdc-pin", NULL); + priv->mdc_pin = *prop; + + prop = of_get_property(np, "mdio-pin", NULL); + priv->mdio_pin = *prop; + + new_bus->dev = dev; + dev_set_drvdata(dev, new_bus); + + err = mdiobus_register(new_bus); + + if (0 != err) { + printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n", + new_bus->name, err); + goto bus_register_fail; + } + + return 0; + +bus_register_fail: + kfree(new_bus); + + return err; +} + + +static int gpio_mdio_remove(struct of_device *dev) +{ + struct mii_bus *bus = dev_get_drvdata(&dev->dev); + + mdiobus_unregister(bus); + + dev_set_drvdata(&dev->dev, NULL); + + kfree(bus->priv); + bus->priv = NULL; + kfree(bus); + + return 0; +} + +static struct of_device_id gpio_mdio_match[] = +{ + { + .compatible = "gpio-mdio", + }, + {}, +}; + +static struct of_platform_driver gpio_mdio_driver = +{ + .name = "gpio-mdio-bitbang", + .match_table = gpio_mdio_match, + .probe = gpio_mdio_probe, + .remove = gpio_mdio_remove, +}; + +int gpio_mdio_init(void) +{ + return of_register_platform_driver(&gpio_mdio_driver); +} + +void gpio_mdio_exit(void) +{ + of_unregister_platform_driver(&gpio_mdio_driver); +} +device_initcall(gpio_mdio_init); + diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c index 1ca3ff38159..5985ce0c5c4 100644 --- a/arch/powerpc/platforms/pasemi/idle.c +++ b/arch/powerpc/platforms/pasemi/idle.c @@ -61,6 +61,10 @@ static int pasemi_system_reset_exception(struct pt_regs *regs) /* do system reset */ return 0; } + + /* Set higher astate since we come out of power savings at 0 */ + restore_astate(hard_smp_processor_id()); + /* everything handled */ regs->msr |= MSR_RI; return 1; @@ -68,6 +72,11 @@ static int pasemi_system_reset_exception(struct pt_regs *regs) void __init pasemi_idle_init(void) { +#ifndef CONFIG_PPC_PASEMI_CPUFREQ + printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n"); + current_mode = 0; +#endif + ppc_md.system_reset_exception = pasemi_system_reset_exception; ppc_md.power_save = modes[current_mode].entry; printk(KERN_INFO "Using PA6T idle loop (%s)\n", modes[current_mode].name); diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index 71dbf1a56e1..95fa6a7d15e 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c @@ -249,13 +249,13 @@ void iommu_init_early_pasemi(void) iommu_off = 1; #else iommu_off = of_chosen && - get_property(of_chosen, "linux,iommu-off", NULL); + of_get_property(of_chosen, "linux,iommu-off", NULL); #endif if (iommu_off) { /* Direct I/O, IOMMU off */ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_null; ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_null; - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); return; } @@ -266,7 +266,7 @@ void iommu_init_early_pasemi(void) ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pasemi; ppc_md.tce_build = iobmap_build; ppc_md.tce_free = iobmap_free; - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); } void __init alloc_iobmap_l2(void) diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h index 2d3927e6edb..be849549761 100644 --- a/arch/powerpc/platforms/pasemi/pasemi.h +++ b/arch/powerpc/platforms/pasemi/pasemi.h @@ -14,6 +14,14 @@ extern void __init pasemi_idle_init(void); extern void idle_spin(void); extern void idle_doze(void); +/* Restore astate to last set */ +#ifdef CONFIG_PPC_PASEMI_CPUFREQ +extern void restore_astate(int cpu); +#else +static inline void restore_astate(int cpu) +{ +} +#endif #endif /* _PASEMI_PASEMI_H */ diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index 7ecb2ba24db..056243da360 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c @@ -33,7 +33,17 @@ #define PA_PXP_CFA(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off)) -#define CONFIG_OFFSET_VALID(off) ((off) < 4096) +static inline int pa_pxp_offset_valid(u8 bus, u8 devfn, int offset) +{ + /* Device 0 Function 0 is special: It's config space spans function 1 as + * well, so allow larger offset. It's really a two-function device but the + * second function does not probe. + */ + if (bus == 0 && devfn == 0) + return offset < 8192; + else + return offset < 4096; +} static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose, u8 bus, u8 devfn, int offset) @@ -51,7 +61,7 @@ static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, if (!hose) return PCIBIOS_DEVICE_NOT_FOUND; - if (!CONFIG_OFFSET_VALID(offset)) + if (!pa_pxp_offset_valid(bus->number, devfn, offset)) return PCIBIOS_BAD_REGISTER_NUMBER; addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); @@ -85,7 +95,7 @@ static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn, if (!hose) return PCIBIOS_DEVICE_NOT_FOUND; - if (!CONFIG_OFFSET_VALID(offset)) + if (!pa_pxp_offset_valid(bus->number, devfn, offset)) return PCIBIOS_BAD_REGISTER_NUMBER; addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 449cf1a0829..f88f0ec4c8c 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -35,6 +35,7 @@ #include <asm/mpic.h> #include <asm/smp.h> #include <asm/time.h> +#include <asm/of_platform.h> #include "pasemi.h" @@ -101,12 +102,6 @@ void __init pas_setup_arch(void) pasemi_idle_init(); } -/* No legacy IO on our parts */ -static int pas_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - static __init void pas_init_IRQ(void) { struct device_node *np; @@ -136,8 +131,8 @@ static __init void pas_init_IRQ(void) /* Find address list in /platform-open-pic */ root = of_find_node_by_path("/"); - naddr = prom_n_addr_cells(root); - opprop = get_property(root, "platform-open-pic", &opplen); + naddr = of_n_addr_cells(root); + opprop = of_get_property(root, "platform-open-pic", &opplen); if (!opprop) { printk(KERN_ERR "No platform-open-pic property.\n"); of_node_put(root); @@ -147,7 +142,7 @@ static __init void pas_init_IRQ(void) printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); mpic = mpic_alloc(mpic_node, openpic_addr, - MPIC_PRIMARY|MPIC_LARGE_VECTORS, + MPIC_PRIMARY|MPIC_LARGE_VECTORS|MPIC_WANTS_RESET, 0, 0, " PAS-OPIC "); BUG_ON(!mpic); @@ -209,6 +204,20 @@ static void __init pas_init_early(void) iommu_init_early_pasemi(); } +static struct of_device_id pasemi_bus_ids[] = { + { .type = "sdc", }, + {}, +}; + +static int __init pasemi_publish_devices(void) +{ + /* Publish OF platform devices for southbridge IOs */ + of_platform_bus_probe(NULL, pasemi_bus_ids, NULL); + + return 0; +} +device_initcall(pasemi_publish_devices); + /* * Called very early, MMU is off, device-tree isn't unflattened @@ -237,7 +246,6 @@ define_machine(pas) { .restart = pas_restart, .get_boot_time = pas_get_boot_time, .calibrate_decr = generic_calibrate_decr, - .check_legacy_ioport = pas_check_legacy_ioport, .progress = pas_progress, .machine_check_exception = pas_machine_check_handler, .pci_irq_fixup = pas_pci_irq_fixup, diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig new file mode 100644 index 00000000000..5b7afe50039 --- /dev/null +++ b/arch/powerpc/platforms/powermac/Kconfig @@ -0,0 +1,20 @@ +config PPC_PMAC + bool "Apple PowerMac based machines" + depends on PPC_MULTIPLATFORM + select MPIC + select PPC_INDIRECT_PCI if PPC32 + select PPC_MPC106 if PPC32 + select PPC_NATIVE + default y + +config PPC_PMAC64 + bool + depends on PPC_PMAC && POWER4 + select MPIC + select U3_DART + select MPIC_U3_HT_IRQS + select GENERIC_TBSYNC + select PPC_970_NAP + default y + + diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c index de7440e62cc..d679964ae2a 100644 --- a/arch/powerpc/platforms/powermac/backlight.c +++ b/arch/powerpc/platforms/powermac/backlight.c @@ -56,13 +56,16 @@ struct backlight_device *pmac_backlight; int pmac_has_backlight_type(const char *type) { - struct device_node* bk_node = find_devices("backlight"); + struct device_node* bk_node = of_find_node_by_name(NULL, "backlight"); if (bk_node) { - const char *prop = get_property(bk_node, + const char *prop = of_get_property(bk_node, "backlight-control", NULL); - if (prop && strncmp(prop, type, strlen(type)) == 0) + if (prop && strncmp(prop, type, strlen(type)) == 0) { + of_node_put(bk_node); return 1; + } + of_node_put(bk_node); } return 0; diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index c2b6b4134f6..8943a9456bb 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -421,7 +421,7 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) static u32 read_gpio(struct device_node *np) { - const u32 *reg = get_property(np, "reg", NULL); + const u32 *reg = of_get_property(np, "reg", NULL); u32 offset; if (reg == NULL) @@ -521,13 +521,14 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) int lenp, rc; const u32 *freqs, *ratio; - freqs = get_property(cpunode, "bus-frequencies", &lenp); + freqs = of_get_property(cpunode, "bus-frequencies", &lenp); lenp /= sizeof(u32); if (freqs == NULL || lenp != 2) { printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); return 1; } - ratio = get_property(cpunode, "processor-to-bus-ratio*2", NULL); + ratio = of_get_property(cpunode, "processor-to-bus-ratio*2", + NULL); if (ratio == NULL) { printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); return 1; @@ -562,7 +563,7 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) /* If we use the PMU, look for the min & max frequencies in the * device-tree */ - value = get_property(cpunode, "min-clock-frequency", NULL); + value = of_get_property(cpunode, "min-clock-frequency", NULL); if (!value) return 1; low_freq = (*value) / 1000; @@ -571,7 +572,7 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) if (low_freq < 100000) low_freq *= 10; - value = get_property(cpunode, "max-clock-frequency", NULL); + value = of_get_property(cpunode, "max-clock-frequency", NULL); if (!value) return 1; hi_freq = (*value) / 1000; @@ -585,7 +586,7 @@ static int pmac_cpufreq_init_7447A(struct device_node *cpunode) { struct device_node *volt_gpio_np; - if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL) return 1; volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); @@ -614,11 +615,11 @@ static int pmac_cpufreq_init_750FX(struct device_node *cpunode) u32 pvr; const u32 *value; - if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL) return 1; hi_freq = cur_freq; - value = get_property(cpunode, "reduced-clock-frequency", NULL); + value = of_get_property(cpunode, "reduced-clock-frequency", NULL); if (!value) return 1; low_freq = (*value) / 1000; @@ -657,19 +658,19 @@ static int __init pmac_cpufreq_setup(void) return 0; /* Assume only one CPU */ - cpunode = find_type_devices("cpu"); + cpunode = of_find_node_by_type(NULL, "cpu"); if (!cpunode) goto out; /* Get current cpu clock freq */ - value = get_property(cpunode, "clock-frequency", NULL); + value = of_get_property(cpunode, "clock-frequency", NULL); if (!value) goto out; cur_freq = (*value) / 1000; /* Check for 7447A based MacRISC3 */ if (machine_is_compatible("MacRISC3") && - get_property(cpunode, "dynamic-power-step", NULL) && + of_get_property(cpunode, "dynamic-power-step", NULL) && PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { pmac_cpufreq_init_7447A(cpunode); /* Check for other MacRISC3 machines */ @@ -707,6 +708,7 @@ static int __init pmac_cpufreq_setup(void) else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) pmac_cpufreq_init_750FX(cpunode); out: + of_node_put(cpunode); if (set_speed_proc == NULL) return -ENODEV; diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index 9d22361a26d..567d5523b69 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -410,7 +410,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) /* Get first CPU node */ for (cpunode = NULL; (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) { - const u32 *reg = get_property(cpunode, "reg", NULL); + const u32 *reg = of_get_property(cpunode, "reg", NULL); if (reg == NULL || (*reg) != 0) continue; if (!strcmp(cpunode->type, "cpu")) @@ -422,7 +422,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) } /* Check 970FX for now */ - valp = get_property(cpunode, "cpu-version", NULL); + valp = of_get_property(cpunode, "cpu-version", NULL); if (!valp) { DBG("No cpu-version property !\n"); goto bail_noprops; @@ -434,7 +434,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) } /* Look for the powertune data in the device-tree */ - g5_pmode_data = get_property(cpunode, "power-mode-data",&psize); + g5_pmode_data = of_get_property(cpunode, "power-mode-data",&psize); if (!g5_pmode_data) { DBG("No power-mode-data !\n"); goto bail_noprops; @@ -493,7 +493,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) * half freq in this version. So far, I haven't yet seen a machine * supporting anything else. */ - valp = get_property(cpunode, "clock-frequency", NULL); + valp = of_get_property(cpunode, "clock-frequency", NULL); if (!valp) return -ENODEV; max_freq = (*valp)/1000; @@ -563,7 +563,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) /* Lookup the cpuid eeprom node */ cpuid = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/cpuid@a0"); if (cpuid != NULL) - eeprom = get_property(cpuid, "cpuid", NULL); + eeprom = of_get_property(cpuid, "cpuid", NULL); if (eeprom == NULL) { printk(KERN_ERR "cpufreq: Can't find cpuid EEPROM !\n"); rc = -ENODEV; @@ -573,13 +573,13 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) /* Lookup the i2c hwclock */ for (hwclock = NULL; (hwclock = of_find_node_by_name(hwclock, "i2c-hwclock")) != NULL;){ - const char *loc = get_property(hwclock, + const char *loc = of_get_property(hwclock, "hwctrl-location", NULL); if (loc == NULL) continue; if (strcmp(loc, "CPU CLOCK")) continue; - if (!get_property(hwclock, "platform-get-frequency", NULL)) + if (!of_get_property(hwclock, "platform-get-frequency", NULL)) continue; break; } @@ -638,7 +638,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus) */ /* Get max frequency from device-tree */ - valp = get_property(cpunode, "clock-frequency", NULL); + valp = of_get_property(cpunode, "clock-frequency", NULL); if (!valp) { printk(KERN_ERR "cpufreq: Can't find CPU frequency !\n"); rc = -ENODEV; diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 24cc50c1774..52cfdd86c92 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -1044,6 +1044,7 @@ core99_reset_cpu(struct device_node *node, long param, long value) unsigned long flags; struct macio_chip *macio; struct device_node *np; + struct device_node *cpus; const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, KL_GPIO_RESET_CPU1, KL_GPIO_RESET_CPU2, @@ -1053,12 +1054,12 @@ core99_reset_cpu(struct device_node *node, long param, long value) if (macio->type != macio_keylargo) return -ENODEV; - np = find_path_device("/cpus"); - if (np == NULL) + cpus = of_find_node_by_path("/cpus"); + if (cpus == NULL) return -ENODEV; - for (np = np->child; np != NULL; np = np->sibling) { - const u32 *num = get_property(np, "reg", NULL); - const u32 *rst = get_property(np, "soft-reset", NULL); + for (np = cpus->child; np != NULL; np = np->sibling) { + const u32 *num = of_get_property(np, "reg", NULL); + const u32 *rst = of_get_property(np, "soft-reset", NULL); if (num == NULL || rst == NULL) continue; if (param == *num) { @@ -1066,6 +1067,7 @@ core99_reset_cpu(struct device_node *node, long param, long value) break; } } + of_node_put(cpus); if (np == NULL || reset_io == 0) reset_io = dflt_reset_lines[param]; @@ -1095,7 +1097,7 @@ core99_usb_enable(struct device_node *node, long param, long value) macio->type != macio_intrepid) return -ENODEV; - prop = get_property(node, "AAPL,clock-id", NULL); + prop = of_get_property(node, "AAPL,clock-id", NULL); if (!prop) return -ENODEV; if (strncmp(prop, "usb0u048", 8) == 0) @@ -1497,17 +1499,18 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) unsigned long flags; struct macio_chip *macio; struct device_node *np; + struct device_node *cpus; macio = &macio_chips[0]; if (macio->type != macio_keylargo2 && macio->type != macio_shasta) return -ENODEV; - np = find_path_device("/cpus"); - if (np == NULL) + cpus = of_find_node_by_path("/cpus"); + if (cpus == NULL) return -ENODEV; - for (np = np->child; np != NULL; np = np->sibling) { - const u32 *num = get_property(np, "reg", NULL); - const u32 *rst = get_property(np, "soft-reset", NULL); + for (np = cpus->child; np != NULL; np = np->sibling) { + const u32 *num = of_get_property(np, "reg", NULL); + const u32 *rst = of_get_property(np, "soft-reset", NULL); if (num == NULL || rst == NULL) continue; if (param == *num) { @@ -1515,6 +1518,7 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) break; } } + of_node_put(cpus); if (np == NULL || reset_io == 0) return -ENODEV; @@ -2404,14 +2408,15 @@ static int __init probe_motherboard(void) struct macio_chip *macio = &macio_chips[0]; const char *model = NULL; struct device_node *dt; + int ret = 0; /* Lookup known motherboard type in device-tree. First try an * exact match on the "model" property, then try a "compatible" * match is none is found. */ - dt = find_devices("device-tree"); + dt = of_find_node_by_name(NULL, "device-tree"); if (dt != NULL) - model = get_property(dt, "model", NULL); + model = of_get_property(dt, "model", NULL); for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { if (strcmp(model, pmac_mb_defs[i].model_string) == 0) { pmac_mb = pmac_mb_defs[i]; @@ -2474,15 +2479,18 @@ static int __init probe_motherboard(void) break; #endif /* CONFIG_POWER4 */ default: - return -ENODEV; + ret = -ENODEV; + goto done; } found: #ifndef CONFIG_POWER4 /* Fixup Hooper vs. Comet */ if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); - if (!mach_id_ptr) - return -ENODEV; + if (!mach_id_ptr) { + ret = -ENODEV; + goto done; + } /* Here, I used to disable the media-bay on comet. It * appears this is wrong, the floppy connector is actually * a kind of media-bay and works with the current driver. @@ -2499,18 +2507,26 @@ found: * that all Apple OF revs did it properly, I do it the paranoid way. */ while (uninorth_base && uninorth_rev > 3) { - struct device_node *np = find_path_device("/cpus"); - if (!np || !np->child) { + struct device_node *cpus = of_find_node_by_path("/cpus"); + struct device_node *np; + + if (!cpus || !cpus->child) { printk(KERN_WARNING "Can't find CPU(s) in device tree !\n"); + of_node_put(cpus); break; } - np = np->child; + np = cpus->child; /* Nap mode not supported on SMP */ - if (np->sibling) + if (np->sibling) { + of_node_put(cpus); break; + } /* Nap mode not supported if flush-on-lock property is present */ - if (get_property(np, "flush-on-lock", NULL)) + if (of_get_property(np, "flush-on-lock", NULL)) { + of_node_put(cpus); break; + } + of_node_put(cpus); powersave_nap = 1; printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n"); break; @@ -2532,7 +2548,9 @@ found: printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); - return 0; +done: + of_node_put(dt); + return ret; } /* Initialize the Core99 UniNorth host bridge and memory controller @@ -2558,7 +2576,7 @@ static void __init probe_uninorth(void) if (uninorth_node == NULL) return; - addrp = get_property(uninorth_node, "reg", NULL); + addrp = of_get_property(uninorth_node, "reg", NULL); if (addrp == NULL) return; address = of_translate_address(uninorth_node, addrp); @@ -2642,7 +2660,7 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ return; } if (type == macio_keylargo || type == macio_keylargo2) { - const u32 *did = get_property(node, "device-id", NULL); + const u32 *did = of_get_property(node, "device-id", NULL); if (*did == 0x00000025) type = macio_pangea; if (*did == 0x0000003e) @@ -2655,7 +2673,7 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ macio_chips[i].base = base; macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON; macio_chips[i].name = macio_names[type]; - revp = get_property(node, "revision-id", NULL); + revp = of_get_property(node, "revision-id", NULL); if (revp) macio_chips[i].rev = *revp; printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", @@ -2706,8 +2724,8 @@ initial_serial_shutdown(struct device_node *np) int port_type = PMAC_SCC_ASYNC; int modem = 0; - slots = get_property(np, "slot-names", &len); - conn = get_property(np, "AAPL,connector", &len); + slots = of_get_property(np, "slot-names", &len); + conn = of_get_property(np, "AAPL,connector", &len); if (conn && (strcmp(conn, "infrared") == 0)) port_type = PMAC_SCC_IRDA; else if (device_is_compatible(np, "cobalt")) @@ -2735,12 +2753,14 @@ set_initial_features(void) * differenciate them all and since that hack was there for a long * time, I'll keep it around */ - if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) { + if (macio_chips[0].type == macio_ohare) { struct macio_chip *macio = &macio_chips[0]; - MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); - } else if (macio_chips[0].type == macio_ohare) { - struct macio_chip *macio = &macio_chips[0]; - MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); + np = of_find_node_by_name(NULL, "via-pmu"); + if (np) + MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); + else + MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); + of_node_put(np); } else if (macio_chips[1].type == macio_ohare) { struct macio_chip *macio = &macio_chips[1]; MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); @@ -2833,14 +2853,13 @@ set_initial_features(void) } /* Switch airport off */ - np = find_devices("radio"); - while(np) { + for_each_node_by_name(np, "radio") { if (np && np->parent == macio_chips[0].of_node) { macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON; core99_airport_enable(np, 0, 0); } - np = np->next; } + of_node_put(np); } /* On all machines that support sound PM, switch sound off */ @@ -2860,16 +2879,12 @@ set_initial_features(void) #endif /* CONFIG_POWER4 */ /* On all machines, switch modem & serial ports off */ - np = find_devices("ch-a"); - while(np) { + for_each_node_by_name(np, "ch-a") initial_serial_shutdown(np); - np = np->next; - } - np = find_devices("ch-b"); - while(np) { + of_node_put(np); + for_each_node_by_name(np, "ch-b") initial_serial_shutdown(np); - np = np->next; - } + of_node_put(np); } void __init diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index bfc4829162f..5430e146b3e 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -491,7 +491,7 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) * on all i2c keywest nodes so far ... we would have to fallback * to macio parsing if that wasn't the case */ - addrp = get_property(np, "AAPL,address", NULL); + addrp = of_get_property(np, "AAPL,address", NULL); if (addrp == NULL) { printk(KERN_ERR "low_i2c: Can't find address for %s\n", np->full_name); @@ -505,13 +505,13 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) host->timeout_timer.function = kw_i2c_timeout; host->timeout_timer.data = (unsigned long)host; - psteps = get_property(np, "AAPL,address-step", NULL); + psteps = of_get_property(np, "AAPL,address-step", NULL); steps = psteps ? (*psteps) : 0x10; for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) steps >>= 1; /* Select interface rate */ host->speed = KW_I2C_MODE_25KHZ; - prate = get_property(np, "AAPL,i2c-rate", NULL); + prate = of_get_property(np, "AAPL,i2c-rate", NULL); if (prate) switch(*prate) { case 100: host->speed = KW_I2C_MODE_100KHZ; @@ -619,7 +619,7 @@ static void __init kw_i2c_probe(void) } else { for (child = NULL; (child = of_get_next_child(np, child)) != NULL;) { - const u32 *reg = get_property(child, + const u32 *reg = of_get_property(child, "reg", NULL); if (reg == NULL) continue; @@ -905,7 +905,7 @@ static void __init smu_i2c_probe(void) if (strcmp(busnode->type, "i2c") && strcmp(busnode->type, "i2c-bus")) continue; - reg = get_property(busnode, "reg", NULL); + reg = of_get_property(busnode, "reg", NULL); if (reg == NULL) continue; @@ -950,7 +950,8 @@ struct pmac_i2c_bus *pmac_i2c_find_bus(struct device_node *node) if (p == bus->busnode) { if (prev && bus->flags & pmac_i2c_multibus) { const u32 *reg; - reg = get_property(prev, "reg", NULL); + reg = of_get_property(prev, "reg", + NULL); if (!reg) continue; if (((*reg) >> 8) != bus->channel) @@ -971,7 +972,7 @@ EXPORT_SYMBOL_GPL(pmac_i2c_find_bus); u8 pmac_i2c_get_dev_addr(struct device_node *device) { - const u32 *reg = get_property(device, "reg", NULL); + const u32 *reg = of_get_property(device, "reg", NULL); if (reg == NULL) return 0; diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 6fbac308ded..22c4ae4c693 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -70,11 +70,11 @@ static int __init fixup_one_level_bus_range(struct device_node *node, int higher int len; /* For PCI<->PCI bridges or CardBus bridges, we go down */ - class_code = get_property(node, "class-code", NULL); + class_code = of_get_property(node, "class-code", NULL); if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) continue; - bus_range = get_property(node, "bus-range", &len); + bus_range = of_get_property(node, "bus-range", &len); if (bus_range != NULL && len > 2 * sizeof(int)) { if (bus_range[1] > higher) higher = bus_range[1]; @@ -100,7 +100,7 @@ static void __init fixup_bus_range(struct device_node *bridge) if (prop == NULL || prop->length < 2 * sizeof(int)) return; - bus_range = (int *)prop->value; + bus_range = prop->value; bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); } @@ -246,8 +246,8 @@ static int chaos_validate_dev(struct pci_bus *bus, int devfn, int offset) if (np == NULL) return PCIBIOS_DEVICE_NOT_FOUND; - vendor = get_property(np, "vendor-id", NULL); - device = get_property(np, "device-id", NULL); + vendor = of_get_property(np, "vendor-id", NULL); + device = of_get_property(np, "device-id", NULL); if (vendor == NULL || device == NULL) return PCIBIOS_DEVICE_NOT_FOUND; @@ -622,13 +622,14 @@ static void __init init_p2pbridge(void) /* XXX it would be better here to identify the specific PCI-PCI bridge chip we have. */ - if ((p2pbridge = find_devices("pci-bridge")) == 0 + p2pbridge = of_find_node_by_name(NULL, "pci-bridge"); + if (p2pbridge == NULL || p2pbridge->parent == NULL || strcmp(p2pbridge->parent->name, "pci") != 0) - return; + goto done; if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) { DBG("Can't find PCI infos for PCI<->PCI bridge\n"); - return; + goto done; } /* Warning: At this point, we have not yet renumbered all busses. * So we must use OF walking to find out hose @@ -636,16 +637,18 @@ static void __init init_p2pbridge(void) hose = pci_find_hose_for_OF_device(p2pbridge); if (!hose) { DBG("Can't find hose for PCI<->PCI bridge\n"); - return; + goto done; } if (early_read_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, &val) < 0) { printk(KERN_ERR "init_p2pbridge: couldn't read bridge" " control\n"); - return; + goto done; } val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); +done: + of_node_put(p2pbridge); } static void __init init_second_ohare(void) @@ -691,17 +694,17 @@ static void __init fixup_nec_usb2(void) const u32 *prop; u8 bus, devfn; - prop = get_property(nec, "vendor-id", NULL); + prop = of_get_property(nec, "vendor-id", NULL); if (prop == NULL) continue; if (0x1033 != *prop) continue; - prop = get_property(nec, "device-id", NULL); + prop = of_get_property(nec, "device-id", NULL); if (prop == NULL) continue; if (0x0035 != *prop) continue; - prop = get_property(nec, "reg", NULL); + prop = of_get_property(nec, "reg", NULL); if (prop == NULL) continue; devfn = (prop[0] >> 8) & 0xff; @@ -909,7 +912,7 @@ static int __init add_bridge(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); @@ -1199,8 +1202,7 @@ void __init pmac_pcibios_after_init(void) } #endif /* CONFIG_BLK_DEV_IDE */ - nd = find_devices("firewire"); - while (nd) { + for_each_node_by_name(nd, "firewire") { if (nd->parent && (device_is_compatible(nd, "pci106b,18") || device_is_compatible(nd, "pci106b,30") || device_is_compatible(nd, "pci11c1,5811")) @@ -1208,15 +1210,14 @@ void __init pmac_pcibios_after_init(void) pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0); pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0); } - nd = nd->next; } - nd = find_devices("ethernet"); - while (nd) { + of_node_put(nd); + for_each_node_by_name(nd, "ethernet") { if (nd->parent && device_is_compatible(nd, "gmac") && device_is_compatible(nd->parent, "uni-north")) pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0); - nd = nd->next; } + of_node_put(nd); } #ifdef CONFIG_PPC32 diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c index 5c6c15c5f9a..45d54b9ad9e 100644 --- a/arch/powerpc/platforms/powermac/pfunc_base.c +++ b/arch/powerpc/platforms/powermac/pfunc_base.c @@ -114,7 +114,7 @@ static void macio_gpio_init_one(struct macio_chip *macio) * we just create them all */ for (gp = NULL; (gp = of_get_next_child(gparent, gp)) != NULL;) { - const u32 *reg = get_property(gp, "reg", NULL); + const u32 *reg = of_get_property(gp, "reg", NULL); unsigned long offset; if (reg == NULL) continue; diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index 7651f278615..85434231ae1 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -692,8 +692,7 @@ static int pmf_add_functions(struct pmf_device *dev, void *driverdata) name = pp->name + plen; if (strlen(name) && pp->length >= 12) count += pmf_add_function_prop(dev, driverdata, name, - (u32 *)pp->value, - pp->length); + pp->value, pp->length); } return count; } @@ -821,7 +820,7 @@ struct pmf_function *__pmf_find_function(struct device_node *target, * one, then we fallback to a direct call attempt */ snprintf(fname, 63, "platform-%s", name); - prop = get_property(target, fname, NULL); + prop = of_get_property(target, fname, NULL); if (prop == NULL) goto find_it; ph = *prop; diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 5e5c0e4add9..ae5097ac037 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -482,14 +482,14 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0); flags |= MPIC_WANTS_RESET; - if (get_property(np, "big-endian", NULL)) + if (of_get_property(np, "big-endian", NULL)) flags |= MPIC_BIG_ENDIAN; /* Primary Big Endian means HT interrupts. This is quite dodgy * but works until I find a better way */ if (master && (flags & MPIC_BIG_ENDIAN)) - flags |= MPIC_BROKEN_U3; + flags |= MPIC_U3_HT_IRQS; mpic = mpic_alloc(np, r.start, flags, 0, 0, name); if (mpic == NULL) @@ -510,7 +510,7 @@ static int __init pmac_pic_probe_mpic(void) for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) != NULL;) { if (master == NULL && - get_property(np, "interrupts", NULL) == NULL) + of_get_property(np, "interrupts", NULL) == NULL) master = of_node_get(np); else if (slave == NULL) slave = of_node_get(np); @@ -575,7 +575,7 @@ void __init pmac_pic_init(void) #ifdef CONFIG_PPC32 if (!pmac_newworld) flags |= OF_IMAP_OLDWORLD_MAC; - if (get_property(of_chosen, "linux,bootx", NULL) != NULL) + if (of_get_property(of_chosen, "linux,bootx", NULL) != NULL) flags |= OF_IMAP_NO_PHANDLE; #endif /* CONFIG_PPC_32 */ diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 651fa424ea0..b820cabac69 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -42,7 +42,6 @@ #include <linux/initrd.h> #include <linux/vt_kern.h> #include <linux/console.h> -#include <linux/ide.h> #include <linux/pci.h> #include <linux/adb.h> #include <linux/cuda.h> @@ -135,12 +134,12 @@ static void pmac_show_cpuinfo(struct seq_file *m) seq_printf(m, "machine\t\t: "); np = of_find_node_by_path("/"); if (np != NULL) { - pp = get_property(np, "model", NULL); + pp = of_get_property(np, "model", NULL); if (pp != NULL) seq_printf(m, "%s\n", pp); else seq_printf(m, "PowerMac\n"); - pp = get_property(np, "compatible", &plen); + pp = of_get_property(np, "compatible", &plen); if (pp != NULL) { seq_printf(m, "motherboard\t:"); while (plen > 0) { @@ -164,11 +163,13 @@ static void pmac_show_cpuinfo(struct seq_file *m) if (np == NULL) np = of_find_node_by_type(NULL, "cache"); if (np != NULL) { - const unsigned int *ic = get_property(np, "i-cache-size", NULL); - const unsigned int *dc = get_property(np, "d-cache-size", NULL); + const unsigned int *ic = + of_get_property(np, "i-cache-size", NULL); + const unsigned int *dc = + of_get_property(np, "d-cache-size", NULL); seq_printf(m, "L2 cache\t:"); has_l2cache = 1; - if (get_property(np, "cache-unified", NULL) != 0 && dc) { + if (of_get_property(np, "cache-unified", NULL) != 0 && dc) { seq_printf(m, " %dK unified", *dc / 1024); } else { if (ic) @@ -177,7 +178,7 @@ static void pmac_show_cpuinfo(struct seq_file *m) seq_printf(m, "%s %dK data", (ic? " +": ""), *dc / 1024); } - pp = get_property(np, "ram-type", NULL); + pp = of_get_property(np, "ram-type", NULL); if (pp) seq_printf(m, " %s", pp); seq_printf(m, "\n"); @@ -192,8 +193,11 @@ static void pmac_show_cpuinfo(struct seq_file *m) #ifndef CONFIG_ADB_CUDA int find_via_cuda(void) { - if (!find_devices("via-cuda")) + struct device_node *dn = of_find_node_by_name(NULL, "via-cuda"); + + if (!dn) return 0; + of_node_put(dn); printk("WARNING ! Your machine is CUDA-based but your kernel\n"); printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); return 0; @@ -203,8 +207,11 @@ int find_via_cuda(void) #ifndef CONFIG_ADB_PMU int find_via_pmu(void) { - if (!find_devices("via-pmu")) + struct device_node *dn = of_find_node_by_name(NULL, "via-pmu"); + + if (!dn) return 0; + of_node_put(dn); printk("WARNING ! Your machine is PMU-based but your kernel\n"); printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); return 0; @@ -224,6 +231,8 @@ static volatile u32 *sysctrl_regs; static void __init ohare_init(void) { + struct device_node *dn; + /* this area has the CPU identification register and some registers used by smp boards */ sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); @@ -233,7 +242,9 @@ static void __init ohare_init(void) * We assume that we have a PSX memory controller iff * we have an ohare I/O controller. */ - if (find_devices("ohare") != NULL) { + dn = of_find_node_by_name(NULL, "ohare"); + if (dn) { + of_node_put(dn); if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) { if (sysctrl_regs[4] & 0x10) sysctrl_regs[4] |= 0x04000020; @@ -249,18 +260,19 @@ static void __init l2cr_init(void) { /* Checks "l2cr-value" property in the registry */ if (cpu_has_feature(CPU_FTR_L2CR)) { - struct device_node *np = find_devices("cpus"); + struct device_node *np = of_find_node_by_name(NULL, "cpus"); if (np == 0) - np = find_type_devices("cpu"); + np = of_find_node_by_type(NULL, "cpu"); if (np != 0) { const unsigned int *l2cr = - get_property(np, "l2cr-value", NULL); + of_get_property(np, "l2cr-value", NULL); if (l2cr != 0) { ppc_override_l2cr = 1; ppc_override_l2cr_value = *l2cr; _set_L2CR(0); _set_L2CR(ppc_override_l2cr_value); } + of_node_put(np); } } @@ -286,7 +298,7 @@ static void __init pmac_setup_arch(void) loops_per_jiffy = 50000000 / HZ; cpu = of_find_node_by_type(NULL, "cpu"); if (cpu != NULL) { - fp = get_property(cpu, "clock-frequency", NULL); + fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != NULL) { if (pvr >= 0x30 && pvr < 0x80) /* PPC970 etc. */ @@ -303,7 +315,7 @@ static void __init pmac_setup_arch(void) /* See if newworld or oldworld */ for (ic = NULL; (ic = of_find_all_nodes(ic)) != NULL; ) - if (get_property(ic, "interrupt-controller", NULL)) + if (of_get_property(ic, "interrupt-controller", NULL)) break; if (ic) { pmac_newworld = 1; @@ -341,8 +353,15 @@ static void __init pmac_setup_arch(void) #ifdef CONFIG_SMP /* Check for Core99 */ - if (find_devices("uni-n") || find_devices("u3") || find_devices("u4")) + ic = of_find_node_by_name(NULL, "uni-n"); + if (!ic) + ic = of_find_node_by_name(NULL, "u3"); + if (!ic) + ic = of_find_node_by_name(NULL, "u4"); + if (ic) { + of_node_put(ic); smp_ops = &core99_smp_ops; + } #ifdef CONFIG_PPC32 else smp_ops = &psurge_smp_ops; @@ -616,15 +635,6 @@ static void __init pmac_init_early(void) #endif } -/* - * pmac has no legacy IO, anything calling this function has to - * fail or bad things will happen - */ -static int pmac_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - static int __init pmac_declare_of_platform_devices(void) { struct device_node *np; @@ -736,7 +746,6 @@ define_machine(powermac) { .get_rtc_time = pmac_get_rtc_time, .calibrate_decr = pmac_calibrate_decr, .feature_call = pmac_do_feature_call, - .check_legacy_ioport = pmac_check_legacy_ioport, .progress = udbg_progress, #ifdef CONFIG_PPC64 .pci_probe_mode = pmac_pci_probe_mode, diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index d73fb73802b..6f32c4eca6e 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -264,6 +264,7 @@ static void __init psurge_quad_init(void) static int __init smp_psurge_probe(void) { int i, ncpus; + struct device_node *dn; /* We don't do SMP on the PPC601 -- paulus */ if (PVR_VER(mfspr(SPRN_PVR)) == 1) @@ -279,8 +280,10 @@ static int __init smp_psurge_probe(void) * in the hammerhead memory controller in the case of the * dual-cpu powersurge board. -- paulus. */ - if (find_devices("hammerhead") == NULL) + dn = of_find_node_by_name(NULL, "hammerhead"); + if (dn == NULL) return 1; + of_node_put(dn); hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); @@ -567,7 +570,7 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus) pmac_tb_clock_chip_host = pmac_i2c_find_bus(cc); if (pmac_tb_clock_chip_host == NULL) continue; - reg = get_property(cc, "reg", NULL); + reg = of_get_property(cc, "reg", NULL); if (reg == NULL) continue; switch (*reg) { @@ -695,7 +698,7 @@ static void __init smp_core99_setup(int ncpus) struct device_node *cpus = of_find_node_by_path("/cpus"); if (cpus && - get_property(cpus, "platform-cpu-timebase", NULL)) { + of_get_property(cpus, "platform-cpu-timebase", NULL)) { pmac_tb_freeze = smp_core99_pfunc_tb_freeze; printk(KERN_INFO "Processor timebase sync using" " platform function\n"); @@ -712,7 +715,7 @@ static void __init smp_core99_setup(int ncpus) core99_tb_gpio = KL_GPIO_TB_ENABLE; /* default value */ cpu = of_find_node_by_type(NULL, "cpu"); if (cpu != NULL) { - tbprop = get_property(cpu, "timebase-enable", NULL); + tbprop = of_get_property(cpu, "timebase-enable", NULL); if (tbprop) core99_tb_gpio = *tbprop; of_node_put(cpu); diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index a4173906e94..bf9da56942e 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c @@ -297,49 +297,11 @@ int __init via_calibrate_decr(void) } #endif -#ifdef CONFIG_PM -/* - * Reset the time after a sleep. - */ -static int -time_sleep_notify(struct pmu_sleep_notifier *self, int when) -{ - static unsigned long time_diff; - unsigned long flags; - unsigned long seq; - struct timespec tv; - - switch (when) { - case PBOOK_SLEEP_NOW: - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - time_diff = xtime.tv_sec - pmac_get_boot_time(); - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - break; - case PBOOK_WAKE: - tv.tv_sec = pmac_get_boot_time() + time_diff; - tv.tv_nsec = 0; - do_settimeofday(&tv); - break; - } - return PBOOK_SLEEP_OK; -} - -static struct pmu_sleep_notifier time_sleep_notifier = { - time_sleep_notify, SLEEP_LEVEL_MISC, -}; -#endif /* CONFIG_PM */ - /* * Query the OF and get the decr frequency. */ void __init pmac_calibrate_decr(void) { -#if defined(CONFIG_PM) && defined(CONFIG_ADB_PMU) - /* XXX why here? */ - pmu_register_sleep_notifier(&time_sleep_notifier); -#endif - generic_calibrate_decr(); #ifdef CONFIG_PPC32 diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c index 379db05b008..47de4d3fc16 100644 --- a/arch/powerpc/platforms/powermac/udbg_scc.c +++ b/arch/powerpc/platforms/powermac/udbg_scc.c @@ -81,7 +81,7 @@ void udbg_scc_init(int force_scc) macio = of_get_parent(escc); if (macio == NULL) goto bail; - path = get_property(of_chosen, "linux,stdout-path", NULL); + path = of_get_property(of_chosen, "linux,stdout-path", NULL); if (path != NULL) stdout = of_find_node_by_path(path); for (ch = NULL; (ch = of_get_next_child(escc, ch)) != NULL;) { @@ -96,13 +96,13 @@ void udbg_scc_init(int force_scc) ch = ch_def ? ch_def : ch_a; /* Get address within mac-io ASIC */ - reg = get_property(escc, "reg", NULL); + reg = of_get_property(escc, "reg", NULL); if (reg == NULL) goto bail; addr = reg[0]; /* Get address of mac-io PCI itself */ - reg = get_property(macio, "assigned-addresses", NULL); + reg = of_get_property(macio, "assigned-addresses", NULL); if (reg == NULL) goto bail; addr += reg[2]; diff --git a/arch/powerpc/platforms/prep/Kconfig b/arch/powerpc/platforms/prep/Kconfig index 673ac47a162..29d411279b0 100644 --- a/arch/powerpc/platforms/prep/Kconfig +++ b/arch/powerpc/platforms/prep/Kconfig @@ -1,3 +1,12 @@ +config PPC_PREP + bool "PowerPC Reference Platform (PReP) based machines" + depends on PPC_MULTIPLATFORM && PPC32 && BROKEN + select MPIC + select PPC_I8259 + select PPC_INDIRECT_PCI + select PPC_UDBG_16550 + select PPC_NATIVE + default n config PREP_RESIDUAL bool "Support for PReP Residual Data" diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index 1a481a60a88..40f0008af4d 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -1,3 +1,19 @@ +config PPC_PS3 + bool "Sony PS3 (incomplete)" + depends on PPC_MULTIPLATFORM && PPC64 + select PPC_CELL + select USB_ARCH_HAS_OHCI + select USB_OHCI_LITTLE_ENDIAN + select USB_OHCI_BIG_ENDIAN_MMIO + select USB_ARCH_HAS_EHCI + select USB_EHCI_BIG_ENDIAN_MMIO + help + This option enables support for the Sony PS3 game console + and other platforms using the PS3 hypervisor. + Support for this platform is not yet complete, so + enabling this will not result in a bootable kernel on a + PS3 system. + menu "PS3 Platform Options" depends on PPC_PS3 diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index e12e59fea13..ea60c451cf8 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c @@ -39,7 +39,7 @@ static unsigned long htab_addr; static unsigned char *bolttab; static unsigned char *inusetab; -static spinlock_t ps3_bolttab_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(ps3_bolttab_lock); #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \ _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index a57032cf6f1..16e4e401b82 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -1,3 +1,13 @@ +config PPC_PSERIES + depends on PPC_MULTIPLATFORM && PPC64 + bool "IBM pSeries & new (POWER5-based) iSeries" + select MPIC + select PPC_I8259 + select PPC_RTAS + select RTAS_ERROR_LOGGING + select PPC_UDBG_16550 + select PPC_NATIVE + default y config PPC_SPLPAR depends on PPC_PSERIES diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 2dfd05095a2..90235d59875 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -2,14 +2,15 @@ ifeq ($(CONFIG_PPC64),y) EXTRA_CFLAGS += -mno-minimal-toc endif -obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ - setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ +obj-y := lpar.o hvCall.o nvram.o reconfig.o \ + setup.o iommu.o ras.o rtasd.o \ firmware.o power.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o obj-$(CONFIG_KEXEC) += kexec.o +obj-$(CONFIG_PCI) += pci.o pci_dlpar.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 6cedbc002e0..48fbd442e9d 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -74,7 +74,10 @@ * is broken and panic. This sets the threshold for how many read * attempts we allow before panicking. */ -#define EEH_MAX_FAILS 100000 +#define EEH_MAX_FAILS 2100000 + +/* Time to wait for a PCI slot to retport status, in milliseconds */ +#define PCI_BUS_RESET_WAIT_MSEC (60*1000) /* RTAS tokens */ static int ibm_set_eeh_option; @@ -83,6 +86,7 @@ static int ibm_read_slot_reset_state; static int ibm_read_slot_reset_state2; static int ibm_slot_error_detail; static int ibm_get_config_addr_info; +static int ibm_get_config_addr_info2; static int ibm_configure_bridge; int eeh_subsystem_enabled; @@ -168,6 +172,55 @@ static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) } /** + * eeh_wait_for_slot_status - returns error status of slot + * @pdn pci device node + * @max_wait_msecs maximum number to millisecs to wait + * + * Return negative value if a permanent error, else return + * Partition Endpoint (PE) status value. + * + * If @max_wait_msecs is positive, then this routine will + * sleep until a valid status can be obtained, or until + * the max allowed wait time is exceeded, in which case + * a -2 is returned. + */ +int +eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs) +{ + int rc; + int rets[3]; + int mwait; + + while (1) { + rc = read_slot_reset_state(pdn, rets); + if (rc) return rc; + if (rets[1] == 0) return -1; /* EEH is not supported */ + + if (rets[0] != 5) return rets[0]; /* return actual status */ + + if (rets[2] == 0) return -1; /* permanently unavailable */ + + if (max_wait_msecs <= 0) return -1; + + mwait = rets[2]; + if (mwait <= 0) { + printk (KERN_WARNING + "EEH: Firmware returned bad wait value=%d\n", mwait); + mwait = 1000; + } else if (mwait > 300*1000) { + printk (KERN_WARNING + "EEH: Firmware is taking too long, time=%d\n", mwait); + mwait = 300*1000; + } + max_wait_msecs -= mwait; + msleep (mwait); + } + + printk(KERN_WARNING "EEH: Timed out waiting for slot status\n"); + return -2; +} + +/** * eeh_token_to_phys - convert EEH address token to phys address * @token i/o token, should be address in the form 0xA.... */ @@ -229,7 +282,7 @@ void eeh_mark_slot (struct device_node *dn, int mode_flag) dn = find_device_pe (dn); /* Back up one, since config addrs might be shared */ - if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr) + if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) dn = dn->parent; PCI_DN(dn)->eeh_mode |= mode_flag; @@ -263,7 +316,7 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag) dn = find_device_pe (dn); /* Back up one, since config addrs might be shared */ - if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr) + if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) dn = dn->parent; PCI_DN(dn)->eeh_mode &= ~mode_flag; @@ -293,7 +346,6 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) int rets[3]; unsigned long flags; struct pci_dn *pdn; - enum pci_channel_state state; int rc = 0; total_mmio_ffs++; @@ -367,25 +419,25 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) goto dn_unlock; } - /* If EEH is not supported on this device, punt. */ - if (rets[1] != 1) { - printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", - ret, dn->full_name); + /* Note that config-io to empty slots may fail; + * they are empty when they don't have children. */ + if ((rets[0] == 5) && (dn->child == NULL)) { false_positives++; rc = 0; goto dn_unlock; } - /* If not the kind of error we know about, punt. */ - if (rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { + /* If EEH is not supported on this device, punt. */ + if (rets[1] != 1) { + printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", + ret, dn->full_name); false_positives++; rc = 0; goto dn_unlock; } - /* Note that config-io to empty slots may fail; - * we recognize empty because they don't have children. */ - if ((rets[0] == 5) && (dn->child == NULL)) { + /* If not the kind of error we know about, punt. */ + if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { false_positives++; rc = 0; goto dn_unlock; @@ -399,17 +451,12 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) eeh_mark_slot (dn, EEH_MODE_ISOLATED); spin_unlock_irqrestore(&confirm_error_lock, flags); - state = pci_channel_io_normal; - if ((rets[0] == 2) || (rets[0] == 4)) - state = pci_channel_io_frozen; - if (rets[0] == 5) - state = pci_channel_io_perm_failure; - eeh_send_failure_event (dn, dev, state, rets[2]); + eeh_send_failure_event (dn, dev); /* Most EEH events are due to device driver bugs. Having * a stack trace will help the device-driver authors figure * out what happened. So print that out. */ - if (rets[0] != 5) dump_stack(); + dump_stack(); return 1; dn_unlock: @@ -458,38 +505,6 @@ EXPORT_SYMBOL(eeh_check_failure); /* The code below deals with error recovery */ /** - * eeh_slot_availability - returns error status of slot - * @pdn pci device node - * - * Return negative value if a permanent error, else return - * a number of milliseconds to wait until the PCI slot is - * ready to be used. - */ -static int -eeh_slot_availability(struct pci_dn *pdn) -{ - int rc; - int rets[3]; - - rc = read_slot_reset_state(pdn, rets); - - if (rc) return rc; - - if (rets[1] == 0) return -1; /* EEH is not supported */ - if (rets[0] == 0) return 0; /* Oll Korrect */ - if (rets[0] == 5) { - if (rets[2] == 0) return -1; /* permanently unavailable */ - return rets[2]; /* number of millisecs to wait */ - } - if (rets[0] == 1) - return 250; - - printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n", - rc, rets[0], rets[1], rets[2]); - return -2; -} - -/** * rtas_pci_enable - enable MMIO or DMA transfers for this slot * @pdn pci device node */ @@ -512,9 +527,13 @@ rtas_pci_enable(struct pci_dn *pdn, int function) function); if (rc) - printk(KERN_WARNING "EEH: Cannot enable function %d, err=%d dn=%s\n", + printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n", function, rc, pdn->node->full_name); + rc = eeh_wait_for_slot_status (pdn, PCI_BUS_RESET_WAIT_MSEC); + if ((rc == 4) && (function == EEH_THAW_MMIO)) + return 0; + return rc; } @@ -595,36 +614,24 @@ int rtas_set_slot_reset(struct pci_dn *pdn) { int i, rc; - __rtas_set_slot_reset(pdn); + /* Take three shots at resetting the bus */ + for (i=0; i<3; i++) { + __rtas_set_slot_reset(pdn); - /* Now double check with the firmware to make sure the device is - * ready to be used; if not, wait for recovery. */ - for (i=0; i<10; i++) { - rc = eeh_slot_availability (pdn); + rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC); if (rc == 0) return 0; - if (rc == -2) { - printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n", - i, pdn->node->full_name); - __rtas_set_slot_reset(pdn); - continue; - } - if (rc < 0) { printk (KERN_ERR "EEH: unrecoverable slot failure %s\n", pdn->node->full_name); return -1; } - - msleep (rc+100); + printk (KERN_ERR "EEH: bus reset %d failed on slot %s\n", + i+1, pdn->node->full_name); } - rc = eeh_slot_availability (pdn); - if (rc) - printk (KERN_ERR "EEH: timeout resetting slot %s\n", pdn->node->full_name); - - return rc; + return -1; } /* ------------------------------------------------------- */ @@ -744,16 +751,48 @@ struct eeh_early_enable_info { unsigned int buid_lo; }; +static int get_pe_addr (int config_addr, + struct eeh_early_enable_info *info) +{ + unsigned int rets[3]; + int ret; + + /* Use latest config-addr token on power6 */ + if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) { + /* Make sure we have a PE in hand */ + ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets, + config_addr, info->buid_hi, info->buid_lo, 1); + if (ret || (rets[0]==0)) + return 0; + + ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets, + config_addr, info->buid_hi, info->buid_lo, 0); + if (ret) + return 0; + return rets[0]; + } + + /* Use older config-addr token on power5 */ + if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { + ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets, + config_addr, info->buid_hi, info->buid_lo, 0); + if (ret) + return 0; + return rets[0]; + } + return 0; +} + /* Enable eeh for the given device node. */ static void *early_enable_eeh(struct device_node *dn, void *data) { unsigned int rets[3]; struct eeh_early_enable_info *info = data; int ret; - const char *status = get_property(dn, "status", NULL); - const u32 *class_code = get_property(dn, "class-code", NULL); - const u32 *vendor_id = get_property(dn, "vendor-id", NULL); - const u32 *device_id = get_property(dn, "device-id", NULL); + const char *status = of_get_property(dn, "status", NULL); + const u32 *class_code = of_get_property(dn, "class-code", NULL); + const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL); + const u32 *device_id = of_get_property(dn, "device-id", NULL); const u32 *regs; int enable; struct pci_dn *pdn = PCI_DN(dn); @@ -796,7 +835,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) /* Ok... see if this device supports EEH. Some do, some don't, * and the only way to find out is to check each and every one. */ - regs = get_property(dn, "reg", NULL); + regs = of_get_property(dn, "reg", NULL); if (regs) { /* First register entry is addr (00BBSS00) */ /* Try to enable eeh */ @@ -810,15 +849,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) /* If the newer, better, ibm,get-config-addr-info is supported, * then use that instead. */ - pdn->eeh_pe_config_addr = 0; - if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { - ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets, - pdn->eeh_config_addr, - info->buid_hi, info->buid_lo, - 0); - if (ret == 0) - pdn->eeh_pe_config_addr = rets[0]; - } + pdn->eeh_pe_config_addr = get_pe_addr(pdn->eeh_config_addr, info); /* Some older systems (Power4) allow the * ibm,set-eeh-option call to succeed even on nodes @@ -889,6 +920,7 @@ void __init eeh_init(void) ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state"); ibm_slot_error_detail = rtas_token("ibm,slot-error-detail"); ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info"); + ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2"); ibm_configure_bridge = rtas_token ("ibm,configure-bridge"); if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index a4c0bf84ef2..3170e003f76 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -158,7 +158,8 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata) return; rc = driver->err_handler->slot_reset(dev); - if (*res == PCI_ERS_RESULT_NONE) *res = rc; + if ((*res == PCI_ERS_RESULT_NONE) || + (*res == PCI_ERS_RESULT_RECOVERED)) *res = rc; if (*res == PCI_ERS_RESULT_DISCONNECT && rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; } @@ -248,6 +249,7 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata) static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) { + struct device_node *dn; int cnt, rc; /* pcibios will clear the counter; save the value */ @@ -263,23 +265,20 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) if (rc) return rc; - /* New-style config addrs might be shared across multiple devices, - * Walk over all functions on this device */ - if (pe_dn->eeh_pe_config_addr) { - struct device_node *pe = pe_dn->node; - pe = pe->parent->child; - while (pe) { - struct pci_dn *ppe = PCI_DN(pe); - if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) { - rtas_configure_bridge(ppe); - eeh_restore_bars(ppe); - } - pe = pe->sibling; + /* Walk over all functions on this device. */ + dn = pe_dn->node; + if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) + dn = dn->parent->child; + + while (dn) { + struct pci_dn *ppe = PCI_DN(dn); + /* On Power4, always true because eeh_pe_config_addr=0 */ + if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) { + rtas_configure_bridge(ppe); + eeh_restore_bars(ppe); } - } else { - rtas_configure_bridge(pe_dn); - eeh_restore_bars(pe_dn); - } + dn = dn->sibling; + } /* Give the system 5 seconds to finish running the user-space * hotplug shutdown scripts, e.g. ifdown for ethernet. Yes, @@ -299,7 +298,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) /* The longest amount of time to wait for a pci device * to come back on line, in seconds. */ -#define MAX_WAIT_FOR_RECOVERY 15 +#define MAX_WAIT_FOR_RECOVERY 150 struct pci_dn * handle_eeh_events (struct eeh_event *event) { @@ -315,14 +314,14 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) if (!frozen_dn) { - location = get_property(event->dn, "ibm,loc-code", NULL); + location = of_get_property(event->dn, "ibm,loc-code", NULL); location = location ? location : "unknown"; printk(KERN_ERR "EEH: Error: Cannot find partition endpoint " "for location=%s pci addr=%s\n", location, pci_name(event->dev)); return NULL; } - location = get_property(frozen_dn, "ibm,loc-code", NULL); + location = of_get_property(frozen_dn, "ibm,loc-code", NULL); location = location ? location : "unknown"; /* There are two different styles for coming up with the PE. @@ -341,13 +340,6 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) return NULL; } -#if 0 - /* We may get "permanent failure" messages on empty slots. - * These are false alarms. Empty slots have no child dn. */ - if ((event->state == pci_channel_io_perm_failure) && (frozen_device == NULL)) - return; -#endif - frozen_pdn = PCI_DN(frozen_dn); frozen_pdn->eeh_freeze_count++; @@ -362,13 +354,12 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES) goto excess_failures; - /* If the reset state is a '5' and the time to reset is 0 (infinity) - * or is more then 15 seconds, then mark this as a permanent failure. - */ - if ((event->state == pci_channel_io_perm_failure) && - ((event->time_unavail <= 0) || - (event->time_unavail > MAX_WAIT_FOR_RECOVERY*1000))) + /* Get the current PCI slot state. */ + rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000); + if (rc < 0) { + printk(KERN_WARNING "EEH: Permanent failure\n"); goto hard_fail; + } eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); printk(KERN_WARNING @@ -390,14 +381,18 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) */ if (result == PCI_ERS_RESULT_NONE) { rc = eeh_reset_device(frozen_pdn, frozen_bus); - if (rc) + if (rc) { + printk(KERN_WARNING "EEH: Unable to reset, rc=%d\n", rc); goto hard_fail; + } } /* If all devices reported they can proceed, then re-enable MMIO */ if (result == PCI_ERS_RESULT_CAN_RECOVER) { rc = rtas_pci_enable(frozen_pdn, EEH_THAW_MMIO); + if (rc < 0) + goto hard_fail; if (rc) { result = PCI_ERS_RESULT_NEED_RESET; } else { @@ -410,6 +405,8 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) if (result == PCI_ERS_RESULT_CAN_RECOVER) { rc = rtas_pci_enable(frozen_pdn, EEH_THAW_DMA); + if (rc < 0) + goto hard_fail; if (rc) result = PCI_ERS_RESULT_NEED_RESET; else @@ -417,21 +414,28 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) } /* If any device has a hard failure, then shut off everything. */ - if (result == PCI_ERS_RESULT_DISCONNECT) + if (result == PCI_ERS_RESULT_DISCONNECT) { + printk(KERN_WARNING "EEH: Device driver gave up\n"); goto hard_fail; + } /* If any device called out for a reset, then reset the slot */ if (result == PCI_ERS_RESULT_NEED_RESET) { rc = eeh_reset_device(frozen_pdn, NULL); - if (rc) + if (rc) { + printk(KERN_WARNING "EEH: Cannot reset, rc=%d\n", rc); goto hard_fail; + } result = PCI_ERS_RESULT_NONE; pci_walk_bus(frozen_bus, eeh_report_reset, &result); } /* All devices should claim they have recovered by now. */ - if (result != PCI_ERS_RESULT_RECOVERED) + if ((result != PCI_ERS_RESULT_RECOVERED) && + (result != PCI_ERS_RESULT_NONE)) { + printk(KERN_WARNING "EEH: Not recovered\n"); goto hard_fail; + } /* Tell all device drivers that they can resume operations */ pci_walk_bus(frozen_bus, eeh_report_resume, NULL); diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 49037edf7d3..ddb80f5d850 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -118,9 +118,7 @@ static void eeh_thread_launcher(struct work_struct *dummy) * (from a workqueue). */ int eeh_send_failure_event (struct device_node *dn, - struct pci_dev *dev, - enum pci_channel_state state, - int time_unavail) + struct pci_dev *dev) { unsigned long flags; struct eeh_event *event; @@ -128,7 +126,7 @@ int eeh_send_failure_event (struct device_node *dn, if (!mem_init_done) { printk(KERN_ERR "EEH: event during early boot not handled\n"); - location = get_property(dn, "ibm,loc-code", NULL); + location = of_get_property(dn, "ibm,loc-code", NULL); printk(KERN_ERR "EEH: device node = %s\n", dn->full_name); printk(KERN_ERR "EEH: PCI location = %s\n", location); return 1; @@ -144,8 +142,6 @@ int eeh_send_failure_event (struct device_node *dn, event->dn = dn; event->dev = dev; - event->state = state; - event->time_unavail = time_unavail; /* We may or may not be called in an interrupt context */ spin_lock_irqsave(&eeh_eventlist_lock, flags); diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 90522e3c9d4..29bf83bfb1f 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c @@ -80,7 +80,7 @@ void __init fw_feature_init(void) goto out; } - hypertas = get_property(dn, "ibm,hypertas-functions", &len); + hypertas = of_get_property(dn, "ibm,hypertas-functions", &len); if (hypertas == NULL) goto out; diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index f460b9cbfd4..9711eb0d549 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -143,7 +143,7 @@ static int pseries_add_processor(struct device_node *np) int err = -ENOSPC, len, nthreads, i; const u32 *intserv; - intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); + intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len); if (!intserv) return 0; @@ -203,7 +203,7 @@ static void pseries_remove_processor(struct device_node *np) int len, nthreads, i; const u32 *intserv; - intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); + intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len); if (!intserv) return; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index e6653a868b9..66665c82415 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -242,6 +242,7 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum) return tce_ret; } +#ifdef CONFIG_PCI static void iommu_table_setparms(struct pci_controller *phb, struct device_node *dn, struct iommu_table *tbl) @@ -252,8 +253,8 @@ static void iommu_table_setparms(struct pci_controller *phb, node = (struct device_node *)phb->arch_data; - basep = get_property(node, "linux,tce-base", NULL); - sizep = get_property(node, "linux,tce-size", NULL); + basep = of_get_property(node, "linux,tce-base", NULL); + sizep = of_get_property(node, "linux,tce-size", NULL); if (basep == NULL || sizep == NULL) { printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has " "missing tce entries !\n", dn->full_name); @@ -403,7 +404,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) /* Find nearest ibm,dma-window, walking up the device tree */ for (pdn = dn; pdn != NULL; pdn = pdn->parent) { - dma_window = get_property(pdn, "ibm,dma-window", NULL); + dma_window = of_get_property(pdn, "ibm,dma-window", NULL); if (dma_window != NULL) break; } @@ -478,29 +479,6 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) pci_name(dev)); } -static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) -{ - int err = NOTIFY_OK; - struct device_node *np = node; - struct pci_dn *pci = PCI_DN(np); - - switch (action) { - case PSERIES_RECONFIG_REMOVE: - if (pci && pci->iommu_table && - get_property(np, "ibm,dma-window", NULL)) - iommu_free_table(np); - break; - default: - err = NOTIFY_DONE; - break; - } - return err; -} - -static struct notifier_block iommu_reconfig_nb = { - .notifier_call = iommu_reconfig_notifier, -}; - static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) { struct device_node *pdn, *dn; @@ -521,7 +499,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; pdn = pdn->parent) { - dma_window = get_property(pdn, "ibm,dma-window", NULL); + dma_window = of_get_property(pdn, "ibm,dma-window", NULL); if (dma_window) break; } @@ -554,15 +532,44 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) dev->dev.archdata.dma_data = pci->iommu_table; } +#else /* CONFIG_PCI */ +#define pci_dma_bus_setup_pSeries NULL +#define pci_dma_dev_setup_pSeries NULL +#define pci_dma_bus_setup_pSeriesLP NULL +#define pci_dma_dev_setup_pSeriesLP NULL +#endif /* !CONFIG_PCI */ + +static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) +{ + int err = NOTIFY_OK; + struct device_node *np = node; + struct pci_dn *pci = PCI_DN(np); + + switch (action) { + case PSERIES_RECONFIG_REMOVE: + if (pci && pci->iommu_table && + of_get_property(np, "ibm,dma-window", NULL)) + iommu_free_table(np); + break; + default: + err = NOTIFY_DONE; + break; + } + return err; +} + +static struct notifier_block iommu_reconfig_nb = { + .notifier_call = iommu_reconfig_notifier, +}; /* These are called very early. */ void iommu_init_early_pSeries(void) { - if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { + if (of_chosen && of_get_property(of_chosen, "linux,iommu-off", NULL)) { /* Direct I/O, IOMMU off */ ppc_md.pci_dma_dev_setup = NULL; ppc_md.pci_dma_bus_setup = NULL; - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); return; } @@ -588,6 +595,6 @@ void iommu_init_early_pSeries(void) pSeries_reconfig_notifier_register(&iommu_reconfig_nb); - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); } diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 843ee964321..3a70e8ad7bc 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -209,13 +209,13 @@ void __init find_udbg_vterm(void) /* find the boot console from /chosen/stdout */ if (!of_chosen) return; - name = get_property(of_chosen, "linux,stdout-path", NULL); + name = of_get_property(of_chosen, "linux,stdout-path", NULL); if (name == NULL) return; stdout_node = of_find_node_by_path(name); if (!stdout_node) return; - name = get_property(stdout_node, "name", NULL); + name = of_get_property(stdout_node, "name", NULL); if (!name) { printk(KERN_WARNING "stdout node missing 'name' property!\n"); goto out; @@ -226,7 +226,7 @@ void __init find_udbg_vterm(void) /* Check if it's a virtual terminal */ if (strncmp(name, "vty", 3) != 0) goto out; - termno = get_property(stdout_node, "reg", NULL); + termno = of_get_property(stdout_node, "reg", NULL); if (termno == NULL) goto out; vtermno = termno[0]; diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 64163cecdf9..f68903e15bd 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -130,7 +130,7 @@ int __init pSeries_nvram_init(void) if (nvram == NULL) return -ENODEV; - nbytes_p = get_property(nvram, "#bytes", &proplen); + nbytes_p = of_get_property(nvram, "#bytes", &proplen); if (nbytes_p == NULL || proplen != sizeof(unsigned int)) return -EIO; diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index fa59124ce3f..2c6ded29f73 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -25,6 +25,7 @@ #include <linux/pci.h> #include <linux/string.h> +#include <asm/eeh.h> #include <asm/pci-bridge.h> #include <asm/prom.h> #include <asm/ppc-pci.h> @@ -39,7 +40,7 @@ void pcibios_name_device(struct pci_dev *dev) */ dn = pci_device_to_OF_node(dev); if (dn) { - char *loc_code = get_property(dn, "ibm,loc-code", 0); + const char *loc_code = of_get_property(dn, "ibm,loc-code", 0); if (loc_code) { int loc_len = strlen(loc_code); if (loc_len < sizeof(dev->dev.name)) { diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index ac56b868913..fdc1a369f76 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -29,6 +29,7 @@ #include <asm/pci-bridge.h> #include <asm/ppc-pci.h> #include <asm/firmware.h> +#include <asm/eeh.h> static struct pci_bus * find_bus_among_children(struct pci_bus *bus, diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index edc03887311..53aa04101ce 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -85,7 +85,7 @@ static void request_ras_irqs(struct device_node *np, * map those interrupts using the default interrupt host and default * trigger */ - opicprop = get_property(np, "open-pic-interrupt", &opicplen); + opicprop = of_get_property(np, "open-pic-interrupt", &opicplen); if (opicprop) { opicplen /= sizeof(u32); for (i = 0; i < opicplen; i++) { diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index 77d0937d5c0..9797b10b293 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -363,7 +363,7 @@ static int get_eventscan_parms(void) node = of_find_node_by_path("/rtas"); - ip = get_property(node, "rtas-event-scan-rate", NULL); + ip = of_get_property(node, "rtas-event-scan-rate", NULL); if (ip == NULL) { printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n"); of_node_put(node); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 34aff47b1f5..33eec2822c6 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -65,6 +65,7 @@ #include <asm/udbg.h> #include <asm/smp.h> #include <asm/firmware.h> +#include <asm/eeh.h> #include "plpar_wrappers.h" #include "pseries.h" @@ -92,7 +93,7 @@ static void pSeries_show_cpuinfo(struct seq_file *m) root = of_find_node_by_path("/"); if (root) - model = get_property(root, "model", NULL); + model = of_get_property(root, "model", NULL); seq_printf(m, "machine\t\t: CHRP %s\n", model); of_node_put(root); } @@ -138,8 +139,8 @@ static void __init pseries_mpic_init_IRQ(void) struct mpic *mpic; np = of_find_node_by_path("/"); - naddr = prom_n_addr_cells(np); - opprop = get_property(np, "platform-open-pic", &opplen); + naddr = of_n_addr_cells(np); + opprop = of_get_property(np, "platform-open-pic", &opplen); if (opprop != 0) { openpic_addr = of_read_number(opprop, naddr); printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); @@ -188,11 +189,11 @@ static void __init pseries_mpic_init_IRQ(void) break; if (strcmp(np->name, "pci") != 0) continue; - addrp = get_property(np, "8259-interrupt-acknowledge", + addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL); if (addrp == NULL) continue; - naddr = prom_n_addr_cells(np); + naddr = of_n_addr_cells(np); intack = addrp[naddr-1]; if (naddr > 1) intack |= ((unsigned long)addrp[naddr-2]) << 32; @@ -225,7 +226,7 @@ static void __init pseries_discover_pic(void) for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) { - typep = get_property(np, "compatible", NULL); + typep = of_get_property(np, "compatible", NULL); if (strstr(typep, "open-pic")) { pSeries_mpic_node = of_node_get(np); ppc_md.init_IRQ = pseries_mpic_init_IRQ; @@ -334,32 +335,6 @@ static void __init pSeries_init_early(void) DBG(" <- pSeries_init_early()\n"); } - -static int pSeries_check_legacy_ioport(unsigned int baseport) -{ - struct device_node *np; - -#define I8042_DATA_REG 0x60 -#define FDC_BASE 0x3f0 - - - switch(baseport) { - case I8042_DATA_REG: - np = of_find_node_by_type(NULL, "8042"); - if (np == NULL) - return -ENODEV; - of_node_put(np); - break; - case FDC_BASE: - np = of_find_node_by_type(NULL, "fdc"); - if (np == NULL) - return -ENODEV; - of_node_put(np); - break; - } - return 0; -} - /* * Called very early, MMU is off, device-tree isn't unflattened */ @@ -514,6 +489,10 @@ void pSeries_power_off(void) for (;;); } +#ifndef CONFIG_PCI +void pSeries_final_fixup(void) { } +#endif + define_machine(pseries) { .name = "pSeries", .probe = pSeries_probe, @@ -532,7 +511,6 @@ define_machine(pseries) { .set_rtc_time = rtas_set_rtc_time, .calibrate_decr = generic_calibrate_decr, .progress = rtas_progress, - .check_legacy_ioport = pSeries_check_legacy_ioport, .system_reset_exception = pSeries_system_reset_exception, .machine_check_exception = pSeries_machine_check_exception, }; diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 81d172d6503..896cbf340c4 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -576,7 +576,7 @@ static void __init xics_init_one_node(struct device_node *np, * This happens to be the case so far but we are playing with fire... * should be fixed one of these days. -BenH. */ - ireg = get_property(np, "ibm,interrupt-server-ranges", NULL); + ireg = of_get_property(np, "ibm,interrupt-server-ranges", NULL); /* Do that ever happen ? we'll know soon enough... but even good'old * f80 does have that property .. @@ -588,7 +588,7 @@ static void __init xics_init_one_node(struct device_node *np, */ *indx = *ireg; } - ireg = get_property(np, "reg", &ilen); + ireg = of_get_property(np, "reg", &ilen); if (!ireg) panic("xics_init_IRQ: can't find interrupt reg property"); @@ -640,10 +640,10 @@ static void __init xics_setup_8259_cascade(void) break; if (strcmp(np->name, "pci") != 0) continue; - addrp = get_property(np, "8259-interrupt-acknowledge", NULL); + addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL); if (addrp == NULL) continue; - naddr = prom_n_addr_cells(np); + naddr = of_n_addr_cells(np); intack = addrp[naddr-1]; if (naddr > 1) intack |= ((unsigned long)addrp[naddr-2]) << 32; @@ -664,10 +664,11 @@ static struct device_node *cpuid_to_of_node(int cpu) int i, len; const u32 *intserv; - intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); + intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", + &len); if (!intserv) - intserv = get_property(np, "reg", &len); + intserv = of_get_property(np, "reg", &len); i = len / sizeof(u32); @@ -709,7 +710,7 @@ void __init xics_init_IRQ(void) /* Find the server numbers for the boot cpu. */ np = cpuid_to_of_node(boot_cpuid); BUG_ON(!np); - ireg = get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); + ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); if (!ireg) goto skip_gserver_check; i = ilen / sizeof(int); @@ -725,7 +726,7 @@ void __init xics_init_IRQ(void) default_server = hcpuid; default_distrib_server = ireg[j+1]; - isize = get_property(np, + isize = of_get_property(np, "ibm,interrupt-server#-size", NULL); if (isize) interrupt_server_size = *isize; diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 26ca3ffbc1d..e96ca9618db 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -11,12 +11,17 @@ obj-$(CONFIG_PPC_PMI) += pmi.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o +obj-$(CONFIG_FSL_PCIE) += fsl_pcie.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ +# contains only the suspend handler for time +obj-$(CONFIG_PM) += timer.o + ifeq ($(CONFIG_PPC_MERGE),y) obj-$(CONFIG_PPC_I8259) += i8259.o obj-$(CONFIG_PPC_83xx) += ipic.o +obj-$(CONFIG_4xx) += uic.o endif # Temporary hack until we have migrated to asm-powerpc diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 1488535b0e1..336186dd7f1 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -333,7 +333,7 @@ void iommu_init_early_dart(void) ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; /* Setup pci_dma ops */ - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); return; } @@ -343,7 +343,7 @@ void iommu_init_early_dart(void) ppc_md.pci_dma_bus_setup = NULL; /* Setup pci_dma ops */ - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); } diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index 1fc5819e7d1..574b6ef44e0 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c @@ -26,7 +26,7 @@ unsigned int dcr_resource_start(struct device_node *np, unsigned int index) { unsigned int ds; - const u32 *dr = get_property(np, "dcr-reg", &ds); + const u32 *dr = of_get_property(np, "dcr-reg", &ds); if (dr == NULL || ds & 1 || index >= (ds / 8)) return 0; @@ -37,7 +37,7 @@ unsigned int dcr_resource_start(struct device_node *np, unsigned int index) unsigned int dcr_resource_len(struct device_node *np, unsigned int index) { unsigned int ds; - const u32 *dr = get_property(np, "dcr-reg", &ds); + const u32 *dr = of_get_property(np, "dcr-reg", &ds); if (dr == NULL || ds & 1 || index >= (ds / 8)) return 0; @@ -53,9 +53,9 @@ static struct device_node * find_dcr_parent(struct device_node * node) const u32 *p; for (par = of_node_get(node); par;) { - if (get_property(par, "dcr-controller", NULL)) + if (of_get_property(par, "dcr-controller", NULL)) break; - p = get_property(par, "dcr-parent", NULL); + p = of_get_property(par, "dcr-parent", NULL); tmp = par; if (p == NULL) par = of_get_parent(par); @@ -80,13 +80,13 @@ u64 of_translate_dcr_address(struct device_node *dev, return OF_BAD_ADDR; /* Stride is not properly defined yet, default to 0x10 for Axon */ - p = get_property(dp, "dcr-mmio-stride", NULL); + p = of_get_property(dp, "dcr-mmio-stride", NULL); stride = (p == NULL) ? 0x10 : *p; /* XXX FIXME: Which property name is to use of the 2 following ? */ - p = get_property(dp, "dcr-mmio-range", NULL); + p = of_get_property(dp, "dcr-mmio-range", NULL); if (p == NULL) - p = get_property(dp, "dcr-mmio-space", NULL); + p = of_get_property(dp, "dcr-mmio-space", NULL); if (p == NULL) return OF_BAD_ADDR; diff --git a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c b/arch/powerpc/sysdev/fsl_pcie.c index a2f4f730213..041c07e8b66 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c +++ b/arch/powerpc/sysdev/fsl_pcie.c @@ -24,8 +24,6 @@ #include <asm/pci-bridge.h> #include <asm/machdep.h> -#include "mpc86xx.h" - #define PCI_CFG_OUT out_be32 /* ERRATA PCI-Ex 14 PCIE Controller timeout */ diff --git a/arch/powerpc/sysdev/fsl_pcie.h b/arch/powerpc/sysdev/fsl_pcie.h new file mode 100644 index 00000000000..8d9779c84be --- /dev/null +++ b/arch/powerpc/sysdev/fsl_pcie.h @@ -0,0 +1,94 @@ +/* + * MPC85xx/86xx PCI Express structure define + * + * Copyright 2007 Freescale Semiconductor, 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. + * + */ + +#ifdef __KERNEL__ +#ifndef __POWERPC_FSL_PCIE_H +#define __POWERPC_FSL_PCIE_H + +/* PCIE Express IO block registers in 85xx/86xx */ + +struct ccsr_pex { + __be32 __iomem pex_config_addr; /* 0x.000 - PCI Express Configuration Address Register */ + __be32 __iomem pex_config_data; /* 0x.004 - PCI Express Configuration Data Register */ + u8 __iomem res1[4]; + __be32 __iomem pex_otb_cpl_tor; /* 0x.00c - PCI Express Outbound completion timeout register */ + __be32 __iomem pex_conf_tor; /* 0x.010 - PCI Express configuration timeout register */ + u8 __iomem res2[12]; + __be32 __iomem pex_pme_mes_dr; /* 0x.020 - PCI Express PME and message detect register */ + __be32 __iomem pex_pme_mes_disr; /* 0x.024 - PCI Express PME and message disable register */ + __be32 __iomem pex_pme_mes_ier; /* 0x.028 - PCI Express PME and message interrupt enable register */ + __be32 __iomem pex_pmcr; /* 0x.02c - PCI Express power management command register */ + u8 __iomem res3[3024]; + __be32 __iomem pexotar0; /* 0x.c00 - PCI Express outbound translation address register 0 */ + __be32 __iomem pexotear0; /* 0x.c04 - PCI Express outbound translation extended address register 0*/ + u8 __iomem res4[8]; + __be32 __iomem pexowar0; /* 0x.c10 - PCI Express outbound window attributes register 0*/ + u8 __iomem res5[12]; + __be32 __iomem pexotar1; /* 0x.c20 - PCI Express outbound translation address register 1 */ + __be32 __iomem pexotear1; /* 0x.c24 - PCI Express outbound translation extended address register 1*/ + __be32 __iomem pexowbar1; /* 0x.c28 - PCI Express outbound window base address register 1*/ + u8 __iomem res6[4]; + __be32 __iomem pexowar1; /* 0x.c30 - PCI Express outbound window attributes register 1*/ + u8 __iomem res7[12]; + __be32 __iomem pexotar2; /* 0x.c40 - PCI Express outbound translation address register 2 */ + __be32 __iomem pexotear2; /* 0x.c44 - PCI Express outbound translation extended address register 2*/ + __be32 __iomem pexowbar2; /* 0x.c48 - PCI Express outbound window base address register 2*/ + u8 __iomem res8[4]; + __be32 __iomem pexowar2; /* 0x.c50 - PCI Express outbound window attributes register 2*/ + u8 __iomem res9[12]; + __be32 __iomem pexotar3; /* 0x.c60 - PCI Express outbound translation address register 3 */ + __be32 __iomem pexotear3; /* 0x.c64 - PCI Express outbound translation extended address register 3*/ + __be32 __iomem pexowbar3; /* 0x.c68 - PCI Express outbound window base address register 3*/ + u8 __iomem res10[4]; + __be32 __iomem pexowar3; /* 0x.c70 - PCI Express outbound window attributes register 3*/ + u8 __iomem res11[12]; + __be32 __iomem pexotar4; /* 0x.c80 - PCI Express outbound translation address register 4 */ + __be32 __iomem pexotear4; /* 0x.c84 - PCI Express outbound translation extended address register 4*/ + __be32 __iomem pexowbar4; /* 0x.c88 - PCI Express outbound window base address register 4*/ + u8 __iomem res12[4]; + __be32 __iomem pexowar4; /* 0x.c90 - PCI Express outbound window attributes register 4*/ + u8 __iomem res13[12]; + u8 __iomem res14[256]; + __be32 __iomem pexitar3; /* 0x.da0 - PCI Express inbound translation address register 3 */ + u8 __iomem res15[4]; + __be32 __iomem pexiwbar3; /* 0x.da8 - PCI Express inbound window base address register 3 */ + __be32 __iomem pexiwbear3; /* 0x.dac - PCI Express inbound window base extended address register 3 */ + __be32 __iomem pexiwar3; /* 0x.db0 - PCI Express inbound window attributes register 3 */ + u8 __iomem res16[12]; + __be32 __iomem pexitar2; /* 0x.dc0 - PCI Express inbound translation address register 2 */ + u8 __iomem res17[4]; + __be32 __iomem pexiwbar2; /* 0x.dc8 - PCI Express inbound window base address register 2 */ + __be32 __iomem pexiwbear2; /* 0x.dcc - PCI Express inbound window base extended address register 2 */ + __be32 __iomem pexiwar2; /* 0x.dd0 - PCI Express inbound window attributes register 2 */ + u8 __iomem res18[12]; + __be32 __iomem pexitar1; /* 0x.de0 - PCI Express inbound translation address register 2 */ + u8 __iomem res19[4]; + __be32 __iomem pexiwbar1; /* 0x.de8 - PCI Express inbound window base address register 2 */ + __be32 __iomem pexiwbear1; /* 0x.dec - PCI Express inbound window base extended address register 2 */ + __be32 __iomem pexiwar1; /* 0x.df0 - PCI Express inbound window attributes register 2 */ + u8 __iomem res20[12]; + __be32 __iomem pex_err_dr; /* 0x.e00 - PCI Express error detect register */ + u8 __iomem res21[4]; + __be32 __iomem pex_err_en; /* 0x.e08 - PCI Express error interrupt enable register */ + u8 __iomem res22[4]; + __be32 __iomem pex_err_disr; /* 0x.e10 - PCI Express error disable register */ + u8 __iomem res23[12]; + __be32 __iomem pex_err_cap_stat; /* 0x.e20 - PCI Express error capture status register */ + u8 __iomem res24[4]; + __be32 __iomem pex_err_cap_r0; /* 0x.e28 - PCI Express error capture register 0 */ + __be32 __iomem pex_err_cap_r1; /* 0x.e2c - PCI Express error capture register 0 */ + __be32 __iomem pex_err_cap_r2; /* 0x.e30 - PCI Express error capture register 0 */ + __be32 __iomem pex_err_cap_r3; /* 0x.e34 - PCI Express error capture register 0 */ +}; + +#endif /* __POWERPC_FSL_PCIE_H */ +#endif /* __KERNEL__ */ diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index d20f02927f7..8a123c71449 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -52,7 +52,7 @@ phys_addr_t get_immrbase(void) soc = of_find_node_by_type(NULL, "soc"); if (soc) { unsigned int size; - const void *prop = get_property(soc, "reg", &size); + const void *prop = of_get_property(soc, "reg", &size); if (prop) immrbase = of_translate_address(soc, prop); @@ -78,8 +78,8 @@ u32 get_brgfreq(void) node = of_find_node_by_type(NULL, "cpm"); if (node) { unsigned int size; - const unsigned int *prop = get_property(node, "brg-frequency", - &size); + const unsigned int *prop = of_get_property(node, + "brg-frequency", &size); if (prop) brgfreq = *prop; @@ -103,8 +103,8 @@ u32 get_baudrate(void) node = of_find_node_by_type(NULL, "serial"); if (node) { unsigned int size; - const unsigned int *prop = get_property(node, "current-speed", - &size); + const unsigned int *prop = of_get_property(node, + "current-speed", &size); if (prop) fs_baudrate = *prop; @@ -153,7 +153,8 @@ static int __init gfar_mdio_of_init(void) while ((child = of_get_next_child(np, child)) != NULL) { int irq = irq_of_parse_and_map(child, 0); if (irq != NO_IRQ) { - const u32 *id = get_property(child, "reg", NULL); + const u32 *id = of_get_property(child, + "reg", NULL); mdio_data.irq[*id] = irq; } } @@ -209,7 +210,7 @@ static int __init gfar_of_init(void) of_irq_to_resource(np, 0, &r[1]); - model = get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); /* If we aren't the FEC we have multiple interrupts */ if (model && strcasecmp(model, "FEC")) { @@ -253,7 +254,7 @@ static int __init gfar_of_init(void) FSL_GIANFAR_DEV_HAS_VLAN | FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; - ph = get_property(np, "phy-handle", NULL); + ph = of_get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); if (phy == NULL) { @@ -263,7 +264,7 @@ static int __init gfar_of_init(void) mdio = of_get_parent(phy); - id = get_property(phy, "reg", NULL); + id = of_get_property(phy, "reg", NULL); ret = of_address_to_resource(mdio, 0, &res); if (ret) { of_node_put(phy); @@ -325,11 +326,11 @@ static int __init fsl_i2c_of_init(void) } i2c_data.device_flags = 0; - flags = get_property(np, "dfsrr", NULL); + flags = of_get_property(np, "dfsrr", NULL); if (flags) i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR; - flags = get_property(np, "fsl5200-clocking", NULL); + flags = of_get_property(np, "fsl5200-clocking", NULL); if (flags) i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200; @@ -374,7 +375,7 @@ static int __init mpc83xx_wdt_init(void) goto nosoc; } - freq = get_property(soc, "bus-frequency", NULL); + freq = of_get_property(soc, "bus-frequency", NULL); if (!freq) { ret = -ENODEV; goto err; @@ -466,15 +467,15 @@ static int __init fsl_usb_of_init(void) usb_data.operating_mode = FSL_USB2_MPH_HOST; - prop = get_property(np, "port0", NULL); + prop = of_get_property(np, "port0", NULL); if (prop) usb_data.port_enables |= FSL_USB2_PORT0_ENABLED; - prop = get_property(np, "port1", NULL); + prop = of_get_property(np, "port1", NULL); if (prop) usb_data.port_enables |= FSL_USB2_PORT1_ENABLED; - prop = get_property(np, "phy_type", NULL); + prop = of_get_property(np, "phy_type", NULL); usb_data.phy_mode = determine_usb_phy(prop); ret = @@ -501,7 +502,7 @@ static int __init fsl_usb_of_init(void) of_irq_to_resource(np, 0, &r[1]); - prop = get_property(np, "dr_mode", NULL); + prop = of_get_property(np, "dr_mode", NULL); if (!prop || !strcmp(prop, "host")) { usb_data.operating_mode = FSL_USB2_DR_HOST; @@ -538,7 +539,7 @@ static int __init fsl_usb_of_init(void) goto err; } - prop = get_property(np, "phy_type", NULL); + prop = of_get_property(np, "phy_type", NULL); usb_data.phy_mode = determine_usb_phy(prop); if (usb_dev_dr_host) { @@ -633,7 +634,7 @@ static int __init fs_enet_of_init(void) goto err; } - model = get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); if (model == NULL) { ret = -ENODEV; goto unreg; @@ -643,7 +644,7 @@ static int __init fs_enet_of_init(void) if (mac_addr) memcpy(fs_enet_data.macaddr, mac_addr, 6); - ph = get_property(np, "phy-handle", NULL); + ph = of_get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); if (phy == NULL) { @@ -651,12 +652,12 @@ static int __init fs_enet_of_init(void) goto unreg; } - phy_addr = get_property(phy, "reg", NULL); + phy_addr = of_get_property(phy, "reg", NULL); fs_enet_data.phy_addr = *phy_addr; - phy_irq = get_property(phy, "interrupts", NULL); + phy_irq = of_get_property(phy, "interrupts", NULL); - id = get_property(np, "device-id", NULL); + id = of_get_property(np, "device-id", NULL); fs_enet_data.fs_no = *id; strcpy(fs_enet_data.fs_type, model); @@ -668,8 +669,10 @@ static int __init fs_enet_of_init(void) goto unreg; } - fs_enet_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL)); - fs_enet_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL)); + fs_enet_data.clk_rx = *((u32 *)of_get_property(np, + "rx-clock", NULL)); + fs_enet_data.clk_tx = *((u32 *)of_get_property(np, + "tx-clock", NULL)); if (strstr(model, "FCC")) { int fcc_index = *id - 1; @@ -690,7 +693,7 @@ static int __init fs_enet_of_init(void) fs_enet_data.bus_id = (char*)&bus_id[(*id)]; fs_enet_data.init_ioports = init_fcc_ioports; - mdio_bb_prop = get_property(phy, "bitbang", NULL); + mdio_bb_prop = of_get_property(phy, "bitbang", NULL); if (mdio_bb_prop) { struct platform_device *fs_enet_mdio_bb_dev; struct fs_mii_bb_platform_info fs_enet_mdio_bb_data; @@ -796,10 +799,10 @@ static int __init cpm_uart_of_init(void) goto err; } - id = get_property(np, "device-id", NULL); + id = of_get_property(np, "device-id", NULL); cpm_uart_data.fs_no = *id; - model = (char*)get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); strcpy(cpm_uart_data.fs_type, model); cpm_uart_data.uart_clk = ppc_proc_freq; @@ -808,8 +811,10 @@ static int __init cpm_uart_of_init(void) cpm_uart_data.tx_buf_size = 32; cpm_uart_data.rx_num_fifo = 4; cpm_uart_data.rx_buf_size = 32; - cpm_uart_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL)); - cpm_uart_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL)); + cpm_uart_data.clk_rx = *((u32 *)of_get_property(np, + "rx-clock", NULL)); + cpm_uart_data.clk_tx = *((u32 *)of_get_property(np, + "tx-clock", NULL)); ret = platform_device_add_data(cpm_uart_dev, &cpm_uart_data, @@ -833,7 +838,7 @@ arch_initcall(cpm_uart_of_init); #ifdef CONFIG_8xx extern void init_scc_ioports(struct fs_platform_info*); -extern int platform_device_skip(char *model, int id); +extern int platform_device_skip(const char *model, int id); static int __init fs_enet_mdio_of_init(void) { @@ -900,21 +905,22 @@ static int __init fs_enet_of_init(void) struct resource r[4]; struct device_node *phy = NULL, *mdio = NULL; struct fs_platform_info fs_enet_data; - unsigned int *id, *phy_addr; + const unsigned int *id; + const unsigned int *phy_addr; void *mac_addr; - phandle *ph; - char *model; + const phandle *ph; + const char *model; memset(r, 0, sizeof(r)); memset(&fs_enet_data, 0, sizeof(fs_enet_data)); - model = (char *)get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); if (model == NULL) { ret = -ENODEV; goto unreg; } - id = (u32 *) get_property(np, "device-id", NULL); + id = of_get_property(np, "device-id", NULL); fs_enet_data.fs_no = *id; if (platform_device_skip(model, *id)) @@ -929,12 +935,12 @@ static int __init fs_enet_of_init(void) if (mac_addr) memcpy(fs_enet_data.macaddr, mac_addr, 6); - ph = (phandle *) get_property(np, "phy-handle", NULL); + ph = of_get_property(np, "phy-handle", NULL); if (ph != NULL) phy = of_find_node_by_phandle(*ph); if (phy != NULL) { - phy_addr = (u32 *) get_property(phy, "reg", NULL); + phy_addr = of_get_property(phy, "reg", NULL); fs_enet_data.phy_addr = *phy_addr; fs_enet_data.has_phy = 1; @@ -947,7 +953,7 @@ static int __init fs_enet_of_init(void) } } - model = (char*)get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); strcpy(fs_enet_data.fs_type, model); if (strstr(model, "FEC")) { @@ -1038,8 +1044,8 @@ static int __init cpm_smc_uart_of_init(void) i++) { struct resource r[3]; struct fs_uart_platform_info cpm_uart_data; - int *id; - char *model; + const int *id; + const char *model; memset(r, 0, sizeof(r)); memset(&cpm_uart_data, 0, sizeof(cpm_uart_data)); @@ -1066,10 +1072,10 @@ static int __init cpm_smc_uart_of_init(void) goto err; } - model = (char*)get_property(np, "model", NULL); + model = of_get_property(np, "model", NULL); strcpy(cpm_uart_data.fs_type, model); - id = (int*)get_property(np, "device-id", NULL); + id = of_get_property(np, "device-id", NULL); cpm_uart_data.fs_no = *id; cpm_uart_data.uart_clk = ppc_proc_freq; diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index bcfb900481f..0b84b7c775d 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -304,7 +304,7 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic) } } -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS /* Test if an interrupt is sourced from HyperTransport (used on broken U3s) * to force the edge setting on the MPIC and do the ack workaround. @@ -476,7 +476,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) } } -#else /* CONFIG_MPIC_BROKEN_U3 */ +#else /* CONFIG_MPIC_U3_HT_IRQS */ static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source) { @@ -487,7 +487,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) { } -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ #define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) @@ -615,7 +615,7 @@ static void mpic_end_irq(unsigned int irq) mpic_eoi(mpic); } -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS static void mpic_unmask_ht_irq(unsigned int irq) { @@ -665,7 +665,7 @@ static void mpic_end_ht_irq(unsigned int irq) mpic_ht_end_irq(mpic, src); mpic_eoi(mpic); } -#endif /* !CONFIG_MPIC_BROKEN_U3 */ +#endif /* !CONFIG_MPIC_U3_HT_IRQS */ #ifdef CONFIG_SMP @@ -788,7 +788,7 @@ static struct irq_chip mpic_ipi_chip = { }; #endif /* CONFIG_SMP */ -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS static struct irq_chip mpic_irq_ht_chip = { .startup = mpic_startup_ht_irq, .shutdown = mpic_shutdown_ht_irq, @@ -797,7 +797,7 @@ static struct irq_chip mpic_irq_ht_chip = { .eoi = mpic_end_ht_irq, .set_type = mpic_set_irq_type, }; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ static int mpic_host_match(struct irq_host *h, struct device_node *node) @@ -837,11 +837,11 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, /* Default chip */ chip = &mpic->hc_irq; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS /* Check for HT interrupts, override vecpri */ if (mpic_is_ht_interrupt(mpic, hw)) chip = &mpic->hc_ht_irq; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ DBG("mpic: mapping to irq chip @%p\n", chip); @@ -937,12 +937,12 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->hc_irq.typename = name; if (flags & MPIC_PRIMARY) mpic->hc_irq.set_affinity = mpic_set_affinity; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS mpic->hc_ht_irq = mpic_irq_ht_chip; mpic->hc_ht_irq.typename = name; if (flags & MPIC_PRIMARY) mpic->hc_ht_irq.set_affinity = mpic_set_affinity; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ #ifdef CONFIG_SMP mpic->hc_ipi = mpic_ipi_chip; @@ -970,7 +970,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->spurious_vec = intvec_top; /* Check for "big-endian" in device-tree */ - if (node && get_property(node, "big-endian", NULL) != NULL) + if (node && of_get_property(node, "big-endian", NULL) != NULL) mpic->flags |= MPIC_BIG_ENDIAN; @@ -986,13 +986,13 @@ struct mpic * __init mpic_alloc(struct device_node *node, BUG_ON(paddr == 0 && node == NULL); /* If no physical address passed in, check if it's dcr based */ - if (paddr == 0 && get_property(node, "dcr-reg", NULL) != NULL) + if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL) mpic->flags |= MPIC_USES_DCR; #ifdef CONFIG_PPC_DCR if (mpic->flags & MPIC_USES_DCR) { const u32 *dbasep; - dbasep = get_property(node, "dcr-reg", NULL); + dbasep = of_get_property(node, "dcr-reg", NULL); BUG_ON(dbasep == NULL); mpic->dcr_base = *dbasep; mpic->reg_type = mpic_access_dcr; @@ -1006,7 +1006,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, */ if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) { const u32 *reg; - reg = get_property(node, "reg", NULL); + reg = of_get_property(node, "reg", NULL); BUG_ON(reg == NULL); paddr = of_translate_address(node, reg); BUG_ON(paddr == OF_BAD_ADDR); @@ -1142,7 +1142,7 @@ void __init mpic_init(struct mpic *mpic) /* Do the HT PIC fixups on U3 broken mpic */ DBG("MPIC flags: %x\n", mpic->flags); - if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) + if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY)) mpic_scan_ht_pics(mpic); for (i = 0; i < mpic->num_sources; i++) { diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index a5282011d39..85a7c99c100 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c @@ -33,7 +33,7 @@ #include <asm/of_platform.h> #include <asm/io.h> #include <asm/pmi.h> - +#include <asm/prom.h> struct pmi_data { struct list_head handler; @@ -49,21 +49,6 @@ struct pmi_data { }; - -static void __iomem *of_iomap(struct device_node *np) -{ - struct resource res; - - if (of_address_to_resource(np, 0, &res)) - return NULL; - - pr_debug("Resource start: 0x%lx\n", res.start); - pr_debug("Resource end: 0x%lx\n", res.end); - - return ioremap(res.start, 1 + res.end - res.start); -} - - static int pmi_irq_handler(int irq, void *dev_id) { struct pmi_data *data; @@ -118,6 +103,7 @@ out: static struct of_device_id pmi_match[] = { { .type = "ibm,pmi", .name = "ibm,pmi" }, + { .type = "ibm,pmi" }, {}, }; @@ -153,7 +139,7 @@ static int pmi_of_probe(struct of_device *dev, goto out; } - data->pmi_reg = of_iomap(np); + data->pmi_reg = of_iomap(np, 0); if (!data->pmi_reg) { printk(KERN_ERR "pmi: invalid register address.\n"); rc = -EFAULT; @@ -279,6 +265,9 @@ void pmi_register_handler(struct of_device *device, struct pmi_data *data; data = device->dev.driver_data; + if (!data) + return; + spin_lock(&data->handler_spinlock); list_add_tail(&handler->node, &data->handler); spin_unlock(&data->handler_spinlock); @@ -289,10 +278,12 @@ void pmi_unregister_handler(struct of_device *device, struct pmi_handler *handler) { struct pmi_data *data; + data = device->dev.driver_data; - pr_debug("pmi: unregistering handler %p\n", handler); + if (!data) + return; - data = device->dev.driver_data; + pr_debug("pmi: unregistering handler %p\n", handler); spin_lock(&data->handler_spinlock); list_del(&handler->node); diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig index a725e80befa..887739f3bad 100644 --- a/arch/powerpc/sysdev/qe_lib/Kconfig +++ b/arch/powerpc/sysdev/qe_lib/Kconfig @@ -2,11 +2,8 @@ # QE Communication options # -menu "QE Options" - depends on QUICC_ENGINE - config UCC_SLOW - bool "UCC Slow Protocols Support" + bool default n select UCC help @@ -14,10 +11,9 @@ config UCC_SLOW protocols: UART, BISYNC, QMC config UCC_FAST - bool "UCC Fast Protocols Support" + bool default n select UCC - select UCC_SLOW help This option provides qe_lib support to UCC fast protocols: HDLC, Ethernet, ATM, transparent @@ -26,5 +22,3 @@ config UCC bool default y if UCC_FAST || UCC_SLOW -endmenu - diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 43f6cc9d7ea..7f4c0754396 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -71,7 +71,7 @@ phys_addr_t get_qe_base(void) qe = of_find_node_by_type(NULL, "qe"); if (qe) { unsigned int size; - const void *prop = get_property(qe, "reg", &size); + const void *prop = of_get_property(qe, "reg", &size); qebase = of_translate_address(qe, prop); of_node_put(qe); }; @@ -158,7 +158,7 @@ unsigned int get_brg_clk(void) qe = of_find_node_by_type(NULL, "qe"); if (qe) { unsigned int size; - const u32 *prop = get_property(qe, "brg-frequency", &size); + const u32 *prop = of_get_property(qe, "brg-frequency", &size); brg_clk = *prop; of_node_put(qe); }; diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c index 0afe6bfe371..e32b45bf9ff 100644 --- a/arch/powerpc/sysdev/qe_lib/qe_io.c +++ b/arch/powerpc/sysdev/qe_lib/qe_io.c @@ -53,7 +53,7 @@ int par_io_init(struct device_node *np) return ret; par_io = ioremap(res.start, res.end - res.start + 1); - num_ports = get_property(np, "num-ports", NULL); + num_ports = of_get_property(np, "num-ports", NULL); if (num_ports) num_par_io_ports = *num_ports; @@ -161,7 +161,7 @@ int par_io_of_config(struct device_node *np) return -1; } - ph = get_property(np, "pio-handle", NULL); + ph = of_get_property(np, "pio-handle", NULL); if (ph == 0) { printk(KERN_ERR "pio-handle not available \n"); return -1; @@ -169,7 +169,7 @@ int par_io_of_config(struct device_node *np) pio = of_find_node_by_phandle(*ph); - pio_map = get_property(pio, "pio-map", &pio_map_len); + pio_map = of_get_property(pio, "pio-map", &pio_map_len); if (pio_map == NULL) { printk(KERN_ERR "pio-map is not set! \n"); return -1; diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c index a457ac1c663..66137bf2dfb 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c @@ -210,6 +210,9 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc uf_regs = uccf->uf_regs; uccf->p_ucce = (u32 *) & (uf_regs->ucce); uccf->p_uccm = (u32 *) & (uf_regs->uccm); +#ifdef CONFIG_UGETH_TX_ON_DEMAND + uccf->p_utodr = (u16 *) & (uf_regs->utodr); +#endif #ifdef STATISTICS uccf->tx_frames = 0; uccf->rx_frames = 0; diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c index 817df73ecf5..b930d686a4d 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c @@ -187,7 +187,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc uccs->us_pram = qe_muram_addr(uccs->us_pram_offset); /* Init Guemr register */ - if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->regs)))) { + if ((ret = ucc_init_guemr((struct ucc_common *) us_regs))) { printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__); ucc_slow_free(uccs); return ret; @@ -195,7 +195,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc /* Set UCC to slow type */ if ((ret = ucc_set_type(us_info->ucc_num, - (struct ucc_common *) (us_info->regs), + (struct ucc_common *) us_regs, UCC_SPEED_TYPE_SLOW))) { printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__); ucc_slow_free(uccs); diff --git a/arch/powerpc/sysdev/timer.c b/arch/powerpc/sysdev/timer.c new file mode 100644 index 00000000000..4a01748b421 --- /dev/null +++ b/arch/powerpc/sysdev/timer.c @@ -0,0 +1,71 @@ +/* + * Common code to keep time when machine suspends. + * + * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> + * + * GPLv2 + */ + +#include <linux/time.h> +#include <linux/sysdev.h> +#include <asm/rtc.h> + +static unsigned long suspend_rtc_time; + +/* + * Reset the time after a sleep. + */ +static int timer_resume(struct sys_device *dev) +{ + struct timeval tv; + struct timespec ts; + struct rtc_time cur_rtc_tm; + unsigned long cur_rtc_time, diff; + + /* get current RTC time and convert to seconds */ + get_rtc_time(&cur_rtc_tm); + rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time); + + diff = cur_rtc_time - suspend_rtc_time; + + /* adjust time of day by seconds that elapsed while + * we were suspended */ + do_gettimeofday(&tv); + ts.tv_sec = tv.tv_sec + diff; + ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC; + do_settimeofday(&ts); + + return 0; +} + +static int timer_suspend(struct sys_device *dev, pm_message_t state) +{ + struct rtc_time suspend_rtc_tm; + WARN_ON(!ppc_md.get_rtc_time); + + get_rtc_time(&suspend_rtc_tm); + rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time); + + return 0; +} + +static struct sysdev_class timer_sysclass = { + .resume = timer_resume, + .suspend = timer_suspend, + set_kset_name("timer"), +}; + +static struct sys_device device_timer = { + .id = 0, + .cls = &timer_sysclass, +}; + +static int time_init_device(void) +{ + int error = sysdev_class_register(&timer_sysclass); + if (!error) + error = sysdev_register(&device_timer); + return error; +} + +device_initcall(time_init_device); diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c index 97f37ef4bbb..337039ee51e 100644 --- a/arch/powerpc/sysdev/tsi108_dev.c +++ b/arch/powerpc/sysdev/tsi108_dev.c @@ -48,7 +48,7 @@ phys_addr_t get_csrbase(void) tsi = of_find_node_by_type(NULL, "tsi-bridge"); if (tsi) { unsigned int size; - const void *prop = get_property(tsi, "reg", &size); + const void *prop = of_get_property(tsi, "reg", &size); tsi108_csr_base = of_translate_address(tsi, prop); of_node_put(tsi); }; @@ -77,10 +77,10 @@ static int __init tsi108_eth_of_init(void) struct resource r[2]; struct device_node *phy; hw_info tsi_eth_data; - unsigned int *id; - unsigned int *phy_id; + const unsigned int *id; + const unsigned int *phy_id; const void *mac_addr; - phandle *ph; + const phandle *ph; memset(r, 0, sizeof(r)); memset(&tsi_eth_data, 0, sizeof(tsi_eth_data)); @@ -107,10 +107,10 @@ static int __init tsi108_eth_of_init(void) goto err; } - mac_addr = get_property(np, "address", NULL); + mac_addr = of_get_property(np, "address", NULL); memcpy(tsi_eth_data.mac_addr, mac_addr, 6); - ph = (phandle *) get_property(np, "phy-handle", NULL); + ph = of_get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); if (phy == NULL) { @@ -118,8 +118,8 @@ static int __init tsi108_eth_of_init(void) goto unreg; } - id = (u32 *) get_property(phy, "reg", NULL); - phy_id = (u32 *) get_property(phy, "phy-id", NULL); + id = of_get_property(phy, "reg", NULL); + phy_id = of_get_property(phy, "phy-id", NULL); ret = of_address_to_resource(phy, 0, &res); if (ret) { of_node_put(phy); diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index ae249c6bbbc..58b9e7f8abf 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c @@ -211,7 +211,7 @@ int __init tsi108_setup_pci(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - bus_range = get_property(dev, "bus-range", &len); + bus_range = of_get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c new file mode 100644 index 00000000000..968fb40af9d --- /dev/null +++ b/arch/powerpc/sysdev/uic.c @@ -0,0 +1,342 @@ +/* + * arch/powerpc/sysdev/uic.c + * + * IBM PowerPC 4xx Universal Interrupt Controller + * + * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation. + * + * 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. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/reboot.h> +#include <linux/slab.h> +#include <linux/stddef.h> +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/sysdev.h> +#include <linux/device.h> +#include <linux/bootmem.h> +#include <linux/spinlock.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/dcr.h> + +#define NR_UIC_INTS 32 + +#define UIC_SR 0x0 +#define UIC_ER 0x2 +#define UIC_CR 0x3 +#define UIC_PR 0x4 +#define UIC_TR 0x5 +#define UIC_MSR 0x6 +#define UIC_VR 0x7 +#define UIC_VCR 0x8 + +#define uic_irq_to_hw(virq) (irq_map[virq].hwirq) + +struct uic *primary_uic; + +struct uic { + int index; + int dcrbase; + + spinlock_t lock; + + /* The remapper for this UIC */ + struct irq_host *irqhost; + + /* For secondary UICs, the cascade interrupt's irqaction */ + struct irqaction cascade; + + /* The device node of the interrupt controller */ + struct device_node *of_node; +}; + +static void uic_unmask_irq(unsigned int virq) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + unsigned long flags; + u32 er; + + spin_lock_irqsave(&uic->lock, flags); + er = mfdcr(uic->dcrbase + UIC_ER); + er |= 1 << (31 - src); + mtdcr(uic->dcrbase + UIC_ER, er); + spin_unlock_irqrestore(&uic->lock, flags); +} + +static void uic_mask_irq(unsigned int virq) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + unsigned long flags; + u32 er; + + spin_lock_irqsave(&uic->lock, flags); + er = mfdcr(uic->dcrbase + UIC_ER); + er &= ~(1 << (31 - src)); + mtdcr(uic->dcrbase + UIC_ER, er); + spin_unlock_irqrestore(&uic->lock, flags); +} + +static void uic_ack_irq(unsigned int virq) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + unsigned long flags; + + spin_lock_irqsave(&uic->lock, flags); + mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src)); + spin_unlock_irqrestore(&uic->lock, flags); +} + +static int uic_set_irq_type(unsigned int virq, unsigned int flow_type) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + struct irq_desc *desc = get_irq_desc(virq); + unsigned long flags; + int trigger, polarity; + u32 tr, pr, mask; + + switch (flow_type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_NONE: + uic_mask_irq(virq); + return 0; + + case IRQ_TYPE_EDGE_RISING: + trigger = 1; polarity = 1; + break; + case IRQ_TYPE_EDGE_FALLING: + trigger = 1; polarity = 0; + break; + case IRQ_TYPE_LEVEL_HIGH: + trigger = 0; polarity = 1; + break; + case IRQ_TYPE_LEVEL_LOW: + trigger = 0; polarity = 0; + break; + default: + return -EINVAL; + } + + mask = ~(1 << (31 - src)); + + spin_lock_irqsave(&uic->lock, flags); + tr = mfdcr(uic->dcrbase + UIC_TR); + pr = mfdcr(uic->dcrbase + UIC_PR); + tr = (tr & mask) | (trigger << (31-src)); + pr = (pr & mask) | (polarity << (31-src)); + + mtdcr(uic->dcrbase + UIC_PR, pr); + mtdcr(uic->dcrbase + UIC_TR, tr); + + desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); + desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; + if (trigger) + desc->status |= IRQ_LEVEL; + + spin_unlock_irqrestore(&uic->lock, flags); + + return 0; +} + +static struct irq_chip uic_irq_chip = { + .typename = " UIC ", + .unmask = uic_unmask_irq, + .mask = uic_mask_irq, +/* .mask_ack = uic_mask_irq_and_ack, */ + .ack = uic_ack_irq, + .set_type = uic_set_irq_type, +}; + +static int uic_host_match(struct irq_host *h, struct device_node *node) +{ + struct uic *uic = h->host_data; + return uic->of_node == node; +} + +static int uic_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct uic *uic = h->host_data; + + set_irq_chip_data(virq, uic); + /* Despite the name, handle_level_irq() works for both level + * and edge irqs on UIC. FIXME: check this is correct */ + set_irq_chip_and_handler(virq, &uic_irq_chip, handle_level_irq); + + /* Set default irq type */ + set_irq_type(virq, IRQ_TYPE_NONE); + + return 0; +} + +static int uic_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_type) + +{ + /* UIC intspecs must have 2 cells */ + BUG_ON(intsize != 2); + *out_hwirq = intspec[0]; + *out_type = intspec[1]; + return 0; +} + +static struct irq_host_ops uic_host_ops = { + .match = uic_host_match, + .map = uic_host_map, + .xlate = uic_host_xlate, +}; + +irqreturn_t uic_cascade(int virq, void *data) +{ + struct uic *uic = data; + u32 msr; + int src; + int subvirq; + + msr = mfdcr(uic->dcrbase + UIC_MSR); + src = 32 - ffs(msr); + + subvirq = irq_linear_revmap(uic->irqhost, src); + generic_handle_irq(subvirq); + + return IRQ_HANDLED; +} + +static struct uic * __init uic_init_one(struct device_node *node) +{ + struct uic *uic; + const u32 *indexp, *dcrreg; + int len; + + BUG_ON(! device_is_compatible(node, "ibm,uic")); + + uic = alloc_bootmem(sizeof(*uic)); + if (! uic) + return NULL; /* FIXME: panic? */ + + memset(uic, 0, sizeof(*uic)); + spin_lock_init(&uic->lock); + uic->of_node = of_node_get(node); + indexp = of_get_property(node, "cell-index", &len); + if (!indexp || (len != sizeof(u32))) { + printk(KERN_ERR "uic: Device node %s has missing or invalid " + "cell-index property\n", node->full_name); + return NULL; + } + uic->index = *indexp; + + dcrreg = of_get_property(node, "dcr-reg", &len); + if (!dcrreg || (len != 2*sizeof(u32))) { + printk(KERN_ERR "uic: Device node %s has missing or invalid " + "dcr-reg property\n", node->full_name); + return NULL; + } + uic->dcrbase = *dcrreg; + + uic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, NR_UIC_INTS, + &uic_host_ops, -1); + if (! uic->irqhost) { + of_node_put(node); + return NULL; /* FIXME: panic? */ + } + + uic->irqhost->host_data = uic; + + /* Start with all interrupts disabled, level and non-critical */ + mtdcr(uic->dcrbase + UIC_ER, 0); + mtdcr(uic->dcrbase + UIC_CR, 0); + mtdcr(uic->dcrbase + UIC_TR, 0); + /* Clear any pending interrupts, in case the firmware left some */ + mtdcr(uic->dcrbase + UIC_SR, 0xffffffff); + + printk ("UIC%d (%d IRQ sources) at DCR 0x%x\n", uic->index, + NR_UIC_INTS, uic->dcrbase); + + return uic; +} + +void __init uic_init_tree(void) +{ + struct device_node *np; + struct uic *uic; + const u32 *interrupts; + + /* First locate and initialize the top-level UIC */ + + np = of_find_compatible_node(NULL, NULL, "ibm,uic"); + while (np) { + interrupts = of_get_property(np, "interrupts", NULL); + if (! interrupts) + break; + + np = of_find_compatible_node(np, NULL, "ibm,uic"); + } + + BUG_ON(!np); /* uic_init_tree() assumes there's a UIC as the + * top-level interrupt controller */ + primary_uic = uic_init_one(np); + if (! primary_uic) + panic("Unable to initialize primary UIC %s\n", np->full_name); + + irq_set_default_host(primary_uic->irqhost); + of_node_put(np); + + /* The scan again for cascaded UICs */ + np = of_find_compatible_node(NULL, NULL, "ibm,uic"); + while (np) { + interrupts = of_get_property(np, "interrupts", NULL); + if (interrupts) { + /* Secondary UIC */ + int cascade_virq; + int ret; + + uic = uic_init_one(np); + if (! uic) + panic("Unable to initialize a secondary UIC %s\n", + np->full_name); + + cascade_virq = irq_of_parse_and_map(np, 0); + + uic->cascade.handler = uic_cascade; + uic->cascade.name = "UIC cascade"; + uic->cascade.dev_id = uic; + + ret = setup_irq(cascade_virq, &uic->cascade); + if (ret) + printk(KERN_ERR "Failed to setup_irq(%d) for " + "UIC%d cascade\n", cascade_virq, + uic->index); + + /* FIXME: setup critical cascade?? */ + } + + np = of_find_compatible_node(np, NULL, "ibm,uic"); + } +} + +/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ +unsigned int uic_get_irq(void) +{ + u32 msr; + int src; + + BUG_ON(! primary_uic); + + msr = mfdcr(primary_uic->dcrbase + UIC_MSR); + src = 32 - ffs(msr); + + return irq_linear_revmap(primary_uic->irqhost, src); +} diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index bf299b66f3f..b481db1dacb 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -330,18 +330,17 @@ static void release_output_lock(void) static int xmon_core(struct pt_regs *regs, int fromipi) { int cmd = 0; - unsigned long msr; struct bpt *bp; long recurse_jmp[JMP_BUF_LEN]; unsigned long offset; + unsigned long flags; #ifdef CONFIG_SMP int cpu; int secondary; unsigned long timeout; #endif - msr = mfmsr(); - mtmsr(msr & ~MSR_EE); /* disable interrupts */ + local_irq_save(flags); bp = in_breakpoint_table(regs->nip, &offset); if (bp != NULL) { @@ -516,7 +515,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi) insert_cpu_bpts(); - mtmsr(msr); /* restore interrupt enable */ + local_irq_restore(flags); return cmd != 'X' && cmd != EOF; } @@ -1360,8 +1359,12 @@ static void print_bug_trap(struct pt_regs *regs) if (is_warning_bug(bug)) return; +#ifdef CONFIG_DEBUG_BUGVERBOSE printf("kernel BUG at %s:%u!\n", bug->file, bug->line); +#else + printf("kernel BUG at %p!\n", (void *)bug->bug_addr); +#endif } void excprint(struct pt_regs *fp) diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c index a6056c29cf0..48ce84f5be9 100644 --- a/arch/ppc/8260_io/enet.c +++ b/arch/ppc/8260_io/enet.c @@ -477,7 +477,6 @@ for (;;) { cep->stats.rx_dropped++; } else { - skb->dev = dev; skb_put(skb,pkt_len-4); /* Make room */ eth_copy_and_sum(skb, (unsigned char *)__va(bdp->cbd_bufaddr), diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c index 06b84c372e5..9db825fe37f 100644 --- a/arch/ppc/8260_io/fcc_enet.c +++ b/arch/ppc/8260_io/fcc_enet.c @@ -734,7 +734,6 @@ for (;;) { cep->stats.rx_dropped++; } else { - skb->dev = dev; skb_put(skb,pkt_len); /* Make room */ eth_copy_and_sum(skb, (unsigned char *)__va(bdp->cbd_bufaddr), diff --git a/arch/ppc/8xx_io/Kconfig b/arch/ppc/8xx_io/Kconfig index 57dacf97853..c623e44f01a 100644 --- a/arch/ppc/8xx_io/Kconfig +++ b/arch/ppc/8xx_io/Kconfig @@ -74,10 +74,6 @@ config ENET_BIG_BUFFERS Allocate large buffers for MPC8xx Ethernet. Increases throughput and decreases the likelihood of dropped packets, but costs memory. -config HTDMSOUND - bool "Embedded Planet HIOX Audio" - depends on SOUND=y - # This doesn't really belong here, but it is convenient to ask # 8xx specific questions. comment "Generic MPC8xx Options" diff --git a/arch/ppc/8xx_io/Makefile b/arch/ppc/8xx_io/Makefile index d8760181fe9..1051a06df7e 100644 --- a/arch/ppc/8xx_io/Makefile +++ b/arch/ppc/8xx_io/Makefile @@ -7,4 +7,3 @@ obj-y := commproc.o obj-$(CONFIG_FEC_ENET) += fec.o obj-$(CONFIG_SCC_ENET) += enet.o obj-$(CONFIG_UCODE_PATCH) += micropatch.o -obj-$(CONFIG_HTDMSOUND) += cs4218_tdm.o diff --git a/arch/ppc/8xx_io/cs4218.h b/arch/ppc/8xx_io/cs4218.h deleted file mode 100644 index e5f943045af..00000000000 --- a/arch/ppc/8xx_io/cs4218.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef _cs4218_h_ -/* - * Hacked version of linux/drivers/sound/dmasound/dmasound.h - * - * - * Minor numbers for the sound driver. - * - * Unfortunately Creative called the codec chip of SB as a DSP. For this - * reason the /dev/dsp is reserved for digitized audio use. There is a - * device for true DSP processors but it will be called something else. - * In v3.0 it's /dev/sndproc but this could be a temporary solution. - */ -#define _cs4218_h_ - -#include <linux/types.h> - -#define SND_NDEVS 256 /* Number of supported devices */ -#define SND_DEV_CTL 0 /* Control port /dev/mixer */ -#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM - synthesizer and MIDI output) */ -#define SND_DEV_MIDIN 2 /* Raw midi access */ -#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */ -#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */ -#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */ -#define SND_DEV_STATUS 6 /* /dev/sndstat */ -/* #7 not in use now. Was in 2.4. Free for use after v3.0. */ -#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */ -#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */ -#define SND_DEV_PSS SND_DEV_SNDPROC - -/* switch on various prinks */ -#define DEBUG_DMASOUND 1 - -#define MAX_AUDIO_DEV 5 -#define MAX_MIXER_DEV 4 -#define MAX_SYNTH_DEV 3 -#define MAX_MIDI_DEV 6 -#define MAX_TIMER_DEV 3 - -#define MAX_CATCH_RADIUS 10 - -#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff)) -#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff)) - -#define IOCTL_IN(arg, ret) \ - do { int error = get_user(ret, (int *)(arg)); \ - if (error) return error; \ - } while (0) -#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret) - -static inline int ioctl_return(int *addr, int value) -{ - return value < 0 ? value : put_user(value, addr); -} - -#define HAS_RECORD - - /* - * Initialization - */ - -/* description of the set-up applies to either hard or soft settings */ - -typedef struct { - int format; /* AFMT_* */ - int stereo; /* 0 = mono, 1 = stereo */ - int size; /* 8/16 bit*/ - int speed; /* speed */ -} SETTINGS; - - /* - * Machine definitions - */ - -typedef struct { - const char *name; - const char *name2; - void (*open)(void); - void (*release)(void); - void *(*dma_alloc)(unsigned int, gfp_t); - void (*dma_free)(void *, unsigned int); - int (*irqinit)(void); -#ifdef MODULE - void (*irqcleanup)(void); -#endif - void (*init)(void); - void (*silence)(void); - int (*setFormat)(int); - int (*setVolume)(int); - int (*setBass)(int); - int (*setTreble)(int); - int (*setGain)(int); - void (*play)(void); - void (*record)(void); /* optional */ - void (*mixer_init)(void); /* optional */ - int (*mixer_ioctl)(u_int, u_long); /* optional */ - int (*write_sq_setup)(void); /* optional */ - int (*read_sq_setup)(void); /* optional */ - int (*sq_open)(mode_t); /* optional */ - int (*state_info)(char *, size_t); /* optional */ - void (*abort_read)(void); /* optional */ - int min_dsp_speed; - int max_dsp_speed; - int version ; - int hardware_afmts ; /* OSS says we only return h'ware info */ - /* when queried via SNDCTL_DSP_GETFMTS */ - int capabilities ; /* low-level reply to SNDCTL_DSP_GETCAPS */ - SETTINGS default_hard ; /* open() or init() should set something valid */ - SETTINGS default_soft ; /* you can make it look like old OSS, if you want to */ -} MACHINE; - - /* - * Low level stuff - */ - -typedef struct { - ssize_t (*ct_ulaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_alaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); -} TRANS; - - - /* - * Sound queue stuff, the heart of the driver - */ - -struct sound_queue { - /* buffers allocated for this queue */ - int numBufs; /* real limits on what the user can have */ - int bufSize; /* in bytes */ - char **buffers; - - /* current parameters */ - int locked ; /* params cannot be modified when != 0 */ - int user_frags ; /* user requests this many */ - int user_frag_size ; /* of this size */ - int max_count; /* actual # fragments <= numBufs */ - int block_size; /* internal block size in bytes */ - int max_active; /* in-use fragments <= max_count */ - - /* it shouldn't be necessary to declare any of these volatile */ - int front, rear, count; - int rear_size; - /* - * The use of the playing field depends on the hardware - * - * Atari, PMac: The number of frames that are loaded/playing - * - * Amiga: Bit 0 is set: a frame is loaded - * Bit 1 is set: a frame is playing - */ - int active; - wait_queue_head_t action_queue, open_queue, sync_queue; - int open_mode; - int busy, syncing, xruns, died; -}; - -#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ) -#define WAKE_UP(queue) (wake_up_interruptible(&queue)) - -#endif /* _cs4218_h_ */ diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c deleted file mode 100644 index a956f28ab16..00000000000 --- a/arch/ppc/8xx_io/cs4218_tdm.c +++ /dev/null @@ -1,2833 +0,0 @@ - -/* This is a modified version of linux/drivers/sound/dmasound.c to - * support the CS4218 codec on the 8xx TDM port. Thanks to everyone - * that contributed to the dmasound software (which includes me :-). - * - * The CS4218 is configured in Mode 4, sub-mode 0. This provides - * left/right data only on the TDM port, as a 32-bit word, per frame - * pulse. The control of the CS4218 is provided by some other means, - * like the SPI port. - * Dan Malek (dmalek@jlc.net) - */ - -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/timer.h> -#include <linux/major.h> -#include <linux/fcntl.h> -#include <linux/errno.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/sound.h> -#include <linux/init.h> -#include <linux/delay.h> - -#include <asm/system.h> -#include <asm/irq.h> -#include <asm/pgtable.h> -#include <asm/uaccess.h> -#include <asm/io.h> - -/* Should probably do something different with this path name..... - * Actually, I should just stop using it... - */ -#include "cs4218.h" -#include <linux/soundcard.h> - -#include <asm/mpc8xx.h> -#include <asm/8xx_immap.h> -#include <asm/commproc.h> - -#define DMASND_CS4218 5 - -#define MAX_CATCH_RADIUS 10 -#define MIN_BUFFERS 4 -#define MIN_BUFSIZE 4 -#define MAX_BUFSIZE 128 - -#define HAS_8BIT_TABLES - -static int sq_unit = -1; -static int mixer_unit = -1; -static int state_unit = -1; -static int irq_installed = 0; -static char **sound_buffers = NULL; -static char **sound_read_buffers = NULL; - -static DEFINE_SPINLOCK(cs4218_lock); - -/* Local copies of things we put in the control register. Output - * volume, like most codecs is really attenuation. - */ -static int cs4218_rate_index; - -/* - * Stuff for outputting a beep. The values range from -327 to +327 - * so we can multiply by an amplitude in the range 0..100 to get a - * signed short value to put in the output buffer. - */ -static short beep_wform[256] = { - 0, 40, 79, 117, 153, 187, 218, 245, - 269, 288, 304, 316, 323, 327, 327, 324, - 318, 310, 299, 288, 275, 262, 249, 236, - 224, 213, 204, 196, 190, 186, 183, 182, - 182, 183, 186, 189, 192, 196, 200, 203, - 206, 208, 209, 209, 209, 207, 204, 201, - 197, 193, 188, 183, 179, 174, 170, 166, - 163, 161, 160, 159, 159, 160, 161, 162, - 164, 166, 168, 169, 171, 171, 171, 170, - 169, 167, 163, 159, 155, 150, 144, 139, - 133, 128, 122, 117, 113, 110, 107, 105, - 103, 103, 103, 103, 104, 104, 105, 105, - 105, 103, 101, 97, 92, 86, 78, 68, - 58, 45, 32, 18, 3, -11, -26, -41, - -55, -68, -79, -88, -95, -100, -102, -102, - -99, -93, -85, -75, -62, -48, -33, -16, - 0, 16, 33, 48, 62, 75, 85, 93, - 99, 102, 102, 100, 95, 88, 79, 68, - 55, 41, 26, 11, -3, -18, -32, -45, - -58, -68, -78, -86, -92, -97, -101, -103, - -105, -105, -105, -104, -104, -103, -103, -103, - -103, -105, -107, -110, -113, -117, -122, -128, - -133, -139, -144, -150, -155, -159, -163, -167, - -169, -170, -171, -171, -171, -169, -168, -166, - -164, -162, -161, -160, -159, -159, -160, -161, - -163, -166, -170, -174, -179, -183, -188, -193, - -197, -201, -204, -207, -209, -209, -209, -208, - -206, -203, -200, -196, -192, -189, -186, -183, - -182, -182, -183, -186, -190, -196, -204, -213, - -224, -236, -249, -262, -275, -288, -299, -310, - -318, -324, -327, -327, -323, -316, -304, -288, - -269, -245, -218, -187, -153, -117, -79, -40, -}; - -#define BEEP_SPEED 5 /* 22050 Hz sample rate */ -#define BEEP_BUFLEN 512 -#define BEEP_VOLUME 15 /* 0 - 100 */ - -static int beep_volume = BEEP_VOLUME; -static int beep_playing = 0; -static int beep_state = 0; -static short *beep_buf; -static void (*orig_mksound)(unsigned int, unsigned int); - -/* This is found someplace else......I guess in the keyboard driver - * we don't include. - */ -static void (*kd_mksound)(unsigned int, unsigned int); - -static int catchRadius = 0; -static int numBufs = 4, bufSize = 32; -static int numReadBufs = 4, readbufSize = 32; - - -/* TDM/Serial transmit and receive buffer descriptors. -*/ -static volatile cbd_t *rx_base, *rx_cur, *tx_base, *tx_cur; - -module_param(catchRadius, int, 0); -module_param(numBufs, int, 0); -module_param(bufSize, int, 0); -module_param(numreadBufs, int, 0); -module_param(readbufSize, int, 0); - -#define arraysize(x) (sizeof(x)/sizeof(*(x))) -#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff)) -#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff)) - -#define IOCTL_IN(arg, ret) \ - do { int error = get_user(ret, (int *)(arg)); \ - if (error) return error; \ - } while (0) -#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret) - -/* CS4218 serial port control in mode 4. -*/ -#define CS_INTMASK ((uint)0x40000000) -#define CS_DO1 ((uint)0x20000000) -#define CS_LATTEN ((uint)0x1f000000) -#define CS_RATTEN ((uint)0x00f80000) -#define CS_MUTE ((uint)0x00040000) -#define CS_ISL ((uint)0x00020000) -#define CS_ISR ((uint)0x00010000) -#define CS_LGAIN ((uint)0x0000f000) -#define CS_RGAIN ((uint)0x00000f00) - -#define CS_LATTEN_SET(X) (((X) & 0x1f) << 24) -#define CS_RATTEN_SET(X) (((X) & 0x1f) << 19) -#define CS_LGAIN_SET(X) (((X) & 0x0f) << 12) -#define CS_RGAIN_SET(X) (((X) & 0x0f) << 8) - -#define CS_LATTEN_GET(X) (((X) >> 24) & 0x1f) -#define CS_RATTEN_GET(X) (((X) >> 19) & 0x1f) -#define CS_LGAIN_GET(X) (((X) >> 12) & 0x0f) -#define CS_RGAIN_GET(X) (((X) >> 8) & 0x0f) - -/* The control register is effectively write only. We have to keep a copy - * of what we write. - */ -static uint cs4218_control; - -/* A place to store expanding information. -*/ -static int expand_bal; -static int expand_data; - -/* Since I can't make the microcode patch work for the SPI, I just - * clock the bits using software. - */ -static void sw_spi_init(void); -static void sw_spi_io(u_char *obuf, u_char *ibuf, uint bcnt); -static uint cs4218_ctl_write(uint ctlreg); - -/*** Some low level helpers **************************************************/ - -/* 16 bit mu-law */ - -static short ulaw2dma16[] = { - -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, - -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, - -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, - -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, - -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, - -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, - -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, - -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, - -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, - -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, - -876, -844, -812, -780, -748, -716, -684, -652, - -620, -588, -556, -524, -492, -460, -428, -396, - -372, -356, -340, -324, -308, -292, -276, -260, - -244, -228, -212, -196, -180, -164, -148, -132, - -120, -112, -104, -96, -88, -80, -72, -64, - -56, -48, -40, -32, -24, -16, -8, 0, - 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, - 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, - 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, - 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, - 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, - 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, - 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, - 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, - 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, - 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, - 876, 844, 812, 780, 748, 716, 684, 652, - 620, 588, 556, 524, 492, 460, 428, 396, - 372, 356, 340, 324, 308, 292, 276, 260, - 244, 228, 212, 196, 180, 164, 148, 132, - 120, 112, 104, 96, 88, 80, 72, 64, - 56, 48, 40, 32, 24, 16, 8, 0, -}; - -/* 16 bit A-law */ - -static short alaw2dma16[] = { - -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, - -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, - -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, - -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, - -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, - -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, - -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, - -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, - -344, -328, -376, -360, -280, -264, -312, -296, - -472, -456, -504, -488, -408, -392, -440, -424, - -88, -72, -120, -104, -24, -8, -56, -40, - -216, -200, -248, -232, -152, -136, -184, -168, - -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, - -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, - -688, -656, -752, -720, -560, -528, -624, -592, - -944, -912, -1008, -976, -816, -784, -880, -848, - 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, - 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, - 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, - 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, - 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, - 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, - 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, - 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, - 344, 328, 376, 360, 280, 264, 312, 296, - 472, 456, 504, 488, 408, 392, 440, 424, - 88, 72, 120, 104, 24, 8, 56, 40, - 216, 200, 248, 232, 152, 136, 184, 168, - 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, - 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, - 688, 656, 752, 720, 560, 528, 624, 592, - 944, 912, 1008, 976, 816, 784, 880, 848, -}; - - -/*** Translations ************************************************************/ - - -static ssize_t cs4218_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ctx_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ctx_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ctx_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ctx_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ctx_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_s16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t cs4218_ct_u16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); - - -/*** Low level stuff *********************************************************/ - -struct cs_sound_settings { - MACHINE mach; /* machine dependent things */ - SETTINGS hard; /* hardware settings */ - SETTINGS soft; /* software settings */ - SETTINGS dsp; /* /dev/dsp default settings */ - TRANS *trans_write; /* supported translations for playback */ - TRANS *trans_read; /* supported translations for record */ - int volume_left; /* volume (range is machine dependent) */ - int volume_right; - int bass; /* tone (range is machine dependent) */ - int treble; - int gain; - int minDev; /* minor device number currently open */ -}; - -static struct cs_sound_settings sound; - -static void *CS_Alloc(unsigned int size, gfp_t flags); -static void CS_Free(void *ptr, unsigned int size); -static int CS_IrqInit(void); -#ifdef MODULE -static void CS_IrqCleanup(void); -#endif /* MODULE */ -static void CS_Silence(void); -static void CS_Init(void); -static void CS_Play(void); -static void CS_Record(void); -static int CS_SetFormat(int format); -static int CS_SetVolume(int volume); -static void cs4218_tdm_tx_intr(void *devid); -static void cs4218_tdm_rx_intr(void *devid); -static void cs4218_intr(void *devid); -static int cs_get_volume(uint reg); -static int cs_volume_setter(int volume, int mute); -static int cs_get_gain(uint reg); -static int cs_set_gain(int gain); -static void cs_mksound(unsigned int hz, unsigned int ticks); -static void cs_nosound(unsigned long xx); - -/*** Mid level stuff *********************************************************/ - - -static void sound_silence(void); -static void sound_init(void); -static int sound_set_format(int format); -static int sound_set_speed(int speed); -static int sound_set_stereo(int stereo); -static int sound_set_volume(int volume); - -static ssize_t sound_copy_translate(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t sound_copy_translate_read(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); - - -/* - * /dev/mixer abstraction - */ - -struct sound_mixer { - int busy; - int modify_counter; -}; - -static struct sound_mixer mixer; - -static struct sound_queue sq; -static struct sound_queue read_sq; - -#define sq_block_address(i) (sq.buffers[i]) -#define SIGNAL_RECEIVED (signal_pending(current)) -#define NON_BLOCKING(open_mode) (open_mode & O_NONBLOCK) -#define ONE_SECOND HZ /* in jiffies (100ths of a second) */ -#define NO_TIME_LIMIT 0xffffffff - -/* - * /dev/sndstat - */ - -struct sound_state { - int busy; - char buf[512]; - int len, ptr; -}; - -static struct sound_state state; - -/*** Common stuff ********************************************************/ - -static long long sound_lseek(struct file *file, long long offset, int orig); - -/*** Config & Setup **********************************************************/ - -void dmasound_setup(char *str, int *ints); - -/*** Translations ************************************************************/ - - -/* ++TeSche: radically changed for new expanding purposes... - * - * These two routines now deal with copying/expanding/translating the samples - * from user space into our buffer at the right frequency. They take care about - * how much data there's actually to read, how much buffer space there is and - * to convert samples into the right frequency/encoding. They will only work on - * complete samples so it may happen they leave some bytes in the input stream - * if the user didn't write a multiple of the current sample size. They both - * return the number of bytes they've used from both streams so you may detect - * such a situation. Luckily all programs should be able to cope with that. - * - * I think I've optimized anything as far as one can do in plain C, all - * variables should fit in registers and the loops are really short. There's - * one loop for every possible situation. Writing a more generalized and thus - * parameterized loop would only produce slower code. Feel free to optimize - * this in assembler if you like. :) - * - * I think these routines belong here because they're not yet really hardware - * independent, especially the fact that the Falcon can play 16bit samples - * only in stereo is hardcoded in both of them! - * - * ++geert: split in even more functions (one per format) - */ - -static ssize_t cs4218_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - short *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16; - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - val = table[data]; - *p++ = val; - if (stereo) { - if (get_user(data, userPtr++)) - return -EFAULT; - val = table[data]; - } - *p++ = val; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t cs4218_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - val = data << 8; - *p++ = val; - if (stereo) { - if (get_user(data, userPtr++)) - return -EFAULT; - val = data << 8; - } - *p++ = val; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t cs4218_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - val = (data ^ 0x80) << 8; - *p++ = val; - if (stereo) { - if (get_user(data, userPtr++)) - return -EFAULT; - val = (data ^ 0x80) << 8; - } - *p++ = val; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -/* This is the default format of the codec. Signed, 16-bit stereo - * generated by an application shouldn't have to be copied at all. - * We should just get the phsical address of the buffers and update - * the TDM BDs directly. - */ -static ssize_t cs4218_ct_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - if (!stereo) { - short *up = (short *) userPtr; - while (count > 0) { - short data; - if (get_user(data, up++)) - return -EFAULT; - *fp++ = data; - *fp++ = data; - count--; - } - } else { - if (copy_from_user(fp, userPtr, count * 4)) - return -EFAULT; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - -static ssize_t cs4218_ct_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - short *up = (short *) userPtr; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - while (count > 0) { - int data; - if (get_user(data, up++)) - return -EFAULT; - data ^= mask; - *fp++ = data; - if (stereo) { - if (get_user(data, up++)) - return -EFAULT; - data ^= mask; - } - *fp++ = data; - count--; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - - -static ssize_t cs4218_ctx_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned short *table = (unsigned short *) - (sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16); - unsigned int data = expand_data; - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - int bal = expand_bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int utotal, ftotal; - int stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = table[c]; - if (stereo) { - if (get_user(c, userPtr++)) - return -EFAULT; - data = (data << 16) + table[c]; - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 2: utotal; -} - - -static ssize_t cs4218_ctx_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = expand_data; - int bal = expand_bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = c << 8; - if (stereo) { - if (get_user(c, userPtr++)) - return -EFAULT; - data = (data << 16) + (c << 8); - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 2: utotal; -} - - -static ssize_t cs4218_ctx_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = expand_data; - int bal = expand_bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = (c ^ 0x80) << 8; - if (stereo) { - if (get_user(c, userPtr++)) - return -EFAULT; - data = (data << 16) + ((c ^ 0x80) << 8); - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 2: utotal; -} - - -static ssize_t cs4218_ctx_s16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = expand_data; - unsigned short *up = (unsigned short *) userPtr; - int bal = expand_bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - unsigned short c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(data, up++)) - return -EFAULT; - if (stereo) { - if (get_user(c, up++)) - return -EFAULT; - data = (data << 16) + c; - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 4: utotal * 2; -} - - -static ssize_t cs4218_ctx_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); - unsigned int *p = (unsigned int *) &frame[*frameUsed]; - unsigned int data = expand_data; - unsigned short *up = (unsigned short *) userPtr; - int bal = expand_bal; - int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - int stereo = sound.soft.stereo; - int utotal, ftotal; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - unsigned short c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(data, up++)) - return -EFAULT; - data ^= mask; - if (stereo) { - if (get_user(c, up++)) - return -EFAULT; - data = (data << 16) + (c ^ mask); - } else - data = (data << 16) + data; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) * 4; - utotal -= userCount; - return stereo? utotal * 4: utotal * 2; -} - -static ssize_t cs4218_ct_s8_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - - val = *p++; - data = val >> 8; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - if (stereo) { - val = *p; - data = val >> 8; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - } - p++; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t cs4218_ct_u8_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - while (count > 0) { - u_char data; - - val = *p++; - data = (val >> 8) ^ 0x80; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - if (stereo) { - val = *p; - data = (val >> 8) ^ 0x80; - if (put_user(data, (u_char *)userPtr++)) - return -EFAULT; - } - p++; - count--; - } - *frameUsed += used * 4; - return stereo? used * 2: used; -} - - -static ssize_t cs4218_ct_s16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - if (!stereo) { - short *up = (short *) userPtr; - while (count > 0) { - short data; - data = *fp; - if (put_user(data, up++)) - return -EFAULT; - fp+=2; - count--; - } - } else { - if (copy_to_user((u_char *)userPtr, fp, count * 4)) - return -EFAULT; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - -static ssize_t cs4218_ct_u16_read(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - short *up = (short *) userPtr; - - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - while (count > 0) { - int data; - - data = *fp++; - data ^= mask; - if (put_user(data, up++)) - return -EFAULT; - if (stereo) { - data = *fp; - data ^= mask; - if (put_user(data, up++)) - return -EFAULT; - } - fp++; - count--; - } - *frameUsed += used * 4; - return stereo? used * 4: used * 2; -} - -static TRANS transCSNormal = { - cs4218_ct_law, cs4218_ct_law, cs4218_ct_s8, cs4218_ct_u8, - cs4218_ct_s16, cs4218_ct_u16, cs4218_ct_s16, cs4218_ct_u16 -}; - -static TRANS transCSExpand = { - cs4218_ctx_law, cs4218_ctx_law, cs4218_ctx_s8, cs4218_ctx_u8, - cs4218_ctx_s16, cs4218_ctx_u16, cs4218_ctx_s16, cs4218_ctx_u16 -}; - -static TRANS transCSNormalRead = { - NULL, NULL, cs4218_ct_s8_read, cs4218_ct_u8_read, - cs4218_ct_s16_read, cs4218_ct_u16_read, - cs4218_ct_s16_read, cs4218_ct_u16_read -}; - -/*** Low level stuff *********************************************************/ - -static void *CS_Alloc(unsigned int size, gfp_t flags) -{ - int order; - - size >>= 13; - for (order=0; order < 5; order++) { - if (size == 0) - break; - size >>= 1; - } - return (void *)__get_free_pages(flags, order); -} - -static void CS_Free(void *ptr, unsigned int size) -{ - int order; - - size >>= 13; - for (order=0; order < 5; order++) { - if (size == 0) - break; - size >>= 1; - } - free_pages((ulong)ptr, order); -} - -static int __init CS_IrqInit(void) -{ - cpm_install_handler(CPMVEC_SMC2, cs4218_intr, NULL); - return 1; -} - -#ifdef MODULE -static void CS_IrqCleanup(void) -{ - volatile smc_t *sp; - volatile cpm8xx_t *cp; - - /* First disable transmitter and receiver. - */ - sp = &cpmp->cp_smc[1]; - sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); - - /* And now shut down the SMC. - */ - cp = cpmp; /* Get pointer to Communication Processor */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, - CPM_CR_STOP_TX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - - /* Release the interrupt handler. - */ - cpm_free_handler(CPMVEC_SMC2); - - kfree(beep_buf); - kd_mksound = orig_mksound; -} -#endif /* MODULE */ - -static void CS_Silence(void) -{ - volatile smc_t *sp; - - /* Disable transmitter. - */ - sp = &cpmp->cp_smc[1]; - sp->smc_smcmr &= ~SMCMR_TEN; -} - -/* Frequencies depend upon external oscillator. There are two - * choices, 12.288 and 11.2896 MHz. The RPCG audio supports both through - * and external control register selection bit. - */ -static int cs4218_freqs[] = { - /* 12.288 11.2896 */ - 48000, 44100, - 32000, 29400, - 24000, 22050, - 19200, 17640, - 16000, 14700, - 12000, 11025, - 9600, 8820, - 8000, 7350 -}; - -static void CS_Init(void) -{ - int i, tolerance; - - switch (sound.soft.format) { - case AFMT_S16_LE: - case AFMT_U16_LE: - sound.hard.format = AFMT_S16_LE; - break; - default: - sound.hard.format = AFMT_S16_BE; - break; - } - sound.hard.stereo = 1; - sound.hard.size = 16; - - /* - * If we have a sample rate which is within catchRadius percent - * of the requested value, we don't have to expand the samples. - * Otherwise choose the next higher rate. - */ - i = (sizeof(cs4218_freqs) / sizeof(int)); - do { - tolerance = catchRadius * cs4218_freqs[--i] / 100; - } while (sound.soft.speed > cs4218_freqs[i] + tolerance && i > 0); - if (sound.soft.speed >= cs4218_freqs[i] - tolerance) - sound.trans_write = &transCSNormal; - else - sound.trans_write = &transCSExpand; - sound.trans_read = &transCSNormalRead; - sound.hard.speed = cs4218_freqs[i]; - cs4218_rate_index = i; - - /* The CS4218 has seven selectable clock dividers for the sample - * clock. The HIOX then provides one of two external rates. - * An even numbered frequency table index uses the high external - * clock rate. - */ - *(uint *)HIOX_CSR4_ADDR &= ~(HIOX_CSR4_AUDCLKHI | HIOX_CSR4_AUDCLKSEL); - if ((i & 1) == 0) - *(uint *)HIOX_CSR4_ADDR |= HIOX_CSR4_AUDCLKHI; - i >>= 1; - *(uint *)HIOX_CSR4_ADDR |= (i & HIOX_CSR4_AUDCLKSEL); - - expand_bal = -sound.soft.speed; -} - -static int CS_SetFormat(int format) -{ - int size; - - switch (format) { - case AFMT_QUERY: - return sound.soft.format; - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_U8: - case AFMT_S8: - size = 8; - break; - case AFMT_S16_BE: - case AFMT_U16_BE: - case AFMT_S16_LE: - case AFMT_U16_LE: - size = 16; - break; - default: /* :-) */ - printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n", - format); - size = 8; - format = AFMT_U8; - } - - sound.soft.format = format; - sound.soft.size = size; - if (sound.minDev == SND_DEV_DSP) { - sound.dsp.format = format; - sound.dsp.size = size; - } - - CS_Init(); - - return format; -} - -/* Volume is the amount of attenuation we tell the codec to impose - * on the outputs. There are 32 levels, with 0 the "loudest". - */ -#define CS_VOLUME_TO_MASK(x) (31 - ((((x) - 1) * 31) / 99)) -#define CS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 31)) - -static int cs_get_volume(uint reg) -{ - int volume; - - volume = CS_MASK_TO_VOLUME(CS_LATTEN_GET(reg)); - volume |= CS_MASK_TO_VOLUME(CS_RATTEN_GET(reg)) << 8; - return volume; -} - -static int cs_volume_setter(int volume, int mute) -{ - uint tempctl; - - if (mute && volume == 0) { - tempctl = cs4218_control | CS_MUTE; - } else { - tempctl = cs4218_control & ~CS_MUTE; - tempctl = tempctl & ~(CS_LATTEN | CS_RATTEN); - tempctl |= CS_LATTEN_SET(CS_VOLUME_TO_MASK(volume & 0xff)); - tempctl |= CS_RATTEN_SET(CS_VOLUME_TO_MASK((volume >> 8) & 0xff)); - volume = cs_get_volume(tempctl); - } - if (tempctl != cs4218_control) { - cs4218_ctl_write(tempctl); - } - return volume; -} - - -/* Gain has 16 steps from 0 to 15. These are in 1.5dB increments from - * 0 (no gain) to 22.5 dB. - */ -#define CS_RECLEVEL_TO_GAIN(v) \ - ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20) -#define CS_GAIN_TO_RECLEVEL(v) (((v) * 20 + 2) / 3) - -static int cs_get_gain(uint reg) -{ - int gain; - - gain = CS_GAIN_TO_RECLEVEL(CS_LGAIN_GET(reg)); - gain |= CS_GAIN_TO_RECLEVEL(CS_RGAIN_GET(reg)) << 8; - return gain; -} - -static int cs_set_gain(int gain) -{ - uint tempctl; - - tempctl = cs4218_control & ~(CS_LGAIN | CS_RGAIN); - tempctl |= CS_LGAIN_SET(CS_RECLEVEL_TO_GAIN(gain & 0xff)); - tempctl |= CS_RGAIN_SET(CS_RECLEVEL_TO_GAIN((gain >> 8) & 0xff)); - gain = cs_get_gain(tempctl); - - if (tempctl != cs4218_control) { - cs4218_ctl_write(tempctl); - } - return gain; -} - -static int CS_SetVolume(int volume) -{ - return cs_volume_setter(volume, CS_MUTE); -} - -static void CS_Play(void) -{ - int i, count; - unsigned long flags; - volatile cbd_t *bdp; - volatile cpm8xx_t *cp; - - /* Protect buffer */ - spin_lock_irqsave(&cs4218_lock, flags); -#if 0 - if (awacs_beep_state) { - /* sound takes precedence over beeps */ - out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (awacs_rate_index << 8)); - out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE); - out_le32(&awacs_txdma->cmdptr, virt_to_bus(&(awacs_tx_cmds[(sq.front+sq.active) % sq.max_count]))); - - beep_playing = 0; - awacs_beep_state = 0; - } -#endif - i = sq.front + sq.active; - if (i >= sq.max_count) - i -= sq.max_count; - while (sq.active < 2 && sq.active < sq.count) { - count = (sq.count == sq.active + 1)?sq.rear_size:sq.block_size; - if (count < sq.block_size && !sq.syncing) - /* last block not yet filled, and we're not syncing. */ - break; - - bdp = &tx_base[i]; - bdp->cbd_datlen = count; - - flush_dcache_range((ulong)sound_buffers[i], - (ulong)(sound_buffers[i] + count)); - - if (++i >= sq.max_count) - i = 0; - - if (sq.active == 0) { - /* The SMC does not load its fifo until the first - * TDM frame pulse, so the transmit data gets shifted - * by one word. To compensate for this, we incorrectly - * transmit the first buffer and shorten it by one - * word. Subsequent buffers are then aligned properly. - */ - bdp->cbd_datlen -= 2; - - /* Start up the SMC Transmitter. - */ - cp = cpmp; - cp->cp_smc[1].smc_smcmr |= SMCMR_TEN; - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, - CPM_CR_RESTART_TX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - } - - /* Buffer is ready now. - */ - bdp->cbd_sc |= BD_SC_READY; - - ++sq.active; - } - spin_unlock_irqrestore(&cs4218_lock, flags); -} - - -static void CS_Record(void) -{ - unsigned long flags; - volatile smc_t *sp; - - if (read_sq.active) - return; - - /* Protect buffer */ - spin_lock_irqsave(&cs4218_lock, flags); - - /* This is all we have to do......Just start it up. - */ - sp = &cpmp->cp_smc[1]; - sp->smc_smcmr |= SMCMR_REN; - - read_sq.active = 1; - - spin_unlock_irqrestore(&cs4218_lock, flags); -} - - -static void -cs4218_tdm_tx_intr(void *devid) -{ - int i = sq.front; - volatile cbd_t *bdp; - - while (sq.active > 0) { - bdp = &tx_base[i]; - if (bdp->cbd_sc & BD_SC_READY) - break; /* this frame is still going */ - --sq.count; - --sq.active; - if (++i >= sq.max_count) - i = 0; - } - if (i != sq.front) - WAKE_UP(sq.action_queue); - sq.front = i; - - CS_Play(); - - if (!sq.active) - WAKE_UP(sq.sync_queue); -} - - -static void -cs4218_tdm_rx_intr(void *devid) -{ - - /* We want to blow 'em off when shutting down. - */ - if (read_sq.active == 0) - return; - - /* Check multiple buffers in case we were held off from - * interrupt processing for a long time. Geeze, I really hope - * this doesn't happen. - */ - while ((rx_base[read_sq.rear].cbd_sc & BD_SC_EMPTY) == 0) { - - /* Invalidate the data cache range for this buffer. - */ - invalidate_dcache_range( - (uint)(sound_read_buffers[read_sq.rear]), - (uint)(sound_read_buffers[read_sq.rear] + read_sq.block_size)); - - /* Make buffer available again and move on. - */ - rx_base[read_sq.rear].cbd_sc |= BD_SC_EMPTY; - read_sq.rear++; - - /* Wrap the buffer ring. - */ - if (read_sq.rear >= read_sq.max_active) - read_sq.rear = 0; - - /* If we have caught up to the front buffer, bump it. - * This will cause weird (but not fatal) results if the - * read loop is currently using this buffer. The user is - * behind in this case anyway, so weird things are going - * to happen. - */ - if (read_sq.rear == read_sq.front) { - read_sq.front++; - if (read_sq.front >= read_sq.max_active) - read_sq.front = 0; - } - } - - WAKE_UP(read_sq.action_queue); -} - -static void cs_nosound(unsigned long xx) -{ - unsigned long flags; - - /* not sure if this is needed, since hardware command is #if 0'd */ - spin_lock_irqsave(&cs4218_lock, flags); - if (beep_playing) { -#if 0 - st_le16(&beep_dbdma_cmd->command, DBDMA_STOP); -#endif - beep_playing = 0; - } - spin_unlock_irqrestore(&cs4218_lock, flags); -} - -static DEFINE_TIMER(beep_timer, cs_nosound, 0, 0); - -static void cs_mksound(unsigned int hz, unsigned int ticks) -{ - unsigned long flags; - int beep_speed = BEEP_SPEED; - int srate = cs4218_freqs[beep_speed]; - int period, ncycles, nsamples; - int i, j, f; - short *p; - static int beep_hz_cache; - static int beep_nsamples_cache; - static int beep_volume_cache; - - if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) { -#if 1 - /* this is a hack for broken X server code */ - hz = 750; - ticks = 12; -#else - /* cancel beep currently playing */ - awacs_nosound(0); - return; -#endif - } - /* lock while modifying beep_timer */ - spin_lock_irqsave(&cs4218_lock, flags); - del_timer(&beep_timer); - if (ticks) { - beep_timer.expires = jiffies + ticks; - add_timer(&beep_timer); - } - if (beep_playing || sq.active || beep_buf == NULL) { - spin_unlock_irqrestore(&cs4218_lock, flags); - return; /* too hard, sorry :-( */ - } - beep_playing = 1; -#if 0 - st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS); -#endif - spin_unlock_irqrestore(&cs4218_lock, flags); - - if (hz == beep_hz_cache && beep_volume == beep_volume_cache) { - nsamples = beep_nsamples_cache; - } else { - period = srate * 256 / hz; /* fixed point */ - ncycles = BEEP_BUFLEN * 256 / period; - nsamples = (period * ncycles) >> 8; - f = ncycles * 65536 / nsamples; - j = 0; - p = beep_buf; - for (i = 0; i < nsamples; ++i, p += 2) { - p[0] = p[1] = beep_wform[j >> 8] * beep_volume; - j = (j + f) & 0xffff; - } - beep_hz_cache = hz; - beep_volume_cache = beep_volume; - beep_nsamples_cache = nsamples; - } - -#if 0 - st_le16(&beep_dbdma_cmd->req_count, nsamples*4); - st_le16(&beep_dbdma_cmd->xfer_status, 0); - st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd)); - st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf)); - awacs_beep_state = 1; - - spin_lock_irqsave(&cs4218_lock, flags); - if (beep_playing) { /* i.e. haven't been terminated already */ - out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (beep_speed << 8)); - out_le32(&awacs->byteswap, 0); - out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); - out_le32(&awacs_txdma->control, RUN | (RUN << 16)); - } - spin_unlock_irqrestore(&cs4218_lock, flags); -#endif -} - -static MACHINE mach_cs4218 = { - .owner = THIS_MODULE, - .name = "HIOX CS4218", - .name2 = "Built-in Sound", - .dma_alloc = CS_Alloc, - .dma_free = CS_Free, - .irqinit = CS_IrqInit, -#ifdef MODULE - .irqcleanup = CS_IrqCleanup, -#endif /* MODULE */ - .init = CS_Init, - .silence = CS_Silence, - .setFormat = CS_SetFormat, - .setVolume = CS_SetVolume, - .play = CS_Play -}; - - -/*** Mid level stuff *********************************************************/ - - -static void sound_silence(void) -{ - /* update hardware settings one more */ - (*sound.mach.init)(); - - (*sound.mach.silence)(); -} - - -static void sound_init(void) -{ - (*sound.mach.init)(); -} - - -static int sound_set_format(int format) -{ - return(*sound.mach.setFormat)(format); -} - - -static int sound_set_speed(int speed) -{ - if (speed < 0) - return(sound.soft.speed); - - sound.soft.speed = speed; - (*sound.mach.init)(); - if (sound.minDev == SND_DEV_DSP) - sound.dsp.speed = sound.soft.speed; - - return(sound.soft.speed); -} - - -static int sound_set_stereo(int stereo) -{ - if (stereo < 0) - return(sound.soft.stereo); - - stereo = !!stereo; /* should be 0 or 1 now */ - - sound.soft.stereo = stereo; - if (sound.minDev == SND_DEV_DSP) - sound.dsp.stereo = stereo; - (*sound.mach.init)(); - - return(stereo); -} - - -static int sound_set_volume(int volume) -{ - return(*sound.mach.setVolume)(volume); -} - -static ssize_t sound_copy_translate(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL; - - switch (sound.soft.format) { - case AFMT_MU_LAW: - ct_func = sound.trans_write->ct_ulaw; - break; - case AFMT_A_LAW: - ct_func = sound.trans_write->ct_alaw; - break; - case AFMT_S8: - ct_func = sound.trans_write->ct_s8; - break; - case AFMT_U8: - ct_func = sound.trans_write->ct_u8; - break; - case AFMT_S16_BE: - ct_func = sound.trans_write->ct_s16be; - break; - case AFMT_U16_BE: - ct_func = sound.trans_write->ct_u16be; - break; - case AFMT_S16_LE: - ct_func = sound.trans_write->ct_s16le; - break; - case AFMT_U16_LE: - ct_func = sound.trans_write->ct_u16le; - break; - } - if (ct_func) - return ct_func(userPtr, userCount, frame, frameUsed, frameLeft); - else - return 0; -} - -static ssize_t sound_copy_translate_read(const u_char *userPtr, - size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL; - - switch (sound.soft.format) { - case AFMT_MU_LAW: - ct_func = sound.trans_read->ct_ulaw; - break; - case AFMT_A_LAW: - ct_func = sound.trans_read->ct_alaw; - break; - case AFMT_S8: - ct_func = sound.trans_read->ct_s8; - break; - case AFMT_U8: - ct_func = sound.trans_read->ct_u8; - break; - case AFMT_S16_BE: - ct_func = sound.trans_read->ct_s16be; - break; - case AFMT_U16_BE: - ct_func = sound.trans_read->ct_u16be; - break; - case AFMT_S16_LE: - ct_func = sound.trans_read->ct_s16le; - break; - case AFMT_U16_LE: - ct_func = sound.trans_read->ct_u16le; - break; - } - if (ct_func) - return ct_func(userPtr, userCount, frame, frameUsed, frameLeft); - else - return 0; -} - - -/* - * /dev/mixer abstraction - */ - -static int mixer_open(struct inode *inode, struct file *file) -{ - mixer.busy = 1; - return nonseekable_open(inode, file); -} - - -static int mixer_release(struct inode *inode, struct file *file) -{ - mixer.busy = 0; - return 0; -} - - -static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg) -{ - int data; - uint tmpcs; - - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - mixer.modify_counter++; - if (cmd == OSS_GETVERSION) - return IOCTL_OUT(arg, SOUND_VERSION); - switch (cmd) { - case SOUND_MIXER_INFO: { - mixer_info info; - strlcpy(info.id, "CS4218_TDM", sizeof(info.id)); - strlcpy(info.name, "CS4218_TDM", sizeof(info.name)); - info.name[sizeof(info.name)-1] = 0; - info.modify_counter = mixer.modify_counter; - if (copy_to_user((int *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - case SOUND_MIXER_READ_DEVMASK: - data = SOUND_MASK_VOLUME | SOUND_MASK_LINE - | SOUND_MASK_MIC | SOUND_MASK_RECLEV - | SOUND_MASK_ALTPCM; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECMASK: - data = SOUND_MASK_LINE | SOUND_MASK_MIC; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECSRC: - if (cs4218_control & CS_DO1) - data = SOUND_MASK_LINE; - else - data = SOUND_MASK_MIC; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_RECSRC: - IOCTL_IN(arg, data); - data &= (SOUND_MASK_LINE | SOUND_MASK_MIC); - if (data & SOUND_MASK_LINE) - tmpcs = cs4218_control | - (CS_ISL | CS_ISR | CS_DO1); - if (data & SOUND_MASK_MIC) - tmpcs = cs4218_control & - ~(CS_ISL | CS_ISR | CS_DO1); - if (tmpcs != cs4218_control) - cs4218_ctl_write(tmpcs); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_STEREODEVS: - data = SOUND_MASK_VOLUME | SOUND_MASK_RECLEV; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_CAPS: - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_READ_VOLUME: - data = (cs4218_control & CS_MUTE)? 0: - cs_get_volume(cs4218_control); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_volume(data)); - case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ - IOCTL_IN(arg, data); - beep_volume = data & 0xff; - /* fall through */ - case SOUND_MIXER_READ_ALTPCM: - return IOCTL_OUT(arg, beep_volume); - case SOUND_MIXER_WRITE_RECLEV: - IOCTL_IN(arg, data); - data = cs_set_gain(data); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECLEV: - data = cs_get_gain(cs4218_control); - return IOCTL_OUT(arg, data); - } - - return -EINVAL; -} - - -static const struct file_operations mixer_fops = -{ - .owner = THIS_MODULE, - .llseek = sound_lseek, - .ioctl = mixer_ioctl, - .open = mixer_open, - .release = mixer_release, -}; - - -static void __init mixer_init(void) -{ - mixer_unit = register_sound_mixer(&mixer_fops, -1); - if (mixer_unit < 0) - return; - - mixer.busy = 0; - sound.treble = 0; - sound.bass = 0; - - /* Set Line input, no gain, no attenuation. - */ - cs4218_control = CS_ISL | CS_ISR | CS_DO1; - cs4218_control |= CS_LGAIN_SET(0) | CS_RGAIN_SET(0); - cs4218_control |= CS_LATTEN_SET(0) | CS_RATTEN_SET(0); - cs4218_ctl_write(cs4218_control); -} - - -/* - * Sound queue stuff, the heart of the driver - */ - - -static int sq_allocate_buffers(void) -{ - int i; - - if (sound_buffers) - return 0; - sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL); - if (!sound_buffers) - return -ENOMEM; - for (i = 0; i < numBufs; i++) { - sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL); - if (!sound_buffers[i]) { - while (i--) - sound.mach.dma_free (sound_buffers[i], bufSize << 10); - kfree (sound_buffers); - sound_buffers = 0; - return -ENOMEM; - } - } - return 0; -} - - -static void sq_release_buffers(void) -{ - int i; - - if (sound_buffers) { - for (i = 0; i < numBufs; i++) - sound.mach.dma_free (sound_buffers[i], bufSize << 10); - kfree (sound_buffers); - sound_buffers = 0; - } -} - - -static int sq_allocate_read_buffers(void) -{ - int i; - - if (sound_read_buffers) - return 0; - sound_read_buffers = kmalloc(numReadBufs * sizeof(char *), GFP_KERNEL); - if (!sound_read_buffers) - return -ENOMEM; - for (i = 0; i < numBufs; i++) { - sound_read_buffers[i] = sound.mach.dma_alloc (readbufSize<<10, - GFP_KERNEL); - if (!sound_read_buffers[i]) { - while (i--) - sound.mach.dma_free (sound_read_buffers[i], - readbufSize << 10); - kfree (sound_read_buffers); - sound_read_buffers = 0; - return -ENOMEM; - } - } - return 0; -} - -static void sq_release_read_buffers(void) -{ - int i; - - if (sound_read_buffers) { - cpmp->cp_smc[1].smc_smcmr &= ~SMCMR_REN; - for (i = 0; i < numReadBufs; i++) - sound.mach.dma_free (sound_read_buffers[i], - bufSize << 10); - kfree (sound_read_buffers); - sound_read_buffers = 0; - } -} - - -static void sq_setup(int numBufs, int bufSize, char **write_buffers) -{ - int i; - volatile cbd_t *bdp; - volatile cpm8xx_t *cp; - volatile smc_t *sp; - - /* Make sure the SMC transmit is shut down. - */ - cp = cpmp; - sp = &cpmp->cp_smc[1]; - sp->smc_smcmr &= ~SMCMR_TEN; - - sq.max_count = numBufs; - sq.max_active = numBufs; - sq.block_size = bufSize; - sq.buffers = write_buffers; - - sq.front = sq.count = 0; - sq.rear = -1; - sq.syncing = 0; - sq.active = 0; - - bdp = tx_base; - for (i=0; i<numBufs; i++) { - bdp->cbd_bufaddr = virt_to_bus(write_buffers[i]); - bdp++; - } - - /* This causes the SMC to sync up with the first buffer again. - */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_TX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); -} - -static void read_sq_setup(int numBufs, int bufSize, char **read_buffers) -{ - int i; - volatile cbd_t *bdp; - volatile cpm8xx_t *cp; - volatile smc_t *sp; - - /* Make sure the SMC receive is shut down. - */ - cp = cpmp; - sp = &cpmp->cp_smc[1]; - sp->smc_smcmr &= ~SMCMR_REN; - - read_sq.max_count = numBufs; - read_sq.max_active = numBufs; - read_sq.block_size = bufSize; - read_sq.buffers = read_buffers; - - read_sq.front = read_sq.count = 0; - read_sq.rear = 0; - read_sq.rear_size = 0; - read_sq.syncing = 0; - read_sq.active = 0; - - bdp = rx_base; - for (i=0; i<numReadBufs; i++) { - bdp->cbd_bufaddr = virt_to_bus(read_buffers[i]); - bdp->cbd_datlen = read_sq.block_size; - bdp++; - } - - /* This causes the SMC to sync up with the first buffer again. - */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_RX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); -} - - -static void sq_play(void) -{ - (*sound.mach.play)(); -} - - -/* ++TeSche: radically changed this one too */ - -static ssize_t sq_write(struct file *file, const char *src, size_t uLeft, - loff_t *ppos) -{ - ssize_t uWritten = 0; - u_char *dest; - ssize_t uUsed, bUsed, bLeft; - - /* ++TeSche: Is something like this necessary? - * Hey, that's an honest question! Or does any other part of the - * filesystem already checks this situation? I really don't know. - */ - if (uLeft == 0) - return 0; - - /* The interrupt doesn't start to play the last, incomplete frame. - * Thus we can append to it without disabling the interrupts! (Note - * also that sq.rear isn't affected by the interrupt.) - */ - - if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) { - dest = sq_block_address(sq.rear); - bUsed = sq.rear_size; - uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); - if (uUsed <= 0) - return uUsed; - src += uUsed; - uWritten += uUsed; - uLeft -= uUsed; - sq.rear_size = bUsed; - } - - do { - while (sq.count == sq.max_active) { - sq_play(); - if (NON_BLOCKING(sq.open_mode)) - return uWritten > 0 ? uWritten : -EAGAIN; - SLEEP(sq.action_queue); - if (SIGNAL_RECEIVED) - return uWritten > 0 ? uWritten : -EINTR; - } - - /* Here, we can avoid disabling the interrupt by first - * copying and translating the data, and then updating - * the sq variables. Until this is done, the interrupt - * won't see the new frame and we can work on it - * undisturbed. - */ - - dest = sq_block_address((sq.rear+1) % sq.max_count); - bUsed = 0; - bLeft = sq.block_size; - uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); - if (uUsed <= 0) - break; - src += uUsed; - uWritten += uUsed; - uLeft -= uUsed; - if (bUsed) { - sq.rear = (sq.rear+1) % sq.max_count; - sq.rear_size = bUsed; - sq.count++; - } - } while (bUsed); /* uUsed may have been 0 */ - - sq_play(); - - return uUsed < 0? uUsed: uWritten; -} - - -/***********/ - -/* Here is how the values are used for reading. - * The value 'active' simply indicates the DMA is running. This is - * done so the driver semantics are DMA starts when the first read is - * posted. The value 'front' indicates the buffer we should next - * send to the user. The value 'rear' indicates the buffer the DMA is - * currently filling. When 'front' == 'rear' the buffer "ring" is - * empty (we always have an empty available). The 'rear_size' is used - * to track partial offsets into the current buffer. Right now, I just keep - * The DMA running. If the reader can't keep up, the interrupt tosses - * the oldest buffer. We could also shut down the DMA in this case. - */ -static ssize_t sq_read(struct file *file, char *dst, size_t uLeft, - loff_t *ppos) -{ - - ssize_t uRead, bLeft, bUsed, uUsed; - - if (uLeft == 0) - return 0; - - if (!read_sq.active) - CS_Record(); /* Kick off the record process. */ - - uRead = 0; - - /* Move what the user requests, depending upon other options. - */ - while (uLeft > 0) { - - /* When front == rear, the DMA is not done yet. - */ - while (read_sq.front == read_sq.rear) { - if (NON_BLOCKING(read_sq.open_mode)) { - return uRead > 0 ? uRead : -EAGAIN; - } - SLEEP(read_sq.action_queue); - if (SIGNAL_RECEIVED) - return uRead > 0 ? uRead : -EINTR; - } - - /* The amount we move is either what is left in the - * current buffer or what the user wants. - */ - bLeft = read_sq.block_size - read_sq.rear_size; - bUsed = read_sq.rear_size; - uUsed = sound_copy_translate_read(dst, uLeft, - read_sq.buffers[read_sq.front], &bUsed, bLeft); - if (uUsed <= 0) - return uUsed; - dst += uUsed; - uRead += uUsed; - uLeft -= uUsed; - read_sq.rear_size += bUsed; - if (read_sq.rear_size >= read_sq.block_size) { - read_sq.rear_size = 0; - read_sq.front++; - if (read_sq.front >= read_sq.max_active) - read_sq.front = 0; - } - } - return uRead; -} - -static int sq_open(struct inode *inode, struct file *file) -{ - int rc = 0; - - if (file->f_mode & FMODE_WRITE) { - if (sq.busy) { - rc = -EBUSY; - if (NON_BLOCKING(file->f_flags)) - goto err_out; - rc = -EINTR; - while (sq.busy) { - SLEEP(sq.open_queue); - if (SIGNAL_RECEIVED) - goto err_out; - } - } - sq.busy = 1; /* Let's play spot-the-race-condition */ - - if (sq_allocate_buffers()) goto err_out_nobusy; - - sq_setup(numBufs, bufSize<<10,sound_buffers); - sq.open_mode = file->f_mode; - } - - - if (file->f_mode & FMODE_READ) { - if (read_sq.busy) { - rc = -EBUSY; - if (NON_BLOCKING(file->f_flags)) - goto err_out; - rc = -EINTR; - while (read_sq.busy) { - SLEEP(read_sq.open_queue); - if (SIGNAL_RECEIVED) - goto err_out; - } - rc = 0; - } - read_sq.busy = 1; - if (sq_allocate_read_buffers()) goto err_out_nobusy; - - read_sq_setup(numReadBufs,readbufSize<<10, sound_read_buffers); - read_sq.open_mode = file->f_mode; - } - - /* Start up the 4218 by: - * Reset. - * Enable, unreset. - */ - *((volatile uint *)HIOX_CSR4_ADDR) &= ~HIOX_CSR4_RSTAUDIO; - eieio(); - *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_ENAUDIO; - mdelay(50); - *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_RSTAUDIO; - - /* We need to send the current control word in case someone - * opened /dev/mixer and changed things while we were shut - * down. Chances are good the initialization that follows - * would have done this, but it is still possible it wouldn't. - */ - cs4218_ctl_write(cs4218_control); - - sound.minDev = iminor(inode) & 0x0f; - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_init(); - if ((iminor(inode) & 0x0f) == SND_DEV_AUDIO) { - sound_set_speed(8000); - sound_set_stereo(0); - sound_set_format(AFMT_MU_LAW); - } - - return nonseekable_open(inode, file); - -err_out_nobusy: - if (file->f_mode & FMODE_WRITE) { - sq.busy = 0; - WAKE_UP(sq.open_queue); - } - if (file->f_mode & FMODE_READ) { - read_sq.busy = 0; - WAKE_UP(read_sq.open_queue); - } -err_out: - return rc; -} - - -static void sq_reset(void) -{ - sound_silence(); - sq.active = 0; - sq.count = 0; - sq.front = (sq.rear+1) % sq.max_count; -#if 0 - init_tdm_buffers(); -#endif -} - - -static int sq_fsync(struct file *filp, struct dentry *dentry) -{ - int rc = 0; - - sq.syncing = 1; - sq_play(); /* there may be an incomplete frame waiting */ - - while (sq.active) { - SLEEP(sq.sync_queue); - if (SIGNAL_RECEIVED) { - /* While waiting for audio output to drain, an - * interrupt occurred. Stop audio output immediately - * and clear the queue. */ - sq_reset(); - rc = -EINTR; - break; - } - } - - sq.syncing = 0; - return rc; -} - -static int sq_release(struct inode *inode, struct file *file) -{ - int rc = 0; - - if (sq.busy) - rc = sq_fsync(file, file->f_path.dentry); - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_silence(); - - sq_release_read_buffers(); - sq_release_buffers(); - - if (file->f_mode & FMODE_READ) { - read_sq.busy = 0; - WAKE_UP(read_sq.open_queue); - } - - if (file->f_mode & FMODE_WRITE) { - sq.busy = 0; - WAKE_UP(sq.open_queue); - } - - /* Shut down the SMC. - */ - cpmp->cp_smc[1].smc_smcmr &= ~(SMCMR_TEN | SMCMR_REN); - - /* Shut down the codec. - */ - *((volatile uint *)HIOX_CSR4_ADDR) |= HIOX_CSR4_RSTAUDIO; - eieio(); - *((volatile uint *)HIOX_CSR4_ADDR) &= ~HIOX_CSR4_ENAUDIO; - - /* Wake up a process waiting for the queue being released. - * Note: There may be several processes waiting for a call - * to open() returning. */ - - return rc; -} - - -static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg) -{ - u_long fmt; - int data; -#if 0 - int size, nbufs; -#else - int size; -#endif - - switch (cmd) { - case SNDCTL_DSP_RESET: - sq_reset(); - return 0; - case SNDCTL_DSP_POST: - case SNDCTL_DSP_SYNC: - return sq_fsync(file, file->f_path.dentry); - - /* ++TeSche: before changing any of these it's - * probably wise to wait until sound playing has - * settled down. */ - case SNDCTL_DSP_SPEED: - sq_fsync(file, file->f_path.dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_speed(data)); - case SNDCTL_DSP_STEREO: - sq_fsync(file, file->f_path.dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_stereo(data)); - case SOUND_PCM_WRITE_CHANNELS: - sq_fsync(file, file->f_path.dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_stereo(data-1)+1); - case SNDCTL_DSP_SETFMT: - sq_fsync(file, file->f_path.dentry); - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, sound_set_format(data)); - case SNDCTL_DSP_GETFMTS: - fmt = 0; - if (sound.trans_write) { - if (sound.trans_write->ct_ulaw) - fmt |= AFMT_MU_LAW; - if (sound.trans_write->ct_alaw) - fmt |= AFMT_A_LAW; - if (sound.trans_write->ct_s8) - fmt |= AFMT_S8; - if (sound.trans_write->ct_u8) - fmt |= AFMT_U8; - if (sound.trans_write->ct_s16be) - fmt |= AFMT_S16_BE; - if (sound.trans_write->ct_u16be) - fmt |= AFMT_U16_BE; - if (sound.trans_write->ct_s16le) - fmt |= AFMT_S16_LE; - if (sound.trans_write->ct_u16le) - fmt |= AFMT_U16_LE; - } - return IOCTL_OUT(arg, fmt); - case SNDCTL_DSP_GETBLKSIZE: - size = sq.block_size - * sound.soft.size * (sound.soft.stereo + 1) - / (sound.hard.size * (sound.hard.stereo + 1)); - return IOCTL_OUT(arg, size); - case SNDCTL_DSP_SUBDIVIDE: - break; -#if 0 /* Sorry can't do this at the moment. The CPM allocated buffers - * long ago that can't be changed. - */ - case SNDCTL_DSP_SETFRAGMENT: - if (sq.count || sq.active || sq.syncing) - return -EINVAL; - IOCTL_IN(arg, size); - nbufs = size >> 16; - if (nbufs < 2 || nbufs > numBufs) - nbufs = numBufs; - size &= 0xffff; - if (size >= 8 && size <= 30) { - size = 1 << size; - size *= sound.hard.size * (sound.hard.stereo + 1); - size /= sound.soft.size * (sound.soft.stereo + 1); - if (size > (bufSize << 10)) - size = bufSize << 10; - } else - size = bufSize << 10; - sq_setup(numBufs, size, sound_buffers); - sq.max_active = nbufs; - return 0; -#endif - - default: - return mixer_ioctl(inode, file, cmd, arg); - } - return -EINVAL; -} - - - -static const struct file_operations sq_fops = -{ - .owner = THIS_MODULE, - .llseek = sound_lseek, - .read = sq_read, /* sq_read */ - .write = sq_write, - .ioctl = sq_ioctl, - .open = sq_open, - .release = sq_release, -}; - - -static void __init sq_init(void) -{ - sq_unit = register_sound_dsp(&sq_fops, -1); - if (sq_unit < 0) - return; - - init_waitqueue_head(&sq.action_queue); - init_waitqueue_head(&sq.open_queue); - init_waitqueue_head(&sq.sync_queue); - init_waitqueue_head(&read_sq.action_queue); - init_waitqueue_head(&read_sq.open_queue); - init_waitqueue_head(&read_sq.sync_queue); - - sq.busy = 0; - read_sq.busy = 0; - - /* whatever you like as startup mode for /dev/dsp, - * (/dev/audio hasn't got a startup mode). note that - * once changed a new open() will *not* restore these! - */ - sound.dsp.format = AFMT_S16_BE; - sound.dsp.stereo = 1; - sound.dsp.size = 16; - - /* set minimum rate possible without expanding */ - sound.dsp.speed = 8000; - - /* before the first open to /dev/dsp this wouldn't be set */ - sound.soft = sound.dsp; - sound.hard = sound.dsp; - - sound_silence(); -} - -/* - * /dev/sndstat - */ - - -/* state.buf should not overflow! */ - -static int state_open(struct inode *inode, struct file *file) -{ - char *buffer = state.buf, *mach = "", cs4218_buf[50]; - int len = 0; - - if (state.busy) - return -EBUSY; - - state.ptr = 0; - state.busy = 1; - - sprintf(cs4218_buf, "Crystal CS4218 on TDM, "); - mach = cs4218_buf; - - len += sprintf(buffer+len, "%sDMA sound driver:\n", mach); - - len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format); - switch (sound.soft.format) { - case AFMT_MU_LAW: - len += sprintf(buffer+len, " (mu-law)"); - break; - case AFMT_A_LAW: - len += sprintf(buffer+len, " (A-law)"); - break; - case AFMT_U8: - len += sprintf(buffer+len, " (unsigned 8 bit)"); - break; - case AFMT_S8: - len += sprintf(buffer+len, " (signed 8 bit)"); - break; - case AFMT_S16_BE: - len += sprintf(buffer+len, " (signed 16 bit big)"); - break; - case AFMT_U16_BE: - len += sprintf(buffer+len, " (unsigned 16 bit big)"); - break; - case AFMT_S16_LE: - len += sprintf(buffer+len, " (signed 16 bit little)"); - break; - case AFMT_U16_LE: - len += sprintf(buffer+len, " (unsigned 16 bit little)"); - break; - } - len += sprintf(buffer+len, "\n"); - len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n", - sound.soft.speed, sound.hard.speed); - len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n", - sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono"); - len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d" - " sq.max_active = %d\n", - sq.block_size, sq.max_count, sq.max_active); - len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count, - sq.rear_size); - len += sprintf(buffer+len, "\tsq.active = %d sq.syncing = %d\n", - sq.active, sq.syncing); - state.len = len; - return nonseekable_open(inode, file); -} - - -static int state_release(struct inode *inode, struct file *file) -{ - state.busy = 0; - return 0; -} - - -static ssize_t state_read(struct file *file, char *buf, size_t count, - loff_t *ppos) -{ - int n = state.len - state.ptr; - if (n > count) - n = count; - if (n <= 0) - return 0; - if (copy_to_user(buf, &state.buf[state.ptr], n)) - return -EFAULT; - state.ptr += n; - return n; -} - - -static const struct file_operations state_fops = -{ - .owner = THIS_MODULE, - .llseek = sound_lseek, - .read = state_read, - .open = state_open, - .release = state_release, -}; - - -static void __init state_init(void) -{ - state_unit = register_sound_special(&state_fops, SND_DEV_STATUS); - if (state_unit < 0) - return; - state.busy = 0; -} - - -/*** Common stuff ********************************************************/ - -static long long sound_lseek(struct file *file, long long offset, int orig) -{ - return -ESPIPE; -} - - -/*** Config & Setup **********************************************************/ - - -int __init tdm8xx_sound_init(void) -{ - int i, has_sound; - uint dp_offset; - volatile uint *sirp; - volatile cbd_t *bdp; - volatile cpm8xx_t *cp; - volatile smc_t *sp; - volatile smc_uart_t *up; - volatile immap_t *immap; - - has_sound = 0; - - /* Program the SI/TSA to use TDMa, connected to SMC2, for 4 bytes. - */ - cp = cpmp; /* Get pointer to Communication Processor */ - immap = (immap_t *)IMAP_ADDR; /* and to internal registers */ - - /* Set all TDMa control bits to zero. This enables most features - * we want. - */ - cp->cp_simode &= ~0x00000fff; - - /* Enable common receive/transmit clock pins, use IDL format. - * Sync on falling edge, transmit rising clock, receive falling - * clock, delay 1 bit on both Tx and Rx. Common Tx/Rx clocks and - * sync. - * Connect SMC2 to TSA. - */ - cp->cp_simode |= 0x80000141; - - /* Configure port A pins for TDMa operation. - * The RPX-Lite (MPC850/823) loses SMC2 when TDM is used. - */ - immap->im_ioport.iop_papar |= 0x01c0; /* Enable TDMa functions */ - immap->im_ioport.iop_padir |= 0x00c0; /* Enable TDMa Tx/Rx */ - immap->im_ioport.iop_padir &= ~0x0100; /* Enable L1RCLKa */ - - immap->im_ioport.iop_pcpar |= 0x0800; /* Enable L1RSYNCa */ - immap->im_ioport.iop_pcdir &= ~0x0800; - - /* Initialize the SI TDM routing table. We use TDMa only. - * The receive table and transmit table each have only one - * entry, to capture/send four bytes after each frame pulse. - * The 16-bit ram entry is 0000 0001 1000 1111. (SMC2) - */ - cp->cp_sigmr = 0; - sirp = (uint *)cp->cp_siram; - - *sirp = 0x018f0000; /* Receive entry */ - sirp += 64; - *sirp = 0x018f0000; /* Tramsmit entry */ - - /* Enable single TDMa routing. - */ - cp->cp_sigmr = 0x04; - - /* Initialize the SMC for transparent operation. - */ - sp = &cpmp->cp_smc[1]; - up = (smc_uart_t *)&cp->cp_dparam[PROFF_SMC2]; - - /* We need to allocate a transmit and receive buffer - * descriptors from dual port ram. - */ - dp_addr = cpm_dpalloc(sizeof(cbd_t) * numReadBufs, 8); - - /* Set the physical address of the host memory - * buffers in the buffer descriptors, and the - * virtual address for us to work with. - */ - bdp = (cbd_t *)&cp->cp_dpmem[dp_addr]; - up->smc_rbase = dp_offset; - rx_cur = rx_base = (cbd_t *)bdp; - - for (i=0; i<(numReadBufs-1); i++) { - bdp->cbd_bufaddr = 0; - bdp->cbd_datlen = 0; - bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; - bdp++; - } - bdp->cbd_bufaddr = 0; - bdp->cbd_datlen = 0; - bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; - - /* Now, do the same for the transmit buffers. - */ - dp_offset = cpm_dpalloc(sizeof(cbd_t) * numBufs, 8); - - bdp = (cbd_t *)&cp->cp_dpmem[dp_addr]; - up->smc_tbase = dp_offset; - tx_cur = tx_base = (cbd_t *)bdp; - - for (i=0; i<(numBufs-1); i++) { - bdp->cbd_bufaddr = 0; - bdp->cbd_datlen = 0; - bdp->cbd_sc = BD_SC_INTRPT; - bdp++; - } - bdp->cbd_bufaddr = 0; - bdp->cbd_datlen = 0; - bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT); - - /* Set transparent SMC mode. - * A few things are specific to our application. The codec interface - * is MSB first, hence the REVD selection. The CD/CTS pulse are - * used by the TSA to indicate the frame start to the SMC. - */ - up->smc_rfcr = SCC_EB; - up->smc_tfcr = SCC_EB; - up->smc_mrblr = readbufSize * 1024; - - /* Set 16-bit reversed data, transparent mode. - */ - sp->smc_smcmr = smcr_mk_clen(15) | - SMCMR_SM_TRANS | SMCMR_REVD | SMCMR_BS; - - /* Enable and clear events. - * Because of FIFO delays, all we need is the receive interrupt - * and we can process both the current receive and current - * transmit interrupt within a few microseconds of the transmit. - */ - sp->smc_smce = 0xff; - sp->smc_smcm = SMCM_TXE | SMCM_TX | SMCM_RX; - - /* Send the CPM an initialize command. - */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, - CPM_CR_INIT_TRX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - - sound.mach = mach_cs4218; - has_sound = 1; - - /* Initialize beep stuff */ - orig_mksound = kd_mksound; - kd_mksound = cs_mksound; - beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); - if (beep_buf == NULL) - printk(KERN_WARNING "dmasound: no memory for " - "beep buffer\n"); - - if (!has_sound) - return -ENODEV; - - /* Initialize the software SPI. - */ - sw_spi_init(); - - /* Set up sound queue, /dev/audio and /dev/dsp. */ - - /* Set default settings. */ - sq_init(); - - /* Set up /dev/sndstat. */ - state_init(); - - /* Set up /dev/mixer. */ - mixer_init(); - - if (!sound.mach.irqinit()) { - printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n"); - return -ENODEV; - } -#ifdef MODULE - irq_installed = 1; -#endif - - printk(KERN_INFO "DMA sound driver installed, using %d buffers of %dk.\n", - numBufs, bufSize); - - return 0; -} - -/* Due to FIFOs and bit delays, the transmit interrupt occurs a few - * microseconds ahead of the receive interrupt. - * When we get an interrupt, we service the transmit first, then - * check for a receive to prevent the overhead of returning through - * the interrupt handler only to get back here right away during - * full duplex operation. - */ -static void -cs4218_intr(void *dev_id) -{ - volatile smc_t *sp; - volatile cpm8xx_t *cp; - - sp = &cpmp->cp_smc[1]; - - if (sp->smc_smce & SCCM_TX) { - sp->smc_smce = SCCM_TX; - cs4218_tdm_tx_intr((void *)sp); - } - - if (sp->smc_smce & SCCM_RX) { - sp->smc_smce = SCCM_RX; - cs4218_tdm_rx_intr((void *)sp); - } - - if (sp->smc_smce & SCCM_TXE) { - /* Transmit underrun. This happens with the application - * didn't keep up sending buffers. We tell the SMC to - * restart, which will cause it to poll the current (next) - * BD. If the user supplied data since this occurred, - * we just start running again. If they didn't, the SMC - * will poll the descriptor until data is placed there. - */ - sp->smc_smce = SCCM_TXE; - cp = cpmp; /* Get pointer to Communication Processor */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, - CPM_CR_RESTART_TX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - } -} - - -#define MAXARGS 8 /* Should be sufficient for now */ - -void __init dmasound_setup(char *str, int *ints) -{ - /* check the bootstrap parameter for "dmasound=" */ - - switch (ints[0]) { - case 3: - if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) - printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius); - else - catchRadius = ints[3]; - /* fall through */ - case 2: - if (ints[1] < MIN_BUFFERS) - printk("dmasound_setup: invalid number of buffers, using default = %d\n", numBufs); - else - numBufs = ints[1]; - if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE) - printk("dmasound_setup: invalid buffer size, using default = %d\n", bufSize); - else - bufSize = ints[2]; - break; - case 0: - break; - default: - printk("dmasound_setup: invalid number of arguments\n"); - } -} - -/* Software SPI functions. - * These are on Port B. - */ -#define PB_SPICLK ((uint)0x00000002) -#define PB_SPIMOSI ((uint)0x00000004) -#define PB_SPIMISO ((uint)0x00000008) - -static -void sw_spi_init(void) -{ - volatile cpm8xx_t *cp; - volatile uint *hcsr4; - - hcsr4 = (volatile uint *)HIOX_CSR4_ADDR; - cp = cpmp; /* Get pointer to Communication Processor */ - - *hcsr4 &= ~HIOX_CSR4_AUDSPISEL; /* Disable SPI select */ - - /* Make these Port B signals general purpose I/O. - * First, make sure the clock is low. - */ - cp->cp_pbdat &= ~PB_SPICLK; - cp->cp_pbpar &= ~(PB_SPICLK | PB_SPIMOSI | PB_SPIMISO); - - /* Clock and Master Output are outputs. - */ - cp->cp_pbdir |= (PB_SPICLK | PB_SPIMOSI); - - /* Master Input. - */ - cp->cp_pbdir &= ~PB_SPIMISO; - -} - -/* Write the CS4218 control word out the SPI port. While the - * the control word is going out, the status word is arriving. - */ -static -uint cs4218_ctl_write(uint ctlreg) -{ - uint status; - - sw_spi_io((u_char *)&ctlreg, (u_char *)&status, 4); - - /* Shadow the control register.....I guess we could do - * the same for the status, but for now we just return it - * and let the caller decide. - */ - cs4218_control = ctlreg; - return status; -} - -static -void sw_spi_io(u_char *obuf, u_char *ibuf, uint bcnt) -{ - int bits, i; - u_char outbyte, inbyte; - volatile cpm8xx_t *cp; - volatile uint *hcsr4; - - hcsr4 = (volatile uint *)HIOX_CSR4_ADDR; - cp = cpmp; /* Get pointer to Communication Processor */ - - /* The timing on the bus is pretty slow. Code inefficiency - * and eieio() is our friend here :-). - */ - cp->cp_pbdat &= ~PB_SPICLK; - *hcsr4 |= HIOX_CSR4_AUDSPISEL; /* Enable SPI select */ - eieio(); - - /* Clock in/out the bytes. Data is valid on the falling edge - * of the clock. Data is MSB first. - */ - for (i=0; i<bcnt; i++) { - outbyte = *obuf++; - inbyte = 0; - for (bits=0; bits<8; bits++) { - eieio(); - cp->cp_pbdat |= PB_SPICLK; - eieio(); - if (outbyte & 0x80) - cp->cp_pbdat |= PB_SPIMOSI; - else - cp->cp_pbdat &= ~PB_SPIMOSI; - eieio(); - cp->cp_pbdat &= ~PB_SPICLK; - eieio(); - outbyte <<= 1; - inbyte <<= 1; - if (cp->cp_pbdat & PB_SPIMISO) - inbyte |= 1; - } - *ibuf++ = inbyte; - } - - *hcsr4 &= ~HIOX_CSR4_AUDSPISEL; /* Disable SPI select */ - eieio(); -} - -void cleanup_module(void) -{ - if (irq_installed) { - sound_silence(); -#ifdef MODULE - sound.mach.irqcleanup(); -#endif - } - - sq_release_read_buffers(); - sq_release_buffers(); - - if (mixer_unit >= 0) - unregister_sound_mixer(mixer_unit); - if (state_unit >= 0) - unregister_sound_special(state_unit); - if (sq_unit >= 0) - unregister_sound_dsp(sq_unit); -} - -module_init(tdm8xx_sound_init); -module_exit(cleanup_module); - diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c index b23c45bc151..bfa3f52996d 100644 --- a/arch/ppc/8xx_io/enet.c +++ b/arch/ppc/8xx_io/enet.c @@ -506,7 +506,6 @@ for (;;) { cep->stats.rx_dropped++; } else { - skb->dev = dev; skb_put(skb,pkt_len-4); /* Make room */ eth_copy_and_sum(skb, cep->rx_vaddr[bdp - cep->rx_bd_base], diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c index e6c28fb423b..57a9a61e54b 100644 --- a/arch/ppc/8xx_io/fec.c +++ b/arch/ppc/8xx_io/fec.c @@ -724,7 +724,6 @@ while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) { printk("%s: Memory squeeze, dropping packet.\n", dev->name); fep->stats.rx_dropped++; } else { - skb->dev = dev; skb_put(skb,pkt_len-4); /* Make room */ eth_copy_and_sum(skb, data, pkt_len-4, 0); skb->protocol=eth_type_trans(skb,dev); diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c index 8e1fccd96fc..9589969cec7 100644 --- a/arch/ppc/boot/common/misc-common.c +++ b/arch/ppc/boot/common/misc-common.c @@ -57,7 +57,8 @@ unsigned char *ISA_io = NULL; #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ - || defined(CONFIG_SERIAL_MPSC_CONSOLE) + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \ + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE) extern unsigned long com_port; extern int serial_tstc(unsigned long com_port); @@ -80,7 +81,8 @@ int tstc(void) { #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ - || defined(CONFIG_SERIAL_MPSC_CONSOLE) + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \ + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE) if(keyb_present) return (CRT_tstc() || serial_tstc(com_port)); else @@ -95,7 +97,8 @@ int getc(void) while (1) { #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ - || defined(CONFIG_SERIAL_MPSC_CONSOLE) + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \ + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE) if (serial_tstc(com_port)) return (serial_getc(com_port)); #endif /* serial console */ @@ -112,7 +115,8 @@ putc(const char c) #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ - || defined(CONFIG_SERIAL_MPSC_CONSOLE) + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \ + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE) serial_putc(com_port, c); if ( c == '\n' ) serial_putc(com_port, '\r'); @@ -161,7 +165,8 @@ void puts(const char *s) while ( ( c = *s++ ) != '\0' ) { #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \ || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \ - || defined(CONFIG_SERIAL_MPSC_CONSOLE) + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \ + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE) serial_putc(com_port, c); if ( c == '\n' ) serial_putc(com_port, '\r'); #endif /* serial console */ diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index bcfb6cde70c..5b877792d14 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -201,6 +201,7 @@ boot-$(CONFIG_8260) += m8260_tty.o endif boot-$(CONFIG_SERIAL_MPC52xx_CONSOLE) += mpc52xx_tty.o boot-$(CONFIG_SERIAL_MPSC_CONSOLE) += mv64x60_tty.o +boot-$(CONFIG_SERIAL_UARTLITE_CONSOLE) += uartlite_tty.o LIBS := $(common)/lib.a $(bootlib)/lib.a ifeq ($(CONFIG_PPC_PREP),y) diff --git a/arch/ppc/boot/simple/uartlite_tty.c b/arch/ppc/boot/simple/uartlite_tty.c new file mode 100644 index 00000000000..0eae1eab38d --- /dev/null +++ b/arch/ppc/boot/simple/uartlite_tty.c @@ -0,0 +1,37 @@ +/* + * Xilinx UARTLITE bootloader driver + * + * Copyright (c) 2007 Secret Lab Technologies Ltd. + * + * 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. + */ + +#include <linux/types.h> +#include <asm/serial.h> +#include <asm/io.h> +#include <platforms/4xx/xparameters/xparameters.h> + +#define UARTLITE_BASEADDR ((void*)(XPAR_UARTLITE_0_BASEADDR)) + +void +serial_putc(unsigned long com_port, unsigned char c) +{ + while ((in_be32(UARTLITE_BASEADDR + 0x8) & 0x08) != 0); /* spin */ + out_be32(UARTLITE_BASEADDR + 0x4, c); +} + +unsigned char +serial_getc(unsigned long com_port) +{ + while ((in_be32(UARTLITE_BASEADDR + 0x8) & 0x01) == 0); /* spin */ + return in_be32(UARTLITE_BASEADDR); +} + +int +serial_tstc(unsigned long com_port) +{ + return ((in_be32(UARTLITE_BASEADDR + 0x8) & 0x01) != 0); +} diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c index 1f91eca2f3d..c5850a27265 100644 --- a/arch/ppc/kernel/asm-offsets.c +++ b/arch/ppc/kernel/asm-offsets.c @@ -40,7 +40,6 @@ main(void) DEFINE(PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(KSP, offsetof(struct thread_struct, ksp)); DEFINE(PGDIR, offsetof(struct thread_struct, pgdir)); - DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index a9d455369dc..ab64256110b 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -191,7 +191,6 @@ stack_ovf: 0: _GLOBAL(DoSyscall) - stw r0,THREAD+LAST_SYSCALL(r2) stw r3,ORIG_GPR3(r1) li r12,0 stw r12,RESULT(r1) diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 1318b6f4c3d..4ad499605d0 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -93,8 +93,6 @@ EXPORT_SYMBOL(strncpy); EXPORT_SYMBOL(strcat); EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strcasecmp); -EXPORT_SYMBOL(strncasecmp); EXPORT_SYMBOL(__div64_32); EXPORT_SYMBOL(csum_partial); diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile index 50358e4ea15..422bef9bae7 100644 --- a/arch/ppc/lib/Makefile +++ b/arch/ppc/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for ppc-specific library files.. # -obj-y := checksum.o string.o strcase.o div64.o +obj-y := checksum.o string.o div64.o obj-$(CONFIG_8xx) += rheap.o obj-$(CONFIG_CPM2) += rheap.o diff --git a/arch/ppc/lib/strcase.c b/arch/ppc/lib/strcase.c deleted file mode 100644 index 3b0094cc2b5..00000000000 --- a/arch/ppc/lib/strcase.c +++ /dev/null @@ -1,24 +0,0 @@ -#include <linux/ctype.h> -#include <linux/types.h> - -int strcasecmp(const char *s1, const char *s2) -{ - int c1, c2; - - do { - c1 = tolower(*s1++); - c2 = tolower(*s2++); - } while (c1 == c2 && c1 != 0); - return c1 - c2; -} - -int strncasecmp(const char *s1, const char *s2, size_t n) -{ - int c1, c2; - - do { - c1 = tolower(*s1++); - c2 = tolower(*s2++); - } while ((--n > 0) && c1 == c2 && c1 != 0); - return c1 - c2; -} diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 705ae56016f..76551b67903 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -29,6 +29,7 @@ config CPCI405 config EP405 bool "EP405/EP405PC" + select EMBEDDEDBOOT help This option enables support for the EP405/EP405PC boards. @@ -54,11 +55,15 @@ config WALNUT config XILINX_ML300 bool "Xilinx-ML300" + select XILINX_VIRTEX_II_PRO + select EMBEDDEDBOOT help This option enables support for the Xilinx ML300 evaluation board. config XILINX_ML403 bool "Xilinx-ML403" + select XILINX_VIRTEX_4_FX + select EMBEDDEDBOOT help This option enables support for the Xilinx ML403 evaluation board. endchoice @@ -215,18 +220,14 @@ config 405GPR config XILINX_VIRTEX_II_PRO bool - depends on XILINX_ML300 - default y + select XILINX_VIRTEX config XILINX_VIRTEX_4_FX bool - depends on XILINX_ML403 - default y + select XILINX_VIRTEX config XILINX_VIRTEX bool - depends on XILINX_VIRTEX_II_PRO || XILINX_VIRTEX_4_FX - default y config STB03xxx bool @@ -235,8 +236,6 @@ config STB03xxx config EMBEDDEDBOOT bool - depends on EP405 || XILINX_ML300 || XILINX_ML403 - default y config IBM_OPENBIOS bool diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index fa6610bccaf..723ad7985cc 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -28,5 +28,4 @@ obj-$(CONFIG_440SP) += ibm440sp.o obj-$(CONFIG_440SPE) += ppc440spe.o obj-$(CONFIG_405EP) += ibm405ep.o obj-$(CONFIG_405GPR) += ibm405gpr.o -obj-$(CONFIG_XILINX_VIRTEX) += virtex.o diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 84e999d9a7b..5e994e146ba 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -178,7 +178,7 @@ ocotea_setup_pcix(void) /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); - PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA); + PCIX_WRITEL(0x80000007, PCIX0_PIM0SA); eieio(); } @@ -289,7 +289,7 @@ ocotea_setup_arch(void) * from FPGA, because it can be changed by on-board switches * --ebs */ - ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); + ibm440gx_get_clocks(&clocks, 33300000, 6 * 1843200); ocp_sys_info.opb_bus_freq = clocks.opb; /* Setup TODC access */ diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c index bb0253eef45..5d9af8ddb15 100644 --- a/arch/ppc/platforms/4xx/taishan.c +++ b/arch/ppc/platforms/4xx/taishan.c @@ -235,7 +235,7 @@ taishan_setup_pcix(void) /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); - PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA); + PCIX_WRITEL(0x80000007, PCIX0_PIM0SA); PCIX_WRITEL(0xffffffff, PCIX0_PIM0SAH); iounmap(pcix_reg_base); diff --git a/arch/ppc/platforms/4xx/virtex.c b/arch/ppc/platforms/4xx/virtex.c deleted file mode 100644 index 133a8314719..00000000000 --- a/arch/ppc/platforms/4xx/virtex.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Virtex-II Pro & Virtex-4 FX common infrastructure - * - * Maintainer: Grant Likely <grant.likely@secretlab.ca> - * - * Copyright 2005 Secret Lab Technologies Ltd. - * Copyright 2005 General Dynamics Canada Ltd. - * Copyright 2005 Freescale Semiconductor 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. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/serial_8250.h> -#include <asm/ppc_sys.h> -#include <platforms/4xx/virtex.h> -#include <platforms/4xx/xparameters/xparameters.h> - -#define XPAR_UART(num) { \ - .mapbase = XPAR_UARTNS550_##num##_BASEADDR + 3, \ - .irq = XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \ - .iotype = UPIO_MEM, \ - .uartclk = XPAR_UARTNS550_##num##_CLOCK_FREQ_HZ, \ - .flags = UPF_BOOT_AUTOCONF, \ - .regshift = 2, \ - } - -struct plat_serial8250_port serial_platform_data[] = { -#ifdef XPAR_UARTNS550_0_BASEADDR - XPAR_UART(0), -#endif -#ifdef XPAR_UARTNS550_1_BASEADDR - XPAR_UART(1), -#endif -#ifdef XPAR_UARTNS550_2_BASEADDR - XPAR_UART(2), -#endif -#ifdef XPAR_UARTNS550_3_BASEADDR - XPAR_UART(3), -#endif - { }, /* terminated by empty record */ -}; - -struct platform_device ppc_sys_platform_devices[] = { - [VIRTEX_UART] = { - .name = "serial8250", - .id = 0, - .dev.platform_data = serial_platform_data, - }, -}; - diff --git a/arch/ppc/platforms/4xx/virtex.h b/arch/ppc/platforms/4xx/virtex.h index c14325dfd7b..738280420be 100644 --- a/arch/ppc/platforms/4xx/virtex.h +++ b/arch/ppc/platforms/4xx/virtex.h @@ -1,35 +1,35 @@ /* - * arch/ppc/platforms/4xx/virtex.h + * Basic Virtex platform defines, included by <asm/ibm4xx.h> * - * Include file that defines the Xilinx Virtex-II Pro processor + * 2005-2007 (c) Secret Lab Technologies Ltd. + * 2002-2004 (c) MontaVista Software, Inc. * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is licensed - * "as is" without any warranty of any kind, whether express or implied. + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. */ #ifdef __KERNEL__ #ifndef __ASM_VIRTEX_H__ #define __ASM_VIRTEX_H__ -/* serial defines */ - #include <asm/ibm405.h> +#include <asm/ppcboot.h> /* Ugly, ugly, ugly! BASE_BAUD defined here to keep 8250.c happy. */ #if !defined(BASE_BAUD) #define BASE_BAUD (0) /* dummy value; not used */ #endif - -/* Device type enumeration for platform bus definitions */ + #ifndef __ASSEMBLY__ -enum ppc_sys_devices { - VIRTEX_UART, NUM_PPC_SYS_DEVS, -}; -#endif - +extern const char* virtex_machine_name; +#define PPC4xx_MACHINE_NAME (virtex_machine_name) +#endif /* !__ASSEMBLY__ */ + +/* We don't need anything mapped. Size of zero will accomplish that. */ +#define PPC4xx_ONB_IO_PADDR 0u +#define PPC4xx_ONB_IO_VADDR 0u +#define PPC4xx_ONB_IO_SIZE 0u + #endif /* __ASM_VIRTEX_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c index fb5f0b5e13d..6e522fefc26 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml300.c +++ b/arch/ppc/platforms/4xx/xilinx_ml300.c @@ -18,9 +18,9 @@ #include <linux/serialP.h> #include <asm/io.h> #include <asm/machdep.h> -#include <asm/ppc_sys.h> #include <syslib/gen550.h> +#include <syslib/virtex_devices.h> #include <platforms/4xx/xparameters/xparameters.h> /* @@ -53,24 +53,9 @@ * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c */ -/* Board specifications structures */ -struct ppc_sys_spec *cur_ppc_sys_spec; -struct ppc_sys_spec ppc_sys_specs[] = { - { - /* Only one entry, always assume the same design */ - .ppc_sys_name = "Xilinx ML300 Reference Design", - .mask = 0x00000000, - .value = 0x00000000, - .num_devices = 1, - .device_list = (enum ppc_sys_devices[]) - { - VIRTEX_UART, - }, - }, -}; +const char* virtex_machine_name = "ML300 Reference Design"; #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) - static volatile unsigned *powerdown_base = (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR; @@ -95,52 +80,14 @@ ml300_map_io(void) #endif } -/* Early serial support functions */ -static void __init -ml300_early_serial_init(int num, struct plat_serial8250_port *pdata) -{ -#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) - struct uart_port serial_req; - - memset(&serial_req, 0, sizeof(serial_req)); - serial_req.mapbase = pdata->mapbase; - serial_req.membase = pdata->membase; - serial_req.irq = pdata->irq; - serial_req.uartclk = pdata->uartclk; - serial_req.regshift = pdata->regshift; - serial_req.iotype = pdata->iotype; - serial_req.flags = pdata->flags; - gen550_init(num, &serial_req); -#endif -} - -void __init -ml300_early_serial_map(void) -{ -#ifdef CONFIG_SERIAL_8250 - struct plat_serial8250_port *pdata; - int i = 0; - - pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(VIRTEX_UART); - while(pdata && pdata->flags) - { - pdata->membase = ioremap(pdata->mapbase, 0x100); - ml300_early_serial_init(i, pdata); - pdata++; - i++; - } -#endif /* CONFIG_SERIAL_8250 */ -} - void __init ml300_setup_arch(void) { - ml300_early_serial_map(); + virtex_early_serial_map(); ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */ /* Identify the system */ - printk(KERN_INFO "Xilinx Virtex-II Pro port\n"); - printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); + printk(KERN_INFO "Xilinx ML300 Reference System (Virtex-II Pro)\n"); } /* Called after board_setup_irq from ppc4xx_init_IRQ(). */ @@ -156,8 +103,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, { ppc4xx_init(r3, r4, r5, r6, r7); - identify_ppc_sys_by_id(mfspr(SPRN_PVR)); - ppc_md.setup_arch = ml300_setup_arch; ppc_md.setup_io_mappings = ml300_map_io; ppc_md.init_IRQ = ml300_init_irq; @@ -167,7 +112,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #endif #ifdef CONFIG_KGDB - ppc_md.early_serial_map = ml300_early_serial_map; + ppc_md.early_serial_map = virtex_early_serial_map; #endif } diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.h b/arch/ppc/platforms/4xx/xilinx_ml300.h deleted file mode 100644 index 3d57332ba82..00000000000 --- a/arch/ppc/platforms/4xx/xilinx_ml300.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Include file that defines the Xilinx ML300 evaluation board - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is licensed - * "as is" without any warranty of any kind, whether express or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_XILINX_ML300_H__ -#define __ASM_XILINX_ML300_H__ - -/* ML300 has a Xilinx Virtex-II Pro processor */ -#include <platforms/4xx/virtex.h> - -#ifndef __ASSEMBLY__ - -#include <linux/types.h> - -typedef struct board_info { - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - -#endif /* !__ASSEMBLY__ */ - -/* We don't need anything mapped. Size of zero will accomplish that. */ -#define PPC4xx_ONB_IO_PADDR 0u -#define PPC4xx_ONB_IO_VADDR 0u -#define PPC4xx_ONB_IO_SIZE 0u - -#define PPC4xx_MACHINE_NAME "Xilinx ML300 Reference System" - -#endif /* __ASM_XILINX_ML300_H__ */ -#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.c b/arch/ppc/platforms/4xx/xilinx_ml403.c index cb3bf7a2bcb..bc3ace3762e 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml403.c +++ b/arch/ppc/platforms/4xx/xilinx_ml403.c @@ -1,11 +1,9 @@ /* - * arch/ppc/platforms/4xx/xilinx_ml403.c - * * Xilinx ML403 evaluation board initialization * * Author: Grant Likely <grant.likely@secretlab.ca> * - * 2005 (c) Secret Lab Technologies Ltd. + * 2005-2007 (c) Secret Lab Technologies Ltd. * 2002-2004 (c) MontaVista Software, Inc. * * This file is licensed under the terms of the GNU General Public License @@ -22,9 +20,9 @@ #include <linux/serialP.h> #include <asm/io.h> #include <asm/machdep.h> -#include <asm/ppc_sys.h> #include <syslib/gen550.h> +#include <syslib/virtex_devices.h> #include <platforms/4xx/xparameters/xparameters.h> /* @@ -57,24 +55,9 @@ * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c */ -/* Board specifications structures */ -struct ppc_sys_spec *cur_ppc_sys_spec; -struct ppc_sys_spec ppc_sys_specs[] = { - { - /* Only one entry, always assume the same design */ - .ppc_sys_name = "Xilinx ML403 Reference Design", - .mask = 0x00000000, - .value = 0x00000000, - .num_devices = 1, - .device_list = (enum ppc_sys_devices[]) - { - VIRTEX_UART, - }, - }, -}; +const char* virtex_machine_name = "ML403 Reference Design"; #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) - static volatile unsigned *powerdown_base = (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR; @@ -99,47 +82,10 @@ ml403_map_io(void) #endif } -/* Early serial support functions */ -static void __init -ml403_early_serial_init(int num, struct plat_serial8250_port *pdata) -{ -#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) - struct uart_port serial_req; - - memset(&serial_req, 0, sizeof(serial_req)); - serial_req.mapbase = pdata->mapbase; - serial_req.membase = pdata->membase; - serial_req.irq = pdata->irq; - serial_req.uartclk = pdata->uartclk; - serial_req.regshift = pdata->regshift; - serial_req.iotype = pdata->iotype; - serial_req.flags = pdata->flags; - gen550_init(num, &serial_req); -#endif -} - -void __init -ml403_early_serial_map(void) -{ -#ifdef CONFIG_SERIAL_8250 - struct plat_serial8250_port *pdata; - int i = 0; - - pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(VIRTEX_UART); - while(pdata && pdata->flags) - { - pdata->membase = ioremap(pdata->mapbase, 0x100); - ml403_early_serial_init(i, pdata); - pdata++; - i++; - } -#endif /* CONFIG_SERIAL_8250 */ -} - void __init ml403_setup_arch(void) { - ml403_early_serial_map(); + virtex_early_serial_map(); ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */ /* Identify the system */ @@ -159,8 +105,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, { ppc4xx_init(r3, r4, r5, r6, r7); - identify_ppc_sys_by_id(mfspr(SPRN_PVR)); - ppc_md.setup_arch = ml403_setup_arch; ppc_md.setup_io_mappings = ml403_map_io; ppc_md.init_IRQ = ml403_init_irq; @@ -170,7 +114,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #endif #ifdef CONFIG_KGDB - ppc_md.early_serial_map = ml403_early_serial_map; + ppc_md.early_serial_map = virtex_early_serial_map; #endif } diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.h b/arch/ppc/platforms/4xx/xilinx_ml403.h deleted file mode 100644 index 47359695990..00000000000 --- a/arch/ppc/platforms/4xx/xilinx_ml403.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * arch/ppc/platforms/4xx/xilinx_ml403.h - * - * Include file that defines the Xilinx ML403 reference design - * - * Author: Grant Likely <grant.likely@secretlab.ca> - * - * 2005 (c) Secret Lab Technologies Ltd. - * 2002-2004 (c) MontaVista Software, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_XILINX_ML403_H__ -#define __ASM_XILINX_ML403_H__ - -/* ML403 has a Xilinx Virtex-4 FPGA with a PPC405 hard core */ -#include <platforms/4xx/virtex.h> - -#ifndef __ASSEMBLY__ - -#include <linux/types.h> - -typedef struct board_info { - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - -#endif /* !__ASSEMBLY__ */ - -/* We don't need anything mapped. Size of zero will accomplish that. */ -#define PPC4xx_ONB_IO_PADDR 0u -#define PPC4xx_ONB_IO_VADDR 0u -#define PPC4xx_ONB_IO_SIZE 0u - -#define PPC4xx_MACHINE_NAME "Xilinx ML403 Reference Design" - -#endif /* __ASM_XILINX_ML403_H__ */ -#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters.h b/arch/ppc/platforms/4xx/xparameters/xparameters.h index 66ec5f35f30..01aa043ff38 100644 --- a/arch/ppc/platforms/4xx/xparameters/xparameters.h +++ b/arch/ppc/platforms/4xx/xparameters/xparameters.h @@ -34,3 +34,63 @@ .io_type = SERIAL_IO_MEM, \ }, #endif + +/* + * A few reasonable defaults for the #defines which could be missing depending + * on the IP version or variant (e.g. OPB vs PLB) + */ + +#ifndef XPAR_EMAC_0_CAM_EXIST +#define XPAR_EMAC_0_CAM_EXIST 0 +#endif +#ifndef XPAR_EMAC_0_JUMBO_EXIST +#define XPAR_EMAC_0_JUMBO_EXIST 0 +#endif +#ifndef XPAR_EMAC_0_TX_DRE_TYPE +#define XPAR_EMAC_0_TX_DRE_TYPE 0 +#endif +#ifndef XPAR_EMAC_0_RX_DRE_TYPE +#define XPAR_EMAC_0_RX_DRE_TYPE 0 +#endif +#ifndef XPAR_EMAC_0_TX_INCLUDE_CSUM +#define XPAR_EMAC_0_TX_INCLUDE_CSUM 0 +#endif +#ifndef XPAR_EMAC_0_RX_INCLUDE_CSUM +#define XPAR_EMAC_0_RX_INCLUDE_CSUM 0 +#endif + +#ifndef XPAR_EMAC_1_CAM_EXIST +#define XPAR_EMAC_1_CAM_EXIST 0 +#endif +#ifndef XPAR_EMAC_1_JUMBO_EXIST +#define XPAR_EMAC_1_JUMBO_EXIST 0 +#endif +#ifndef XPAR_EMAC_1_TX_DRE_TYPE +#define XPAR_EMAC_1_TX_DRE_TYPE 0 +#endif +#ifndef XPAR_EMAC_1_RX_DRE_TYPE +#define XPAR_EMAC_1_RX_DRE_TYPE 0 +#endif +#ifndef XPAR_EMAC_1_TX_INCLUDE_CSUM +#define XPAR_EMAC_1_TX_INCLUDE_CSUM 0 +#endif +#ifndef XPAR_EMAC_1_RX_INCLUDE_CSUM +#define XPAR_EMAC_1_RX_INCLUDE_CSUM 0 +#endif + +#ifndef XPAR_GPIO_0_IS_DUAL +#define XPAR_GPIO_0_IS_DUAL 0 +#endif +#ifndef XPAR_GPIO_1_IS_DUAL +#define XPAR_GPIO_1_IS_DUAL 0 +#endif +#ifndef XPAR_GPIO_2_IS_DUAL +#define XPAR_GPIO_2_IS_DUAL 0 +#endif +#ifndef XPAR_GPIO_3_IS_DUAL +#define XPAR_GPIO_3_IS_DUAL 0 +#endif +#ifndef XPAR_GPIO_4_IS_DUAL +#define XPAR_GPIO_4_IS_DUAL 0 +#endif + diff --git a/arch/ppc/platforms/rpxclassic.h b/arch/ppc/platforms/rpxclassic.h index 57a2a55dab8..a3c1118e5b0 100644 --- a/arch/ppc/platforms/rpxclassic.h +++ b/arch/ppc/platforms/rpxclassic.h @@ -69,10 +69,6 @@ extern bd_t m8xx_board_info; #define BCSR2_QSPACESEL ((uint)0x00004000) #define BCSR2_FETHLEDMODE ((uint)0x00000800) /* CLLF */ -#if defined(CONFIG_HTDMSOUND) -#include <platforms/rpxhiox.h> -#endif - /* define IO_BASE for pcmcia, CLLF only */ #if !defined(CONFIG_PCI) #define _IO_BASE 0x80000000 diff --git a/arch/ppc/platforms/rpxhiox.h b/arch/ppc/platforms/rpxhiox.h deleted file mode 100644 index c3fa5a65376..00000000000 --- a/arch/ppc/platforms/rpxhiox.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * The Embedded Planet HIOX expansion card definitions. - * There were a few different versions of these cards, but only - * the one that escaped real production is defined here. - * - * Copyright (c) 2000 Dan Malek (dmalek@jlc.net) - */ -#ifndef __MACH_RPX_HIOX_DEFS -#define __MACH_RPX_HIOX_DEFS - -#define HIOX_CSR_ADDR ((uint)0xfac00000) -#define HIOX_CSR_SIZE ((uint)(4 * 1024)) -#define HIOX_CSR0_ADDR HIOX_CSR_ADDR -#define HIOX_CSR4_ADDR ((uint)0xfac00004) - -#define HIOX_CSR0_DEFAULT ((uint)0x380f3c00) -#define HIOX_CSR0_ENSCC2 ((uint)0x80000000) -#define HIOX_CSR0_ENSMC2 ((uint)0x04000000) -#define HIOX_CSR0_ENVDOCLK ((uint)0x02000000) -#define HIOX_CSR0_VDORST_HL ((uint)0x01000000) -#define HIOX_CSR0_RS232SEL ((uint)0x0000c000) -#define HIOX_CSR0_SCC3SEL ((uint)0x0000c000) -#define HIOX_CSR0_SMC1SEL ((uint)0x00008000) -#define HIOX_CSR0_SCC1SEL ((uint)0x00004000) -#define HIOX_CSR0_ENTOUCH ((uint)0x00000080) -#define HIOX_CSR0_PDOWN100 ((uint)0x00000060) -#define HIOX_CSR0_PDOWN10 ((uint)0x00000040) -#define HIOX_CSR0_PDOWN1 ((uint)0x00000020) -#define HIOX_CSR0_TSELSPI ((uint)0x00000010) -#define HIOX_CSR0_TIRQSTAT ((uint)0x00000008) -#define HIOX_CSR4_DEFAULT ((uint)0x00000000) -#define HIOX_CSR4_ENTIRQ2 ((uint)0x20000000) -#define HIOX_CSR4_ENTIRQ3 ((uint)0x10000000) -#define HIOX_CSR4_ENAUDIO ((uint)0x00000080) -#define HIOX_CSR4_RSTAUDIO ((uint)0x00000040) /* 0 == reset */ -#define HIOX_CSR4_AUDCLKHI ((uint)0x00000020) -#define HIOX_CSR4_AUDSPISEL ((uint)0x00000010) -#define HIOX_CSR4_AUDIRQSTAT ((uint)0x00000008) -#define HIOX_CSR4_AUDCLKSEL ((uint)0x00000007) - -#endif diff --git a/arch/ppc/platforms/rpxlite.h b/arch/ppc/platforms/rpxlite.h index 71978064627..b615501d55f 100644 --- a/arch/ppc/platforms/rpxlite.h +++ b/arch/ppc/platforms/rpxlite.h @@ -57,10 +57,6 @@ extern bd_t m8xx_board_info; #define BCSR1_PCVCTL6 ((uint)0x00020000) #define BCSR1_PCVCTL7 ((uint)0x00010000) -#if defined(CONFIG_HTDMSOUND) -#include <platforms/rpxhiox.h> -#endif - /* define IO_BASE for pcmcia */ #define _IO_BASE 0x80000000 #define _IO_BASE_SIZE 0x1000 diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 09911118c67..95694159b22 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -18,7 +18,8 @@ obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o obj-$(CONFIG_440SPE) += ibm440gx_common.o ibm440sp_common.o ppc440spe_pcie.o ifeq ($(CONFIG_4xx),y) ifeq ($(CONFIG_XILINX_VIRTEX),y) -obj-$(CONFIG_40x) += xilinx_pic.o ppc_sys.o +obj-$(CONFIG_40x) += xilinx_pic.o +obj-y += virtex_devices.o else ifeq ($(CONFIG_403),y) obj-$(CONFIG_40x) += ppc403_pic.o diff --git a/arch/ppc/syslib/cpc710.h b/arch/ppc/syslib/cpc710.h deleted file mode 100644 index 5299bf8b5d0..00000000000 --- a/arch/ppc/syslib/cpc710.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Definitions for the IBM CPC710 PCI Host Bridge - * - * Author: Matt Porter <mporter@mvista.com> - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifndef __PPC_PLATFORMS_CPC710_H -#define __PPC_PLATFORMS_CPC710_H - -/* General bridge and memory controller registers */ -#define PIDR 0xff000008 -#define CNFR 0xff00000c -#define RSTR 0xff000010 -#define UCTL 0xff001000 -#define MPSR 0xff001010 -#define SIOC 0xff001020 -#define ABCNTL 0xff001030 -#define SRST 0xff001040 -#define ERRC 0xff001050 -#define SESR 0xff001060 -#define SEAR 0xff001070 -#define SIOC1 0xff001090 -#define PGCHP 0xff001100 -#define GPDIR 0xff001130 -#define GPOUT 0xff001150 -#define ATAS 0xff001160 -#define AVDG 0xff001170 -#define MCCR 0xff001200 -#define MESR 0xff001220 -#define MEAR 0xff001230 -#define MCER0 0xff001300 -#define MCER1 0xff001310 -#define MCER2 0xff001320 -#define MCER3 0xff001330 -#define MCER4 0xff001340 -#define MCER5 0xff001350 -#define MCER6 0xff001360 -#define MCER7 0xff001370 - -/* - * PCI32/64 configuration registers - * Given as offsets from their - * respective physical segment BAR - */ -#define PIBAR 0x000f7800 -#define PMBAR 0x000f7810 -#define MSIZE 0x000f7f40 -#define IOSIZE 0x000f7f60 -#define SMBAR 0x000f7f80 -#define SIBAR 0x000f7fc0 -#define PSSIZE 0x000f8100 -#define PPSIZE 0x000f8110 -#define BARPS 0x000f8120 -#define BARPP 0x000f8130 -#define PSBAR 0x000f8140 -#define PPBAR 0x000f8150 -#define BPMDLK 0x000f8200 /* Bottom of Peripheral Memory Space */ -#define TPMDLK 0x000f8210 /* Top of Peripheral Memory Space */ -#define BIODLK 0x000f8220 /* Bottom of Peripheral I/O Space */ -#define TIODLK 0x000f8230 /* Top of Perioheral I/O Space */ -#define DLKCTRL 0x000f8240 /* Deadlock control */ -#define DLKDEV 0x000f8250 /* Deadlock device */ - -/* System standard configuration registers space */ -#define DCR 0xff200000 -#define DID 0xff200004 -#define BAR 0xff200018 - -/* Device specific configuration space */ -#define PCIENB 0xff201000 - -/* Configuration space registers */ -#define CPC710_BUS_NUMBER 0x40 -#define CPC710_SUB_BUS_NUMBER 0x41 - -#endif /* __PPC_PLATFORMS_CPC710_H */ diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c index 01e48d88f22..9caf850c9b3 100644 --- a/arch/ppc/syslib/m8xx_setup.c +++ b/arch/ppc/syslib/m8xx_setup.c @@ -413,7 +413,7 @@ m8xx_map_io(void) io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO); #endif #endif -#if defined(CONFIG_HTDMSOUND) || defined(CONFIG_RPXTOUCH) || defined(CONFIG_FB_RPX) +#if defined(CONFIG_RPXTOUCH) || defined(CONFIG_FB_RPX) io_block_mapping(HIOX_CSR_ADDR, HIOX_CSR_ADDR, HIOX_CSR_SIZE, _PAGE_IO); #endif #ifdef CONFIG_FADS diff --git a/arch/ppc/syslib/ppc4xx_sgdma.c b/arch/ppc/syslib/ppc4xx_sgdma.c index 2f83e162971..939abe3c1f4 100644 --- a/arch/ppc/syslib/ppc4xx_sgdma.c +++ b/arch/ppc/syslib/ppc4xx_sgdma.c @@ -27,6 +27,7 @@ #include <asm/system.h> #include <asm/io.h> +#include <asm/dma-mapping.h> #include <asm/ppc4xx_dma.h> void diff --git a/arch/ppc/syslib/virtex_devices.c b/arch/ppc/syslib/virtex_devices.c new file mode 100644 index 00000000000..16546788e23 --- /dev/null +++ b/arch/ppc/syslib/virtex_devices.c @@ -0,0 +1,233 @@ +/* + * Virtex hard ppc405 core common device listing + * + * Copyright 2005-2007 Secret Lab Technologies Ltd. + * Copyright 2005 Freescale Semiconductor Inc. + * Copyright 2002-2004 MontaVista Software, 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. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/serial_8250.h> +#include <syslib/virtex_devices.h> +#include <platforms/4xx/xparameters/xparameters.h> +#include <asm/io.h> + +/* + * UARTLITE: shortcut macro for single instance + */ +#define XPAR_UARTLITE(num) { \ + .name = "uartlite", \ + .id = num, \ + .num_resources = 2, \ + .resource = (struct resource[]) { \ + { \ + .start = XPAR_UARTLITE_##num##_BASEADDR + 3, \ + .end = XPAR_UARTLITE_##num##_HIGHADDR, \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = XPAR_INTC_0_UARTLITE_##num##_VEC_ID, \ + .flags = IORESOURCE_IRQ, \ + }, \ + }, \ +} + +/* + * Full UART: shortcut macro for single instance + platform data structure + */ +#define XPAR_UART(num) { \ + .mapbase = XPAR_UARTNS550_##num##_BASEADDR + 3, \ + .irq = XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \ + .iotype = UPIO_MEM, \ + .uartclk = XPAR_UARTNS550_##num##_CLOCK_FREQ_HZ, \ + .flags = UPF_BOOT_AUTOCONF, \ + .regshift = 2, \ +} + +/* + * SystemACE: shortcut macro for single instance + */ +#define XPAR_SYSACE(num) { \ + .name = "xsysace", \ + .id = XPAR_SYSACE_##num##_DEVICE_ID, \ + .num_resources = 2, \ + .resource = (struct resource[]) { \ + { \ + .start = XPAR_SYSACE_##num##_BASEADDR, \ + .end = XPAR_SYSACE_##num##_HIGHADDR, \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = XPAR_INTC_0_SYSACE_##num##_VEC_ID, \ + .flags = IORESOURCE_IRQ, \ + }, \ + }, \ +} + + +/* UART 8250 driver platform data table */ +struct plat_serial8250_port virtex_serial_platform_data[] = { +#if defined(XPAR_UARTNS550_0_BASEADDR) + XPAR_UART(0), +#endif +#if defined(XPAR_UARTNS550_1_BASEADDR) + XPAR_UART(1), +#endif +#if defined(XPAR_UARTNS550_2_BASEADDR) + XPAR_UART(2), +#endif +#if defined(XPAR_UARTNS550_3_BASEADDR) + XPAR_UART(3), +#endif +#if defined(XPAR_UARTNS550_4_BASEADDR) + XPAR_UART(4), +#endif +#if defined(XPAR_UARTNS550_5_BASEADDR) + XPAR_UART(5), +#endif +#if defined(XPAR_UARTNS550_6_BASEADDR) + XPAR_UART(6), +#endif +#if defined(XPAR_UARTNS550_7_BASEADDR) + XPAR_UART(7), +#endif + { }, /* terminated by empty record */ +}; + + +struct platform_device virtex_platform_devices[] = { + /* UARTLITE instances */ +#if defined(XPAR_UARTLITE_0_BASEADDR) + XPAR_UARTLITE(0), +#endif +#if defined(XPAR_UARTLITE_1_BASEADDR) + XPAR_UARTLITE(1), +#endif +#if defined(XPAR_UARTLITE_2_BASEADDR) + XPAR_UARTLITE(2), +#endif +#if defined(XPAR_UARTLITE_3_BASEADDR) + XPAR_UARTLITE(3), +#endif +#if defined(XPAR_UARTLITE_4_BASEADDR) + XPAR_UARTLITE(4), +#endif +#if defined(XPAR_UARTLITE_5_BASEADDR) + XPAR_UARTLITE(5), +#endif +#if defined(XPAR_UARTLITE_6_BASEADDR) + XPAR_UARTLITE(6), +#endif +#if defined(XPAR_UARTLITE_7_BASEADDR) + XPAR_UARTLITE(7), +#endif + + /* Full UART instances */ +#if defined(XPAR_UARTNS550_0_BASEADDR) + { + .name = "serial8250", + .id = 0, + .dev.platform_data = virtex_serial_platform_data, + }, +#endif + + /* SystemACE instances */ +#if defined(XPAR_SYSACE_0_BASEADDR) + XPAR_SYSACE(0), +#endif +#if defined(XPAR_SYSACE_1_BASEADDR) + XPAR_SYSACE(1), +#endif + + /* ML300/403 reference design framebuffer */ +#if defined(XPAR_TFT_0_BASEADDR) + { + .name = "xilinxfb", + .id = 0, + .num_resources = 1, + .resource = (struct resource[]) { + { + .start = XPAR_TFT_0_BASEADDR, + .end = XPAR_TFT_0_BASEADDR+7, + .flags = IORESOURCE_IO, + }, + }, + }, +#endif +}; + +/* Early serial support functions */ +static void __init +virtex_early_serial_init(int num, struct plat_serial8250_port *pdata) +{ +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + struct uart_port serial_req; + + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.mapbase = pdata->mapbase; + serial_req.membase = pdata->membase; + serial_req.irq = pdata->irq; + serial_req.uartclk = pdata->uartclk; + serial_req.regshift = pdata->regshift; + serial_req.iotype = pdata->iotype; + serial_req.flags = pdata->flags; + gen550_init(num, &serial_req); +#endif +} + +void __init +virtex_early_serial_map(void) +{ +#ifdef CONFIG_SERIAL_8250 + struct plat_serial8250_port *pdata; + int i = 0; + + pdata = virtex_serial_platform_data; + while(pdata && pdata->flags) { + pdata->membase = ioremap(pdata->mapbase, 0x100); + virtex_early_serial_init(i, pdata); + pdata++; + i++; + } +#endif /* CONFIG_SERIAL_8250 */ +} + +/* + * default fixup routine; do nothing and return success. + * + * Reimplement this routine in your custom board support file to + * override the default behaviour + */ +int __attribute__ ((weak)) +virtex_device_fixup(struct platform_device *dev) +{ + return 0; +} + +static int __init virtex_init(void) +{ + struct platform_device *index = virtex_platform_devices; + unsigned int ret = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(virtex_platform_devices); i++, index++) { + if (virtex_device_fixup(index) != 0) + continue; + + if (platform_device_register(index)) { + ret = 1; + printk(KERN_ERR "cannot register dev %s:%d\n", + index->name, index->id); + } + } + return ret; +} + +subsys_initcall(virtex_init); diff --git a/arch/ppc/syslib/virtex_devices.h b/arch/ppc/syslib/virtex_devices.h new file mode 100644 index 00000000000..4a17dd3927c --- /dev/null +++ b/arch/ppc/syslib/virtex_devices.h @@ -0,0 +1,27 @@ +/* + * Common support header for virtex ppc405 platforms + * + * Copyright 2007 Secret Lab Technologies Ltd. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef __ASM_VIRTEX_DEVICES_H__ +#define __ASM_VIRTEX_DEVICES_H__ + +#include <linux/platform_device.h> + +void __init virtex_early_serial_map(void); + +/* Prototype for device fixup routine. Implement this routine in the + * board specific fixup code and the generic setup code will call it for + * each device is the platform device list. + * + * If the hook returns a non-zero value, then the device will not get + * registered with the platform bus + */ +int virtex_device_fixup(struct platform_device *dev); + +#endif /* __ASM_VIRTEX_DEVICES_H__ */ diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 0f293aa7b0f..e6ec418093e 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -41,6 +41,11 @@ config GENERIC_HWEIGHT config GENERIC_TIME def_bool y +config GENERIC_BUG + bool + depends on BUG + default y + config NO_IOMEM def_bool y @@ -514,6 +519,14 @@ config KEXEC current kernel, and to start another kernel. It is like a reboot but is independent of hardware/microcode support. +config ZFCPDUMP + tristate "zfcpdump support" + select SMP + default n + help + Select this option if you want to build an zfcpdump enabled kernel. + Refer to "Documentation/s390/zfcpdump.txt" for more details on this. + endmenu source "net/Kconfig" diff --git a/arch/s390/Makefile b/arch/s390/Makefile index b1e55849646..68441e0e74b 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -67,8 +67,10 @@ endif ifeq ($(call cc-option-yn,-mstack-size=8192 -mstack-guard=128),y) cflags-$(CONFIG_CHECK_STACK) += -mstack-size=$(STACK_SIZE) +ifneq ($(call cc-option-yn,-mstack-size=8192),y) cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD) endif +endif ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y) cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack @@ -103,6 +105,9 @@ install: vmlinux image: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ +zfcpdump: + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 0c3cf4b16ae..ee89b33145d 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -668,45 +668,7 @@ EXPORT_SYMBOL_GPL(appldata_register_ops); EXPORT_SYMBOL_GPL(appldata_unregister_ops); EXPORT_SYMBOL_GPL(appldata_diag); -#ifdef MODULE -/* - * Kernel symbols needed by appldata_mem and appldata_os modules. - * However, if this file is compiled as a module (for testing only), these - * symbols are not exported. In this case, we define them locally and export - * those. - */ -void si_swapinfo(struct sysinfo *val) -{ - val->freeswap = -1ul; - val->totalswap = -1ul; -} - -unsigned long avenrun[3] = {-1 - FIXED_1/200, -1 - FIXED_1/200, - -1 - FIXED_1/200}; -int nr_threads = -1; - -void get_full_page_state(struct page_state *ps) -{ - memset(ps, -1, sizeof(struct page_state)); -} - -unsigned long nr_running(void) -{ - return -1; -} - -unsigned long nr_iowait(void) -{ - return -1; -} - -/*unsigned long nr_context_switches(void) -{ - return -1; -}*/ -#endif /* MODULE */ EXPORT_SYMBOL_GPL(si_swapinfo); EXPORT_SYMBOL_GPL(nr_threads); EXPORT_SYMBOL_GPL(nr_running); EXPORT_SYMBOL_GPL(nr_iowait); -//EXPORT_SYMBOL_GPL(nr_context_switches); diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c index f64b8c867ae..a43f3488fec 100644 --- a/arch/s390/appldata/appldata_net_sum.c +++ b/arch/s390/appldata/appldata_net_sum.c @@ -108,9 +108,6 @@ static void appldata_get_net_sum_data(void *data) collisions = 0; read_lock(&dev_base_lock); for (dev = dev_base; dev != NULL; dev = dev->next) { - if (dev->get_stats == NULL) { - continue; - } stats = dev->get_stats(dev); rx_packets += stats->rx_packets; tx_packets += stats->tx_packets; diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index 91636353f6f..3660ca6a330 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -119,7 +119,8 @@ static struct crypto_alg aes_alg = { .cra_name = "aes", .cra_driver_name = "aes-s390", .cra_priority = CRYPT_S390_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_flags = CRYPTO_ALG_TYPE_CIPHER | + CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_aes_ctx), .cra_module = THIS_MODULE, @@ -206,7 +207,8 @@ static struct crypto_alg ecb_aes_alg = { .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-s390", .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | + CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_aes_ctx), .cra_type = &crypto_blkcipher_type, @@ -300,7 +302,8 @@ static struct crypto_alg cbc_aes_alg = { .cra_name = "cbc(aes)", .cra_driver_name = "cbc-aes-s390", .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | + CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_aes_ctx), .cra_type = &crypto_blkcipher_type, @@ -333,10 +336,14 @@ static int __init aes_init(void) return -EOPNOTSUPP; /* z9 109 and z9 BC/EC only support 128 bit key length */ - if (keylen_flag == AES_KEYLEN_128) + if (keylen_flag == AES_KEYLEN_128) { + aes_alg.cra_u.cipher.cia_max_keysize = AES_MIN_KEY_SIZE; + ecb_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE; + cbc_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE; printk(KERN_INFO "aes_s390: hardware acceleration only available for" "128 bit keys\n"); + } ret = crypto_register_alg(&aes_alg); if (ret) diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c index 969639f3197..af4460ec381 100644 --- a/arch/s390/crypto/sha1_s390.c +++ b/arch/s390/crypto/sha1_s390.c @@ -25,99 +25,100 @@ */ #include <linux/init.h> #include <linux/module.h> -#include <linux/mm.h> #include <linux/crypto.h> -#include <asm/scatterlist.h> -#include <asm/byteorder.h> + #include "crypt_s390.h" #define SHA1_DIGEST_SIZE 20 #define SHA1_BLOCK_SIZE 64 -struct crypt_s390_sha1_ctx { - u64 count; +struct s390_sha1_ctx { + u64 count; /* message length */ u32 state[5]; - u32 buf_len; - u8 buffer[2 * SHA1_BLOCK_SIZE]; + u8 buf[2 * SHA1_BLOCK_SIZE]; }; static void sha1_init(struct crypto_tfm *tfm) { - struct crypt_s390_sha1_ctx *ctx = crypto_tfm_ctx(tfm); - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; - - ctx->count = 0; - ctx->buf_len = 0; + struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); + + sctx->state[0] = 0x67452301; + sctx->state[1] = 0xEFCDAB89; + sctx->state[2] = 0x98BADCFE; + sctx->state[3] = 0x10325476; + sctx->state[4] = 0xC3D2E1F0; + sctx->count = 0; } static void sha1_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len) { - struct crypt_s390_sha1_ctx *sctx; - long imd_len; - - sctx = crypto_tfm_ctx(tfm); - sctx->count += len * 8; /* message bit length */ - - /* anything in buffer yet? -> must be completed */ - if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) { - /* complete full block and hash */ - memcpy(sctx->buffer + sctx->buf_len, data, - SHA1_BLOCK_SIZE - sctx->buf_len); - crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, - SHA1_BLOCK_SIZE); - data += SHA1_BLOCK_SIZE - sctx->buf_len; - len -= SHA1_BLOCK_SIZE - sctx->buf_len; - sctx->buf_len = 0; + struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); + unsigned int index; + int ret; + + /* how much is already in the buffer? */ + index = sctx->count & 0x3f; + + sctx->count += len; + + if (index + len < SHA1_BLOCK_SIZE) + goto store; + + /* process one stored block */ + if (index) { + memcpy(sctx->buf + index, data, SHA1_BLOCK_SIZE - index); + ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf, + SHA1_BLOCK_SIZE); + BUG_ON(ret != SHA1_BLOCK_SIZE); + data += SHA1_BLOCK_SIZE - index; + len -= SHA1_BLOCK_SIZE - index; } - /* rest of data contains full blocks? */ - imd_len = len & ~0x3ful; - if (imd_len) { - crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, imd_len); - data += imd_len; - len -= imd_len; + /* process as many blocks as possible */ + if (len >= SHA1_BLOCK_SIZE) { + ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, + len & ~(SHA1_BLOCK_SIZE - 1)); + BUG_ON(ret != (len & ~(SHA1_BLOCK_SIZE - 1))); + data += ret; + len -= ret; } - /* anything left? store in buffer */ - if (len) { - memcpy(sctx->buffer + sctx->buf_len , data, len); - sctx->buf_len += len; - } -} +store: + /* anything left? */ + if (len) + memcpy(sctx->buf + index , data, len); +} -static void pad_message(struct crypt_s390_sha1_ctx* sctx) +/* Add padding and return the message digest. */ +static void sha1_final(struct crypto_tfm *tfm, u8 *out) { - int index; + struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); + u64 bits; + unsigned int index, end; + int ret; + + /* must perform manual padding */ + index = sctx->count & 0x3f; + end = (index < 56) ? SHA1_BLOCK_SIZE : (2 * SHA1_BLOCK_SIZE); - index = sctx->buf_len; - sctx->buf_len = (sctx->buf_len < 56) ? - SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE; /* start pad with 1 */ - sctx->buffer[index] = 0x80; + sctx->buf[index] = 0x80; + /* pad with zeros */ index++; - memset(sctx->buffer + index, 0x00, sctx->buf_len - index); - /* append length */ - memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count, - sizeof sctx->count); -} + memset(sctx->buf + index, 0x00, end - index - 8); -/* Add padding and return the message digest. */ -static void sha1_final(struct crypto_tfm *tfm, u8 *out) -{ - struct crypt_s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); + /* append message length */ + bits = sctx->count * 8; + memcpy(sctx->buf + end - 8, &bits, sizeof(bits)); + + ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf, end); + BUG_ON(ret != end); - /* must perform manual padding */ - pad_message(sctx); - crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len); /* copy digest to out */ memcpy(out, sctx->state, SHA1_DIGEST_SIZE); + /* wipe context */ memset(sctx, 0, sizeof *sctx); } @@ -128,7 +129,7 @@ static struct crypto_alg alg = { .cra_priority = CRYPT_S390_PRIORITY, .cra_flags = CRYPTO_ALG_TYPE_DIGEST, .cra_blocksize = SHA1_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx), + .cra_ctxsize = sizeof(struct s390_sha1_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .digest = { diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c index 78436c696d3..2ced3330bce 100644 --- a/arch/s390/crypto/sha256_s390.c +++ b/arch/s390/crypto/sha256_s390.c @@ -26,7 +26,7 @@ #define SHA256_BLOCK_SIZE 64 struct s390_sha256_ctx { - u64 count; + u64 count; /* message length */ u32 state[8]; u8 buf[2 * SHA256_BLOCK_SIZE]; }; @@ -54,10 +54,9 @@ static void sha256_update(struct crypto_tfm *tfm, const u8 *data, int ret; /* how much is already in the buffer? */ - index = sctx->count / 8 & 0x3f; + index = sctx->count & 0x3f; - /* update message bit length */ - sctx->count += len * 8; + sctx->count += len; if ((index + len) < SHA256_BLOCK_SIZE) goto store; @@ -87,12 +86,17 @@ store: memcpy(sctx->buf + index , data, len); } -static void pad_message(struct s390_sha256_ctx* sctx) +/* Add padding and return the message digest */ +static void sha256_final(struct crypto_tfm *tfm, u8 *out) { - int index, end; + struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm); + u64 bits; + unsigned int index, end; + int ret; - index = sctx->count / 8 & 0x3f; - end = index < 56 ? SHA256_BLOCK_SIZE : 2 * SHA256_BLOCK_SIZE; + /* must perform manual padding */ + index = sctx->count & 0x3f; + end = (index < 56) ? SHA256_BLOCK_SIZE : (2 * SHA256_BLOCK_SIZE); /* start pad with 1 */ sctx->buf[index] = 0x80; @@ -102,21 +106,11 @@ static void pad_message(struct s390_sha256_ctx* sctx) memset(sctx->buf + index, 0x00, end - index - 8); /* append message length */ - memcpy(sctx->buf + end - 8, &sctx->count, sizeof sctx->count); - - sctx->count = end * 8; -} - -/* Add padding and return the message digest */ -static void sha256_final(struct crypto_tfm *tfm, u8 *out) -{ - struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm); - - /* must perform manual padding */ - pad_message(sctx); + bits = sctx->count * 8; + memcpy(sctx->buf + end - 8, &bits, sizeof(bits)); - crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, - sctx->count / 8); + ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, end); + BUG_ON(ret != end); /* copy digest to out */ memcpy(out, sctx->state, SHA256_DIGEST_SIZE); diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 741d2bbb2b3..0e4da8a7d82 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -12,6 +12,7 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_BUG=y CONFIG_NO_IOMEM=y CONFIG_S390=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -166,6 +167,7 @@ CONFIG_NO_IDLE_HZ=y CONFIG_NO_IDLE_HZ_INIT=y CONFIG_S390_HYPFS_FS=y CONFIG_KEXEC=y +# CONFIG_ZFCPDUMP is not set # # Networking @@ -705,6 +707,7 @@ CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 5492d25d7d6..3195d375bd5 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional obj-y := bitmap.o traps.o time.o process.o base.o early.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ - semaphore.o s390_ext.o debug.o irq.o ipl.o + semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 664c669b185..5236fdb17fc 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -495,29 +495,34 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) * sys32_execve() executes a new program after the asm stub has set * things up for us. This should basically do what I want it to. */ -asmlinkage long -sys32_execve(struct pt_regs regs) +asmlinkage long sys32_execve(void) { - int error; - char * filename; + struct pt_regs *regs = task_pt_regs(current); + char *filename; + unsigned long result; + int rc; - filename = getname(compat_ptr(regs.orig_gpr2)); - error = PTR_ERR(filename); - if (IS_ERR(filename)) + filename = getname(compat_ptr(regs->orig_gpr2)); + if (IS_ERR(filename)) { + result = PTR_ERR(filename); goto out; - error = compat_do_execve(filename, compat_ptr(regs.gprs[3]), - compat_ptr(regs.gprs[4]), ®s); - if (error == 0) - { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - current->thread.fp_regs.fpc=0; - asm volatile("sfpc %0,0" : : "d" (0)); } + rc = compat_do_execve(filename, compat_ptr(regs->gprs[3]), + compat_ptr(regs->gprs[4]), regs); + if (rc) { + result = rc; + goto out_putname; + } + task_lock(current); + current->ptrace &= ~PT_DTRACE; + task_unlock(current); + current->thread.fp_regs.fpc=0; + asm volatile("sfpc %0,0" : : "d" (0)); + result = regs->gprs[2]; +out_putname: putname(filename); out: - return error; + return result; } @@ -918,19 +923,20 @@ asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count) return sys_write(fd, buf, count); } -asmlinkage long sys32_clone(struct pt_regs regs) +asmlinkage long sys32_clone(void) { - unsigned long clone_flags; - unsigned long newsp; + struct pt_regs *regs = task_pt_regs(current); + unsigned long clone_flags; + unsigned long newsp; int __user *parent_tidptr, *child_tidptr; - clone_flags = regs.gprs[3] & 0xffffffffUL; - newsp = regs.orig_gpr2 & 0x7fffffffUL; - parent_tidptr = compat_ptr(regs.gprs[4]); - child_tidptr = compat_ptr(regs.gprs[5]); - if (!newsp) - newsp = regs.gprs[15]; - return do_fork(clone_flags, newsp, ®s, 0, + clone_flags = regs->gprs[3] & 0xffffffffUL; + newsp = regs->orig_gpr2 & 0x7fffffffUL; + parent_tidptr = compat_ptr(regs->gprs[4]); + child_tidptr = compat_ptr(regs->gprs[5]); + if (!newsp) + newsp = regs->gprs[15]; + return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 887a9881d0d..80a54a0149a 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -255,9 +255,9 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, } asmlinkage long -sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss, - struct pt_regs *regs) +sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss) { + struct pt_regs *regs = task_pt_regs(current); stack_t kss, koss; unsigned long ss_sp; int ret, err = 0; @@ -344,8 +344,9 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) return 0; } -asmlinkage long sys32_sigreturn(struct pt_regs *regs) +asmlinkage long sys32_sigreturn(void) { + struct pt_regs *regs = task_pt_regs(current); sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15]; sigset_t set; @@ -370,8 +371,9 @@ badframe: return 0; } -asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) +asmlinkage long sys32_rt_sigreturn(void) { + struct pt_regs *regs = task_pt_regs(current); rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15]; sigset_t set; stack_t st; @@ -407,8 +409,8 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) return regs->gprs[2]; badframe: - force_sig(SIGSEGV, current); - return 0; + force_sig(SIGSEGV, current); + return 0; } /* diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c new file mode 100644 index 00000000000..dabaf98943d --- /dev/null +++ b/arch/s390/kernel/dis.c @@ -0,0 +1,1278 @@ +/* + * arch/s390/kernel/dis.c + * + * Disassemble s390 instructions. + * + * Copyright IBM Corp. 2007 + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/ptrace.h> +#include <linux/timer.h> +#include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/kallsyms.h> +#include <linux/reboot.h> +#include <linux/kprobes.h> + +#include <asm/system.h> +#include <asm/uaccess.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include <asm/mathemu.h> +#include <asm/cpcmd.h> +#include <asm/s390_ext.h> +#include <asm/lowcore.h> +#include <asm/debug.h> +#include <asm/kdebug.h> + +#ifndef CONFIG_64BIT +#define ONELONG "%08lx: " +#else /* CONFIG_64BIT */ +#define ONELONG "%016lx: " +#endif /* CONFIG_64BIT */ + +#define OPERAND_GPR 0x1 /* Operand printed as %rx */ +#define OPERAND_FPR 0x2 /* Operand printed as %fx */ +#define OPERAND_AR 0x4 /* Operand printed as %ax */ +#define OPERAND_CR 0x8 /* Operand printed as %cx */ +#define OPERAND_DISP 0x10 /* Operand printed as displacement */ +#define OPERAND_BASE 0x20 /* Operand printed as base register */ +#define OPERAND_INDEX 0x40 /* Operand printed as index register */ +#define OPERAND_PCREL 0x80 /* Operand printed as pc-relative symbol */ +#define OPERAND_SIGNED 0x100 /* Operand printed as signed value */ +#define OPERAND_LENGTH 0x200 /* Operand printed as length (+1) */ + +enum { + UNUSED, /* Indicates the end of the operand list */ + R_8, /* GPR starting at position 8 */ + R_12, /* GPR starting at position 12 */ + R_16, /* GPR starting at position 16 */ + R_20, /* GPR starting at position 20 */ + R_24, /* GPR starting at position 24 */ + R_28, /* GPR starting at position 28 */ + R_32, /* GPR starting at position 32 */ + F_8, /* FPR starting at position 8 */ + F_12, /* FPR starting at position 12 */ + F_16, /* FPR starting at position 16 */ + F_20, /* FPR starting at position 16 */ + F_24, /* FPR starting at position 24 */ + F_28, /* FPR starting at position 28 */ + F_32, /* FPR starting at position 32 */ + A_8, /* Access reg. starting at position 8 */ + A_12, /* Access reg. starting at position 12 */ + A_24, /* Access reg. starting at position 24 */ + A_28, /* Access reg. starting at position 28 */ + C_8, /* Control reg. starting at position 8 */ + C_12, /* Control reg. starting at position 12 */ + B_16, /* Base register starting at position 16 */ + B_32, /* Base register starting at position 32 */ + X_12, /* Index register starting at position 12 */ + D_20, /* Displacement starting at position 20 */ + D_36, /* Displacement starting at position 36 */ + D20_20, /* 20 bit displacement starting at 20 */ + L4_8, /* 4 bit length starting at position 8 */ + L4_12, /* 4 bit length starting at position 12 */ + L8_8, /* 8 bit length starting at position 8 */ + U4_8, /* 4 bit unsigned value starting at 8 */ + U4_12, /* 4 bit unsigned value starting at 12 */ + U4_16, /* 4 bit unsigned value starting at 16 */ + U4_20, /* 4 bit unsigned value starting at 20 */ + U8_8, /* 8 bit unsigned value starting at 8 */ + U8_16, /* 8 bit unsigned value starting at 16 */ + I16_16, /* 16 bit signed value starting at 16 */ + U16_16, /* 16 bit unsigned value starting at 16 */ + J16_16, /* PC relative jump offset at 16 */ + J32_16, /* PC relative long offset at 16 */ + I32_16, /* 32 bit signed value starting at 16 */ + U32_16, /* 32 bit unsigned value starting at 16 */ + M_16, /* 4 bit optional mask starting at 16 */ + RO_28, /* optional GPR starting at position 28 */ +}; + +/* + * Enumeration of the different instruction formats. + * For details consult the principles of operation. + */ +enum { + INSTR_INVALID, + INSTR_E, INSTR_RIE_RRP, INSTR_RIL_RI, INSTR_RIL_RP, INSTR_RIL_RU, + INSTR_RIL_UP, INSTR_RI_RI, INSTR_RI_RP, INSTR_RI_RU, INSTR_RI_UP, + INSTR_RRE_00, INSTR_RRE_0R, INSTR_RRE_AA, INSTR_RRE_AR, INSTR_RRE_F0, + INSTR_RRE_FF, INSTR_RRE_R0, INSTR_RRE_RA, INSTR_RRE_RF, INSTR_RRE_RR, + INSTR_RRE_RR_OPT, INSTR_RRF_F0FF, INSTR_RRF_FUFF, INSTR_RRF_M0RR, + INSTR_RRF_R0RR, INSTR_RRF_RURR, INSTR_RRF_U0FF, INSTR_RRF_U0RF, + INSTR_RR_FF, INSTR_RR_R0, INSTR_RR_RR, INSTR_RR_U0, INSTR_RR_UR, + INSTR_RSE_CCRD, INSTR_RSE_RRRD, INSTR_RSE_RURD, INSTR_RSI_RRP, + INSTR_RSL_R0RD, INSTR_RSY_AARD, INSTR_RSY_CCRD, INSTR_RSY_RRRD, + INSTR_RSY_RURD, INSTR_RS_AARD, INSTR_RS_CCRD, INSTR_RS_R0RD, + INSTR_RS_RRRD, INSTR_RS_RURD, INSTR_RXE_FRRD, INSTR_RXE_RRRD, + INSTR_RXF_FRRDF, INSTR_RXY_FRRD, INSTR_RXY_RRRD, INSTR_RX_FRRD, + INSTR_RX_RRRD, INSTR_RX_URRD, INSTR_SIY_URD, INSTR_SI_URD, + INSTR_SSE_RDRD, INSTR_SSF_RRDRD, INSTR_SS_L0RDRD, INSTR_SS_LIRDRD, + INSTR_SS_LLRDRD, INSTR_SS_RRRDRD, INSTR_SS_RRRDRD2, INSTR_SS_RRRDRD3, + INSTR_S_00, INSTR_S_RD, +}; + +struct operand { + int bits; /* The number of bits in the operand. */ + int shift; /* The number of bits to shift. */ + int flags; /* One bit syntax flags. */ +}; + +struct insn { + const char name[5]; + unsigned char opfrag; + unsigned char format; +}; + +static const struct operand operands[] = +{ + [UNUSED] = { 0, 0, 0 }, + [R_8] = { 4, 8, OPERAND_GPR }, + [R_12] = { 4, 12, OPERAND_GPR }, + [R_16] = { 4, 16, OPERAND_GPR }, + [R_20] = { 4, 20, OPERAND_GPR }, + [R_24] = { 4, 24, OPERAND_GPR }, + [R_28] = { 4, 28, OPERAND_GPR }, + [R_32] = { 4, 32, OPERAND_GPR }, + [F_8] = { 4, 8, OPERAND_FPR }, + [F_12] = { 4, 12, OPERAND_FPR }, + [F_16] = { 4, 16, OPERAND_FPR }, + [F_20] = { 4, 16, OPERAND_FPR }, + [F_24] = { 4, 24, OPERAND_FPR }, + [F_28] = { 4, 28, OPERAND_FPR }, + [F_32] = { 4, 32, OPERAND_FPR }, + [A_8] = { 4, 8, OPERAND_AR }, + [A_12] = { 4, 12, OPERAND_AR }, + [A_24] = { 4, 24, OPERAND_AR }, + [A_28] = { 4, 28, OPERAND_AR }, + [C_8] = { 4, 8, OPERAND_CR }, + [C_12] = { 4, 12, OPERAND_CR }, + [B_16] = { 4, 16, OPERAND_BASE | OPERAND_GPR }, + [B_32] = { 4, 32, OPERAND_BASE | OPERAND_GPR }, + [X_12] = { 4, 12, OPERAND_INDEX | OPERAND_GPR }, + [D_20] = { 12, 20, OPERAND_DISP }, + [D_36] = { 12, 36, OPERAND_DISP }, + [D20_20] = { 20, 20, OPERAND_DISP | OPERAND_SIGNED }, + [L4_8] = { 4, 8, OPERAND_LENGTH }, + [L4_12] = { 4, 12, OPERAND_LENGTH }, + [L8_8] = { 8, 8, OPERAND_LENGTH }, + [U4_8] = { 4, 8, 0 }, + [U4_12] = { 4, 12, 0 }, + [U4_16] = { 4, 16, 0 }, + [U4_20] = { 4, 20, 0 }, + [U8_8] = { 8, 8, 0 }, + [U8_16] = { 8, 16, 0 }, + [I16_16] = { 16, 16, OPERAND_SIGNED }, + [U16_16] = { 16, 16, 0 }, + [J16_16] = { 16, 16, OPERAND_PCREL }, + [J32_16] = { 32, 16, OPERAND_PCREL }, + [I32_16] = { 32, 16, OPERAND_SIGNED }, + [U32_16] = { 32, 16, 0 }, + [M_16] = { 4, 16, 0 }, + [RO_28] = { 4, 28, OPERAND_GPR } +}; + +static const unsigned char formats[][7] = { + [INSTR_E] = { 0xff, 0,0,0,0,0,0 }, /* e.g. pr */ + [INSTR_RIE_RRP] = { 0xff, R_8,R_12,J16_16,0,0,0 }, /* e.g. brxhg */ + [INSTR_RIL_RP] = { 0x0f, R_8,J32_16,0,0,0,0 }, /* e.g. brasl */ + [INSTR_RIL_UP] = { 0x0f, U4_8,J32_16,0,0,0,0 }, /* e.g. brcl */ + [INSTR_RIL_RI] = { 0x0f, R_8,I32_16,0,0,0,0 }, /* e.g. afi */ + [INSTR_RIL_RU] = { 0x0f, R_8,U32_16,0,0,0,0 }, /* e.g. alfi */ + [INSTR_RI_RI] = { 0x0f, R_8,I16_16,0,0,0,0 }, /* e.g. ahi */ + [INSTR_RI_RP] = { 0x0f, R_8,J16_16,0,0,0,0 }, /* e.g. brct */ + [INSTR_RI_RU] = { 0x0f, R_8,U16_16,0,0,0,0 }, /* e.g. tml */ + [INSTR_RI_UP] = { 0x0f, U4_8,J16_16,0,0,0,0 }, /* e.g. brc */ + [INSTR_RRE_00] = { 0xff, 0,0,0,0,0,0 }, /* e.g. palb */ + [INSTR_RRE_0R] = { 0xff, R_28,0,0,0,0,0 }, /* e.g. tb */ + [INSTR_RRE_AA] = { 0xff, A_24,A_28,0,0,0,0 }, /* e.g. cpya */ + [INSTR_RRE_AR] = { 0xff, A_24,R_28,0,0,0,0 }, /* e.g. sar */ + [INSTR_RRE_F0] = { 0xff, F_24,0,0,0,0,0 }, /* e.g. sqer */ + [INSTR_RRE_FF] = { 0xff, F_24,F_28,0,0,0,0 }, /* e.g. debr */ + [INSTR_RRE_R0] = { 0xff, R_24,0,0,0,0,0 }, /* e.g. ipm */ + [INSTR_RRE_RA] = { 0xff, R_24,A_28,0,0,0,0 }, /* e.g. ear */ + [INSTR_RRE_RF] = { 0xff, R_24,F_28,0,0,0,0 }, /* e.g. cefbr */ + [INSTR_RRE_RR] = { 0xff, R_24,R_28,0,0,0,0 }, /* e.g. lura */ + [INSTR_RRE_RR_OPT]= { 0xff, R_24,RO_28,0,0,0,0 }, /* efpc, sfpc */ + [INSTR_RRF_F0FF] = { 0xff, F_16,F_24,F_28,0,0,0 }, /* e.g. madbr */ + [INSTR_RRF_FUFF] = { 0xff, F_24,F_16,F_28,U4_20,0,0 },/* e.g. didbr */ + [INSTR_RRF_RURR] = { 0xff, R_24,R_28,R_16,U4_20,0,0 },/* e.g. .insn */ + [INSTR_RRF_R0RR] = { 0xff, R_24,R_28,R_16,0,0,0 }, /* e.g. idte */ + [INSTR_RRF_U0FF] = { 0xff, F_24,U4_16,F_28,0,0,0 }, /* e.g. fixr */ + [INSTR_RRF_U0RF] = { 0xff, R_24,U4_16,F_28,0,0,0 }, /* e.g. cfebr */ + [INSTR_RRF_M0RR] = { 0xff, R_24,R_28,M_16,0,0,0 }, /* e.g. sske */ + [INSTR_RR_FF] = { 0xff, F_8,F_12,0,0,0,0 }, /* e.g. adr */ + [INSTR_RR_R0] = { 0xff, R_8, 0,0,0,0,0 }, /* e.g. spm */ + [INSTR_RR_RR] = { 0xff, R_8,R_12,0,0,0,0 }, /* e.g. lr */ + [INSTR_RR_U0] = { 0xff, U8_8, 0,0,0,0,0 }, /* e.g. svc */ + [INSTR_RR_UR] = { 0xff, U4_8,R_12,0,0,0,0 }, /* e.g. bcr */ + [INSTR_RSE_RRRD] = { 0xff, R_8,R_12,D_20,B_16,0,0 }, /* e.g. lmh */ + [INSTR_RSE_CCRD] = { 0xff, C_8,C_12,D_20,B_16,0,0 }, /* e.g. lmh */ + [INSTR_RSE_RURD] = { 0xff, R_8,U4_12,D_20,B_16,0,0 }, /* e.g. icmh */ + [INSTR_RSL_R0RD] = { 0xff, R_8,D_20,B_16,0,0,0 }, /* e.g. tp */ + [INSTR_RSI_RRP] = { 0xff, R_8,R_12,J16_16,0,0,0 }, /* e.g. brxh */ + [INSTR_RSY_RRRD] = { 0xff, R_8,R_12,D20_20,B_16,0,0 },/* e.g. stmy */ + [INSTR_RSY_RURD] = { 0xff, R_8,U4_12,D20_20,B_16,0,0 }, + /* e.g. icmh */ + [INSTR_RSY_AARD] = { 0xff, A_8,A_12,D20_20,B_16,0,0 },/* e.g. lamy */ + [INSTR_RSY_CCRD] = { 0xff, C_8,C_12,D20_20,B_16,0,0 },/* e.g. lamy */ + [INSTR_RS_AARD] = { 0xff, A_8,A_12,D_20,B_16,0,0 }, /* e.g. lam */ + [INSTR_RS_CCRD] = { 0xff, C_8,C_12,D_20,B_16,0,0 }, /* e.g. lctl */ + [INSTR_RS_R0RD] = { 0xff, R_8,D_20,B_16,0,0,0 }, /* e.g. sll */ + [INSTR_RS_RRRD] = { 0xff, R_8,R_12,D_20,B_16,0,0 }, /* e.g. cs */ + [INSTR_RS_RURD] = { 0xff, R_8,U4_12,D_20,B_16,0,0 }, /* e.g. icm */ + [INSTR_RXE_FRRD] = { 0xff, F_8,D_20,X_12,B_16,0,0 }, /* e.g. axbr */ + [INSTR_RXE_RRRD] = { 0xff, R_8,D_20,X_12,B_16,0,0 }, /* e.g. lg */ + [INSTR_RXF_FRRDF] = { 0xff, F_32,F_8,D_20,X_12,B_16,0 }, + /* e.g. madb */ + [INSTR_RXY_RRRD] = { 0xff, R_8,D20_20,X_12,B_16,0,0 },/* e.g. ly */ + [INSTR_RXY_FRRD] = { 0xff, F_8,D20_20,X_12,B_16,0,0 },/* e.g. ley */ + [INSTR_RX_FRRD] = { 0xff, F_8,D_20,X_12,B_16,0,0 }, /* e.g. ae */ + [INSTR_RX_RRRD] = { 0xff, R_8,D_20,X_12,B_16,0,0 }, /* e.g. l */ + [INSTR_RX_URRD] = { 0x00, U4_8,D_20,X_12,B_16,0,0 }, /* e.g. bc */ + [INSTR_SI_URD] = { 0x00, D_20,B_16,U8_8,0,0,0 }, /* e.g. cli */ + [INSTR_SIY_URD] = { 0xff, D20_20,B_16,U8_8,0,0,0 }, /* e.g. tmy */ + [INSTR_SSE_RDRD] = { 0xff, D_20,B_16,D_36,B_32,0,0 }, /* e.g. mvsdk */ + [INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 }, + /* e.g. mvc */ + [INSTR_SS_LIRDRD] = { 0xff, D_20,L4_8,B_16,D_36,B_32,U4_12 }, + /* e.g. srp */ + [INSTR_SS_LLRDRD] = { 0xff, D_20,L4_8,B_16,D_36,L4_12,B_32 }, + /* e.g. pack */ + [INSTR_SS_RRRDRD] = { 0xff, D_20,R_8,B_16,D_36,B_32,R_12 }, + /* e.g. mvck */ + [INSTR_SS_RRRDRD2]= { 0xff, R_8,D_20,B_16,R_12,D_36,B_32 }, + /* e.g. plo */ + [INSTR_SS_RRRDRD3]= { 0xff, R_8,R_12,D_20,B_16,D_36,B_32 }, + /* e.g. lmd */ + [INSTR_S_00] = { 0xff, 0,0,0,0,0,0 }, /* e.g. hsch */ + [INSTR_S_RD] = { 0xff, D_20,B_16,0,0,0,0 }, /* e.g. lpsw */ + [INSTR_SSF_RRDRD] = { 0x00, D_20,B_16,D_36,B_32,R_8,0 }, + /* e.g. mvcos */ +}; + +static struct insn opcode[] = { +#ifdef CONFIG_64BIT + { "lmd", 0xef, INSTR_SS_RRRDRD3 }, +#endif + { "spm", 0x04, INSTR_RR_R0 }, + { "balr", 0x05, INSTR_RR_RR }, + { "bctr", 0x06, INSTR_RR_RR }, + { "bcr", 0x07, INSTR_RR_UR }, + { "svc", 0x0a, INSTR_RR_U0 }, + { "bsm", 0x0b, INSTR_RR_RR }, + { "bassm", 0x0c, INSTR_RR_RR }, + { "basr", 0x0d, INSTR_RR_RR }, + { "mvcl", 0x0e, INSTR_RR_RR }, + { "clcl", 0x0f, INSTR_RR_RR }, + { "lpr", 0x10, INSTR_RR_RR }, + { "lnr", 0x11, INSTR_RR_RR }, + { "ltr", 0x12, INSTR_RR_RR }, + { "lcr", 0x13, INSTR_RR_RR }, + { "nr", 0x14, INSTR_RR_RR }, + { "clr", 0x15, INSTR_RR_RR }, + { "or", 0x16, INSTR_RR_RR }, + { "xr", 0x17, INSTR_RR_RR }, + { "lr", 0x18, INSTR_RR_RR }, + { "cr", 0x19, INSTR_RR_RR }, + { "ar", 0x1a, INSTR_RR_RR }, + { "sr", 0x1b, INSTR_RR_RR }, + { "mr", 0x1c, INSTR_RR_RR }, + { "dr", 0x1d, INSTR_RR_RR }, + { "alr", 0x1e, INSTR_RR_RR }, + { "slr", 0x1f, INSTR_RR_RR }, + { "lpdr", 0x20, INSTR_RR_FF }, + { "lndr", 0x21, INSTR_RR_FF }, + { "ltdr", 0x22, INSTR_RR_FF }, + { "lcdr", 0x23, INSTR_RR_FF }, + { "hdr", 0x24, INSTR_RR_FF }, + { "ldxr", 0x25, INSTR_RR_FF }, + { "lrdr", 0x25, INSTR_RR_FF }, + { "mxr", 0x26, INSTR_RR_FF }, + { "mxdr", 0x27, INSTR_RR_FF }, + { "ldr", 0x28, INSTR_RR_FF }, + { "cdr", 0x29, INSTR_RR_FF }, + { "adr", 0x2a, INSTR_RR_FF }, + { "sdr", 0x2b, INSTR_RR_FF }, + { "mdr", 0x2c, INSTR_RR_FF }, + { "ddr", 0x2d, INSTR_RR_FF }, + { "awr", 0x2e, INSTR_RR_FF }, + { "swr", 0x2f, INSTR_RR_FF }, + { "lper", 0x30, INSTR_RR_FF }, + { "lner", 0x31, INSTR_RR_FF }, + { "lter", 0x32, INSTR_RR_FF }, + { "lcer", 0x33, INSTR_RR_FF }, + { "her", 0x34, INSTR_RR_FF }, + { "ledr", 0x35, INSTR_RR_FF }, + { "lrer", 0x35, INSTR_RR_FF }, + { "axr", 0x36, INSTR_RR_FF }, + { "sxr", 0x37, INSTR_RR_FF }, + { "ler", 0x38, INSTR_RR_FF }, + { "cer", 0x39, INSTR_RR_FF }, + { "aer", 0x3a, INSTR_RR_FF }, + { "ser", 0x3b, INSTR_RR_FF }, + { "mder", 0x3c, INSTR_RR_FF }, + { "mer", 0x3c, INSTR_RR_FF }, + { "der", 0x3d, INSTR_RR_FF }, + { "aur", 0x3e, INSTR_RR_FF }, + { "sur", 0x3f, INSTR_RR_FF }, + { "sth", 0x40, INSTR_RX_RRRD }, + { "la", 0x41, INSTR_RX_RRRD }, + { "stc", 0x42, INSTR_RX_RRRD }, + { "ic", 0x43, INSTR_RX_RRRD }, + { "ex", 0x44, INSTR_RX_RRRD }, + { "bal", 0x45, INSTR_RX_RRRD }, + { "bct", 0x46, INSTR_RX_RRRD }, + { "bc", 0x47, INSTR_RX_URRD }, + { "lh", 0x48, INSTR_RX_RRRD }, + { "ch", 0x49, INSTR_RX_RRRD }, + { "ah", 0x4a, INSTR_RX_RRRD }, + { "sh", 0x4b, INSTR_RX_RRRD }, + { "mh", 0x4c, INSTR_RX_RRRD }, + { "bas", 0x4d, INSTR_RX_RRRD }, + { "cvd", 0x4e, INSTR_RX_RRRD }, + { "cvb", 0x4f, INSTR_RX_RRRD }, + { "st", 0x50, INSTR_RX_RRRD }, + { "lae", 0x51, INSTR_RX_RRRD }, + { "n", 0x54, INSTR_RX_RRRD }, + { "cl", 0x55, INSTR_RX_RRRD }, + { "o", 0x56, INSTR_RX_RRRD }, + { "x", 0x57, INSTR_RX_RRRD }, + { "l", 0x58, INSTR_RX_RRRD }, + { "c", 0x59, INSTR_RX_RRRD }, + { "a", 0x5a, INSTR_RX_RRRD }, + { "s", 0x5b, INSTR_RX_RRRD }, + { "m", 0x5c, INSTR_RX_RRRD }, + { "d", 0x5d, INSTR_RX_RRRD }, + { "al", 0x5e, INSTR_RX_RRRD }, + { "sl", 0x5f, INSTR_RX_RRRD }, + { "std", 0x60, INSTR_RX_FRRD }, + { "mxd", 0x67, INSTR_RX_FRRD }, + { "ld", 0x68, INSTR_RX_FRRD }, + { "cd", 0x69, INSTR_RX_FRRD }, + { "ad", 0x6a, INSTR_RX_FRRD }, + { "sd", 0x6b, INSTR_RX_FRRD }, + { "md", 0x6c, INSTR_RX_FRRD }, + { "dd", 0x6d, INSTR_RX_FRRD }, + { "aw", 0x6e, INSTR_RX_FRRD }, + { "sw", 0x6f, INSTR_RX_FRRD }, + { "ste", 0x70, INSTR_RX_FRRD }, + { "ms", 0x71, INSTR_RX_RRRD }, + { "le", 0x78, INSTR_RX_FRRD }, + { "ce", 0x79, INSTR_RX_FRRD }, + { "ae", 0x7a, INSTR_RX_FRRD }, + { "se", 0x7b, INSTR_RX_FRRD }, + { "mde", 0x7c, INSTR_RX_FRRD }, + { "me", 0x7c, INSTR_RX_FRRD }, + { "de", 0x7d, INSTR_RX_FRRD }, + { "au", 0x7e, INSTR_RX_FRRD }, + { "su", 0x7f, INSTR_RX_FRRD }, + { "ssm", 0x80, INSTR_S_RD }, + { "lpsw", 0x82, INSTR_S_RD }, + { "diag", 0x83, INSTR_RS_RRRD }, + { "brxh", 0x84, INSTR_RSI_RRP }, + { "brxle", 0x85, INSTR_RSI_RRP }, + { "bxh", 0x86, INSTR_RS_RRRD }, + { "bxle", 0x87, INSTR_RS_RRRD }, + { "srl", 0x88, INSTR_RS_R0RD }, + { "sll", 0x89, INSTR_RS_R0RD }, + { "sra", 0x8a, INSTR_RS_R0RD }, + { "sla", 0x8b, INSTR_RS_R0RD }, + { "srdl", 0x8c, INSTR_RS_R0RD }, + { "sldl", 0x8d, INSTR_RS_R0RD }, + { "srda", 0x8e, INSTR_RS_R0RD }, + { "slda", 0x8f, INSTR_RS_R0RD }, + { "stm", 0x90, INSTR_RS_RRRD }, + { "tm", 0x91, INSTR_SI_URD }, + { "mvi", 0x92, INSTR_SI_URD }, + { "ts", 0x93, INSTR_S_RD }, + { "ni", 0x94, INSTR_SI_URD }, + { "cli", 0x95, INSTR_SI_URD }, + { "oi", 0x96, INSTR_SI_URD }, + { "xi", 0x97, INSTR_SI_URD }, + { "lm", 0x98, INSTR_RS_RRRD }, + { "trace", 0x99, INSTR_RS_RRRD }, + { "lam", 0x9a, INSTR_RS_AARD }, + { "stam", 0x9b, INSTR_RS_AARD }, + { "mvcle", 0xa8, INSTR_RS_RRRD }, + { "clcle", 0xa9, INSTR_RS_RRRD }, + { "stnsm", 0xac, INSTR_SI_URD }, + { "stosm", 0xad, INSTR_SI_URD }, + { "sigp", 0xae, INSTR_RS_RRRD }, + { "mc", 0xaf, INSTR_SI_URD }, + { "lra", 0xb1, INSTR_RX_RRRD }, + { "stctl", 0xb6, INSTR_RS_CCRD }, + { "lctl", 0xb7, INSTR_RS_CCRD }, + { "cs", 0xba, INSTR_RS_RRRD }, + { "cds", 0xbb, INSTR_RS_RRRD }, + { "clm", 0xbd, INSTR_RS_RURD }, + { "stcm", 0xbe, INSTR_RS_RURD }, + { "icm", 0xbf, INSTR_RS_RURD }, + { "mvn", 0xd1, INSTR_SS_L0RDRD }, + { "mvc", 0xd2, INSTR_SS_L0RDRD }, + { "mvz", 0xd3, INSTR_SS_L0RDRD }, + { "nc", 0xd4, INSTR_SS_L0RDRD }, + { "clc", 0xd5, INSTR_SS_L0RDRD }, + { "oc", 0xd6, INSTR_SS_L0RDRD }, + { "xc", 0xd7, INSTR_SS_L0RDRD }, + { "mvck", 0xd9, INSTR_SS_RRRDRD }, + { "mvcp", 0xda, INSTR_SS_RRRDRD }, + { "mvcs", 0xdb, INSTR_SS_RRRDRD }, + { "tr", 0xdc, INSTR_SS_L0RDRD }, + { "trt", 0xdd, INSTR_SS_L0RDRD }, + { "ed", 0xde, INSTR_SS_L0RDRD }, + { "edmk", 0xdf, INSTR_SS_L0RDRD }, + { "pku", 0xe1, INSTR_SS_L0RDRD }, + { "unpku", 0xe2, INSTR_SS_L0RDRD }, + { "mvcin", 0xe8, INSTR_SS_L0RDRD }, + { "pka", 0xe9, INSTR_SS_L0RDRD }, + { "unpka", 0xea, INSTR_SS_L0RDRD }, + { "plo", 0xee, INSTR_SS_RRRDRD2 }, + { "srp", 0xf0, INSTR_SS_LIRDRD }, + { "mvo", 0xf1, INSTR_SS_LLRDRD }, + { "pack", 0xf2, INSTR_SS_LLRDRD }, + { "unpk", 0xf3, INSTR_SS_LLRDRD }, + { "zap", 0xf8, INSTR_SS_LLRDRD }, + { "cp", 0xf9, INSTR_SS_LLRDRD }, + { "ap", 0xfa, INSTR_SS_LLRDRD }, + { "sp", 0xfb, INSTR_SS_LLRDRD }, + { "mp", 0xfc, INSTR_SS_LLRDRD }, + { "dp", 0xfd, INSTR_SS_LLRDRD }, + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_01[] = { +#ifdef CONFIG_64BIT + { "sam64", 0x0e, INSTR_E }, +#endif + { "pr", 0x01, INSTR_E }, + { "upt", 0x02, INSTR_E }, + { "sckpf", 0x07, INSTR_E }, + { "tam", 0x0b, INSTR_E }, + { "sam24", 0x0c, INSTR_E }, + { "sam31", 0x0d, INSTR_E }, + { "trap2", 0xff, INSTR_E }, + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_a5[] = { +#ifdef CONFIG_64BIT + { "iihh", 0x00, INSTR_RI_RU }, + { "iihl", 0x01, INSTR_RI_RU }, + { "iilh", 0x02, INSTR_RI_RU }, + { "iill", 0x03, INSTR_RI_RU }, + { "nihh", 0x04, INSTR_RI_RU }, + { "nihl", 0x05, INSTR_RI_RU }, + { "nilh", 0x06, INSTR_RI_RU }, + { "nill", 0x07, INSTR_RI_RU }, + { "oihh", 0x08, INSTR_RI_RU }, + { "oihl", 0x09, INSTR_RI_RU }, + { "oilh", 0x0a, INSTR_RI_RU }, + { "oill", 0x0b, INSTR_RI_RU }, + { "llihh", 0x0c, INSTR_RI_RU }, + { "llihl", 0x0d, INSTR_RI_RU }, + { "llilh", 0x0e, INSTR_RI_RU }, + { "llill", 0x0f, INSTR_RI_RU }, +#endif + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_a7[] = { +#ifdef CONFIG_64BIT + { "tmhh", 0x02, INSTR_RI_RU }, + { "tmhl", 0x03, INSTR_RI_RU }, + { "brctg", 0x07, INSTR_RI_RP }, + { "lghi", 0x09, INSTR_RI_RI }, + { "aghi", 0x0b, INSTR_RI_RI }, + { "mghi", 0x0d, INSTR_RI_RI }, + { "cghi", 0x0f, INSTR_RI_RI }, +#endif + { "tmlh", 0x00, INSTR_RI_RU }, + { "tmll", 0x01, INSTR_RI_RU }, + { "brc", 0x04, INSTR_RI_UP }, + { "bras", 0x05, INSTR_RI_RP }, + { "brct", 0x06, INSTR_RI_RP }, + { "lhi", 0x08, INSTR_RI_RI }, + { "ahi", 0x0a, INSTR_RI_RI }, + { "mhi", 0x0c, INSTR_RI_RI }, + { "chi", 0x0e, INSTR_RI_RI }, + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_b2[] = { +#ifdef CONFIG_64BIT + { "sske", 0x2b, INSTR_RRF_M0RR }, + { "stckf", 0x7c, INSTR_S_RD }, + { "cu21", 0xa6, INSTR_RRF_M0RR }, + { "cuutf", 0xa6, INSTR_RRF_M0RR }, + { "cu12", 0xa7, INSTR_RRF_M0RR }, + { "cutfu", 0xa7, INSTR_RRF_M0RR }, + { "stfle", 0xb0, INSTR_S_RD }, + { "lpswe", 0xb2, INSTR_S_RD }, +#endif + { "stidp", 0x02, INSTR_S_RD }, + { "sck", 0x04, INSTR_S_RD }, + { "stck", 0x05, INSTR_S_RD }, + { "sckc", 0x06, INSTR_S_RD }, + { "stckc", 0x07, INSTR_S_RD }, + { "spt", 0x08, INSTR_S_RD }, + { "stpt", 0x09, INSTR_S_RD }, + { "spka", 0x0a, INSTR_S_RD }, + { "ipk", 0x0b, INSTR_S_00 }, + { "ptlb", 0x0d, INSTR_S_00 }, + { "spx", 0x10, INSTR_S_RD }, + { "stpx", 0x11, INSTR_S_RD }, + { "stap", 0x12, INSTR_S_RD }, + { "sie", 0x14, INSTR_S_RD }, + { "pc", 0x18, INSTR_S_RD }, + { "sac", 0x19, INSTR_S_RD }, + { "cfc", 0x1a, INSTR_S_RD }, + { "ipte", 0x21, INSTR_RRE_RR }, + { "ipm", 0x22, INSTR_RRE_R0 }, + { "ivsk", 0x23, INSTR_RRE_RR }, + { "iac", 0x24, INSTR_RRE_R0 }, + { "ssar", 0x25, INSTR_RRE_R0 }, + { "epar", 0x26, INSTR_RRE_R0 }, + { "esar", 0x27, INSTR_RRE_R0 }, + { "pt", 0x28, INSTR_RRE_RR }, + { "iske", 0x29, INSTR_RRE_RR }, + { "rrbe", 0x2a, INSTR_RRE_RR }, + { "sske", 0x2b, INSTR_RRE_RR }, + { "tb", 0x2c, INSTR_RRE_0R }, + { "dxr", 0x2d, INSTR_RRE_F0 }, + { "pgin", 0x2e, INSTR_RRE_RR }, + { "pgout", 0x2f, INSTR_RRE_RR }, + { "csch", 0x30, INSTR_S_00 }, + { "hsch", 0x31, INSTR_S_00 }, + { "msch", 0x32, INSTR_S_RD }, + { "ssch", 0x33, INSTR_S_RD }, + { "stsch", 0x34, INSTR_S_RD }, + { "tsch", 0x35, INSTR_S_RD }, + { "tpi", 0x36, INSTR_S_RD }, + { "sal", 0x37, INSTR_S_00 }, + { "rsch", 0x38, INSTR_S_00 }, + { "stcrw", 0x39, INSTR_S_RD }, + { "stcps", 0x3a, INSTR_S_RD }, + { "rchp", 0x3b, INSTR_S_00 }, + { "schm", 0x3c, INSTR_S_00 }, + { "bakr", 0x40, INSTR_RRE_RR }, + { "cksm", 0x41, INSTR_RRE_RR }, + { "sqdr", 0x44, INSTR_RRE_F0 }, + { "sqer", 0x45, INSTR_RRE_F0 }, + { "stura", 0x46, INSTR_RRE_RR }, + { "msta", 0x47, INSTR_RRE_R0 }, + { "palb", 0x48, INSTR_RRE_00 }, + { "ereg", 0x49, INSTR_RRE_RR }, + { "esta", 0x4a, INSTR_RRE_RR }, + { "lura", 0x4b, INSTR_RRE_RR }, + { "tar", 0x4c, INSTR_RRE_AR }, + { "cpya", INSTR_RRE_AA }, + { "sar", 0x4e, INSTR_RRE_AR }, + { "ear", 0x4f, INSTR_RRE_RA }, + { "csp", 0x50, INSTR_RRE_RR }, + { "msr", 0x52, INSTR_RRE_RR }, + { "mvpg", 0x54, INSTR_RRE_RR }, + { "mvst", 0x55, INSTR_RRE_RR }, + { "cuse", 0x57, INSTR_RRE_RR }, + { "bsg", 0x58, INSTR_RRE_RR }, + { "bsa", 0x5a, INSTR_RRE_RR }, + { "clst", 0x5d, INSTR_RRE_RR }, + { "srst", 0x5e, INSTR_RRE_RR }, + { "cmpsc", 0x63, INSTR_RRE_RR }, + { "cmpsc", 0x63, INSTR_RRE_RR }, + { "siga", 0x74, INSTR_S_RD }, + { "xsch", 0x76, INSTR_S_00 }, + { "rp", 0x77, INSTR_S_RD }, + { "stcke", 0x78, INSTR_S_RD }, + { "sacf", 0x79, INSTR_S_RD }, + { "stsi", 0x7d, INSTR_S_RD }, + { "srnm", 0x99, INSTR_S_RD }, + { "stfpc", 0x9c, INSTR_S_RD }, + { "lfpc", 0x9d, INSTR_S_RD }, + { "tre", 0xa5, INSTR_RRE_RR }, + { "cuutf", 0xa6, INSTR_RRE_RR }, + { "cutfu", 0xa7, INSTR_RRE_RR }, + { "stfl", 0xb1, INSTR_S_RD }, + { "trap4", 0xff, INSTR_S_RD }, + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_b3[] = { +#ifdef CONFIG_64BIT + { "maylr", 0x38, INSTR_RRF_F0FF }, + { "mylr", 0x39, INSTR_RRF_F0FF }, + { "mayr", 0x3a, INSTR_RRF_F0FF }, + { "myr", 0x3b, INSTR_RRF_F0FF }, + { "mayhr", 0x3c, INSTR_RRF_F0FF }, + { "myhr", 0x3d, INSTR_RRF_F0FF }, + { "cegbr", 0xa4, INSTR_RRE_RR }, + { "cdgbr", 0xa5, INSTR_RRE_RR }, + { "cxgbr", 0xa6, INSTR_RRE_RR }, + { "cgebr", 0xa8, INSTR_RRF_U0RF }, + { "cgdbr", 0xa9, INSTR_RRF_U0RF }, + { "cgxbr", 0xaa, INSTR_RRF_U0RF }, + { "cfer", 0xb8, INSTR_RRF_U0RF }, + { "cfdr", 0xb9, INSTR_RRF_U0RF }, + { "cfxr", 0xba, INSTR_RRF_U0RF }, + { "cegr", 0xc4, INSTR_RRE_RR }, + { "cdgr", 0xc5, INSTR_RRE_RR }, + { "cxgr", 0xc6, INSTR_RRE_RR }, + { "cger", 0xc8, INSTR_RRF_U0RF }, + { "cgdr", 0xc9, INSTR_RRF_U0RF }, + { "cgxr", 0xca, INSTR_RRF_U0RF }, +#endif + { "lpebr", 0x00, INSTR_RRE_FF }, + { "lnebr", 0x01, INSTR_RRE_FF }, + { "ltebr", 0x02, INSTR_RRE_FF }, + { "lcebr", 0x03, INSTR_RRE_FF }, + { "ldebr", 0x04, INSTR_RRE_FF }, + { "lxdbr", 0x05, INSTR_RRE_FF }, + { "lxebr", 0x06, INSTR_RRE_FF }, + { "mxdbr", 0x07, INSTR_RRE_FF }, + { "kebr", 0x08, INSTR_RRE_FF }, + { "cebr", 0x09, INSTR_RRE_FF }, + { "aebr", 0x0a, INSTR_RRE_FF }, + { "sebr", 0x0b, INSTR_RRE_FF }, + { "mdebr", 0x0c, INSTR_RRE_FF }, + { "debr", 0x0d, INSTR_RRE_FF }, + { "maebr", 0x0e, INSTR_RRF_F0FF }, + { "msebr", 0x0f, INSTR_RRF_F0FF }, + { "lpdbr", 0x10, INSTR_RRE_FF }, + { "lndbr", 0x11, INSTR_RRE_FF }, + { "ltdbr", 0x12, INSTR_RRE_FF }, + { "lcdbr", 0x13, INSTR_RRE_FF }, + { "sqebr", 0x14, INSTR_RRE_FF }, + { "sqdbr", 0x15, INSTR_RRE_FF }, + { "sqxbr", 0x16, INSTR_RRE_FF }, + { "meebr", 0x17, INSTR_RRE_FF }, + { "kdbr", 0x18, INSTR_RRE_FF }, + { "cdbr", 0x19, INSTR_RRE_FF }, + { "adbr", 0x1a, INSTR_RRE_FF }, + { "sdbr", 0x1b, INSTR_RRE_FF }, + { "mdbr", 0x1c, INSTR_RRE_FF }, + { "ddbr", 0x1d, INSTR_RRE_FF }, + { "madbr", 0x1e, INSTR_RRF_F0FF }, + { "msdbr", 0x1f, INSTR_RRF_F0FF }, + { "lder", 0x24, INSTR_RRE_FF }, + { "lxdr", 0x25, INSTR_RRE_FF }, + { "lxer", 0x26, INSTR_RRE_FF }, + { "maer", 0x2e, INSTR_RRF_F0FF }, + { "mser", 0x2f, INSTR_RRF_F0FF }, + { "sqxr", 0x36, INSTR_RRE_FF }, + { "meer", 0x37, INSTR_RRE_FF }, + { "madr", 0x3e, INSTR_RRF_F0FF }, + { "msdr", 0x3f, INSTR_RRF_F0FF }, + { "lpxbr", 0x40, INSTR_RRE_FF }, + { "lnxbr", 0x41, INSTR_RRE_FF }, + { "ltxbr", 0x42, INSTR_RRE_FF }, + { "lcxbr", 0x43, INSTR_RRE_FF }, + { "ledbr", 0x44, INSTR_RRE_FF }, + { "ldxbr", 0x45, INSTR_RRE_FF }, + { "lexbr", 0x46, INSTR_RRE_FF }, + { "fixbr", 0x47, INSTR_RRF_U0FF }, + { "kxbr", 0x48, INSTR_RRE_FF }, + { "cxbr", 0x49, INSTR_RRE_FF }, + { "axbr", 0x4a, INSTR_RRE_FF }, + { "sxbr", 0x4b, INSTR_RRE_FF }, + { "mxbr", 0x4c, INSTR_RRE_FF }, + { "dxbr", 0x4d, INSTR_RRE_FF }, + { "tbedr", 0x50, INSTR_RRF_U0FF }, + { "tbdr", 0x51, INSTR_RRF_U0FF }, + { "diebr", 0x53, INSTR_RRF_FUFF }, + { "fiebr", 0x57, INSTR_RRF_U0FF }, + { "thder", 0x58, INSTR_RRE_RR }, + { "thdr", 0x59, INSTR_RRE_RR }, + { "didbr", 0x5b, INSTR_RRF_FUFF }, + { "fidbr", 0x5f, INSTR_RRF_U0FF }, + { "lpxr", 0x60, INSTR_RRE_FF }, + { "lnxr", 0x61, INSTR_RRE_FF }, + { "ltxr", 0x62, INSTR_RRE_FF }, + { "lcxr", 0x63, INSTR_RRE_FF }, + { "lxr", 0x65, INSTR_RRE_RR }, + { "lexr", 0x66, INSTR_RRE_FF }, + { "fixr", 0x67, INSTR_RRF_U0FF }, + { "cxr", 0x69, INSTR_RRE_FF }, + { "lzer", 0x74, INSTR_RRE_R0 }, + { "lzdr", 0x75, INSTR_RRE_R0 }, + { "lzxr", 0x76, INSTR_RRE_R0 }, + { "fier", 0x77, INSTR_RRF_U0FF }, + { "fidr", 0x7f, INSTR_RRF_U0FF }, + { "sfpc", 0x84, INSTR_RRE_RR_OPT }, + { "efpc", 0x8c, INSTR_RRE_RR_OPT }, + { "cefbr", 0x94, INSTR_RRE_RF }, + { "cdfbr", 0x95, INSTR_RRE_RF }, + { "cxfbr", 0x96, INSTR_RRE_RF }, + { "cfebr", 0x98, INSTR_RRF_U0RF }, + { "cfdbr", 0x99, INSTR_RRF_U0RF }, + { "cfxbr", 0x9a, INSTR_RRF_U0RF }, + { "cefr", 0xb4, INSTR_RRE_RF }, + { "cdfr", 0xb5, INSTR_RRE_RF }, + { "cxfr", 0xb6, INSTR_RRE_RF }, + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_b9[] = { +#ifdef CONFIG_64BIT + { "lpgr", 0x00, INSTR_RRE_RR }, + { "lngr", 0x01, INSTR_RRE_RR }, + { "ltgr", 0x02, INSTR_RRE_RR }, + { "lcgr", 0x03, INSTR_RRE_RR }, + { "lgr", 0x04, INSTR_RRE_RR }, + { "lurag", 0x05, INSTR_RRE_RR }, + { "lgbr", 0x06, INSTR_RRE_RR }, + { "lghr", 0x07, INSTR_RRE_RR }, + { "agr", 0x08, INSTR_RRE_RR }, + { "sgr", 0x09, INSTR_RRE_RR }, + { "algr", 0x0a, INSTR_RRE_RR }, + { "slgr", 0x0b, INSTR_RRE_RR }, + { "msgr", 0x0c, INSTR_RRE_RR }, + { "dsgr", 0x0d, INSTR_RRE_RR }, + { "eregg", 0x0e, INSTR_RRE_RR }, + { "lrvgr", 0x0f, INSTR_RRE_RR }, + { "lpgfr", 0x10, INSTR_RRE_RR }, + { "lngfr", 0x11, INSTR_RRE_RR }, + { "ltgfr", 0x12, INSTR_RRE_RR }, + { "lcgfr", 0x13, INSTR_RRE_RR }, + { "lgfr", 0x14, INSTR_RRE_RR }, + { "llgfr", 0x16, INSTR_RRE_RR }, + { "llgtr", 0x17, INSTR_RRE_RR }, + { "agfr", 0x18, INSTR_RRE_RR }, + { "sgfr", 0x19, INSTR_RRE_RR }, + { "algfr", 0x1a, INSTR_RRE_RR }, + { "slgfr", 0x1b, INSTR_RRE_RR }, + { "msgfr", 0x1c, INSTR_RRE_RR }, + { "dsgfr", 0x1d, INSTR_RRE_RR }, + { "cgr", 0x20, INSTR_RRE_RR }, + { "clgr", 0x21, INSTR_RRE_RR }, + { "sturg", 0x25, INSTR_RRE_RR }, + { "lbr", 0x26, INSTR_RRE_RR }, + { "lhr", 0x27, INSTR_RRE_RR }, + { "cgfr", 0x30, INSTR_RRE_RR }, + { "clgfr", 0x31, INSTR_RRE_RR }, + { "bctgr", 0x46, INSTR_RRE_RR }, + { "ngr", 0x80, INSTR_RRE_RR }, + { "ogr", 0x81, INSTR_RRE_RR }, + { "xgr", 0x82, INSTR_RRE_RR }, + { "flogr", 0x83, INSTR_RRE_RR }, + { "llgcr", 0x84, INSTR_RRE_RR }, + { "llghr", 0x85, INSTR_RRE_RR }, + { "mlgr", 0x86, INSTR_RRE_RR }, + { "dlgr", 0x87, INSTR_RRE_RR }, + { "alcgr", 0x88, INSTR_RRE_RR }, + { "slbgr", 0x89, INSTR_RRE_RR }, + { "cspg", 0x8a, INSTR_RRE_RR }, + { "idte", 0x8e, INSTR_RRF_R0RR }, + { "llcr", 0x94, INSTR_RRE_RR }, + { "llhr", 0x95, INSTR_RRE_RR }, + { "esea", 0x9d, INSTR_RRE_R0 }, + { "lptea", 0xaa, INSTR_RRF_RURR }, + { "cu14", 0xb0, INSTR_RRF_M0RR }, + { "cu24", 0xb1, INSTR_RRF_M0RR }, + { "cu41", 0xb2, INSTR_RRF_M0RR }, + { "cu42", 0xb3, INSTR_RRF_M0RR }, +#endif + { "kmac", 0x1e, INSTR_RRE_RR }, + { "lrvr", 0x1f, INSTR_RRE_RR }, + { "km", 0x2e, INSTR_RRE_RR }, + { "kmc", 0x2f, INSTR_RRE_RR }, + { "kimd", 0x3e, INSTR_RRE_RR }, + { "klmd", 0x3f, INSTR_RRE_RR }, + { "epsw", 0x8d, INSTR_RRE_RR }, + { "trtt", 0x90, INSTR_RRE_RR }, + { "trtt", 0x90, INSTR_RRF_M0RR }, + { "trto", 0x91, INSTR_RRE_RR }, + { "trto", 0x91, INSTR_RRF_M0RR }, + { "trot", 0x92, INSTR_RRE_RR }, + { "trot", 0x92, INSTR_RRF_M0RR }, + { "troo", 0x93, INSTR_RRE_RR }, + { "troo", 0x93, INSTR_RRF_M0RR }, + { "mlr", 0x96, INSTR_RRE_RR }, + { "dlr", 0x97, INSTR_RRE_RR }, + { "alcr", 0x98, INSTR_RRE_RR }, + { "slbr", 0x99, INSTR_RRE_RR }, + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_c0[] = { +#ifdef CONFIG_64BIT + { "lgfi", 0x01, INSTR_RIL_RI }, + { "xihf", 0x06, INSTR_RIL_RU }, + { "xilf", 0x07, INSTR_RIL_RU }, + { "iihf", 0x08, INSTR_RIL_RU }, + { "iilf", 0x09, INSTR_RIL_RU }, + { "nihf", 0x0a, INSTR_RIL_RU }, + { "nilf", 0x0b, INSTR_RIL_RU }, + { "oihf", 0x0c, INSTR_RIL_RU }, + { "oilf", 0x0d, INSTR_RIL_RU }, + { "llihf", 0x0e, INSTR_RIL_RU }, + { "llilf", 0x0f, INSTR_RIL_RU }, +#endif + { "larl", 0x00, INSTR_RIL_RP }, + { "brcl", 0x04, INSTR_RIL_UP }, + { "brasl", 0x05, INSTR_RIL_RP }, + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_c2[] = { +#ifdef CONFIG_64BIT + { "slgfi", 0x04, INSTR_RIL_RU }, + { "slfi", 0x05, INSTR_RIL_RU }, + { "agfi", 0x08, INSTR_RIL_RI }, + { "afi", 0x09, INSTR_RIL_RI }, + { "algfi", 0x0a, INSTR_RIL_RU }, + { "alfi", 0x0b, INSTR_RIL_RU }, + { "cgfi", 0x0c, INSTR_RIL_RI }, + { "cfi", 0x0d, INSTR_RIL_RI }, + { "clgfi", 0x0e, INSTR_RIL_RU }, + { "clfi", 0x0f, INSTR_RIL_RU }, +#endif + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_c8[] = { +#ifdef CONFIG_64BIT + { "mvcos", 0x00, INSTR_SSF_RRDRD }, +#endif + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_e3[] = { +#ifdef CONFIG_64BIT + { "ltg", 0x02, INSTR_RXY_RRRD }, + { "lrag", 0x03, INSTR_RXY_RRRD }, + { "lg", 0x04, INSTR_RXY_RRRD }, + { "cvby", 0x06, INSTR_RXY_RRRD }, + { "ag", 0x08, INSTR_RXY_RRRD }, + { "sg", 0x09, INSTR_RXY_RRRD }, + { "alg", 0x0a, INSTR_RXY_RRRD }, + { "slg", 0x0b, INSTR_RXY_RRRD }, + { "msg", 0x0c, INSTR_RXY_RRRD }, + { "dsg", 0x0d, INSTR_RXY_RRRD }, + { "cvbg", 0x0e, INSTR_RXY_RRRD }, + { "lrvg", 0x0f, INSTR_RXY_RRRD }, + { "lt", 0x12, INSTR_RXY_RRRD }, + { "lray", 0x13, INSTR_RXY_RRRD }, + { "lgf", 0x14, INSTR_RXY_RRRD }, + { "lgh", 0x15, INSTR_RXY_RRRD }, + { "llgf", 0x16, INSTR_RXY_RRRD }, + { "llgt", 0x17, INSTR_RXY_RRRD }, + { "agf", 0x18, INSTR_RXY_RRRD }, + { "sgf", 0x19, INSTR_RXY_RRRD }, + { "algf", 0x1a, INSTR_RXY_RRRD }, + { "slgf", 0x1b, INSTR_RXY_RRRD }, + { "msgf", 0x1c, INSTR_RXY_RRRD }, + { "dsgf", 0x1d, INSTR_RXY_RRRD }, + { "cg", 0x20, INSTR_RXY_RRRD }, + { "clg", 0x21, INSTR_RXY_RRRD }, + { "stg", 0x24, INSTR_RXY_RRRD }, + { "cvdy", 0x26, INSTR_RXY_RRRD }, + { "cvdg", 0x2e, INSTR_RXY_RRRD }, + { "strvg", 0x2f, INSTR_RXY_RRRD }, + { "cgf", 0x30, INSTR_RXY_RRRD }, + { "clgf", 0x31, INSTR_RXY_RRRD }, + { "strvh", 0x3f, INSTR_RXY_RRRD }, + { "bctg", 0x46, INSTR_RXY_RRRD }, + { "sty", 0x50, INSTR_RXY_RRRD }, + { "msy", 0x51, INSTR_RXY_RRRD }, + { "ny", 0x54, INSTR_RXY_RRRD }, + { "cly", 0x55, INSTR_RXY_RRRD }, + { "oy", 0x56, INSTR_RXY_RRRD }, + { "xy", 0x57, INSTR_RXY_RRRD }, + { "ly", 0x58, INSTR_RXY_RRRD }, + { "cy", 0x59, INSTR_RXY_RRRD }, + { "ay", 0x5a, INSTR_RXY_RRRD }, + { "sy", 0x5b, INSTR_RXY_RRRD }, + { "aly", 0x5e, INSTR_RXY_RRRD }, + { "sly", 0x5f, INSTR_RXY_RRRD }, + { "sthy", 0x70, INSTR_RXY_RRRD }, + { "lay", 0x71, INSTR_RXY_RRRD }, + { "stcy", 0x72, INSTR_RXY_RRRD }, + { "icy", 0x73, INSTR_RXY_RRRD }, + { "lb", 0x76, INSTR_RXY_RRRD }, + { "lgb", 0x77, INSTR_RXY_RRRD }, + { "lhy", 0x78, INSTR_RXY_RRRD }, + { "chy", 0x79, INSTR_RXY_RRRD }, + { "ahy", 0x7a, INSTR_RXY_RRRD }, + { "shy", 0x7b, INSTR_RXY_RRRD }, + { "ng", 0x80, INSTR_RXY_RRRD }, + { "og", 0x81, INSTR_RXY_RRRD }, + { "xg", 0x82, INSTR_RXY_RRRD }, + { "mlg", 0x86, INSTR_RXY_RRRD }, + { "dlg", 0x87, INSTR_RXY_RRRD }, + { "alcg", 0x88, INSTR_RXY_RRRD }, + { "slbg", 0x89, INSTR_RXY_RRRD }, + { "stpq", 0x8e, INSTR_RXY_RRRD }, + { "lpq", 0x8f, INSTR_RXY_RRRD }, + { "llgc", 0x90, INSTR_RXY_RRRD }, + { "llgh", 0x91, INSTR_RXY_RRRD }, + { "llc", 0x94, INSTR_RXY_RRRD }, + { "llh", 0x95, INSTR_RXY_RRRD }, +#endif + { "lrv", 0x1e, INSTR_RXY_RRRD }, + { "lrvh", 0x1f, INSTR_RXY_RRRD }, + { "strv", 0x3e, INSTR_RXY_RRRD }, + { "ml", 0x96, INSTR_RXY_RRRD }, + { "dl", 0x97, INSTR_RXY_RRRD }, + { "alc", 0x98, INSTR_RXY_RRRD }, + { "slb", 0x99, INSTR_RXY_RRRD }, + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_e5[] = { +#ifdef CONFIG_64BIT + { "strag", 0x02, INSTR_SSE_RDRD }, +#endif + { "lasp", 0x00, INSTR_SSE_RDRD }, + { "tprot", 0x01, INSTR_SSE_RDRD }, + { "mvcsk", 0x0e, INSTR_SSE_RDRD }, + { "mvcdk", 0x0f, INSTR_SSE_RDRD }, + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_eb[] = { +#ifdef CONFIG_64BIT + { "lmg", 0x04, INSTR_RSY_RRRD }, + { "srag", 0x0a, INSTR_RSY_RRRD }, + { "slag", 0x0b, INSTR_RSY_RRRD }, + { "srlg", 0x0c, INSTR_RSY_RRRD }, + { "sllg", 0x0d, INSTR_RSY_RRRD }, + { "tracg", 0x0f, INSTR_RSY_RRRD }, + { "csy", 0x14, INSTR_RSY_RRRD }, + { "rllg", 0x1c, INSTR_RSY_RRRD }, + { "clmh", 0x20, INSTR_RSY_RURD }, + { "clmy", 0x21, INSTR_RSY_RURD }, + { "stmg", 0x24, INSTR_RSY_RRRD }, + { "stctg", 0x25, INSTR_RSY_CCRD }, + { "stmh", 0x26, INSTR_RSY_RRRD }, + { "stcmh", 0x2c, INSTR_RSY_RURD }, + { "stcmy", 0x2d, INSTR_RSY_RURD }, + { "lctlg", 0x2f, INSTR_RSY_CCRD }, + { "csg", 0x30, INSTR_RSY_RRRD }, + { "cdsy", 0x31, INSTR_RSY_RRRD }, + { "cdsg", 0x3e, INSTR_RSY_RRRD }, + { "bxhg", 0x44, INSTR_RSY_RRRD }, + { "bxleg", 0x45, INSTR_RSY_RRRD }, + { "tmy", 0x51, INSTR_SIY_URD }, + { "mviy", 0x52, INSTR_SIY_URD }, + { "niy", 0x54, INSTR_SIY_URD }, + { "cliy", 0x55, INSTR_SIY_URD }, + { "oiy", 0x56, INSTR_SIY_URD }, + { "xiy", 0x57, INSTR_SIY_URD }, + { "icmh", 0x80, INSTR_RSE_RURD }, + { "icmh", 0x80, INSTR_RSY_RURD }, + { "icmy", 0x81, INSTR_RSY_RURD }, + { "clclu", 0x8f, INSTR_RSY_RRRD }, + { "stmy", 0x90, INSTR_RSY_RRRD }, + { "lmh", 0x96, INSTR_RSY_RRRD }, + { "lmy", 0x98, INSTR_RSY_RRRD }, + { "lamy", 0x9a, INSTR_RSY_AARD }, + { "stamy", 0x9b, INSTR_RSY_AARD }, +#endif + { "rll", 0x1d, INSTR_RSY_RRRD }, + { "mvclu", 0x8e, INSTR_RSY_RRRD }, + { "tp", 0xc0, INSTR_RSL_R0RD }, + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_ec[] = { +#ifdef CONFIG_64BIT + { "brxhg", 0x44, INSTR_RIE_RRP }, + { "brxlg", 0x45, INSTR_RIE_RRP }, +#endif + { "", 0, INSTR_INVALID } +}; + +static struct insn opcode_ed[] = { +#ifdef CONFIG_64BIT + { "mayl", 0x38, INSTR_RXF_FRRDF }, + { "myl", 0x39, INSTR_RXF_FRRDF }, + { "may", 0x3a, INSTR_RXF_FRRDF }, + { "my", 0x3b, INSTR_RXF_FRRDF }, + { "mayh", 0x3c, INSTR_RXF_FRRDF }, + { "myh", 0x3d, INSTR_RXF_FRRDF }, + { "ley", 0x64, INSTR_RXY_FRRD }, + { "ldy", 0x65, INSTR_RXY_FRRD }, + { "stey", 0x66, INSTR_RXY_FRRD }, + { "stdy", 0x67, INSTR_RXY_FRRD }, +#endif + { "ldeb", 0x04, INSTR_RXE_FRRD }, + { "lxdb", 0x05, INSTR_RXE_FRRD }, + { "lxeb", 0x06, INSTR_RXE_FRRD }, + { "mxdb", 0x07, INSTR_RXE_FRRD }, + { "keb", 0x08, INSTR_RXE_FRRD }, + { "ceb", 0x09, INSTR_RXE_FRRD }, + { "aeb", 0x0a, INSTR_RXE_FRRD }, + { "seb", 0x0b, INSTR_RXE_FRRD }, + { "mdeb", 0x0c, INSTR_RXE_FRRD }, + { "deb", 0x0d, INSTR_RXE_FRRD }, + { "maeb", 0x0e, INSTR_RXF_FRRDF }, + { "mseb", 0x0f, INSTR_RXF_FRRDF }, + { "tceb", 0x10, INSTR_RXE_FRRD }, + { "tcdb", 0x11, INSTR_RXE_FRRD }, + { "tcxb", 0x12, INSTR_RXE_FRRD }, + { "sqeb", 0x14, INSTR_RXE_FRRD }, + { "sqdb", 0x15, INSTR_RXE_FRRD }, + { "meeb", 0x17, INSTR_RXE_FRRD }, + { "kdb", 0x18, INSTR_RXE_FRRD }, + { "cdb", 0x19, INSTR_RXE_FRRD }, + { "adb", 0x1a, INSTR_RXE_FRRD }, + { "sdb", 0x1b, INSTR_RXE_FRRD }, + { "mdb", 0x1c, INSTR_RXE_FRRD }, + { "ddb", 0x1d, INSTR_RXE_FRRD }, + { "madb", 0x1e, INSTR_RXF_FRRDF }, + { "msdb", 0x1f, INSTR_RXF_FRRDF }, + { "lde", 0x24, INSTR_RXE_FRRD }, + { "lxd", 0x25, INSTR_RXE_FRRD }, + { "lxe", 0x26, INSTR_RXE_FRRD }, + { "mae", 0x2e, INSTR_RXF_FRRDF }, + { "mse", 0x2f, INSTR_RXF_FRRDF }, + { "sqe", 0x34, INSTR_RXE_FRRD }, + { "mee", 0x37, INSTR_RXE_FRRD }, + { "mad", 0x3e, INSTR_RXF_FRRDF }, + { "msd", 0x3f, INSTR_RXF_FRRDF }, + { "", 0, INSTR_INVALID } +}; + +/* Extracts an operand value from an instruction. */ +static unsigned int extract_operand(unsigned char *code, + const struct operand *operand) +{ + unsigned int val; + int bits; + + /* Extract fragments of the operand byte for byte. */ + code += operand->shift / 8; + bits = (operand->shift & 7) + operand->bits; + val = 0; + do { + val <<= 8; + val |= (unsigned int) *code++; + bits -= 8; + } while (bits > 0); + val >>= -bits; + val &= ((1U << (operand->bits - 1)) << 1) - 1; + + /* Check for special long displacement case. */ + if (operand->bits == 20 && operand->shift == 20) + val = (val & 0xff) << 12 | (val & 0xfff00) >> 8; + + /* Sign extend value if the operand is signed or pc relative. */ + if ((operand->flags & (OPERAND_SIGNED | OPERAND_PCREL)) && + (val & (1U << (operand->bits - 1)))) + val |= (-1U << (operand->bits - 1)) << 1; + + /* Double value if the operand is pc relative. */ + if (operand->flags & OPERAND_PCREL) + val <<= 1; + + /* Length x in an instructions has real length x + 1. */ + if (operand->flags & OPERAND_LENGTH) + val++; + return val; +} + +static inline int insn_length(unsigned char code) +{ + return ((((int) code + 64) >> 7) + 1) << 1; +} + +static struct insn *find_insn(unsigned char *code) +{ + unsigned char opfrag = code[1]; + unsigned char opmask; + struct insn *table; + + switch (code[0]) { + case 0x01: + table = opcode_01; + break; + case 0xa5: + table = opcode_a5; + break; + case 0xa7: + table = opcode_a7; + break; + case 0xb2: + table = opcode_b2; + break; + case 0xb3: + table = opcode_b3; + break; + case 0xb9: + table = opcode_b9; + break; + case 0xc0: + table = opcode_c0; + break; + case 0xc2: + table = opcode_c2; + break; + case 0xc8: + table = opcode_c8; + break; + case 0xe3: + table = opcode_e3; + opfrag = code[5]; + break; + case 0xe5: + table = opcode_e5; + break; + case 0xeb: + table = opcode_eb; + opfrag = code[5]; + break; + case 0xec: + table = opcode_ec; + opfrag = code[5]; + break; + case 0xed: + table = opcode_ed; + opfrag = code[5]; + break; + default: + table = opcode; + opfrag = code[0]; + break; + } + while (table->format != INSTR_INVALID) { + opmask = formats[table->format][0]; + if (table->opfrag == (opfrag & opmask)) + return table; + table++; + } + return NULL; +} + +static int print_insn(char *buffer, unsigned char *code, unsigned long addr) +{ + struct insn *insn; + const unsigned char *ops; + const struct operand *operand; + unsigned int value; + char separator; + char *ptr; + + ptr = buffer; + insn = find_insn(code); + if (insn) { + ptr += sprintf(ptr, "%.5s\t", insn->name); + /* Extract the operands. */ + separator = 0; + for (ops = formats[insn->format] + 1; *ops != 0; ops++) { + operand = operands + *ops; + value = extract_operand(code, operand); + if ((operand->flags & OPERAND_INDEX) && value == 0) + continue; + if ((operand->flags & OPERAND_BASE) && + value == 0 && separator == '(') { + separator = ','; + continue; + } + if (separator) + ptr += sprintf(ptr, "%c", separator); + if (operand->flags & OPERAND_GPR) + ptr += sprintf(ptr, "%%r%i", value); + else if (operand->flags & OPERAND_FPR) + ptr += sprintf(ptr, "%%f%i", value); + else if (operand->flags & OPERAND_AR) + ptr += sprintf(ptr, "%%a%i", value); + else if (operand->flags & OPERAND_CR) + ptr += sprintf(ptr, "%%c%i", value); + else if (operand->flags & OPERAND_PCREL) + ptr += sprintf(ptr, "%lx", value + addr); + else if (operand->flags & OPERAND_SIGNED) + ptr += sprintf(ptr, "%i", value); + else + ptr += sprintf(ptr, "%u", value); + if (operand->flags & OPERAND_DISP) + separator = '('; + else if (operand->flags & OPERAND_BASE) { + ptr += sprintf(ptr, ")"); + separator = ','; + } else + separator = ','; + } + } else + ptr += sprintf(ptr, "unknown"); + return (int) (ptr - buffer); +} + +void show_code(struct pt_regs *regs) +{ + char *mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl"; + unsigned char code[64]; + char buffer[64], *ptr; + mm_segment_t old_fs; + unsigned long addr; + int start, end, opsize, hops, i; + + /* Get a snapshot of the 64 bytes surrounding the fault address. */ + old_fs = get_fs(); + set_fs((regs->psw.mask & PSW_MASK_PSTATE) ? USER_DS : KERNEL_DS); + for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) { + addr = regs->psw.addr - 34 + start; + if (__copy_from_user(code + start - 2, + (char __user *) addr, 2)) + break; + } + for (end = 32; end < 64; end += 2) { + addr = regs->psw.addr + end - 32; + if (__copy_from_user(code + end, + (char __user *) addr, 2)) + break; + } + set_fs(old_fs); + /* Code snapshot useable ? */ + if ((regs->psw.addr & 1) || start >= end) { + printk("%s Code: Bad PSW.\n", mode); + return; + } + /* Find a starting point for the disassembly. */ + while (start < 32) { + hops = 0; + for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) { + if (!find_insn(code + start + i)) + break; + i += insn_length(code[start + i]); + } + if (start + i == 32) + /* Looks good, sequence ends at PSW. */ + break; + start += 2; + } + /* Decode the instructions. */ + ptr = buffer; + ptr += sprintf(ptr, "%s Code:", mode); + hops = 0; + while (start < end && hops < 8) { + *ptr++ = (start == 32) ? '>' : ' '; + addr = regs->psw.addr + start - 32; + ptr += sprintf(ptr, ONELONG, addr); + opsize = insn_length(code[start]); + if (start + opsize >= end) + break; + for (i = 0; i < opsize; i++) + ptr += sprintf(ptr, "%02x", code[start + i]); + *ptr++ = '\t'; + if (i < 6) + *ptr++ = '\t'; + ptr += print_insn(ptr, code + start, addr); + start += opsize; + printk(buffer); + ptr = buffer; + ptr += sprintf(ptr, "\n "); + hops++; + } + printk("\n"); +} diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 5e47936573f..50538e54561 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -253,11 +253,10 @@ static noinline __init void find_memory_chunks(unsigned long memsize) break; #endif /* - * Finish memory detection at the first hole, unless - * - we reached the hsa -> skip it. - * - we know there must be more. + * Finish memory detection at the first hole + * if storage size is unknown. */ - if (cc == -1UL && !memsize && old_addr != ADDR2G) + if (cc == -1UL && !memsize) break; if (memsize && addr >= memsize) break; diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index dddc3de3040..c8a2212014e 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -249,8 +249,6 @@ sysc_do_restart: bnz BASED(sysc_tracesys) basr %r14,%r8 # call sys_xxxx st %r2,SP_R2(%r15) # store return value (change R2 on stack) - # ATTENTION: check sys_execve_glue before - # changing anything here !! sysc_return: tm SP_PSW+1(%r15),0x01 # returning to user ? @@ -381,50 +379,37 @@ ret_from_fork: b BASED(sysc_return) # -# clone, fork, vfork, exec and sigreturn need glue, -# because they all expect pt_regs as parameter, -# but are called with different parameter. -# return-address is set up above +# kernel_execve function needs to deal with pt_regs that is not +# at the usual place # -sys_clone_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,BASED(.Lclone) - br %r1 # branch to sys_clone - -sys_fork_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,BASED(.Lfork) - br %r1 # branch to sys_fork - -sys_vfork_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,BASED(.Lvfork) - br %r1 # branch to sys_vfork - -sys_execve_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,BASED(.Lexecve) - lr %r12,%r14 # save return address - basr %r14,%r1 # call sys_execve - ltr %r2,%r2 # check if execve failed - bnz 0(%r12) # it did fail -> store result in gpr2 - b 4(%r12) # SKIP ST 2,SP_R2(15) after BASR 14,8 - # in system_call/sysc_tracesys - -sys_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - l %r1,BASED(.Lsigreturn) - br %r1 # branch to sys_sigreturn - -sys_rt_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - l %r1,BASED(.Lrt_sigreturn) - br %r1 # branch to sys_sigreturn - -sys_sigaltstack_glue: - la %r4,SP_PTREGS(%r15) # load pt_regs as parameter - l %r1,BASED(.Lsigaltstack) - br %r1 # branch to sys_sigreturn + .globl kernel_execve +kernel_execve: + stm %r12,%r15,48(%r15) + lr %r14,%r15 + l %r13,__LC_SVC_NEW_PSW+4 + s %r15,BASED(.Lc_spsize) + st %r14,__SF_BACKCHAIN(%r15) + la %r12,SP_PTREGS(%r15) + xc 0(__PT_SIZE,%r12),0(%r12) + l %r1,BASED(.Ldo_execve) + lr %r5,%r12 + basr %r14,%r1 + ltr %r2,%r2 + be BASED(0f) + a %r15,BASED(.Lc_spsize) + lm %r12,%r15,48(%r15) + br %r14 + # execve succeeded. +0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts + l %r15,__LC_KERNEL_STACK # load ksp + s %r15,BASED(.Lc_spsize) # make room for registers & psw + l %r9,__LC_THREAD_INFO + mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs + xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts + l %r1,BASED(.Lexecve_tail) + basr %r14,%r1 + b BASED(sysc_return) /* * Program check handler routine @@ -1031,19 +1016,11 @@ cleanup_io_leave_insn: .Ldo_extint: .long do_extint .Ldo_signal: .long do_signal .Lhandle_per: .long do_single_step +.Ldo_execve: .long do_execve +.Lexecve_tail: .long execve_tail .Ljump_table: .long pgm_check_table .Lschedule: .long schedule -.Lclone: .long sys_clone -.Lexecve: .long sys_execve -.Lfork: .long sys_fork -.Lrt_sigreturn: .long sys_rt_sigreturn -.Lrt_sigsuspend: - .long sys_rt_sigsuspend -.Lsigreturn: .long sys_sigreturn -.Lsigsuspend: .long sys_sigsuspend -.Lsigaltstack: .long sys_sigaltstack .Ltrace: .long syscall_trace -.Lvfork: .long sys_vfork .Lschedtail: .long schedule_tail .Lsysc_table: .long sys_call_table #ifdef CONFIG_TRACE_IRQFLAGS diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 0f758c329a5..93745fd8f55 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -244,8 +244,6 @@ sysc_noemu: jnz sysc_tracesys basr %r14,%r8 # call sys_xxxx stg %r2,SP_R2(%r15) # store return value (change R2 on stack) - # ATTENTION: check sys_execve_glue before - # changing anything here !! sysc_return: tm SP_PSW+1(%r15),0x01 # returning to user ? @@ -371,77 +369,35 @@ ret_from_fork: j sysc_return # -# clone, fork, vfork, exec and sigreturn need glue, -# because they all expect pt_regs as parameter, -# but are called with different parameter. -# return-address is set up above +# kernel_execve function needs to deal with pt_regs that is not +# at the usual place # -sys_clone_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - jg sys_clone # branch to sys_clone - -#ifdef CONFIG_COMPAT -sys32_clone_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - jg sys32_clone # branch to sys32_clone -#endif - -sys_fork_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - jg sys_fork # branch to sys_fork - -sys_vfork_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - jg sys_vfork # branch to sys_vfork - -sys_execve_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - lgr %r12,%r14 # save return address - brasl %r14,sys_execve # call sys_execve - ltgr %r2,%r2 # check if execve failed - bnz 0(%r12) # it did fail -> store result in gpr2 - b 6(%r12) # SKIP STG 2,SP_R2(15) in - # system_call/sysc_tracesys -#ifdef CONFIG_COMPAT -sys32_execve_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - lgr %r12,%r14 # save return address - brasl %r14,sys32_execve # call sys32_execve - ltgr %r2,%r2 # check if execve failed - bnz 0(%r12) # it did fail -> store result in gpr2 - b 6(%r12) # SKIP STG 2,SP_R2(15) in - # system_call/sysc_tracesys -#endif - -sys_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys_sigreturn # branch to sys_sigreturn - -#ifdef CONFIG_COMPAT -sys32_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys32_sigreturn # branch to sys32_sigreturn -#endif - -sys_rt_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys_rt_sigreturn # branch to sys_sigreturn - -#ifdef CONFIG_COMPAT -sys32_rt_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys32_rt_sigreturn # branch to sys32_sigreturn -#endif - -sys_sigaltstack_glue: - la %r4,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys_sigaltstack # branch to sys_sigreturn - -#ifdef CONFIG_COMPAT -sys32_sigaltstack_glue: - la %r4,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys32_sigaltstack_wrapper # branch to sys_sigreturn -#endif + .globl kernel_execve +kernel_execve: + stmg %r12,%r15,96(%r15) + lgr %r14,%r15 + aghi %r15,-SP_SIZE + stg %r14,__SF_BACKCHAIN(%r15) + la %r12,SP_PTREGS(%r15) + xc 0(__PT_SIZE,%r12),0(%r12) + lgr %r5,%r12 + brasl %r14,do_execve + ltgfr %r2,%r2 + je 0f + aghi %r15,SP_SIZE + lmg %r12,%r15,96(%r15) + br %r14 + # execve succeeded. +0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts + lg %r15,__LC_KERNEL_STACK # load ksp + aghi %r15,-SP_SIZE # make room for registers & psw + lg %r13,__LC_SVC_NEW_PSW+8 + lg %r9,__LC_THREAD_INFO + mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs + xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts + brasl %r14,execve_tail + j sysc_return /* * Program check handler routine diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 37010709fe6..a87b1976d40 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -39,7 +39,69 @@ startup_continue: basr %r13,0 # get base .LPG1: sll %r13,1 # remove high order bit srl %r13,1 - lhi %r1,1 # mode 1 = esame + +#ifdef CONFIG_ZFCPDUMP + + # check if we have been ipled using zfcp dump: + + tm 0xb9,0x01 # test if subchannel is enabled + jno .nodump # subchannel disabled + l %r1,0xb8 + la %r5,.Lipl_schib-.LPG1(%r13) + stsch 0(%r5) # get schib of subchannel + jne .nodump # schib not available + tm 5(%r5),0x01 # devno valid? + jno .nodump + tm 4(%r5),0x80 # qdio capable device? + jno .nodump + l %r2,20(%r0) # address of ipl parameter block + lhi %r3,0 + ic %r3,0x148(%r2) # get opt field + chi %r3,0x20 # load with dump? + jne .nodump + + # store all prefix registers in case of load with dump: + + la %r7,0 # base register for 0 page + la %r8,0 # first cpu + l %r11,.Lpref_arr_ptr-.LPG1(%r13) # address of prefix array + ahi %r11,4 # skip boot cpu + lr %r12,%r11 + ahi %r12,(CONFIG_NR_CPUS*4) # end of prefix array + stap .Lcurrent_cpu+2-.LPG1(%r13) # store current cpu addr +1: + cl %r8,.Lcurrent_cpu-.LPG1(%r13) # is ipl cpu ? + je 4f # if yes get next cpu +2: + lr %r9,%r7 + sigp %r9,%r8,0x9 # stop & store status of cpu + brc 8,3f # accepted + brc 4,4f # status stored: next cpu + brc 2,2b # busy: try again + brc 1,4f # not op: next cpu +3: + mvc 0(4,%r11),264(%r7) # copy prefix register to prefix array + ahi %r11,4 # next element in prefix array + clr %r11,%r12 + je 5f # no more space in prefix array +4: + ahi %r8,1 # next cpu (r8 += 1) + cl %r8,.Llast_cpu-.LPG1(%r13) # is last possible cpu ? + jl 1b # jump if not last cpu +5: + lhi %r1,2 # mode 2 = esame (dump) + j 6f + .align 4 +.Lipl_schib: + .rept 13 + .long 0 + .endr +.nodump: + lhi %r1,1 # mode 1 = esame (normal ipl) +6: +#else + lhi %r1,1 # mode 1 = esame (normal ipl) +#endif /* CONFIG_ZFCPDUMP */ mvi __LC_AR_MODE_ID,1 # set esame flag slr %r0,%r0 # set cpuid to zero sigp %r1,%r0,0x12 # switch to esame mode @@ -149,6 +211,14 @@ startup_continue: .L4malign:.quad 0xffffffffffc00000 .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 .Lnop: .long 0x07000700 +#ifdef CONFIG_ZFCPDUMP +.Lcurrent_cpu: + .long 0x0 +.Llast_cpu: + .long 0x0000ffff +.Lpref_arr_ptr: + .long zfcpdump_prefix_array +#endif /* CONFIG_ZFCPDUMP */ .Lparmaddr: .quad PARMAREA .align 64 diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index f731185bf2b..06833ac2b11 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -29,36 +29,21 @@ #define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm) #define SCCB_FLAG (s390_readinfo_sccb.flags) -enum ipl_type { - IPL_TYPE_NONE = 1, - IPL_TYPE_UNKNOWN = 2, - IPL_TYPE_CCW = 4, - IPL_TYPE_FCP = 8, - IPL_TYPE_NSS = 16, -}; - -#define IPL_NONE_STR "none" -#define IPL_UNKNOWN_STR "unknown" -#define IPL_CCW_STR "ccw" -#define IPL_FCP_STR "fcp" -#define IPL_NSS_STR "nss" - -/* - * Must be in data section since the bss section - * is not cleared when these are accessed. - */ -u16 ipl_devno __attribute__((__section__(".data"))) = 0; -u32 ipl_flags __attribute__((__section__(".data"))) = 0; +#define IPL_UNKNOWN_STR "unknown" +#define IPL_CCW_STR "ccw" +#define IPL_FCP_STR "fcp" +#define IPL_FCP_DUMP_STR "fcp_dump" +#define IPL_NSS_STR "nss" static char *ipl_type_str(enum ipl_type type) { switch (type) { - case IPL_TYPE_NONE: - return IPL_NONE_STR; case IPL_TYPE_CCW: return IPL_CCW_STR; case IPL_TYPE_FCP: return IPL_FCP_STR; + case IPL_TYPE_FCP_DUMP: + return IPL_FCP_DUMP_STR; case IPL_TYPE_NSS: return IPL_NSS_STR; case IPL_TYPE_UNKNOWN: @@ -67,15 +52,55 @@ static char *ipl_type_str(enum ipl_type type) } } +enum dump_type { + DUMP_TYPE_NONE = 1, + DUMP_TYPE_CCW = 2, + DUMP_TYPE_FCP = 4, +}; + +#define DUMP_NONE_STR "none" +#define DUMP_CCW_STR "ccw" +#define DUMP_FCP_STR "fcp" + +static char *dump_type_str(enum dump_type type) +{ + switch (type) { + case DUMP_TYPE_NONE: + return DUMP_NONE_STR; + case DUMP_TYPE_CCW: + return DUMP_CCW_STR; + case DUMP_TYPE_FCP: + return DUMP_FCP_STR; + default: + return NULL; + } +} + +/* + * Must be in data section since the bss section + * is not cleared when these are accessed. + */ +static u16 ipl_devno __attribute__((__section__(".data"))) = 0; +u32 ipl_flags __attribute__((__section__(".data"))) = 0; + enum ipl_method { - IPL_METHOD_NONE, - IPL_METHOD_CCW_CIO, - IPL_METHOD_CCW_DIAG, - IPL_METHOD_CCW_VM, - IPL_METHOD_FCP_RO_DIAG, - IPL_METHOD_FCP_RW_DIAG, - IPL_METHOD_FCP_RO_VM, - IPL_METHOD_NSS, + REIPL_METHOD_CCW_CIO, + REIPL_METHOD_CCW_DIAG, + REIPL_METHOD_CCW_VM, + REIPL_METHOD_FCP_RO_DIAG, + REIPL_METHOD_FCP_RW_DIAG, + REIPL_METHOD_FCP_RO_VM, + REIPL_METHOD_FCP_DUMP, + REIPL_METHOD_NSS, + REIPL_METHOD_DEFAULT, +}; + +enum dump_method { + DUMP_METHOD_NONE, + DUMP_METHOD_CCW_CIO, + DUMP_METHOD_CCW_DIAG, + DUMP_METHOD_CCW_VM, + DUMP_METHOD_FCP_DIAG, }; enum shutdown_action { @@ -107,15 +132,15 @@ static int diag308_set_works = 0; static int reipl_capabilities = IPL_TYPE_UNKNOWN; static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; -static enum ipl_method reipl_method = IPL_METHOD_NONE; +static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT; static struct ipl_parameter_block *reipl_block_fcp; static struct ipl_parameter_block *reipl_block_ccw; static char reipl_nss_name[NSS_NAME_SIZE + 1]; -static int dump_capabilities = IPL_TYPE_NONE; -static enum ipl_type dump_type = IPL_TYPE_NONE; -static enum ipl_method dump_method = IPL_METHOD_NONE; +static int dump_capabilities = DUMP_TYPE_NONE; +static enum dump_type dump_type = DUMP_TYPE_NONE; +static enum dump_method dump_method = DUMP_METHOD_NONE; static struct ipl_parameter_block *dump_block_fcp; static struct ipl_parameter_block *dump_block_ccw; @@ -134,6 +159,7 @@ int diag308(unsigned long subcode, void *addr) : "d" (subcode) : "cc", "memory"); return _rc; } +EXPORT_SYMBOL_GPL(diag308); /* SYSFS */ @@ -197,7 +223,7 @@ static void make_attrs_ro(struct attribute **attrs) * ipl section */ -static enum ipl_type ipl_get_type(void) +static __init enum ipl_type get_ipl_type(void) { struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; @@ -211,12 +237,44 @@ static enum ipl_type ipl_get_type(void) return IPL_TYPE_UNKNOWN; if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP) return IPL_TYPE_UNKNOWN; + if (ipl->ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP) + return IPL_TYPE_FCP_DUMP; return IPL_TYPE_FCP; } +void __init setup_ipl_info(void) +{ + ipl_info.type = get_ipl_type(); + switch (ipl_info.type) { + case IPL_TYPE_CCW: + ipl_info.data.ccw.dev_id.devno = ipl_devno; + ipl_info.data.ccw.dev_id.ssid = 0; + break; + case IPL_TYPE_FCP: + case IPL_TYPE_FCP_DUMP: + ipl_info.data.fcp.dev_id.devno = + IPL_PARMBLOCK_START->ipl_info.fcp.devno; + ipl_info.data.fcp.dev_id.ssid = 0; + ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn; + ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun; + break; + case IPL_TYPE_NSS: + strncpy(ipl_info.data.nss.name, kernel_nss_name, + sizeof(ipl_info.data.nss.name)); + break; + case IPL_TYPE_UNKNOWN: + default: + /* We have no info to copy */ + break; + } +} + +struct ipl_info ipl_info; +EXPORT_SYMBOL_GPL(ipl_info); + static ssize_t ipl_type_show(struct subsystem *subsys, char *page) { - return sprintf(page, "%s\n", ipl_type_str(ipl_get_type())); + return sprintf(page, "%s\n", ipl_type_str(ipl_info.type)); } static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); @@ -225,10 +283,11 @@ static ssize_t sys_ipl_device_show(struct subsystem *subsys, char *page) { struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; - switch (ipl_get_type()) { + switch (ipl_info.type) { case IPL_TYPE_CCW: return sprintf(page, "0.0.%04x\n", ipl_devno); case IPL_TYPE_FCP: + case IPL_TYPE_FCP_DUMP: return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno); default: return 0; @@ -485,23 +544,29 @@ static int reipl_set_type(enum ipl_type type) switch(type) { case IPL_TYPE_CCW: if (MACHINE_IS_VM) - reipl_method = IPL_METHOD_CCW_VM; + reipl_method = REIPL_METHOD_CCW_VM; else - reipl_method = IPL_METHOD_CCW_CIO; + reipl_method = REIPL_METHOD_CCW_CIO; break; case IPL_TYPE_FCP: if (diag308_set_works) - reipl_method = IPL_METHOD_FCP_RW_DIAG; + reipl_method = REIPL_METHOD_FCP_RW_DIAG; else if (MACHINE_IS_VM) - reipl_method = IPL_METHOD_FCP_RO_VM; + reipl_method = REIPL_METHOD_FCP_RO_VM; else - reipl_method = IPL_METHOD_FCP_RO_DIAG; + reipl_method = REIPL_METHOD_FCP_RO_DIAG; + break; + case IPL_TYPE_FCP_DUMP: + reipl_method = REIPL_METHOD_FCP_DUMP; break; case IPL_TYPE_NSS: - reipl_method = IPL_METHOD_NSS; + reipl_method = REIPL_METHOD_NSS; + break; + case IPL_TYPE_UNKNOWN: + reipl_method = REIPL_METHOD_DEFAULT; break; default: - reipl_method = IPL_METHOD_NONE; + BUG(); } reipl_type = type; return 0; @@ -579,22 +644,22 @@ static struct attribute_group dump_ccw_attr_group = { /* dump type */ -static int dump_set_type(enum ipl_type type) +static int dump_set_type(enum dump_type type) { if (!(dump_capabilities & type)) return -EINVAL; switch(type) { - case IPL_TYPE_CCW: + case DUMP_TYPE_CCW: if (MACHINE_IS_VM) - dump_method = IPL_METHOD_CCW_VM; + dump_method = DUMP_METHOD_CCW_VM; else - dump_method = IPL_METHOD_CCW_CIO; + dump_method = DUMP_METHOD_CCW_CIO; break; - case IPL_TYPE_FCP: - dump_method = IPL_METHOD_FCP_RW_DIAG; + case DUMP_TYPE_FCP: + dump_method = DUMP_METHOD_FCP_DIAG; break; default: - dump_method = IPL_METHOD_NONE; + dump_method = DUMP_METHOD_NONE; } dump_type = type; return 0; @@ -602,7 +667,7 @@ static int dump_set_type(enum ipl_type type) static ssize_t dump_type_show(struct subsystem *subsys, char *page) { - return sprintf(page, "%s\n", ipl_type_str(dump_type)); + return sprintf(page, "%s\n", dump_type_str(dump_type)); } static ssize_t dump_type_store(struct subsystem *subsys, const char *buf, @@ -610,12 +675,12 @@ static ssize_t dump_type_store(struct subsystem *subsys, const char *buf, { int rc = -EINVAL; - if (strncmp(buf, IPL_NONE_STR, strlen(IPL_NONE_STR)) == 0) - rc = dump_set_type(IPL_TYPE_NONE); - else if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0) - rc = dump_set_type(IPL_TYPE_CCW); - else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0) - rc = dump_set_type(IPL_TYPE_FCP); + if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0) + rc = dump_set_type(DUMP_TYPE_NONE); + else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0) + rc = dump_set_type(DUMP_TYPE_CCW); + else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0) + rc = dump_set_type(DUMP_TYPE_FCP); return (rc != 0) ? rc : len; } @@ -664,14 +729,14 @@ void do_reipl(void) char loadparm[LOADPARM_LEN + 1]; switch (reipl_method) { - case IPL_METHOD_CCW_CIO: + case REIPL_METHOD_CCW_CIO: devid.devno = reipl_block_ccw->ipl_info.ccw.devno; - if (ipl_get_type() == IPL_TYPE_CCW && devid.devno == ipl_devno) + if (ipl_info.type == IPL_TYPE_CCW && devid.devno == ipl_devno) diag308(DIAG308_IPL, NULL); devid.ssid = 0; reipl_ccw_dev(&devid); break; - case IPL_METHOD_CCW_VM: + case REIPL_METHOD_CCW_VM: reipl_get_ascii_loadparm(loadparm); if (strlen(loadparm) == 0) sprintf(buf, "IPL %X", @@ -681,30 +746,32 @@ void do_reipl(void) reipl_block_ccw->ipl_info.ccw.devno, loadparm); __cpcmd(buf, NULL, 0, NULL); break; - case IPL_METHOD_CCW_DIAG: + case REIPL_METHOD_CCW_DIAG: diag308(DIAG308_SET, reipl_block_ccw); diag308(DIAG308_IPL, NULL); break; - case IPL_METHOD_FCP_RW_DIAG: + case REIPL_METHOD_FCP_RW_DIAG: diag308(DIAG308_SET, reipl_block_fcp); diag308(DIAG308_IPL, NULL); break; - case IPL_METHOD_FCP_RO_DIAG: + case REIPL_METHOD_FCP_RO_DIAG: diag308(DIAG308_IPL, NULL); break; - case IPL_METHOD_FCP_RO_VM: + case REIPL_METHOD_FCP_RO_VM: __cpcmd("IPL", NULL, 0, NULL); break; - case IPL_METHOD_NSS: + case REIPL_METHOD_NSS: sprintf(buf, "IPL %s", reipl_nss_name); __cpcmd(buf, NULL, 0, NULL); break; - case IPL_METHOD_NONE: - default: + case REIPL_METHOD_DEFAULT: if (MACHINE_IS_VM) __cpcmd("IPL", NULL, 0, NULL); diag308(DIAG308_IPL, NULL); break; + case REIPL_METHOD_FCP_DUMP: + default: + break; } signal_processor(smp_processor_id(), sigp_stop_and_store_status); } @@ -715,28 +782,28 @@ static void do_dump(void) static char buf[100]; switch (dump_method) { - case IPL_METHOD_CCW_CIO: + case DUMP_METHOD_CCW_CIO: smp_send_stop(); devid.devno = dump_block_ccw->ipl_info.ccw.devno; devid.ssid = 0; reipl_ccw_dev(&devid); break; - case IPL_METHOD_CCW_VM: + case DUMP_METHOD_CCW_VM: smp_send_stop(); sprintf(buf, "STORE STATUS"); __cpcmd(buf, NULL, 0, NULL); sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno); __cpcmd(buf, NULL, 0, NULL); break; - case IPL_METHOD_CCW_DIAG: + case DUMP_METHOD_CCW_DIAG: diag308(DIAG308_SET, dump_block_ccw); diag308(DIAG308_DUMP, NULL); break; - case IPL_METHOD_FCP_RW_DIAG: + case DUMP_METHOD_FCP_DIAG: diag308(DIAG308_SET, dump_block_fcp); diag308(DIAG308_DUMP, NULL); break; - case IPL_METHOD_NONE: + case DUMP_METHOD_NONE: default: return; } @@ -777,12 +844,13 @@ static int __init ipl_init(void) rc = firmware_register(&ipl_subsys); if (rc) return rc; - switch (ipl_get_type()) { + switch (ipl_info.type) { case IPL_TYPE_CCW: rc = sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_ccw_attr_group); break; case IPL_TYPE_FCP: + case IPL_TYPE_FCP_DUMP: rc = ipl_register_fcp_files(); break; case IPL_TYPE_NSS: @@ -852,7 +920,7 @@ static int __init reipl_ccw_init(void) /* FIXME: check for diag308_set_works when enabling diag ccw reipl */ if (!MACHINE_IS_VM) sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO; - if (ipl_get_type() == IPL_TYPE_CCW) + if (ipl_info.type == IPL_TYPE_CCW) reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; reipl_capabilities |= IPL_TYPE_CCW; return 0; @@ -862,9 +930,9 @@ static int __init reipl_fcp_init(void) { int rc; - if ((!diag308_set_works) && (ipl_get_type() != IPL_TYPE_FCP)) + if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP)) return 0; - if ((!diag308_set_works) && (ipl_get_type() == IPL_TYPE_FCP)) + if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP)) make_attrs_ro(reipl_fcp_attrs); reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); @@ -875,7 +943,7 @@ static int __init reipl_fcp_init(void) free_page((unsigned long)reipl_block_fcp); return rc; } - if (ipl_get_type() == IPL_TYPE_FCP) { + if (ipl_info.type == IPL_TYPE_FCP) { memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE); } else { reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN; @@ -909,7 +977,7 @@ static int __init reipl_init(void) rc = reipl_nss_init(); if (rc) return rc; - rc = reipl_set_type(ipl_get_type()); + rc = reipl_set_type(ipl_info.type); if (rc) return rc; return 0; @@ -931,7 +999,7 @@ static int __init dump_ccw_init(void) dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; - dump_capabilities |= IPL_TYPE_CCW; + dump_capabilities |= DUMP_TYPE_CCW; return 0; } @@ -956,7 +1024,7 @@ static int __init dump_fcp_init(void) dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN; dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP; dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP; - dump_capabilities |= IPL_TYPE_FCP; + dump_capabilities |= DUMP_TYPE_FCP; return 0; } @@ -995,7 +1063,7 @@ static int __init dump_init(void) rc = dump_fcp_init(); if (rc) return rc; - dump_set_type(IPL_TYPE_NONE); + dump_set_type(DUMP_TYPE_NONE); return 0; } @@ -1038,6 +1106,27 @@ static int __init s390_ipl_init(void) __initcall(s390_ipl_init); +void __init ipl_save_parameters(void) +{ + struct cio_iplinfo iplinfo; + unsigned int *ipl_ptr; + void *src, *dst; + + if (cio_get_iplinfo(&iplinfo)) + return; + + ipl_devno = iplinfo.devno; + ipl_flags |= IPL_DEVNO_VALID; + if (!iplinfo.is_qdio) + return; + ipl_flags |= IPL_PARMBLOCK_VALID; + ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR; + src = (void *)(unsigned long)*ipl_ptr; + dst = (void *)IPL_PARMBLOCK_ORIGIN; + memmove(dst, src, PAGE_SIZE); + *ipl_ptr = IPL_PARMBLOCK_ORIGIN; +} + static LIST_HEAD(rcall); static DEFINE_MUTEX(rcall_mutex); diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 993f3538149..23c61f6d965 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c @@ -516,7 +516,7 @@ out: return 1; } -static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) +int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); @@ -603,7 +603,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_TRAP: - case DIE_PAGE_FAULT: /* kprobe_running() needs smp_processor_id() */ preempt_disable(); if (kprobe_running() && diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 39d1dd75252..59b4e796680 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -31,6 +31,7 @@ #include <linux/string.h> #include <linux/kernel.h> #include <linux/moduleloader.h> +#include <linux/bug.h> #if 0 #define DEBUGP printk @@ -398,9 +399,10 @@ int module_finalize(const Elf_Ehdr *hdr, struct module *me) { vfree(me->arch.syminfo); - return 0; + return module_bug_finalize(hdr, sechdrs, me); } void module_arch_cleanup(struct module *mod) { + module_bug_cleanup(mod); } diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 5acfac654f9..11d9b019762 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -280,24 +280,26 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, return 0; } -asmlinkage long sys_fork(struct pt_regs regs) +asmlinkage long sys_fork(void) { - return do_fork(SIGCHLD, regs.gprs[15], ®s, 0, NULL, NULL); + struct pt_regs *regs = task_pt_regs(current); + return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); } -asmlinkage long sys_clone(struct pt_regs regs) +asmlinkage long sys_clone(void) { - unsigned long clone_flags; - unsigned long newsp; + struct pt_regs *regs = task_pt_regs(current); + unsigned long clone_flags; + unsigned long newsp; int __user *parent_tidptr, *child_tidptr; - clone_flags = regs.gprs[3]; - newsp = regs.orig_gpr2; - parent_tidptr = (int __user *) regs.gprs[4]; - child_tidptr = (int __user *) regs.gprs[5]; - if (!newsp) - newsp = regs.gprs[15]; - return do_fork(clone_flags, newsp, ®s, 0, + clone_flags = regs->gprs[3]; + newsp = regs->orig_gpr2; + parent_tidptr = (int __user *) regs->gprs[4]; + child_tidptr = (int __user *) regs->gprs[5]; + if (!newsp) + newsp = regs->gprs[15]; + return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } @@ -311,40 +313,52 @@ asmlinkage long sys_clone(struct pt_regs regs) * do not have enough call-clobbered registers to hold all * the information you need. */ -asmlinkage long sys_vfork(struct pt_regs regs) +asmlinkage long sys_vfork(void) { + struct pt_regs *regs = task_pt_regs(current); return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, - regs.gprs[15], ®s, 0, NULL, NULL); + regs->gprs[15], regs, 0, NULL, NULL); +} + +asmlinkage void execve_tail(void) +{ + task_lock(current); + current->ptrace &= ~PT_DTRACE; + task_unlock(current); + current->thread.fp_regs.fpc = 0; + if (MACHINE_HAS_IEEE) + asm volatile("sfpc %0,%0" : : "d" (0)); } /* * sys_execve() executes a new program. */ -asmlinkage long sys_execve(struct pt_regs regs) +asmlinkage long sys_execve(void) { - int error; - char * filename; - - filename = getname((char __user *) regs.orig_gpr2); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename, (char __user * __user *) regs.gprs[3], - (char __user * __user *) regs.gprs[4], ®s); - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - current->thread.fp_regs.fpc = 0; - if (MACHINE_HAS_IEEE) - asm volatile("sfpc %0,%0" : : "d" (0)); + struct pt_regs *regs = task_pt_regs(current); + char *filename; + unsigned long result; + int rc; + + filename = getname((char __user *) regs->orig_gpr2); + if (IS_ERR(filename)) { + result = PTR_ERR(filename); + goto out; } - putname(filename); + rc = do_execve(filename, (char __user * __user *) regs->gprs[3], + (char __user * __user *) regs->gprs[4], regs); + if (rc) { + result = rc; + goto out_putname; + } + execve_tail(); + result = regs->gprs[2]; +out_putname: + putname(filename); out: - return error; + return result; } - /* * fill in the FPU structure for a core dump. */ diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 863c8d08c02..6bfb0889eb1 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -65,7 +65,7 @@ long psw_user_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | * User copy operations. */ struct uaccess_ops uaccess; -EXPORT_SYMBOL_GPL(uaccess); +EXPORT_SYMBOL(uaccess); /* * Machine setup.. @@ -74,6 +74,8 @@ unsigned int console_mode = 0; unsigned int console_devno = -1; unsigned int console_irq = -1; unsigned long machine_flags = 0; +unsigned long elf_hwcap = 0; +char elf_platform[ELF_PLATFORM_SIZE]; struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS]; volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ @@ -285,6 +287,26 @@ static void __init conmode_default(void) } } +#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) +static void __init setup_zfcpdump(unsigned int console_devno) +{ + static char str[64]; + + if (ipl_info.type != IPL_TYPE_FCP_DUMP) + return; + if (console_devno != -1) + sprintf(str, "cio_ignore=all,!0.0.%04x,!0.0.%04x", + ipl_info.data.fcp.dev_id.devno, console_devno); + else + sprintf(str, "cio_ignore=all,!0.0.%04x", + ipl_info.data.fcp.dev_id.devno); + strcat(COMMAND_LINE, str); + console_loglevel = 2; +} +#else +static inline void setup_zfcpdump(unsigned int console_devno) {} +#endif /* CONFIG_ZFCPDUMP */ + #ifdef CONFIG_SMP void (*_machine_restart)(char *command) = machine_restart_smp; void (*_machine_halt)(void) = machine_halt_smp; @@ -586,13 +608,20 @@ setup_resources(void) } } +unsigned long real_memory_size; +EXPORT_SYMBOL_GPL(real_memory_size); + static void __init setup_memory_end(void) { - unsigned long real_size, memory_size; + unsigned long memory_size; unsigned long max_mem, max_phys; int i; - memory_size = real_size = 0; +#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) + if (ipl_info.type == IPL_TYPE_FCP_DUMP) + memory_end = ZFCPDUMP_HSA_SIZE; +#endif + memory_size = 0; max_phys = VMALLOC_END_INIT - VMALLOC_MIN_SIZE; memory_end &= PAGE_MASK; @@ -601,7 +630,8 @@ static void __init setup_memory_end(void) for (i = 0; i < MEMORY_CHUNKS; i++) { struct mem_chunk *chunk = &memory_chunk[i]; - real_size = max(real_size, chunk->addr + chunk->size); + real_memory_size = max(real_memory_size, + chunk->addr + chunk->size); if (chunk->addr >= max_mem) { memset(chunk, 0, sizeof(*chunk)); continue; @@ -721,6 +751,98 @@ setup_memory(void) #endif } +static __init unsigned int stfl(void) +{ + asm volatile( + " .insn s,0xb2b10000,0(0)\n" /* stfl */ + "0:\n" + EX_TABLE(0b,0b)); + return S390_lowcore.stfl_fac_list; +} + +static __init int stfle(unsigned long long *list, int doublewords) +{ + typedef struct { unsigned long long _[doublewords]; } addrtype; + register unsigned long __nr asm("0") = doublewords - 1; + + asm volatile(".insn s,0xb2b00000,%0" /* stfle */ + : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc"); + return __nr + 1; +} + +/* + * Setup hardware capabilities. + */ +static void __init setup_hwcaps(void) +{ + static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; + struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; + unsigned long long facility_list_extended; + unsigned int facility_list; + int i; + + facility_list = stfl(); + /* + * The store facility list bits numbers as found in the principles + * of operation are numbered with bit 1UL<<31 as number 0 to + * bit 1UL<<0 as number 31. + * Bit 0: instructions named N3, "backported" to esa-mode + * Bit 2: z/Architecture mode is active + * Bit 7: the store-facility-list-extended facility is installed + * Bit 17: the message-security assist is installed + * Bit 19: the long-displacement facility is installed + * Bit 21: the extended-immediate facility is installed + * These get translated to: + * HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1, + * HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3, + * HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5. + */ + for (i = 0; i < 6; i++) + if (facility_list & (1UL << (31 - stfl_bits[i]))) + elf_hwcap |= 1UL << i; + + /* + * Check for additional facilities with store-facility-list-extended. + * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0 + * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information + * as stored by stfl, bits 32-xxx contain additional facilities. + * How many facility words are stored depends on the number of + * doublewords passed to the instruction. The additional facilites + * are: + * Bit 43: decimal floating point facility is installed + * translated to: + * HWCAP_S390_DFP bit 6. + */ + if ((elf_hwcap & (1UL << 2)) && + stfle(&facility_list_extended, 1) > 0) { + if (facility_list_extended & (1ULL << (64 - 43))) + elf_hwcap |= 1UL << 6; + } + + switch (cpuinfo->cpu_id.machine) { + case 0x9672: +#if !defined(CONFIG_64BIT) + default: /* Use "g5" as default for 31 bit kernels. */ +#endif + strcpy(elf_platform, "g5"); + break; + case 0x2064: + case 0x2066: +#if defined(CONFIG_64BIT) + default: /* Use "z900" as default for 64 bit kernels. */ +#endif + strcpy(elf_platform, "z900"); + break; + case 0x2084: + case 0x2086: + strcpy(elf_platform, "z990"); + break; + case 0x2094: + strcpy(elf_platform, "z9-109"); + break; + } +} + /* * Setup function called from init/main.c just after the banner * was printed. @@ -765,6 +887,7 @@ setup_arch(char **cmdline_p) parse_early_param(); + setup_ipl_info(); setup_memory_end(); setup_addressing_mode(); setup_memory(); @@ -776,12 +899,20 @@ setup_arch(char **cmdline_p) smp_setup_cpu_possible_map(); /* + * Setup capabilities (ELF_HWCAP & ELF_PLATFORM). + */ + setup_hwcaps(); + + /* * Create kernel page tables and switch to virtual addressing. */ paging_init(); /* Setup default console */ conmode_default(); + + /* Setup zfcpdump support */ + setup_zfcpdump(console_devno); } void print_cpu_info(struct cpuinfo_S390 *cpuinfo) @@ -807,8 +938,12 @@ void print_cpu_info(struct cpuinfo_S390 *cpuinfo) static int show_cpuinfo(struct seq_file *m, void *v) { + static const char *hwcap_str[7] = { + "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp" + }; struct cpuinfo_S390 *cpuinfo; unsigned long n = (unsigned long) v - 1; + int i; s390_adjust_jiffies(); preempt_disable(); @@ -818,7 +953,13 @@ static int show_cpuinfo(struct seq_file *m, void *v) "bogomips per cpu: %lu.%02lu\n", num_online_cpus(), loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ))%100); + seq_puts(m, "features\t: "); + for (i = 0; i < 7; i++) + if (hwcap_str[i] && (elf_hwcap & (1UL << i))) + seq_printf(m, "%s ", hwcap_str[i]); + seq_puts(m, "\n"); } + if (cpu_online(n)) { #ifdef CONFIG_SMP if (smp_processor_id() == n) diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 554f9cf7499..3c41907799a 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -102,9 +102,9 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, } asmlinkage long -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, - struct pt_regs *regs) +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { + struct pt_regs *regs = task_pt_regs(current); return do_sigaltstack(uss, uoss, regs->gprs[15]); } @@ -163,8 +163,9 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) return 0; } -asmlinkage long sys_sigreturn(struct pt_regs *regs) +asmlinkage long sys_sigreturn(void) { + struct pt_regs *regs = task_pt_regs(current); sigframe __user *frame = (sigframe __user *)regs->gprs[15]; sigset_t set; @@ -189,8 +190,9 @@ badframe: return 0; } -asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) +asmlinkage long sys_rt_sigreturn(void) { + struct pt_regs *regs = task_pt_regs(current); rt_sigframe __user *frame = (rt_sigframe __user *)regs->gprs[15]; sigset_t set; diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 97764f710bb..3754e2031b3 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -1,12 +1,12 @@ /* * arch/s390/kernel/smp.c * - * Copyright (C) IBM Corp. 1999,2006 + * Copyright IBM Corp. 1999,2007 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), - * Martin Schwidefsky (schwidefsky@de.ibm.com) - * Heiko Carstens (heiko.carstens@de.ibm.com) + * Martin Schwidefsky (schwidefsky@de.ibm.com) + * Heiko Carstens (heiko.carstens@de.ibm.com) * - * based on other smp stuff by + * based on other smp stuff by * (c) 1995 Alan Cox, CymruNET Ltd <alan@cymru.net> * (c) 1998 Ingo Molnar * @@ -31,6 +31,7 @@ #include <linux/interrupt.h> #include <linux/cpu.h> #include <linux/timex.h> +#include <linux/bootmem.h> #include <asm/ipl.h> #include <asm/setup.h> #include <asm/sigp.h> @@ -40,17 +41,19 @@ #include <asm/cpcmd.h> #include <asm/tlbflush.h> #include <asm/timer.h> - -extern volatile int __cpu_logical_map[]; +#include <asm/lowcore.h> /* * An array with a pointer the lowcore of every CPU. */ - struct _lowcore *lowcore_ptr[NR_CPUS]; +EXPORT_SYMBOL(lowcore_ptr); cpumask_t cpu_online_map = CPU_MASK_NONE; +EXPORT_SYMBOL(cpu_online_map); + cpumask_t cpu_possible_map = CPU_MASK_NONE; +EXPORT_SYMBOL(cpu_possible_map); static struct task_struct *current_set[NR_CPUS]; @@ -70,7 +73,7 @@ struct call_data_struct { int wait; }; -static struct call_data_struct * call_data; +static struct call_data_struct *call_data; /* * 'Call function' interrupt callback @@ -150,8 +153,8 @@ out: * * Run a function on all other CPUs. * - * You must not call this function with disabled interrupts or from a - * hardware interrupt handler. You may call it from a bottom half. + * You must not call this function with disabled interrupts, from a + * hardware interrupt handler or from a bottom half. */ int smp_call_function(void (*func) (void *info), void *info, int nonatomic, int wait) @@ -177,11 +180,11 @@ EXPORT_SYMBOL(smp_call_function); * * Run a function on one processor. * - * You must not call this function with disabled interrupts or from a - * hardware interrupt handler. You may call it from a bottom half. + * You must not call this function with disabled interrupts, from a + * hardware interrupt handler or from a bottom half. */ int smp_call_function_on(void (*func) (void *info), void *info, int nonatomic, - int wait, int cpu) + int wait, int cpu) { cpumask_t map = CPU_MASK_NONE; @@ -195,9 +198,9 @@ EXPORT_SYMBOL(smp_call_function_on); static void do_send_stop(void) { - int cpu, rc; + int cpu, rc; - /* stop all processors */ + /* stop all processors */ for_each_online_cpu(cpu) { if (cpu == smp_processor_id()) continue; @@ -209,9 +212,9 @@ static void do_send_stop(void) static void do_store_status(void) { - int cpu, rc; + int cpu, rc; - /* store status of all processors in their lowcores (real 0) */ + /* store status of all processors in their lowcores (real 0) */ for_each_online_cpu(cpu) { if (cpu == smp_processor_id()) continue; @@ -219,8 +222,8 @@ static void do_store_status(void) rc = signal_processor_p( (__u32)(unsigned long) lowcore_ptr[cpu], cpu, sigp_store_status_at_address); - } while(rc == sigp_busy); - } + } while (rc == sigp_busy); + } } static void do_wait_for_stop(void) @@ -231,7 +234,7 @@ static void do_wait_for_stop(void) for_each_online_cpu(cpu) { if (cpu == smp_processor_id()) continue; - while(!smp_cpu_not_running(cpu)) + while (!smp_cpu_not_running(cpu)) cpu_relax(); } } @@ -245,7 +248,7 @@ void smp_send_stop(void) /* Disable all interrupts/machine checks */ __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); - /* write magic number to zero page (absolute 0) */ + /* write magic number to zero page (absolute 0) */ lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; /* stop other processors. */ @@ -261,8 +264,7 @@ void smp_send_stop(void) /* * Reboot, halt and power_off routines for SMP. */ - -void machine_restart_smp(char * __unused) +void machine_restart_smp(char *__unused) { smp_send_stop(); do_reipl(); @@ -293,17 +295,17 @@ void machine_power_off_smp(void) static void do_ext_call_interrupt(__u16 code) { - unsigned long bits; + unsigned long bits; - /* - * handle bit signal external calls - * - * For the ec_schedule signal we have to do nothing. All the work - * is done automatically when we return from the interrupt. - */ + /* + * handle bit signal external calls + * + * For the ec_schedule signal we have to do nothing. All the work + * is done automatically when we return from the interrupt. + */ bits = xchg(&S390_lowcore.ext_call_fast, 0); - if (test_bit(ec_call_function, &bits)) + if (test_bit(ec_call_function, &bits)) do_call_function(); } @@ -313,11 +315,11 @@ static void do_ext_call_interrupt(__u16 code) */ static void smp_ext_bitcall(int cpu, ec_bit_sig sig) { - /* - * Set signaling bit in lowcore of target cpu and kick it - */ + /* + * Set signaling bit in lowcore of target cpu and kick it + */ set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast); - while(signal_processor(cpu, sigp_emergency_signal) == sigp_busy) + while (signal_processor(cpu, sigp_emergency_signal) == sigp_busy) udelay(10); } @@ -332,7 +334,7 @@ void smp_ptlb_callback(void *info) void smp_ptlb_all(void) { - on_each_cpu(smp_ptlb_callback, NULL, 0, 1); + on_each_cpu(smp_ptlb_callback, NULL, 0, 1); } EXPORT_SYMBOL(smp_ptlb_all); #endif /* ! CONFIG_64BIT */ @@ -344,7 +346,7 @@ EXPORT_SYMBOL(smp_ptlb_all); */ void smp_send_reschedule(int cpu) { - smp_ext_bitcall(cpu, ec_schedule); + smp_ext_bitcall(cpu, ec_schedule); } /* @@ -358,11 +360,12 @@ struct ec_creg_mask_parms { /* * callback for setting/clearing control bits */ -static void smp_ctl_bit_callback(void *info) { +static void smp_ctl_bit_callback(void *info) +{ struct ec_creg_mask_parms *pp = info; unsigned long cregs[16]; int i; - + __ctl_store(cregs, 0, 15); for (i = 0; i <= 15; i++) cregs[i] = (cregs[i] & pp->andvals[i]) | pp->orvals[i]; @@ -381,6 +384,7 @@ void smp_ctl_set_bit(int cr, int bit) parms.orvals[cr] = 1 << bit; on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1); } +EXPORT_SYMBOL(smp_ctl_set_bit); /* * Clear a bit in a control register of all cpus @@ -394,13 +398,72 @@ void smp_ctl_clear_bit(int cr, int bit) parms.andvals[cr] = ~(1L << bit); on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1); } +EXPORT_SYMBOL(smp_ctl_clear_bit); + +#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) + +/* + * zfcpdump_prefix_array holds prefix registers for the following scenario: + * 64 bit zfcpdump kernel and 31 bit kernel which is to be dumped. We have to + * save its prefix registers, since they get lost, when switching from 31 bit + * to 64 bit. + */ +unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \ + __attribute__((__section__(".data"))); + +static void __init smp_get_save_areas(void) +{ + unsigned int cpu, cpu_num, rc; + __u16 boot_cpu_addr; + + if (ipl_info.type != IPL_TYPE_FCP_DUMP) + return; + boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; + cpu_num = 1; + for (cpu = 0; cpu <= 65535; cpu++) { + if ((u16) cpu == boot_cpu_addr) + continue; + __cpu_logical_map[1] = (__u16) cpu; + if (signal_processor(1, sigp_sense) == sigp_not_operational) + continue; + if (cpu_num >= NR_CPUS) { + printk("WARNING: Registers for cpu %i are not " + "saved, since dump kernel was compiled with" + "NR_CPUS=%i!\n", cpu_num, NR_CPUS); + continue; + } + zfcpdump_save_areas[cpu_num] = + alloc_bootmem(sizeof(union save_area)); + while (1) { + rc = signal_processor(1, sigp_stop_and_store_status); + if (rc != sigp_busy) + break; + cpu_relax(); + } + memcpy(zfcpdump_save_areas[cpu_num], + (void *)(unsigned long) store_prefix() + + SAVE_AREA_BASE, SAVE_AREA_SIZE); +#ifdef __s390x__ + /* copy original prefix register */ + zfcpdump_save_areas[cpu_num]->s390x.pref_reg = + zfcpdump_prefix_array[cpu_num]; +#endif + cpu_num++; + } +} + +union save_area *zfcpdump_save_areas[NR_CPUS + 1]; +EXPORT_SYMBOL_GPL(zfcpdump_save_areas); + +#else +#define smp_get_save_areas() do { } while (0) +#endif /* * Lets check how many CPUs we have. */ -static unsigned int -__init smp_count_cpus(void) +static unsigned int __init smp_count_cpus(void) { unsigned int cpu, num_cpus; __u16 boot_cpu_addr; @@ -416,31 +479,30 @@ __init smp_count_cpus(void) if ((__u16) cpu == boot_cpu_addr) continue; __cpu_logical_map[1] = (__u16) cpu; - if (signal_processor(1, sigp_sense) == - sigp_not_operational) + if (signal_processor(1, sigp_sense) == sigp_not_operational) continue; num_cpus++; } - printk("Detected %d CPU's\n",(int) num_cpus); + printk("Detected %d CPU's\n", (int) num_cpus); printk("Boot cpu address %2X\n", boot_cpu_addr); return num_cpus; } /* - * Activate a secondary processor. + * Activate a secondary processor. */ int __devinit start_secondary(void *cpuvoid) { - /* Setup the cpu */ - cpu_init(); + /* Setup the cpu */ + cpu_init(); preempt_disable(); /* Enable TOD clock interrupts on the secondary cpu. */ - init_cpu_timer(); + init_cpu_timer(); #ifdef CONFIG_VIRT_TIMER /* Enable cpu timer interrupts on the secondary cpu. */ - init_cpu_vtimer(); + init_cpu_vtimer(); #endif /* Enable pfault pseudo page faults on this cpu. */ pfault_init(); @@ -449,11 +511,11 @@ int __devinit start_secondary(void *cpuvoid) cpu_set(smp_processor_id(), cpu_online_map); /* Switch on interrupts */ local_irq_enable(); - /* Print info about this processor */ - print_cpu_info(&S390_lowcore.cpu_data); - /* cpu_idle will call schedule for us */ - cpu_idle(); - return 0; + /* Print info about this processor */ + print_cpu_info(&S390_lowcore.cpu_data); + /* cpu_idle will call schedule for us */ + cpu_idle(); + return 0; } static void __init smp_create_idle(unsigned int cpu) @@ -470,56 +532,13 @@ static void __init smp_create_idle(unsigned int cpu) current_set[cpu] = p; } -/* Reserving and releasing of CPUs */ - -static DEFINE_SPINLOCK(smp_reserve_lock); -static int smp_cpu_reserved[NR_CPUS]; - -int -smp_get_cpu(cpumask_t cpu_mask) -{ - unsigned long flags; - int cpu; - - spin_lock_irqsave(&smp_reserve_lock, flags); - /* Try to find an already reserved cpu. */ - for_each_cpu_mask(cpu, cpu_mask) { - if (smp_cpu_reserved[cpu] != 0) { - smp_cpu_reserved[cpu]++; - /* Found one. */ - goto out; - } - } - /* Reserve a new cpu from cpu_mask. */ - for_each_cpu_mask(cpu, cpu_mask) { - if (cpu_online(cpu)) { - smp_cpu_reserved[cpu]++; - goto out; - } - } - cpu = -ENODEV; -out: - spin_unlock_irqrestore(&smp_reserve_lock, flags); - return cpu; -} - -void -smp_put_cpu(int cpu) -{ - unsigned long flags; - - spin_lock_irqsave(&smp_reserve_lock, flags); - smp_cpu_reserved[cpu]--; - spin_unlock_irqrestore(&smp_reserve_lock, flags); -} - -static int -cpu_stopped(int cpu) +static int cpu_stopped(int cpu) { __u32 status; /* Check for stopped state */ - if (signal_processor_ps(&status, 0, cpu, sigp_sense) == sigp_status_stored) { + if (signal_processor_ps(&status, 0, cpu, sigp_sense) == + sigp_status_stored) { if (status & 0x40) return 1; } @@ -528,14 +547,13 @@ cpu_stopped(int cpu) /* Upping and downing of CPUs */ -int -__cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { struct task_struct *idle; - struct _lowcore *cpu_lowcore; + struct _lowcore *cpu_lowcore; struct stack_frame *sf; - sigp_ccode ccode; - int curr_cpu; + sigp_ccode ccode; + int curr_cpu; for (curr_cpu = 0; curr_cpu <= 65535; curr_cpu++) { __cpu_logical_map[cpu] = (__u16) curr_cpu; @@ -548,7 +566,7 @@ __cpu_up(unsigned int cpu) ccode = signal_processor_p((__u32)(unsigned long)(lowcore_ptr[cpu]), cpu, sigp_set_prefix); - if (ccode){ + if (ccode) { printk("sigp_set_prefix failed for cpu %d " "with condition code %d\n", (int) cpu, (int) ccode); @@ -556,9 +574,9 @@ __cpu_up(unsigned int cpu) } idle = current_set[cpu]; - cpu_lowcore = lowcore_ptr[cpu]; + cpu_lowcore = lowcore_ptr[cpu]; cpu_lowcore->kernel_stack = (unsigned long) - task_stack_page(idle) + (THREAD_SIZE); + task_stack_page(idle) + THREAD_SIZE; sf = (struct stack_frame *) (cpu_lowcore->kernel_stack - sizeof(struct pt_regs) - sizeof(struct stack_frame)); @@ -570,11 +588,11 @@ __cpu_up(unsigned int cpu) " stam 0,15,0(%0)" : : "a" (&cpu_lowcore->access_regs_save_area) : "memory"); cpu_lowcore->percpu_offset = __per_cpu_offset[cpu]; - cpu_lowcore->current_task = (unsigned long) idle; - cpu_lowcore->cpu_data.cpu_nr = cpu; + cpu_lowcore->current_task = (unsigned long) idle; + cpu_lowcore->cpu_data.cpu_nr = cpu; eieio(); - while (signal_processor(cpu,sigp_restart) == sigp_busy) + while (signal_processor(cpu, sigp_restart) == sigp_busy) udelay(10); while (!cpu_online(cpu)) @@ -589,6 +607,7 @@ void __init smp_setup_cpu_possible_map(void) { unsigned int phy_cpus, pos_cpus, cpu; + smp_get_save_areas(); phy_cpus = smp_count_cpus(); pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS); @@ -620,18 +639,11 @@ static int __init setup_possible_cpus(char *s) } early_param("possible_cpus", setup_possible_cpus); -int -__cpu_disable(void) +int __cpu_disable(void) { - unsigned long flags; struct ec_creg_mask_parms cr_parms; int cpu = smp_processor_id(); - spin_lock_irqsave(&smp_reserve_lock, flags); - if (smp_cpu_reserved[cpu] != 0) { - spin_unlock_irqrestore(&smp_reserve_lock, flags); - return -EBUSY; - } cpu_clear(cpu, cpu_online_map); /* Disable pfault pseudo page faults on this cpu. */ @@ -642,24 +654,23 @@ __cpu_disable(void) /* disable all external interrupts */ cr_parms.orvals[0] = 0; - cr_parms.andvals[0] = ~(1<<15 | 1<<14 | 1<<13 | 1<<12 | - 1<<11 | 1<<10 | 1<< 6 | 1<< 4); + cr_parms.andvals[0] = ~(1 << 15 | 1 << 14 | 1 << 13 | 1 << 12 | + 1 << 11 | 1 << 10 | 1 << 6 | 1 << 4); /* disable all I/O interrupts */ cr_parms.orvals[6] = 0; - cr_parms.andvals[6] = ~(1<<31 | 1<<30 | 1<<29 | 1<<28 | - 1<<27 | 1<<26 | 1<<25 | 1<<24); + cr_parms.andvals[6] = ~(1 << 31 | 1 << 30 | 1 << 29 | 1 << 28 | + 1 << 27 | 1 << 26 | 1 << 25 | 1 << 24); /* disable most machine checks */ cr_parms.orvals[14] = 0; - cr_parms.andvals[14] = ~(1<<28 | 1<<27 | 1<<26 | 1<<25 | 1<<24); + cr_parms.andvals[14] = ~(1 << 28 | 1 << 27 | 1 << 26 | + 1 << 25 | 1 << 24); smp_ctl_bit_callback(&cr_parms); - spin_unlock_irqrestore(&smp_reserve_lock, flags); return 0; } -void -__cpu_die(unsigned int cpu) +void __cpu_die(unsigned int cpu) { /* Wait until target cpu is down */ while (!smp_cpu_not_running(cpu)) @@ -667,13 +678,12 @@ __cpu_die(unsigned int cpu) printk("Processor %d spun down\n", cpu); } -void -cpu_die(void) +void cpu_die(void) { idle_task_exit(); signal_processor(smp_processor_id(), sigp_stop); BUG(); - for(;;); + for (;;); } #endif /* CONFIG_HOTPLUG_CPU */ @@ -686,36 +696,36 @@ void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned long stack; unsigned int cpu; - int i; - - /* request the 0x1201 emergency signal external interrupt */ - if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) - panic("Couldn't request external interrupt 0x1201"); - memset(lowcore_ptr,0,sizeof(lowcore_ptr)); - /* - * Initialize prefix pages and stacks for all possible cpus - */ + int i; + + /* request the 0x1201 emergency signal external interrupt */ + if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) + panic("Couldn't request external interrupt 0x1201"); + memset(lowcore_ptr, 0, sizeof(lowcore_ptr)); + /* + * Initialize prefix pages and stacks for all possible cpus + */ print_cpu_info(&S390_lowcore.cpu_data); - for_each_possible_cpu(i) { + for_each_possible_cpu(i) { lowcore_ptr[i] = (struct _lowcore *) - __get_free_pages(GFP_KERNEL|GFP_DMA, - sizeof(void*) == 8 ? 1 : 0); - stack = __get_free_pages(GFP_KERNEL,ASYNC_ORDER); - if (lowcore_ptr[i] == NULL || stack == 0ULL) + __get_free_pages(GFP_KERNEL | GFP_DMA, + sizeof(void*) == 8 ? 1 : 0); + stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); + if (!lowcore_ptr[i] || !stack) panic("smp_boot_cpus failed to allocate memory\n"); *(lowcore_ptr[i]) = S390_lowcore; - lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE); - stack = __get_free_pages(GFP_KERNEL,0); - if (stack == 0ULL) + lowcore_ptr[i]->async_stack = stack + ASYNC_SIZE; + stack = __get_free_pages(GFP_KERNEL, 0); + if (!stack) panic("smp_boot_cpus failed to allocate memory\n"); - lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE); + lowcore_ptr[i]->panic_stack = stack + PAGE_SIZE; #ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) { lowcore_ptr[i]->extended_save_area_addr = - (__u32) __get_free_pages(GFP_KERNEL,0); - if (lowcore_ptr[i]->extended_save_area_addr == 0) + (__u32) __get_free_pages(GFP_KERNEL, 0); + if (!lowcore_ptr[i]->extended_save_area_addr) panic("smp_boot_cpus failed to " "allocate memory\n"); } @@ -754,34 +764,63 @@ void smp_cpus_done(unsigned int max_cpus) */ int setup_profiling_timer(unsigned int multiplier) { - return 0; + return 0; } static DEFINE_PER_CPU(struct cpu, cpu_devices); +static ssize_t show_capability(struct sys_device *dev, char *buf) +{ + unsigned int capability; + int rc; + + rc = get_cpu_capability(&capability); + if (rc) + return rc; + return sprintf(buf, "%u\n", capability); +} +static SYSDEV_ATTR(capability, 0444, show_capability, NULL); + +static int __cpuinit smp_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned int)(long)hcpu; + struct cpu *c = &per_cpu(cpu_devices, cpu); + struct sys_device *s = &c->sysdev; + + switch (action) { + case CPU_ONLINE: + if (sysdev_create_file(s, &attr_capability)) + return NOTIFY_BAD; + break; + case CPU_DEAD: + sysdev_remove_file(s, &attr_capability); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block __cpuinitdata smp_cpu_nb = { + .notifier_call = smp_cpu_notify, +}; + static int __init topology_init(void) { int cpu; - int ret; + + register_cpu_notifier(&smp_cpu_nb); for_each_possible_cpu(cpu) { struct cpu *c = &per_cpu(cpu_devices, cpu); + struct sys_device *s = &c->sysdev; c->hotpluggable = 1; - ret = register_cpu(c, cpu); - if (ret) - printk(KERN_WARNING "topology_init: register_cpu %d " - "failed (%d)\n", cpu, ret); + register_cpu(c, cpu); + if (!cpu_online(cpu)) + continue; + s = &c->sysdev; + sysdev_create_file(s, &attr_capability); } return 0; } - subsys_initcall(topology_init); - -EXPORT_SYMBOL(cpu_online_map); -EXPORT_SYMBOL(cpu_possible_map); -EXPORT_SYMBOL(lowcore_ptr); -EXPORT_SYMBOL(smp_ctl_set_bit); -EXPORT_SYMBOL(smp_ctl_clear_bit); -EXPORT_SYMBOL(smp_get_cpu); -EXPORT_SYMBOL(smp_put_cpu); diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index 584ed95f338..3a77c22cda7 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -266,23 +266,3 @@ s390_fadvise64_64(struct fadvise64_64_args __user *args) return -EFAULT; return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); } - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, char *const argv[], char *const envp[]) -{ - register const char *__arg1 asm("2") = filename; - register char *const*__arg2 asm("3") = argv; - register char *const*__arg3 asm("4") = envp; - register long __svcres asm("2"); - asm volatile( - "svc %b1" - : "=d" (__svcres) - : "i" (__NR_execve), - "0" (__arg1), - "d" (__arg2), - "d" (__arg3) : "memory"); - return __svcres; -} diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index c774f1069e1..cd8d321cd0c 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -10,7 +10,7 @@ NI_SYSCALL /* 0 */ SYSCALL(sys_exit,sys_exit,sys32_exit_wrapper) -SYSCALL(sys_fork_glue,sys_fork_glue,sys_fork_glue) +SYSCALL(sys_fork,sys_fork,sys_fork) SYSCALL(sys_read,sys_read,sys32_read_wrapper) SYSCALL(sys_write,sys_write,sys32_write_wrapper) SYSCALL(sys_open,sys_open,sys32_open_wrapper) /* 5 */ @@ -19,7 +19,7 @@ SYSCALL(sys_restart_syscall,sys_restart_syscall,sys_restart_syscall) SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) SYSCALL(sys_link,sys_link,sys32_link_wrapper) SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */ -SYSCALL(sys_execve_glue,sys_execve_glue,sys32_execve_glue) +SYSCALL(sys_execve,sys_execve,sys32_execve) SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper) SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper) /* old time syscall */ SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper) @@ -127,8 +127,8 @@ SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper) /* 115 */ SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) -SYSCALL(sys_sigreturn_glue,sys_sigreturn_glue,sys32_sigreturn_glue) -SYSCALL(sys_clone_glue,sys_clone_glue,sys32_clone_glue) /* 120 */ +SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn) +SYSCALL(sys_clone,sys_clone,sys32_clone) /* 120 */ SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) SYSCALL(sys_newuname,s390x_newuname,sys32_newuname_wrapper) NI_SYSCALL /* modify_ldt for i386 */ @@ -181,7 +181,7 @@ SYSCALL(sys_nfsservctl,sys_nfsservctl,compat_sys_nfsservctl_wrapper) SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper) /* 170 old setresgid16 syscall */ SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper) /* old getresgid16 syscall */ SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper) -SYSCALL(sys_rt_sigreturn_glue,sys_rt_sigreturn_glue,sys32_rt_sigreturn_glue) +SYSCALL(sys_rt_sigreturn,sys_rt_sigreturn,sys32_rt_sigreturn) SYSCALL(sys_rt_sigaction,sys_rt_sigaction,sys32_rt_sigaction_wrapper) SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 175 */ SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper) @@ -194,11 +194,11 @@ SYSCALL(sys_chown16,sys_ni_syscall,sys32_chown16_wrapper) /* old chown16 syscall SYSCALL(sys_getcwd,sys_getcwd,sys32_getcwd_wrapper) SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper) SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper) /* 185 */ -SYSCALL(sys_sigaltstack_glue,sys_sigaltstack_glue,sys32_sigaltstack_glue) +SYSCALL(sys_sigaltstack,sys_sigaltstack,sys32_sigaltstack) SYSCALL(sys_sendfile,sys_sendfile64,sys32_sendfile_wrapper) NI_SYSCALL /* streams1 */ NI_SYSCALL /* streams2 */ -SYSCALL(sys_vfork_glue,sys_vfork_glue,sys_vfork_glue) /* 190 */ +SYSCALL(sys_vfork,sys_vfork,sys_vfork) /* 190 */ SYSCALL(sys_getrlimit,sys_getrlimit,compat_sys_getrlimit_wrapper) SYSCALL(sys_mmap2,sys_mmap2,sys32_mmap2_wrapper) SYSCALL(sys_truncate64,sys_ni_syscall,sys32_truncate64_wrapper) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index e1ad464b6f2..711dae8da7a 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -280,7 +280,6 @@ static void clock_comparator_interrupt(__u16 code) } static void etr_reset(void); -static void etr_init(void); static void etr_ext_handler(__u16); /* @@ -355,7 +354,6 @@ void __init time_init(void) #ifdef CONFIG_VIRT_TIMER vtime_init(); #endif - etr_init(); } /* @@ -426,11 +424,11 @@ static struct etr_aib etr_port1; static int etr_port1_uptodate; static unsigned long etr_events; static struct timer_list etr_timer; -static struct tasklet_struct etr_tasklet; static DEFINE_PER_CPU(atomic_t, etr_sync_word); static void etr_timeout(unsigned long dummy); -static void etr_tasklet_fn(unsigned long dummy); +static void etr_work_fn(struct work_struct *work); +static DECLARE_WORK(etr_work, etr_work_fn); /* * The etr get_clock function. It will write the current clock value @@ -507,29 +505,31 @@ static void etr_reset(void) } } -static void etr_init(void) +static int __init etr_init(void) { struct etr_aib aib; if (test_bit(ETR_FLAG_ENOSYS, &etr_flags)) - return; + return 0; /* Check if this machine has the steai instruction. */ if (etr_steai(&aib, ETR_STEAI_STEPPING_PORT) == 0) set_bit(ETR_FLAG_STEAI, &etr_flags); setup_timer(&etr_timer, etr_timeout, 0UL); - tasklet_init(&etr_tasklet, etr_tasklet_fn, 0); if (!etr_port0_online && !etr_port1_online) set_bit(ETR_FLAG_EACCES, &etr_flags); if (etr_port0_online) { set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events); - tasklet_hi_schedule(&etr_tasklet); + schedule_work(&etr_work); } if (etr_port1_online) { set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events); - tasklet_hi_schedule(&etr_tasklet); + schedule_work(&etr_work); } + return 0; } +arch_initcall(etr_init); + /* * Two sorts of ETR machine checks. The architecture reads: * "When a machine-check niterruption occurs and if a switch-to-local or @@ -549,7 +549,7 @@ void etr_switch_to_local(void) return; etr_disable_sync_clock(NULL); set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events); - tasklet_hi_schedule(&etr_tasklet); + schedule_work(&etr_work); } /* @@ -564,7 +564,7 @@ void etr_sync_check(void) return; etr_disable_sync_clock(NULL); set_bit(ETR_EVENT_SYNC_CHECK, &etr_events); - tasklet_hi_schedule(&etr_tasklet); + schedule_work(&etr_work); } /* @@ -591,13 +591,13 @@ static void etr_ext_handler(__u16 code) * Both ports are not up-to-date now. */ set_bit(ETR_EVENT_PORT_ALERT, &etr_events); - tasklet_hi_schedule(&etr_tasklet); + schedule_work(&etr_work); } static void etr_timeout(unsigned long dummy) { set_bit(ETR_EVENT_UPDATE, &etr_events); - tasklet_hi_schedule(&etr_tasklet); + schedule_work(&etr_work); } /* @@ -927,7 +927,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib, if (!eacr.e0 && !eacr.e1) return eacr; - /* Update port0 or port1 with aib stored in etr_tasklet_fn. */ + /* Update port0 or port1 with aib stored in etr_work_fn. */ if (aib->esw.q == 0) { /* Information for port 0 stored. */ if (eacr.p0 && !etr_port0_uptodate) { @@ -1007,7 +1007,7 @@ static void etr_update_eacr(struct etr_eacr eacr) * particular this is the only function that calls etr_update_eacr(), * it "controls" the etr control register. */ -static void etr_tasklet_fn(unsigned long dummy) +static void etr_work_fn(struct work_struct *work) { unsigned long long now; struct etr_eacr eacr; @@ -1220,13 +1220,13 @@ static ssize_t etr_online_store(struct sys_device *dev, return count; /* Nothing to do. */ etr_port0_online = value; set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events); - tasklet_hi_schedule(&etr_tasklet); + schedule_work(&etr_work); } else { if (etr_port1_online == value) return count; /* Nothing to do. */ etr_port1_online = value; set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events); - tasklet_hi_schedule(&etr_tasklet); + schedule_work(&etr_work); } return count; } diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index f0e5a320e2e..49dec830373 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -30,7 +30,7 @@ #include <linux/kallsyms.h> #include <linux/reboot.h> #include <linux/kprobes.h> - +#include <linux/bug.h> #include <asm/system.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -188,18 +188,31 @@ void dump_stack(void) EXPORT_SYMBOL(dump_stack); +static inline int mask_bits(struct pt_regs *regs, unsigned long bits) +{ + return (regs->psw.mask & bits) / ((~bits + 1) & bits); +} + void show_registers(struct pt_regs *regs) { - mm_segment_t old_fs; char *mode; - int i; mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl"; printk("%s PSW : %p %p", mode, (void *) regs->psw.mask, (void *) regs->psw.addr); print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN); - printk("%s GPRS: " FOURLONG, mode, + printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x " + "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER), + mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO), + mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY), + mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT), + mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC), + mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM)); +#ifdef CONFIG_64BIT + printk(" EA:%x", mask_bits(regs, PSW_BASE_BITS)); +#endif + printk("\n%s GPRS: " FOURLONG, mode, regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]); printk(" " FOURLONG, regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]); @@ -208,41 +221,7 @@ void show_registers(struct pt_regs *regs) printk(" " FOURLONG, regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]); -#if 0 - /* FIXME: this isn't needed any more but it changes the ksymoops - * input. To remove or not to remove ... */ - save_access_regs(regs->acrs); - printk("%s ACRS: %08x %08x %08x %08x\n", mode, - regs->acrs[0], regs->acrs[1], regs->acrs[2], regs->acrs[3]); - printk(" %08x %08x %08x %08x\n", - regs->acrs[4], regs->acrs[5], regs->acrs[6], regs->acrs[7]); - printk(" %08x %08x %08x %08x\n", - regs->acrs[8], regs->acrs[9], regs->acrs[10], regs->acrs[11]); - printk(" %08x %08x %08x %08x\n", - regs->acrs[12], regs->acrs[13], regs->acrs[14], regs->acrs[15]); -#endif - - /* - * Print the first 20 byte of the instruction stream at the - * time of the fault. - */ - old_fs = get_fs(); - if (regs->psw.mask & PSW_MASK_PSTATE) - set_fs(USER_DS); - else - set_fs(KERNEL_DS); - printk("%s Code: ", mode); - for (i = 0; i < 20; i++) { - unsigned char c; - if (__get_user(c, (char __user *)(regs->psw.addr + i))) { - printk(" Bad PSW."); - break; - } - printk("%02x ", c); - } - set_fs(old_fs); - - printk("\n"); + show_code(regs); } /* This is called from fs/proc/array.c */ @@ -318,6 +297,11 @@ report_user_fault(long interruption_code, struct pt_regs *regs) #endif } +int is_valid_bugaddr(unsigned long addr) +{ + return 1; +} + static void __kprobes inline do_trap(long interruption_code, int signr, char *str, struct pt_regs *regs, siginfo_t *info) @@ -344,8 +328,14 @@ static void __kprobes inline do_trap(long interruption_code, int signr, fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); if (fixup) regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; - else - die(str, regs, interruption_code); + else { + enum bug_trap_type btt; + + btt = report_bug(regs->psw.addr & PSW_ADDR_INSN); + if (btt == BUG_TRAP_TYPE_WARN) + return; + die(str, regs, interruption_code); + } } } diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index c30716ae130..418f6426a94 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -45,6 +45,8 @@ SECTIONS __ex_table : { *(__ex_table) } __stop___ex_table = .; + BUG_TABLE + .data : { /* Data */ *(.data) CONSTRUCTORS @@ -77,6 +79,12 @@ SECTIONS *(.init.text) _einittext = .; } + /* + * .exit.text is discarded at runtime, not link time, + * to deal with references from __bug_table + */ + .exit.text : { *(.exit.text) } + .init.data : { *(.init.data) } . = ALIGN(256); __setup_start = .; @@ -116,7 +124,7 @@ SECTIONS /* Sections to be discarded */ /DISCARD/ : { - *(.exit.text) *(.exit.data) *(.exitcall.exit) + *(.exit.data) *(.exitcall.exit) } /* Stabs debugging sections. */ diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 9d5b02801b4..1e1a6ee2cac 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -128,7 +128,7 @@ static inline void set_vtimer(__u64 expires) S390_lowcore.last_update_timer = expires; /* store expire time for this CPU timer */ - per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; + __get_cpu_var(virt_cpu_timer).to_expire = expires; } #else static inline void set_vtimer(__u64 expires) @@ -137,7 +137,7 @@ static inline void set_vtimer(__u64 expires) asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer)); /* store expire time for this CPU timer */ - per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; + __get_cpu_var(virt_cpu_timer).to_expire = expires; } #endif @@ -145,7 +145,7 @@ static void start_cpu_timer(void) { struct vtimer_queue *vt_list; - vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); + vt_list = &__get_cpu_var(virt_cpu_timer); /* CPU timer interrupt is pending, don't reprogramm it */ if (vt_list->idle & 1LL<<63) @@ -159,7 +159,7 @@ static void stop_cpu_timer(void) { struct vtimer_queue *vt_list; - vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); + vt_list = &__get_cpu_var(virt_cpu_timer); /* nothing to do */ if (list_empty(&vt_list->list)) { @@ -219,7 +219,7 @@ static void do_callbacks(struct list_head *cb_list) if (list_empty(cb_list)) return; - vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); + vt_list = &__get_cpu_var(virt_cpu_timer); list_for_each_entry_safe(event, tmp, cb_list, entry) { fn = event->function; @@ -244,7 +244,6 @@ static void do_callbacks(struct list_head *cb_list) */ static void do_cpu_timer_interrupt(__u16 error_code) { - int cpu; __u64 next, delta; struct vtimer_queue *vt_list; struct vtimer_list *event, *tmp; @@ -253,8 +252,7 @@ static void do_cpu_timer_interrupt(__u16 error_code) struct list_head cb_list; INIT_LIST_HEAD(&cb_list); - cpu = smp_processor_id(); - vt_list = &per_cpu(virt_cpu_timer, cpu); + vt_list = &__get_cpu_var(virt_cpu_timer); /* walk timer list, fire all expired events */ spin_lock(&vt_list->lock); @@ -534,7 +532,7 @@ void init_cpu_vtimer(void) /* enable cpu timer interrupts */ __ctl_set_bit(0,10); - vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); + vt_list = &__get_cpu_var(virt_cpu_timer); INIT_LIST_HEAD(&vt_list->list); spin_lock_init(&vt_list->lock); vt_list->to_expire = 0; diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index 7a44fed21b3..59aea65ce99 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile @@ -5,6 +5,6 @@ EXTRA_AFLAGS := -traditional lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o -lib-$(CONFIG_32BIT) += div64.o +obj-$(CONFIG_32BIT) += div64.o lib-$(CONFIG_64BIT) += uaccess_mvcos.o lib-$(CONFIG_SMP) += spinlock.o diff --git a/arch/s390/lib/div64.c b/arch/s390/lib/div64.c index 0481f3424a1..a5f8300bf3e 100644 --- a/arch/s390/lib/div64.c +++ b/arch/s390/lib/div64.c @@ -147,5 +147,3 @@ uint32_t __div64_32(uint64_t *n, uint32_t base) } #endif /* MARCH_G5 */ - -EXPORT_SYMBOL(__div64_32); diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 7462aebd3eb..91f705adc3f 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -26,9 +26,9 @@ #include <linux/module.h> #include <linux/hardirq.h> #include <linux/kprobes.h> +#include <linux/uaccess.h> #include <asm/system.h> -#include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/kdebug.h> #include <asm/s390_ext.h> @@ -52,34 +52,24 @@ extern int sysctl_userprocess_debug; extern void die(const char *,struct pt_regs *,long); #ifdef CONFIG_KPROBES -static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); -int register_page_fault_notifier(struct notifier_block *nb) +static inline int notify_page_fault(struct pt_regs *regs, long err) { - return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); -} + int ret = 0; + + /* kprobe_running() needs smp_processor_id() */ + if (!user_mode(regs)) { + preempt_disable(); + if (kprobe_running() && kprobe_fault_handler(regs, 14)) + ret = 1; + preempt_enable(); + } -int unregister_page_fault_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); -} - -static inline int notify_page_fault(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) -{ - struct die_args args = { - .regs = regs, - .str = str, - .err = err, - .trapnr = trap, - .signr = sig - }; - return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); + return ret; } #else -static inline int notify_page_fault(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) +static inline int notify_page_fault(struct pt_regs *regs, long err) { - return NOTIFY_DONE; + return 0; } #endif @@ -170,74 +160,127 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code, force_sig_info(SIGSEGV, &si, current); } +static void do_no_context(struct pt_regs *regs, unsigned long error_code, + unsigned long address) +{ + const struct exception_table_entry *fixup; + + /* Are we prepared to handle this kernel fault? */ + fixup = search_exception_tables(regs->psw.addr & __FIXUP_MASK); + if (fixup) { + regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; + return; + } + + /* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ + if (check_space(current) == 0) + printk(KERN_ALERT "Unable to handle kernel pointer dereference" + " at virtual kernel address %p\n", (void *)address); + else + printk(KERN_ALERT "Unable to handle kernel paging request" + " at virtual user address %p\n", (void *)address); + + die("Oops", regs, error_code); + do_exit(SIGKILL); +} + +static void do_low_address(struct pt_regs *regs, unsigned long error_code) +{ + /* Low-address protection hit in kernel mode means + NULL pointer write access in kernel mode. */ + if (regs->psw.mask & PSW_MASK_PSTATE) { + /* Low-address protection hit in user mode 'cannot happen'. */ + die ("Low-address protection", regs, error_code); + do_exit(SIGKILL); + } + + do_no_context(regs, error_code, 0); +} + +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +static int do_out_of_memory(struct pt_regs *regs, unsigned long error_code, + unsigned long address) +{ + struct task_struct *tsk = current; + struct mm_struct *mm = tsk->mm; + + up_read(&mm->mmap_sem); + if (is_init(tsk)) { + yield(); + down_read(&mm->mmap_sem); + return 1; + } + printk("VM: killing process %s\n", tsk->comm); + if (regs->psw.mask & PSW_MASK_PSTATE) + do_exit(SIGKILL); + do_no_context(regs, error_code, address); + return 0; +} + +static void do_sigbus(struct pt_regs *regs, unsigned long error_code, + unsigned long address) +{ + struct task_struct *tsk = current; + struct mm_struct *mm = tsk->mm; + + up_read(&mm->mmap_sem); + /* + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ + tsk->thread.prot_addr = address; + tsk->thread.trap_no = error_code; + force_sig(SIGBUS, tsk); + + /* Kernel mode? Handle exceptions or die */ + if (!(regs->psw.mask & PSW_MASK_PSTATE)) + do_no_context(regs, error_code, address); +} + #ifdef CONFIG_S390_EXEC_PROTECT extern long sys_sigreturn(struct pt_regs *regs); extern long sys_rt_sigreturn(struct pt_regs *regs); extern long sys32_sigreturn(struct pt_regs *regs); extern long sys32_rt_sigreturn(struct pt_regs *regs); -static inline void do_sigreturn(struct mm_struct *mm, struct pt_regs *regs, - int rt) +static int signal_return(struct mm_struct *mm, struct pt_regs *regs, + unsigned long address, unsigned long error_code) { + u16 instruction; + int rc, compat; + + pagefault_disable(); + rc = __get_user(instruction, (u16 __user *) regs->psw.addr); + pagefault_enable(); + if (rc) + return -EFAULT; + up_read(&mm->mmap_sem); clear_tsk_thread_flag(current, TIF_SINGLE_STEP); #ifdef CONFIG_COMPAT - if (test_tsk_thread_flag(current, TIF_31BIT)) { - if (rt) - sys32_rt_sigreturn(regs); - else - sys32_sigreturn(regs); - return; - } -#endif /* CONFIG_COMPAT */ - if (rt) - sys_rt_sigreturn(regs); + compat = test_tsk_thread_flag(current, TIF_31BIT); + if (compat && instruction == 0x0a77) + sys32_sigreturn(regs); + else if (compat && instruction == 0x0aad) + sys32_rt_sigreturn(regs); else +#endif + if (instruction == 0x0a77) sys_sigreturn(regs); - return; -} - -static int signal_return(struct mm_struct *mm, struct pt_regs *regs, - unsigned long address, unsigned long error_code) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - u16 *instruction; - unsigned long pfn, uaddr = regs->psw.addr; - - spin_lock(&mm->page_table_lock); - pgd = pgd_offset(mm, uaddr); - if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) - goto out_fault; - pmd = pmd_offset(pgd, uaddr); - if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) - goto out_fault; - pte = pte_offset_map(pmd_offset(pgd_offset(mm, uaddr), uaddr), uaddr); - if (!pte || !pte_present(*pte)) - goto out_fault; - pfn = pte_pfn(*pte); - if (!pfn_valid(pfn)) - goto out_fault; - spin_unlock(&mm->page_table_lock); - - instruction = (u16 *) ((pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE-1))); - if (*instruction == 0x0a77) - do_sigreturn(mm, regs, 0); - else if (*instruction == 0x0aad) - do_sigreturn(mm, regs, 1); + else if (instruction == 0x0aad) + sys_rt_sigreturn(regs); else { - printk("- XXX - do_exception: task = %s, primary, NO EXEC " - "-> SIGSEGV\n", current->comm); - up_read(&mm->mmap_sem); current->thread.prot_addr = address; current->thread.trap_no = error_code; do_sigsegv(regs, error_code, SEGV_MAPERR, address); } return 0; -out_fault: - spin_unlock(&mm->page_table_lock); - return -EFAULT; } #endif /* CONFIG_S390_EXEC_PROTECT */ @@ -253,49 +296,23 @@ out_fault: * 3b Region third trans. -> Not present (nullification) */ static inline void -do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) +do_exception(struct pt_regs *regs, unsigned long error_code, int write) { - struct task_struct *tsk; - struct mm_struct *mm; - struct vm_area_struct * vma; - unsigned long address; - const struct exception_table_entry *fixup; - int si_code; + struct task_struct *tsk; + struct mm_struct *mm; + struct vm_area_struct *vma; + unsigned long address; int space; + int si_code; - tsk = current; - mm = tsk->mm; - - if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, - SIGSEGV) == NOTIFY_STOP) + if (notify_page_fault(regs, error_code)) return; - /* - * Check for low-address protection. This needs to be treated - * as a special case because the translation exception code - * field is not guaranteed to contain valid data in this case. - */ - if (is_protection && !(S390_lowcore.trans_exc_code & 4)) { - - /* Low-address protection hit in kernel mode means - NULL pointer write access in kernel mode. */ - if (!(regs->psw.mask & PSW_MASK_PSTATE)) { - address = 0; - space = 0; - goto no_context; - } - - /* Low-address protection hit in user mode 'cannot happen'. */ - die ("Low-address protection", regs, error_code); - do_exit(SIGKILL); - } + tsk = current; + mm = tsk->mm; - /* - * get the failing address - * more specific the segment and page table portion of - * the address - */ - address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK; + /* get the failing address and the affected space */ + address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK; space = check_space(tsk); /* @@ -313,7 +330,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) */ local_irq_enable(); - down_read(&mm->mmap_sem); + down_read(&mm->mmap_sem); si_code = SEGV_MAPERR; vma = find_vma(mm, address); @@ -330,19 +347,19 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) return; #endif - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; + if (vma->vm_start <= address) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto bad_area; + if (expand_stack(vma, address)) + goto bad_area; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ good_area: si_code = SEGV_ACCERR; - if (!is_protection) { + if (!write) { /* page not present, check vm flags */ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) goto bad_area; @@ -357,7 +374,7 @@ survive: * make sure we exit gracefully rather than endlessly redo * the fault. */ - switch (handle_mm_fault(mm, vma, address, is_protection)) { + switch (handle_mm_fault(mm, vma, address, write)) { case VM_FAULT_MINOR: tsk->min_flt++; break; @@ -365,9 +382,12 @@ survive: tsk->maj_flt++; break; case VM_FAULT_SIGBUS: - goto do_sigbus; + do_sigbus(regs, error_code, address); + return; case VM_FAULT_OOM: - goto out_of_memory; + if (do_out_of_memory(regs, error_code, address)) + goto survive; + return; default: BUG(); } @@ -385,75 +405,34 @@ survive: * Fix it, but check if it's kernel or user first.. */ bad_area: - up_read(&mm->mmap_sem); + up_read(&mm->mmap_sem); - /* User mode accesses just cause a SIGSEGV */ - if (regs->psw.mask & PSW_MASK_PSTATE) { - tsk->thread.prot_addr = address; - tsk->thread.trap_no = error_code; + /* User mode accesses just cause a SIGSEGV */ + if (regs->psw.mask & PSW_MASK_PSTATE) { + tsk->thread.prot_addr = address; + tsk->thread.trap_no = error_code; do_sigsegv(regs, error_code, si_code, address); - return; + return; } no_context: - /* Are we prepared to handle this kernel fault? */ - fixup = search_exception_tables(regs->psw.addr & __FIXUP_MASK); - if (fixup) { - regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; - return; - } - -/* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ - if (space == 0) - printk(KERN_ALERT "Unable to handle kernel pointer dereference" - " at virtual kernel address %p\n", (void *)address); - else - printk(KERN_ALERT "Unable to handle kernel paging request" - " at virtual user address %p\n", (void *)address); - - die("Oops", regs, error_code); - do_exit(SIGKILL); - - -/* - * We ran out of memory, or some other thing happened to us that made - * us unable to handle the page fault gracefully. -*/ -out_of_memory: - up_read(&mm->mmap_sem); - if (is_init(tsk)) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk("VM: killing process %s\n", tsk->comm); - if (regs->psw.mask & PSW_MASK_PSTATE) - do_exit(SIGKILL); - goto no_context; - -do_sigbus: - up_read(&mm->mmap_sem); - - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ - tsk->thread.prot_addr = address; - tsk->thread.trap_no = error_code; - force_sig(SIGBUS, tsk); - - /* Kernel mode? Handle exceptions or die */ - if (!(regs->psw.mask & PSW_MASK_PSTATE)) - goto no_context; + do_no_context(regs, error_code, address); } void __kprobes do_protection_exception(struct pt_regs *regs, unsigned long error_code) { + /* Protection exception is supressing, decrement psw address. */ regs->psw.addr -= (error_code >> 16); + /* + * Check for low-address protection. This needs to be treated + * as a special case because the translation exception code + * field is not guaranteed to contain valid data in this case. + */ + if (unlikely(!(S390_lowcore.trans_exc_code & 4))) { + do_low_address(regs, error_code); + return; + } do_exception(regs, 4, 1); } diff --git a/arch/sh/boards/hp6xx/pm.c b/arch/sh/boards/hp6xx/pm.c index d1947732fb3..8143d1b948e 100644 --- a/arch/sh/boards/hp6xx/pm.c +++ b/arch/sh/boards/hp6xx/pm.c @@ -27,9 +27,6 @@ static int hp6x0_pm_enter(suspend_state_t state) u16 hd64461_stbcr; #endif - if (state != PM_SUSPEND_MEM) - return -EINVAL; - #ifdef CONFIG_HD64461_ENABLER outb(0, HD64461_PCC1CSCIER); @@ -70,12 +67,9 @@ static int hp6x0_pm_enter(suspend_state_t state) return 0; } -/* - * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. - */ static struct pm_ops hp6x0_pm_ops = { - .pm_disk_mode = PM_DISK_FIRMWARE, .enter = hp6x0_pm_enter, + .valid = pm_valid_only_mem, }; static int __init hp6x0_pm_init(void) diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index b5681e3f968..0b9cca5c7cb 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -3,7 +3,7 @@ # lib-y = delay.o memset.o memmove.o memchr.o \ - checksum.o strcasecmp.o strlen.o div64.o udivdi3.o \ + checksum.o strlen.o div64.o udivdi3.o \ div64-generic.o memcpy-y := memcpy.o diff --git a/arch/sh/lib/strcasecmp.c b/arch/sh/lib/strcasecmp.c deleted file mode 100644 index 4e57a216fea..00000000000 --- a/arch/sh/lib/strcasecmp.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * linux/arch/alpha/lib/strcasecmp.c - */ - -#include <linux/string.h> - - -/* We handle nothing here except the C locale. Since this is used in - only one place, on strings known to contain only 7 bit ASCII, this - is ok. */ - -int strcasecmp(const char *a, const char *b) -{ - int ca, cb; - - do { - ca = *a++ & 0xff; - cb = *b++ & 0xff; - if (ca >= 'A' && ca <= 'Z') - ca += 'a' - 'A'; - if (cb >= 'A' && cb <= 'Z') - cb += 'a' - 'A'; - } while (ca == cb && ca != '\0'); - - return ca - cb; -} diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index ba58c3a061f..7bb86b9cdaa 100644 --- a/arch/sparc/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c @@ -25,7 +25,7 @@ struct linux_ebus *ebus_chain = NULL; /* We are together with pcic.c under CONFIG_PCI. */ -extern unsigned int pcic_pin_to_irq(unsigned int, char *name); +extern unsigned int pcic_pin_to_irq(unsigned int, const char *name); /* * IRQ Blacklist @@ -69,7 +69,7 @@ static inline unsigned long ebus_alloc(size_t size) /* */ -int __init ebus_blacklist_irq(char *name) +int __init ebus_blacklist_irq(const char *name) { struct ebus_device_irq *dp; @@ -86,8 +86,8 @@ int __init ebus_blacklist_irq(char *name) void __init fill_ebus_child(struct device_node *dp, struct linux_ebus_child *dev) { - int *regs; - int *irqs; + const int *regs; + const int *irqs; int i, len; dev->prom_node = dp; @@ -146,9 +146,9 @@ void __init fill_ebus_child(struct device_node *dp, void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) { - struct linux_prom_registers *regs; + const struct linux_prom_registers *regs; struct linux_ebus_child *child; - int *irqs; + const int *irqs; int i, n, len; unsigned long baseaddr; @@ -269,7 +269,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d void __init ebus_init(void) { - struct linux_prom_pci_registers *regs; + const struct linux_prom_pci_registers *regs; struct linux_pbm_info *pbm; struct linux_ebus_device *dev; struct linux_ebus *ebus; diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 48c24f7518c..fd7f8cb668a 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -210,7 +210,7 @@ struct of_bus { int *addrc, int *sizec); int (*map)(u32 *addr, const u32 *range, int na, int ns, int pna); - unsigned int (*get_flags)(u32 *addr); + unsigned int (*get_flags)(const u32 *addr); }; /* @@ -270,7 +270,7 @@ static int of_bus_default_map(u32 *addr, const u32 *range, return 0; } -static unsigned int of_bus_default_get_flags(u32 *addr) +static unsigned int of_bus_default_get_flags(const u32 *addr) { return IORESOURCE_MEM; } @@ -334,7 +334,7 @@ static int of_bus_pci_map(u32 *addr, const u32 *range, return 0; } -static unsigned int of_bus_pci_get_flags(u32 *addr) +static unsigned int of_bus_pci_get_flags(const u32 *addr) { unsigned int flags = 0; u32 w = addr[0]; @@ -375,7 +375,7 @@ static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna) return of_bus_default_map(addr, range, na, ns, pna); } -static unsigned int of_bus_sbus_get_flags(u32 *addr) +static unsigned int of_bus_sbus_get_flags(const u32 *addr) { return IORESOURCE_MEM; } @@ -432,7 +432,7 @@ static int __init build_one_resource(struct device_node *parent, u32 *addr, int na, int ns, int pna) { - u32 *ranges; + const u32 *ranges; unsigned int rlen; int rone; @@ -470,7 +470,7 @@ static void __init build_device_resources(struct of_device *op, struct of_bus *bus; int na, ns; int index, num_reg; - void *preg; + const void *preg; if (!parent) return; @@ -492,7 +492,7 @@ static void __init build_device_resources(struct of_device *op, for (index = 0; index < num_reg; index++) { struct resource *r = &op->resource[index]; u32 addr[OF_MAX_ADDR_CELLS]; - u32 *reg = (preg + (index * ((na + ns) * 4))); + const u32 *reg = (preg + (index * ((na + ns) * 4))); struct device_node *dp = op->node; struct device_node *pp = p_op->node; struct of_bus *pbus, *dbus; @@ -559,7 +559,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, struct device *parent) { struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); - struct linux_prom_irqs *intr; + const struct linux_prom_irqs *intr; int len, i; if (!op) @@ -579,7 +579,8 @@ static struct of_device * __init scan_one_device(struct device_node *dp, for (i = 0; i < op->num_irqs; i++) op->irqs[i] = intr[i].pri; } else { - unsigned int *irq = of_get_property(dp, "interrupts", &len); + const unsigned int *irq = + of_get_property(dp, "interrupts", &len); if (irq) { op->num_irqs = len / sizeof(unsigned int); @@ -594,7 +595,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, }; struct device_node *io_unit, *sbi = dp->parent; - struct linux_prom_registers *regs; + const struct linux_prom_registers *regs; int board, slot; while (sbi) { diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 1c927c538b8..5ca7e8f42bd 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -37,8 +37,6 @@ #include <asm/irq_regs.h> -unsigned int pcic_pin_to_irq(unsigned int pin, char *name); - /* * I studied different documents and many live PROMs both from 2.30 * family and 3.xx versions. I came to the amazing conclusion: there is @@ -681,7 +679,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) * pcic_pin_to_irq() is exported to ebus.c. */ unsigned int -pcic_pin_to_irq(unsigned int pin, char *name) +pcic_pin_to_irq(unsigned int pin, const char *name) { struct linux_pcic *pcic = &pcic0; unsigned int irq; diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index 2cc302b6bec..eed140b3c73 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c @@ -32,12 +32,13 @@ static struct device_node *allnodes; */ static DEFINE_RWLOCK(devtree_lock); -int of_device_is_compatible(struct device_node *device, const char *compat) +int of_device_is_compatible(const struct device_node *device, + const char *compat) { const char* cp; int cplen, l; - cp = (char *) of_get_property(device, "compatible", &cplen); + cp = of_get_property(device, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { @@ -150,13 +151,14 @@ struct device_node *of_find_compatible_node(struct device_node *from, } EXPORT_SYMBOL(of_find_compatible_node); -struct property *of_find_property(struct device_node *np, const char *name, +struct property *of_find_property(const struct device_node *np, + const char *name, int *lenp) { struct property *pp; for (pp = np->properties; pp != 0; pp = pp->next) { - if (strcmp(pp->name, name) == 0) { + if (strcasecmp(pp->name, name) == 0) { if (lenp != 0) *lenp = pp->length; break; @@ -170,7 +172,8 @@ EXPORT_SYMBOL(of_find_property); * Find a property with a given name for a given node * and return the value. */ -void *of_get_property(struct device_node *np, const char *name, int *lenp) +const void *of_get_property(const struct device_node *np, const char *name, + int *lenp) { struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; @@ -192,7 +195,7 @@ EXPORT_SYMBOL(of_getintprop_default); int of_n_addr_cells(struct device_node *np) { - int* ip; + const int* ip; do { if (np->parent) np = np->parent; @@ -207,7 +210,7 @@ EXPORT_SYMBOL(of_n_addr_cells); int of_n_size_cells(struct device_node *np) { - int* ip; + const int* ip; do { if (np->parent) np = np->parent; @@ -239,7 +242,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len while (*prevp) { struct property *prop = *prevp; - if (!strcmp(prop->name, name)) { + if (!strcasecmp(prop->name, name)) { void *old_val = prop->value; int ret; diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 9bb1240aaf8..f1401b57ccc 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -301,7 +301,7 @@ static __inline__ void sun4_clock_probe(void) static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - char *model = of_get_property(dp, "model", NULL); + const char *model = of_get_property(dp, "model", NULL); if (!model) return -ENODEV; diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 1a6348b565f..590a41b864b 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -19,6 +19,14 @@ config SPARC64 SPARC64 ports; its web page is available at <http://www.ultralinux.org/>. +config GENERIC_TIME + bool + default y + +config GENERIC_CLOCKEVENTS + bool + default y + config 64BIT def_bool y @@ -34,10 +42,6 @@ config LOCKDEP_SUPPORT bool default y -config TIME_INTERPOLATION - bool - default y - config ARCH_MAY_HAVE_PC_FDC bool default y @@ -113,6 +117,8 @@ config GENERIC_HARDIRQS menu "General machine setup" +source "kernel/time/Kconfig" + config SMP bool "Symmetric multi-processing support" ---help--- @@ -214,6 +220,7 @@ config ARCH_SPARSEMEM_ENABLE config ARCH_SPARSEMEM_DEFAULT def_bool y + select SPARSEMEM_STATIC config LARGE_ALLOCS def_bool y diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index e724c54af02..c65b2f9c98d 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c @@ -32,7 +32,7 @@ static void central_probe_failure(int line) static void central_ranges_init(struct linux_central *central) { struct device_node *dp = central->prom_node; - void *pval; + const void *pval; int len; central->num_central_ranges = 0; @@ -47,7 +47,7 @@ static void central_ranges_init(struct linux_central *central) static void fhc_ranges_init(struct linux_fhc *fhc) { struct device_node *dp = fhc->prom_node; - void *pval; + const void *pval; int len; fhc->num_fhc_ranges = 0; @@ -119,7 +119,7 @@ static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r) static void probe_other_fhcs(void) { struct device_node *dp; - struct linux_prom64_registers *fpregs; + const struct linux_prom64_registers *fpregs; for_each_node_by_name(dp, "fhc") { struct linux_fhc *fhc; @@ -190,7 +190,8 @@ static void probe_clock_board(struct linux_central *central, struct device_node *fp) { struct device_node *dp; - struct linux_prom_registers cregs[3], *pr; + struct linux_prom_registers cregs[3]; + const struct linux_prom_registers *pr; int nslots, tmp, nregs; dp = fp->child; @@ -299,7 +300,8 @@ static void init_all_fhc_hw(void) void central_probe(void) { - struct linux_prom_registers fpregs[6], *pr; + struct linux_prom_registers fpregs[6]; + const struct linux_prom_registers *pr; struct linux_fhc *fhc; struct device_node *dp, *fp; int err; diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 9699abeb990..777d3457704 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -343,8 +343,8 @@ static int init_one_mctrl(struct device_node *dp) { struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL); int portid = of_getintprop_default(dp, "portid", -1); - struct linux_prom64_registers *regs; - void *pval; + const struct linux_prom64_registers *regs; + const void *pval; int len; if (!mp) diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 35bf895fdee..0ace17bafba 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -285,7 +285,7 @@ static void __init fill_ebus_child(struct device_node *dp, int non_standard_regs) { struct of_device *op; - int *regs; + const int *regs; int i, len; dev->prom_node = dp; @@ -438,11 +438,9 @@ static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p) void __init ebus_init(void) { - struct pci_pbm_info *pbm; struct linux_ebus_device *dev; struct linux_ebus *ebus; struct pci_dev *pdev; - struct pcidev_cookie *cookie; struct device_node *dp; int is_rio; int num_ebus = 0; @@ -453,8 +451,7 @@ void __init ebus_init(void) return; } - cookie = pdev->sysdata; - dp = cookie->prom_node; + dp = pci_device_to_OF_node(pdev); ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); ebus->next = NULL; @@ -480,8 +477,7 @@ void __init ebus_init(void) break; } ebus->is_rio = is_rio; - cookie = pdev->sysdata; - dp = cookie->prom_node; + dp = pci_device_to_OF_node(pdev); continue; } printk("ebus%d:", num_ebus); @@ -489,7 +485,6 @@ void __init ebus_init(void) ebus->index = num_ebus; ebus->prom_node = dp; ebus->self = pdev; - ebus->parent = pbm = cookie->pbm; ebus->ofdev.node = dp; ebus->ofdev.dev.parent = &pdev->dev; @@ -531,8 +526,7 @@ void __init ebus_init(void) if (!pdev) break; - cookie = pdev->sysdata; - dp = cookie->prom_node; + dp = pci_device_to_OF_node(pdev); ebus->next = ebus_alloc(sizeof(struct linux_ebus)); ebus = ebus->next; diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index c443db18437..6241e3dbbd5 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -589,32 +589,6 @@ void ack_bad_irq(unsigned int virt_irq) ino, virt_irq); } -#ifndef CONFIG_SMP -extern irqreturn_t timer_interrupt(int, void *); - -void timer_irq(int irq, struct pt_regs *regs) -{ - unsigned long clr_mask = 1 << irq; - unsigned long tick_mask = tick_ops->softint_mask; - struct pt_regs *old_regs; - - if (get_softint() & tick_mask) { - irq = 0; - clr_mask = tick_mask; - } - clear_softint(clr_mask); - - old_regs = set_irq_regs(regs); - irq_enter(); - - kstat_this_cpu.irqs[0]++; - timer_interrupt(irq, NULL); - - irq_exit(); - set_irq_regs(old_regs); -} -#endif - void handler_irq(int irq, struct pt_regs *regs) { struct ino_bucket *bucket; @@ -653,7 +627,7 @@ static u64 prom_limit0, prom_limit1; static void map_prom_timers(void) { struct device_node *dp; - unsigned int *addr; + const unsigned int *addr; /* PROM timer node hangs out in the top level of device siblings... */ dp = of_find_node_by_path("/"); diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 98721a8f861..6a6882e57ff 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c @@ -24,27 +24,9 @@ static void __init report_dev(struct sparc_isa_device *isa_dev, int child) static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev) { - struct linux_prom_registers *pregs; - unsigned long base, len; - int prop_len; - - pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len); - if (!pregs) - return; - - /* Only the first one is interesting. */ - len = pregs[0].reg_size; - base = (((unsigned long)pregs[0].which_io << 32) | - (unsigned long)pregs[0].phys_addr); - base += isa_dev->bus->parent->io_space.start; - - isa_dev->resource.start = base; - isa_dev->resource.end = (base + len - 1UL); - isa_dev->resource.flags = IORESOURCE_IO; - isa_dev->resource.name = isa_dev->prom_node->name; + struct of_device *op = of_find_device_by_node(isa_dev->prom_node); - request_resource(&isa_dev->bus->parent->io_space, - &isa_dev->resource); + memcpy(&isa_dev->resource, &op->resource[0], sizeof(struct resource)); } static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev) @@ -158,19 +140,10 @@ void __init isa_init(void) pdev = NULL; while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) { - struct pcidev_cookie *pdev_cookie; - struct pci_pbm_info *pbm; struct sparc_isa_bridge *isa_br; struct device_node *dp; - pdev_cookie = pdev->sysdata; - if (!pdev_cookie) { - printk("ISA: Warning, ISA bridge ignored due to " - "lack of OBP data.\n"); - continue; - } - pbm = pdev_cookie->pbm; - dp = pdev_cookie->prom_node; + dp = pci_device_to_OF_node(pdev); isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL); if (!isa_br) { @@ -195,10 +168,9 @@ void __init isa_init(void) isa_br->next = isa_chain; isa_chain = isa_br; - isa_br->parent = pbm; isa_br->self = pdev; isa_br->index = index++; - isa_br->prom_node = pdev_cookie->prom_node; + isa_br->prom_node = dp; printk("isa%d:", isa_br->index); diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index fb9bf1e4d03..9ac9a307999 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -245,7 +245,7 @@ struct of_bus { int *addrc, int *sizec); int (*map)(u32 *addr, const u32 *range, int na, int ns, int pna); - unsigned int (*get_flags)(u32 *addr); + unsigned int (*get_flags)(const u32 *addr); }; /* @@ -305,7 +305,7 @@ static int of_bus_default_map(u32 *addr, const u32 *range, return 0; } -static unsigned int of_bus_default_get_flags(u32 *addr) +static unsigned int of_bus_default_get_flags(const u32 *addr) { return IORESOURCE_MEM; } @@ -317,6 +317,11 @@ static unsigned int of_bus_default_get_flags(u32 *addr) static int of_bus_pci_match(struct device_node *np) { if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { + const char *model = of_get_property(np, "model", NULL); + + if (model && !strcmp(model, "SUNW,simba")) + return 0; + /* Do not do PCI specific frobbing if the * PCI bridge lacks a ranges property. We * want to pass it through up to the next @@ -332,6 +337,21 @@ static int of_bus_pci_match(struct device_node *np) return 0; } +static int of_bus_simba_match(struct device_node *np) +{ + const char *model = of_get_property(np, "model", NULL); + + if (model && !strcmp(model, "SUNW,simba")) + return 1; + return 0; +} + +static int of_bus_simba_map(u32 *addr, const u32 *range, + int na, int ns, int pna) +{ + return 0; +} + static void of_bus_pci_count_cells(struct device_node *np, int *addrc, int *sizec) { @@ -369,7 +389,7 @@ static int of_bus_pci_map(u32 *addr, const u32 *range, return 0; } -static unsigned int of_bus_pci_get_flags(u32 *addr) +static unsigned int of_bus_pci_get_flags(const u32 *addr) { unsigned int flags = 0; u32 w = addr[0]; @@ -436,6 +456,15 @@ static struct of_bus of_busses[] = { .map = of_bus_pci_map, .get_flags = of_bus_pci_get_flags, }, + /* SIMBA */ + { + .name = "simba", + .addr_prop_name = "assigned-addresses", + .match = of_bus_simba_match, + .count_cells = of_bus_pci_count_cells, + .map = of_bus_simba_map, + .get_flags = of_bus_pci_get_flags, + }, /* SBUS */ { .name = "sbus", @@ -482,7 +511,7 @@ static int __init build_one_resource(struct device_node *parent, u32 *addr, int na, int ns, int pna) { - u32 *ranges; + const u32 *ranges; unsigned int rlen; int rone; @@ -513,7 +542,7 @@ static int __init build_one_resource(struct device_node *parent, static int __init use_1to1_mapping(struct device_node *pp) { - char *model; + const char *model; /* If this is on the PMU bus, don't try to translate it even * if a ranges property exists. @@ -548,7 +577,7 @@ static void __init build_device_resources(struct of_device *op, struct of_bus *bus; int na, ns; int index, num_reg; - void *preg; + const void *preg; if (!parent) return; @@ -578,7 +607,7 @@ static void __init build_device_resources(struct of_device *op, for (index = 0; index < num_reg; index++) { struct resource *r = &op->resource[index]; u32 addr[OF_MAX_ADDR_CELLS]; - u32 *reg = (preg + (index * ((na + ns) * 4))); + const u32 *reg = (preg + (index * ((na + ns) * 4))); struct device_node *dp = op->node; struct device_node *pp = p_op->node; struct of_bus *pbus, *dbus; @@ -643,14 +672,14 @@ static void __init build_device_resources(struct of_device *op, static struct device_node * __init apply_interrupt_map(struct device_node *dp, struct device_node *pp, - u32 *imap, int imlen, u32 *imask, + const u32 *imap, int imlen, const u32 *imask, unsigned int *irq_p) { struct device_node *cp; unsigned int irq = *irq_p; struct of_bus *bus; phandle handle; - u32 *reg; + const u32 *reg; int na, num_reg, i; bus = of_match_bus(pp); @@ -705,7 +734,7 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp, struct device_node *pp, unsigned int irq) { - struct linux_prom_pci_registers *regs; + const struct linux_prom_pci_registers *regs; unsigned int bus, devfn, slot, ret; if (irq < 1 || irq > 4) @@ -730,12 +759,6 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp, * D: 2-bit slot number, derived from PCI device number as * (dev - 1) for bus A, or (dev - 2) for bus B * L: 2-bit line number - * - * Actually, more "portable" way to calculate the funky - * slot number is to subtract pbm->pci_first_slot from the - * device number, and that's exactly what the pre-OF - * sparc64 code did, but we're building this stuff generically - * using the OBP tree, not in the PCI controller layer. */ if (bus & 0x80) { /* PBM-A */ @@ -794,7 +817,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op, pp = dp->parent; ip = NULL; while (pp) { - void *imap, *imsk; + const void *imap, *imsk; int imlen; imap = of_get_property(pp, "interrupt-map", &imlen); @@ -859,7 +882,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, struct device *parent) { struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); - unsigned int *irq; + const unsigned int *irq; int len, i; if (!op) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 12109886bb1..023af41ad68 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -1,9 +1,11 @@ -/* $Id: pci.c,v 1.39 2002/01/05 01:13:43 davem Exp $ - * pci.c: UltraSparc PCI controller support. +/* pci.c: UltraSparc PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) + * + * OF tree based PCI bus probing taken from the PowerPC port + * with minor modifications, see there for credits. */ #include <linux/module.h> @@ -24,6 +26,9 @@ #include <asm/ebus.h> #include <asm/isa.h> #include <asm/prom.h> +#include <asm/apb.h> + +#include "pci_impl.h" unsigned long pci_memspace_mask = 0xffffffffUL; @@ -277,10 +282,10 @@ int __init pcic_present(void) return pci_controller_scan(pci_is_controller); } -struct pci_iommu_ops *pci_iommu_ops; +const struct pci_iommu_ops *pci_iommu_ops; EXPORT_SYMBOL(pci_iommu_ops); -extern struct pci_iommu_ops pci_sun4u_iommu_ops, +extern const struct pci_iommu_ops pci_sun4u_iommu_ops, pci_sun4v_iommu_ops; /* Find each controller in the system, attach and initialize @@ -300,6 +305,467 @@ static void __init pci_controller_probe(void) pci_controller_scan(pci_controller_init); } +static unsigned long pci_parse_of_flags(u32 addr0) +{ + unsigned long flags = 0; + + if (addr0 & 0x02000000) { + flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; + flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; + flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; + if (addr0 & 0x40000000) + flags |= IORESOURCE_PREFETCH + | PCI_BASE_ADDRESS_MEM_PREFETCH; + } else if (addr0 & 0x01000000) + flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; + return flags; +} + +/* The of_device layer has translated all of the assigned-address properties + * into physical address resources, we only have to figure out the register + * mapping. + */ +static void pci_parse_of_addrs(struct of_device *op, + struct device_node *node, + struct pci_dev *dev) +{ + struct resource *op_res; + const u32 *addrs; + int proplen; + + addrs = of_get_property(node, "assigned-addresses", &proplen); + if (!addrs) + return; + printk(" parse addresses (%d bytes) @ %p\n", proplen, addrs); + op_res = &op->resource[0]; + for (; proplen >= 20; proplen -= 20, addrs += 5, op_res++) { + struct resource *res; + unsigned long flags; + int i; + + flags = pci_parse_of_flags(addrs[0]); + if (!flags) + continue; + i = addrs[0] & 0xff; + printk(" start: %lx, end: %lx, i: %x\n", + op_res->start, op_res->end, i); + + if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) { + res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; + } else if (i == dev->rom_base_reg) { + res = &dev->resource[PCI_ROM_RESOURCE]; + flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE; + } else { + printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); + continue; + } + res->start = op_res->start; + res->end = op_res->end; + res->flags = flags; + res->name = pci_name(dev); + } +} + +struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, + struct device_node *node, + struct pci_bus *bus, int devfn, + int host_controller) +{ + struct dev_archdata *sd; + struct pci_dev *dev; + const char *type; + u32 class; + + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); + if (!dev) + return NULL; + + sd = &dev->dev.archdata; + sd->iommu = pbm->iommu; + sd->stc = &pbm->stc; + sd->host_controller = pbm; + sd->prom_node = node; + sd->op = of_find_device_by_node(node); + sd->msi_num = 0xffffffff; + + type = of_get_property(node, "device_type", NULL); + if (type == NULL) + type = ""; + + printk(" create device, devfn: %x, type: %s hostcontroller(%d)\n", + devfn, type, host_controller); + + dev->bus = bus; + dev->sysdata = node; + dev->dev.parent = bus->bridge; + dev->dev.bus = &pci_bus_type; + dev->devfn = devfn; + dev->multifunction = 0; /* maybe a lie? */ + + if (host_controller) { + dev->vendor = 0x108e; + dev->device = 0x8000; + dev->subsystem_vendor = 0x0000; + dev->subsystem_device = 0x0000; + dev->cfg_size = 256; + dev->class = PCI_CLASS_BRIDGE_HOST << 8; + sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), + 0x00, PCI_SLOT(devfn), PCI_FUNC(devfn)); + } else { + dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); + dev->device = of_getintprop_default(node, "device-id", 0xffff); + dev->subsystem_vendor = + of_getintprop_default(node, "subsystem-vendor-id", 0); + dev->subsystem_device = + of_getintprop_default(node, "subsystem-id", 0); + + dev->cfg_size = pci_cfg_space_size(dev); + + /* We can't actually use the firmware value, we have + * to read what is in the register right now. One + * reason is that in the case of IDE interfaces the + * firmware can sample the value before the the IDE + * interface is programmed into native mode. + */ + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); + dev->class = class >> 8; + + sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), + dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); + } + printk(" class: 0x%x device name: %s\n", + dev->class, pci_name(dev)); + + dev->current_state = 4; /* unknown power state */ + dev->error_state = pci_channel_io_normal; + + if (host_controller) { + dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; + dev->rom_base_reg = PCI_ROM_ADDRESS1; + dev->irq = PCI_IRQ_NONE; + } else { + if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { + /* a PCI-PCI bridge */ + dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; + dev->rom_base_reg = PCI_ROM_ADDRESS1; + } else if (!strcmp(type, "cardbus")) { + dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; + } else { + dev->hdr_type = PCI_HEADER_TYPE_NORMAL; + dev->rom_base_reg = PCI_ROM_ADDRESS; + + dev->irq = sd->op->irqs[0]; + if (dev->irq == 0xffffffff) + dev->irq = PCI_IRQ_NONE; + } + } + pci_parse_of_addrs(sd->op, node, dev); + + printk(" adding to system ...\n"); + + pci_device_add(dev, bus); + + return dev; +} + +static void __init apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) +{ + u32 idx, first, last; + + first = 8; + last = 0; + for (idx = 0; idx < 8; idx++) { + if ((map & (1 << idx)) != 0) { + if (first > idx) + first = idx; + if (last < idx) + last = idx; + } + } + + *first_p = first; + *last_p = last; +} + +static void __init pci_resource_adjust(struct resource *res, + struct resource *root) +{ + res->start += root->start; + res->end += root->start; +} + +/* Cook up fake bus resources for SUNW,simba PCI bridges which lack + * a proper 'ranges' property. + */ +static void __init apb_fake_ranges(struct pci_dev *dev, + struct pci_bus *bus, + struct pci_pbm_info *pbm) +{ + struct resource *res; + u32 first, last; + u8 map; + + pci_read_config_byte(dev, APB_IO_ADDRESS_MAP, &map); + apb_calc_first_last(map, &first, &last); + res = bus->resource[0]; + res->start = (first << 21); + res->end = (last << 21) + ((1 << 21) - 1); + res->flags = IORESOURCE_IO; + pci_resource_adjust(res, &pbm->io_space); + + pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map); + apb_calc_first_last(map, &first, &last); + res = bus->resource[1]; + res->start = (first << 21); + res->end = (last << 21) + ((1 << 21) - 1); + res->flags = IORESOURCE_MEM; + pci_resource_adjust(res, &pbm->mem_space); +} + +static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, + struct device_node *node, + struct pci_bus *bus); + +#define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) + +void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, + struct device_node *node, + struct pci_dev *dev) +{ + struct pci_bus *bus; + const u32 *busrange, *ranges; + int len, i, simba; + struct resource *res; + unsigned int flags; + u64 size; + + printk("of_scan_pci_bridge(%s)\n", node->full_name); + + /* parse bus-range property */ + busrange = of_get_property(node, "bus-range", &len); + if (busrange == NULL || len != 8) { + printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n", + node->full_name); + return; + } + ranges = of_get_property(node, "ranges", &len); + simba = 0; + if (ranges == NULL) { + const char *model = of_get_property(node, "model", NULL); + if (model && !strcmp(model, "SUNW,simba")) { + simba = 1; + } else { + printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", + node->full_name); + return; + } + } + + bus = pci_add_new_bus(dev->bus, dev, busrange[0]); + if (!bus) { + printk(KERN_ERR "Failed to create pci bus for %s\n", + node->full_name); + return; + } + + bus->primary = dev->bus->number; + bus->subordinate = busrange[1]; + bus->bridge_ctl = 0; + + /* parse ranges property, or cook one up by hand for Simba */ + /* PCI #address-cells == 3 and #size-cells == 2 always */ + res = &dev->resource[PCI_BRIDGE_RESOURCES]; + for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { + res->flags = 0; + bus->resource[i] = res; + ++res; + } + if (simba) { + apb_fake_ranges(dev, bus, pbm); + goto simba_cont; + } + i = 1; + for (; len >= 32; len -= 32, ranges += 8) { + struct resource *root; + + flags = pci_parse_of_flags(ranges[0]); + size = GET_64BIT(ranges, 6); + if (flags == 0 || size == 0) + continue; + if (flags & IORESOURCE_IO) { + res = bus->resource[0]; + if (res->flags) { + printk(KERN_ERR "PCI: ignoring extra I/O range" + " for bridge %s\n", node->full_name); + continue; + } + root = &pbm->io_space; + } else { + if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) { + printk(KERN_ERR "PCI: too many memory ranges" + " for bridge %s\n", node->full_name); + continue; + } + res = bus->resource[i]; + ++i; + root = &pbm->mem_space; + } + + res->start = GET_64BIT(ranges, 1); + res->end = res->start + size - 1; + res->flags = flags; + + /* Another way to implement this would be to add an of_device + * layer routine that can calculate a resource for a given + * range property value in a PCI device. + */ + pci_resource_adjust(res, root); + } +simba_cont: + sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), + bus->number); + printk(" bus name: %s\n", bus->name); + + pci_of_scan_bus(pbm, node, bus); +} + +static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, + struct device_node *node, + struct pci_bus *bus) +{ + struct device_node *child; + const u32 *reg; + int reglen, devfn; + struct pci_dev *dev; + + printk("PCI: scan_bus[%s] bus no %d\n", + node->full_name, bus->number); + + child = NULL; + while ((child = of_get_next_child(node, child)) != NULL) { + printk(" * %s\n", child->full_name); + reg = of_get_property(child, "reg", ®len); + if (reg == NULL || reglen < 20) + continue; + devfn = (reg[0] >> 8) & 0xff; + + /* create a new pci_dev for this device */ + dev = of_create_pci_dev(pbm, child, bus, devfn, 0); + if (!dev) + continue; + printk("PCI: dev header type: %x\n", dev->hdr_type); + + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) + of_scan_pci_bridge(pbm, child, dev); + } +} + +static ssize_t +show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char * buf) +{ + struct pci_dev *pdev; + struct device_node *dp; + + pdev = to_pci_dev(dev); + dp = pdev->dev.archdata.prom_node; + + return snprintf (buf, PAGE_SIZE, "%s\n", dp->full_name); +} + +static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL); + +static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) +{ + struct pci_dev *dev; + struct pci_bus *child_bus; + int err; + + list_for_each_entry(dev, &bus->devices, bus_list) { + /* we don't really care if we can create this file or + * not, but we need to assign the result of the call + * or the world will fall under alien invasion and + * everybody will be frozen on a spaceship ready to be + * eaten on alpha centauri by some green and jelly + * humanoid. + */ + err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr); + } + list_for_each_entry(child_bus, &bus->children, node) + pci_bus_register_of_sysfs(child_bus); +} + +int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev, + unsigned int devfn, + int where, int size, + u32 *value) +{ + static u8 fake_pci_config[] = { + 0x8e, 0x10, /* Vendor: 0x108e (Sun) */ + 0x00, 0x80, /* Device: 0x8000 (PBM) */ + 0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */ + 0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */ + 0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */ + 0x00, /* Cacheline: 0x00 */ + 0x40, /* Latency: 0x40 */ + 0x00, /* Header-Type: 0x00 normal */ + }; + + *value = 0; + if (where >= 0 && where < sizeof(fake_pci_config) && + (where + size) >= 0 && + (where + size) < sizeof(fake_pci_config) && + size <= sizeof(u32)) { + while (size--) { + *value <<= 8; + *value |= fake_pci_config[where + size]; + } + } + + return PCIBIOS_SUCCESSFUL; +} + +int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, + unsigned int devfn, + int where, int size, + u32 value) +{ + return PCIBIOS_SUCCESSFUL; +} + +struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm) +{ + struct pci_controller_info *p = pbm->parent; + struct device_node *node = pbm->prom_node; + struct pci_dev *host_pdev; + struct pci_bus *bus; + + printk("PCI: Scanning PBM %s\n", node->full_name); + + /* XXX parent device? XXX */ + bus = pci_create_bus(NULL, pbm->pci_first_busno, p->pci_ops, pbm); + if (!bus) { + printk(KERN_ERR "Failed to create bus for %s\n", + node->full_name); + return NULL; + } + bus->secondary = pbm->pci_first_busno; + bus->subordinate = pbm->pci_last_busno; + + bus->resource[0] = &pbm->io_space; + bus->resource[1] = &pbm->mem_space; + + /* Create the dummy host bridge and link it in. */ + host_pdev = of_create_pci_dev(pbm, node, bus, 0x00, 1); + bus->self = host_pdev; + + pci_of_scan_bus(pbm, node, bus); + pci_bus_add_devices(bus); + pci_bus_register_of_sysfs(bus); + + return bus; +} + static void __init pci_scan_each_controller_bus(void) { struct pci_controller_info *p; @@ -360,8 +826,33 @@ void pcibios_align_resource(void *data, struct resource *res, { } -int pcibios_enable_device(struct pci_dev *pdev, int mask) +int pcibios_enable_device(struct pci_dev *dev, int mask) { + u16 cmd, oldcmd; + int i; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + oldcmd = cmd; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *res = &dev->resource[i]; + + /* Only set up the requested stuff */ + if (!(mask & (1<<i))) + continue; + + if (res->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (res->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + + if (cmd != oldcmd) { + printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n", + pci_name(dev), cmd); + /* Enable the appropriate bits in the PCI command register. */ + pci_write_config_word(dev, PCI_COMMAND, cmd); + } return 0; } @@ -380,7 +871,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region else root = &pbm->mem_space; - pbm->parent->resource_adjust(pdev, &zero_res, root); + pci_resource_adjust(&zero_res, root); region->start = res->start - zero_res.start; region->end = res->end - zero_res.start; @@ -401,7 +892,7 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res, else root = &pbm->mem_space; - pbm->parent->resource_adjust(pdev, res, root); + pci_resource_adjust(res, root); } EXPORT_SYMBOL(pcibios_bus_to_resource); @@ -422,55 +913,17 @@ char * __devinit pcibios_setup(char *str) static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; struct pci_controller_info *p; unsigned long space_size, user_offset, user_size; - if (!pcp) - return -ENXIO; - pbm = pcp->pbm; - if (!pbm) - return -ENXIO; - p = pbm->parent; - if (p->pbms_same_domain) { - unsigned long lowest, highest; - - lowest = ~0UL; highest = 0UL; - if (mmap_state == pci_mmap_io) { - if (p->pbm_A.io_space.flags) { - lowest = p->pbm_A.io_space.start; - highest = p->pbm_A.io_space.end + 1; - } - if (p->pbm_B.io_space.flags) { - if (lowest > p->pbm_B.io_space.start) - lowest = p->pbm_B.io_space.start; - if (highest < p->pbm_B.io_space.end + 1) - highest = p->pbm_B.io_space.end + 1; - } - space_size = highest - lowest; - } else { - if (p->pbm_A.mem_space.flags) { - lowest = p->pbm_A.mem_space.start; - highest = p->pbm_A.mem_space.end + 1; - } - if (p->pbm_B.mem_space.flags) { - if (lowest > p->pbm_B.mem_space.start) - lowest = p->pbm_B.mem_space.start; - if (highest < p->pbm_B.mem_space.end + 1) - highest = p->pbm_B.mem_space.end + 1; - } - space_size = highest - lowest; - } + if (mmap_state == pci_mmap_io) { + space_size = (pbm->io_space.end - + pbm->io_space.start) + 1; } else { - if (mmap_state == pci_mmap_io) { - space_size = (pbm->io_space.end - - pbm->io_space.start) + 1; - } else { - space_size = (pbm->mem_space.end - - pbm->mem_space.start) + 1; - } + space_size = (pbm->mem_space.end - + pbm->mem_space.start) + 1; } /* Make sure the request is in range. */ @@ -481,31 +934,12 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc (user_offset + user_size) > space_size) return -EINVAL; - if (p->pbms_same_domain) { - unsigned long lowest = ~0UL; - - if (mmap_state == pci_mmap_io) { - if (p->pbm_A.io_space.flags) - lowest = p->pbm_A.io_space.start; - if (p->pbm_B.io_space.flags && - lowest > p->pbm_B.io_space.start) - lowest = p->pbm_B.io_space.start; - } else { - if (p->pbm_A.mem_space.flags) - lowest = p->pbm_A.mem_space.start; - if (p->pbm_B.mem_space.flags && - lowest > p->pbm_B.mem_space.start) - lowest = p->pbm_B.mem_space.start; - } - vma->vm_pgoff = (lowest + user_offset) >> PAGE_SHIFT; + if (mmap_state == pci_mmap_io) { + vma->vm_pgoff = (pbm->io_space.start + + user_offset) >> PAGE_SHIFT; } else { - if (mmap_state == pci_mmap_io) { - vma->vm_pgoff = (pbm->io_space.start + - user_offset) >> PAGE_SHIFT; - } else { - vma->vm_pgoff = (pbm->mem_space.start + - user_offset) >> PAGE_SHIFT; - } + vma->vm_pgoff = (pbm->mem_space.start + + user_offset) >> PAGE_SHIFT; } return 0; @@ -639,9 +1073,8 @@ int pci_domain_nr(struct pci_bus *pbus) struct pci_controller_info *p = pbm->parent; ret = p->index; - if (p->pbms_same_domain == 0) - ret = ((ret << 1) + - ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); + ret = ((ret << 1) + + ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); } return ret; @@ -651,8 +1084,7 @@ EXPORT_SYMBOL(pci_domain_nr); #ifdef CONFIG_PCI_MSI int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; struct pci_controller_info *p = pbm->parent; int virt_irq, err; @@ -670,8 +1102,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq) { struct msi_desc *entry = get_irq_msi(virt_irq); struct pci_dev *pdev = entry->dev; - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; struct pci_controller_info *p = pbm->parent; if (!pbm->msi_num || !p->setup_msi_irq) @@ -683,9 +1114,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq) struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) { - struct pcidev_cookie *pc = pdev->sysdata; - - return pc->op->node; + return pdev->dev.archdata.prom_node; } EXPORT_SYMBOL(pci_device_to_OF_node); diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 5a92cb90ebe..1e6aeedf43c 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -1,7 +1,6 @@ -/* $Id: pci_common.c,v 1.29 2002/02/01 00:56:03 davem Exp $ - * pci_common.c: PCI controller common support. +/* pci_common.c: PCI controller common support. * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) + * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) */ #include <linux/string.h> @@ -16,748 +15,137 @@ #include "pci_impl.h" -/* Fix self device of BUS and hook it into BUS->self. - * The pci_scan_bus does not do this for the host bridge. - */ -void __init pci_fixup_host_bridge_self(struct pci_bus *pbus) -{ - struct pci_dev *pdev; - - list_for_each_entry(pdev, &pbus->devices, bus_list) { - if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) { - pbus->self = pdev; - return; - } - } - - prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n"); - prom_halt(); -} - -/* Find the OBP PROM device tree node for a PCI device. */ -static struct device_node * __init -find_device_prom_node(struct pci_pbm_info *pbm, struct pci_dev *pdev, - struct device_node *bus_node, - struct linux_prom_pci_registers **pregs, - int *nregs) +static void pci_register_legacy_regions(struct resource *io_res, + struct resource *mem_res) { - struct device_node *dp; - - *nregs = 0; - - /* - * Return the PBM's PROM node in case we are it's PCI device, - * as the PBM's reg property is different to standard PCI reg - * properties. We would delete this device entry otherwise, - * which confuses XFree86's device probing... - */ - if ((pdev->bus->number == pbm->pci_bus->number) && (pdev->devfn == 0) && - (pdev->vendor == PCI_VENDOR_ID_SUN) && - (pdev->device == PCI_DEVICE_ID_SUN_PBM || - pdev->device == PCI_DEVICE_ID_SUN_SCHIZO || - pdev->device == PCI_DEVICE_ID_SUN_TOMATILLO || - pdev->device == PCI_DEVICE_ID_SUN_SABRE || - pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD)) - return bus_node; - - dp = bus_node->child; - while (dp) { - struct linux_prom_pci_registers *regs; - struct property *prop; - int len; - - prop = of_find_property(dp, "reg", &len); - if (!prop) - goto do_next_sibling; - - regs = prop->value; - if (((regs[0].phys_hi >> 8) & 0xff) == pdev->devfn) { - *pregs = regs; - *nregs = len / sizeof(struct linux_prom_pci_registers); - return dp; - } - - do_next_sibling: - dp = dp->sibling; - } - - return NULL; -} + struct resource *p; -/* Older versions of OBP on PCI systems encode 64-bit MEM - * space assignments incorrectly, this fixes them up. We also - * take the opportunity here to hide other kinds of bogus - * assignments. - */ -static void __init fixup_obp_assignments(struct pci_dev *pdev, - struct pcidev_cookie *pcp) -{ - int i; - - if (pdev->vendor == PCI_VENDOR_ID_AL && - (pdev->device == PCI_DEVICE_ID_AL_M7101 || - pdev->device == PCI_DEVICE_ID_AL_M1533)) { - int i; - - /* Zap all of the normal resources, they are - * meaningless and generate bogus resource collision - * messages. This is OpenBoot's ill-fated attempt to - * represent the implicit resources that these devices - * have. - */ - pcp->num_prom_assignments = 0; - for (i = 0; i < 6; i++) { - pdev->resource[i].start = - pdev->resource[i].end = - pdev->resource[i].flags = 0; - } - pdev->resource[PCI_ROM_RESOURCE].start = - pdev->resource[PCI_ROM_RESOURCE].end = - pdev->resource[PCI_ROM_RESOURCE].flags = 0; + /* VGA Video RAM. */ + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) return; - } - - for (i = 0; i < pcp->num_prom_assignments; i++) { - struct linux_prom_pci_registers *ap; - int space; - ap = &pcp->prom_assignments[i]; - space = ap->phys_hi >> 24; - if ((space & 0x3) == 2 && - (space & 0x4) != 0) { - ap->phys_hi &= ~(0x7 << 24); - ap->phys_hi |= 0x3 << 24; - } - } -} - -static ssize_t -show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char * buf) -{ - struct pci_dev *pdev; - struct pcidev_cookie *sysdata; - - pdev = to_pci_dev(dev); - sysdata = pdev->sysdata; - - return snprintf (buf, PAGE_SIZE, "%s\n", sysdata->prom_node->full_name); -} - -static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL); + p->name = "Video RAM area"; + p->start = mem_res->start + 0xa0000UL; + p->end = p->start + 0x1ffffUL; + p->flags = IORESOURCE_BUSY; + request_resource(mem_res, p); -/* Fill in the PCI device cookie sysdata for the given - * PCI device. This cookie is the means by which one - * can get to OBP and PCI controller specific information - * for a PCI device. - */ -static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - struct device_node *bus_node) -{ - struct linux_prom_pci_registers *pregs = NULL; - struct pcidev_cookie *pcp; - struct device_node *dp; - struct property *prop; - int nregs, len, err; - - dp = find_device_prom_node(pbm, pdev, bus_node, - &pregs, &nregs); - if (!dp) { - /* If it is not in the OBP device tree then - * there must be a damn good reason for it. - * - * So what we do is delete the device from the - * PCI device tree completely. This scenario - * is seen, for example, on CP1500 for the - * second EBUS/HappyMeal pair if the external - * connector for it is not present. - */ - pci_remove_bus_device(pdev); + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) return; - } - - pcp = kzalloc(sizeof(*pcp), GFP_ATOMIC); - if (pcp == NULL) { - prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n"); - prom_halt(); - } - pcp->pbm = pbm; - pcp->prom_node = dp; - pcp->op = of_find_device_by_node(dp); - memcpy(pcp->prom_regs, pregs, - nregs * sizeof(struct linux_prom_pci_registers)); - pcp->num_prom_regs = nregs; - - /* We can't have the pcidev_cookie assignments be just - * direct pointers into the property value, since they - * are potentially modified by the probing process. - */ - prop = of_find_property(dp, "assigned-addresses", &len); - if (!prop) { - pcp->num_prom_assignments = 0; - } else { - memcpy(pcp->prom_assignments, prop->value, len); - pcp->num_prom_assignments = - (len / sizeof(pcp->prom_assignments[0])); - } - - if (strcmp(dp->name, "ebus") == 0) { - struct linux_prom_ebus_ranges *erng; - int iter; - - /* EBUS is special... */ - prop = of_find_property(dp, "ranges", &len); - if (!prop) { - prom_printf("EBUS: Fatal error, no range property\n"); - prom_halt(); - } - erng = prop->value; - len = (len / sizeof(erng[0])); - for (iter = 0; iter < len; iter++) { - struct linux_prom_ebus_ranges *ep = &erng[iter]; - struct linux_prom_pci_registers *ap; - - ap = &pcp->prom_assignments[iter]; - - ap->phys_hi = ep->parent_phys_hi; - ap->phys_mid = ep->parent_phys_mid; - ap->phys_lo = ep->parent_phys_lo; - ap->size_hi = 0; - ap->size_lo = ep->size; - } - pcp->num_prom_assignments = len; - } - - fixup_obp_assignments(pdev, pcp); - - pdev->sysdata = pcp; - - /* we don't really care if we can create this file or not, - * but we need to assign the result of the call or the world will fall - * under alien invasion and everybody will be frozen on a spaceship - * ready to be eaten on alpha centauri by some green and jelly humanoid. - */ - err = sysfs_create_file(&pdev->dev.kobj, &dev_attr_obppath.attr); -} - -void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, - struct pci_pbm_info *pbm, - struct device_node *dp) -{ - struct pci_dev *pdev, *pdev_next; - struct pci_bus *this_pbus, *pbus_next; - - /* This must be _safe because the cookie fillin - routine can delete devices from the tree. */ - list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list) - pdev_cookie_fillin(pbm, pdev, dp); - - list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) { - struct pcidev_cookie *pcp = this_pbus->self->sysdata; - - pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node); - } -} -static void __init bad_assignment(struct pci_dev *pdev, - struct linux_prom_pci_registers *ap, - struct resource *res, - int do_prom_halt) -{ - prom_printf("PCI: Bogus PROM assignment. BUS[%02x] DEVFN[%x]\n", - pdev->bus->number, pdev->devfn); - if (ap) - prom_printf("PCI: phys[%08x:%08x:%08x] size[%08x:%08x]\n", - ap->phys_hi, ap->phys_mid, ap->phys_lo, - ap->size_hi, ap->size_lo); - if (res) - prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n", - res->start, res->end, res->flags); - if (do_prom_halt) - prom_halt(); -} - -static struct resource * -__init get_root_resource(struct linux_prom_pci_registers *ap, - struct pci_pbm_info *pbm) -{ - int space = (ap->phys_hi >> 24) & 3; - - switch (space) { - case 0: - /* Configuration space, silently ignore it. */ - return NULL; - - case 1: - /* 16-bit IO space */ - return &pbm->io_space; - - case 2: - /* 32-bit MEM space */ - return &pbm->mem_space; - - case 3: - /* 64-bit MEM space, these are allocated out of - * the 32-bit mem_space range for the PBM, ie. - * we just zero out the upper 32-bits. - */ - return &pbm->mem_space; - - default: - printk("PCI: What is resource space %x?\n", space); - return NULL; - }; -} - -static struct resource * -__init get_device_resource(struct linux_prom_pci_registers *ap, - struct pci_dev *pdev) -{ - struct resource *res; - int breg = (ap->phys_hi & 0xff); - - switch (breg) { - case PCI_ROM_ADDRESS: - /* Unfortunately I have seen several cases where - * buggy FCODE uses a space value of '1' (I/O space) - * in the register property for the ROM address - * so disable this sanity check for now. - */ -#if 0 - { - int space = (ap->phys_hi >> 24) & 3; - - /* It had better be MEM space. */ - if (space != 2) - bad_assignment(pdev, ap, NULL, 0); - } -#endif - res = &pdev->resource[PCI_ROM_RESOURCE]; - break; - - case PCI_BASE_ADDRESS_0: - case PCI_BASE_ADDRESS_1: - case PCI_BASE_ADDRESS_2: - case PCI_BASE_ADDRESS_3: - case PCI_BASE_ADDRESS_4: - case PCI_BASE_ADDRESS_5: - res = &pdev->resource[(breg - PCI_BASE_ADDRESS_0) / 4]; - break; - - default: - bad_assignment(pdev, ap, NULL, 0); - res = NULL; - break; - }; - - return res; -} - -static void __init pdev_record_assignments(struct pci_pbm_info *pbm, - struct pci_dev *pdev) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - int i; - - for (i = 0; i < pcp->num_prom_assignments; i++) { - struct linux_prom_pci_registers *ap; - struct resource *root, *res; - - /* The format of this property is specified in - * the PCI Bus Binding to IEEE1275-1994. - */ - ap = &pcp->prom_assignments[i]; - root = get_root_resource(ap, pbm); - res = get_device_resource(ap, pdev); - if (root == NULL || res == NULL || - res->flags == 0) - continue; - - /* Ok we know which resource this PROM assignment is - * for, sanity check it. - */ - if ((res->start & 0xffffffffUL) != ap->phys_lo) - bad_assignment(pdev, ap, res, 1); - - /* If it is a 64-bit MEM space assignment, verify that - * the resource is too and that the upper 32-bits match. - */ - if (((ap->phys_hi >> 24) & 3) == 3) { - if (((res->flags & IORESOURCE_MEM) == 0) || - ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - != PCI_BASE_ADDRESS_MEM_TYPE_64)) - bad_assignment(pdev, ap, res, 1); - if ((res->start >> 32) != ap->phys_mid) - bad_assignment(pdev, ap, res, 1); - - /* PBM cannot generate cpu initiated PIOs - * to the full 64-bit space. Therefore the - * upper 32-bits better be zero. If it is - * not, just skip it and we will assign it - * properly ourselves. - */ - if ((res->start >> 32) != 0UL) { - printk(KERN_ERR "PCI: OBP assigns out of range MEM address " - "%016lx for region %ld on device %s\n", - res->start, (res - &pdev->resource[0]), pci_name(pdev)); - continue; - } - } - - /* Adjust the resource into the physical address space - * of this PBM. - */ - pbm->parent->resource_adjust(pdev, res, root); - - if (request_resource(root, res) < 0) { - int rnum; - - /* OK, there is some conflict. But this is fine - * since we'll reassign it in the fixup pass. - * - * Do not print the warning for ROM resources - * as such a conflict is quite common and - * harmless as the ROM bar is disabled. - */ - rnum = (res - &pdev->resource[0]); - if (rnum != PCI_ROM_RESOURCE) - printk(KERN_ERR "PCI: Resource collision, " - "region %d " - "[%016lx:%016lx] of device %s\n", - rnum, - res->start, res->end, - pci_name(pdev)); - } - } -} - -void __init pci_record_assignments(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; + p->name = "System ROM"; + p->start = mem_res->start + 0xf0000UL; + p->end = p->start + 0xffffUL; + p->flags = IORESOURCE_BUSY; + request_resource(mem_res, p); - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_record_assignments(pbm, dev); + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return; - list_for_each_entry(bus, &pbus->children, node) - pci_record_assignments(pbm, bus); + p->name = "Video ROM"; + p->start = mem_res->start + 0xc0000UL; + p->end = p->start + 0x7fffUL; + p->flags = IORESOURCE_BUSY; + request_resource(mem_res, p); } -/* Return non-zero if PDEV has implicit I/O resources even - * though it may not have an I/O base address register - * active. - */ -static int __init has_implicit_io(struct pci_dev *pdev) +static void pci_register_iommu_region(struct pci_pbm_info *pbm) { - int class = pdev->class >> 8; + const u32 *vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); - if (class == PCI_CLASS_NOT_DEFINED || - class == PCI_CLASS_NOT_DEFINED_VGA || - class == PCI_CLASS_STORAGE_IDE || - (pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) - return 1; + if (vdma) { + struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL); - return 0; -} - -static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm, - struct pci_dev *pdev) -{ - u32 reg; - u16 cmd; - int i, io_seen, mem_seen; - - io_seen = mem_seen = 0; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *root, *res; - unsigned long size, min, max, align; - - res = &pdev->resource[i]; - - if (res->flags & IORESOURCE_IO) - io_seen++; - else if (res->flags & IORESOURCE_MEM) - mem_seen++; - - /* If it is already assigned or the resource does - * not exist, there is nothing to do. - */ - if (res->parent != NULL || res->flags == 0UL) - continue; - - /* Determine the root we allocate from. */ - if (res->flags & IORESOURCE_IO) { - root = &pbm->io_space; - min = root->start + 0x400UL; - max = root->end; - } else { - root = &pbm->mem_space; - min = root->start; - max = min + 0x80000000UL; - } - - size = res->end - res->start; - align = size + 1; - if (allocate_resource(root, res, size + 1, min, max, align, NULL, NULL) < 0) { - /* uh oh */ - prom_printf("PCI: Failed to allocate resource %d for %s\n", - i, pci_name(pdev)); + if (!rp) { + prom_printf("Cannot allocate IOMMU resource.\n"); prom_halt(); } - - /* Update PCI config space. */ - pbm->parent->base_address_update(pdev, i); - } - - /* Special case, disable the ROM. Several devices - * act funny (ie. do not respond to memory space writes) - * when it is left enabled. A good example are Qlogic,ISP - * adapters. - */ - pci_read_config_dword(pdev, PCI_ROM_ADDRESS, ®); - reg &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(pdev, PCI_ROM_ADDRESS, reg); - - /* If we saw I/O or MEM resources, enable appropriate - * bits in PCI command register. - */ - if (io_seen || mem_seen) { - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if (io_seen || has_implicit_io(pdev)) - cmd |= PCI_COMMAND_IO; - if (mem_seen) - cmd |= PCI_COMMAND_MEMORY; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - } - - /* If this is a PCI bridge or an IDE controller, - * enable bus mastering. In the former case also - * set the cache line size correctly. - */ - if (((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI) || - (((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) && - ((pdev->class & 0x80) != 0))) { - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - - if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI) - pci_write_config_byte(pdev, - PCI_CACHE_LINE_SIZE, - (64 / sizeof(u32))); + rp->name = "IOMMU"; + rp->start = pbm->mem_space.start + (unsigned long) vdma[0]; + rp->end = rp->start + (unsigned long) vdma[1] - 1UL; + rp->flags = IORESOURCE_BUSY; + request_resource(&pbm->mem_space, rp); } } -void __init pci_assign_unassigned(struct pci_pbm_info *pbm, - struct pci_bus *pbus) +void pci_determine_mem_io_space(struct pci_pbm_info *pbm) { - struct pci_dev *dev; - struct pci_bus *bus; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_assign_unassigned(pbm, dev); + const struct linux_prom_pci_ranges *pbm_ranges; + int i, saw_mem, saw_io; + int num_pbm_ranges; - list_for_each_entry(bus, &pbus->children, node) - pci_assign_unassigned(pbm, bus); -} + saw_mem = saw_io = 0; + pbm_ranges = of_get_property(pbm->prom_node, "ranges", &i); + num_pbm_ranges = i / sizeof(*pbm_ranges); -static void __init pdev_fixup_irq(struct pci_dev *pdev) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct of_device *op = pcp->op; + for (i = 0; i < num_pbm_ranges; i++) { + const struct linux_prom_pci_ranges *pr = &pbm_ranges[i]; + unsigned long a; + u32 parent_phys_hi, parent_phys_lo; + int type; - if (op->irqs[0] == 0xffffffff) { - pdev->irq = PCI_IRQ_NONE; - return; - } + parent_phys_hi = pr->parent_phys_hi; + parent_phys_lo = pr->parent_phys_lo; + if (tlb_type == hypervisor) + parent_phys_hi &= 0x0fffffff; - pdev->irq = op->irqs[0]; + type = (pr->child_phys_hi >> 24) & 0x3; + a = (((unsigned long)parent_phys_hi << 32UL) | + ((unsigned long)parent_phys_lo << 0UL)); - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, - pdev->irq & PCI_IRQ_INO); -} - -void __init pci_fixup_irq(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_fixup_irq(dev); - - list_for_each_entry(bus, &pbus->children, node) - pci_fixup_irq(pbm, bus); -} - -static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz) -{ - u16 cmd; - u8 hdr_type, min_gnt, ltimer; - - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - - /* Read it back, if the mastering bit did not - * get set, the device does not support bus - * mastering so we have nothing to do here. - */ - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if ((cmd & PCI_COMMAND_MASTER) == 0) - return; - - /* Set correct cache line size, 64-byte on all - * Sparc64 PCI systems. Note that the value is - * measured in 32-bit words. - */ - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, - 64 / sizeof(u32)); - - pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr_type); - hdr_type &= ~0x80; - if (hdr_type != PCI_HEADER_TYPE_NORMAL) - return; - - /* If the latency timer is already programmed with a non-zero - * value, assume whoever set it (OBP or whoever) knows what - * they are doing. - */ - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, <imer); - if (ltimer != 0) - return; - - /* XXX Since I'm tipping off the min grant value to - * XXX choose a suitable latency timer value, I also - * XXX considered making use of the max latency value - * XXX as well. Unfortunately I've seen too many bogusly - * XXX low settings for it to the point where it lacks - * XXX any usefulness. In one case, an ethernet card - * XXX claimed a min grant of 10 and a max latency of 5. - * XXX Now, if I had two such cards on the same bus I - * XXX could not set the desired burst period (calculated - * XXX from min grant) without violating the max latency - * XXX bound. Duh... - * XXX - * XXX I blame dumb PC bios implementors for stuff like - * XXX this, most of them don't even try to do something - * XXX sensible with latency timer values and just set some - * XXX default value (usually 32) into every device. - */ - - pci_read_config_byte(pdev, PCI_MIN_GNT, &min_gnt); - - if (min_gnt == 0) { - /* If no min_gnt setting then use a default - * value. - */ - if (is_66mhz) - ltimer = 16; - else - ltimer = 32; - } else { - int shift_factor; - - if (is_66mhz) - shift_factor = 2; - else - shift_factor = 3; - - /* Use a default value when the min_gnt value - * is erroneously high. - */ - if (((unsigned int) min_gnt << shift_factor) > 512 || - ((min_gnt << shift_factor) & 0xff) == 0) { - ltimer = 8 << shift_factor; - } else { - ltimer = min_gnt << shift_factor; - } - } + switch (type) { + case 0: + /* PCI config space, 16MB */ + pbm->config_space = a; + break; - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ltimer); -} + case 1: + /* 16-bit IO space, 16MB */ + pbm->io_space.start = a; + pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL); + pbm->io_space.flags = IORESOURCE_IO; + saw_io = 1; + break; -void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *pdev; - int all_are_66mhz; - u16 status; + case 2: + /* 32-bit MEM space, 2GB */ + pbm->mem_space.start = a; + pbm->mem_space.end = a + (0x80000000UL - 1UL); + pbm->mem_space.flags = IORESOURCE_MEM; + saw_mem = 1; + break; - if (pbm->is_66mhz_capable == 0) { - all_are_66mhz = 0; - goto out; - } + case 3: + /* XXX 64-bit MEM handling XXX */ - all_are_66mhz = 1; - list_for_each_entry(pdev, &pbus->devices, bus_list) { - pci_read_config_word(pdev, PCI_STATUS, &status); - if (!(status & PCI_STATUS_66MHZ)) { - all_are_66mhz = 0; + default: break; - } + }; } -out: - pbm->all_devs_66mhz = all_are_66mhz; - - printk("PCI%d(PBM%c): Bus running at %dMHz\n", - pbm->parent->index, - (pbm == &pbm->parent->pbm_A) ? 'A' : 'B', - (all_are_66mhz ? 66 : 33)); -} - -void pci_setup_busmastering(struct pci_pbm_info *pbm, - struct pci_bus *pbus) -{ - struct pci_dev *dev; - struct pci_bus *bus; - int is_66mhz; - - is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz; - - list_for_each_entry(dev, &pbus->devices, bus_list) - pdev_setup_busmastering(dev, is_66mhz); - - list_for_each_entry(bus, &pbus->children, node) - pci_setup_busmastering(pbm, bus); -} - -void pci_register_legacy_regions(struct resource *io_res, - struct resource *mem_res) -{ - struct resource *p; - - /* VGA Video RAM. */ - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return; - p->name = "Video RAM area"; - p->start = mem_res->start + 0xa0000UL; - p->end = p->start + 0x1ffffUL; - p->flags = IORESOURCE_BUSY; - request_resource(mem_res, p); + if (!saw_io || !saw_mem) { + prom_printf("%s: Fatal error, missing %s PBM range.\n", + pbm->name, + (!saw_io ? "IO" : "MEM")); + prom_halt(); + } - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return; + printk("%s: PCI IO[%lx] MEM[%lx]\n", + pbm->name, + pbm->io_space.start, + pbm->mem_space.start); - p->name = "System ROM"; - p->start = mem_res->start + 0xf0000UL; - p->end = p->start + 0xffffUL; - p->flags = IORESOURCE_BUSY; - request_resource(mem_res, p); + pbm->io_space.name = pbm->mem_space.name = pbm->name; - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return; + request_resource(&ioport_resource, &pbm->io_space); + request_resource(&iomem_resource, &pbm->mem_space); - p->name = "Video ROM"; - p->start = mem_res->start + 0xc0000UL; - p->end = p->start + 0x7fffUL; - p->flags = IORESOURCE_BUSY; - request_resource(mem_res, p); + pci_register_legacy_regions(&pbm->io_space, + &pbm->mem_space); + pci_register_iommu_region(pbm); } /* Generic helper routines for PCI error reporting. */ diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 971e2bea30b..1208583fcb8 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -1,7 +1,6 @@ -/* $Id: pci_impl.h,v 1.9 2001/06/13 06:34:30 davem Exp $ - * pci_impl.h: Helper definitions for PCI controller support. +/* pci_impl.h: Helper definitions for PCI controller support. * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) + * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) */ #ifndef PCI_IMPL_H @@ -13,26 +12,22 @@ #include <asm/prom.h> extern struct pci_controller_info *pci_controller_root; +extern unsigned long pci_memspace_mask; extern int pci_num_controllers; /* PCI bus scanning and fixup support. */ -extern void pci_fixup_host_bridge_self(struct pci_bus *pbus); -extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus, - struct pci_pbm_info *pbm, - struct device_node *prom_node); -extern void pci_record_assignments(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_assign_unassigned(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_fixup_irq(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_setup_busmastering(struct pci_pbm_info *pbm, - struct pci_bus *pbus); -extern void pci_register_legacy_regions(struct resource *io_res, - struct resource *mem_res); +extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); +extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); + +extern int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev, + unsigned int devfn, + int where, int size, + u32 *value); +extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, + unsigned int devfn, + int where, int size, + u32 value); /* Error reporting support. */ extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 7aca0f33f88..66712772f49 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -1,7 +1,6 @@ -/* $Id: pci_iommu.c,v 1.17 2001/12/17 07:05:09 davem Exp $ - * pci_iommu.c: UltraSparc PCI controller IOM/STC support. +/* pci_iommu.c: UltraSparc PCI controller IOM/STC support. * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) + * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) * Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com) */ @@ -36,7 +35,7 @@ "i" (ASI_PHYS_BYPASS_EC_E)) /* Must be invoked under the IOMMU lock. */ -static void __iommu_flushall(struct pci_iommu *iommu) +static void __iommu_flushall(struct iommu *iommu) { unsigned long tag; int entry; @@ -64,7 +63,7 @@ static void __iommu_flushall(struct pci_iommu *iommu) #define IOPTE_IS_DUMMY(iommu, iopte) \ ((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa) -static inline void iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) +static inline void iopte_make_dummy(struct iommu *iommu, iopte_t *iopte) { unsigned long val = iopte_val(*iopte); @@ -75,9 +74,9 @@ static inline void iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) } /* Based largely upon the ppc64 iommu allocator. */ -static long pci_arena_alloc(struct pci_iommu *iommu, unsigned long npages) +static long pci_arena_alloc(struct iommu *iommu, unsigned long npages) { - struct pci_iommu_arena *arena = &iommu->arena; + struct iommu_arena *arena = &iommu->arena; unsigned long n, i, start, end, limit; int pass; @@ -116,7 +115,7 @@ again: return n; } -static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, unsigned long npages) +static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages) { unsigned long i; @@ -124,7 +123,7 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un __clear_bit(i, arena->map); } -void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask) +void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask) { unsigned long i, tsbbase, order, sz, num_tsb_entries; @@ -170,7 +169,7 @@ void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, iopte_make_dummy(iommu, &iommu->page_table[i]); } -static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npages) +static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages) { long entry; @@ -181,12 +180,12 @@ static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npage return iommu->page_table + entry; } -static inline void free_npages(struct pci_iommu *iommu, dma_addr_t base, unsigned long npages) +static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages) { pci_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages); } -static int iommu_alloc_ctx(struct pci_iommu *iommu) +static int iommu_alloc_ctx(struct iommu *iommu) { int lowest = iommu->ctx_lowest_free; int sz = IOMMU_NUM_CTXS - lowest; @@ -205,7 +204,7 @@ static int iommu_alloc_ctx(struct pci_iommu *iommu) return n; } -static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) +static inline void iommu_free_ctx(struct iommu *iommu, int ctx) { if (likely(ctx)) { __clear_bit(ctx, iommu->ctx_bitmap); @@ -220,8 +219,7 @@ static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) */ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; + struct iommu *iommu; iopte_t *iopte; unsigned long flags, order, first_page; void *ret; @@ -237,8 +235,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr return NULL; memset((char *)first_page, 0, PAGE_SIZE << order); - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; + iommu = pdev->dev.archdata.iommu; spin_lock_irqsave(&iommu->lock, flags); iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT); @@ -268,14 +265,12 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr /* Free and unmap a consistent DMA translation. */ static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; + struct iommu *iommu; iopte_t *iopte; unsigned long flags, order, npages; npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; + iommu = pdev->dev.archdata.iommu; iopte = iommu->page_table + ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); @@ -295,18 +290,16 @@ static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, */ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; + struct iommu *iommu; + struct strbuf *strbuf; iopte_t *base; unsigned long flags, npages, oaddr; unsigned long i, base_paddr, ctx; u32 bus_addr, ret; unsigned long iopte_protection; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; if (unlikely(direction == PCI_DMA_NONE)) goto bad_no_ctx; @@ -349,7 +342,7 @@ bad_no_ctx: return PCI_DMA_ERROR_CODE; } -static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction) +static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction) { int limit; @@ -416,9 +409,8 @@ do_flush_sync: /* Unmap a single streaming mode DMA translation. */ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; + struct iommu *iommu; + struct strbuf *strbuf; iopte_t *base; unsigned long flags, npages, ctx, i; @@ -428,9 +420,8 @@ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_ return; } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); npages >>= IO_PAGE_SHIFT; @@ -549,9 +540,8 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, */ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; + struct iommu *iommu; + struct strbuf *strbuf; unsigned long flags, ctx, npages, iopte_protection; iopte_t *base; u32 dma_base; @@ -570,9 +560,8 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n return 1; } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; if (unlikely(direction == PCI_DMA_NONE)) goto bad_no_ctx; @@ -636,9 +625,8 @@ bad_no_ctx: /* Unmap a set of streaming mode DMA translations. */ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; + struct iommu *iommu; + struct strbuf *strbuf; iopte_t *base; unsigned long flags, ctx, i, npages; u32 bus_addr; @@ -648,9 +636,8 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in WARN_ON(1); } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; bus_addr = sglist->dma_address & IO_PAGE_MASK; @@ -696,14 +683,12 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in */ static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; + struct iommu *iommu; + struct strbuf *strbuf; unsigned long flags, ctx, npages; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; if (!strbuf->strbuf_enabled) return; @@ -736,15 +721,13 @@ static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_ */ static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; - struct pci_strbuf *strbuf; + struct iommu *iommu; + struct strbuf *strbuf; unsigned long flags, ctx, npages, i; u32 bus_addr; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - strbuf = &pcp->pbm->stc; + iommu = pdev->dev.archdata.iommu; + strbuf = pdev->dev.archdata.stc; if (!strbuf->strbuf_enabled) return; @@ -775,7 +758,7 @@ static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist spin_unlock_irqrestore(&iommu->lock, flags); } -struct pci_iommu_ops pci_sun4u_iommu_ops = { +const struct pci_iommu_ops pci_sun4u_iommu_ops = { .alloc_consistent = pci_4u_alloc_consistent, .free_consistent = pci_4u_free_consistent, .map_single = pci_4u_map_single, @@ -809,13 +792,12 @@ static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) int pci_dma_supported(struct pci_dev *pdev, u64 device_mask) { - struct pcidev_cookie *pcp = pdev->sysdata; u64 dma_addr_mask; if (pdev == NULL) { dma_addr_mask = 0xffffffff; } else { - struct pci_iommu *iommu = pcp->pbm->iommu; + struct iommu *iommu = pdev->dev.archdata.iommu; dma_addr_mask = iommu->dma_addr_mask; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index fda5db223d9..253d40ec224 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1,7 +1,6 @@ -/* $Id: pci_psycho.c,v 1.33 2002/02/01 00:58:33 davem Exp $ - * pci_psycho.c: PSYCHO/U2P specific PCI controller support. +/* pci_psycho.c: PSYCHO/U2P specific PCI controller support. * - * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) + * Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) */ @@ -119,6 +118,10 @@ static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, u16 tmp16; u8 tmp8; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); + switch (size) { case 1: *value = 0xff; @@ -172,6 +175,9 @@ static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned char bus = bus_dev->number; u32 *addr; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; @@ -263,7 +269,7 @@ static void __psycho_check_one_stc(struct pci_controller_info *p, struct pci_pbm_info *pbm, int is_pbm_a) { - struct pci_strbuf *strbuf = &pbm->stc; + struct strbuf *strbuf = &pbm->stc; unsigned long regbase = p->pbm_A.controller_regs; unsigned long err_base, tag_base, line_base; u64 control; @@ -412,7 +418,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, unsigned long afar, enum psycho_error_type type) { - struct pci_iommu *iommu = p->pbm_A.iommu; + struct iommu *iommu = p->pbm_A.iommu; unsigned long iommu_tag[16]; unsigned long iommu_data[16]; unsigned long flags; @@ -895,59 +901,6 @@ static void psycho_register_error_handlers(struct pci_controller_info *p) } /* PSYCHO boot time probing and initialization. */ -static void psycho_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - res->start += root->start; - res->end += root->start; -} - -static void psycho_base_address_update(struct pci_dev *pdev, int resource) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; - struct resource *res, *root; - u32 reg; - int where, size, is_64bit; - - res = &pdev->resource[resource]; - if (resource < 6) { - where = PCI_BASE_ADDRESS_0 + (resource * 4); - } else if (resource == PCI_ROM_RESOURCE) { - where = pdev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - is_64bit = 0; - if (res->flags & IORESOURCE_IO) - root = &pbm->io_space; - else { - root = &pbm->mem_space; - if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - == PCI_BASE_ADDRESS_MEM_TYPE_64) - is_64bit = 1; - } - - size = res->end - res->start; - pci_read_config_dword(pdev, where, ®); - reg = ((reg & size) | - (((u32)(res->start - root->start)) & ~size)); - if (resource == PCI_ROM_RESOURCE) { - reg |= PCI_ROM_ADDRESS_ENABLE; - res->flags |= IORESOURCE_ROM_ENABLE; - } - pci_write_config_dword(pdev, where, reg); - - /* This knows that the upper 32-bits of the address - * must be zero. Our PCI common layer enforces this. - */ - if (is_64bit) - pci_write_config_dword(pdev, where + 4, 0); -} - static void pbm_config_busmastering(struct pci_pbm_info *pbm) { u8 *addr; @@ -968,28 +921,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) static void pbm_scan_bus(struct pci_controller_info *p, struct pci_pbm_info *pbm) { - struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("PSYCHO: Critical allocation failure.\n"); - prom_halt(); - } - - /* All we care about is the PBM. */ - cookie->pbm = pbm; - - pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, - p->pci_ops, - pbm); - pci_fixup_host_bridge_self(pbm->pci_bus); - pbm->pci_bus->self->sysdata = cookie; - - pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbm->pci_bus); - pci_assign_unassigned(pbm, pbm->pci_bus); - pci_fixup_irq(pbm, pbm->pci_bus); - pci_determine_66mhz_disposition(pbm, pbm->pci_bus); - pci_setup_busmastering(pbm, pbm->pci_bus); + pbm->pci_bus = pci_scan_one_pbm(pbm); } static void psycho_scan_bus(struct pci_controller_info *p) @@ -1009,7 +941,7 @@ static void psycho_scan_bus(struct pci_controller_info *p) static void psycho_iommu_init(struct pci_controller_info *p) { - struct pci_iommu *iommu = p->pbm_A.iommu; + struct iommu *iommu = p->pbm_A.iommu; unsigned long i; u64 control; @@ -1094,19 +1026,6 @@ static void psycho_controller_hwinit(struct pci_controller_info *p) psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp); } -static void pbm_register_toplevel_resources(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - char *name = pbm->name; - - pbm->io_space.name = pbm->mem_space.name = name; - - request_resource(&ioport_resource, &pbm->io_space); - request_resource(&iomem_resource, &pbm->mem_space); - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); -} - static void psycho_pbm_strbuf_init(struct pci_controller_info *p, struct pci_pbm_info *pbm, int is_pbm_a) @@ -1172,19 +1091,11 @@ static void psycho_pbm_init(struct pci_controller_info *p, unsigned int *busrange; struct property *prop; struct pci_pbm_info *pbm; - int len; - if (is_pbm_a) { + if (is_pbm_a) pbm = &p->pbm_A; - pbm->pci_first_slot = 1; - pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_A; - pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_A; - } else { + else pbm = &p->pbm_B; - pbm->pci_first_slot = 2; - pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_B; - pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_B; - } pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; pbm->chip_version = 0; @@ -1196,41 +1107,15 @@ static void psycho_pbm_init(struct pci_controller_info *p, if (prop) pbm->chip_revision = *(int *) prop->value; - pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE; - pbm->io_space.flags = IORESOURCE_IO; - pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE; - pbm->mem_space.flags = IORESOURCE_MEM; - pbm->parent = p; pbm->prom_node = dp; pbm->name = dp->full_name; - pbm_register_toplevel_resources(p, pbm); - printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", pbm->name, pbm->chip_version, pbm->chip_revision); - prop = of_find_property(dp, "ranges", &len); - if (prop) { - pbm->pbm_ranges = prop->value; - pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - } else { - pbm->num_pbm_ranges = 0; - } - - prop = of_find_property(dp, "interrupt-map", &len); - if (prop) { - pbm->pbm_intmap = prop->value; - pbm->num_pbm_intmap = - (len / sizeof(struct linux_prom_pci_intmap)); - - prop = of_find_property(dp, "interrupt-map-mask", NULL); - pbm->pbm_intmask = prop->value; - } else { - pbm->num_pbm_intmap = 0; - } + pci_determine_mem_io_space(pbm); prop = of_find_property(dp, "bus-range", NULL); busrange = prop->value; @@ -1246,7 +1131,7 @@ void psycho_init(struct device_node *dp, char *model_name) { struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; - struct pci_iommu *iommu; + struct iommu *iommu; struct property *prop; u32 upa_portid; int is_pbm_a; @@ -1269,7 +1154,7 @@ void psycho_init(struct device_node *dp, char *model_name) prom_printf("PSYCHO: Fatal memory allocation error.\n"); prom_halt(); } - iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC); + iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { prom_printf("PSYCHO: Fatal memory allocation error.\n"); prom_halt(); @@ -1282,10 +1167,7 @@ void psycho_init(struct device_node *dp, char *model_name) p->pbm_A.portid = upa_portid; p->pbm_B.portid = upa_portid; p->index = pci_num_controllers++; - p->pbms_same_domain = 0; p->scan_bus = psycho_scan_bus; - p->base_address_update = psycho_base_address_update; - p->resource_adjust = psycho_resource_adjust; p->pci_ops = &psycho_ops; prop = of_find_property(dp, "reg", NULL); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 94bb681f232..397862fbd9e 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1,7 +1,6 @@ -/* $Id: pci_sabre.c,v 1.42 2002/01/23 11:27:32 davem Exp $ - * pci_sabre.c: Sabre specific PCI controller support. +/* pci_sabre.c: Sabre specific PCI controller support. * - * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) + * Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) */ @@ -254,9 +253,6 @@ static int __sabre_out_of_range(struct pci_pbm_info *pbm, return 0; return ((pbm->parent == 0) || - ((pbm == &pbm->parent->pbm_B) && - (bus == pbm->pci_first_busno) && - PCI_SLOT(devfn) > 8) || ((pbm == &pbm->parent->pbm_A) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8)); @@ -322,6 +318,12 @@ static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { + struct pci_pbm_info *pbm = bus->sysdata; + + if (bus == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus, devfn, where, + size, value); + if (!bus->number && sabre_out_of_range(devfn)) { switch (size) { case 1: @@ -438,6 +440,12 @@ static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { + struct pci_pbm_info *pbm = bus->sysdata; + + if (bus == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus, devfn, where, + size, value); + if (bus->number) return __sabre_write_pci_cfg(bus, devfn, where, size, value); @@ -490,7 +498,7 @@ static void sabre_check_iommu_error(struct pci_controller_info *p, unsigned long afsr, unsigned long afar) { - struct pci_iommu *iommu = p->pbm_A.iommu; + struct iommu *iommu = p->pbm_A.iommu; unsigned long iommu_tag[16]; unsigned long iommu_data[16]; unsigned long flags; @@ -710,8 +718,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) p->index); ret = IRQ_HANDLED; } - pci_read_config_word(sabre_root_bus->self, - PCI_STATUS, &stat); + pci_bus_read_config_word(sabre_root_bus, 0, + PCI_STATUS, &stat); if (stat & (PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | PCI_STATUS_REC_TARGET_ABORT | @@ -719,8 +727,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) PCI_STATUS_SIG_SYSTEM_ERROR)) { printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n", p->index, stat); - pci_write_config_word(sabre_root_bus->self, - PCI_STATUS, 0xffff); + pci_bus_write_config_word(sabre_root_bus, 0, + PCI_STATUS, 0xffff); ret = IRQ_HANDLED; } return ret; @@ -800,12 +808,10 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { sabre_check_iommu_error(p, afsr, afar); pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_target_abort(p, &p->pbm_B, p->pbm_B.pci_bus); } - if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) { + if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_master_abort(p, &p->pbm_B, p->pbm_B.pci_bus); - } + /* For excessive retries, SABRE/PBM will abort the device * and there is no way to specifically check for excessive * retries in the config space status registers. So what @@ -813,10 +819,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) * abort events. */ - if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) { + if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus); - pci_scan_for_parity_error(p, &p->pbm_B, p->pbm_B.pci_bus); - } return IRQ_HANDLED; } @@ -869,144 +873,52 @@ static void sabre_register_error_handlers(struct pci_controller_info *p) sabre_write(base + SABRE_PCICTRL, tmp); } -static void sabre_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - struct pci_pbm_info *pbm = pdev->bus->sysdata; - unsigned long base; - - if (res->flags & IORESOURCE_IO) - base = pbm->controller_regs + SABRE_IOSPACE; - else - base = pbm->controller_regs + SABRE_MEMSPACE; - - res->start += base; - res->end += base; -} - -static void sabre_base_address_update(struct pci_dev *pdev, int resource) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; - struct resource *res; - unsigned long base; - u32 reg; - int where, size, is_64bit; - - res = &pdev->resource[resource]; - if (resource < 6) { - where = PCI_BASE_ADDRESS_0 + (resource * 4); - } else if (resource == PCI_ROM_RESOURCE) { - where = pdev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - is_64bit = 0; - if (res->flags & IORESOURCE_IO) - base = pbm->controller_regs + SABRE_IOSPACE; - else { - base = pbm->controller_regs + SABRE_MEMSPACE; - if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - == PCI_BASE_ADDRESS_MEM_TYPE_64) - is_64bit = 1; - } - - size = res->end - res->start; - pci_read_config_dword(pdev, where, ®); - reg = ((reg & size) | - (((u32)(res->start - base)) & ~size)); - if (resource == PCI_ROM_RESOURCE) { - reg |= PCI_ROM_ADDRESS_ENABLE; - res->flags |= IORESOURCE_ROM_ENABLE; - } - pci_write_config_dword(pdev, where, reg); - - /* This knows that the upper 32-bits of the address - * must be zero. Our PCI common layer enforces this. - */ - if (is_64bit) - pci_write_config_dword(pdev, where + 4, 0); -} - static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) { struct pci_dev *pdev; list_for_each_entry(pdev, &sabre_bus->devices, bus_list) { - if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { - u32 word32; u16 word16; - sabre_read_pci_cfg(pdev->bus, pdev->devfn, - PCI_COMMAND, 2, &word32); - word16 = (u16) word32; + pci_read_config_word(pdev, PCI_COMMAND, &word16); word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; - word32 = (u32) word16; - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_COMMAND, 2, word32); + pci_write_config_word(pdev, PCI_COMMAND, word16); /* Status register bits are "write 1 to clear". */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_STATUS, 2, 0xffff); - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_SEC_STATUS, 2, 0xffff); + pci_write_config_word(pdev, PCI_STATUS, 0xffff); + pci_write_config_word(pdev, PCI_SEC_STATUS, 0xffff); /* Use a primary/seconday latency timer value * of 64. */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_LATENCY_TIMER, 1, 64); - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_SEC_LATENCY_TIMER, 1, 64); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); + pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64); /* Enable reporting/forwarding of master aborts, * parity, and SERR. */ - sabre_write_pci_cfg(pdev->bus, pdev->devfn, - PCI_BRIDGE_CONTROL, 1, - (PCI_BRIDGE_CTL_PARITY | - PCI_BRIDGE_CTL_SERR | - PCI_BRIDGE_CTL_MASTER_ABORT)); + pci_write_config_byte(pdev, PCI_BRIDGE_CONTROL, + (PCI_BRIDGE_CTL_PARITY | + PCI_BRIDGE_CTL_SERR | + PCI_BRIDGE_CTL_MASTER_ABORT)); } } } -static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm) -{ - struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("SABRE: Critical allocation failure.\n"); - prom_halt(); - } - - /* All we care about is the PBM. */ - cookie->pbm = pbm; - - return cookie; -} - static void sabre_scan_bus(struct pci_controller_info *p) { static int once; - struct pci_bus *sabre_bus, *pbus; - struct pci_pbm_info *pbm; - struct pcidev_cookie *cookie; - int sabres_scanned; + struct pci_bus *pbus; /* The APB bridge speaks to the Sabre host PCI bridge * at 66Mhz, but the front side of APB runs at 33Mhz * for both segments. */ p->pbm_A.is_66mhz_capable = 0; - p->pbm_B.is_66mhz_capable = 0; /* This driver has not been verified to handle * multiple SABREs yet, so trap this. @@ -1020,56 +932,13 @@ static void sabre_scan_bus(struct pci_controller_info *p) } once++; - cookie = alloc_bridge_cookie(&p->pbm_A); - - sabre_bus = pci_scan_bus(p->pci_first_busno, - p->pci_ops, - &p->pbm_A); - pci_fixup_host_bridge_self(sabre_bus); - sabre_bus->self->sysdata = cookie; - - sabre_root_bus = sabre_bus; - - apb_init(p, sabre_bus); - - sabres_scanned = 0; - - list_for_each_entry(pbus, &sabre_bus->children, node) { - - if (pbus->number == p->pbm_A.pci_first_busno) { - pbm = &p->pbm_A; - } else if (pbus->number == p->pbm_B.pci_first_busno) { - pbm = &p->pbm_B; - } else - continue; - - cookie = alloc_bridge_cookie(pbm); - pbus->self->sysdata = cookie; - - sabres_scanned++; + pbus = pci_scan_one_pbm(&p->pbm_A); + if (!pbus) + return; - pbus->sysdata = pbm; - pbm->pci_bus = pbus; - pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbus); - pci_assign_unassigned(pbm, pbus); - pci_fixup_irq(pbm, pbus); - pci_determine_66mhz_disposition(pbm, pbus); - pci_setup_busmastering(pbm, pbus); - } + sabre_root_bus = pbus; - if (!sabres_scanned) { - /* Hummingbird, no APBs. */ - pbm = &p->pbm_A; - sabre_bus->sysdata = pbm; - pbm->pci_bus = sabre_bus; - pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, sabre_bus); - pci_assign_unassigned(pbm, sabre_bus); - pci_fixup_irq(pbm, sabre_bus); - pci_determine_66mhz_disposition(pbm, sabre_bus); - pci_setup_busmastering(pbm, sabre_bus); - } + apb_init(p, pbus); sabre_register_error_handlers(p); } @@ -1078,7 +947,7 @@ static void sabre_iommu_init(struct pci_controller_info *p, int tsbsize, unsigned long dvma_offset, u32 dma_mask) { - struct pci_iommu *iommu = p->pbm_A.iommu; + struct iommu *iommu = p->pbm_A.iommu; unsigned long i; u64 control; @@ -1126,224 +995,31 @@ static void sabre_iommu_init(struct pci_controller_info *p, sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); } -static void pbm_register_toplevel_resources(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - char *name = pbm->name; - unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE; - unsigned long mbase = p->pbm_A.controller_regs + SABRE_MEMSPACE; - unsigned int devfn; - unsigned long first, last, i; - u8 *addr, map; - - sprintf(name, "SABRE%d PBM%c", - p->index, - (pbm == &p->pbm_A ? 'A' : 'B')); - pbm->io_space.name = pbm->mem_space.name = name; - - devfn = PCI_DEVFN(1, (pbm == &p->pbm_A) ? 0 : 1); - addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_IO_ADDRESS_MAP); - map = 0; - pci_config_read8(addr, &map); - - first = 8; - last = 0; - for (i = 0; i < 8; i++) { - if ((map & (1 << i)) != 0) { - if (first > i) - first = i; - if (last < i) - last = i; - } - } - pbm->io_space.start = ibase + (first << 21UL); - pbm->io_space.end = ibase + (last << 21UL) + ((1 << 21UL) - 1); - pbm->io_space.flags = IORESOURCE_IO; - - addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_MEM_ADDRESS_MAP); - map = 0; - pci_config_read8(addr, &map); - - first = 8; - last = 0; - for (i = 0; i < 8; i++) { - if ((map & (1 << i)) != 0) { - if (first > i) - first = i; - if (last < i) - last = i; - } - } - pbm->mem_space.start = mbase + (first << 29UL); - pbm->mem_space.end = mbase + (last << 29UL) + ((1 << 29UL) - 1); - pbm->mem_space.flags = IORESOURCE_MEM; - - if (request_resource(&ioport_resource, &pbm->io_space) < 0) { - prom_printf("Cannot register PBM-%c's IO space.\n", - (pbm == &p->pbm_A ? 'A' : 'B')); - prom_halt(); - } - if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { - prom_printf("Cannot register PBM-%c's MEM space.\n", - (pbm == &p->pbm_A ? 'A' : 'B')); - prom_halt(); - } - - /* Register legacy regions if this PBM covers that area. */ - if (pbm->io_space.start == ibase && - pbm->mem_space.start == mbase) - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); -} - -static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end) +static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp) { struct pci_pbm_info *pbm; - struct device_node *node; - struct property *prop; - u32 *busrange; - int len, simbas_found; - - simbas_found = 0; - node = dp->child; - while (node != NULL) { - if (strcmp(node->name, "pci")) - goto next_pci; - - prop = of_find_property(node, "model", NULL); - if (!prop || strncmp(prop->value, "SUNW,simba", prop->length)) - goto next_pci; - - simbas_found++; - - prop = of_find_property(node, "bus-range", NULL); - busrange = prop->value; - if (busrange[0] == 1) - pbm = &p->pbm_B; - else - pbm = &p->pbm_A; - - pbm->name = node->full_name; - printk("%s: SABRE PCI Bus Module\n", pbm->name); - - pbm->chip_type = PBM_CHIP_TYPE_SABRE; - pbm->parent = p; - pbm->prom_node = node; - pbm->pci_first_slot = 1; - pbm->pci_first_busno = busrange[0]; - pbm->pci_last_busno = busrange[1]; - - prop = of_find_property(node, "ranges", &len); - if (prop) { - pbm->pbm_ranges = prop->value; - pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - } else { - pbm->num_pbm_ranges = 0; - } - prop = of_find_property(node, "interrupt-map", &len); - if (prop) { - pbm->pbm_intmap = prop->value; - pbm->num_pbm_intmap = - (len / sizeof(struct linux_prom_pci_intmap)); - - prop = of_find_property(node, "interrupt-map-mask", - NULL); - pbm->pbm_intmask = prop->value; - } else { - pbm->num_pbm_intmap = 0; - } + pbm = &p->pbm_A; + pbm->name = dp->full_name; + printk("%s: SABRE PCI Bus Module\n", pbm->name); - pbm_register_toplevel_resources(p, pbm); - - next_pci: - node = node->sibling; - } - if (simbas_found == 0) { - struct resource *rp; + pbm->chip_type = PBM_CHIP_TYPE_SABRE; + pbm->parent = p; + pbm->prom_node = dp; + pbm->pci_first_busno = p->pci_first_busno; + pbm->pci_last_busno = p->pci_last_busno; - /* No APBs underneath, probably this is a hummingbird - * system. - */ - pbm = &p->pbm_A; - pbm->parent = p; - pbm->prom_node = dp; - pbm->pci_first_busno = p->pci_first_busno; - pbm->pci_last_busno = p->pci_last_busno; - - prop = of_find_property(dp, "ranges", &len); - if (prop) { - pbm->pbm_ranges = prop->value; - pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - } else { - pbm->num_pbm_ranges = 0; - } - - prop = of_find_property(dp, "interrupt-map", &len); - if (prop) { - pbm->pbm_intmap = prop->value; - pbm->num_pbm_intmap = - (len / sizeof(struct linux_prom_pci_intmap)); - - prop = of_find_property(dp, "interrupt-map-mask", - NULL); - pbm->pbm_intmask = prop->value; - } else { - pbm->num_pbm_intmap = 0; - } - - pbm->name = dp->full_name; - printk("%s: SABRE PCI Bus Module\n", pbm->name); - - pbm->io_space.name = pbm->mem_space.name = pbm->name; - - /* Hack up top-level resources. */ - pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE; - pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; - pbm->io_space.flags = IORESOURCE_IO; - - pbm->mem_space.start = - (p->pbm_A.controller_regs + SABRE_MEMSPACE); - pbm->mem_space.end = - (pbm->mem_space.start + ((1UL << 32UL) - 1UL)); - pbm->mem_space.flags = IORESOURCE_MEM; - - if (request_resource(&ioport_resource, &pbm->io_space) < 0) { - prom_printf("Cannot register Hummingbird's IO space.\n"); - prom_halt(); - } - if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { - prom_printf("Cannot register Hummingbird's MEM space.\n"); - prom_halt(); - } - - rp = kmalloc(sizeof(*rp), GFP_KERNEL); - if (!rp) { - prom_printf("Cannot allocate IOMMU resource.\n"); - prom_halt(); - } - rp->name = "IOMMU"; - rp->start = pbm->mem_space.start + (unsigned long) dma_start; - rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL; - rp->flags = IORESOURCE_BUSY; - request_resource(&pbm->mem_space, rp); - - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); - } + pci_determine_mem_io_space(pbm); } void sabre_init(struct device_node *dp, char *model_name) { - struct linux_prom64_registers *pr_regs; + const struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; - struct pci_iommu *iommu; - struct property *prop; + struct iommu *iommu; int tsbsize; - u32 *busrange; - u32 *vdma; + const u32 *busrange; + const u32 *vdma; u32 upa_portid, dma_mask; u64 clear_irq; @@ -1351,13 +1027,9 @@ void sabre_init(struct device_node *dp, char *model_name) if (!strcmp(model_name, "pci108e,a001")) hummingbird_p = 1; else if (!strcmp(model_name, "SUNW,sabre")) { - prop = of_find_property(dp, "compatible", NULL); - if (prop) { - const char *compat = prop->value; - - if (!strcmp(compat, "pci108e,a001")) - hummingbird_p = 1; - } + const char *compat = of_get_property(dp, "compatible", NULL); + if (compat && !strcmp(compat, "pci108e,a001")) + hummingbird_p = 1; if (!hummingbird_p) { struct device_node *dp; @@ -1381,37 +1053,28 @@ void sabre_init(struct device_node *dp, char *model_name) prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n"); prom_halt(); } - p->pbm_A.iommu = p->pbm_B.iommu = iommu; + p->pbm_A.iommu = iommu; - upa_portid = 0xff; - prop = of_find_property(dp, "upa-portid", NULL); - if (prop) - upa_portid = *(u32 *) prop->value; + upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); p->next = pci_controller_root; pci_controller_root = p; p->pbm_A.portid = upa_portid; - p->pbm_B.portid = upa_portid; p->index = pci_num_controllers++; - p->pbms_same_domain = 1; p->scan_bus = sabre_scan_bus; - p->base_address_update = sabre_base_address_update; - p->resource_adjust = sabre_resource_adjust; p->pci_ops = &sabre_ops; /* * Map in SABRE register set and report the presence of this SABRE. */ - prop = of_find_property(dp, "reg", NULL); - pr_regs = prop->value; + pr_regs = of_get_property(dp, "reg", NULL); /* * First REG in property is base of entire SABRE register space. */ p->pbm_A.controller_regs = pr_regs[0].phys_addr; - p->pbm_B.controller_regs = pr_regs[0].phys_addr; /* Clear interrupts */ @@ -1429,11 +1092,10 @@ void sabre_init(struct device_node *dp, char *model_name) SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); /* Now map in PCI config space for entire SABRE. */ - p->pbm_A.config_space = p->pbm_B.config_space = + p->pbm_A.config_space = (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); - prop = of_find_property(dp, "virtual-dma", NULL); - vdma = prop->value; + vdma = of_get_property(dp, "virtual-dma", NULL); dma_mask = vdma[0]; switch(vdma[1]) { @@ -1457,13 +1119,12 @@ void sabre_init(struct device_node *dp, char *model_name) sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); - prop = of_find_property(dp, "bus-range", NULL); - busrange = prop->value; + busrange = of_get_property(dp, "bus-range", NULL); p->pci_first_busno = busrange[0]; p->pci_last_busno = busrange[1]; /* * Look for APB underneath. */ - sabre_pbm_init(p, dp, vdma[0], vdma[0] + vdma[1]); + sabre_pbm_init(p, dp); } diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 66911b126ae..91a7385e5d3 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1,7 +1,6 @@ -/* $Id: pci_schizo.c,v 1.24 2002/01/23 11:27:32 davem Exp $ - * pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support. +/* pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support. * - * Copyright (C) 2001, 2002, 2003 David S. Miller (davem@redhat.com) + * Copyright (C) 2001, 2002, 2003, 2007 David S. Miller (davem@davemloft.net) */ #include <linux/kernel.h> @@ -126,6 +125,9 @@ static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, u16 tmp16; u8 tmp8; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); switch (size) { case 1: *value = 0xff; @@ -179,6 +181,9 @@ static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned char bus = bus_dev->number; u32 *addr; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; @@ -274,7 +279,7 @@ struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm, enum schizo_error_type type) { - struct pci_strbuf *strbuf = &pbm->stc; + struct strbuf *strbuf = &pbm->stc; unsigned long regbase = pbm->pbm_regs; unsigned long err_base, tag_base, line_base; u64 control; @@ -382,7 +387,7 @@ static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm, static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, enum schizo_error_type type) { - struct pci_iommu *iommu = pbm->iommu; + struct iommu *iommu = pbm->iommu; unsigned long iommu_tag[16]; unsigned long iommu_data[16]; unsigned long flags; @@ -1229,42 +1234,8 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void pbm_scan_bus(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("%s: Critical allocation failure.\n", pbm->name); - prom_halt(); - } - - /* All we care about is the PBM. */ - cookie->pbm = pbm; - - pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, - p->pci_ops, - pbm); - pci_fixup_host_bridge_self(pbm->pci_bus); - pbm->pci_bus->self->sysdata = cookie; - - pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbm->pci_bus); - pci_assign_unassigned(pbm, pbm->pci_bus); - pci_fixup_irq(pbm, pbm->pci_bus); - pci_determine_66mhz_disposition(pbm, pbm->pci_bus); - pci_setup_busmastering(pbm, pbm->pci_bus); -} - -static void __schizo_scan_bus(struct pci_controller_info *p, - int chip_type) +static void schizo_scan_bus(struct pci_controller_info *p) { - if (!p->pbm_B.prom_node || !p->pbm_A.prom_node) { - printk("PCI: Only one PCI bus module of controller found.\n"); - printk("PCI: Ignoring entire controller.\n"); - return; - } - pbm_config_busmastering(&p->pbm_B); p->pbm_B.is_66mhz_capable = (of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL) @@ -1273,154 +1244,19 @@ static void __schizo_scan_bus(struct pci_controller_info *p, p->pbm_A.is_66mhz_capable = (of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL) != NULL); - pbm_scan_bus(p, &p->pbm_B); - pbm_scan_bus(p, &p->pbm_A); + + p->pbm_B.pci_bus = pci_scan_one_pbm(&p->pbm_B); + p->pbm_A.pci_bus = pci_scan_one_pbm(&p->pbm_A); /* After the PCI bus scan is complete, we can register * the error interrupt handlers. */ - if (chip_type == PBM_CHIP_TYPE_TOMATILLO) + if (p->pbm_B.chip_type == PBM_CHIP_TYPE_TOMATILLO) tomatillo_register_error_handlers(p); else schizo_register_error_handlers(p); } -static void schizo_scan_bus(struct pci_controller_info *p) -{ - __schizo_scan_bus(p, PBM_CHIP_TYPE_SCHIZO); -} - -static void tomatillo_scan_bus(struct pci_controller_info *p) -{ - __schizo_scan_bus(p, PBM_CHIP_TYPE_TOMATILLO); -} - -static void schizo_base_address_update(struct pci_dev *pdev, int resource) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; - struct resource *res, *root; - u32 reg; - int where, size, is_64bit; - - res = &pdev->resource[resource]; - if (resource < 6) { - where = PCI_BASE_ADDRESS_0 + (resource * 4); - } else if (resource == PCI_ROM_RESOURCE) { - where = pdev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - is_64bit = 0; - if (res->flags & IORESOURCE_IO) - root = &pbm->io_space; - else { - root = &pbm->mem_space; - if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - == PCI_BASE_ADDRESS_MEM_TYPE_64) - is_64bit = 1; - } - - size = res->end - res->start; - pci_read_config_dword(pdev, where, ®); - reg = ((reg & size) | - (((u32)(res->start - root->start)) & ~size)); - if (resource == PCI_ROM_RESOURCE) { - reg |= PCI_ROM_ADDRESS_ENABLE; - res->flags |= IORESOURCE_ROM_ENABLE; - } - pci_write_config_dword(pdev, where, reg); - - /* This knows that the upper 32-bits of the address - * must be zero. Our PCI common layer enforces this. - */ - if (is_64bit) - pci_write_config_dword(pdev, where + 4, 0); -} - -static void schizo_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - res->start += root->start; - res->end += root->start; -} - -/* Use ranges property to determine where PCI MEM, I/O, and Config - * space are for this PCI bus module. - */ -static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm) -{ - int i, saw_cfg, saw_mem, saw_io; - - saw_cfg = saw_mem = saw_io = 0; - for (i = 0; i < pbm->num_pbm_ranges; i++) { - struct linux_prom_pci_ranges *pr = &pbm->pbm_ranges[i]; - unsigned long a; - int type; - - type = (pr->child_phys_hi >> 24) & 0x3; - a = (((unsigned long)pr->parent_phys_hi << 32UL) | - ((unsigned long)pr->parent_phys_lo << 0UL)); - - switch (type) { - case 0: - /* PCI config space, 16MB */ - pbm->config_space = a; - saw_cfg = 1; - break; - - case 1: - /* 16-bit IO space, 16MB */ - pbm->io_space.start = a; - pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL); - pbm->io_space.flags = IORESOURCE_IO; - saw_io = 1; - break; - - case 2: - /* 32-bit MEM space, 2GB */ - pbm->mem_space.start = a; - pbm->mem_space.end = a + (0x80000000UL - 1UL); - pbm->mem_space.flags = IORESOURCE_MEM; - saw_mem = 1; - break; - - default: - break; - }; - } - - if (!saw_cfg || !saw_io || !saw_mem) { - prom_printf("%s: Fatal error, missing %s PBM range.\n", - pbm->name, - ((!saw_cfg ? - "CFG" : - (!saw_io ? - "IO" : "MEM")))); - prom_halt(); - } - - printk("%s: PCI CFG[%lx] IO[%lx] MEM[%lx]\n", - pbm->name, - pbm->config_space, - pbm->io_space.start, - pbm->mem_space.start); -} - -static void pbm_register_toplevel_resources(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - pbm->io_space.name = pbm->mem_space.name = pbm->name; - - request_resource(&ioport_resource, &pbm->io_space); - request_resource(&iomem_resource, &pbm->mem_space); - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); -} - #define SCHIZO_STRBUF_CONTROL (0x02800UL) #define SCHIZO_STRBUF_FLUSH (0x02808UL) #define SCHIZO_STRBUF_FSYNC (0x02810UL) @@ -1472,7 +1308,7 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) { - struct pci_iommu *iommu = pbm->iommu; + struct iommu *iommu = pbm->iommu; unsigned long i, tagbase, database; struct property *prop; u32 vdma[2], dma_mask; @@ -1654,14 +1490,12 @@ static void schizo_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 portid, int chip_type) { - struct linux_prom64_registers *regs; - struct property *prop; - unsigned int *busrange; + const struct linux_prom64_registers *regs; + const unsigned int *busrange; struct pci_pbm_info *pbm; const char *chipset_name; - u32 *ino_bitmap; + const u32 *ino_bitmap; int is_pbm_a; - int len; switch (chip_type) { case PBM_CHIP_TYPE_TOMATILLO: @@ -1689,11 +1523,9 @@ static void schizo_pbm_init(struct pci_controller_info *p, * 3) PBM PCI config space * 4) Ichip regs */ - prop = of_find_property(dp, "reg", NULL); - regs = prop->value; + regs = of_get_property(dp, "reg", NULL); is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); - if (is_pbm_a) pbm = &p->pbm_A; else @@ -1702,17 +1534,10 @@ static void schizo_pbm_init(struct pci_controller_info *p, pbm->portid = portid; pbm->parent = p; pbm->prom_node = dp; - pbm->pci_first_slot = 1; pbm->chip_type = chip_type; - pbm->chip_version = 0; - prop = of_find_property(dp, "version#", NULL); - if (prop) - pbm->chip_version = *(int *) prop->value; - pbm->chip_revision = 0; - prop = of_find_property(dp, "module-revision#", NULL); - if (prop) - pbm->chip_revision = *(int *) prop->value; + pbm->chip_version = of_getintprop_default(dp, "version#", 0); + pbm->chip_revision = of_getintprop_default(dp, "module-version#", 0); pbm->pbm_regs = regs[0].phys_addr; pbm->controller_regs = regs[1].phys_addr - 0x10000UL; @@ -1723,40 +1548,18 @@ static void schizo_pbm_init(struct pci_controller_info *p, pbm->name = dp->full_name; printk("%s: %s PCI Bus Module ver[%x:%x]\n", - pbm->name, - (chip_type == PBM_CHIP_TYPE_TOMATILLO ? - "TOMATILLO" : "SCHIZO"), + pbm->name, chipset_name, pbm->chip_version, pbm->chip_revision); schizo_pbm_hw_init(pbm); - prop = of_find_property(dp, "ranges", &len); - pbm->pbm_ranges = prop->value; - pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); + pci_determine_mem_io_space(pbm); - schizo_determine_mem_io_space(pbm); - pbm_register_toplevel_resources(p, pbm); - - prop = of_find_property(dp, "interrupt-map", &len); - if (prop) { - pbm->pbm_intmap = prop->value; - pbm->num_pbm_intmap = - (len / sizeof(struct linux_prom_pci_intmap)); - - prop = of_find_property(dp, "interrupt-map-mask", NULL); - pbm->pbm_intmask = prop->value; - } else { - pbm->num_pbm_intmap = 0; - } - - prop = of_find_property(dp, "ino-bitmap", NULL); - ino_bitmap = prop->value; + ino_bitmap = of_get_property(dp, "ino-bitmap", NULL); pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | ((u64)ino_bitmap[0] << 0UL)); - prop = of_find_property(dp, "bus-range", NULL); - busrange = prop->value; + busrange = of_get_property(dp, "bus-range", NULL); pbm->pci_first_busno = busrange[0]; pbm->pci_last_busno = busrange[1]; @@ -1777,15 +1580,10 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) static void __schizo_init(struct device_node *dp, char *model_name, int chip_type) { struct pci_controller_info *p; - struct pci_iommu *iommu; - struct property *prop; - int is_pbm_a; + struct iommu *iommu; u32 portid; - portid = 0xff; - prop = of_find_property(dp, "portid", NULL); - if (prop) - portid = *(u32 *) prop->value; + portid = of_getintprop_default(dp, "portid", 0xff); for (p = pci_controller_root; p; p = p->next) { struct pci_pbm_info *pbm; @@ -1798,48 +1596,43 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ &p->pbm_B); if (portid_compare(pbm->portid, portid, chip_type)) { - is_pbm_a = (p->pbm_A.prom_node == NULL); schizo_pbm_init(p, dp, portid, chip_type); return; } } p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - prom_printf("SCHIZO: Fatal memory allocation error.\n"); - prom_halt(); - } + if (!p) + goto memfail; + + iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); + if (!iommu) + goto memfail; - iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC); - if (!iommu) { - prom_printf("SCHIZO: Fatal memory allocation error.\n"); - prom_halt(); - } p->pbm_A.iommu = iommu; - iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC); - if (!iommu) { - prom_printf("SCHIZO: Fatal memory allocation error.\n"); - prom_halt(); - } + iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); + if (!iommu) + goto memfail; + p->pbm_B.iommu = iommu; p->next = pci_controller_root; pci_controller_root = p; p->index = pci_num_controllers++; - p->pbms_same_domain = 0; - p->scan_bus = (chip_type == PBM_CHIP_TYPE_TOMATILLO ? - tomatillo_scan_bus : - schizo_scan_bus); - p->base_address_update = schizo_base_address_update; - p->resource_adjust = schizo_resource_adjust; + p->scan_bus = schizo_scan_bus; p->pci_ops = &schizo_ops; /* Like PSYCHO we have a 2GB aligned area for memory space. */ pci_memspace_mask = 0x7fffffffUL; schizo_pbm_init(p, dp, portid, chip_type); + return; + +memfail: + prom_printf("SCHIZO: Fatal memory allocation error.\n"); + prom_halt(); } void schizo_init(struct device_node *dp, char *model_name) diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index ec22cd61ec8..94295c21932 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -1,6 +1,6 @@ /* pci_sun4v.c: SUN4V specific PCI controller support. * - * Copyright (C) 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) */ #include <linux/kernel.h> @@ -29,7 +29,7 @@ #define PGLIST_NENTS (PAGE_SIZE / sizeof(u64)) -struct pci_iommu_batch { +struct iommu_batch { struct pci_dev *pdev; /* Device mapping is for. */ unsigned long prot; /* IOMMU page protections */ unsigned long entry; /* Index into IOTSB. */ @@ -37,12 +37,12 @@ struct pci_iommu_batch { unsigned long npages; /* Number of pages in list. */ }; -static DEFINE_PER_CPU(struct pci_iommu_batch, pci_iommu_batch); +static DEFINE_PER_CPU(struct iommu_batch, pci_iommu_batch); /* Interrupts must be disabled. */ static inline void pci_iommu_batch_start(struct pci_dev *pdev, unsigned long prot, unsigned long entry) { - struct pci_iommu_batch *p = &__get_cpu_var(pci_iommu_batch); + struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch); p->pdev = pdev; p->prot = prot; @@ -51,10 +51,10 @@ static inline void pci_iommu_batch_start(struct pci_dev *pdev, unsigned long pro } /* Interrupts must be disabled. */ -static long pci_iommu_batch_flush(struct pci_iommu_batch *p) +static long pci_iommu_batch_flush(struct iommu_batch *p) { - struct pcidev_cookie *pcp = p->pdev->sysdata; - unsigned long devhandle = pcp->pbm->devhandle; + struct pci_pbm_info *pbm = p->pdev->dev.archdata.host_controller; + unsigned long devhandle = pbm->devhandle; unsigned long prot = p->prot; unsigned long entry = p->entry; u64 *pglist = p->pglist; @@ -89,7 +89,7 @@ static long pci_iommu_batch_flush(struct pci_iommu_batch *p) /* Interrupts must be disabled. */ static inline long pci_iommu_batch_add(u64 phys_page) { - struct pci_iommu_batch *p = &__get_cpu_var(pci_iommu_batch); + struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch); BUG_ON(p->npages >= PGLIST_NENTS); @@ -103,14 +103,14 @@ static inline long pci_iommu_batch_add(u64 phys_page) /* Interrupts must be disabled. */ static inline long pci_iommu_batch_end(void) { - struct pci_iommu_batch *p = &__get_cpu_var(pci_iommu_batch); + struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch); BUG_ON(p->npages >= PGLIST_NENTS); return pci_iommu_batch_flush(p); } -static long pci_arena_alloc(struct pci_iommu_arena *arena, unsigned long npages) +static long pci_arena_alloc(struct iommu_arena *arena, unsigned long npages) { unsigned long n, i, start, end, limit; int pass; @@ -149,7 +149,7 @@ again: return n; } -static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, unsigned long npages) +static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages) { unsigned long i; @@ -159,8 +159,7 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; + struct iommu *iommu; unsigned long flags, order, first_page, npages, n; void *ret; long entry; @@ -178,8 +177,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr memset((char *)first_page, 0, PAGE_SIZE << order); - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; + iommu = pdev->dev.archdata.iommu; spin_lock_irqsave(&iommu->lock, flags); entry = pci_arena_alloc(&iommu->arena, npages); @@ -226,15 +224,15 @@ arena_alloc_fail: static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; + struct pci_pbm_info *pbm; + struct iommu *iommu; unsigned long flags, order, npages, entry; u32 devhandle; npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - devhandle = pcp->pbm->devhandle; + iommu = pdev->dev.archdata.iommu; + pbm = pdev->dev.archdata.host_controller; + devhandle = pbm->devhandle; entry = ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); spin_lock_irqsave(&iommu->lock, flags); @@ -259,16 +257,14 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; + struct iommu *iommu; unsigned long flags, npages, oaddr; unsigned long i, base_paddr; u32 bus_addr, ret; unsigned long prot; long entry; - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; + iommu = pdev->dev.archdata.iommu; if (unlikely(direction == PCI_DMA_NONE)) goto bad; @@ -324,8 +320,8 @@ iommu_map_fail: static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; + struct pci_pbm_info *pbm; + struct iommu *iommu; unsigned long flags, npages; long entry; u32 devhandle; @@ -336,9 +332,9 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_ return; } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - devhandle = pcp->pbm->devhandle; + iommu = pdev->dev.archdata.iommu; + pbm = pdev->dev.archdata.host_controller; + devhandle = pbm->devhandle; npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); npages >>= IO_PAGE_SHIFT; @@ -460,8 +456,7 @@ iommu_map_failed: static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; + struct iommu *iommu; unsigned long flags, npages, prot; u32 dma_base; struct scatterlist *sgtmp; @@ -480,8 +475,7 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n return 1; } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; + iommu = pdev->dev.archdata.iommu; if (unlikely(direction == PCI_DMA_NONE)) goto bad; @@ -537,8 +531,8 @@ iommu_map_failed: static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { - struct pcidev_cookie *pcp; - struct pci_iommu *iommu; + struct pci_pbm_info *pbm; + struct iommu *iommu; unsigned long flags, i, npages; long entry; u32 devhandle, bus_addr; @@ -548,9 +542,9 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in WARN_ON(1); } - pcp = pdev->sysdata; - iommu = pcp->pbm->iommu; - devhandle = pcp->pbm->devhandle; + iommu = pdev->dev.archdata.iommu; + pbm = pdev->dev.archdata.host_controller; + devhandle = pbm->devhandle; bus_addr = sglist->dma_address & IO_PAGE_MASK; @@ -589,7 +583,7 @@ static void pci_4v_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist /* Nothing to do... */ } -struct pci_iommu_ops pci_sun4v_iommu_ops = { +const struct pci_iommu_ops pci_sun4v_iommu_ops = { .alloc_consistent = pci_4v_alloc_consistent, .free_consistent = pci_4v_free_consistent, .map_single = pci_4v_map_single, @@ -600,132 +594,12 @@ struct pci_iommu_ops pci_sun4v_iommu_ops = { .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu, }; -/* SUN4V PCI configuration space accessors. */ - -struct pdev_entry { - struct pdev_entry *next; - u32 devhandle; - unsigned int bus; - unsigned int device; - unsigned int func; -}; - -#define PDEV_HTAB_SIZE 16 -#define PDEV_HTAB_MASK (PDEV_HTAB_SIZE - 1) -static struct pdev_entry *pdev_htab[PDEV_HTAB_SIZE]; - -static inline unsigned int pdev_hashfn(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func) -{ - unsigned int val; - - val = (devhandle ^ (devhandle >> 4)); - val ^= bus; - val ^= device; - val ^= func; - - return val & PDEV_HTAB_MASK; -} - -static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func) -{ - struct pdev_entry *p = kmalloc(sizeof(*p), GFP_KERNEL); - struct pdev_entry **slot; - - if (!p) - return -ENOMEM; - - slot = &pdev_htab[pdev_hashfn(devhandle, bus, device, func)]; - p->next = *slot; - *slot = p; - - p->devhandle = devhandle; - p->bus = bus; - p->device = device; - p->func = func; - - return 0; -} - -/* Recursively descend into the OBP device tree, rooted at toplevel_node, - * looking for a PCI device matching bus and devfn. - */ -static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn) -{ - toplevel_node = toplevel_node->child; - - while (toplevel_node != NULL) { - struct linux_prom_pci_registers *regs; - struct property *prop; - int ret; - - ret = obp_find(toplevel_node, bus, devfn); - if (ret != 0) - return ret; - - prop = of_find_property(toplevel_node, "reg", NULL); - if (!prop) - goto next_sibling; - - regs = prop->value; - if (((regs->phys_hi >> 16) & 0xff) == bus && - ((regs->phys_hi >> 8) & 0xff) == devfn) - break; - - next_sibling: - toplevel_node = toplevel_node->sibling; - } - - return toplevel_node != NULL; -} - -static int pdev_htab_populate(struct pci_pbm_info *pbm) -{ - u32 devhandle = pbm->devhandle; - unsigned int bus; - - for (bus = pbm->pci_first_busno; bus <= pbm->pci_last_busno; bus++) { - unsigned int devfn; - - for (devfn = 0; devfn < 256; devfn++) { - unsigned int device = PCI_SLOT(devfn); - unsigned int func = PCI_FUNC(devfn); - - if (obp_find(pbm->prom_node, bus, devfn)) { - int err = pdev_htab_add(devhandle, bus, - device, func); - if (err) - return err; - } - } - } - - return 0; -} - -static struct pdev_entry *pdev_find(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func) -{ - struct pdev_entry *p; - - p = pdev_htab[pdev_hashfn(devhandle, bus, device, func)]; - while (p) { - if (p->devhandle == devhandle && - p->bus == bus && - p->device == device && - p->func == func) - break; - - p = p->next; - } - - return p; -} - static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func) { if (bus < pbm->pci_first_busno || bus > pbm->pci_last_busno) return 1; - return pdev_find(pbm->devhandle, bus, device, func) == NULL; + return 0; } static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, @@ -738,6 +612,9 @@ static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned int func = PCI_FUNC(devfn); unsigned long ret; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); if (pci_sun4v_out_of_range(pbm, bus, device, func)) { ret = ~0UL; } else { @@ -776,6 +653,9 @@ static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, unsigned int func = PCI_FUNC(devfn); unsigned long ret; + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); if (pci_sun4v_out_of_range(pbm, bus, device, func)) { /* Do nothing. */ } else { @@ -800,27 +680,7 @@ static struct pci_ops pci_sun4v_ops = { static void pbm_scan_bus(struct pci_controller_info *p, struct pci_pbm_info *pbm) { - struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); - - if (!cookie) { - prom_printf("%s: Critical allocation failure.\n", pbm->name); - prom_halt(); - } - - /* All we care about is the PBM. */ - cookie->pbm = pbm; - - pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, p->pci_ops, pbm); -#if 0 - pci_fixup_host_bridge_self(pbm->pci_bus); - pbm->pci_bus->self->sysdata = cookie; -#endif - pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); - pci_record_assignments(pbm, pbm->pci_bus); - pci_assign_unassigned(pbm, pbm->pci_bus); - pci_fixup_irq(pbm, pbm->pci_bus); - pci_determine_66mhz_disposition(pbm, pbm->pci_bus); - pci_setup_busmastering(pbm, pbm->pci_bus); + pbm->pci_bus = pci_scan_one_pbm(pbm); } static void pci_sun4v_scan_bus(struct pci_controller_info *p) @@ -844,130 +704,10 @@ static void pci_sun4v_scan_bus(struct pci_controller_info *p) /* XXX register error interrupt handlers XXX */ } -static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource) -{ - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; - struct resource *res, *root; - u32 reg; - int where, size, is_64bit; - - res = &pdev->resource[resource]; - if (resource < 6) { - where = PCI_BASE_ADDRESS_0 + (resource * 4); - } else if (resource == PCI_ROM_RESOURCE) { - where = pdev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - /* XXX 64-bit MEM handling is not %100 correct... XXX */ - is_64bit = 0; - if (res->flags & IORESOURCE_IO) - root = &pbm->io_space; - else { - root = &pbm->mem_space; - if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - == PCI_BASE_ADDRESS_MEM_TYPE_64) - is_64bit = 1; - } - - size = res->end - res->start; - pci_read_config_dword(pdev, where, ®); - reg = ((reg & size) | - (((u32)(res->start - root->start)) & ~size)); - if (resource == PCI_ROM_RESOURCE) { - reg |= PCI_ROM_ADDRESS_ENABLE; - res->flags |= IORESOURCE_ROM_ENABLE; - } - pci_write_config_dword(pdev, where, reg); - - /* This knows that the upper 32-bits of the address - * must be zero. Our PCI common layer enforces this. - */ - if (is_64bit) - pci_write_config_dword(pdev, where + 4, 0); -} - -static void pci_sun4v_resource_adjust(struct pci_dev *pdev, - struct resource *res, - struct resource *root) -{ - res->start += root->start; - res->end += root->start; -} - -/* Use ranges property to determine where PCI MEM, I/O, and Config - * space are for this PCI bus module. - */ -static void pci_sun4v_determine_mem_io_space(struct pci_pbm_info *pbm) -{ - int i, saw_mem, saw_io; - - saw_mem = saw_io = 0; - for (i = 0; i < pbm->num_pbm_ranges; i++) { - struct linux_prom_pci_ranges *pr = &pbm->pbm_ranges[i]; - unsigned long a; - int type; - - type = (pr->child_phys_hi >> 24) & 0x3; - a = (((unsigned long)pr->parent_phys_hi << 32UL) | - ((unsigned long)pr->parent_phys_lo << 0UL)); - - switch (type) { - case 1: - /* 16-bit IO space, 16MB */ - pbm->io_space.start = a; - pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL); - pbm->io_space.flags = IORESOURCE_IO; - saw_io = 1; - break; - - case 2: - /* 32-bit MEM space, 2GB */ - pbm->mem_space.start = a; - pbm->mem_space.end = a + (0x80000000UL - 1UL); - pbm->mem_space.flags = IORESOURCE_MEM; - saw_mem = 1; - break; - - case 3: - /* XXX 64-bit MEM handling XXX */ - - default: - break; - }; - } - - if (!saw_io || !saw_mem) { - prom_printf("%s: Fatal error, missing %s PBM range.\n", - pbm->name, - (!saw_io ? "IO" : "MEM")); - prom_halt(); - } - - printk("%s: PCI IO[%lx] MEM[%lx]\n", - pbm->name, - pbm->io_space.start, - pbm->mem_space.start); -} - -static void pbm_register_toplevel_resources(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - pbm->io_space.name = pbm->mem_space.name = pbm->name; - - request_resource(&ioport_resource, &pbm->io_space); - request_resource(&iomem_resource, &pbm->mem_space); - pci_register_legacy_regions(&pbm->io_space, - &pbm->mem_space); -} - static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, - struct pci_iommu *iommu) + struct iommu *iommu) { - struct pci_iommu_arena *arena = &iommu->arena; + struct iommu_arena *arena = &iommu->arena; unsigned long i, cnt = 0; u32 devhandle; @@ -994,7 +734,7 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) { - struct pci_iommu *iommu = pbm->iommu; + struct iommu *iommu = pbm->iommu; struct property *prop; unsigned long num_tsb_entries, sz; u32 vdma[2], dma_mask, dma_offset; @@ -1281,7 +1021,7 @@ h_error: static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) { - u32 *val; + const u32 *val; int len; val = of_get_property(pbm->prom_node, "#msi-eqs", &len); @@ -1289,16 +1029,16 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) goto no_msi; pbm->msiq_num = *val; if (pbm->msiq_num) { - struct msiq_prop { + const struct msiq_prop { u32 first_msiq; u32 num_msiq; u32 first_devino; } *mqp; - struct msi_range_prop { + const struct msi_range_prop { u32 first_msi; u32 num_msi; } *mrng; - struct addr_range_prop { + const struct addr_range_prop { u32 msi32_high; u32 msi32_low; u32 msi32_len; @@ -1410,8 +1150,7 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p, struct pci_dev *pdev, struct msi_desc *entry) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; unsigned long devino, msiqid; struct msi_msg msg; int msi_num, err; @@ -1455,7 +1194,7 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p, if (pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_VALID)) goto out_err; - pcp->msi_num = msi_num; + pdev->dev.archdata.msi_num = msi_num; if (entry->msi_attrib.is_64) { msg.address_hi = pbm->msi64_start >> 32; @@ -1484,12 +1223,11 @@ out_err: static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq, struct pci_dev *pdev) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_pbm_info *pbm = pcp->pbm; + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; unsigned long msiqid, err; unsigned int msi_num; - msi_num = pcp->msi_num; + msi_num = pdev->dev.archdata.msi_num; err = pci_sun4v_msi_getmsiq(pbm->devhandle, msi_num, &msiqid); if (err) { printk(KERN_ERR "%s: getmsiq gives error %lu\n", @@ -1516,8 +1254,6 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) { struct pci_pbm_info *pbm; - struct property *prop; - int len, i; if (devhandle & 0x40) pbm = &p->pbm_B; @@ -1526,7 +1262,6 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pbm->parent = p; pbm->prom_node = dp; - pbm->pci_first_slot = 1; pbm->devhandle = devhandle; @@ -1534,39 +1269,17 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node printk("%s: SUN4V PCI Bus Module\n", pbm->name); - prop = of_find_property(dp, "ranges", &len); - pbm->pbm_ranges = prop->value; - pbm->num_pbm_ranges = - (len / sizeof(struct linux_prom_pci_ranges)); - - /* Mask out the top 8 bits of the ranges, leaving the real - * physical address. - */ - for (i = 0; i < pbm->num_pbm_ranges; i++) - pbm->pbm_ranges[i].parent_phys_hi &= 0x0fffffff; - - pci_sun4v_determine_mem_io_space(pbm); - pbm_register_toplevel_resources(p, pbm); - - prop = of_find_property(dp, "interrupt-map", &len); - pbm->pbm_intmap = prop->value; - pbm->num_pbm_intmap = - (len / sizeof(struct linux_prom_pci_intmap)); - - prop = of_find_property(dp, "interrupt-map-mask", NULL); - pbm->pbm_intmask = prop->value; + pci_determine_mem_io_space(pbm); pci_sun4v_get_bus_range(pbm); pci_sun4v_iommu_init(pbm); pci_sun4v_msi_init(pbm); - - pdev_htab_populate(pbm); } void sun4v_pci_init(struct device_node *dp, char *model_name) { struct pci_controller_info *p; - struct pci_iommu *iommu; + struct iommu *iommu; struct property *prop; struct linux_prom64_registers *regs; u32 devhandle; @@ -1606,13 +1319,13 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) if (!p) goto fatal_memory_error; - iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC); + iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) goto fatal_memory_error; p->pbm_A.iommu = iommu; - iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC); + iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) goto fatal_memory_error; @@ -1622,11 +1335,8 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) pci_controller_root = p; p->index = pci_num_controllers++; - p->pbms_same_domain = 0; p->scan_bus = pci_sun4v_scan_bus; - p->base_address_update = pci_sun4v_base_address_update; - p->resource_adjust = pci_sun4v_resource_adjust; #ifdef CONFIG_PCI_MSI p->setup_msi_irq = pci_sun4v_setup_msi_irq; p->teardown_msi_irq = pci_sun4v_teardown_msi_irq; diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index b291060c25a..a114151f9fb 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -28,6 +28,7 @@ #include <linux/reboot.h> #include <linux/delay.h> #include <linux/compat.h> +#include <linux/tick.h> #include <linux/init.h> #include <asm/oplib.h> @@ -88,12 +89,14 @@ void cpu_idle(void) set_thread_flag(TIF_POLLING_NRFLAG); while(1) { - if (need_resched()) { - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } - sparc64_yield(); + tick_nohz_stop_sched_tick(); + while (!need_resched()) + sparc64_yield(); + tick_nohz_restart_sched_tick(); + + preempt_enable_no_resched(); + schedule(); + preempt_disable(); } } diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 0917c24c4f0..5e1fcd05160 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -36,12 +36,13 @@ static struct device_node *allnodes; */ static DEFINE_RWLOCK(devtree_lock); -int of_device_is_compatible(struct device_node *device, const char *compat) +int of_device_is_compatible(const struct device_node *device, + const char *compat) { const char* cp; int cplen, l; - cp = (char *) of_get_property(device, "compatible", &cplen); + cp = of_get_property(device, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { @@ -154,13 +155,14 @@ struct device_node *of_find_compatible_node(struct device_node *from, } EXPORT_SYMBOL(of_find_compatible_node); -struct property *of_find_property(struct device_node *np, const char *name, +struct property *of_find_property(const struct device_node *np, + const char *name, int *lenp) { struct property *pp; for (pp = np->properties; pp != 0; pp = pp->next) { - if (strcmp(pp->name, name) == 0) { + if (strcasecmp(pp->name, name) == 0) { if (lenp != 0) *lenp = pp->length; break; @@ -174,7 +176,8 @@ EXPORT_SYMBOL(of_find_property); * Find a property with a given name for a given node * and return the value. */ -void *of_get_property(struct device_node *np, const char *name, int *lenp) +const void *of_get_property(const struct device_node *np, const char *name, + int *lenp) { struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; @@ -196,7 +199,7 @@ EXPORT_SYMBOL(of_getintprop_default); int of_n_addr_cells(struct device_node *np) { - int* ip; + const int* ip; do { if (np->parent) np = np->parent; @@ -211,7 +214,7 @@ EXPORT_SYMBOL(of_n_addr_cells); int of_n_size_cells(struct device_node *np) { - int* ip; + const int* ip; do { if (np->parent) np = np->parent; @@ -243,7 +246,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len while (*prevp) { struct property *prop = *prevp; - if (!strcmp(prop->name, name)) { + if (!strcasecmp(prop->name, name)) { void *old_val = prop->value; int ret; @@ -397,7 +400,7 @@ static unsigned int psycho_irq_build(struct device_node *dp, static void psycho_irq_trans_init(struct device_node *dp) { - struct linux_prom64_registers *regs; + const struct linux_prom64_registers *regs; dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans->irq_build = psycho_irq_build; @@ -547,7 +550,7 @@ static unsigned long __sabre_onboard_imap_off[] = { static int sabre_device_needs_wsync(struct device_node *dp) { struct device_node *parent = dp->parent; - char *parent_model, *parent_compat; + const char *parent_model, *parent_compat; /* This traversal up towards the root is meant to * handle two cases: @@ -589,7 +592,7 @@ static unsigned int sabre_irq_build(struct device_node *dp, { struct sabre_irq_data *irq_data = _data; unsigned long controller_regs = irq_data->controller_regs; - struct linux_prom_pci_registers *regs; + const struct linux_prom_pci_registers *regs; unsigned long imap, iclr; unsigned long imap_off, iclr_off; int inofixup = 0; @@ -639,9 +642,9 @@ static unsigned int sabre_irq_build(struct device_node *dp, static void sabre_irq_trans_init(struct device_node *dp) { - struct linux_prom64_registers *regs; + const struct linux_prom64_registers *regs; struct sabre_irq_data *irq_data; - u32 *busrange; + const u32 *busrange; dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans->irq_build = sabre_irq_build; @@ -795,7 +798,7 @@ static unsigned int schizo_irq_build(struct device_node *dp, static void __schizo_irq_trans_init(struct device_node *dp, int is_tomatillo) { - struct linux_prom64_registers *regs; + const struct linux_prom64_registers *regs; struct schizo_irq_data *irq_data; dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); @@ -836,7 +839,7 @@ static unsigned int pci_sun4v_irq_build(struct device_node *dp, static void pci_sun4v_irq_trans_init(struct device_node *dp) { - struct linux_prom64_registers *regs; + const struct linux_prom64_registers *regs; dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans->irq_build = pci_sun4v_irq_build; @@ -940,7 +943,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp, void *_data) { unsigned long reg_base = (unsigned long) _data; - struct linux_prom_registers *regs; + const struct linux_prom_registers *regs; unsigned long imap, iclr; int sbus_slot = 0; int sbus_level = 0; @@ -994,7 +997,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp, static void sbus_irq_trans_init(struct device_node *dp) { - struct linux_prom64_registers *regs; + const struct linux_prom64_registers *regs; dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans->irq_build = sbus_of_build_irq; @@ -1080,7 +1083,7 @@ static unsigned int sun4v_vdev_irq_build(struct device_node *dp, static void sun4v_vdev_irq_trans_init(struct device_node *dp) { - struct linux_prom64_registers *regs; + const struct linux_prom64_registers *regs; dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans->irq_build = sun4v_vdev_irq_build; diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 14f78fb5e89..3b05428cc90 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -26,23 +26,9 @@ #define MAP_BASE ((u32)0xc0000000) -struct sbus_iommu_arena { - unsigned long *map; - unsigned int hint; - unsigned int limit; -}; - -struct sbus_iommu { - spinlock_t lock; - - struct sbus_iommu_arena arena; - - iopte_t *page_table; - unsigned long strbuf_regs; - unsigned long iommu_regs; - unsigned long sbus_control_reg; - - volatile unsigned long strbuf_flushflag; +struct sbus_info { + struct iommu iommu; + struct strbuf strbuf; }; /* Offsets from iommu_regs */ @@ -58,16 +44,17 @@ struct sbus_iommu { #define IOMMU_DRAM_VALID (1UL << 30UL) -static void __iommu_flushall(struct sbus_iommu *iommu) +static void __iommu_flushall(struct iommu *iommu) { - unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG; + unsigned long tag; int entry; + tag = iommu->iommu_control + (IOMMU_TAGDIAG - IOMMU_CONTROL); for (entry = 0; entry < 16; entry++) { upa_writeq(0, tag); tag += 8UL; } - upa_readq(iommu->sbus_control_reg); + upa_readq(iommu->write_complete_reg); } /* Offsets from strbuf_regs */ @@ -82,15 +69,14 @@ static void __iommu_flushall(struct sbus_iommu *iommu) #define STRBUF_TAG_VALID 0x02UL -static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages, int direction) +static void sbus_strbuf_flush(struct iommu *iommu, struct strbuf *strbuf, u32 base, unsigned long npages, int direction) { unsigned long n; int limit; n = npages; while (n--) - upa_writeq(base + (n << IO_PAGE_SHIFT), - iommu->strbuf_regs + STRBUF_PFLUSH); + upa_writeq(base + (n << IO_PAGE_SHIFT), strbuf->strbuf_pflush); /* If the device could not have possibly put dirty data into * the streaming cache, no flush-flag synchronization needs @@ -99,15 +85,14 @@ static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long if (direction == SBUS_DMA_TODEVICE) return; - iommu->strbuf_flushflag = 0UL; + *(strbuf->strbuf_flushflag) = 0UL; /* Whoopee cushion! */ - upa_writeq(__pa(&iommu->strbuf_flushflag), - iommu->strbuf_regs + STRBUF_FSYNC); - upa_readq(iommu->sbus_control_reg); + upa_writeq(strbuf->strbuf_flushflag_pa, strbuf->strbuf_fsync); + upa_readq(iommu->write_complete_reg); limit = 100000; - while (iommu->strbuf_flushflag == 0UL) { + while (*(strbuf->strbuf_flushflag) == 0UL) { limit--; if (!limit) break; @@ -121,9 +106,9 @@ static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long } /* Based largely upon the ppc64 iommu allocator. */ -static long sbus_arena_alloc(struct sbus_iommu *iommu, unsigned long npages) +static long sbus_arena_alloc(struct iommu *iommu, unsigned long npages) { - struct sbus_iommu_arena *arena = &iommu->arena; + struct iommu_arena *arena = &iommu->arena; unsigned long n, i, start, end, limit; int pass; @@ -162,7 +147,7 @@ again: return n; } -static void sbus_arena_free(struct sbus_iommu_arena *arena, unsigned long base, unsigned long npages) +static void sbus_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages) { unsigned long i; @@ -170,7 +155,7 @@ static void sbus_arena_free(struct sbus_iommu_arena *arena, unsigned long base, __clear_bit(i, arena->map); } -static void sbus_iommu_table_init(struct sbus_iommu *iommu, unsigned int tsbsize) +static void sbus_iommu_table_init(struct iommu *iommu, unsigned int tsbsize) { unsigned long tsbbase, order, sz, num_tsb_entries; @@ -178,13 +163,14 @@ static void sbus_iommu_table_init(struct sbus_iommu *iommu, unsigned int tsbsize /* Setup initial software IOMMU state. */ spin_lock_init(&iommu->lock); + iommu->page_table_map_base = MAP_BASE; /* Allocate and initialize the free area map. */ sz = num_tsb_entries / 8; sz = (sz + 7UL) & ~7UL; iommu->arena.map = kzalloc(sz, GFP_KERNEL); if (!iommu->arena.map) { - prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n"); + prom_printf("SBUS_IOMMU: Error, kmalloc(arena.map) failed.\n"); prom_halt(); } iommu->arena.limit = num_tsb_entries; @@ -200,7 +186,7 @@ static void sbus_iommu_table_init(struct sbus_iommu *iommu, unsigned int tsbsize memset(iommu->page_table, 0, tsbsize); } -static inline iopte_t *alloc_npages(struct sbus_iommu *iommu, unsigned long npages) +static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages) { long entry; @@ -211,14 +197,15 @@ static inline iopte_t *alloc_npages(struct sbus_iommu *iommu, unsigned long npag return iommu->page_table + entry; } -static inline void free_npages(struct sbus_iommu *iommu, dma_addr_t base, unsigned long npages) +static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages) { sbus_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages); } void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma_addr) { - struct sbus_iommu *iommu; + struct sbus_info *info; + struct iommu *iommu; iopte_t *iopte; unsigned long flags, order, first_page; void *ret; @@ -234,7 +221,8 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma return NULL; memset((char *)first_page, 0, PAGE_SIZE << order); - iommu = sdev->bus->iommu; + info = sdev->bus->iommu; + iommu = &info->iommu; spin_lock_irqsave(&iommu->lock, flags); iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT); @@ -245,7 +233,7 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma return NULL; } - *dvma_addr = (MAP_BASE + + *dvma_addr = (iommu->page_table_map_base + ((iopte - iommu->page_table) << IO_PAGE_SHIFT)); ret = (void *) first_page; npages = size >> IO_PAGE_SHIFT; @@ -263,18 +251,20 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_addr_t dvma) { - struct sbus_iommu *iommu; + struct sbus_info *info; + struct iommu *iommu; iopte_t *iopte; unsigned long flags, order, npages; npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; - iommu = sdev->bus->iommu; + info = sdev->bus->iommu; + iommu = &info->iommu; iopte = iommu->page_table + - ((dvma - MAP_BASE) >> IO_PAGE_SHIFT); + ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); spin_lock_irqsave(&iommu->lock, flags); - free_npages(iommu, dvma - MAP_BASE, npages); + free_npages(iommu, dvma - iommu->page_table_map_base, npages); spin_unlock_irqrestore(&iommu->lock, flags); @@ -285,14 +275,16 @@ void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_add dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t sz, int direction) { - struct sbus_iommu *iommu; + struct sbus_info *info; + struct iommu *iommu; iopte_t *base; unsigned long flags, npages, oaddr; unsigned long i, base_paddr; u32 bus_addr, ret; unsigned long iopte_protection; - iommu = sdev->bus->iommu; + info = sdev->bus->iommu; + iommu = &info->iommu; if (unlikely(direction == SBUS_DMA_NONE)) BUG(); @@ -308,7 +300,7 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t sz, int dire if (unlikely(!base)) BUG(); - bus_addr = (MAP_BASE + + bus_addr = (iommu->page_table_map_base + ((base - iommu->page_table) << IO_PAGE_SHIFT)); ret = bus_addr | (oaddr & ~IO_PAGE_MASK); base_paddr = __pa(oaddr & IO_PAGE_MASK); @@ -325,7 +317,9 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t sz, int dire void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, int direction) { - struct sbus_iommu *iommu = sdev->bus->iommu; + struct sbus_info *info = sdev->bus->iommu; + struct iommu *iommu = &info->iommu; + struct strbuf *strbuf = &info->strbuf; iopte_t *base; unsigned long flags, npages, i; @@ -335,15 +329,15 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, in npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); npages >>= IO_PAGE_SHIFT; base = iommu->page_table + - ((bus_addr - MAP_BASE) >> IO_PAGE_SHIFT); + ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); bus_addr &= IO_PAGE_MASK; spin_lock_irqsave(&iommu->lock, flags); - sbus_strbuf_flush(iommu, bus_addr, npages, direction); + sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction); for (i = 0; i < npages; i++) iopte_val(base[i]) = 0UL; - free_npages(iommu, bus_addr - MAP_BASE, npages); + free_npages(iommu, bus_addr - iommu->page_table_map_base, npages); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -425,7 +419,8 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction) { - struct sbus_iommu *iommu; + struct sbus_info *info; + struct iommu *iommu; unsigned long flags, npages, iopte_protection; iopte_t *base; u32 dma_base; @@ -442,7 +437,8 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, i return 1; } - iommu = sdev->bus->iommu; + info = sdev->bus->iommu; + iommu = &info->iommu; if (unlikely(direction == SBUS_DMA_NONE)) BUG(); @@ -456,7 +452,7 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, i if (unlikely(base == NULL)) BUG(); - dma_base = MAP_BASE + + dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << IO_PAGE_SHIFT); /* Normalize DVMA addresses. */ @@ -485,7 +481,9 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, i void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction) { - struct sbus_iommu *iommu; + struct sbus_info *info; + struct iommu *iommu; + struct strbuf *strbuf; iopte_t *base; unsigned long flags, i, npages; u32 bus_addr; @@ -493,7 +491,9 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems if (unlikely(direction == SBUS_DMA_NONE)) BUG(); - iommu = sdev->bus->iommu; + info = sdev->bus->iommu; + iommu = &info->iommu; + strbuf = &info->strbuf; bus_addr = sglist->dma_address & IO_PAGE_MASK; @@ -505,29 +505,33 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems bus_addr) >> IO_PAGE_SHIFT; base = iommu->page_table + - ((bus_addr - MAP_BASE) >> IO_PAGE_SHIFT); + ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); spin_lock_irqsave(&iommu->lock, flags); - sbus_strbuf_flush(iommu, bus_addr, npages, direction); + sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction); for (i = 0; i < npages; i++) iopte_val(base[i]) = 0UL; - free_npages(iommu, bus_addr - MAP_BASE, npages); + free_npages(iommu, bus_addr - iommu->page_table_map_base, npages); spin_unlock_irqrestore(&iommu->lock, flags); } void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, int direction) { - struct sbus_iommu *iommu; + struct sbus_info *info; + struct iommu *iommu; + struct strbuf *strbuf; unsigned long flags, npages; - iommu = sdev->bus->iommu; + info = sdev->bus->iommu; + iommu = &info->iommu; + strbuf = &info->strbuf; npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); npages >>= IO_PAGE_SHIFT; bus_addr &= IO_PAGE_MASK; spin_lock_irqsave(&iommu->lock, flags); - sbus_strbuf_flush(iommu, bus_addr, npages, direction); + sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -537,11 +541,15 @@ void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t base, siz void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction) { - struct sbus_iommu *iommu; + struct sbus_info *info; + struct iommu *iommu; + struct strbuf *strbuf; unsigned long flags, npages, i; u32 bus_addr; - iommu = sdev->bus->iommu; + info = sdev->bus->iommu; + iommu = &info->iommu; + strbuf = &info->strbuf; bus_addr = sglist[0].dma_address & IO_PAGE_MASK; for (i = 0; i < nelems; i++) { @@ -553,7 +561,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sglist, - bus_addr) >> IO_PAGE_SHIFT; spin_lock_irqsave(&iommu->lock, flags); - sbus_strbuf_flush(iommu, bus_addr, npages, direction); + sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -564,12 +572,13 @@ void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, /* Enable 64-bit DVMA mode for the given device. */ void sbus_set_sbus64(struct sbus_dev *sdev, int bursts) { - struct sbus_iommu *iommu = sdev->bus->iommu; + struct sbus_info *info = sdev->bus->iommu; + struct iommu *iommu = &info->iommu; int slot = sdev->slot; unsigned long cfg_reg; u64 val; - cfg_reg = iommu->sbus_control_reg; + cfg_reg = iommu->write_complete_reg; switch (slot) { case 0: cfg_reg += 0x20UL; @@ -704,8 +713,9 @@ static unsigned long sysio_imap_to_iclr(unsigned long imap) unsigned int sbus_build_irq(void *buscookie, unsigned int ino) { struct sbus_bus *sbus = (struct sbus_bus *)buscookie; - struct sbus_iommu *iommu = sbus->iommu; - unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; + struct sbus_info *info = sbus->iommu; + struct iommu *iommu = &info->iommu; + unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned long imap, iclr; int sbus_level = 0; @@ -766,8 +776,9 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) static irqreturn_t sysio_ue_handler(int irq, void *dev_id) { struct sbus_bus *sbus = dev_id; - struct sbus_iommu *iommu = sbus->iommu; - unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; + struct sbus_info *info = sbus->iommu; + struct iommu *iommu = &info->iommu; + unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned long afsr_reg, afar_reg; unsigned long afsr, afar, error_bits; int reported; @@ -838,8 +849,9 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) static irqreturn_t sysio_ce_handler(int irq, void *dev_id) { struct sbus_bus *sbus = dev_id; - struct sbus_iommu *iommu = sbus->iommu; - unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; + struct sbus_info *info = sbus->iommu; + struct iommu *iommu = &info->iommu; + unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned long afsr_reg, afar_reg; unsigned long afsr, afar, error_bits; int reported; @@ -915,12 +927,13 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) { struct sbus_bus *sbus = dev_id; - struct sbus_iommu *iommu = sbus->iommu; + struct sbus_info *info = sbus->iommu; + struct iommu *iommu = &info->iommu; unsigned long afsr_reg, afar_reg, reg_base; unsigned long afsr, afar, error_bits; int reported; - reg_base = iommu->sbus_control_reg - 0x2000UL; + reg_base = iommu->write_complete_reg - 0x2000UL; afsr_reg = reg_base + SYSIO_SBUS_AFSR; afar_reg = reg_base + SYSIO_SBUS_AFAR; @@ -982,8 +995,9 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) static void __init sysio_register_error_handlers(struct sbus_bus *sbus) { - struct sbus_iommu *iommu = sbus->iommu; - unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; + struct sbus_info *info = sbus->iommu; + struct iommu *iommu = &info->iommu; + unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned int irq; u64 control; @@ -1017,18 +1031,20 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) SYSIO_ECNTRL_CEEN), reg_base + ECC_CONTROL); - control = upa_readq(iommu->sbus_control_reg); + control = upa_readq(iommu->write_complete_reg); control |= 0x100UL; /* SBUS Error Interrupt Enable */ - upa_writeq(control, iommu->sbus_control_reg); + upa_writeq(control, iommu->write_complete_reg); } /* Boot time initialization. */ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) { - struct linux_prom64_registers *pr; + const struct linux_prom64_registers *pr; struct device_node *dp; - struct sbus_iommu *iommu; - unsigned long regs; + struct sbus_info *info; + struct iommu *iommu; + struct strbuf *strbuf; + unsigned long regs, reg_base; u64 control; int i; @@ -1043,33 +1059,42 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) } regs = pr->phys_addr; - iommu = kmalloc(sizeof(*iommu) + SMP_CACHE_BYTES, GFP_ATOMIC); - if (iommu == NULL) { - prom_printf("sbus_iommu_init: Fatal error, kmalloc(iommu) failed\n"); + info = kzalloc(sizeof(*info), GFP_ATOMIC); + if (info == NULL) { + prom_printf("sbus_iommu_init: Fatal error, " + "kmalloc(info) failed\n"); prom_halt(); } - /* Align on E$ line boundary. */ - iommu = (struct sbus_iommu *) - (((unsigned long)iommu + (SMP_CACHE_BYTES - 1UL)) & - ~(SMP_CACHE_BYTES - 1UL)); + iommu = &info->iommu; + strbuf = &info->strbuf; - memset(iommu, 0, sizeof(*iommu)); + reg_base = regs + SYSIO_IOMMUREG_BASE; + iommu->iommu_control = reg_base + IOMMU_CONTROL; + iommu->iommu_tsbbase = reg_base + IOMMU_TSBBASE; + iommu->iommu_flush = reg_base + IOMMU_FLUSH; - /* Setup spinlock. */ - spin_lock_init(&iommu->lock); + reg_base = regs + SYSIO_STRBUFREG_BASE; + strbuf->strbuf_control = reg_base + STRBUF_CONTROL; + strbuf->strbuf_pflush = reg_base + STRBUF_PFLUSH; + strbuf->strbuf_fsync = reg_base + STRBUF_FSYNC; - /* Init register offsets. */ - iommu->iommu_regs = regs + SYSIO_IOMMUREG_BASE; - iommu->strbuf_regs = regs + SYSIO_STRBUFREG_BASE; + strbuf->strbuf_enabled = 1; + + strbuf->strbuf_flushflag = (volatile unsigned long *) + ((((unsigned long)&strbuf->__flushflag_buf[0]) + + 63UL) + & ~63UL); + strbuf->strbuf_flushflag_pa = (unsigned long) + __pa(strbuf->strbuf_flushflag); /* The SYSIO SBUS control register is used for dummy reads * in order to ensure write completion. */ - iommu->sbus_control_reg = regs + 0x2000UL; + iommu->write_complete_reg = regs + 0x2000UL; /* Link into SYSIO software state. */ - sbus->iommu = iommu; + sbus->iommu = info; printk("SYSIO: UPA portID %x, at %016lx\n", sbus->portid, regs); @@ -1077,40 +1102,44 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ sbus_iommu_table_init(iommu, IO_TSB_SIZE); - control = upa_readq(iommu->iommu_regs + IOMMU_CONTROL); + control = upa_readq(iommu->iommu_control); control = ((7UL << 16UL) | (0UL << 2UL) | (1UL << 1UL) | (1UL << 0UL)); - upa_writeq(control, iommu->iommu_regs + IOMMU_CONTROL); + upa_writeq(control, iommu->iommu_control); /* Clean out any cruft in the IOMMU using * diagnostic accesses. */ for (i = 0; i < 16; i++) { - unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG; - unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG; + unsigned long dram, tag; + + dram = iommu->iommu_control + (IOMMU_DRAMDIAG - IOMMU_CONTROL); + tag = iommu->iommu_control + (IOMMU_TAGDIAG - IOMMU_CONTROL); dram += (unsigned long)i * 8UL; tag += (unsigned long)i * 8UL; upa_writeq(0, dram); upa_writeq(0, tag); } - upa_readq(iommu->sbus_control_reg); + upa_readq(iommu->write_complete_reg); /* Give the TSB to SYSIO. */ - upa_writeq(__pa(iommu->page_table), iommu->iommu_regs + IOMMU_TSBBASE); + upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase); /* Setup streaming buffer, DE=1 SB_EN=1 */ control = (1UL << 1UL) | (1UL << 0UL); - upa_writeq(control, iommu->strbuf_regs + STRBUF_CONTROL); + upa_writeq(control, strbuf->strbuf_control); /* Clear out the tags using diagnostics. */ for (i = 0; i < 16; i++) { unsigned long ptag, ltag; - ptag = iommu->strbuf_regs + STRBUF_PTAGDIAG; - ltag = iommu->strbuf_regs + STRBUF_LTAGDIAG; + ptag = strbuf->strbuf_control + + (STRBUF_PTAGDIAG - STRBUF_CONTROL); + ltag = strbuf->strbuf_control + + (STRBUF_LTAGDIAG - STRBUF_CONTROL); ptag += (unsigned long)i * 8UL; ltag += (unsigned long)i * 8UL; @@ -1119,9 +1148,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) } /* Enable DVMA arbitration for all devices/slots. */ - control = upa_readq(iommu->sbus_control_reg); + control = upa_readq(iommu->write_complete_reg); control |= 0x3fUL; - upa_writeq(control, iommu->sbus_control_reg); + upa_writeq(control, iommu->write_complete_reg); /* Now some Xfire specific grot... */ if (this_is_starfire) @@ -1133,7 +1162,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) void sbus_fill_device_irq(struct sbus_dev *sdev) { struct device_node *dp = of_find_node_by_phandle(sdev->prom_node); - struct linux_prom_irqs *irqs; + const struct linux_prom_irqs *irqs; irqs = of_get_property(dp, "interrupts", NULL); if (!irqs) { diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index fc99f7b8012..d4f0a70f484 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -45,7 +45,7 @@ extern void calibrate_delay(void); /* Please don't make this stuff initdata!!! --DaveM */ -static unsigned char boot_cpu_id; +unsigned char boot_cpu_id; cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE; cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE; @@ -81,8 +81,6 @@ void __init smp_store_cpu_info(int id) struct device_node *dp; int def; - /* multiplier and counter set by - smp_setup_percpu_timer() */ cpu_data(id).udelay_val = loops_per_jiffy; cpu_find_by_mid(id, &dp); @@ -125,7 +123,7 @@ void __init smp_store_cpu_info(int id) cpu_data(id).ecache_size, cpu_data(id).ecache_line_size); } -static void smp_setup_percpu_timer(void); +extern void setup_sparc64_timer(void); static volatile unsigned long callin_flag = 0; @@ -140,7 +138,7 @@ void __init smp_callin(void) __flush_tlb_all(); - smp_setup_percpu_timer(); + setup_sparc64_timer(); if (cheetah_pcache_forced_on) cheetah_enable_pcache(); @@ -177,8 +175,6 @@ void cpu_panic(void) panic("SMP bolixed\n"); } -static unsigned long current_tick_offset __read_mostly; - /* This tick register synchronization scheme is taken entirely from * the ia64 port, see arch/ia64/kernel/smpboot.c for details and credit. * @@ -261,7 +257,7 @@ void smp_synchronize_tick_client(void) } else adj = -delta; - tick_ops->add_tick(adj, current_tick_offset); + tick_ops->add_tick(adj); } #if DEBUG_TICK_SYNC t[i].rt = rt; @@ -1180,117 +1176,15 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs) preempt_enable(); } -#define prof_multiplier(__cpu) cpu_data(__cpu).multiplier -#define prof_counter(__cpu) cpu_data(__cpu).counter - -void smp_percpu_timer_interrupt(struct pt_regs *regs) -{ - unsigned long compare, tick, pstate; - int cpu = smp_processor_id(); - int user = user_mode(regs); - struct pt_regs *old_regs; - - /* - * Check for level 14 softint. - */ - { - unsigned long tick_mask = tick_ops->softint_mask; - - if (!(get_softint() & tick_mask)) { - extern void handler_irq(int, struct pt_regs *); - - handler_irq(14, regs); - return; - } - clear_softint(tick_mask); - } - - old_regs = set_irq_regs(regs); - do { - profile_tick(CPU_PROFILING); - if (!--prof_counter(cpu)) { - irq_enter(); - - if (cpu == boot_cpu_id) { - kstat_this_cpu.irqs[0]++; - timer_tick_interrupt(regs); - } - - update_process_times(user); - - irq_exit(); - - prof_counter(cpu) = prof_multiplier(cpu); - } - - /* Guarantee that the following sequences execute - * uninterrupted. - */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (pstate) - : "i" (PSTATE_IE)); - - compare = tick_ops->add_compare(current_tick_offset); - tick = tick_ops->get_tick(); - - /* Restore PSTATE_IE. */ - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : /* no outputs */ - : "r" (pstate)); - } while (time_after_eq(tick, compare)); - set_irq_regs(old_regs); -} - -static void __init smp_setup_percpu_timer(void) -{ - int cpu = smp_processor_id(); - unsigned long pstate; - - prof_counter(cpu) = prof_multiplier(cpu) = 1; - - /* Guarantee that the following sequences execute - * uninterrupted. - */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (pstate) - : "i" (PSTATE_IE)); - - tick_ops->init_tick(current_tick_offset); - - /* Restore PSTATE_IE. */ - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : /* no outputs */ - : "r" (pstate)); -} - void __init smp_tick_init(void) { boot_cpu_id = hard_smp_processor_id(); - current_tick_offset = timer_tick_offset; - - prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1; } /* /proc/profile writes can call this, don't __init it please. */ -static DEFINE_SPINLOCK(prof_setup_lock); - int setup_profiling_timer(unsigned int multiplier) { - unsigned long flags; - int i; - - if ((!multiplier) || (timer_tick_offset / multiplier) < 1000) - return -EINVAL; - - spin_lock_irqsave(&prof_setup_lock, flags); - for_each_possible_cpu(i) - prof_multiplier(i) = multiplier; - current_tick_offset = (timer_tick_offset / multiplier); - spin_unlock_irqrestore(&prof_setup_lock, flags); - - return 0; + return -EINVAL; } static void __init smp_tune_scheduling(void) diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index beffc82a1e8..d00f51a5683 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -212,7 +212,6 @@ EXPORT_SYMBOL(insl); #ifdef CONFIG_PCI EXPORT_SYMBOL(ebus_chain); EXPORT_SYMBOL(isa_chain); -EXPORT_SYMBOL(pci_memspace_mask); EXPORT_SYMBOL(pci_alloc_consistent); EXPORT_SYMBOL(pci_free_consistent); EXPORT_SYMBOL(pci_map_single); diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index f84da4f1b70..259063f41f9 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -31,6 +31,9 @@ #include <linux/profile.h> #include <linux/miscdevice.h> #include <linux/rtc.h> +#include <linux/kernel_stat.h> +#include <linux/clockchips.h> +#include <linux/clocksource.h> #include <asm/oplib.h> #include <asm/mostek.h> @@ -60,6 +63,7 @@ static void __iomem *mstk48t59_regs; static int set_rtc_mmss(unsigned long); #define TICK_PRIV_BIT (1UL << 63) +#define TICKCMP_IRQ_BIT (1UL << 63) #ifdef CONFIG_SMP unsigned long profile_pc(struct pt_regs *regs) @@ -93,21 +97,22 @@ static void tick_disable_protection(void) : "g2"); } -static void tick_init_tick(unsigned long offset) +static void tick_disable_irq(void) { - tick_disable_protection(); - __asm__ __volatile__( - " rd %%tick, %%g1\n" - " andn %%g1, %1, %%g1\n" " ba,pt %%xcc, 1f\n" - " add %%g1, %0, %%g1\n" + " nop\n" " .align 64\n" - "1: wr %%g1, 0x0, %%tick_cmpr\n" + "1: wr %0, 0x0, %%tick_cmpr\n" " rd %%tick_cmpr, %%g0" : /* no outputs */ - : "r" (offset), "r" (TICK_PRIV_BIT) - : "g1"); + : "r" (TICKCMP_IRQ_BIT)); +} + +static void tick_init_tick(void) +{ + tick_disable_protection(); + tick_disable_irq(); } static unsigned long tick_get_tick(void) @@ -121,20 +126,14 @@ static unsigned long tick_get_tick(void) return ret & ~TICK_PRIV_BIT; } -static unsigned long tick_get_compare(void) +static int tick_add_compare(unsigned long adj) { - unsigned long ret; + unsigned long orig_tick, new_tick, new_compare; - __asm__ __volatile__("rd %%tick_cmpr, %0\n\t" - "mov %0, %0" - : "=r" (ret)); + __asm__ __volatile__("rd %%tick, %0" + : "=r" (orig_tick)); - return ret; -} - -static unsigned long tick_add_compare(unsigned long adj) -{ - unsigned long new_compare; + orig_tick &= ~TICKCMP_IRQ_BIT; /* Workaround for Spitfire Errata (#54 I think??), I discovered * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch @@ -145,44 +144,41 @@ static unsigned long tick_add_compare(unsigned long adj) * at the start of an I-cache line, and perform a dummy * read back from %tick_cmpr right after writing to it. -DaveM */ - __asm__ __volatile__("rd %%tick_cmpr, %0\n\t" - "ba,pt %%xcc, 1f\n\t" - " add %0, %1, %0\n\t" + __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" + " add %1, %2, %0\n\t" ".align 64\n" "1:\n\t" "wr %0, 0, %%tick_cmpr\n\t" - "rd %%tick_cmpr, %%g0" - : "=&r" (new_compare) - : "r" (adj)); + "rd %%tick_cmpr, %%g0\n\t" + : "=r" (new_compare) + : "r" (orig_tick), "r" (adj)); - return new_compare; + __asm__ __volatile__("rd %%tick, %0" + : "=r" (new_tick)); + new_tick &= ~TICKCMP_IRQ_BIT; + + return ((long)(new_tick - (orig_tick+adj))) > 0L; } -static unsigned long tick_add_tick(unsigned long adj, unsigned long offset) +static unsigned long tick_add_tick(unsigned long adj) { - unsigned long new_tick, tmp; + unsigned long new_tick; /* Also need to handle Blackbird bug here too. */ __asm__ __volatile__("rd %%tick, %0\n\t" - "add %0, %2, %0\n\t" + "add %0, %1, %0\n\t" "wrpr %0, 0, %%tick\n\t" - "andn %0, %4, %1\n\t" - "ba,pt %%xcc, 1f\n\t" - " add %1, %3, %1\n\t" - ".align 64\n" - "1:\n\t" - "wr %1, 0, %%tick_cmpr\n\t" - "rd %%tick_cmpr, %%g0" - : "=&r" (new_tick), "=&r" (tmp) - : "r" (adj), "r" (offset), "r" (TICK_PRIV_BIT)); + : "=&r" (new_tick) + : "r" (adj)); return new_tick; } static struct sparc64_tick_ops tick_operations __read_mostly = { + .name = "tick", .init_tick = tick_init_tick, + .disable_irq = tick_disable_irq, .get_tick = tick_get_tick, - .get_compare = tick_get_compare, .add_tick = tick_add_tick, .add_compare = tick_add_compare, .softint_mask = 1UL << 0, @@ -190,7 +186,15 @@ static struct sparc64_tick_ops tick_operations __read_mostly = { struct sparc64_tick_ops *tick_ops __read_mostly = &tick_operations; -static void stick_init_tick(unsigned long offset) +static void stick_disable_irq(void) +{ + __asm__ __volatile__( + "wr %0, 0x0, %%asr25" + : /* no outputs */ + : "r" (TICKCMP_IRQ_BIT)); +} + +static void stick_init_tick(void) { /* Writes to the %tick and %stick register are not * allowed on sun4v. The Hypervisor controls that @@ -198,6 +202,7 @@ static void stick_init_tick(unsigned long offset) */ if (tlb_type != hypervisor) { tick_disable_protection(); + tick_disable_irq(); /* Let the user get at STICK too. */ __asm__ __volatile__( @@ -209,14 +214,7 @@ static void stick_init_tick(unsigned long offset) : "g1", "g2"); } - __asm__ __volatile__( - " rd %%asr24, %%g1\n" - " andn %%g1, %1, %%g1\n" - " add %%g1, %0, %%g1\n" - " wr %%g1, 0x0, %%asr25" - : /* no outputs */ - : "r" (offset), "r" (TICK_PRIV_BIT) - : "g1"); + stick_disable_irq(); } static unsigned long stick_get_tick(void) @@ -229,49 +227,43 @@ static unsigned long stick_get_tick(void) return ret & ~TICK_PRIV_BIT; } -static unsigned long stick_get_compare(void) +static unsigned long stick_add_tick(unsigned long adj) { - unsigned long ret; - - __asm__ __volatile__("rd %%asr25, %0" - : "=r" (ret)); - - return ret; -} - -static unsigned long stick_add_tick(unsigned long adj, unsigned long offset) -{ - unsigned long new_tick, tmp; + unsigned long new_tick; __asm__ __volatile__("rd %%asr24, %0\n\t" - "add %0, %2, %0\n\t" + "add %0, %1, %0\n\t" "wr %0, 0, %%asr24\n\t" - "andn %0, %4, %1\n\t" - "add %1, %3, %1\n\t" - "wr %1, 0, %%asr25" - : "=&r" (new_tick), "=&r" (tmp) - : "r" (adj), "r" (offset), "r" (TICK_PRIV_BIT)); + : "=&r" (new_tick) + : "r" (adj)); return new_tick; } -static unsigned long stick_add_compare(unsigned long adj) +static int stick_add_compare(unsigned long adj) { - unsigned long new_compare; + unsigned long orig_tick, new_tick; - __asm__ __volatile__("rd %%asr25, %0\n\t" - "add %0, %1, %0\n\t" - "wr %0, 0, %%asr25" - : "=&r" (new_compare) - : "r" (adj)); + __asm__ __volatile__("rd %%asr24, %0" + : "=r" (orig_tick)); + orig_tick &= ~TICKCMP_IRQ_BIT; + + __asm__ __volatile__("wr %0, 0, %%asr25" + : /* no outputs */ + : "r" (orig_tick + adj)); + + __asm__ __volatile__("rd %%asr24, %0" + : "=r" (new_tick)); + new_tick &= ~TICKCMP_IRQ_BIT; - return new_compare; + return ((long)(new_tick - (orig_tick+adj))) > 0L; } static struct sparc64_tick_ops stick_operations __read_mostly = { + .name = "stick", .init_tick = stick_init_tick, + .disable_irq = stick_disable_irq, .get_tick = stick_get_tick, - .get_compare = stick_get_compare, .add_tick = stick_add_tick, .add_compare = stick_add_compare, .softint_mask = 1UL << 16, @@ -320,20 +312,6 @@ static unsigned long __hbird_read_stick(void) return ret; } -static unsigned long __hbird_read_compare(void) -{ - unsigned long low, high; - unsigned long addr = HBIRD_STICKCMP_ADDR; - - __asm__ __volatile__("ldxa [%2] %3, %0\n\t" - "add %2, 0x8, %2\n\t" - "ldxa [%2] %3, %1" - : "=&r" (low), "=&r" (high), "=&r" (addr) - : "i" (ASI_PHYS_BYPASS_EC_E), "2" (addr)); - - return (high << 32UL) | low; -} - static void __hbird_write_stick(unsigned long val) { unsigned long low = (val & 0xffffffffUL); @@ -364,10 +342,13 @@ static void __hbird_write_compare(unsigned long val) "i" (ASI_PHYS_BYPASS_EC_E)); } -static void hbtick_init_tick(unsigned long offset) +static void hbtick_disable_irq(void) { - unsigned long val; + __hbird_write_compare(TICKCMP_IRQ_BIT); +} +static void hbtick_init_tick(void) +{ tick_disable_protection(); /* XXX This seems to be necessary to 'jumpstart' Hummingbird @@ -377,8 +358,7 @@ static void hbtick_init_tick(unsigned long offset) */ __hbird_write_stick(__hbird_read_stick()); - val = __hbird_read_stick() & ~TICK_PRIV_BIT; - __hbird_write_compare(val + offset); + hbtick_disable_irq(); } static unsigned long hbtick_get_tick(void) @@ -386,122 +366,95 @@ static unsigned long hbtick_get_tick(void) return __hbird_read_stick() & ~TICK_PRIV_BIT; } -static unsigned long hbtick_get_compare(void) -{ - return __hbird_read_compare(); -} - -static unsigned long hbtick_add_tick(unsigned long adj, unsigned long offset) +static unsigned long hbtick_add_tick(unsigned long adj) { unsigned long val; val = __hbird_read_stick() + adj; __hbird_write_stick(val); - val &= ~TICK_PRIV_BIT; - __hbird_write_compare(val + offset); - return val; } -static unsigned long hbtick_add_compare(unsigned long adj) +static int hbtick_add_compare(unsigned long adj) { - unsigned long val = __hbird_read_compare() + adj; + unsigned long val = __hbird_read_stick(); + unsigned long val2; - val &= ~TICK_PRIV_BIT; + val &= ~TICKCMP_IRQ_BIT; + val += adj; __hbird_write_compare(val); - return val; + val2 = __hbird_read_stick() & ~TICKCMP_IRQ_BIT; + + return ((long)(val2 - val)) > 0L; } static struct sparc64_tick_ops hbtick_operations __read_mostly = { + .name = "hbtick", .init_tick = hbtick_init_tick, + .disable_irq = hbtick_disable_irq, .get_tick = hbtick_get_tick, - .get_compare = hbtick_get_compare, .add_tick = hbtick_add_tick, .add_compare = hbtick_add_compare, .softint_mask = 1UL << 0, }; -/* timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - * - * NOTE: On SUN5 systems the ticker interrupt comes in using 2 - * interrupts, one at level14 and one with softint bit 0. - */ -unsigned long timer_tick_offset __read_mostly; - static unsigned long timer_ticks_per_nsec_quotient __read_mostly; #define TICK_SIZE (tick_nsec / 1000) -static inline void timer_check_rtc(void) -{ - /* last time the cmos clock got updated */ - static long last_rtc_update; - - /* Determine when to update the Mostek clock. */ - if (ntp_synced() && - xtime.tv_sec > last_rtc_update + 660 && - (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && - (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; - /* do it again in 60 s */ - } -} +#define USEC_AFTER 500000 +#define USEC_BEFORE 500000 -irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - unsigned long ticks, compare, pstate; +static void sync_cmos_clock(unsigned long dummy); - write_seqlock(&xtime_lock); +static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0); - do { -#ifndef CONFIG_SMP - profile_tick(CPU_PROFILING); - update_process_times(user_mode(get_irq_regs())); -#endif - do_timer(1); +static void sync_cmos_clock(unsigned long dummy) +{ + struct timeval now, next; + int fail = 1; - /* Guarantee that the following sequences execute - * uninterrupted. + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + * This code is run on a timer. If the clock is set, that timer + * may not expire at the correct time. Thus, we adjust... + */ + if (!ntp_synced()) + /* + * Not synced, exit, do not restart a timer (if one is + * running, let it run out). */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (pstate) - : "i" (PSTATE_IE)); + return; - compare = tick_ops->add_compare(timer_tick_offset); - ticks = tick_ops->get_tick(); + do_gettimeofday(&now); + if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 && + now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) + fail = set_rtc_mmss(now.tv_sec); - /* Restore PSTATE_IE. */ - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : /* no outputs */ - : "r" (pstate)); - } while (time_after_eq(ticks, compare)); + next.tv_usec = USEC_AFTER - now.tv_usec; + if (next.tv_usec <= 0) + next.tv_usec += USEC_PER_SEC; - timer_check_rtc(); + if (!fail) + next.tv_sec = 659; + else + next.tv_sec = 0; - write_sequnlock(&xtime_lock); - - return IRQ_HANDLED; + if (next.tv_usec >= USEC_PER_SEC) { + next.tv_sec++; + next.tv_usec -= USEC_PER_SEC; + } + mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next)); } -#ifdef CONFIG_SMP -void timer_tick_interrupt(struct pt_regs *regs) +void notify_arch_cmos_timer(void) { - write_seqlock(&xtime_lock); - - do_timer(1); - - timer_check_rtc(); - - write_sequnlock(&xtime_lock); + mod_timer(&sync_cmos_timer, jiffies + 1); } -#endif /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ static void __init kick_start_clock(void) @@ -751,7 +704,7 @@ retry: return -EOPNOTSUPP; } -static int __init clock_model_matches(char *model) +static int __init clock_model_matches(const char *model) { if (strcmp(model, "mk48t02") && strcmp(model, "mk48t08") && @@ -768,7 +721,7 @@ static int __init clock_model_matches(char *model) static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - char *model = of_get_property(dp, "model", NULL); + const char *model = of_get_property(dp, "model", NULL); unsigned long size, flags; void __iomem *regs; @@ -900,7 +853,6 @@ static unsigned long sparc64_init_timers(void) prop = of_find_property(dp, "stick-frequency", NULL); } clock = *(unsigned int *) prop->value; - timer_tick_offset = clock / HZ; #ifdef CONFIG_SMP smp_tick_init(); @@ -909,26 +861,6 @@ static unsigned long sparc64_init_timers(void) return clock; } -static void sparc64_start_timers(void) -{ - unsigned long pstate; - - /* Guarantee that the following sequences execute - * uninterrupted. - */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %1, %%pstate" - : "=r" (pstate) - : "i" (PSTATE_IE)); - - tick_ops->init_tick(timer_tick_offset); - - /* Restore PSTATE_IE. */ - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" - : /* no outputs */ - : "r" (pstate)); -} - struct freq_table { unsigned long clock_tick_ref; unsigned int ref_freq; @@ -975,29 +907,148 @@ static struct notifier_block sparc64_cpufreq_notifier_block = { #endif /* CONFIG_CPU_FREQ */ -static struct time_interpolator sparc64_cpu_interpolator = { - .source = TIME_SOURCE_CPU, - .shift = 16, - .mask = 0xffffffffffffffffLL +static int sparc64_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + return tick_ops->add_compare(delta) ? -ETIME : 0; +} + +static void sparc64_timer_setup(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + break; + + case CLOCK_EVT_MODE_SHUTDOWN: + tick_ops->disable_irq(); + break; + + case CLOCK_EVT_MODE_PERIODIC: + case CLOCK_EVT_MODE_UNUSED: + WARN_ON(1); + break; + }; +} + +static struct clock_event_device sparc64_clockevent = { + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_mode = sparc64_timer_setup, + .set_next_event = sparc64_next_event, + .rating = 100, + .shift = 30, + .irq = -1, }; +static DEFINE_PER_CPU(struct clock_event_device, sparc64_events); -/* The quotient formula is taken from the IA64 port. */ -#define SPARC64_NSEC_PER_CYC_SHIFT 10UL -void __init time_init(void) +void timer_interrupt(int irq, struct pt_regs *regs) { - unsigned long clock = sparc64_init_timers(); + struct pt_regs *old_regs = set_irq_regs(regs); + unsigned long tick_mask = tick_ops->softint_mask; + int cpu = smp_processor_id(); + struct clock_event_device *evt = &per_cpu(sparc64_events, cpu); + + clear_softint(tick_mask); + + irq_enter(); - sparc64_cpu_interpolator.frequency = clock; - register_time_interpolator(&sparc64_cpu_interpolator); + kstat_this_cpu.irqs[0]++; - /* Now that the interpolator is registered, it is - * safe to start the timer ticking. + if (unlikely(!evt->event_handler)) { + printk(KERN_WARNING + "Spurious SPARC64 timer interrupt on cpu %d\n", cpu); + } else + evt->event_handler(evt); + + irq_exit(); + + set_irq_regs(old_regs); +} + +void __devinit setup_sparc64_timer(void) +{ + struct clock_event_device *sevt; + unsigned long pstate; + + /* Guarantee that the following sequences execute + * uninterrupted. */ - sparc64_start_timers(); + __asm__ __volatile__("rdpr %%pstate, %0\n\t" + "wrpr %0, %1, %%pstate" + : "=r" (pstate) + : "i" (PSTATE_IE)); + + tick_ops->init_tick(); + + /* Restore PSTATE_IE. */ + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" + : /* no outputs */ + : "r" (pstate)); + + sevt = &__get_cpu_var(sparc64_events); + + memcpy(sevt, &sparc64_clockevent, sizeof(*sevt)); + sevt->cpumask = cpumask_of_cpu(smp_processor_id()); + + clockevents_register_device(sevt); +} + +#define SPARC64_NSEC_PER_CYC_SHIFT 32UL + +static struct clocksource clocksource_tick = { + .rating = 100, + .mask = CLOCKSOURCE_MASK(64), + .shift = 16, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void __init setup_clockevent_multiplier(unsigned long hz) +{ + unsigned long mult, shift = 32; + + while (1) { + mult = div_sc(hz, NSEC_PER_SEC, shift); + if (mult && (mult >> 32UL) == 0UL) + break; + + shift--; + } + + sparc64_clockevent.shift = shift; + sparc64_clockevent.mult = mult; +} + +void __init time_init(void) +{ + unsigned long clock = sparc64_init_timers(); timer_ticks_per_nsec_quotient = - (((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) + - (clock / 2)) / clock); + clocksource_hz2mult(clock, SPARC64_NSEC_PER_CYC_SHIFT); + + clocksource_tick.name = tick_ops->name; + clocksource_tick.mult = + clocksource_hz2mult(clock, + clocksource_tick.shift); + clocksource_tick.read = tick_ops->get_tick; + + printk("clocksource: mult[%x] shift[%d]\n", + clocksource_tick.mult, clocksource_tick.shift); + + clocksource_register(&clocksource_tick); + + sparc64_clockevent.name = tick_ops->name; + + setup_clockevent_multiplier(clock); + + sparc64_clockevent.max_delta_ns = + clockevent_delta2ns(0x7fffffffffffffff, &sparc64_clockevent); + sparc64_clockevent.min_delta_ns = + clockevent_delta2ns(0xF, &sparc64_clockevent); + + printk("clockevent: mult[%lx] shift[%d]\n", + sparc64_clockevent.mult, sparc64_clockevent.shift); + + setup_sparc64_timer(); #ifdef CONFIG_CPU_FREQ cpufreq_register_notifier(&sparc64_cpufreq_notifier_block, @@ -1126,10 +1177,6 @@ static int set_rtc_mmss(unsigned long nowtime) #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ static unsigned char mini_rtc_status; /* bitmapped status byte. */ -/* months start at 0 now */ -static unsigned char days_in_mo[] = -{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - #define FEBRUARY 2 #define STARTOFTIME 1970 #define SECDAY 86400L @@ -1278,8 +1325,7 @@ static int mini_rtc_ioctl(struct inode *inode, struct file *file, case RTC_SET_TIME: /* Set the RTC */ { - int year; - unsigned char leap_yr; + int year, days; if (!capable(CAP_SYS_TIME)) return -EACCES; @@ -1288,14 +1334,14 @@ static int mini_rtc_ioctl(struct inode *inode, struct file *file, return -EFAULT; year = wtime.tm_year + 1900; - leap_yr = ((!(year % 4) && (year % 100)) || - !(year % 400)); + days = month_days[wtime.tm_mon] + + ((wtime.tm_mon == 1) && leapyear(year)); - if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1)) + if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || + (wtime.tm_mday < 1)) return -EINVAL; - if (wtime.tm_mday < 0 || wtime.tm_mday > - (days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr))) + if (wtime.tm_mday < 0 || wtime.tm_mday > days) return -EINVAL; if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 || diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S index d7d2a8bdc66..7575aa371da 100644 --- a/arch/sparc64/kernel/ttable.S +++ b/arch/sparc64/kernel/ttable.S @@ -60,11 +60,7 @@ tl0_irq4: BTRAP(0x44) tl0_irq5: TRAP_IRQ(handler_irq, 5) tl0_irq6: BTRAP(0x46) BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) -#ifndef CONFIG_SMP -tl0_irq14: TRAP_IRQ(timer_irq, 14) -#else -tl0_irq14: TICK_SMP_IRQ -#endif +tl0_irq14: TRAP_IRQ(timer_interrupt, 14) tl0_irq15: TRAP_IRQ(handler_irq, 15) tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55) tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b) diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index f146071a4b2..cafadcbcdf3 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -122,24 +122,19 @@ static void __init read_obp_memory(const char *property, size = 0UL; base = new_base; } - regs[i].phys_addr = base; - regs[i].reg_size = size; - } - - for (i = 0; i < ents; i++) { - if (regs[i].reg_size == 0UL) { - int j; - - for (j = i; j < ents - 1; j++) { - regs[j].phys_addr = - regs[j+1].phys_addr; - regs[j].reg_size = - regs[j+1].reg_size; - } - - ents--; + if (size == 0UL) { + /* If it is empty, simply get rid of it. + * This simplifies the logic of the other + * functions that process these arrays. + */ + memmove(®s[i], ®s[i + 1], + (ents - i - 1) * sizeof(regs[0])); i--; + ents--; + continue; } + regs[i].phys_addr = base; + regs[i].reg_size = size; } *num_ents = ents; @@ -154,15 +149,6 @@ unsigned long *sparc64_valid_addr_bitmap __read_mostly; unsigned long kern_base __read_mostly; unsigned long kern_size __read_mostly; -/* get_new_mmu_context() uses "cache + 1". */ -DEFINE_SPINLOCK(ctx_alloc_lock); -unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; -#define CTX_BMAP_SLOTS (1UL << (CTX_NR_BITS - 6)) -unsigned long mmu_context_bmap[CTX_BMAP_SLOTS]; - -/* References to special section boundaries */ -extern char _start[], _end[]; - /* Initial ramdisk setup */ extern unsigned long sparc_ramdisk_image64; extern unsigned int sparc_ramdisk_image; @@ -406,19 +392,70 @@ void __kprobes flush_icache_range(unsigned long start, unsigned long end) if (tlb_type == spitfire) { unsigned long kaddr; - for (kaddr = start; kaddr < end; kaddr += PAGE_SIZE) - __flush_icache_page(__get_phys(kaddr)); + /* This code only runs on Spitfire cpus so this is + * why we can assume _PAGE_PADDR_4U. + */ + for (kaddr = start; kaddr < end; kaddr += PAGE_SIZE) { + unsigned long paddr, mask = _PAGE_PADDR_4U; + + if (kaddr >= PAGE_OFFSET) + paddr = kaddr & mask; + else { + pgd_t *pgdp = pgd_offset_k(kaddr); + pud_t *pudp = pud_offset(pgdp, kaddr); + pmd_t *pmdp = pmd_offset(pudp, kaddr); + pte_t *ptep = pte_offset_kernel(pmdp, kaddr); + + paddr = pte_val(*ptep) & mask; + } + __flush_icache_page(paddr); + } } } void show_mem(void) { - printk("Mem-info:\n"); + unsigned long total = 0, reserved = 0; + unsigned long shared = 0, cached = 0; + pg_data_t *pgdat; + + printk(KERN_INFO "Mem-info:\n"); show_free_areas(); - printk("Free swap: %6ldkB\n", + printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages << (PAGE_SHIFT-10)); - printk("%ld pages of RAM\n", num_physpages); - printk("%lu free pages\n", nr_free_pages()); + for_each_online_pgdat(pgdat) { + unsigned long i, flags; + + pgdat_resize_lock(pgdat, &flags); + for (i = 0; i < pgdat->node_spanned_pages; i++) { + struct page *page = pgdat_page_nr(pgdat, i); + total++; + if (PageReserved(page)) + reserved++; + else if (PageSwapCache(page)) + cached++; + else if (page_count(page)) + shared += page_count(page) - 1; + } + pgdat_resize_unlock(pgdat, &flags); + } + + printk(KERN_INFO "%lu pages of RAM\n", total); + printk(KERN_INFO "%lu reserved pages\n", reserved); + printk(KERN_INFO "%lu pages shared\n", shared); + printk(KERN_INFO "%lu pages swap cached\n", cached); + + printk(KERN_INFO "%lu pages dirty\n", + global_page_state(NR_FILE_DIRTY)); + printk(KERN_INFO "%lu pages writeback\n", + global_page_state(NR_WRITEBACK)); + printk(KERN_INFO "%lu pages mapped\n", + global_page_state(NR_FILE_MAPPED)); + printk(KERN_INFO "%lu pages slab\n", + global_page_state(NR_SLAB_RECLAIMABLE) + + global_page_state(NR_SLAB_UNRECLAIMABLE)); + printk(KERN_INFO "%lu pages pagetables\n", + global_page_state(NR_PAGETABLE)); } void mmu_info(struct seq_file *m) @@ -658,6 +695,13 @@ void __flush_dcache_range(unsigned long start, unsigned long end) } #endif /* DCACHE_ALIASING_POSSIBLE */ +/* get_new_mmu_context() uses "cache + 1". */ +DEFINE_SPINLOCK(ctx_alloc_lock); +unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; +#define MAX_CTX_NR (1UL << CTX_NR_BITS) +#define CTX_BMAP_SLOTS BITS_TO_LONGS(MAX_CTX_NR) +DECLARE_BITMAP(mmu_context_bmap, MAX_CTX_NR); + /* Caller does TLB context flushing on local CPU if necessary. * The caller also ensures that CTX_VALID(mm->context) is false. * @@ -717,95 +761,6 @@ out: smp_new_mmu_context_version(); } -void sparc_ultra_dump_itlb(void) -{ - int slot; - - if (tlb_type == spitfire) { - printk ("Contents of itlb: "); - for (slot = 0; slot < 14; slot++) printk (" "); - printk ("%2x:%016lx,%016lx\n", - 0, - spitfire_get_itlb_tag(0), spitfire_get_itlb_data(0)); - for (slot = 1; slot < 64; slot+=3) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - spitfire_get_itlb_tag(slot), spitfire_get_itlb_data(slot), - slot+1, - spitfire_get_itlb_tag(slot+1), spitfire_get_itlb_data(slot+1), - slot+2, - spitfire_get_itlb_tag(slot+2), spitfire_get_itlb_data(slot+2)); - } - } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { - printk ("Contents of itlb0:\n"); - for (slot = 0; slot < 16; slot+=2) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - cheetah_get_litlb_tag(slot), cheetah_get_litlb_data(slot), - slot+1, - cheetah_get_litlb_tag(slot+1), cheetah_get_litlb_data(slot+1)); - } - printk ("Contents of itlb2:\n"); - for (slot = 0; slot < 128; slot+=2) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - cheetah_get_itlb_tag(slot), cheetah_get_itlb_data(slot), - slot+1, - cheetah_get_itlb_tag(slot+1), cheetah_get_itlb_data(slot+1)); - } - } -} - -void sparc_ultra_dump_dtlb(void) -{ - int slot; - - if (tlb_type == spitfire) { - printk ("Contents of dtlb: "); - for (slot = 0; slot < 14; slot++) printk (" "); - printk ("%2x:%016lx,%016lx\n", 0, - spitfire_get_dtlb_tag(0), spitfire_get_dtlb_data(0)); - for (slot = 1; slot < 64; slot+=3) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - spitfire_get_dtlb_tag(slot), spitfire_get_dtlb_data(slot), - slot+1, - spitfire_get_dtlb_tag(slot+1), spitfire_get_dtlb_data(slot+1), - slot+2, - spitfire_get_dtlb_tag(slot+2), spitfire_get_dtlb_data(slot+2)); - } - } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { - printk ("Contents of dtlb0:\n"); - for (slot = 0; slot < 16; slot+=2) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - cheetah_get_ldtlb_tag(slot), cheetah_get_ldtlb_data(slot), - slot+1, - cheetah_get_ldtlb_tag(slot+1), cheetah_get_ldtlb_data(slot+1)); - } - printk ("Contents of dtlb2:\n"); - for (slot = 0; slot < 512; slot+=2) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - cheetah_get_dtlb_tag(slot, 2), cheetah_get_dtlb_data(slot, 2), - slot+1, - cheetah_get_dtlb_tag(slot+1, 2), cheetah_get_dtlb_data(slot+1, 2)); - } - if (tlb_type == cheetah_plus) { - printk ("Contents of dtlb3:\n"); - for (slot = 0; slot < 512; slot+=2) { - printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n", - slot, - cheetah_get_dtlb_tag(slot, 3), cheetah_get_dtlb_data(slot, 3), - slot+1, - cheetah_get_dtlb_tag(slot+1, 3), cheetah_get_dtlb_data(slot+1, 3)); - } - } - } -} - -extern unsigned long cmdline_memory_size; - /* Find a free area for the bootmem map, avoiding the kernel image * and the initial ramdisk. */ @@ -815,8 +770,8 @@ static unsigned long __init choose_bootmap_pfn(unsigned long start_pfn, unsigned long avoid_start, avoid_end, bootmap_size; int i; - bootmap_size = ((end_pfn - start_pfn) + 7) / 8; - bootmap_size = ALIGN(bootmap_size, sizeof(long)); + bootmap_size = bootmem_bootmap_pages(end_pfn - start_pfn); + bootmap_size <<= PAGE_SHIFT; avoid_start = avoid_end = 0; #ifdef CONFIG_BLK_DEV_INITRD @@ -983,6 +938,20 @@ static void __init trim_pavail(unsigned long *cur_size_p, } } +/* About pages_avail, this is the value we will use to calculate + * the zholes_size[] argument given to free_area_init_node(). The + * page allocator uses this to calculate nr_kernel_pages, + * nr_all_pages and zone->present_pages. On NUMA it is used + * to calculate zone->min_unmapped_pages and zone->min_slab_pages. + * + * So this number should really be set to what the page allocator + * actually ends up with. This means: + * 1) It should include bootmem map pages, we'll release those. + * 2) It should not include the kernel image, except for the + * __init sections which we will also release. + * 3) It should include the initrd image, since we'll release + * that too. + */ static unsigned long __init bootmem_init(unsigned long *pages_avail, unsigned long phys_base) { @@ -1069,7 +1038,6 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail, initrd_start, initrd_end); #endif reserve_bootmem(initrd_start, size); - *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; initrd_start += PAGE_OFFSET; initrd_end += PAGE_OFFSET; @@ -1082,6 +1050,11 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail, reserve_bootmem(kern_base, kern_size); *pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT; + /* Add back in the initmem pages. */ + size = ((unsigned long)(__init_end) & PAGE_MASK) - + PAGE_ALIGN((unsigned long)__init_begin); + *pages_avail += size >> PAGE_SHIFT; + /* Reserve the bootmem map. We do not account for it * in pages_avail because we will release that memory * in free_all_bootmem. @@ -1092,7 +1065,6 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail, (bootmap_pfn << PAGE_SHIFT), size); #endif reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size); - *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; for (i = 0; i < pavail_ents; i++) { unsigned long start_pfn, end_pfn; @@ -1584,6 +1556,10 @@ void __init mem_init(void) #ifdef CONFIG_DEBUG_BOOTMEM prom_printf("mem_init: Calling free_all_bootmem().\n"); #endif + + /* We subtract one to account for the mem_map_zero page + * allocated below. + */ totalram_pages = num_physpages = free_all_bootmem() - 1; /* @@ -1883,62 +1859,6 @@ static unsigned long kern_large_tte(unsigned long paddr) return val | paddr; } -/* - * Translate PROM's mapping we capture at boot time into physical address. - * The second parameter is only set from prom_callback() invocations. - */ -unsigned long prom_virt_to_phys(unsigned long promva, int *error) -{ - unsigned long mask; - int i; - - mask = _PAGE_PADDR_4U; - if (tlb_type == hypervisor) - mask = _PAGE_PADDR_4V; - - for (i = 0; i < prom_trans_ents; i++) { - struct linux_prom_translation *p = &prom_trans[i]; - - if (promva >= p->virt && - promva < (p->virt + p->size)) { - unsigned long base = p->data & mask; - - if (error) - *error = 0; - return base + (promva & (8192 - 1)); - } - } - if (error) - *error = 1; - return 0UL; -} - -/* XXX We should kill off this ugly thing at so me point. XXX */ -unsigned long sun4u_get_pte(unsigned long addr) -{ - pgd_t *pgdp; - pud_t *pudp; - pmd_t *pmdp; - pte_t *ptep; - unsigned long mask = _PAGE_PADDR_4U; - - if (tlb_type == hypervisor) - mask = _PAGE_PADDR_4V; - - if (addr >= PAGE_OFFSET) - return addr & mask; - - if ((addr >= LOW_OBP_ADDRESS) && (addr < HI_OBP_ADDRESS)) - return prom_virt_to_phys(addr, NULL); - - pgdp = pgd_offset_k(addr); - pudp = pud_offset(pgdp, addr); - pmdp = pmd_offset(pudp, addr); - ptep = pte_offset_kernel(pmdp, addr); - - return pte_val(*ptep) & mask; -} - /* If not locked, zap it. */ void __flush_tlb_all(void) { diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index 9fcaad6dd11..542c808ec2c 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -224,7 +224,8 @@ static char *serial(char *buffer, int sz) *buffer = 0; if (dp) { - char *val = of_get_property(dp, "system-board-serial#", &len); + const char *val = + of_get_property(dp, "system-board-serial#", &len); if (val && len > 0) { if (len > sz) diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c index 9c2e7a758f2..adeece11e59 100644 --- a/arch/um/drivers/daemon_kern.c +++ b/arch/um/drivers/daemon_kern.c @@ -46,7 +46,7 @@ static int daemon_read(int fd, struct sk_buff **skb, { *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); if(*skb == NULL) return(-ENOMEM); - return(net_recvfrom(fd, (*skb)->mac.raw, + return(net_recvfrom(fd, skb_mac_header(*skb), (*skb)->dev->mtu + ETH_HEADER_OTHER)); } diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c index 52ccb7b53cd..e6b8e0dd72a 100644 --- a/arch/um/drivers/mcast_kern.c +++ b/arch/um/drivers/mcast_kern.c @@ -50,7 +50,7 @@ static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) { *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); if(*skb == NULL) return(-ENOMEM); - return(net_recvfrom(fd, (*skb)->mac.raw, + return(net_recvfrom(fd, skb_mac_header(*skb), (*skb)->dev->mtu + ETH_HEADER_OTHER)); } diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 04e31f86c10..859303730b2 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -55,7 +55,7 @@ static int uml_net_rx(struct net_device *dev) skb->dev = dev; skb_put(skb, dev->mtu); - skb->mac.raw = skb->data; + skb_reset_mac_header(skb); pkt_len = (*lp->read)(lp->fd, &skb, lp); if (pkt_len > 0) { diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c index e67362acf0e..948849343ca 100644 --- a/arch/um/drivers/pcap_kern.c +++ b/arch/um/drivers/pcap_kern.c @@ -36,7 +36,7 @@ static int pcap_read(int fd, struct sk_buff **skb, { *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); if(*skb == NULL) return(-ENOMEM); - return(pcap_user_read(fd, (*skb)->mac.raw, + return(pcap_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu + ETH_HEADER_OTHER, (struct pcap_data *) &lp->user)); } diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c index 25634bd1f58..125c44f7763 100644 --- a/arch/um/drivers/slip_kern.c +++ b/arch/um/drivers/slip_kern.c @@ -49,7 +49,7 @@ static unsigned short slip_protocol(struct sk_buff *skbuff) static int slip_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) { - return(slip_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu, + return(slip_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu, (struct slip_data *) &lp->user)); } diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c index b3ed8fb874a..0a0324a6d29 100644 --- a/arch/um/drivers/slirp_kern.c +++ b/arch/um/drivers/slirp_kern.c @@ -53,7 +53,7 @@ static unsigned short slirp_protocol(struct sk_buff *skbuff) static int slirp_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) { - return(slirp_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu, + return(slirp_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu, (struct slirp_data *) &lp->user)); } diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c index 70541821775..12689141414 100644 --- a/arch/um/os-Linux/drivers/ethertap_kern.c +++ b/arch/um/os-Linux/drivers/ethertap_kern.c @@ -43,7 +43,7 @@ static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); if(*skb == NULL) return(-ENOMEM); - len = net_recvfrom(fd, (*skb)->mac.raw, + len = net_recvfrom(fd, skb_mac_header(*skb), (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); if(len <= 0) return(len); skb_pull(*skb, 2); diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c index 76570a2c25c..f1714e7fb1d 100644 --- a/arch/um/os-Linux/drivers/tuntap_kern.c +++ b/arch/um/os-Linux/drivers/tuntap_kern.c @@ -43,7 +43,7 @@ static int tuntap_read(int fd, struct sk_buff **skb, { *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); if(*skb == NULL) return(-ENOMEM); - return(net_read(fd, (*skb)->mac.raw, + return(net_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu + ETH_HEADER_OTHER)); } diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 7a1e251e333..b26378815b9 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -631,7 +631,6 @@ CONFIG_SATA_SIL=y CONFIG_SATA_VIA=y # CONFIG_SATA_VITESSE is not set # CONFIG_SATA_INIC162X is not set -CONFIG_SATA_INTEL_COMBINED=y CONFIG_SATA_ACPI=y # CONFIG_PATA_ALI is not set # CONFIG_PATA_AMD is not set diff --git a/arch/xtensa/lib/Makefile b/arch/xtensa/lib/Makefile index ed935b58e8a..6c4fdd86acd 100644 --- a/arch/xtensa/lib/Makefile +++ b/arch/xtensa/lib/Makefile @@ -2,6 +2,6 @@ # Makefile for Xtensa-specific library files. # -lib-y += memcopy.o memset.o checksum.o strcasecmp.o \ +lib-y += memcopy.o memset.o checksum.o \ usercopy.o strncpy_user.o strnlen_user.o lib-$(CONFIG_PCI) += pci-auto.o diff --git a/arch/xtensa/lib/strcasecmp.c b/arch/xtensa/lib/strcasecmp.c deleted file mode 100644 index 165b2d6effa..00000000000 --- a/arch/xtensa/lib/strcasecmp.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * linux/arch/xtensa/lib/strcasecmp.c - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file "COPYING" in the main directory of - * this archive for more details. - * - * Copyright (C) 2002 Tensilica Inc. - */ - -#include <linux/string.h> - - -/* We handle nothing here except the C locale. Since this is used in - only one place, on strings known to contain only 7 bit ASCII, this - is ok. */ - -int strcasecmp(const char *a, const char *b) -{ - int ca, cb; - - do { - ca = *a++ & 0xff; - cb = *b++ & 0xff; - if (ca >= 'A' && ca <= 'Z') - ca += 'a' - 'A'; - if (cb >= 'A' && cb <= 'Z') - cb += 'a' - 'A'; - } while (ca == cb && ca != '\0'); - - return ca - cb; -} diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c index 8ebfc876122..ab05bff4010 100644 --- a/arch/xtensa/platform-iss/network.c +++ b/arch/xtensa/platform-iss/network.c @@ -386,7 +386,7 @@ static int iss_net_rx(struct net_device *dev) /* Setup skb */ skb->dev = dev; - skb->mac.raw = skb->data; + skb_reset_mac_header(skb); pkt_len = lp->tp.read(lp, &skb); skb_put(skb, pkt_len); |