diff options
Diffstat (limited to 'arch')
143 files changed, 2097 insertions, 1774 deletions
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index ae21755..d973c98 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -321,11 +321,42 @@ static void locomo_gpio_unmask_irq(unsigned int irq) locomo_writel(r, mapbase + LOCOMO_GIE); } +static int GPIO_IRQ_rising_edge; +static int GPIO_IRQ_falling_edge; + +static int locomo_gpio_type(unsigned int irq, unsigned int type) +{ + unsigned int mask; + void __iomem *mapbase = get_irq_chip_data(irq); + + mask = 1 << (irq - LOCOMO_IRQ_GPIO_START); + + if (type == IRQT_PROBE) { + if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask) + return 0; + type = __IRQT_RISEDGE | __IRQT_FALEDGE; + } + + if (type & __IRQT_RISEDGE) + GPIO_IRQ_rising_edge |= mask; + else + GPIO_IRQ_rising_edge &= ~mask; + if (type & __IRQT_FALEDGE) + GPIO_IRQ_falling_edge |= mask; + else + GPIO_IRQ_falling_edge &= ~mask; + locomo_writel(GPIO_IRQ_rising_edge, mapbase + LOCOMO_GRIE); + locomo_writel(GPIO_IRQ_falling_edge, mapbase + LOCOMO_GFIE); + + return 0; +} + static struct irq_chip locomo_gpio_chip = { - .name = "LOCOMO-gpio", - .ack = locomo_gpio_ack_irq, - .mask = locomo_gpio_mask_irq, - .unmask = locomo_gpio_unmask_irq, + .name = "LOCOMO-gpio", + .ack = locomo_gpio_ack_irq, + .mask = locomo_gpio_mask_irq, + .unmask = locomo_gpio_unmask_irq, + .set_type = locomo_gpio_type, }; static void locomo_lt_handler(unsigned int irq, struct irq_desc *desc) @@ -450,22 +481,18 @@ static void locomo_setup_irq(struct locomo *lchip) set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip); set_irq_chip_data(IRQ_LOCOMO_KEY_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler); - set_irq_flags(IRQ_LOCOMO_KEY_BASE, IRQF_VALID | IRQF_PROBE); set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip); set_irq_chip_data(IRQ_LOCOMO_GPIO_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler); - set_irq_flags(IRQ_LOCOMO_GPIO_BASE, IRQF_VALID | IRQF_PROBE); set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip); set_irq_chip_data(IRQ_LOCOMO_LT_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler); - set_irq_flags(IRQ_LOCOMO_LT_BASE, IRQF_VALID | IRQF_PROBE); set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip); set_irq_chip_data(IRQ_LOCOMO_SPI_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler); - set_irq_flags(IRQ_LOCOMO_SPI_BASE, IRQF_VALID | IRQF_PROBE); /* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */ set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip); @@ -488,7 +515,7 @@ static void locomo_setup_irq(struct locomo *lchip) set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE); /* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */ - for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 3; irq++) { + for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 4; irq++) { set_irq_chip(irq, &locomo_spi_chip); set_irq_chip_data(irq, irqbase); set_irq_handler(irq, handle_edge_irq); @@ -574,20 +601,20 @@ static int locomo_suspend(struct platform_device *dev, pm_message_t state) save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */ locomo_writel(0x00, lchip->base + LOCOMO_GPO); - save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPICT); /* SPI */ + save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPICT); /* SPI */ locomo_writel(0x40, lchip->base + LOCOMO_SPICT); save->LCM_GPE = locomo_readl(lchip->base + LOCOMO_GPE); /* GPIO */ locomo_writel(0x00, lchip->base + LOCOMO_GPE); save->LCM_ASD = locomo_readl(lchip->base + LOCOMO_ASD); /* ADSTART */ locomo_writel(0x00, lchip->base + LOCOMO_ASD); - save->LCM_SPIMD = locomo_readl(lchip->base + LOCOMO_SPIMD); /* SPI */ - locomo_writel(0x3C14, lchip->base + LOCOMO_SPIMD); + save->LCM_SPIMD = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPIMD); /* SPI */ + locomo_writel(0x3C14, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD); locomo_writel(0x00, lchip->base + LOCOMO_PAIF); locomo_writel(0x00, lchip->base + LOCOMO_DAC); locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC); - if ( (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88) ) + if ((locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88)) locomo_writel(0x00, lchip->base + LOCOMO_C32K); /* CLK32 off */ else /* 18MHz already enabled, so no wait */ @@ -616,10 +643,10 @@ static int locomo_resume(struct platform_device *dev) spin_lock_irqsave(&lchip->lock, flags); locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO); - locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPICT); + locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPI + LOCOMO_SPICT); locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE); locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD); - locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPIMD); + locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD); locomo_writel(0x00, lchip->base + LOCOMO_C32K); locomo_writel(0x90, lchip->base + LOCOMO_TADC); @@ -688,9 +715,9 @@ __locomo_probe(struct device *me, struct resource *mem, int irq) /* GPIO */ locomo_writel(0, lchip->base + LOCOMO_GPO); - locomo_writel( (LOCOMO_GPIO(2) | LOCOMO_GPIO(3) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14)) + locomo_writel((LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14)) , lchip->base + LOCOMO_GPE); - locomo_writel( (LOCOMO_GPIO(2) | LOCOMO_GPIO(3) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14)) + locomo_writel((LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14)) , lchip->base + LOCOMO_GPD); locomo_writel(0, lchip->base + LOCOMO_GIE); @@ -833,7 +860,10 @@ void locomo_gpio_set_dir(struct device *dev, unsigned int bits, unsigned int dir spin_lock_irqsave(&lchip->lock, flags); r = locomo_readl(lchip->base + LOCOMO_GPD); - r &= ~bits; + if (dir) + r |= bits; + else + r &= ~bits; locomo_writel(r, lchip->base + LOCOMO_GPD); r = locomo_readl(lchip->base + LOCOMO_GPE); diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index f73d62e..688b7b1 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -179,3 +179,5 @@ EXPORT_SYMBOL(_find_next_zero_bit_be); EXPORT_SYMBOL(_find_first_bit_be); EXPORT_SYMBOL(_find_next_bit_be); #endif + +EXPORT_SYMBOL(copy_page); diff --git a/arch/arm/kernel/arthur.c b/arch/arm/kernel/arthur.c index 0ee2e98..321c529 100644 --- a/arch/arm/kernel/arthur.c +++ b/arch/arm/kernel/arthur.c @@ -90,3 +90,5 @@ static void __exit arthur_exit(void) module_init(arthur_init); module_exit(arthur_exit); + +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 8bc1872..1d7bca6 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -280,7 +280,7 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) const int port = gpio >> 3; const int port_mask = 1 << (gpio & 7); - gpio_direction_output(gpio, gpio_get_value(gpio)); + gpio_direction_input(gpio); switch (type) { case IRQT_RISING: diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c index 36e5835..ca85d24 100644 --- a/arch/arm/mach-ns9xxx/irq.c +++ b/arch/arm/mach-ns9xxx/irq.c @@ -62,7 +62,7 @@ static struct irq_chip ns9xxx_chip = { #if 0 #define handle_irq handle_level_irq #else -void handle_prio_irq(unsigned int irq, struct irq_desc *desc) +static void handle_prio_irq(unsigned int irq, struct irq_desc *desc) { unsigned int cpu = smp_processor_id(); struct irqaction *action; @@ -70,27 +70,35 @@ void handle_prio_irq(unsigned int irq, struct irq_desc *desc) spin_lock(&desc->lock); - if (unlikely(desc->status & IRQ_INPROGRESS)) - goto out_unlock; + BUG_ON(desc->status & IRQ_INPROGRESS); desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); kstat_cpu(cpu).irqs[irq]++; action = desc->action; if (unlikely(!action || (desc->status & IRQ_DISABLED))) - goto out_unlock; + goto out_mask; desc->status |= IRQ_INPROGRESS; spin_unlock(&desc->lock); action_ret = handle_IRQ_event(irq, action); + /* XXX: There is no direct way to access noirqdebug, so check + * unconditionally for spurious irqs... + * Maybe this function should go to kernel/irq/chip.c? */ + note_interrupt(irq, desc, action_ret); + spin_lock(&desc->lock); desc->status &= ~IRQ_INPROGRESS; - if (!(desc->status & IRQ_DISABLED) && desc->chip->ack) - desc->chip->ack(irq); -out_unlock: + if (desc->status & IRQ_DISABLED) +out_mask: + desc->chip->mask(irq); + + /* ack unconditionally to unmask lower prio irqs */ + desc->chip->ack(irq); + spin_unlock(&desc->lock); } #define handle_irq handle_prio_irq diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c index 9608503..e63fb05 100644 --- a/arch/arm/mach-orion5x/addr-map.c +++ b/arch/arm/mach-orion5x/addr-map.c @@ -34,11 +34,7 @@ * Non-CPU Masters address decoding -- * Unlike the CPU, we setup the access from Orion's master interfaces to DDR * banks only (the typical use case). - * Setup access for each master to DDR is issued by common.c. - * - * Note: although orion_setbits() and orion_clrbits() are not atomic - * no locking is necessary here since code in this file is only called - * at boot time when there is no concurrency issues. + * Setup access for each master to DDR is issued by platform device setup. */ /* @@ -48,10 +44,6 @@ #define TARGET_DEV_BUS 1 #define TARGET_PCI 3 #define TARGET_PCIE 4 -#define ATTR_DDR_CS(n) (((n) ==0) ? 0xe : \ - ((n) == 1) ? 0xd : \ - ((n) == 2) ? 0xb : \ - ((n) == 3) ? 0x7 : 0xf) #define ATTR_PCIE_MEM 0x59 #define ATTR_PCIE_IO 0x51 #define ATTR_PCIE_WA 0x79 @@ -61,17 +53,12 @@ #define ATTR_DEV_CS1 0x1d #define ATTR_DEV_CS2 0x1b #define ATTR_DEV_BOOT 0xf -#define WIN_EN 1 /* * Helpers to get DDR bank info */ -#define DDR_BASE_CS(n) ORION5X_DDR_REG(0x1500 + ((n) * 8)) -#define DDR_SIZE_CS(n) ORION5X_DDR_REG(0x1504 + ((n) * 8)) -#define DDR_MAX_CS 4 -#define DDR_REG_TO_SIZE(reg) (((reg) | 0xffffff) + 1) -#define DDR_REG_TO_BASE(reg) ((reg) & 0xff000000) -#define DDR_BANK_EN 1 +#define DDR_BASE_CS(n) ORION5X_DDR_REG(0x1500 + ((n) << 3)) +#define DDR_SIZE_CS(n) ORION5X_DDR_REG(0x1504 + ((n) << 3)) /* * CPU Address Decode Windows registers @@ -81,17 +68,6 @@ #define CPU_WIN_REMAP_LO(n) ORION5X_BRIDGE_REG(0x008 | ((n) << 4)) #define CPU_WIN_REMAP_HI(n) ORION5X_BRIDGE_REG(0x00c | ((n) << 4)) -/* - * Gigabit Ethernet Address Decode Windows registers - */ -#define ETH_WIN_BASE(win) ORION5X_ETH_REG(0x200 + ((win) * 8)) -#define ETH_WIN_SIZE(win) ORION5X_ETH_REG(0x204 + ((win) * 8)) -#define ETH_WIN_REMAP(win) ORION5X_ETH_REG(0x280 + ((win) * 4)) -#define ETH_WIN_EN ORION5X_ETH_REG(0x290) -#define ETH_WIN_PROT ORION5X_ETH_REG(0x294) -#define ETH_MAX_WIN 6 -#define ETH_MAX_REMAP_WIN 4 - struct mbus_dram_target_info orion5x_mbus_dram_info; @@ -202,39 +178,3 @@ void __init orion5x_setup_pcie_wa_win(u32 base, u32 size) { setup_cpu_win(7, base, size, TARGET_PCIE, ATTR_PCIE_WA, -1); } - -void __init orion5x_setup_eth_wins(void) -{ - int i; - - /* - * First, disable and clear windows - */ - for (i = 0; i < ETH_MAX_WIN; i++) { - orion5x_write(ETH_WIN_BASE(i), 0); - orion5x_write(ETH_WIN_SIZE(i), 0); - orion5x_setbits(ETH_WIN_EN, 1 << i); - orion5x_clrbits(ETH_WIN_PROT, 0x3 << (i * 2)); - if (i < ETH_MAX_REMAP_WIN) - orion5x_write(ETH_WIN_REMAP(i), 0); - } - - /* - * Setup windows for DDR banks. - */ - for (i = 0; i < DDR_MAX_CS; i++) { - u32 base, size; - size = orion5x_read(DDR_SIZE_CS(i)); - base = orion5x_read(DDR_BASE_CS(i)); - if (size & DDR_BANK_EN) { - base = DDR_REG_TO_BASE(base); - size = DDR_REG_TO_SIZE(size); - orion5x_write(ETH_WIN_SIZE(i), (size-1) & 0xffff0000); - orion5x_write(ETH_WIN_BASE(i), (base & 0xffff0000) | - (ATTR_DDR_CS(i) << 8) | - TARGET_DDR); - orion5x_clrbits(ETH_WIN_EN, 1 << i); - orion5x_setbits(ETH_WIN_PROT, 0x3 << (i * 2)); - } - } -} diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 968deb5..4f13fd0 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -190,6 +190,11 @@ static struct platform_device orion5x_ehci1 = { * (The Orion and Discovery (MV643xx) families use the same Ethernet driver) ****************************************************************************/ +struct mv643xx_eth_shared_platform_data orion5x_eth_shared_data = { + .dram = &orion5x_mbus_dram_info, + .t_clk = ORION5X_TCLK, +}; + static struct resource orion5x_eth_shared_resources[] = { { .start = ORION5X_ETH_PHYS_BASE + 0x2000, @@ -201,6 +206,9 @@ static struct resource orion5x_eth_shared_resources[] = { static struct platform_device orion5x_eth_shared = { .name = MV643XX_ETH_SHARED_NAME, .id = 0, + .dev = { + .platform_data = &orion5x_eth_shared_data, + }, .num_resources = 1, .resource = orion5x_eth_shared_resources, }; @@ -223,7 +231,9 @@ static struct platform_device orion5x_eth = { void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data) { + eth_data->shared = &orion5x_eth_shared; orion5x_eth.dev.platform_data = eth_data; + platform_device_register(&orion5x_eth_shared); platform_device_register(&orion5x_eth); } @@ -360,7 +370,6 @@ void __init orion5x_init(void) * Setup Orion address map */ orion5x_setup_cpu_mbus_bridge(); - orion5x_setup_eth_wins(); /* * Register devices. diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index 14adf8d..bd0f05d 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -22,7 +22,6 @@ void orion5x_setup_dev0_win(u32 base, u32 size); void orion5x_setup_dev1_win(u32 base, u32 size); void orion5x_setup_dev2_win(u32 base, u32 size); void orion5x_setup_pcie_wa_win(u32 base, u32 size); -void orion5x_setup_eth_wins(void); /* * Shared code used internally by other Orion core functions. diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index f9430f5..27ce967 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -58,7 +58,7 @@ static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) } static struct hw_pci dns323_pci __initdata = { - .nr_controllers = 1, + .nr_controllers = 2, .swizzle = pci_std_swizzle, .setup = orion5x_pci_sys_setup, .scan = orion5x_pci_sys_scan_bus, diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c index 8841086..f5074b8 100644 --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -138,7 +138,7 @@ static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) } static struct hw_pci kurobox_pro_pci __initdata = { - .nr_controllers = 1, + .nr_controllers = 2, .swizzle = pci_std_swizzle, .setup = orion5x_pci_sys_setup, .scan = orion5x_pci_sys_scan_bus, diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 6a83085..0e6d05b 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -5,6 +5,13 @@ # Common support (must be linked before board specific support) obj-y += clock.o devices.o generic.o irq.o dma.o \ time.o gpio.o +obj-$(CONFIG_PM) += pm.o sleep.o standby.o +obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o + +# Generic drivers that other drivers may depend upon +obj-$(CONFIG_PXA_SSP) += ssp.o + +# SoC-specific code obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa25x.o obj-$(CONFIG_PXA27x) += mfp-pxa2xx.o pxa27x.o obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o pxa3xx.o smemc.o @@ -48,11 +55,6 @@ led-$(CONFIG_MACH_TRIZEPS4) += leds-trizeps4.o obj-$(CONFIG_LEDS) += $(led-y) -# Misc features -obj-$(CONFIG_PM) += pm.o sleep.o standby.o -obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o -obj-$(CONFIG_PXA_SSP) += ssp.o - ifeq ($(CONFIG_PCI),y) obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o endif diff --git a/arch/arm/mach-pxa/colibri.c b/arch/arm/mach-pxa/colibri.c index 43bf5a1..574839d 100644 --- a/arch/arm/mach-pxa/colibri.c +++ b/arch/arm/mach-pxa/colibri.c @@ -98,7 +98,7 @@ static struct resource dm9000_resources[] = { [2] = { .start = COLIBRI_ETH_IRQ, .end = COLIBRI_ETH_IRQ, - .flags = IORESOURCE_IRQ, + .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING, }, }; @@ -119,7 +119,6 @@ static void __init colibri_init(void) /* DM9000 LAN */ pxa_gpio_mode(GPIO78_nCS_2_MD); pxa_gpio_mode(GPIO_DM9000 | GPIO_IN); - set_irq_type(COLIBRI_ETH_IRQ, IRQT_FALLING); platform_add_devices(colibri_devices, ARRAY_SIZE(colibri_devices)); } diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 259ca82..b757dd7 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -493,8 +493,6 @@ static struct platform_device *devices[] __initdata = { static void corgi_poweroff(void) { - RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; - if (!machine_is_corgi()) /* Green LED off tells the bootloader to halt */ reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); @@ -503,8 +501,6 @@ static void corgi_poweroff(void) static void corgi_restart(char mode) { - RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; - if (!machine_is_corgi()) /* Green LED on tells the bootloader to reboot */ set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); diff --git a/arch/arm/mach-pxa/cpu-pxa.c b/arch/arm/mach-pxa/cpu-pxa.c index 4b21479..fb9ba1a 100644 --- a/arch/arm/mach-pxa/cpu-pxa.c +++ b/arch/arm/mach-pxa/cpu-pxa.c @@ -49,125 +49,216 @@ MODULE_PARM_DESC(freq_debug, "Set the debug messages to on=1/off=0"); #define freq_debug 0 #endif +static unsigned int pxa27x_maxfreq; +module_param(pxa27x_maxfreq, uint, 0); +MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz" + "(typically 624=>pxa270, 416=>pxa271, 520=>pxa272)"); + typedef struct { unsigned int khz; unsigned int membus; unsigned int cccr; unsigned int div2; + unsigned int cclkcfg; } pxa_freqs_t; /* Define the refresh period in mSec for the SDRAM and the number of rows */ -#define SDRAM_TREF 64 /* standard 64ms SDRAM */ -#define SDRAM_ROWS 4096 /* 64MB=8192 32MB=4096 */ -#define MDREFR_DRI(x) (((x) * SDRAM_TREF) / (SDRAM_ROWS * 32)) - -#define CCLKCFG_TURBO 0x1 -#define CCLKCFG_FCS 0x2 -#define PXA25x_MIN_FREQ 99500 -#define PXA25x_MAX_FREQ 398100 -#define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2) -#define MDREFR_DRI_MASK 0xFFF +#define SDRAM_TREF 64 /* standard 64ms SDRAM */ +#define SDRAM_ROWS 4096 /* 64MB=8192 32MB=4096 */ +#define CCLKCFG_TURBO 0x1 +#define CCLKCFG_FCS 0x2 +#define CCLKCFG_HALFTURBO 0x4 +#define CCLKCFG_FASTBUS 0x8 +#define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2) +#define MDREFR_DRI_MASK 0xFFF +/* + * PXA255 definitions + */ /* Use the run mode frequencies for the CPUFREQ_POLICY_PERFORMANCE policy */ +#define CCLKCFG CCLKCFG_TURBO | CCLKCFG_FCS + static pxa_freqs_t pxa255_run_freqs[] = { - /* CPU MEMBUS CCCR DIV2*/ - { 99500, 99500, 0x121, 1}, /* run= 99, turbo= 99, PXbus=50, SDRAM=50 */ - {132700, 132700, 0x123, 1}, /* run=133, turbo=133, PXbus=66, SDRAM=66 */ - {199100, 99500, 0x141, 0}, /* run=199, turbo=199, PXbus=99, SDRAM=99 */ - {265400, 132700, 0x143, 1}, /* run=265, turbo=265, PXbus=133, SDRAM=66 */ - {331800, 165900, 0x145, 1}, /* run=331, turbo=331, PXbus=166, SDRAM=83 */ - {398100, 99500, 0x161, 0}, /* run=398, turbo=398, PXbus=196, SDRAM=99 */ - {0,} + /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ + { 99500, 99500, 0x121, 1, CCLKCFG}, /* 99, 99, 50, 50 */ + {132700, 132700, 0x123, 1, CCLKCFG}, /* 133, 133, 66, 66 */ + {199100, 99500, 0x141, 0, CCLKCFG}, /* 199, 199, 99, 99 */ + {265400, 132700, 0x143, 1, CCLKCFG}, /* 265, 265, 133, 66 */ + {331800, 165900, 0x145, 1, CCLKCFG}, /* 331, 331, 166, 83 */ + {398100, 99500, 0x161, 0, CCLKCFG}, /* 398, 398, 196, 99 */ }; -#define NUM_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs) - -static struct cpufreq_frequency_table pxa255_run_freq_table[NUM_RUN_FREQS+1]; /* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */ static pxa_freqs_t pxa255_turbo_freqs[] = { - /* CPU MEMBUS CCCR DIV2*/ - { 99500, 99500, 0x121, 1}, /* run=99, turbo= 99, PXbus=50, SDRAM=50 */ - {199100, 99500, 0x221, 0}, /* run=99, turbo=199, PXbus=50, SDRAM=99 */ - {298500, 99500, 0x321, 0}, /* run=99, turbo=287, PXbus=50, SDRAM=99 */ - {298600, 99500, 0x1c1, 0}, /* run=199, turbo=287, PXbus=99, SDRAM=99 */ - {398100, 99500, 0x241, 0}, /* run=199, turbo=398, PXbus=99, SDRAM=99 */ - {0,} + /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ + { 99500, 99500, 0x121, 1, CCLKCFG}, /* 99, 99, 50, 50 */ + {199100, 99500, 0x221, 0, CCLKCFG}, /* 99, 199, 50, 99 */ + {298500, 99500, 0x321, 0, CCLKCFG}, /* 99, 287, 50, 99 */ + {298600, 99500, 0x1c1, 0, CCLKCFG}, /* 199, 287, 99, 99 */ + {398100, 99500, 0x241, 0, CCLKCFG}, /* 199, 398, 99, 99 */ +}; + +#define NUM_PXA25x_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs) +#define NUM_PXA25x_TURBO_FREQS ARRAY_SIZE(pxa255_turbo_freqs) + +static struct cpufreq_frequency_table + pxa255_run_freq_table[NUM_PXA25x_RUN_FREQS+1]; +static struct cpufreq_frequency_table + pxa255_turbo_freq_table[NUM_PXA25x_TURBO_FREQS+1]; + +/* + * PXA270 definitions + * + * For the PXA27x: + * Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG. + * + * A = 0 => memory controller clock from table 3-7, + * A = 1 => memory controller clock = system bus clock + * Run mode frequency = 13 MHz * L + * Turbo mode frequency = 13 MHz * L * N + * System bus frequency = 13 MHz * L / (B + 1) + * + * In CCCR: + * A = 1 + * L = 16 oscillator to run mode ratio + * 2N = 6 2 * (turbo mode to run mode ratio) + * + * In CCLKCFG: + * B = 1 Fast bus mode + * HT = 0 Half-Turbo mode + * T = 1 Turbo mode + * + * For now, just support some of the combinations in table 3-7 of + * PXA27x Processor Family Developer's Manual to simplify frequency + * change sequences. + */ +#define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L) +#define CCLKCFG2(B, HT, T) \ + (CCLKCFG_FCS | \ + ((B) ? CCLKCFG_FASTBUS : 0) | \ + ((HT) ? CCLKCFG_HALFTURBO : 0) | \ + ((T) ? CCLKCFG_TURBO : 0)) + +static pxa_freqs_t pxa27x_freqs[] = { + {104000, 104000, PXA27x_CCCR(1, 8, 2), 0, CCLKCFG2(1, 0, 1)}, + {156000, 104000, PXA27x_CCCR(1, 8, 6), 0, CCLKCFG2(1, 1, 1)}, + {208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1)}, + {312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1)}, + {416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1)}, + {520000, 208000, PXA27x_CCCR(1, 16, 5), 1, CCLKCFG2(1, 0, 1)}, + {624000, 208000, PXA27x_CCCR(1, 16, 6), 1, CCLKCFG2(1, 0, 1)} }; -#define NUM_TURBO_FREQS ARRAY_SIZE(pxa255_turbo_freqs) -static struct cpufreq_frequency_table pxa255_turbo_freq_table[NUM_TURBO_FREQS+1]; +#define NUM_PXA27x_FREQS ARRAY_SIZE(pxa27x_freqs) +static struct cpufreq_frequency_table + pxa27x_freq_table[NUM_PXA27x_FREQS+1]; extern unsigned get_clk_frequency_khz(int info); +static void find_freq_tables(struct cpufreq_policy *policy, + struct cpufreq_frequency_table **freq_table, + pxa_freqs_t **pxa_freqs) +{ + if (cpu_is_pxa25x()) { + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { + *pxa_freqs = pxa255_run_freqs; + *freq_table = pxa255_run_freq_table; + } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) { + *pxa_freqs = pxa255_turbo_freqs; + *freq_table = pxa255_turbo_freq_table; + } else { + printk("CPU PXA: Unknown policy found. " + "Using CPUFREQ_POLICY_PERFORMANCE\n"); + *pxa_freqs = pxa255_run_freqs; + *freq_table = pxa255_run_freq_table; + } + } + if (cpu_is_pxa27x()) { + *pxa_freqs = pxa27x_freqs; + *freq_table = pxa27x_freq_table; + } +} + +static void pxa27x_guess_max_freq(void) +{ + if (!pxa27x_maxfreq) { + pxa27x_maxfreq = 416000; + printk(KERN_INFO "PXA CPU 27x max frequency not defined " + "(pxa27x_maxfreq), assuming pxa271 with %dkHz maxfreq\n", + pxa27x_maxfreq); + } else { + pxa27x_maxfreq *= 1000; + } +} + +static u32 mdrefr_dri(unsigned int freq) +{ + u32 dri = 0; + + if (cpu_is_pxa25x()) + dri = ((freq * SDRAM_TREF) / (SDRAM_ROWS * 32)); + if (cpu_is_pxa27x()) + dri = ((freq * SDRAM_TREF) / (SDRAM_ROWS - 31)) / 32; + return dri; +} + /* find a valid frequency point */ static int pxa_verify_policy(struct cpufreq_policy *policy) { struct cpufreq_frequency_table *pxa_freqs_table; + pxa_freqs_t *pxa_freqs; int ret; - if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { - pxa_freqs_table = pxa255_run_freq_table; - } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) { - pxa_freqs_table = pxa255_turbo_freq_table; - } else { - printk("CPU PXA: Unknown policy found. " - "Using CPUFREQ_POLICY_PERFORMANCE\n"); - pxa_freqs_table = pxa255_run_freq_table; - } - + find_freq_tables(policy, &pxa_freqs_table, &pxa_freqs); ret = cpufreq_frequency_table_verify(policy, pxa_freqs_table); if (freq_debug) pr_debug("Verified CPU policy: %dKhz min to %dKhz max\n", - policy->min, policy->max); + policy->min, policy->max); return ret; } +static unsigned int pxa_cpufreq_get(unsigned int cpu) +{ + return get_clk_frequency_khz(0); +} + static int pxa_set_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int target_freq, + unsigned int relation) { struct cpufreq_frequency_table *pxa_freqs_table; pxa_freqs_t *pxa_freq_settings; struct cpufreq_freqs freqs; unsigned int idx; unsigned long flags; - unsigned int unused, preset_mdrefr, postset_mdrefr; - void *ramstart = phys_to_virt(0xa0000000); + unsigned int new_freq_cpu, new_freq_mem; + unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg; /* Get the current policy */ - if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { - pxa_freq_settings = pxa255_run_freqs; - pxa_freqs_table = pxa255_run_freq_table; - } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) { - pxa_freq_settings = pxa255_turbo_freqs; - pxa_freqs_table = pxa255_turbo_freq_table; - } else { - printk("CPU PXA: Unknown policy found. " - "Using CPUFREQ_POLICY_PERFORMANCE\n"); - pxa_freq_settings = pxa255_run_freqs; - pxa_freqs_table = pxa255_run_freq_table; - } + find_freq_tables(policy, &pxa_freqs_table, &pxa_freq_settings); /* Lookup the next frequency */ if (cpufreq_frequency_table_target(policy, pxa_freqs_table, - target_freq, relation, &idx)) { + target_freq, relation, &idx)) { return -EINVAL; } + new_freq_cpu = pxa_freq_settings[idx].khz; + new_freq_mem = pxa_freq_settings[idx].membus; freqs.old = policy->cur; - freqs.new = pxa_freq_settings[idx].khz; + freqs.new = new_freq_cpu; freqs.cpu = policy->cpu; if (freq_debug) - pr_debug(KERN_INFO "Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n", - freqs.new / 1000, (pxa_freq_settings[idx].div2) ? - (pxa_freq_settings[idx].membus / 2000) : - (pxa_freq_settings[idx].membus / 1000)); + pr_debug(KERN_INFO "Changing CPU frequency to %d Mhz, " + "(SDRAM %d Mhz)\n", + freqs.new / 1000, (pxa_freq_settings[idx].div2) ? + (new_freq_mem / 2000) : (new_freq_mem / 1000)); /* * Tell everyone what we're about to do... @@ -177,16 +268,16 @@ static int pxa_set_target(struct cpufreq_policy *policy, cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); /* Calculate the next MDREFR. If we're slowing down the SDRAM clock - * we need to preset the smaller DRI before the change. If we're speeding - * up we need to set the larger DRI value after the change. + * we need to preset the smaller DRI before the change. If we're + * speeding up we need to set the larger DRI value after the change. */ preset_mdrefr = postset_mdrefr = MDREFR; - if ((MDREFR & MDREFR_DRI_MASK) > MDREFR_DRI(pxa_freq_settings[idx].membus)) { - preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK) | - MDREFR_DRI(pxa_freq_settings[idx].membus); + if ((MDREFR & MDREFR_DRI_MASK) > mdrefr_dri(new_freq_mem)) { + preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK); + preset_mdrefr |= mdrefr_dri(new_freq_mem); } - postset_mdrefr = (postset_mdrefr & ~MDREFR_DRI_MASK) | - MDREFR_DRI(pxa_freq_settings[idx].membus); + postset_mdrefr = + (postset_mdrefr & ~MDREFR_DRI_MASK) | mdrefr_dri(new_freq_mem); /* If we're dividing the memory clock by two for the SDRAM clock, this * must be set prior to the change. Clearing the divide must be done @@ -201,26 +292,27 @@ static int pxa_set_target(struct cpufreq_policy *policy, local_irq_save(flags); - /* Set new the CCCR */ + /* Set new the CCCR and prepare CCLKCFG */ CCCR = pxa_freq_settings[idx].cccr; + cclkcfg = pxa_freq_settings[idx].cclkcfg; asm volatile(" \n\ ldr r4, [%1] /* load MDREFR */ \n\ b 2f \n\ - .align 5 \n\ + .align 5 \n\ 1: \n\ - str %4, [%1] /* preset the MDREFR */ \n\ + str %3, [%1] /* preset the MDREFR */ \n\ mcr p14, 0, %2, c6, c0, 0 /* set CCLKCFG[FCS] */ \n\ - str %5, [%1] /* postset the MDREFR */ \n\ + str %4, [%1] /* postset the MDREFR */ \n\ \n\ b 3f \n\ 2: b 1b \n\ 3: nop \n\ " - : "=&r" (unused) - : "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart), - "r" (preset_mdrefr), "r" (postset_mdrefr) - : "r4", "r5"); + : "=&r" (unused) + : "r" (&MDREFR), "r" (cclkcfg), + "r" (preset_mdrefr), "r" (postset_mdrefr) + : "r4", "r5"); local_irq_restore(flags); /* @@ -233,38 +325,57 @@ static int pxa_set_target(struct cpufreq_policy *policy, return 0; } -static unsigned int pxa_cpufreq_get(unsigned int cpu) -{ - return get_clk_frequency_khz(0); -} - -static int pxa_cpufreq_init(struct cpufreq_policy *policy) +static __init int pxa_cpufreq_init(struct cpufreq_policy *policy) { int i; + unsigned int freq; + + /* try to guess pxa27x cpu */ + if (cpu_is_pxa27x()) + pxa27x_guess_max_freq(); /* set default policy and cpuinfo */ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->policy = CPUFREQ_POLICY_PERFORMANCE; - policy->cpuinfo.max_freq = PXA25x_MAX_FREQ; - policy->cpuinfo.min_freq = PXA25x_MIN_FREQ; + if (cpu_is_pxa25x()) + policy->policy = CPUFREQ_POLICY_PERFORMANCE; policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ - policy->cur = get_clk_frequency_khz(0); /* current freq */ + policy->cur = get_clk_frequency_khz(0); /* current freq */ policy->min = policy->max = policy->cur; - /* Generate the run cpufreq_frequency_table struct */ - for (i = 0; i < NUM_RUN_FREQS; i++) { + /* Generate pxa25x the run cpufreq_frequency_table struct */ + for (i = 0; i < NUM_PXA25x_RUN_FREQS; i++) { pxa255_run_freq_table[i].frequency = pxa255_run_freqs[i].khz; pxa255_run_freq_table[i].index = i; } - pxa255_run_freq_table[i].frequency = CPUFREQ_TABLE_END; - /* Generate the turbo cpufreq_frequency_table struct */ - for (i = 0; i < NUM_TURBO_FREQS; i++) { - pxa255_turbo_freq_table[i].frequency = pxa255_turbo_freqs[i].khz; + + /* Generate pxa25x the turbo cpufreq_frequency_table struct */ + for (i = 0; i < NUM_PXA25x_TURBO_FREQS; i++) { + pxa255_turbo_freq_table[i].frequency = + pxa255_turbo_freqs[i].khz; pxa255_turbo_freq_table[i].index = i; } pxa255_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END; + /* Generate the pxa27x cpufreq_frequency_table struct */ + for (i = 0; i < NUM_PXA27x_FREQS; i++) { + freq = pxa27x_freqs[i].khz; + if (freq > pxa27x_maxfreq) + break; + pxa27x_freq_table[i].frequency = freq; + pxa27x_freq_table[i].index = i; + } + pxa27x_freq_table[i].frequency = CPUFREQ_TABLE_END; + + /* + * Set the policy's minimum and maximum frequencies from the tables + * just constructed. This sets cpuinfo.mxx_freq, min and max. + */ + if (cpu_is_pxa25x()) + cpufreq_frequency_table_cpuinfo(policy, pxa255_run_freq_table); + else if (cpu_is_pxa27x()) + cpufreq_frequency_table_cpuinfo(policy, pxa27x_freq_table); + printk(KERN_INFO "PXA CPU frequency change support initialized\n"); return 0; @@ -275,26 +386,25 @@ static struct cpufreq_driver pxa_cpufreq_driver = { .target = pxa_set_target, .init = pxa_cpufreq_init, .get = pxa_cpufreq_get, - .name = "PXA25x", + .name = "PXA2xx", }; static int __init pxa_cpu_init(void) { int ret = -ENODEV; - if (cpu_is_pxa25x()) + if (cpu_is_pxa25x() || cpu_is_pxa27x()) ret = cpufreq_register_driver(&pxa_cpufreq_driver); return ret; } static void __exit pxa_cpu_exit(void) { - if (cpu_is_pxa25x()) - cpufreq_unregister_driver(&pxa_cpufreq_driver); + cpufreq_unregister_driver(&pxa_cpufreq_driver); } -MODULE_AUTHOR ("Intrinsyc Software Inc."); -MODULE_DESCRIPTION ("CPU frequency changing driver for the PXA architecture"); +MODULE_AUTHOR("Intrinsyc Software Inc."); +MODULE_DESCRIPTION("CPU frequency changing driver for the PXA architecture"); MODULE_LICENSE("GPL"); module_init(pxa_cpu_init); module_exit(pxa_cpu_exit); diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 0993f4d..7b9bdd0 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -396,7 +396,7 @@ static struct pxafb_mach_info sharp_lm8v31 = { .cmap_inverse = 0, .cmap_static = 0, .lcd_conn = LCD_COLOR_DSTN_16BPP | LCD_PCLK_EDGE_FALL | - LCD_AC_BIAS_FREQ(255); + LCD_AC_BIAS_FREQ(255), }; #define MMC_POLL_RATE msecs_to_jiffies(1000) diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index ec1bbf3..7d4debb 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -42,20 +42,17 @@ int pxa_pm_enter(suspend_state_t state) if (state != PM_SUSPEND_STANDBY) { pxa_cpu_pm_fns->save(sleep_save); /* before sleeping, calculate and save a checksum */ - for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++) + for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++) sleep_save_checksum += sleep_save[i]; } - /* Clear reset status */ - RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; - /* *** go zzz *** */ pxa_cpu_pm_fns->enter(state); cpu_init(); if (state != PM_SUSPEND_STANDBY) { /* after sleeping, validate the checksum */ - for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++) + for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++) checksum += sleep_save[i]; /* if invalid, display message and wait for a hardware reset */ @@ -101,7 +98,8 @@ static int __init pxa_pm_init(void) return -EINVAL; } - sleep_save = kmalloc(pxa_cpu_pm_fns->save_size, GFP_KERNEL); + sleep_save = kmalloc(pxa_cpu_pm_fns->save_count * sizeof(unsigned long), + GFP_KERNEL); if (!sleep_save) { printk(KERN_ERR "failed to alloc memory for pm save\n"); return -ENOMEM; diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index ca5ac19..0b30f25 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -326,13 +326,11 @@ static struct platform_device *devices[] __initdata = { static void poodle_poweroff(void) { - RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; arm_machine_restart('h'); } static void poodle_restart(char mode) { - RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; arm_machine_restart('h'); } diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index d9b5450..e5b417d 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -150,9 +150,7 @@ static struct clk pxa25x_clks[] = { * More ones like CP and general purpose register values are preserved * with the stack pointer in sleep.S. */ -enum { SLEEP_SAVE_START = 0, - - SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, +enum { SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U, @@ -162,7 +160,7 @@ enum { SLEEP_SAVE_START = 0, SLEEP_SAVE_CKEN, - SLEEP_SAVE_SIZE + SLEEP_SAVE_COUNT }; @@ -200,6 +198,9 @@ static void pxa25x_cpu_pm_restore(unsigned long *sleep_save) static void pxa25x_cpu_pm_enter(suspend_state_t state) { + /* Clear reset status */ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + switch (state) { case PM_SUSPEND_MEM: /* set resume return address */ @@ -210,7 +211,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state) } static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = { - .save_size = SLEEP_SAVE_SIZE, + .save_count = SLEEP_SAVE_COUNT, .valid = suspend_valid_only_mem, .save = pxa25x_cpu_pm_save, .restore = pxa25x_cpu_pm_restore, diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 7a2449d..7e94583 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -181,9 +181,7 @@ static struct clk pxa27x_clks[] = { * More ones like CP and general purpose register values are preserved * with the stack pointer in sleep.S. */ -enum { SLEEP_SAVE_START = 0, - - SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3, +enum { SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3, SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U, @@ -198,7 +196,7 @@ enum { SLEEP_SAVE_START = 0, SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER, SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR, - SLEEP_SAVE_SIZE + SLEEP_SAVE_COUNT }; void pxa27x_cpu_pm_save(unsigned long *sleep_save) @@ -251,6 +249,9 @@ void pxa27x_cpu_pm_enter(suspend_state_t state) /* Clear edge-detect status register. */ PEDR = 0xDF12FE1B; + /* Clear reset status */ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + switch (state) { case PM_SUSPEND_STANDBY: pxa_cpu_standby(); @@ -269,7 +270,7 @@ static int pxa27x_cpu_pm_valid(suspend_state_t state) } static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = { - .save_size = SLEEP_SAVE_SIZE, + .save_count = SLEEP_SAVE_COUNT, .save = pxa27x_cpu_pm_save, .restore = pxa27x_cpu_pm_restore, .valid = pxa27x_cpu_pm_valid, diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index b6a6f5f..644550b 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -256,12 +256,11 @@ static unsigned long wakeup_src; #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] -enum { SLEEP_SAVE_START = 0, - SLEEP_SAVE_CKENA, +enum { SLEEP_SAVE_CKENA, SLEEP_SAVE_CKENB, SLEEP_SAVE_ACCR, - SLEEP_SAVE_SIZE, + SLEEP_SAVE_COUNT, }; static void pxa3xx_cpu_pm_save(unsigned long *sleep_save) @@ -376,7 +375,7 @@ static int pxa3xx_cpu_pm_valid(suspend_state_t state) } static struct pxa_cpu_pm_fns pxa3xx_cpu_pm_fns = { - .save_size = SLEEP_SAVE_SIZE, + .save_count = SLEEP_SAVE_COUNT, .save = pxa3xx_cpu_pm_save, .restore = pxa3xx_cpu_pm_restore, .valid = pxa3xx_cpu_pm_valid, diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 62a02c3..dace382 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -38,6 +38,7 @@ #include <asm/arch/pxa-regs.h> #include <asm/arch/pxa2xx-regs.h> #include <asm/arch/pxa2xx-gpio.h> +#include <asm/arch/pxa27x-udc.h> #include <asm/arch/irda.h> #include <asm/arch/mmc.h> #include <asm/arch/ohci.h> @@ -529,8 +530,6 @@ static struct platform_device *devices[] __initdata = { static void spitz_poweroff(void) { - RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; - pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT); GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET); diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index 7a7f5f9..23f050f 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -119,9 +119,6 @@ static void spitz_presuspend(void) /* nRESET_OUT Disable */ PSLR |= PSLR_SL_ROD; - /* Clear reset status */ - RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; - /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ PCFR = PCFR_GPR_EN | PCFR_OPDE; } diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 6458f6d..c2cbd66 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -467,8 +467,6 @@ static struct platform_device *devices[] __initdata = { static void tosa_poweroff(void) { - RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; - pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_OUT); GPSR(TOSA_GPIO_ON_RESET) = GPIO_bit(TOSA_GPIO_ON_RESET); diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index 246c573..1693d44 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -43,20 +43,18 @@ extern void sa1100_cpu_resume(void); * More ones like CP and general purpose register values are preserved * on the stack and then the stack pointer is stored last in sleep.S. */ -enum { SLEEP_SAVE_SP = 0, - - SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR, +enum { SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR, SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR, SLEEP_SAVE_Ser1SDCR0, - SLEEP_SAVE_SIZE + SLEEP_SAVE_COUNT }; static int sa11x0_pm_enter(suspend_state_t state) { - unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE]; + unsigned long gpio, sleep_save[SLEEP_SAVE_COUNT]; gpio = GPLR; diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index 065087a..d045812 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -332,7 +332,7 @@ ENTRY(arm925_dma_flush_range) #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry #else - mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry #endif add r0, r0, #CACHE_DLINESIZE cmp r0, r1 diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 997db84..4cd3316 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -295,7 +295,7 @@ ENTRY(arm926_dma_flush_range) #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry #else - mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry #endif add r0, r0, #CACHE_DLINESIZE cmp r0, r1 diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S index 44ead90..1a3d63d 100644 --- a/arch/arm/mm/proc-arm940.S +++ b/arch/arm/mm/proc-arm940.S @@ -222,7 +222,7 @@ ENTRY(arm940_dma_flush_range) #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r3, c7, c14, 2 @ clean/flush D entry #else - mcr p15, 0, r3, c7, c10, 2 @ clean D entry + mcr p15, 0, r3, c7, c6, 2 @ invalidate D entry #endif subs r3, r3, #1 << 26 bcs 2b @ entries 63 to 0 diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S index 2218b0c..82d579a 100644 --- a/arch/arm/mm/proc-arm946.S +++ b/arch/arm/mm/proc-arm946.S @@ -265,7 +265,7 @@ ENTRY(arm946_dma_flush_range) #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry #else - mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry #endif add r0, r0, #CACHE_DLINESIZE cmp r0, r1 diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c index d84167f..3ac8d8d 100644 --- a/arch/arm/plat-s3c24xx/clock.c +++ b/arch/arm/plat-s3c24xx/clock.c @@ -411,7 +411,7 @@ static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) clk->parent = parent; - if (clk == &s3c24xx_dclk0) + if (clk == &s3c24xx_clkout0) mask = S3C2410_MISCCR_CLK0_MASK; else { source <<= 4; @@ -437,7 +437,7 @@ struct clk s3c24xx_dclk0 = { struct clk s3c24xx_dclk1 = { .name = "dclk1", .id = -1, - .ctrlbit = S3C2410_DCLKCON_DCLK0EN, + .ctrlbit = S3C2410_DCLKCON_DCLK1EN, .enable = s3c24xx_dclk_enable, .set_parent = s3c24xx_dclk_setparent, .set_rate = s3c24xx_set_dclk_rate, diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 795d0ac..fd57085 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -832,6 +832,7 @@ config BANK_0 config BANK_1 hex "Bank 1" default 0x7BB0 + default 0x5558 if BF54x config BANK_2 hex "Bank 2" @@ -963,21 +964,22 @@ endchoice endmenu -if (BF537 || BF533 || BF54x) - menu "CPU Frequency scaling" source "drivers/cpufreq/Kconfig" -config CPU_FREQ - bool +config CPU_VOLTAGE + bool "CPU Voltage scaling" + depends on EXPERIMENTAL + depends on CPU_FREQ default n help - If you want to enable this option, you should select the - DPMC driver from Character Devices. -endmenu + Say Y here if you want CPU voltage scaling according to the CPU frequency. + This option violates the PLL BYPASS recommendation in the Blackfin Processor + manuals. There is a theoretical risk that during VDDINT transitions + the PLL may unlock. -endif +endmenu source "net/Kconfig" diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c index 721f15f..881afe9 100644 --- a/arch/blackfin/kernel/asm-offsets.c +++ b/arch/blackfin/kernel/asm-offsets.c @@ -56,9 +56,6 @@ int main(void) /* offsets into the thread struct */ DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); - DEFINE(THREAD_SR, offsetof(struct thread_struct, seqstat)); - DEFINE(PT_SR, offsetof(struct thread_struct, seqstat)); - DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); DEFINE(THREAD_PC, offsetof(struct thread_struct, pc)); DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE); diff --git a/arch/blackfin/kernel/fixed_code.S b/arch/blackfin/kernel/fixed_code.S index 5ed47228..4b03ba0 100644 --- a/arch/blackfin/kernel/fixed_code.S +++ b/arch/blackfin/kernel/fixed_code.S @@ -1,6 +1,6 @@ /* * This file contains sequences of code that will be copied to a - * fixed location, defined in <asm/atomic_seq.h>. The interrupt + * fixed location, defined in <asm/fixed_code.h>. The interrupt * handlers ensure that these sequences appear to be atomic when * executed from userspace. * These are aligned to 16 bytes, so that we have some space to replace diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c index 8b9fe29..14a4284 100644 --- a/arch/blackfin/kernel/module.c +++ b/arch/blackfin/kernel/module.c @@ -160,6 +160,13 @@ int module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, char *secstrings, struct module *mod) { + /* + * XXX: sechdrs are vmalloced in kernel/module.c + * and would be vfreed just after module is loaded, + * so we hack to keep the only information we needed + * in mod->arch to correctly free L1 I/D sram later. + * NOTE: this breaks the semantic of mod->arch structure. + */ Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; void *dest = NULL; @@ -167,8 +174,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) || ((strcmp(".text", secstrings + s->sh_name) == 0) && (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) { - mod->arch.text_l1 = s; dest = l1_inst_sram_alloc(s->sh_size); + mod->arch.text_l1 = dest; if (dest == NULL) { printk(KERN_ERR "module %s: L1 instruction memory allocation failed\n", @@ -182,8 +189,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) || ((strcmp(".data", secstrings + s->sh_name) == 0) && (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) { - mod->arch.data_a_l1 = s; dest = l1_data_sram_alloc(s->sh_size); + mod->arch.data_a_l1 = dest; if (dest == NULL) { printk(KERN_ERR "module %s: L1 data memory allocation failed\n", @@ -197,8 +204,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 || ((strcmp(".bss", secstrings + s->sh_name) == 0) && (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) { - mod->arch.bss_a_l1 = s; dest = l1_data_sram_alloc(s->sh_size); + mod->arch.bss_a_l1 = dest; if (dest == NULL) { printk(KERN_ERR "module %s: L1 data memory allocation failed\n", @@ -210,8 +217,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, s->sh_addr = (unsigned long)dest; } if (strcmp(".l1.data.B", secstrings + s->sh_name) == 0) { - mod->arch.data_b_l1 = s; dest = l1_data_B_sram_alloc(s->sh_size); + mod->arch.data_b_l1 = dest; if (dest == NULL) { printk(KERN_ERR "module %s: L1 data memory allocation failed\n", @@ -223,8 +230,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, s->sh_addr = (unsigned long)dest; } if (strcmp(".l1.bss.B", secstrings + s->sh_name) == 0) { - mod->arch.bss_b_l1 = s; dest = l1_data_B_sram_alloc(s->sh_size); + mod->arch.bss_b_l1 = dest; if (dest == NULL) { printk(KERN_ERR "module %s: L1 data memory allocation failed\n", @@ -416,14 +423,14 @@ module_finalize(const Elf_Ehdr * hdr, void module_arch_cleanup(struct module *mod) { - if ((mod->arch.text_l1) && (mod->arch.text_l1->sh_addr)) - l1_inst_sram_free((void *)mod->arch.text_l1->sh_addr); - if ((mod->arch.data_a_l1) && (mod->arch.data_a_l1->sh_addr)) - l1_data_sram_free((void *)mod->arch.data_a_l1->sh_addr); - if ((mod->arch.bss_a_l1) && (mod->arch.bss_a_l1->sh_addr)) - l1_data_sram_free((void *)mod->arch.bss_a_l1->sh_addr); - if ((mod->arch.data_b_l1) && (mod->arch.data_b_l1->sh_addr)) - l1_data_B_sram_free((void *)mod->arch.data_b_l1->sh_addr); - if ((mod->arch.bss_b_l1) && (mod->arch.bss_b_l1->sh_addr)) - l1_data_B_sram_free((void *)mod->arch.bss_b_l1->sh_addr); + if (mod->arch.text_l1) + l1_inst_sram_free((void *)mod->arch.text_l1); + if (mod->arch.data_a_l1) + l1_data_sram_free((void *)mod->arch.data_a_l1); + if (mod->arch.bss_a_l1) + l1_data_sram_free((void *)mod->arch.bss_a_l1); + if (mod->arch.data_b_l1) + l1_data_B_sram_free((void *)mod->arch.data_b_l1); + if (mod->arch.bss_b_l1) + l1_data_B_sram_free((void *)mod->arch.bss_b_l1); } diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index be9fdd0..53c2cd25 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -245,7 +245,7 @@ unsigned long get_wchan(struct task_struct *p) void finish_atomic_sections (struct pt_regs *regs) { - int __user *up0 = (int __user *)®s->p0; + int __user *up0 = (int __user *)regs->p0; if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END) return; diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index b4f062c..f51ab08 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -185,8 +185,8 @@ void ptrace_disable(struct task_struct *child) { unsigned long tmp; /* make sure the single step bit is not set. */ - tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); - put_reg(child, PT_SR, tmp); + tmp = get_reg(child, PT_SYSCFG) & ~TRACE_BITS; + put_reg(child, PT_SYSCFG, tmp); } long arch_ptrace(struct task_struct *child, long request, long addr, long data) diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index cb9d883..dbc3bbf 100644 --- a/arch/blackfin/kernel/signal.c +++ b/arch/blackfin/kernel/signal.c @@ -42,6 +42,9 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) +/* Location of the trace bit in SYSCFG. */ +#define TRACE_BITS 0x0001 + struct fdpic_func_descriptor { unsigned long text; unsigned long GOT; @@ -225,6 +228,16 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, regs->r1 = (unsigned long)(&frame->info); regs->r2 = (unsigned long)(&frame->uc); + /* + * Clear the trace flag when entering the signal handler, but + * notify any tracer that was single-stepping it. The tracer + * may want to single-step inside the handler too. + */ + if (regs->syscfg & TRACE_BITS) { + regs->syscfg &= ~TRACE_BITS; + ptrace_notify(SIGTRAP); + } + return 0; give_sigsegv: diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c index 4482c47..e887efc 100644 --- a/arch/blackfin/kernel/time-ts.c +++ b/arch/blackfin/kernel/time-ts.c @@ -60,7 +60,7 @@ static inline unsigned long long cycles_2_ns(cycle_t cyc) static cycle_t read_cycles(void) { - return get_cycles(); + return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod); } unsigned long long sched_clock(void) @@ -117,7 +117,7 @@ static void bfin_timer_set_mode(enum clock_event_mode mode, break; } case CLOCK_EVT_MODE_ONESHOT: - bfin_write_TSCALE(0); + bfin_write_TSCALE(TIME_SCALE - 1); bfin_write_TCOUNT(0); bfin_write_TCNTL(TMPWR | TMREN); CSYNC(); @@ -183,10 +183,14 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) static int __init bfin_clockevent_init(void) { + unsigned long timer_clk; + + timer_clk = get_cclk() / TIME_SCALE; + setup_irq(IRQ_CORETMR, &bfin_timer_irq); bfin_timer_init(); - clockevent_bfin.mult = div_sc(get_cclk(), NSEC_PER_SEC, clockevent_bfin.shift); + clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift); clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin); clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin); clockevents_register_device(&clockevent_bfin); diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 583d538..8aa49f8 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -32,12 +32,14 @@ #include <linux/platform_device.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> +#include <linux/mtd/physmap.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) #include <linux/usb/isp1362.h> #endif #include <linux/ata_platform.h> +#include <linux/i2c.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/usb/sl811.h> @@ -50,6 +52,7 @@ #include <asm/reboot.h> #include <asm/nand.h> #include <asm/portmux.h> +#include <asm/dpmc.h> #include <linux/spi/ad7877.h> /* @@ -171,6 +174,46 @@ static struct platform_device bf52x_t350mcqb_device = { }; #endif +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) +static struct mtd_partition ezkit_partitions[] = { + { + .name = "Bootloader", + .size = 0x40000, + .offset = 0, + }, { + .name = "Kernel", + .size = 0x1C0000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "RootFS", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + } +}; + +static struct physmap_flash_data ezkit_flash_data = { + .width = 2, + .parts = ezkit_partitions, + .nr_parts = ARRAY_SIZE(ezkit_partitions), +}; + +static struct resource ezkit_flash_resource = { + .start = 0x20000000, + .end = 0x203fffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ezkit_flash_device = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ezkit_flash_data, + }, + .num_resources = 1, + .resource = &ezkit_flash_resource, +}; +#endif + #if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE) static struct mtd_partition partition_info[] = { { @@ -420,11 +463,7 @@ static struct mtd_partition bfin_spi_flash_partitions[] = { .offset = 0, .mask_flags = MTD_CAP_ROM }, { - .name = "kernel", - .size = 0xe0000, - .offset = MTDPART_OFS_APPEND, - }, { - .name = "file system", + .name = "linux kernel", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_APPEND, } @@ -434,7 +473,7 @@ static struct flash_platform_data bfin_spi_flash_data = { .name = "m25p80", .parts = bfin_spi_flash_partitions, .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions), - .type = "m25p64", + .type = "m25p16", }; /* SPI flash chip (m25p64) */ @@ -755,6 +794,24 @@ static struct platform_device i2c_bfin_twi_device = { }; #endif +#ifdef CONFIG_I2C_BOARDINFO +static struct i2c_board_info __initdata bfin_i2c_board_info[] = { +#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) + { + I2C_BOARD_INFO("pcf8574_lcd", 0x22), + .type = "pcf8574_lcd", + }, +#endif +#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE) + { + I2C_BOARD_INFO("pcf8574_keypad", 0x27), + .type = "pcf8574_keypad", + .irq = IRQ_PF8, + }, +#endif +}; +#endif + #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { .name = "bfin-sport-uart", @@ -839,7 +896,32 @@ static struct platform_device bfin_gpios_device = { .resource = &bfin_gpios_resources, }; +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_100, 400000000), + VRPAIR(VLEV_105, 426000000), + VRPAIR(VLEV_110, 500000000), + VRPAIR(VLEV_115, 533000000), + VRPAIR(VLEV_120, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *stamp_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE) &bf5xx_nand_device, #endif @@ -921,12 +1003,22 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_device_gpiokeys, #endif +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) + &ezkit_flash_device, +#endif + &bfin_gpios_device, }; static int __init stamp_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); + +#ifdef CONFIG_I2C_BOARDINFO + i2c_register_board_info(0, bfin_i2c_board_info, + ARRAY_SIZE(bfin_i2c_board_info)); +#endif + platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) spi_register_board_info(bfin_spi_board_info, diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c index a03149c..ed2b0b8 100644 --- a/arch/blackfin/mach-bf533/boards/cm_bf533.c +++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c @@ -33,12 +33,15 @@ #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> +#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) #include <linux/usb/isp1362.h> +#endif #include <linux/ata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -341,7 +344,37 @@ static struct platform_device bfin_pata_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 376000000), + VRPAIR(VLEV_095, 426000000), + VRPAIR(VLEV_100, 426000000), + VRPAIR(VLEV_105, 476000000), + VRPAIR(VLEV_110, 476000000), + VRPAIR(VLEV_115, 476000000), + VRPAIR(VLEV_120, 600000000), + VRPAIR(VLEV_125, 600000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *cm_bf533_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) &bfin_uart_device, #endif diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c index 08a7943..9d28415 100644 --- a/arch/blackfin/mach-bf533/boards/ezkit.c +++ b/arch/blackfin/mach-bf533/boards/ezkit.c @@ -42,6 +42,7 @@ #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -350,7 +351,37 @@ static struct platform_device i2c_gpio_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 376000000), + VRPAIR(VLEV_095, 426000000), + VRPAIR(VLEV_100, 426000000), + VRPAIR(VLEV_105, 476000000), + VRPAIR(VLEV_110, 476000000), + VRPAIR(VLEV_115, 476000000), + VRPAIR(VLEV_120, 600000000), + VRPAIR(VLEV_125, 600000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *ezkit_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) &smc91x_device, #endif diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index 024f418..7fd35fb 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c @@ -45,6 +45,7 @@ #include <asm/bfin5xx_spi.h> #include <asm/reboot.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -516,7 +517,37 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 376000000), + VRPAIR(VLEV_095, 426000000), + VRPAIR(VLEV_100, 426000000), + VRPAIR(VLEV_105, 476000000), + VRPAIR(VLEV_110, 476000000), + VRPAIR(VLEV_115, 476000000), + VRPAIR(VLEV_120, 600000000), + VRPAIR(VLEV_125, 600000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *stamp_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) &rtc_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c index d8a23cd..73f2142 100644 --- a/arch/blackfin/mach-bf537/boards/cm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c @@ -35,12 +35,15 @@ #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> +#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) #include <linux/usb/isp1362.h> +#endif #include <linux/ata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -428,7 +431,37 @@ static struct platform_device bfin_pata_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 376000000), + VRPAIR(VLEV_095, 426000000), + VRPAIR(VLEV_100, 426000000), + VRPAIR(VLEV_105, 476000000), + VRPAIR(VLEV_110, 476000000), + VRPAIR(VLEV_115, 476000000), + VRPAIR(VLEV_120, 500000000), + VRPAIR(VLEV_125, 533000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *cm_bf537_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_FB_HITACHI_TX09) || defined(CONFIG_FB_HITACHI_TX09_MODULE) &hitachi_fb_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index d3727b7..9a756d1 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -47,6 +47,7 @@ #include <asm/bfin5xx_spi.h> #include <asm/reboot.h> #include <asm/portmux.h> +#include <asm/dpmc.h> #include <linux/spi/ad7877.h> /* @@ -817,7 +818,37 @@ static struct platform_device bfin_pata_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 376000000), + VRPAIR(VLEV_095, 426000000), + VRPAIR(VLEV_100, 426000000), + VRPAIR(VLEV_105, 476000000), + VRPAIR(VLEV_110, 476000000), + VRPAIR(VLEV_115, 476000000), + VRPAIR(VLEV_120, 500000000), + VRPAIR(VLEV_125, 533000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *stamp_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE) &bfin_pcmcia_cf_device, #endif diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c index e3e8479..3b74f96 100644 --- a/arch/blackfin/mach-bf548/boards/cm_bf548.c +++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c @@ -36,7 +36,9 @@ #include <linux/spi/flash.h> #include <linux/irq.h> #include <linux/interrupt.h> +#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) #include <linux/usb/musb.h> +#endif #include <asm/bfin5xx_spi.h> #include <asm/cplb.h> #include <asm/dma.h> @@ -44,6 +46,7 @@ #include <asm/nand.h> #include <asm/portmux.h> #include <asm/mach/bf54x_keys.h> +#include <asm/dpmc.h> #include <linux/input.h> #include <linux/spi/ad7877.h> @@ -590,7 +593,38 @@ static struct platform_device bfin_device_gpiokeys = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ +/* + * Internal VLEV BF54XSBBC1533 + ****temporarily using these values until data sheet is updated + */ + VRPAIR(VLEV_085, 150000000), + VRPAIR(VLEV_090, 250000000), + VRPAIR(VLEV_110, 276000000), + VRPAIR(VLEV_115, 301000000), + VRPAIR(VLEV_120, 525000000), + VRPAIR(VLEV_125, 550000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *cm_bf548_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) &rtc_device, #endif diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index b00f68a..d1682bb 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -46,6 +46,7 @@ #include <asm/dma.h> #include <asm/gpio.h> #include <asm/nand.h> +#include <asm/dpmc.h> #include <asm/portmux.h> #include <asm/mach/bf54x_keys.h> #include <linux/input.h> @@ -689,7 +690,38 @@ static struct platform_device bfin_gpios_device = { .resource = &bfin_gpios_resources, }; +static const unsigned int cclk_vlev_datasheet[] = +{ +/* + * Internal VLEV BF54XSBBC1533 + ****temporarily using these values until data sheet is updated + */ + VRPAIR(VLEV_085, 150000000), + VRPAIR(VLEV_090, 250000000), + VRPAIR(VLEV_110, 276000000), + VRPAIR(VLEV_115, 301000000), + VRPAIR(VLEV_120, 525000000), + VRPAIR(VLEV_125, 550000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *ezkit_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) &rtc_device, #endif diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c index 9fd5809..466ef59 100644 --- a/arch/blackfin/mach-bf561/boards/cm_bf561.c +++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c @@ -33,12 +33,15 @@ #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> +#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) #include <linux/usb/isp1362.h> +#endif #include <linux/ata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -339,8 +342,37 @@ static struct platform_device bfin_pata_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 300000000), + VRPAIR(VLEV_095, 313000000), + VRPAIR(VLEV_100, 350000000), + VRPAIR(VLEV_105, 400000000), + VRPAIR(VLEV_110, 444000000), + VRPAIR(VLEV_115, 450000000), + VRPAIR(VLEV_120, 475000000), + VRPAIR(VLEV_125, 500000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *cm_bf561_devices[] __initdata = { + &bfin_dpmc, + #if defined(CONFIG_FB_HITACHI_TX09) || defined(CONFIG_FB_HITACHI_TX09_MODULE) &hitachi_fb_device, #endif diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c index 0d74b7d..61d8f76 100644 --- a/arch/blackfin/mach-bf561/boards/ezkit.c +++ b/arch/blackfin/mach-bf561/boards/ezkit.c @@ -39,6 +39,7 @@ #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/portmux.h> +#include <asm/dpmc.h> /* * Name the Board for the /proc/cpuinfo @@ -443,7 +444,37 @@ static struct platform_device i2c_gpio_device = { }; #endif +static const unsigned int cclk_vlev_datasheet[] = +{ + VRPAIR(VLEV_085, 250000000), + VRPAIR(VLEV_090, 300000000), + VRPAIR(VLEV_095, 313000000), + VRPAIR(VLEV_100, 350000000), + VRPAIR(VLEV_105, 400000000), + VRPAIR(VLEV_110, 444000000), + VRPAIR(VLEV_115, 450000000), + VRPAIR(VLEV_120, 475000000), + VRPAIR(VLEV_125, 500000000), + VRPAIR(VLEV_130, 600000000), +}; + +static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = { + .tuple_tab = cclk_vlev_datasheet, + .tabsize = ARRAY_SIZE(cclk_vlev_datasheet), + .vr_settling_time = 25 /* us */, +}; + +static struct platform_device bfin_dpmc = { + .name = "bfin dpmc", + .dev = { + .platform_data = &bfin_dmpc_vreg_data, + }, +}; + static struct platform_device *ezkit_devices[] __initdata = { + + &bfin_dpmc, + #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) &smc91x_device, #endif diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index 393081e..422bfee 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -6,5 +6,6 @@ obj-y := \ cache.o cacheinit.o entry.o \ interrupt.o lock.o irqpanic.o arch_checks.o ints-priority.o -obj-$(CONFIG_PM) += pm.o dpmc.o -obj-$(CONFIG_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_PM) += pm.o dpmc_modes.o +obj-$(CONFIG_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c index ed81e00..75cdad2 100644 --- a/arch/blackfin/mach-common/cpufreq.c +++ b/arch/blackfin/mach-common/cpufreq.c @@ -62,6 +62,14 @@ static struct bfin_dpm_state { unsigned int tscale; /* change the divider on the core timer interrupt */ } dpm_state_table[3]; +/* + normalized to maximum frequncy offset for CYCLES, + used in time-ts cycles clock source, but could be used + somewhere also. + */ +unsigned long long __bfin_cycles_off; +unsigned int __bfin_cycles_mod; + /**************************************************************************/ static unsigned int bfin_getfreq(unsigned int cpu) @@ -80,6 +88,7 @@ static int bfin_target(struct cpufreq_policy *policy, unsigned int index, plldiv, tscale; unsigned long flags, cclk_hz; struct cpufreq_freqs freqs; + cycles_t cycles; if (cpufreq_frequency_table_target(policy, bfin_freq_table, target_freq, relation, &index)) @@ -101,8 +110,14 @@ static int bfin_target(struct cpufreq_policy *policy, bfin_write_PLL_DIV(plldiv); /* we have to adjust the core timer, because it is using cclk */ bfin_write_TSCALE(tscale); + cycles = get_cycles(); SSYNC(); + cycles += 10; /* ~10 cycles we loose after get_cycles() */ + __bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index); + __bfin_cycles_mod = index; local_irq_restore(flags); + /* TODO: just test case for cycles clock source, remove later */ + pr_debug("cpufreq: done\n"); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return 0; @@ -119,22 +134,13 @@ static int __init __bfin_cpu_init(struct cpufreq_policy *policy) unsigned long cclk, sclk, csel, min_cclk; int index; -#ifdef CONFIG_CYCLES_CLOCKSOURCE -/* - * Clocksource CYCLES is still CONTINUOUS but not longer MONOTONIC in case we enable - * CPU frequency scaling, since CYCLES runs off Core Clock. - */ - printk(KERN_WARNING "CPU frequency scaling not supported: Clocksource not suitable\n" - return -ENODEV; -#endif - if (policy->cpu != 0) return -EINVAL; cclk = get_cclk(); sclk = get_sclk(); -#if ANOMALY_05000273 +#if ANOMALY_05000273 || (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_DCACHE)) min_cclk = sclk * 2; #else min_cclk = sclk; diff --git a/arch/blackfin/mach-common/dpmc.c b/arch/blackfin/mach-common/dpmc.c new file mode 100644 index 0000000..02c7efd --- /dev/null +++ b/arch/blackfin/mach-common/dpmc.c @@ -0,0 +1,137 @@ +/* + * Copyright 2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/cdev.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/cpufreq.h> + +#include <asm/delay.h> +#include <asm/dpmc.h> + +#define DRIVER_NAME "bfin dpmc" + +#define dprintk(msg...) \ + cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, DRIVER_NAME, msg) + +struct bfin_dpmc_platform_data *pdata; + +/** + * bfin_set_vlev - Update VLEV field in VR_CTL Reg. + * Avoid BYPASS sequence + */ +static void bfin_set_vlev(unsigned int vlev) +{ + unsigned pll_lcnt; + + pll_lcnt = bfin_read_PLL_LOCKCNT(); + + bfin_write_PLL_LOCKCNT(1); + bfin_write_VR_CTL((bfin_read_VR_CTL() & ~VLEV) | vlev); + bfin_write_PLL_LOCKCNT(pll_lcnt); +} + +/** + * bfin_get_vlev - Get CPU specific VLEV from platform device data + */ +static unsigned int bfin_get_vlev(unsigned int freq) +{ + int i; + + if (!pdata) + goto err_out; + + freq >>= 16; + + for (i = 0; i < pdata->tabsize; i++) + if (freq <= (pdata->tuple_tab[i] & 0xFFFF)) + return pdata->tuple_tab[i] >> 16; + +err_out: + printk(KERN_WARNING "DPMC: No suitable CCLK VDDINT voltage pair found\n"); + return VLEV_120; +} + +#ifdef CONFIG_CPU_FREQ +static int +vreg_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + + if (val == CPUFREQ_PRECHANGE && freq->old < freq->new) { + bfin_set_vlev(bfin_get_vlev(freq->new)); + udelay(pdata->vr_settling_time); /* Wait until Volatge settled */ + + } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) + bfin_set_vlev(bfin_get_vlev(freq->new)); + + return 0; +} + +static struct notifier_block vreg_cpufreq_notifier_block = { + .notifier_call = vreg_cpufreq_notifier +}; +#endif /* CONFIG_CPU_FREQ */ + +/** + * bfin_dpmc_probe - + * + */ +static int __devinit bfin_dpmc_probe(struct platform_device *pdev) +{ + if (pdev->dev.platform_data) + pdata = pdev->dev.platform_data; + else + return -EINVAL; + + return cpufreq_register_notifier(&vreg_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); +} + +/** + * bfin_dpmc_remove - + */ +static int __devexit bfin_dpmc_remove(struct platform_device *pdev) +{ + pdata = NULL; + return cpufreq_unregister_notifier(&vreg_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); +} + +struct platform_driver bfin_dpmc_device_driver = { + .probe = bfin_dpmc_probe, + .remove = __devexit_p(bfin_dpmc_remove), + .driver = { + .name = DRIVER_NAME, + } +}; + +/** + * bfin_dpmc_init - Init driver + */ +static int __init bfin_dpmc_init(void) +{ + return platform_driver_register(&bfin_dpmc_device_driver); +} +module_init(bfin_dpmc_init); + +/** + * bfin_dpmc_exit - break down driver + */ +static void __exit bfin_dpmc_exit(void) +{ + platform_driver_unregister(&bfin_dpmc_device_driver); +} +module_exit(bfin_dpmc_exit); + +MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_DESCRIPTION("cpu power management driver for Blackfin"); +MODULE_LICENSE("GPL"); diff --git a/arch/blackfin/mach-common/dpmc.S b/arch/blackfin/mach-common/dpmc_modes.S index 9d45aa3..b7981d3 100644 --- a/arch/blackfin/mach-common/dpmc.S +++ b/arch/blackfin/mach-common/dpmc_modes.S @@ -1,30 +1,7 @@ /* - * File: arch/blackfin/mach-common/dpmc.S - * Based on: - * Author: LG Soft India + * Copyright 2004-2008 Analog Devices Inc. * - * Created: ? - * Description: Watchdog Timer APIs - * - * Modified: - * Copyright 2004-2006 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.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. - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Licensed under the GPL-2 or later. */ #include <linux/linkage.h> diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index f2fb87e..038f70e 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -151,26 +151,62 @@ ENTRY(_ex_soft_bp) ENDPROC(_ex_soft_bp) ENTRY(_ex_single_step) + /* If we just returned from an interrupt, the single step event is + for the RTI instruction. */ r7 = retx; r6 = reti; cc = r7 == r6; - if cc jump _bfin_return_from_exception - r7 = syscfg; - bitclr (r7, 0); - syscfg = R7; + if cc jump _bfin_return_from_exception; + /* If we were in user mode, do the single step normally. */ p5.l = lo(IPEND); p5.h = hi(IPEND); r6 = [p5]; - cc = bittst(r6, 5); - if !cc jump _ex_trap_c; - p4.l = lo(EVT5); - p4.h = hi(EVT5); - r6.h = _exception_to_level5; - r6.l = _exception_to_level5; - r7 = [p4]; - cc = r6 == r7; - if !cc jump _ex_trap_c; + r7 = 0xffe0 (z); + r7 = r7 & r6; + cc = r7 == 0; + if !cc jump 1f; + + /* Single stepping only a single instruction, so clear the trace + * bit here. */ + r7 = syscfg; + bitclr (r7, 0); + syscfg = R7; + jump _ex_trap_c; + +1: + /* + * We were in an interrupt handler. By convention, all of them save + * SYSCFG with their first instruction, so by checking whether our + * RETX points at the entry point, we can determine whether to allow + * a single step, or whether to clear SYSCFG. + * + * First, find out the interrupt level and the event vector for it. + */ + p5.l = lo(EVT0); + p5.h = hi(EVT0); + p5 += -4; +2: + r7 = rot r7 by -1; + p5 += 4; + if !cc jump 2b; + + /* What we actually do is test for the _second_ instruction in the + * IRQ handler. That way, if there are insns following the restore + * of SYSCFG after leaving the handler, we will not turn off SYSCFG + * for them. */ + + r7 = [p5]; + r7 += 2; + r6 = RETX; + cc = R7 == R6; + if !cc jump _bfin_return_from_exception; + + r7 = syscfg; + bitclr (r7, 0); + syscfg = R7; + + /* Fall through to _bfin_return_from_exception. */ ENDPROC(_ex_single_step) ENTRY(_bfin_return_from_exception) @@ -234,20 +270,26 @@ ENTRY(_ex_trap_c) p5.l = _saved_icplb_fault_addr; [p5] = r7; - p4.l = __retx; - p4.h = __retx; + p4.l = _excpt_saved_stuff; + p4.h = _excpt_saved_stuff; + r6 = retx; [p4] = r6; - p4.l = lo(SAFE_USER_INSTRUCTION); - p4.h = hi(SAFE_USER_INSTRUCTION); - retx = p4; + + r6 = SYSCFG; + [p4 + 4] = r6; + BITCLR(r6, 0); + SYSCFG = r6; /* Disable all interrupts, but make sure level 5 is enabled so * we can switch to that level. Save the old mask. */ cli r6; - p4.l = _excpt_saved_imask; - p4.h = _excpt_saved_imask; - [p4] = r6; + [p4 + 8] = r6; + + p4.l = lo(SAFE_USER_INSTRUCTION); + p4.h = hi(SAFE_USER_INSTRUCTION); + retx = p4; + r6 = 0x3f; sti r6; @@ -295,6 +337,11 @@ ENTRY(_double_fault) */ SAVE_ALL_SYS + /* The dumping functions expect the return address in the RETI + * slot. */ + r6 = retx; + [sp + PT_PC] = r6; + r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ SP += -12; call _double_fault_c; @@ -307,16 +354,17 @@ ENDPROC(_double_fault) ENTRY(_exception_to_level5) SAVE_ALL_SYS - p4.l = __retx; - p4.h = __retx; + p4.l = _excpt_saved_stuff; + p4.h = _excpt_saved_stuff; r6 = [p4]; [sp + PT_PC] = r6; + r6 = [p4 + 4]; + [sp + PT_SYSCFG] = r6; + /* Restore interrupt mask. We haven't pushed RETI, so this * doesn't enable interrupts until we return from this handler. */ - p4.l = _excpt_saved_imask; - p4.h = _excpt_saved_imask; - r6 = [p4]; + r6 = [p4 + 8]; sti r6; /* Restore the hardware error vector. */ @@ -1344,7 +1392,14 @@ ENTRY(_sys_call_table) .rept NR_syscalls-(.-_sys_call_table)/4 .long _sys_ni_syscall .endr -_excpt_saved_imask: + + /* + * Used to save the real RETX, IMASK and SYSCFG when temporarily + * storing safe values across the transition from exception to IRQ5. + */ +_excpt_saved_stuff: + .long 0; + .long 0; .long 0; _exception_stack: @@ -1358,7 +1413,3 @@ _exception_stack_top: _last_cplb_fault_retx: .long 0; #endif - /* Used to save the real RETX when temporarily storing a safe - * return address. */ -__retx: - .long 0; diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c index 8b99841..a79fbd8 100644 --- a/arch/cris/kernel/sys_cris.c +++ b/arch/cris/kernel/sys_cris.c @@ -27,25 +27,6 @@ #include <asm/uaccess.h> #include <asm/segment.h> -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage int sys_pipe(unsigned long __user * fildes) -{ - int fd[2]; - int error; - - lock_kernel(); - error = do_pipe(fd); - unlock_kernel(); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - /* common code for old and new mmaps */ static inline long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index 6d7a80f..305ac85 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c @@ -76,26 +76,6 @@ asmlinkage int sys_tas(int __user *addr) return oldval; } -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage int -sys_pipe(unsigned long r0, unsigned long r1, unsigned long r2, - unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, struct pt_regs regs) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user((void __user *)r0, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 6a6409a..e856218 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -186,17 +186,6 @@ config PREEMPT Say Y here if you are building a kernel for a desktop, embedded or real-time system. Say N if you are unsure. -config PREEMPT_BKL - bool "Preempt The Big Kernel Lock" - depends on PREEMPT - default y - help - This option reduces the latency of the kernel by making the - big kernel lock preemptible. - - Say Y here if you are building a kernel for a desktop system. - Say N if you are unsure. - config MN10300_CURRENT_IN_E2 bool "Hold current task address in E2 register" default y diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts index a1ae4d6..72d6756 100644 --- a/arch/powerpc/boot/dts/sequoia.dts +++ b/arch/powerpc/boot/dts/sequoia.dts @@ -342,9 +342,14 @@ /* Outbound ranges, one memory and one IO, * later cannot be changed. Chip supports a second * IO range but we don't use it for now + * From the 440EPx user manual: + * PCI 1 Memory 1 8000 0000 1 BFFF FFFF 1GB + * I/O 1 E800 0000 1 E800 FFFF 64KB + * I/O 1 E880 0000 1 EBFF FFFF 56MB */ - ranges = <02000000 0 80000000 1 80000000 0 10000000 - 01000000 0 00000000 1 e8000000 0 00100000>; + ranges = <02000000 0 80000000 1 80000000 0 40000000 + 01000000 0 00000000 1 e8000000 0 00010000 + 01000000 0 00000000 1 e8800000 0 03800000>; /* Inbound 2GB range starting at 0 */ dma-ranges = <42000000 0 0 0 0 0 80000000>; diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 9f93777..d8f0329 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -16,7 +16,6 @@ #include <asm/mmu.h> #include <asm/pgtable.h> #include <asm/io.h> -#include <asm/prom.h> #include <asm/processor.h> #include <asm/udbg.h> diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 36080d4..81738a4 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1208,6 +1208,18 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_4xx, .platform = "ppc405", }, + { /* default match */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic 40x PPC)", + .cpu_features = CPU_FTRS_40X, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + .machine_check = machine_check_4xx, + .platform = "ppc405", + } #endif /* CONFIG_40x */ #ifdef CONFIG_44x @@ -1421,8 +1433,18 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_440A, .platform = "ppc440", }, + { /* default match */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic 44x PPC)", + .cpu_features = CPU_FTRS_44X, + .cpu_user_features = COMMON_USER_BOOKE, + .icache_bsize = 32, + .dcache_bsize = 32, + .machine_check = machine_check_4xx, + .platform = "ppc440", + } #endif /* CONFIG_44x */ -#ifdef CONFIG_FSL_BOOKE #ifdef CONFIG_E200 { /* e200z5 */ .pvr_mask = 0xfff00000, @@ -1451,7 +1473,19 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_e200, .platform = "ppc5554", }, -#elif defined(CONFIG_E500) + { /* default match */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic E200 PPC)", + .cpu_features = CPU_FTRS_E200, + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_HAS_EFP_SINGLE | + PPC_FEATURE_UNIFIED_CACHE, + .dcache_bsize = 32, + .machine_check = machine_check_e200, + .platform = "ppc5554", +#endif /* CONFIG_E200 */ +#ifdef CONFIG_E500 { /* e500 */ .pvr_mask = 0xffff0000, .pvr_value = 0x80200000, @@ -1487,20 +1521,19 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_e500, .platform = "ppc8548", }, -#endif -#endif -#if !CLASSIC_PPC { /* default match */ .pvr_mask = 0x00000000, .pvr_value = 0x00000000, - .cpu_name = "(generic PPC)", - .cpu_features = CPU_FTRS_GENERIC_32, - .cpu_user_features = PPC_FEATURE_32, + .cpu_name = "(generic E500 PPC)", + .cpu_features = CPU_FTRS_E500, + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_HAS_SPE_COMP | + PPC_FEATURE_HAS_EFP_SINGLE_COMP, .icache_bsize = 32, .dcache_bsize = 32, + .machine_check = machine_check_e500, .platform = "powerpc", - } -#endif /* !CLASSIC_PPC */ +#endif /* CONFIG_E500 */ #endif /* CONFIG_PPC32 */ }; diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index b84ec6a..c2b9dc4 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -653,7 +653,14 @@ finish_tlb_load: rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */ rlwimi r12, r10, 0, 26, 31 /* Insert static perms */ - rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */ + + /* + * Clear U0-U3 and WL1 IL1I IL1D IL2I IL2D bits which are added + * on newer 440 cores like the 440x6 used on AMCC 460EX/460GT (see + * include/asm-powerpc/pgtable-ppc32.h for details). + */ + rlwinm r12, r12, 0, 20, 10 + tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */ /* Done...restore registers and get out of here. diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 024805e..25e84c0 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1517,10 +1517,6 @@ _INIT_STATIC(start_here_multiplatform) addi r2,r2,0x4000 add r2,r2,r26 - /* Set initial ptr to current */ - LOAD_REG_IMMEDIATE(r4, init_task) - std r4,PACACURRENT(r13) - /* Do very early kernel initializations, including initial hash table, * stab and slb setup before we turn on relocation. */ diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c index 289af34..4d5731b 100644 --- a/arch/powerpc/kernel/isa-bridge.c +++ b/arch/powerpc/kernel/isa-bridge.c @@ -108,9 +108,6 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, if (size > 0x10000) size = 0x10000; - printk(KERN_ERR "no ISA IO ranges or unexpected isa range, " - "mapping 64k\n"); - __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, size, _PAGE_NO_CACHE|_PAGE_GUARDED); return; diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 25e3fd8..098fd96 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -170,6 +170,8 @@ void __init setup_paca(int cpu) void __init early_setup(unsigned long dt_ptr) { + /* -------- printk is _NOT_ safe to use here ! ------- */ + /* Fill in any unititialised pacas */ initialise_pacas(); @@ -179,12 +181,14 @@ void __init early_setup(unsigned long dt_ptr) /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ setup_paca(0); - /* Enable early debugging if any specified (see udbg.h) */ - udbg_early_init(); - /* Initialize lockdep early or else spinlocks will blow */ lockdep_init(); + /* -------- printk is now safe to use ------- */ + + /* Enable early debugging if any specified (see udbg.h) */ + udbg_early_init(); + DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr); /* diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 04f74f9..5bf7df1 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -35,6 +35,7 @@ #include <linux/percpu.h> #include <linux/types.h> #include <linux/ioport.h> +#include <linux/kernel_stat.h> #include <asm/io.h> #include <asm/pgtable.h> @@ -231,6 +232,54 @@ static int iic_host_match(struct irq_host *h, struct device_node *node) "IBM,CBEA-Internal-Interrupt-Controller"); } +extern int noirqdebug; + +static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) +{ + const unsigned int cpu = smp_processor_id(); + + spin_lock(&desc->lock); + + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + + /* + * If we're currently running this IRQ, or its disabled, + * we shouldn't process the IRQ. Mark it pending, handle + * the necessary masking and go out + */ + if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || + !desc->action)) { + desc->status |= IRQ_PENDING; + goto out_eoi; + } + + kstat_cpu(cpu).irqs[irq]++; + + /* Mark the IRQ currently in progress.*/ + desc->status |= IRQ_INPROGRESS; + + do { + struct irqaction *action = desc->action; + irqreturn_t action_ret; + + if (unlikely(!action)) + goto out_eoi; + + desc->status &= ~IRQ_PENDING; + spin_unlock(&desc->lock); + action_ret = handle_IRQ_event(irq, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret); + spin_lock(&desc->lock); + + } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); + + desc->status &= ~IRQ_INPROGRESS; +out_eoi: + desc->chip->eoi(irq); + spin_unlock(&desc->lock); +} + static int iic_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { @@ -240,10 +289,10 @@ static int iic_host_map(struct irq_host *h, unsigned int virq, break; case IIC_IRQ_TYPE_IOEXC: set_irq_chip_and_handler(virq, &iic_ioexc_chip, - handle_fasteoi_irq); + handle_iic_irq); break; default: - set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq); + set_irq_chip_and_handler(virq, &iic_chip, handle_iic_irq); } return 0; } diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 6bab44b..70c6601 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -141,6 +141,10 @@ static void spu_restart_dma(struct spu *spu) if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags)) out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); + else { + set_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags); + mb(); + } } static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb) @@ -226,11 +230,13 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) return 0; } - spu->class_0_pending = 0; - spu->dar = ea; - spu->dsisr = dsisr; + spu->class_1_dar = ea; + spu->class_1_dsisr = dsisr; + + spu->stop_callback(spu, 1); - spu->stop_callback(spu); + spu->class_1_dar = 0; + spu->class_1_dsisr = 0; return 0; } @@ -318,11 +324,15 @@ spu_irq_class_0(int irq, void *data) stat = spu_int_stat_get(spu, 0) & mask; spu->class_0_pending |= stat; - spu->dsisr = spu_mfc_dsisr_get(spu); - spu->dar = spu_mfc_dar_get(spu); + spu->class_0_dsisr = spu_mfc_dsisr_get(spu); + spu->class_0_dar = spu_mfc_dar_get(spu); spin_unlock(&spu->register_lock); - spu->stop_callback(spu); + spu->stop_callback(spu, 0); + + spu->class_0_pending = 0; + spu->class_0_dsisr = 0; + spu->class_0_dar = 0; spu_int_stat_clear(spu, 0, stat); @@ -363,6 +373,9 @@ spu_irq_class_1(int irq, void *data) if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR) ; + spu->class_1_dsisr = 0; + spu->class_1_dar = 0; + return stat ? IRQ_HANDLED : IRQ_NONE; } @@ -396,10 +409,10 @@ spu_irq_class_2(int irq, void *data) spu->ibox_callback(spu); if (stat & CLASS2_SPU_STOP_INTR) - spu->stop_callback(spu); + spu->stop_callback(spu, 2); if (stat & CLASS2_SPU_HALT_INTR) - spu->stop_callback(spu); + spu->stop_callback(spu, 2); if (stat & CLASS2_SPU_DMA_TAG_GROUP_COMPLETE_INTR) spu->mfc_callback(spu); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index 67fa724..906a0a2 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -28,6 +28,7 @@ #include <linux/io.h> #include <linux/mutex.h> #include <linux/device.h> +#include <linux/sched.h> #include <asm/spu.h> #include <asm/spu_priv1.h> @@ -75,8 +76,19 @@ static u64 int_stat_get(struct spu *spu, int class) static void cpu_affinity_set(struct spu *spu, int cpu) { - u64 target = iic_get_target_id(cpu); - u64 route = target << 48 | target << 32 | target << 16; + u64 target; + u64 route; + + if (nr_cpus_node(spu->node)) { + cpumask_t spumask = node_to_cpumask(spu->node); + cpumask_t cpumask = node_to_cpumask(cpu_to_node(cpu)); + + if (!cpus_intersects(spumask, cpumask)) + return; + } + + target = iic_get_target_id(cpu); + route = target << 48 | target << 32 | target << 16; out_be64(&spu->priv1->int_route_RW, route); } diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c index e46d300..f093a58 100644 --- a/arch/powerpc/platforms/cell/spufs/fault.c +++ b/arch/powerpc/platforms/cell/spufs/fault.c @@ -83,13 +83,18 @@ int spufs_handle_class0(struct spu_context *ctx) return 0; if (stat & CLASS0_DMA_ALIGNMENT_INTR) - spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_DMA_ALIGNMENT); + spufs_handle_event(ctx, ctx->csa.class_0_dar, + SPE_EVENT_DMA_ALIGNMENT); if (stat & CLASS0_INVALID_DMA_COMMAND_INTR) - spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_INVALID_DMA); + spufs_handle_event(ctx, ctx->csa.class_0_dar, + SPE_EVENT_INVALID_DMA); if (stat & CLASS0_SPU_ERROR_INTR) - spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_SPE_ERROR); + spufs_handle_event(ctx, ctx->csa.class_0_dar, + SPE_EVENT_SPE_ERROR); + + ctx->csa.class_0_pending = 0; return -EIO; } @@ -119,8 +124,8 @@ int spufs_handle_class1(struct spu_context *ctx) * in time, we can still expect to get the same fault * the immediately after the context restore. */ - ea = ctx->csa.dar; - dsisr = ctx->csa.dsisr; + ea = ctx->csa.class_1_dar; + dsisr = ctx->csa.class_1_dsisr; if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) return 0; @@ -158,7 +163,7 @@ int spufs_handle_class1(struct spu_context *ctx) * time slicing will not preempt the context while the page fault * handler is running. Context switch code removes mappings. */ - ctx->csa.dar = ctx->csa.dsisr = 0; + ctx->csa.class_1_dar = ctx->csa.class_1_dsisr = 0; /* * If we handled the fault successfully and are in runnable diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 0c32a05..f407b24 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -23,6 +23,7 @@ #include <linux/file.h> #include <linux/fs.h> +#include <linux/fsnotify.h> #include <linux/backing-dev.h> #include <linux/init.h> #include <linux/ioctl.h> @@ -223,7 +224,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file) parent = dir->d_parent->d_inode; ctx = SPUFS_I(dir->d_inode)->i_ctx; - mutex_lock(&parent->i_mutex); + mutex_lock_nested(&parent->i_mutex, I_MUTEX_PARENT); ret = spufs_rmdir(parent, dir); mutex_unlock(&parent->i_mutex); WARN_ON(ret); @@ -618,12 +619,15 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, mode &= ~current->fs->umask; if (flags & SPU_CREATE_GANG) - return spufs_create_gang(nd->path.dentry->d_inode, + ret = spufs_create_gang(nd->path.dentry->d_inode, dentry, nd->path.mnt, mode); else - return spufs_create_context(nd->path.dentry->d_inode, + ret = spufs_create_context(nd->path.dentry->d_inode, dentry, nd->path.mnt, flags, mode, filp); + if (ret >= 0) + fsnotify_mkdir(nd->path.dentry->d_inode, dentry); + return ret; out_dput: dput(dentry); diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index a9c35b7..b7493b8 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -11,7 +11,7 @@ #include "spufs.h" /* interrupt-level stop callback function. */ -void spufs_stop_callback(struct spu *spu) +void spufs_stop_callback(struct spu *spu, int irq) { struct spu_context *ctx = spu->ctx; @@ -24,9 +24,19 @@ void spufs_stop_callback(struct spu *spu) */ if (ctx) { /* Copy exception arguments into module specific structure */ - ctx->csa.class_0_pending = spu->class_0_pending; - ctx->csa.dsisr = spu->dsisr; - ctx->csa.dar = spu->dar; + switch(irq) { + case 0 : + ctx->csa.class_0_pending = spu->class_0_pending; + ctx->csa.class_0_dsisr = spu->class_0_dsisr; + ctx->csa.class_0_dar = spu->class_0_dar; + break; + case 1 : + ctx->csa.class_1_dsisr = spu->class_1_dsisr; + ctx->csa.class_1_dar = spu->class_1_dar; + break; + case 2 : + break; + } /* ensure that the exception status has hit memory before a * thread waiting on the context's stop queue is woken */ @@ -34,11 +44,6 @@ void spufs_stop_callback(struct spu *spu) wake_up_all(&ctx->stop_wq); } - - /* Clear callback arguments from spu structure */ - spu->class_0_pending = 0; - spu->dsisr = 0; - spu->dar = 0; } int spu_stopped(struct spu_context *ctx, u32 *stat) @@ -56,7 +61,11 @@ int spu_stopped(struct spu_context *ctx, u32 *stat) if (!(*stat & SPU_STATUS_RUNNING) && (*stat & stopped)) return 1; - dsisr = ctx->csa.dsisr; + dsisr = ctx->csa.class_0_dsisr; + if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) + return 1; + + dsisr = ctx->csa.class_1_dsisr; if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) return 1; @@ -294,7 +303,7 @@ static int spu_process_callback(struct spu_context *ctx) u32 ls_pointer, npc; void __iomem *ls; long spu_ret; - int ret, ret2; + int ret; /* get syscall block from local store */ npc = ctx->ops->npc_read(ctx) & ~3; @@ -316,11 +325,9 @@ static int spu_process_callback(struct spu_context *ctx) if (spu_ret <= -ERESTARTSYS) { ret = spu_handle_restartsys(ctx, &spu_ret, &npc); } - ret2 = spu_acquire(ctx); + mutex_lock(&ctx->state_mutex); if (ret == -ERESTARTSYS) return ret; - if (ret2) - return -EINTR; } /* need to re-get the ls, as it may have changed when we released the @@ -343,13 +350,14 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) if (mutex_lock_interruptible(&ctx->run_mutex)) return -ERESTARTSYS; - spu_enable_spu(ctx); ctx->event_return = 0; ret = spu_acquire(ctx); if (ret) goto out_unlock; + spu_enable_spu(ctx); + spu_update_sched_info(ctx); ret = spu_run_init(ctx, npc); diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 7298e7d..2e411f2 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -140,6 +140,9 @@ void __spu_update_sched_info(struct spu_context *ctx) * if it is timesliced or preempted. */ ctx->cpus_allowed = current->cpus_allowed; + + /* Save the current cpu id for spu interrupt routing. */ + ctx->last_ran = raw_smp_processor_id(); } void spu_update_sched_info(struct spu_context *ctx) @@ -243,7 +246,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) spu_switch_log_notify(spu, ctx, SWITCH_LOG_START, 0); spu_restore(&ctx->csa, spu); spu->timestamp = jiffies; - spu_cpu_affinity_set(spu, raw_smp_processor_id()); spu_switch_notify(spu, ctx); ctx->state = SPU_STATE_RUNNABLE; @@ -657,7 +659,8 @@ static struct spu *find_victim(struct spu_context *ctx) victim->stats.invol_ctx_switch++; spu->stats.invol_ctx_switch++; - spu_add_to_rq(victim); + if (test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags)) + spu_add_to_rq(victim); mutex_unlock(&victim->state_mutex); diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 7312745..454c277 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -121,6 +121,7 @@ struct spu_context { cpumask_t cpus_allowed; int policy; int prio; + int last_ran; /* statistics */ struct { @@ -331,7 +332,7 @@ size_t spu_ibox_read(struct spu_context *ctx, u32 *data); /* irq callback funcs. */ void spufs_ibox_callback(struct spu *spu); void spufs_wbox_callback(struct spu *spu); -void spufs_stop_callback(struct spu *spu); +void spufs_stop_callback(struct spu *spu, int irq); void spufs_mfc_callback(struct spu *spu); void spufs_dma_callback(struct spu *spu, int type); diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index d2a1249..3df9a36 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -132,6 +132,14 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu) spu_int_mask_set(spu, 2, 0ul); eieio(); spin_unlock_irq(&spu->register_lock); + + /* + * This flag needs to be set before calling synchronize_irq so + * that the update will be visible to the relevant handlers + * via a simple load. + */ + set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); + clear_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags); synchronize_irq(spu->irqs[0]); synchronize_irq(spu->irqs[1]); synchronize_irq(spu->irqs[2]); @@ -166,9 +174,8 @@ static inline void set_switch_pending(struct spu_state *csa, struct spu *spu) /* Save, Step 7: * Restore, Step 5: * Set a software context switch pending flag. + * Done above in Step 3 - disable_interrupts(). */ - set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); - mb(); } static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) @@ -186,20 +193,21 @@ static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) MFC_CNTL_SUSPEND_COMPLETE); /* fall through */ case MFC_CNTL_SUSPEND_COMPLETE: - if (csa) { + if (csa) csa->priv2.mfc_control_RW = - MFC_CNTL_SUSPEND_MASK | + in_be64(&priv2->mfc_control_RW) | MFC_CNTL_SUSPEND_DMA_QUEUE; - } break; case MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION: out_be64(&priv2->mfc_control_RW, MFC_CNTL_SUSPEND_DMA_QUEUE); POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) & MFC_CNTL_SUSPEND_DMA_STATUS_MASK) == MFC_CNTL_SUSPEND_COMPLETE); - if (csa) { - csa->priv2.mfc_control_RW = 0; - } + if (csa) + csa->priv2.mfc_control_RW = + in_be64(&priv2->mfc_control_RW) & + ~MFC_CNTL_SUSPEND_DMA_QUEUE & + ~MFC_CNTL_SUSPEND_MASK; break; } } @@ -249,16 +257,21 @@ static inline void save_spu_status(struct spu_state *csa, struct spu *spu) } } -static inline void save_mfc_decr(struct spu_state *csa, struct spu *spu) +static inline void save_mfc_stopped_status(struct spu_state *csa, + struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; + const u64 mask = MFC_CNTL_DECREMENTER_RUNNING | + MFC_CNTL_DMA_QUEUES_EMPTY; /* Save, Step 12: * Read MFC_CNTL[Ds]. Update saved copy of * CSA.MFC_CNTL[Ds]. + * + * update: do the same with MFC_CNTL[Q]. */ - csa->priv2.mfc_control_RW |= - in_be64(&priv2->mfc_control_RW) & MFC_CNTL_DECREMENTER_RUNNING; + csa->priv2.mfc_control_RW &= ~mask; + csa->priv2.mfc_control_RW |= in_be64(&priv2->mfc_control_RW) & mask; } static inline void halt_mfc_decr(struct spu_state *csa, struct spu *spu) @@ -462,7 +475,9 @@ static inline void purge_mfc_queue(struct spu_state *csa, struct spu *spu) * Restore, Step 14. * Write MFC_CNTL[Pc]=1 (purge queue). */ - out_be64(&priv2->mfc_control_RW, MFC_CNTL_PURGE_DMA_REQUEST); + out_be64(&priv2->mfc_control_RW, + MFC_CNTL_PURGE_DMA_REQUEST | + MFC_CNTL_SUSPEND_MASK); eieio(); } @@ -725,10 +740,14 @@ static inline void set_switch_active(struct spu_state *csa, struct spu *spu) /* Save, Step 48: * Restore, Step 23. * Change the software context switch pending flag - * to context switch active. + * to context switch active. This implementation does + * not uses a switch active flag. * - * This implementation does not uses a switch active flag. + * Now that we have saved the mfc in the csa, we can add in the + * restart command if an exception occurred. */ + if (test_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags)) + csa->priv2.mfc_control_RW |= MFC_CNTL_RESTART_DMA_COMMAND; clear_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); mb(); } @@ -1690,6 +1709,13 @@ static inline void restore_mfc_sr1(struct spu_state *csa, struct spu *spu) eieio(); } +static inline void set_int_route(struct spu_state *csa, struct spu *spu) +{ + struct spu_context *ctx = spu->ctx; + + spu_cpu_affinity_set(spu, ctx->last_ran); +} + static inline void restore_other_spu_access(struct spu_state *csa, struct spu *spu) { @@ -1721,15 +1747,15 @@ static inline void restore_mfc_cntl(struct spu_state *csa, struct spu *spu) */ out_be64(&priv2->mfc_control_RW, csa->priv2.mfc_control_RW); eieio(); + /* - * FIXME: this is to restart a DMA that we were processing - * before the save. better remember the fault information - * in the csa instead. + * The queue is put back into the same state that was evident prior to + * the context switch. The suspend flag is added to the saved state in + * the csa, if the operational state was suspending or suspended. In + * this case, the code that suspended the mfc is responsible for + * continuing it. Note that SPE faults do not change the operational + * state of the spu. */ - if ((csa->priv2.mfc_control_RW & MFC_CNTL_SUSPEND_DMA_QUEUE_MASK)) { - out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); - eieio(); - } } static inline void enable_user_access(struct spu_state *csa, struct spu *spu) @@ -1788,7 +1814,7 @@ static int quiece_spu(struct spu_state *prev, struct spu *spu) save_spu_runcntl(prev, spu); /* Step 9. */ save_mfc_sr1(prev, spu); /* Step 10. */ save_spu_status(prev, spu); /* Step 11. */ - save_mfc_decr(prev, spu); /* Step 12. */ + save_mfc_stopped_status(prev, spu); /* Step 12. */ halt_mfc_decr(prev, spu); /* Step 13. */ save_timebase(prev, spu); /* Step 14. */ remove_other_spu_access(prev, spu); /* Step 15. */ @@ -2000,6 +2026,7 @@ static void restore_csa(struct spu_state *next, struct spu *spu) check_ppuint_mb_stat(next, spu); /* Step 67. */ spu_invalidate_slbs(spu); /* Modified Step 68. */ restore_mfc_sr1(next, spu); /* Step 69. */ + set_int_route(next, spu); /* NEW */ restore_other_spu_access(next, spu); /* Step 70. */ restore_spu_runcntl(next, spu); /* Step 71. */ restore_mfc_cntl(next, spu); /* Step 72. */ diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c index 5bcc58d..130ff72 100644 --- a/arch/powerpc/platforms/chrp/pegasos_eth.c +++ b/arch/powerpc/platforms/chrp/pegasos_eth.c @@ -58,7 +58,9 @@ static struct resource mv643xx_eth0_resources[] = { static struct mv643xx_eth_platform_data eth0_pd = { + .shared = &mv643xx_eth_shared_device, .port_number = 0, + .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0, .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE, .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16, @@ -88,7 +90,9 @@ static struct resource mv643xx_eth1_resources[] = { }; static struct mv643xx_eth_platform_data eth1_pd = { + .shared = &mv643xx_eth_shared_device, .port_number = 1, + .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1, .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE, .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16, diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 41af122..a132e0d 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c @@ -239,6 +239,8 @@ static int __init mv64x60_eth_device_setup(struct device_node *np, int id, memset(&pdata, 0, sizeof(pdata)); + pdata.shared = shared_pdev; + prop = of_get_property(np, "reg", NULL); if (!prop) return -ENODEV; diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 1814adb..b4a54c5 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -1387,28 +1387,59 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, resource_size_t size = res->end - res->start + 1; u64 sa; - /* Calculate window size */ - sa = (0xffffffffffffffffull << ilog2(size));; - if (res->flags & IORESOURCE_PREFETCH) - sa |= 0x8; + if (port->endpoint) { + resource_size_t ep_addr = 0; + resource_size_t ep_size = 32 << 20; + + /* Currently we map a fixed 64MByte window to PLB address + * 0 (SDRAM). This should probably be configurable via a dts + * property. + */ + + /* Calculate window size */ + sa = (0xffffffffffffffffull << ilog2(ep_size));; + + /* Setup BAR0 */ + out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa) | + PCI_BASE_ADDRESS_MEM_TYPE_64); - out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); - out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); + /* Disable BAR1 & BAR2 */ + out_le32(mbase + PECFG_BAR1MPA, 0); + out_le32(mbase + PECFG_BAR2HMPA, 0); + out_le32(mbase + PECFG_BAR2LMPA, 0); - /* The setup of the split looks weird to me ... let's see if it works */ - out_le32(mbase + PECFG_PIM0LAL, 0x00000000); - out_le32(mbase + PECFG_PIM0LAH, 0x00000000); - out_le32(mbase + PECFG_PIM1LAL, 0x00000000); - out_le32(mbase + PECFG_PIM1LAH, 0x00000000); - out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); - out_le32(mbase + PECFG_PIM01SAL, 0x00000000); + out_le32(mbase + PECFG_PIM01SAH, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_PIM01SAL, RES_TO_U32_LOW(sa)); + + out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(ep_addr)); + out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(ep_addr)); + } else { + /* Calculate window size */ + sa = (0xffffffffffffffffull << ilog2(size));; + if (res->flags & IORESOURCE_PREFETCH) + sa |= 0x8; + + out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); + out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); + + /* The setup of the split looks weird to me ... let's see + * if it works + */ + out_le32(mbase + PECFG_PIM0LAL, 0x00000000); + out_le32(mbase + PECFG_PIM0LAH, 0x00000000); + out_le32(mbase + PECFG_PIM1LAL, 0x00000000); + out_le32(mbase + PECFG_PIM1LAH, 0x00000000); + out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); + out_le32(mbase + PECFG_PIM01SAL, 0x00000000); + + out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start)); + out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start)); + } /* Enable inbound mapping */ out_le32(mbase + PECFG_PIMEN, 0x1); - out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start)); - out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start)); - /* Enable I/O, Mem, and Busmaster cycles */ out_le16(mbase + PCI_COMMAND, in_le16(mbase + PCI_COMMAND) | @@ -1422,13 +1453,8 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) const int *bus_range; int primary = 0, busses; void __iomem *mbase = NULL, *cfg_data = NULL; - - /* XXX FIXME: Handle endpoint mode properly */ - if (port->endpoint) { - printk(KERN_WARNING "PCIE%d: Port in endpoint mode !\n", - port->index); - return; - } + const u32 *pval; + u32 val; /* Check if primary bridge */ if (of_get_property(port->node, "primary", NULL)) @@ -1462,21 +1488,30 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) hose->last_busno = hose->first_busno + busses; } - /* We map the external config space in cfg_data and the host config - * space in cfg_addr. External space is 1M per bus, internal space - * is 4K + if (!port->endpoint) { + /* Only map the external config space in cfg_data for + * PCIe root-complexes. External space is 1M per bus + */ + cfg_data = ioremap(port->cfg_space.start + + (hose->first_busno + 1) * 0x100000, + busses * 0x100000); + if (cfg_data == NULL) { + printk(KERN_ERR "%s: Can't map external config space !", + port->node->full_name); + goto fail; + } + hose->cfg_data = cfg_data; + } + + /* Always map the host config space in cfg_addr. + * Internal space is 4K */ - cfg_data = ioremap(port->cfg_space.start + - (hose->first_busno + 1) * 0x100000, - busses * 0x100000); mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000); - if (cfg_data == NULL || mbase == NULL) { - printk(KERN_ERR "%s: Can't map config space !", + if (mbase == NULL) { + printk(KERN_ERR "%s: Can't map internal config space !", port->node->full_name); goto fail; } - - hose->cfg_data = cfg_data; hose->cfg_addr = mbase; pr_debug("PCIE %s, bus %d..%d\n", port->node->full_name, @@ -1489,12 +1524,14 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) port->hose = hose; mbase = (void __iomem *)hose->cfg_addr; - /* - * Set bus numbers on our root port - */ - out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno); - out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1); - out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno); + if (!port->endpoint) { + /* + * Set bus numbers on our root port + */ + out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno); + out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1); + out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno); + } /* * OMRs are already reset, also disable PIMs @@ -1515,17 +1552,49 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) ppc4xx_configure_pciex_PIMs(port, hose, mbase, &dma_window); /* The root complex doesn't show up if we don't set some vendor - * and device IDs into it. Those are the same bogus one that the - * initial code in arch/ppc add. We might want to change that. + * and device IDs into it. The defaults below are the same bogus + * one that the initial code in arch/ppc had. This can be + * overwritten by setting the "vendor-id/device-id" properties + * in the pciex node. */ - out_le16(mbase + 0x200, 0xaaa0 + port->index); - out_le16(mbase + 0x202, 0xbed0 + port->index); - /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ - out_le32(mbase + 0x208, 0x06040001); + /* Get the (optional) vendor-/device-id from the device-tree */ + pval = of_get_property(port->node, "vendor-id", NULL); + if (pval) { + val = *pval; + } else { + if (!port->endpoint) + val = 0xaaa0 + port->index; + else + val = 0xeee0 + port->index; + } + out_le16(mbase + 0x200, val); + + pval = of_get_property(port->node, "device-id", NULL); + if (pval) { + val = *pval; + } else { + if (!port->endpoint) + val = 0xbed0 + port->index; + else + val = 0xfed0 + port->index; + } + out_le16(mbase + 0x202, val); + + if (!port->endpoint) { + /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ + out_le32(mbase + 0x208, 0x06040001); + + printk(KERN_INFO "PCIE%d: successfully set as root-complex\n", + port->index); + } else { + /* Set Class Code to Processor/PPC */ + out_le32(mbase + 0x208, 0x0b200001); + + printk(KERN_INFO "PCIE%d: successfully set as endpoint\n", + port->index); + } - printk(KERN_INFO "PCIE%d: successfully set as root-complex\n", - port->index); return; fail: if (hose) @@ -1542,6 +1611,7 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np) const u32 *pval; int portno; unsigned int dcrs; + const char *val; /* First, proceed to core initialization as we assume there's * only one PCIe core in the system @@ -1573,8 +1643,20 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np) } port->sdr_base = *pval; - /* XXX Currently, we only support root complex mode */ - port->endpoint = 0; + /* Check if device_type property is set to "pci" or "pci-endpoint". + * Resulting from this setup this PCIe port will be configured + * as root-complex or as endpoint. + */ + val = of_get_property(port->node, "device_type", NULL); + if (!strcmp(val, "pci-endpoint")) { + port->endpoint = 1; + } else if (!strcmp(val, "pci")) { + port->endpoint = 0; + } else { + printk(KERN_ERR "PCIE: missing or incorrect device_type for %s\n", + np->full_name); + return; + } /* Fetch config space registers address */ if (of_address_to_resource(np, 0, &port->cfg_space)) { diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 52c7478..1702de9 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -2842,9 +2842,11 @@ static void dump_spu_fields(struct spu *spu) DUMP_FIELD(spu, "0x%lx", ls_size); DUMP_FIELD(spu, "0x%x", node); DUMP_FIELD(spu, "0x%lx", flags); - DUMP_FIELD(spu, "0x%lx", dar); - DUMP_FIELD(spu, "0x%lx", dsisr); DUMP_FIELD(spu, "%d", class_0_pending); + DUMP_FIELD(spu, "0x%lx", class_0_dar); + DUMP_FIELD(spu, "0x%lx", class_0_dsisr); + DUMP_FIELD(spu, "0x%lx", class_1_dar); + DUMP_FIELD(spu, "0x%lx", class_1_dsisr); DUMP_FIELD(spu, "0x%lx", irqs[0]); DUMP_FIELD(spu, "0x%lx", irqs[1]); DUMP_FIELD(spu, "0x%lx", irqs[2]); diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 90fe904..418f305 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -341,6 +341,7 @@ static struct resource mv64x60_eth0_resources[] = { }; static struct mv643xx_eth_platform_data eth0_pd = { + .shared = &mv64x60_eth_shared_device; .port_number = 0, }; @@ -366,6 +367,7 @@ static struct resource mv64x60_eth1_resources[] = { }; static struct mv643xx_eth_platform_data eth1_pd = { + .shared = &mv64x60_eth_shared_device; .port_number = 1, }; @@ -391,6 +393,7 @@ static struct resource mv64x60_eth2_resources[] = { }; static struct mv643xx_eth_platform_data eth2_pd = { + .shared = &mv64x60_eth_shared_device; .port_number = 2, }; diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 29a7940..1d03508 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -430,6 +430,13 @@ config CMM_IUCV Select this option to enable the special message interface to the cooperative memory management. +config PAGE_STATES + bool "Unused page notification" + help + This enables the notification of unused pages to the + hypervisor. The ESSA instruction is used to do the states + changes between a page that has content and the unused state. + config VIRT_TIMER bool "Virtual CPU timer support" help diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 743d54f..d003a6e 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -121,7 +121,7 @@ sys32_ptrace_wrapper: lgfr %r3,%r3 # long llgtr %r4,%r4 # long llgfr %r5,%r5 # long - jg sys_ptrace # branch to system call + jg compat_sys_ptrace # branch to system call .globl sys32_alarm_wrapper sys32_alarm_wrapper: diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index bdbb3bc..708cf9c 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -279,8 +279,6 @@ sysc_do_restart: st %r2,SP_R2(%r15) # store return value (change R2 on stack) sysc_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? - bno BASED(sysc_restore) tm __TI_flags+3(%r9),_TIF_WORK_SVC bnz BASED(sysc_work) # there is work to do (signals etc.) sysc_restore: @@ -312,6 +310,8 @@ sysc_work_loop: # One of the work bits is on. Find out which one. # sysc_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? + bno BASED(sysc_restore) tm __TI_flags+3(%r9),_TIF_MCCK_PENDING bo BASED(sysc_mcck_pending) tm __TI_flags+3(%r9),_TIF_NEED_RESCHED @@ -602,12 +602,6 @@ io_no_vtime: la %r2,SP_PTREGS(%r15) # address of register-save area basr %r14,%r1 # branch to standard irq handler io_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? -#ifdef CONFIG_PREEMPT - bno BASED(io_preempt) # no -> check for preemptive scheduling -#else - bno BASED(io_restore) # no-> skip resched & signal -#endif tm __TI_flags+3(%r9),_TIF_WORK_INT bnz BASED(io_work) # there is work to do (signals etc.) io_restore: @@ -629,10 +623,18 @@ io_restore_trace_psw: .long 0, io_restore_trace + 0x80000000 #endif -#ifdef CONFIG_PREEMPT -io_preempt: +# +# switch to kernel stack, then check the TIF bits +# +io_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? +#ifndef CONFIG_PREEMPT + bno BASED(io_restore) # no-> skip resched & signal +#else + bnz BASED(io_work_user) # no -> check for preemptive scheduling + # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) - bnz BASED(io_restore) + bnz BASED(io_restore) # preemption disabled l %r1,SP_R15(%r15) s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) @@ -646,10 +648,7 @@ io_resume_loop: br %r1 # call schedule #endif -# -# switch to kernel stack, then check the TIF bits -# -io_work: +io_work_user: l %r1,__LC_KERNEL_STACK s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 5a4a7bc..fee1017 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -271,8 +271,6 @@ sysc_noemu: stg %r2,SP_R2(%r15) # store return value (change R2 on stack) sysc_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? - jno sysc_restore tm __TI_flags+7(%r9),_TIF_WORK_SVC jnz sysc_work # there is work to do (signals etc.) sysc_restore: @@ -304,6 +302,8 @@ sysc_work_loop: # One of the work bits is on. Find out which one. # sysc_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? + jno sysc_restore tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jo sysc_mcck_pending tm __TI_flags+7(%r9),_TIF_NEED_RESCHED @@ -585,12 +585,6 @@ io_no_vtime: la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handler io_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? -#ifdef CONFIG_PREEMPT - jno io_preempt # no -> check for preemptive scheduling -#else - jno io_restore # no-> skip resched & signal -#endif tm __TI_flags+7(%r9),_TIF_WORK_INT jnz io_work # there is work to do (signals etc.) io_restore: @@ -612,10 +606,41 @@ io_restore_trace_psw: .quad 0, io_restore_trace #endif -#ifdef CONFIG_PREEMPT -io_preempt: +# +# There is work todo, we need to check if we return to userspace, then +# check, if we are in SIE, if yes leave it +# +io_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? +#ifndef CONFIG_PREEMPT +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) + jnz io_work_user # yes -> no need to check for SIE + la %r1, BASED(sie_opcode) # we return to kernel here + lg %r2, SP_PSW+8(%r15) + clc 0(2,%r1), 0(%r2) # is current instruction = SIE? + jne io_restore # no-> return to kernel + lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE + aghi %r1, 4 + stg %r1, SP_PSW+8(%r15) + j io_restore # return to kernel +#else + jno io_restore # no-> skip resched & signal +#endif +#else + jnz io_work_user # yes -> do resched & signal +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) + la %r1, BASED(sie_opcode) + lg %r2, SP_PSW+8(%r15) + clc 0(2,%r1), 0(%r2) # is current instruction = SIE? + jne 0f # no -> leave PSW alone + lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE + aghi %r1, 4 + stg %r1, SP_PSW+8(%r15) +0: +#endif + # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) - jnz io_restore + jnz io_restore # preemption is disabled # switch to kernel stack lg %r1,SP_R15(%r15) aghi %r1,-SP_SIZE @@ -629,10 +654,7 @@ io_resume_loop: jg preempt_schedule_irq #endif -# -# switch to kernel stack, then check TIF bits -# -io_work: +io_work_user: lg %r1,__LC_KERNEL_STACK aghi %r1,-SP_SIZE mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) @@ -653,6 +675,11 @@ io_work_loop: j io_restore io_work_done: +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) +sie_opcode: + .long 0xb2140000 +#endif + # # _TIF_MCCK_PENDING is set, call handler # diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 7f42701..35827b9 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -292,8 +292,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) return 0; } -static int -do_ptrace_normal(struct task_struct *child, long request, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { ptrace_area parea; int copied, ret; @@ -529,35 +528,19 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) return 0; } -static int -do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) { - unsigned int tmp; /* 4 bytes !! */ + unsigned long addr = caddr; + unsigned long data = cdata; ptrace_area_emu31 parea; int copied, ret; switch (request) { - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - /* read word at location addr. */ - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - return -EIO; - return put_user(tmp, (unsigned int __force __user *) data); - case PTRACE_PEEKUSR: /* read the word at location addr in the USER area. */ return peek_user_emu31(child, addr, data); - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - /* write the word at location addr. */ - tmp = data; - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1); - if (copied != sizeof(tmp)) - return -EIO; - return 0; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ return poke_user_emu31(child, addr, data); @@ -587,82 +570,11 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) copied += sizeof(unsigned int); } return 0; - case PTRACE_GETEVENTMSG: - return put_user((__u32) child->ptrace_message, - (unsigned int __force __user *) data); - case PTRACE_GETSIGINFO: - if (child->last_siginfo == NULL) - return -EINVAL; - return copy_siginfo_to_user32((compat_siginfo_t - __force __user *) data, - child->last_siginfo); - case PTRACE_SETSIGINFO: - if (child->last_siginfo == NULL) - return -EINVAL; - return copy_siginfo_from_user32(child->last_siginfo, - (compat_siginfo_t - __force __user *) data); } - return ptrace_request(child, request, addr, data); + return compat_ptrace_request(child, request, addr, data); } #endif -long arch_ptrace(struct task_struct *child, long request, long addr, long data) -{ - switch (request) { - case PTRACE_SYSCALL: - /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: - /* restart after signal. */ - if (!valid_signal(data)) - return -EIO; - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - child->exit_code = data; - /* make sure the single step bit is not set. */ - user_disable_single_step(child); - wake_up_process(child); - return 0; - - case PTRACE_KILL: - /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ - return 0; - child->exit_code = SIGKILL; - /* make sure the single step bit is not set. */ - user_disable_single_step(child); - wake_up_process(child); - return 0; - - case PTRACE_SINGLESTEP: - /* set the trap flag. */ - if (!valid_signal(data)) - return -EIO; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - child->exit_code = data; - user_enable_single_step(child); - /* give it a chance to run. */ - wake_up_process(child); - return 0; - - /* Do requests that differ for 31/64 bit */ - default: -#ifdef CONFIG_COMPAT - if (test_thread_flag(TIF_31BIT)) - return do_ptrace_emu31(child, request, addr, data); -#endif - return do_ptrace_normal(child, request, addr, data); - } - /* Not reached. */ - return -EIO; -} - asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) { diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index 1761b74..e051cad 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig @@ -22,7 +22,6 @@ config KVM select PREEMPT_NOTIFIERS select ANON_INODES select S390_SWITCH_AMODE - select PREEMPT ---help--- Support hosting paravirtualized guest machines using the SIE virtualization capability on the mainframe. This should work diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 349581a..47a0b64 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -105,6 +105,9 @@ static intercept_handler_t instruction_handlers[256] = { static int handle_noop(struct kvm_vcpu *vcpu) { switch (vcpu->arch.sie_block->icptcode) { + case 0x0: + vcpu->stat.exit_null++; + break; case 0x10: vcpu->stat.exit_external_request++; break; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 98d1e73..0ac36a6 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -31,6 +31,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "userspace_handled", VCPU_STAT(exit_userspace) }, + { "exit_null", VCPU_STAT(exit_null) }, { "exit_validity", VCPU_STAT(exit_validity) }, { "exit_stop_request", VCPU_STAT(exit_stop_request) }, { "exit_external_request", VCPU_STAT(exit_external_request) }, @@ -221,10 +222,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK; restore_fp_regs(&vcpu->arch.guest_fpregs); restore_access_regs(vcpu->arch.guest_acrs); - - if (signal_pending(current)) - atomic_set_mask(CPUSTAT_STOP_INT, - &vcpu->arch.sie_block->cpuflags); } void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile index fb988a4..2a74581 100644 --- a/arch/s390/mm/Makefile +++ b/arch/s390/mm/Makefile @@ -5,3 +5,4 @@ obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o obj-$(CONFIG_CMM) += cmm.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o +obj-$(CONFIG_PAGE_STATES) += page-states.o diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index fa31de6..29f3a63 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -126,6 +126,9 @@ void __init mem_init(void) /* clear the zero-page */ memset(empty_zero_page, 0, PAGE_SIZE); + /* Setup guest page hinting */ + cmma_init(); + /* this will put all low memory onto the freelists */ totalram_pages += free_all_bootmem(); diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c new file mode 100644 index 0000000..fc0ad73 --- /dev/null +++ b/arch/s390/mm/page-states.c @@ -0,0 +1,79 @@ +/* + * arch/s390/mm/page-states.c + * + * Copyright IBM Corp. 2008 + * + * Guest page hinting for unused pages. + * + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/init.h> + +#define ESSA_SET_STABLE 1 +#define ESSA_SET_UNUSED 2 + +static int cmma_flag; + +static int __init cmma(char *str) +{ + char *parm; + parm = strstrip(str); + if (strcmp(parm, "yes") == 0 || strcmp(parm, "on") == 0) { + cmma_flag = 1; + return 1; + } + cmma_flag = 0; + if (strcmp(parm, "no") == 0 || strcmp(parm, "off") == 0) + return 1; + return 0; +} + +__setup("cmma=", cmma); + +void __init cmma_init(void) +{ + register unsigned long tmp asm("0") = 0; + register int rc asm("1") = -EOPNOTSUPP; + + if (!cmma_flag) + return; + asm volatile( + " .insn rrf,0xb9ab0000,%1,%1,0,0\n" + "0: la %0,0\n" + "1:\n" + EX_TABLE(0b,1b) + : "+&d" (rc), "+&d" (tmp)); + if (rc) + cmma_flag = 0; +} + +void arch_free_page(struct page *page, int order) +{ + int i, rc; + + if (!cmma_flag) + return; + for (i = 0; i < (1 << order); i++) + asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" + : "=&d" (rc) + : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT), + "i" (ESSA_SET_UNUSED)); +} + +void arch_alloc_page(struct page *page, int order) +{ + int i, rc; + + if (!cmma_flag) + return; + for (i = 0; i < (1 << order); i++) + asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" + : "=&d" (rc) + : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT), + "i" (ESSA_SET_STABLE)); +} diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 6a679c3..8a68160 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -448,14 +448,6 @@ config SH_DREAMCAST Select Dreamcast if configuring for a SEGA Dreamcast. More information at <http://www.linux-sh.org> -config SH_MPC1211 - bool "Interface MPC1211" - depends on CPU_SUBTYPE_SH7751 && BROKEN - help - CTP/PCI-SH02 is a CPU module computer that is produced - by Interface Corporation. - More information at <http://www.interface.co.jp> - config SH_SH03 bool "Interface CTP/PCI-SH03" depends on CPU_SUBTYPE_SH7751 @@ -657,8 +649,7 @@ source "arch/sh/drivers/Kconfig" endmenu config ISA_DMA_API - def_bool y - depends on SH_MPC1211 + bool menu "Kernel features" @@ -666,7 +657,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on SUPERH32 && EXPERIMENTAL help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot @@ -683,7 +674,7 @@ config KEXEC config CRASH_DUMP bool "kernel crash dumps (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on SUPERH32 && EXPERIMENTAL help Generate crash dump after being started by kexec. This should be normally only set in special crash dump kernels @@ -763,7 +754,7 @@ menu "Boot options" config ZERO_PAGE_OFFSET hex "Zero page offset" - default "0x00004000" if SH_MPC1211 || SH_SH03 + default "0x00004000" if SH_SH03 default "0x00010000" if PAGE_SIZE_64KB default "0x00002000" if PAGE_SIZE_8KB default "0x00001000" diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index d9d28f9..0d2ef1e 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -7,6 +7,7 @@ source "lib/Kconfig.debug" config SH_STANDARD_BIOS bool "Use LinuxSH standard BIOS" + depends on SUPERH32 help Say Y here if your target has the gdb-sh-stub package from www.m17n.org (or any conforming standard LinuxSH BIOS) diff --git a/arch/sh/Makefile b/arch/sh/Makefile index bb06f83..8050b03 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -110,7 +110,6 @@ machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE) += se/7343 machdir-$(CONFIG_SH_7721_SOLUTION_ENGINE) += se/7721 machdir-$(CONFIG_SH_HP6XX) += hp6xx machdir-$(CONFIG_SH_DREAMCAST) += dreamcast -machdir-$(CONFIG_SH_MPC1211) += mpc1211 machdir-$(CONFIG_SH_SH03) += sh03 machdir-$(CONFIG_SH_SECUREEDGE5410) += snapgear machdir-$(CONFIG_SH_RTS7751R2D) += renesas/rts7751r2d diff --git a/arch/sh/boards/mpc1211/Makefile b/arch/sh/boards/mpc1211/Makefile deleted file mode 100644 index 8cd31b5..0000000 --- a/arch/sh/boards/mpc1211/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel -# - -obj-y := setup.o rtc.o - -obj-$(CONFIG_PCI) += pci.o - diff --git a/arch/sh/boards/mpc1211/pci.c b/arch/sh/boards/mpc1211/pci.c deleted file mode 100644 index 23849f7..0000000 --- a/arch/sh/boards/mpc1211/pci.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Low-Level PCI Support for the MPC-1211(CTP/PCI/MPC-SH02) - * - * (c) 2002-2003 Saito.K & Jeanne - * - * Dustin McIntire (dustin@sensoria.com) - * Derived from arch/i386/kernel/pci-*.c which bore the message: - * (c) 1999--2000 Martin Mares <mj@ucw.cz> - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/pci.h> -#include <linux/sched.h> -#include <linux/ioport.h> -#include <linux/errno.h> -#include <linux/irq.h> -#include <linux/interrupt.h> - -#include <asm/machvec.h> -#include <asm/io.h> -#include <asm/mpc1211/pci.h> - -static struct resource mpcpci_io_resource = { - "MPCPCI IO", - 0x00000000, - 0xffffffff, - IORESOURCE_IO -}; - -static struct resource mpcpci_mem_resource = { - "MPCPCI mem", - 0x00000000, - 0xffffffff, - IORESOURCE_MEM -}; - -static struct pci_ops pci_direct_conf1; -struct pci_channel board_pci_channels[] = { - {&pci_direct_conf1, &mpcpci_io_resource, &mpcpci_mem_resource, 0, 256}, - {NULL, NULL, NULL, 0, 0}, -}; - -/* - * Direct access to PCI hardware... - */ - - -#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3)) - -/* - * Functions for accessing PCI configuration space with type 1 accesses - */ -static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) -{ - u32 word; - unsigned long flags; - - /* - * PCIPDR may only be accessed as 32 bit words, - * so we must do byte alignment by hand - */ - local_irq_save(flags); - writel(CONFIG_CMD(bus,devfn,where), PCIPAR); - word = readl(PCIPDR); - local_irq_restore(flags); - - switch (size) { - case 1: - switch (where & 0x3) { - case 3: - *value = (u8)(word >> 24); - break; - case 2: - *value = (u8)(word >> 16); - break; - case 1: - *value = (u8)(word >> 8); - break; - default: - *value = (u8)word; - break; - } - break; - case 2: - switch (where & 0x3) { - case 3: - *value = (u16)(word >> 24); - local_irq_save(flags); - writel(CONFIG_CMD(bus,devfn,(where+1)), PCIPAR); - word = readl(PCIPDR); - local_irq_restore(flags); - *value |= ((word & 0xff) << 8); - break; - case 2: - *value = (u16)(word >> 16); - break; - case 1: - *value = (u16)(word >> 8); - break; - default: - *value = (u16)word; - break; - } - break; - case 4: - *value = word; - break; - } - PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value); - return PCIBIOS_SUCCESSFUL; -} - -/* - * Since MPC-1211 only does 32bit access we'll have to do a read,mask,write operation. - * We'll allow an odd byte offset, though it should be illegal. - */ -static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) -{ - u32 word,mask = 0; - unsigned long flags; - u32 shift = (where & 3) * 8; - - if(size == 1) { - mask = ((1 << 8) - 1) << shift; // create the byte mask - } else if(size == 2){ - if(shift == 24) - return PCIBIOS_BAD_REGISTER_NUMBER; - mask = ((1 << 16) - 1) << shift; // create the word mask - } - local_irq_save(flags); - writel(CONFIG_CMD(bus,devfn,where), PCIPAR); - if(size == 4){ - writel(value, PCIPDR); - local_irq_restore(flags); - PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value); - return PCIBIOS_SUCCESSFUL; - } - word = readl(PCIPDR); - word &= ~mask; - word |= ((value << shift) & mask); - writel(word, PCIPDR); - local_irq_restore(flags); - PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word); - return PCIBIOS_SUCCESSFUL; -} - -#undef CONFIG_CMD - -static struct pci_ops pci_direct_conf1 = { - .read = pci_conf1_read, - .write = pci_conf1_write, -}; - -static void __devinit quirk_ali_ide_ports(struct pci_dev *dev) -{ - dev->resource[0].start = 0x1f0; - dev->resource[0].end = 0x1f7; - dev->resource[0].flags = IORESOURCE_IO; - dev->resource[1].start = 0x3f6; - dev->resource[1].end = 0x3f6; - dev->resource[1].flags = IORESOURCE_IO; - dev->resource[2].start = 0x170; - dev->resource[2].end = 0x177; - dev->resource[2].flags = IORESOURCE_IO; - dev->resource[3].start = 0x376; - dev->resource[3].end = 0x376; - dev->resource[3].flags = IORESOURCE_IO; - dev->resource[4].start = 0xf000; - dev->resource[4].end = 0xf00f; - dev->resource[4].flags = IORESOURCE_IO; -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports); - -char * __devinit pcibios_setup(char *str) -{ - return str; -} - -/* - * Called after each bus is probed, but before its children - * are examined. - */ - -void __devinit pcibios_fixup_bus(struct pci_bus *b) -{ - pci_read_bridge_bases(b); -} - -/* - * IRQ functions - */ -static inline u8 bridge_swizzle(u8 pin, u8 slot) -{ - return (((pin-1) + slot) % 4) + 1; -} - -static inline u8 bridge_swizzle_pci_1(u8 pin, u8 slot) -{ - return (((pin-1) - slot) & 3) + 1; -} - -static u8 __init mpc1211_swizzle(struct pci_dev *dev, u8 *pinp) -{ - unsigned long flags; - u8 pin = *pinp; - u32 word; - - for ( ; dev->bus->self; dev = dev->bus->self) { - if (!pin) - continue; - - if (dev->bus->number == 1) { - local_irq_save(flags); - writel(0x80000000 | 0x2c, PCIPAR); - word = readl(PCIPDR); - local_irq_restore(flags); - word >>= 16; - - if (word == 0x0001) - pin = bridge_swizzle_pci_1(pin, PCI_SLOT(dev->devfn)); - else - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - } else - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - } - - *pinp = pin; - - return PCI_SLOT(dev->devfn); -} - -static int __init map_mpc1211_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - int irq = -1; - - /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */ - if (dev->bus->number == 0) { - switch (slot) { - case 13: irq = 9; break; /* USB */ - case 22: irq = 10; break; /* LAN */ - default: irq = 0; break; - } - } else { - switch (pin) { - case 0: irq = 0; break; - case 1: irq = 7; break; - case 2: irq = 9; break; - case 3: irq = 10; break; - case 4: irq = 11; break; - } - } - - if( irq < 0 ) { - PCIDBG(3, "PCI: Error mapping IRQ on device %s\n", pci_name(dev)); - return irq; - } - - PCIDBG(2, "Setting IRQ for slot %s to %d\n", pci_name(dev), irq); - - return irq; -} - -void __init pcibios_fixup_irqs(void) -{ - pci_fixup_irqs(mpc1211_swizzle, map_mpc1211_irq); -} - -void pcibios_align_resource(void *data, struct resource *res, - resource_size_t size, resource_size_t align) -{ - resource_size_t start = res->start; - - if (res->flags & IORESOURCE_IO) { - if (start >= 0x10000UL) { - if ((start & 0xffffUL) < 0x4000UL) { - start = (start & 0xffff0000UL) + 0x4000UL; - } else if ((start & 0xffffUL) >= 0xf000UL) { - start = (start & 0xffff0000UL) + 0x10000UL; - } - res->start = start; - } else { - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } - } -} - diff --git a/arch/sh/boards/mpc1211/rtc.c b/arch/sh/boards/mpc1211/rtc.c deleted file mode 100644 index 03b123a..0000000 --- a/arch/sh/boards/mpc1211/rtc.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * linux/arch/sh/kernel/rtc-mpc1211.c -- MPC-1211 on-chip RTC support - * - * Copyright (C) 2002 Saito.K & Jeanne - * - */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/time.h> -#include <linux/bcd.h> -#include <linux/mc146818rtc.h> - -unsigned long get_cmos_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - - spin_lock(&rtc_lock); - - do { - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - - spin_unlock(&rtc_lock); - - year += 1900; - if (year < 1970) - year += 100; - - return mktime(year, mon, day, hour, min, sec); -} - -void mpc1211_rtc_gettimeofday(struct timeval *tv) -{ - - tv->tv_sec = get_cmos_time(); - tv->tv_usec = 0; -} - -/* arc/i386/kernel/time.c */ -/* - * In order to set the CMOS clock precisely, set_rtc_mmss has to be - * called 500 ms after the second nowtime has started, because when - * nowtime is written into the registers of the CMOS clock, it will - * jump to the next second precisely 500 ms later. Check the Motorola - * MC146818A or Dallas DS12887 data sheet for details. - * - * BUG: This routine does not handle hour overflow properly; it just - * sets the minutes. Usually you'll only notice that after reboot! - */ -static int set_rtc_mmss(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - unsigned char save_control, save_freq_select; - - /* gets recalled with irq locally disabled */ - spin_lock(&rtc_lock); - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - cmos_minutes = CMOS_READ(RTC_MINUTES); - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(cmos_minutes); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - } - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data - * sheets anyway ... -- Markus Kuhn - */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - spin_unlock(&rtc_lock); - - return retval; -} - -int mpc1211_rtc_settimeofday(const struct timeval *tv) -{ - unsigned long nowtime = tv->tv_sec; - - return set_rtc_mmss(nowtime); -} - -void mpc1211_time_init(void) -{ - rtc_sh_get_time = mpc1211_rtc_gettimeofday; - rtc_sh_set_time = mpc1211_rtc_settimeofday; -} - diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c deleted file mode 100644 index fede363..0000000 --- a/arch/sh/boards/mpc1211/setup.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * linux/arch/sh/boards/mpc1211/setup.c - * - * Copyright (C) 2002 Saito.K & Jeanne, Fujii.Y - * - */ - -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/hdreg.h> -#include <linux/ide.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <asm/io.h> -#include <asm/machvec.h> -#include <asm/mpc1211/mpc1211.h> -#include <asm/mpc1211/pci.h> -#include <asm/mpc1211/m1543c.h> - -/* ALI15X3 SMBus address offsets */ -#define SMBHSTSTS (0 + 0x3100) -#define SMBHSTCNT (1 + 0x3100) -#define SMBHSTSTART (2 + 0x3100) -#define SMBHSTCMD (7 + 0x3100) -#define SMBHSTADD (3 + 0x3100) -#define SMBHSTDAT0 (4 + 0x3100) -#define SMBHSTDAT1 (5 + 0x3100) -#define SMBBLKDAT (6 + 0x3100) - -/* Other settings */ -#define MAX_TIMEOUT 500 /* times 1/100 sec */ - -/* ALI15X3 command constants */ -#define ALI15X3_ABORT 0x04 -#define ALI15X3_T_OUT 0x08 -#define ALI15X3_QUICK 0x00 -#define ALI15X3_BYTE 0x10 -#define ALI15X3_BYTE_DATA 0x20 -#define ALI15X3_WORD_DATA 0x30 -#define ALI15X3_BLOCK_DATA 0x40 -#define ALI15X3_BLOCK_CLR 0x80 - -/* ALI15X3 status register bits */ -#define ALI15X3_STS_IDLE 0x04 -#define ALI15X3_STS_BUSY 0x08 -#define ALI15X3_STS_DONE 0x10 -#define ALI15X3_STS_DEV 0x20 /* device error */ -#define ALI15X3_STS_COLL 0x40 /* collision or no response */ -#define ALI15X3_STS_TERM 0x80 /* terminated by abort */ -#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */ - -static void __init pci_write_config(unsigned long busNo, - unsigned long devNo, - unsigned long fncNo, - unsigned long cnfAdd, - unsigned long cnfData) -{ - ctrl_outl((0x80000000 - + ((busNo & 0xff) << 16) - + ((devNo & 0x1f) << 11) - + ((fncNo & 0x07) << 8) - + (cnfAdd & 0xfc)), PCIPAR); - - ctrl_outl(cnfData, PCIPDR); -} - -/* - Initialize IRQ setting -*/ - -static unsigned char m_irq_mask = 0xfb; -static unsigned char s_irq_mask = 0xff; - -static void disable_mpc1211_irq(unsigned int irq) -{ - if( irq < 8) { - m_irq_mask |= (1 << irq); - outb(m_irq_mask,I8259_M_MR); - } else { - s_irq_mask |= (1 << (irq - 8)); - outb(s_irq_mask,I8259_S_MR); - } - -} - -static void enable_mpc1211_irq(unsigned int irq) -{ - if( irq < 8) { - m_irq_mask &= ~(1 << irq); - outb(m_irq_mask,I8259_M_MR); - } else { - s_irq_mask &= ~(1 << (irq - 8)); - outb(s_irq_mask,I8259_S_MR); - } -} - -static inline int mpc1211_irq_real(unsigned int irq) -{ - int value; - int irqmask; - - if ( irq < 8) { - irqmask = 1<<irq; - outb(0x0b,I8259_M_CR); /* ISR register */ - value = inb(I8259_M_CR) & irqmask; - outb(0x0a,I8259_M_CR); /* back ro the IPR reg */ - return value; - } - irqmask = 1<<(irq - 8); - outb(0x0b,I8259_S_CR); /* ISR register */ - value = inb(I8259_S_CR) & irqmask; - outb(0x0a,I8259_S_CR); /* back ro the IPR reg */ - return value; -} - -static void mask_and_ack_mpc1211(unsigned int irq) -{ - if(irq < 8) { - if(m_irq_mask & (1<<irq)){ - if(!mpc1211_irq_real(irq)){ - atomic_inc(&irq_err_count) - printk("spurious 8259A interrupt: IRQ %x\n",irq); - } - } else { - m_irq_mask |= (1<<irq); - } - inb(I8259_M_MR); /* DUMMY */ - outb(m_irq_mask,I8259_M_MR); /* disable */ - outb(0x60+irq,I8259_M_CR); /* EOI */ - - } else { - if(s_irq_mask & (1<<(irq - 8))){ - if(!mpc1211_irq_real(irq)){ - atomic_inc(&irq_err_count); - printk("spurious 8259A interrupt: IRQ %x\n",irq); - } - } else { - s_irq_mask |= (1<<(irq - 8)); - } - inb(I8259_S_MR); /* DUMMY */ - outb(s_irq_mask,I8259_S_MR); /* disable */ - outb(0x60+(irq-8),I8259_S_CR); /* EOI */ - outb(0x60+2,I8259_M_CR); - } -} - -static void end_mpc1211_irq(unsigned int irq) -{ - enable_mpc1211_irq(irq); -} - -static unsigned int startup_mpc1211_irq(unsigned int irq) -{ - enable_mpc1211_irq(irq); - return 0; -} - -static void shutdown_mpc1211_irq(unsigned int irq) -{ - disable_mpc1211_irq(irq); -} - -static struct hw_interrupt_type mpc1211_irq_type = { - .typename = "MPC1211-IRQ", - .startup = startup_mpc1211_irq, - .shutdown = shutdown_mpc1211_irq, - .enable = enable_mpc1211_irq, - .disable = disable_mpc1211_irq, - .ack = mask_and_ack_mpc1211, - .end = end_mpc1211_irq -}; - -static void make_mpc1211_irq(unsigned int irq) -{ - irq_desc[irq].chip = &mpc1211_irq_type; - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = 0; - irq_desc[irq].depth = 1; - disable_mpc1211_irq(irq); -} - -int mpc1211_irq_demux(int irq) -{ - unsigned int poll; - - if( irq == 2 ) { - outb(0x0c,I8259_M_CR); - poll = inb(I8259_M_CR); - if(poll & 0x80) { - irq = (poll & 0x07); - } - if( irq == 2) { - outb(0x0c,I8259_S_CR); - poll = inb(I8259_S_CR); - irq = (poll & 0x07) + 8; - } - } - return irq; -} - -static void __init init_mpc1211_IRQ(void) -{ - int i; - /* - * Super I/O (Just mimic PC): - * 1: keyboard - * 3: serial 1 - * 4: serial 0 - * 5: printer - * 6: floppy - * 8: rtc - * 10: lan - * 12: mouse - * 14: ide0 - * 15: ide1 - */ - - pci_write_config(0,0,0,0x54, 0xb0b0002d); - outb(0x11, I8259_M_CR); /* mater icw1 edge trigger */ - outb(0x11, I8259_S_CR); /* slave icw1 edge trigger */ - outb(0x20, I8259_M_MR); /* m icw2 base vec 0x08 */ - outb(0x28, I8259_S_MR); /* s icw2 base vec 0x70 */ - outb(0x04, I8259_M_MR); /* m icw3 slave irq2 */ - outb(0x02, I8259_S_MR); /* s icw3 slave id */ - outb(0x01, I8259_M_MR); /* m icw4 non buf normal eoi*/ - outb(0x01, I8259_S_MR); /* s icw4 non buf normal eo1*/ - outb(0xfb, I8259_M_MR); /* disable irq0--irq7 */ - outb(0xff, I8259_S_MR); /* disable irq8--irq15 */ - - for ( i=0; i < 16; i++) { - if(i != 2) { - make_mpc1211_irq(i); - } - } -} - -static void delay1000(void) -{ - int i; - - for (i=0; i<1000; i++) - ctrl_delay(); -} - -static int put_smb_blk(unsigned char *p, int address, int command, int no) -{ - int temp; - int timeout; - int i; - - outb(0xff, SMBHSTSTS); - temp = inb(SMBHSTSTS); - for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) { - delay1000(); - temp = inb(SMBHSTSTS); - } - if (timeout >= MAX_TIMEOUT){ - return -1; - } - - outb(((address & 0x7f) << 1), SMBHSTADD); - outb(0xc0, SMBHSTCNT); - outb(command & 0xff, SMBHSTCMD); - outb(no & 0x1f, SMBHSTDAT0); - - for(i = 1; i <= no; i++) { - outb(*p++, SMBBLKDAT); - } - outb(0xff, SMBHSTSTART); - - temp = inb(SMBHSTSTS); - for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) { - delay1000(); - temp = inb(SMBHSTSTS); - } - if (timeout >= MAX_TIMEOUT) { - return -2; - } - if ( temp & ALI15X3_STS_ERR ){ - return -3; - } - return 0; -} - -static struct resource heartbeat_resources[] = { - [0] = { - .start = 0xa2000000, - .end = 0xa2000000, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device heartbeat_device = { - .name = "heartbeat", - .id = -1, - .num_resources = ARRAY_SIZE(heartbeat_resources), - .resource = heartbeat_resources, -}; - -static struct platform_device *mpc1211_devices[] __initdata = { - &heartbeat_device, -}; - -static int __init mpc1211_devices_setup(void) -{ - return platform_add_devices(mpc1211_devices, - ARRAY_SIZE(mpc1211_devices)); -} -__initcall(mpc1211_devices_setup); - -/* arch/sh/boards/mpc1211/rtc.c */ -void mpc1211_time_init(void); - -static void __init mpc1211_setup(char **cmdline_p) -{ - unsigned char spd_buf[128]; - - __set_io_port_base(PA_PCI_IO); - - pci_write_config(0,0,0,0x54, 0xb0b00000); - - do { - outb(ALI15X3_ABORT, SMBHSTCNT); - spd_buf[0] = 0x0c; - spd_buf[1] = 0x43; - spd_buf[2] = 0x7f; - spd_buf[3] = 0x03; - spd_buf[4] = 0x00; - spd_buf[5] = 0x03; - spd_buf[6] = 0x00; - } while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0); - - board_time_init = mpc1211_time_init; - - return 0; -} - -/* - * The Machine Vector - */ -static struct sh_machine_vector mv_mpc1211 __initmv = { - .mv_name = "Interface MPC-1211(CTP/PCI/MPC-SH02)", - .mv_setup = mpc1211_setup, - .mv_nr_irqs = 48, - .mv_irq_demux = mpc1211_irq_demux, - .mv_init_irq = init_mpc1211_IRQ, -}; diff --git a/arch/sh/boards/renesas/migor/setup.c b/arch/sh/boards/renesas/migor/setup.c index e7c150d..01af442 100644 --- a/arch/sh/boards/renesas/migor/setup.c +++ b/arch/sh/boards/renesas/migor/setup.c @@ -14,6 +14,7 @@ #include <linux/mtd/physmap.h> #include <linux/mtd/nand.h> #include <linux/i2c.h> +#include <linux/smc91x.h> #include <asm/machvec.h> #include <asm/io.h> #include <asm/sh_keysc.h> @@ -27,6 +28,11 @@ * 0x18000000 8GB 8 NAND Flash (K9K8G08U0A) */ +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT, + .irq_flags = IRQF_TRIGGER_HIGH, +}; + static struct resource smc91x_eth_resources[] = { [0] = { .name = "SMC91C111" , @@ -36,7 +42,7 @@ static struct resource smc91x_eth_resources[] = { }, [1] = { .start = 32, /* IRQ0 */ - .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, + .flags = IORESOURCE_IRQ, }, }; @@ -44,6 +50,9 @@ static struct platform_device smc91x_eth_device = { .name = "smc91x", .num_resources = ARRAY_SIZE(smc91x_eth_resources), .resource = smc91x_eth_resources, + .dev = { + .platform_data = &smc91x_info, + }, }; static struct sh_keysc_info sh_keysc_info = { diff --git a/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c b/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c index 68f0ad1..ae1cfcb 100644 --- a/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c +++ b/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c @@ -62,7 +62,7 @@ static unsigned char irl2irq[HL_NR_IRL] __initdata = { static DECLARE_INTC_DESC(intc_desc, "r7780mp", vectors, NULL, mask_registers, NULL, NULL); -unsigned char * __init highlander_init_irq_r7780mp(void) +unsigned char * __init highlander_plat_irq_setup(void) { if ((ctrl_inw(0xa4000700) & 0xf000) == 0x2000) { printk(KERN_INFO "Using r7780mp interrupt controller.\n"); diff --git a/arch/sh/boards/renesas/r7780rp/irq-r7780rp.c b/arch/sh/boards/renesas/r7780rp/irq-r7780rp.c index bd34048..9d3921f 100644 --- a/arch/sh/boards/renesas/r7780rp/irq-r7780rp.c +++ b/arch/sh/boards/renesas/r7780rp/irq-r7780rp.c @@ -55,7 +55,7 @@ static unsigned char irl2irq[HL_NR_IRL] __initdata = { static DECLARE_INTC_DESC(intc_desc, "r7780rp", vectors, NULL, mask_registers, NULL, NULL); -unsigned char * __init highlander_init_irq_r7780rp(void) +unsigned char * __init highlander_plat_irq_setup(void) { if (ctrl_inw(0xa5000600)) { printk(KERN_INFO "Using r7780rp interrupt controller.\n"); diff --git a/arch/sh/boards/renesas/r7780rp/irq-r7785rp.c b/arch/sh/boards/renesas/r7780rp/irq-r7785rp.c index bf7ec10..896c045 100644 --- a/arch/sh/boards/renesas/r7780rp/irq-r7785rp.c +++ b/arch/sh/boards/renesas/r7780rp/irq-r7785rp.c @@ -64,7 +64,7 @@ static unsigned char irl2irq[HL_NR_IRL] __initdata = { static DECLARE_INTC_DESC(intc_desc, "r7785rp", vectors, NULL, mask_registers, NULL, NULL); -unsigned char * __init highlander_init_irq_r7785rp(void) +unsigned char * __init highlander_plat_irq_setup(void) { if ((ctrl_inw(0xa4000158) & 0xf000) != 0x1000) return NULL; diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c index ac0a965..bc79afb 100644 --- a/arch/sh/boards/renesas/r7780rp/setup.c +++ b/arch/sh/boards/renesas/r7780rp/setup.c @@ -316,7 +316,7 @@ static void __init highlander_setup(char **cmdline_p) static unsigned char irl2irq[HL_NR_IRL]; -int highlander_irq_demux(int irq) +static int highlander_irq_demux(int irq) { if (irq >= HL_NR_IRL || !irl2irq[irq]) return irq; @@ -324,27 +324,9 @@ int highlander_irq_demux(int irq) return irl2irq[irq]; } -void __init highlander_init_irq(void) +static void __init highlander_init_irq(void) { - unsigned char *ucp = NULL; - - do { -#ifdef CONFIG_SH_R7780MP - ucp = highlander_init_irq_r7780mp(); - if (ucp) - break; -#endif -#ifdef CONFIG_SH_R7785RP - ucp = highlander_init_irq_r7785rp(); - if (ucp) - break; -#endif -#ifdef CONFIG_SH_R7780RP - ucp = highlander_init_irq_r7780rp(); - if (ucp) - break; -#endif - } while (0); + unsigned char *ucp = highlander_plat_irq_setup(); if (ucp) { plat_irq_setup_pins(IRQ_MODE_IRL3210); diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c index f21ee49..452d0d6 100644 --- a/arch/sh/boards/renesas/rts7751r2d/setup.c +++ b/arch/sh/boards/renesas/rts7751r2d/setup.c @@ -109,7 +109,6 @@ static struct platform_device heartbeat_device = { .resource = heartbeat_resources, }; -#ifdef CONFIG_MFD_SM501 static struct plat_serial8250_port uart_platform_data[] = { { .membase = (void __iomem *)0xb3e30000, @@ -208,13 +207,9 @@ static struct platform_device sm501_device = { .resource = sm501_resources, }; -#endif /* CONFIG_MFD_SM501 */ - static struct platform_device *rts7751r2d_devices[] __initdata = { -#ifdef CONFIG_MFD_SM501 &uart_device, &sm501_device, -#endif &heartbeat_device, &spi_sh_sci_device, }; @@ -234,7 +229,9 @@ static int __init rts7751r2d_devices_setup(void) { if (register_trapped_io(&cf_trapped_io) == 0) platform_device_register(&cf_ide_device); + spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus)); + return platform_add_devices(rts7751r2d_devices, ARRAY_SIZE(rts7751r2d_devices)); } diff --git a/arch/sh/boards/se/7206/setup.c b/arch/sh/boards/se/7206/setup.c index 5b3ee08..4fe84cc 100644 --- a/arch/sh/boards/se/7206/setup.c +++ b/arch/sh/boards/se/7206/setup.c @@ -3,12 +3,13 @@ * linux/arch/sh/boards/se/7206/setup.c * * Copyright (C) 2006 Yoshinori Sato - * Copyright (C) 2007 Paul Mundt + * Copyright (C) 2007 - 2008 Paul Mundt * * Hitachi 7206 SolutionEngine Support. */ #include <linux/init.h> #include <linux/platform_device.h> +#include <linux/smc91x.h> #include <asm/se7206.h> #include <asm/io.h> #include <asm/machvec.h> @@ -16,8 +17,9 @@ static struct resource smc91x_resources[] = { [0] = { - .start = 0x300, - .end = 0x300 + 0x020 - 1, + .name = "smc91x-regs", + .start = PA_SMSC + 0x300, + .end = PA_SMSC + 0x300 + 0x020 - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -27,9 +29,18 @@ static struct resource smc91x_resources[] = { }, }; +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT, +}; + static struct platform_device smc91x_device = { .name = "smc91x", .id = -1, + .dev = { + .dma_mask = NULL, + .coherent_dma_mask = 0xffffffff, + .platform_data = &smc91x_info, + }, .num_resources = ARRAY_SIZE(smc91x_resources), .resource = smc91x_resources, }; diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c index 33f6ee7..ede3957 100644 --- a/arch/sh/boards/se/7722/setup.c +++ b/arch/sh/boards/se/7722/setup.c @@ -14,6 +14,7 @@ #include <linux/platform_device.h> #include <linux/ata_platform.h> #include <linux/input.h> +#include <linux/smc91x.h> #include <asm/machvec.h> #include <asm/se7722.h> #include <asm/io.h> @@ -44,6 +45,10 @@ static struct platform_device heartbeat_device = { }; /* SMC91x */ +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT, +}; + static struct resource smc91x_eth_resources[] = { [0] = { .name = "smc91x-regs" , @@ -64,6 +69,7 @@ static struct platform_device smc91x_eth_device = { .dev = { .dma_mask = NULL, /* don't use dma */ .coherent_dma_mask = 0xffffffff, + .platform_data = &smc91x_info, }, .num_resources = ARRAY_SIZE(smc91x_eth_resources), .resource = smc91x_eth_resources, diff --git a/arch/sh/boot/compressed/Makefile_32 b/arch/sh/boot/compressed/Makefile_32 index 6ac8d4a..c0d25fb 100644 --- a/arch/sh/boot/compressed/Makefile_32 +++ b/arch/sh/boot/compressed/Makefile_32 @@ -6,7 +6,6 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz \ head_32.o misc_32.o piggy.o -EXTRA_AFLAGS := -traditional OBJECTS = $(obj)/head_32.o $(obj)/misc_32.o diff --git a/arch/sh/boot/compressed/Makefile_64 b/arch/sh/boot/compressed/Makefile_64 index 4334f2b..912f3e2 100644 --- a/arch/sh/boot/compressed/Makefile_64 +++ b/arch/sh/boot/compressed/Makefile_64 @@ -13,7 +13,6 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz \ head_64.o misc_64.o cache.o piggy.o -EXTRA_AFLAGS := -traditional OBJECTS := $(obj)/vmlinux_64.lds $(obj)/head_64.o $(obj)/misc_64.o \ $(obj)/cache.o diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c index d6e0e2b..de45c6a 100644 --- a/arch/sh/kernel/cpu/irq/intc-sh5.c +++ b/arch/sh/kernel/cpu/irq/intc-sh5.c @@ -184,9 +184,8 @@ int intc_irq_describe(char* p, int irq) void __init plat_irq_setup(void) { - unsigned long long __dummy0, __dummy1=~0x00000000100000f0; + unsigned long long __dummy0, __dummy1=~0x00000000100000f0; unsigned long reg; - unsigned long data; int i; intc_virt = onchip_remap(INTC_BASE, 1024, "INTC"); @@ -196,11 +195,8 @@ void __init plat_irq_setup(void) /* Set default: per-line enable/disable, priority driven ack/eoi */ - for (i = 0; i < NR_INTC_IRQS; i++) { - if (platform_int_priority[i] != NO_PRIORITY) { - irq_desc[i].chip = &intc_irq_type; - } - } + for (i = 0; i < NR_INTC_IRQS; i++) + irq_desc[i].chip = &intc_irq_type; /* Disable all interrupts and set all priorities to 0 to avoid trouble */ @@ -211,35 +207,42 @@ void __init plat_irq_setup(void) ctrl_outl( NO_PRIORITY, reg); - /* Set IRLM */ - /* If all the priorities are set to 'no priority', then - * assume we are using encoded mode. - */ - irlm = platform_int_priority[IRQ_IRL0] + platform_int_priority[IRQ_IRL1] + \ - platform_int_priority[IRQ_IRL2] + platform_int_priority[IRQ_IRL3]; - - if (irlm == NO_PRIORITY) { - /* IRLM = 0 */ - reg = INTC_ICR_CLEAR; - i = IRQ_INTA; - printk("Trying to use encoded IRL0-3. IRLs unsupported.\n"); - } else { - /* IRLM = 1 */ - reg = INTC_ICR_SET; - i = IRQ_IRL0; - } - ctrl_outl(INTC_ICR_IRLM, reg); - - /* Set interrupt priorities according to platform description */ - for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { - data |= platform_int_priority[i] << ((i % INTC_INTPRI_PPREG) * 4); - if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { - /* Upon the 7th, set Priority Register */ - ctrl_outl(data, reg); - data = 0; - reg += 8; +#ifdef CONFIG_SH_CAYMAN + { + unsigned long data; + + /* Set IRLM */ + /* If all the priorities are set to 'no priority', then + * assume we are using encoded mode. + */ + irlm = platform_int_priority[IRQ_IRL0] + + platform_int_priority[IRQ_IRL1] + + platform_int_priority[IRQ_IRL2] + + platform_int_priority[IRQ_IRL3]; + if (irlm == NO_PRIORITY) { + /* IRLM = 0 */ + reg = INTC_ICR_CLEAR; + i = IRQ_INTA; + printk("Trying to use encoded IRL0-3. IRLs unsupported.\n"); + } else { + /* IRLM = 1 */ + reg = INTC_ICR_SET; + i = IRQ_IRL0; } - } + ctrl_outl(INTC_ICR_IRLM, reg); + + /* Set interrupt priorities according to platform description */ + for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { + data |= platform_int_priority[i] << + ((i % INTC_INTPRI_PPREG) * 4); + if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { + /* Upon the 7th, set Priority Register */ + ctrl_outl(data, reg); + data = 0; + reg += 8; + } + } +#endif /* * And now let interrupts come in. diff --git a/arch/sh/kernel/cpu/irq/intc.c b/arch/sh/kernel/cpu/irq/intc.c index 84806b2..da5dae7 100644 --- a/arch/sh/kernel/cpu/irq/intc.c +++ b/arch/sh/kernel/cpu/irq/intc.c @@ -1,7 +1,7 @@ /* * Shared interrupt handling code for IPR and INTC2 types of IRQs. * - * Copyright (C) 2007 Magnus Damm + * Copyright (C) 2007, 2008 Magnus Damm * * Based on intc2.c and ipr.c * @@ -62,6 +62,9 @@ struct intc_desc_int { #endif static unsigned int intc_prio_level[NR_IRQS]; /* for now */ +#ifdef CONFIG_CPU_SH3 +static unsigned long ack_handle[NR_IRQS]; +#endif static inline struct intc_desc_int *get_intc_desc(unsigned int irq) { @@ -98,17 +101,26 @@ static void write_32(unsigned long addr, unsigned long h, unsigned long data) static void modify_8(unsigned long addr, unsigned long h, unsigned long data) { + unsigned long flags; + local_irq_save(flags); ctrl_outb(set_field(ctrl_inb(addr), data, h), addr); + local_irq_restore(flags); } static void modify_16(unsigned long addr, unsigned long h, unsigned long data) { + unsigned long flags; + local_irq_save(flags); ctrl_outw(set_field(ctrl_inw(addr), data, h), addr); + local_irq_restore(flags); } static void modify_32(unsigned long addr, unsigned long h, unsigned long data) { + unsigned long flags; + local_irq_save(flags); ctrl_outl(set_field(ctrl_inl(addr), data, h), addr); + local_irq_restore(flags); } enum { REG_FN_ERR = 0, REG_FN_WRITE_BASE = 1, REG_FN_MODIFY_BASE = 5 }; @@ -219,6 +231,25 @@ static void intc_disable(unsigned int irq) } } +#ifdef CONFIG_CPU_SH3 +static void intc_mask_ack(unsigned int irq) +{ + struct intc_desc_int *d = get_intc_desc(irq); + unsigned long handle = ack_handle[irq]; + unsigned long addr; + + intc_disable(irq); + + /* read register and write zero only to the assocaited bit */ + + if (handle) { + addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); + ctrl_inb(addr); + ctrl_outb(0x3f ^ set_field(0, 1, handle), addr); + } +} +#endif + static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, unsigned int nr_hp, unsigned int irq) @@ -280,7 +311,12 @@ static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { [IRQ_TYPE_EDGE_FALLING] = VALID(0), [IRQ_TYPE_EDGE_RISING] = VALID(1), [IRQ_TYPE_LEVEL_LOW] = VALID(2), + /* SH7706, SH7707 and SH7709 do not support high level triggered */ +#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \ + !defined(CONFIG_CPU_SUBTYPE_SH7707) && \ + !defined(CONFIG_CPU_SUBTYPE_SH7709) [IRQ_TYPE_LEVEL_HIGH] = VALID(3), +#endif }; static int intc_set_sense(unsigned int irq, unsigned int type) @@ -430,6 +466,40 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc, return 0; } +#ifdef CONFIG_CPU_SH3 +static unsigned int __init intc_ack_data(struct intc_desc *desc, + struct intc_desc_int *d, + intc_enum enum_id) +{ + struct intc_mask_reg *mr = desc->ack_regs; + unsigned int i, j, fn, mode; + unsigned long reg_e, reg_d; + + for (i = 0; mr && enum_id && i < desc->nr_ack_regs; i++) { + mr = desc->ack_regs + i; + + for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) { + if (mr->enum_ids[j] != enum_id) + continue; + + fn = REG_FN_MODIFY_BASE; + mode = MODE_ENABLE_REG; + reg_e = mr->set_reg; + reg_d = mr->set_reg; + + fn += (mr->reg_width >> 3) - 1; + return _INTC_MK(fn, mode, + intc_get_reg(d, reg_e), + intc_get_reg(d, reg_d), + 1, + (mr->reg_width - 1) - j); + } + } + + return 0; +} +#endif + static unsigned int __init intc_sense_data(struct intc_desc *desc, struct intc_desc_int *d, intc_enum enum_id) @@ -530,6 +600,11 @@ static void __init intc_register_irq(struct intc_desc *desc, /* irq should be disabled by default */ d->chip.mask(irq); + +#ifdef CONFIG_CPU_SH3 + if (desc->ack_regs) + ack_handle[irq] = intc_ack_data(desc, d, enum_id); +#endif } static unsigned int __init save_reg(struct intc_desc_int *d, @@ -560,6 +635,9 @@ void __init register_intc_controller(struct intc_desc *desc) d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0; d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0; +#ifdef CONFIG_CPU_SH3 + d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0; +#endif d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg)); #ifdef CONFIG_SMP d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp)); @@ -592,14 +670,23 @@ void __init register_intc_controller(struct intc_desc *desc) } } - BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ - d->chip.name = desc->name; d->chip.mask = intc_disable; d->chip.unmask = intc_enable; d->chip.mask_ack = intc_disable; d->chip.set_type = intc_set_sense; +#ifdef CONFIG_CPU_SH3 + if (desc->ack_regs) { + for (i = 0; i < desc->nr_ack_regs; i++) + k += save_reg(d, k, desc->ack_regs[i].set_reg, 0); + + d->chip.mask_ack = intc_mask_ack; + } +#endif + + BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ + for (i = 0; i < desc->nr_vectors; i++) { struct intc_vect *vect = desc->vectors + i; diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c index 5627c0b..6df2fb9 100644 --- a/arch/sh/kernel/cpu/sh2a/fpu.c +++ b/arch/sh/kernel/cpu/sh2a/fpu.c @@ -300,7 +300,7 @@ static int denormal_addf(int hx, int hy) iy = hy & 0x7fffffff; if (iy < 0x00800000) { ix = denormal_subf1(ix, iy); - if (ix < 0) { + if ((int) ix < 0) { ix = -ix; sign ^= 0x80000000; } @@ -385,7 +385,7 @@ static long long denormal_addd(long long hx, long long hy) iy = hy & 0x7fffffffffffffffLL; if (iy < 0x0010000000000000LL) { ix = denormal_subd1(ix, iy); - if (ix < 0) { + if ((int) ix < 0) { ix = -ix; sign ^= 0x8000000000000000LL; } diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index 3ae4d91..511de55 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux/SuperH SH-3 backends. # -obj-y := ex.o probe.o entry.o +obj-y := ex.o probe.o entry.o setup-sh3.o # CPU subtype setup obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o diff --git a/arch/sh/kernel/cpu/sh3/setup-sh3.c b/arch/sh/kernel/cpu/sh3/setup-sh3.c new file mode 100644 index 0000000..c988468 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/setup-sh3.c @@ -0,0 +1,71 @@ +/* + * Shared SH3 Setup code + * + * Copyright (C) 2008 Magnus Damm + * + * 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. + */ + +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/io.h> + +/* All SH3 devices are equipped with IRQ0->5 (except sh7708) */ + +enum { + UNUSED = 0, + + /* interrupt sources */ + IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, +}; + +static struct intc_vect vectors_irq0123[] __initdata = { + INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), + INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), +}; + +static struct intc_vect vectors_irq45[] __initdata = { + INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), +}; + +static struct intc_prio_reg prio_registers[] __initdata = { + { 0xa4000016, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } }, + { 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } }, +}; + +static struct intc_mask_reg ack_registers[] __initdata = { + { 0xa4000004, 0, 8, /* IRR0 */ + { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } }, +}; + +static struct intc_sense_reg sense_registers[] __initdata = { + { 0xa4000010, 16, 2, { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } }, +}; + +static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh3-irq0123", + vectors_irq0123, NULL, NULL, + prio_registers, sense_registers, ack_registers); + +static DECLARE_INTC_DESC_ACK(intc_desc_irq45, "sh3-irq45", + vectors_irq45, NULL, NULL, + prio_registers, sense_registers, ack_registers); + +#define INTC_ICR1 0xa4000010UL +#define INTC_ICR1_IRQLVL (1<<14) + +void __init plat_irq_setup_pins(int mode) +{ + if (mode == IRQ_MODE_IRQ) { + ctrl_outw(ctrl_inw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1); + register_intc_controller(&intc_desc_irq0123); + return; + } + BUG(); +} + +void __init plat_irq_setup_sh3(void) +{ + register_intc_controller(&intc_desc_irq45); +} diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c index f581534..6468ae8 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c @@ -37,7 +37,7 @@ enum { }; static struct intc_vect vectors[] __initdata = { - INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), + /* IRQ0->5 are handled in setup-sh3.c */ INTC_VECT(PINT07, 0x700), INTC_VECT(PINT815, 0x720), INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820), INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860), @@ -48,7 +48,7 @@ static struct intc_vect vectors[] __initdata = { INTC_VECT(ADC_ADI, 0x980), INTC_VECT(USB_USI0, 0xa20), INTC_VECT(USB_USI1, 0xa40), INTC_VECT(TPU0, 0xc00), INTC_VECT(TPU1, 0xc20), - INTC_VECT(TPU3, 0xc80), INTC_VECT(TPU1, 0xca0), + INTC_VECT(TPU2, 0xc80), INTC_VECT(TPU3, 0xca0), INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460), INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0), @@ -81,14 +81,6 @@ static struct intc_prio_reg prio_registers[] __initdata = { static DECLARE_INTC_DESC(intc_desc, "sh7705", vectors, groups, NULL, prio_registers, NULL); -static struct intc_vect vectors_irq[] __initdata = { - INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), - INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), -}; - -static DECLARE_INTC_DESC(intc_desc_irq, "sh7705-irq", vectors_irq, NULL, - NULL, prio_registers, NULL); - static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xa4410000, @@ -159,16 +151,8 @@ static int __init sh7705_devices_setup(void) } __initcall(sh7705_devices_setup); -void __init plat_irq_setup_pins(int mode) -{ - if (mode == IRQ_MODE_IRQ) { - register_intc_controller(&intc_desc_irq); - return; - } - BUG(); -} - void __init plat_irq_setup(void) { register_intc_controller(&intc_desc); + plat_irq_setup_sh3(); } diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c index d3733b1..93c55e2 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c @@ -52,7 +52,7 @@ static struct intc_vect vectors[] __initdata = { #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ defined(CONFIG_CPU_SUBTYPE_SH7707) || \ defined(CONFIG_CPU_SUBTYPE_SH7709) - INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), + /* IRQ0->5 are handled in setup-sh3.c */ INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820), INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860), INTC_VECT(ADC_ADI, 0x980), @@ -104,18 +104,6 @@ static struct intc_prio_reg prio_registers[] __initdata = { static DECLARE_INTC_DESC(intc_desc, "sh770x", vectors, groups, NULL, prio_registers, NULL); -#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) -static struct intc_vect vectors_irq[] __initdata = { - INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), - INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), -}; - -static DECLARE_INTC_DESC(intc_desc_irq, "sh770x-irq", vectors_irq, NULL, - NULL, prio_registers, NULL); -#endif - static struct resource rtc_resources[] = { [0] = { .start = 0xfffffec0, @@ -194,24 +182,12 @@ static int __init sh770x_devices_setup(void) } __initcall(sh770x_devices_setup); -#define INTC_ICR1 0xa4000010UL -#define INTC_ICR1_IRQLVL (1<<14) - -void __init plat_irq_setup_pins(int mode) +void __init plat_irq_setup(void) { - if (mode == IRQ_MODE_IRQ) { + register_intc_controller(&intc_desc); #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ defined(CONFIG_CPU_SUBTYPE_SH7707) || \ defined(CONFIG_CPU_SUBTYPE_SH7709) - ctrl_outw(ctrl_inw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1); - register_intc_controller(&intc_desc_irq); - return; + plat_irq_setup_sh3(); #endif - } - BUG(); -} - -void __init plat_irq_setup(void) -{ - register_intc_controller(&intc_desc); } diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c index 7406c9a..77eee48 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c @@ -38,7 +38,7 @@ enum { }; static struct intc_vect vectors[] __initdata = { - INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), + /* IRQ0->5 are handled in setup-sh3.c */ INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820), INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860), INTC_VECT(SCIF0_ERI, 0x880), INTC_VECT(SCIF0_RXI, 0x8a0), @@ -79,10 +79,7 @@ static struct intc_prio_reg prio_registers[] __initdata = { { 0xa4000016, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } }, { 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } }, { 0xa400001a, 0, 16, 4, /* IPRE */ { DMAC1, SCIF0, SCIF1 } }, - { 0xa4080000, 0, 16, 4, /* IPRF */ { 0, DMAC2 } }, -#ifdef CONFIG_CPU_SUBTYPE_SH7710 - { 0xa4080000, 0, 16, 4, /* IPRF */ { IPSEC } }, -#endif + { 0xa4080000, 0, 16, 4, /* IPRF */ { IPSEC, DMAC2 } }, { 0xa4080002, 0, 16, 4, /* IPRG */ { EDMAC0, EDMAC1, EDMAC2 } }, { 0xa4080004, 0, 16, 4, /* IPRH */ { 0, 0, 0, SIOF0 } }, { 0xa4080006, 0, 16, 4, /* IPRI */ { 0, 0, SIOF1 } }, @@ -91,14 +88,6 @@ static struct intc_prio_reg prio_registers[] __initdata = { static DECLARE_INTC_DESC(intc_desc, "sh7710", vectors, groups, NULL, prio_registers, NULL); -static struct intc_vect vectors_irq[] __initdata = { - INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), - INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), -}; - -static DECLARE_INTC_DESC(intc_desc_irq, "sh7710-irq", vectors_irq, NULL, - NULL, prio_registers, NULL); - static struct resource rtc_resources[] = { [0] = { .start = 0xa413fec0, @@ -170,16 +159,8 @@ static int __init sh7710_devices_setup(void) } __initcall(sh7710_devices_setup); -void __init plat_irq_setup_pins(int mode) -{ - if (mode == IRQ_MODE_IRQ) { - register_intc_controller(&intc_desc_irq); - return; - } - BUG(); -} - void __init plat_irq_setup(void) { register_intc_controller(&intc_desc); + plat_irq_setup_sh3(); } diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c index 8028082..f807a21 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c @@ -19,10 +19,6 @@ #include <linux/serial_sci.h> #include <asm/rtc.h> -#define INTC_ICR1 0xA4140010UL -#define INTC_ICR_IRLM 0x4000 -#define INTC_ICR_IRQ (~INTC_ICR_IRLM) - static struct resource rtc_resources[] = { [0] = { .start = 0xa413fec0, @@ -170,6 +166,7 @@ enum { }; static struct intc_vect vectors[] __initdata = { + /* IRQ0->5 are handled in setup-sh3.c */ INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), INTC_VECT(TMU2, 0x440), INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0), INTC_VECT(RTC_CUI, 0x4c0), @@ -214,11 +211,7 @@ static struct intc_prio_reg prio_registers[] __initdata = { { 0xA414FEE4UL, 0, 16, 4, /* IPRB */ { WDT, REF_RCMI, SIM, 0 } }, { 0xA4140016UL, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } }, { 0xA4140018UL, 0, 16, 4, /* IPRD */ { USBF_SPD, TMU_SUNI, IRQ5, IRQ4 } }, -#if defined(CONFIG_CPU_SUBTYPE_SH7720) { 0xA414001AUL, 0, 16, 4, /* IPRE */ { DMAC1, 0, LCDC, SSL } }, -#else - { 0xA414001AUL, 0, 16, 4, /* IPRE */ { DMAC1, 0, LCDC, 0 } }, -#endif { 0xA4080000UL, 0, 16, 4, /* IPRF */ { ADC, DMAC2, USBFI, CMT } }, { 0xA4080002UL, 0, 16, 4, /* IPRG */ { SCIF0, SCIF1, 0, 0 } }, { 0xA4080004UL, 0, 16, 4, /* IPRH */ { PINT07, PINT815, TPU, IIC } }, @@ -229,32 +222,8 @@ static struct intc_prio_reg prio_registers[] __initdata = { static DECLARE_INTC_DESC(intc_desc, "sh7720", vectors, groups, NULL, prio_registers, NULL); -static struct intc_sense_reg sense_registers[] __initdata = { - { INTC_ICR1, 16, 2, { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } }, -}; - -static struct intc_vect vectors_irq[] __initdata = { - INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), - INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), - INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), -}; - -static DECLARE_INTC_DESC(intc_irq_desc, "sh7720-irq", vectors_irq, - NULL, NULL, prio_registers, sense_registers); - -void __init plat_irq_setup_pins(int mode) -{ - switch (mode) { - case IRQ_MODE_IRQ: - ctrl_outw(ctrl_inw(INTC_ICR1) & INTC_ICR_IRQ, INTC_ICR1); - register_intc_controller(&intc_irq_desc); - break; - default: - BUG(); - } -} - void __init plat_irq_setup(void) { register_intc_controller(&intc_desc); + plat_irq_setup_sh3(); } diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index ba87501..05372ed 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S @@ -143,12 +143,22 @@ resvec_save_area: trap_jtable: .long do_exception_error /* 0x000 */ .long do_exception_error /* 0x020 */ +#ifdef CONFIG_MMU .long tlb_miss_load /* 0x040 */ .long tlb_miss_store /* 0x060 */ +#else + .long do_exception_error + .long do_exception_error +#endif ! ARTIFICIAL pseudo-EXPEVT setting .long do_debug_interrupt /* 0x080 */ +#ifdef CONFIG_MMU .long tlb_miss_load /* 0x0A0 */ .long tlb_miss_store /* 0x0C0 */ +#else + .long do_exception_error + .long do_exception_error +#endif .long do_address_error_load /* 0x0E0 */ .long do_address_error_store /* 0x100 */ #ifdef CONFIG_SH_FPU @@ -185,10 +195,18 @@ trap_jtable: .endr .long do_IRQ /* 0xA00 */ .long do_IRQ /* 0xA20 */ +#ifdef CONFIG_MMU .long itlb_miss_or_IRQ /* 0xA40 */ +#else + .long do_IRQ +#endif .long do_IRQ /* 0xA60 */ .long do_IRQ /* 0xA80 */ +#ifdef CONFIG_MMU .long itlb_miss_or_IRQ /* 0xAA0 */ +#else + .long do_IRQ +#endif .long do_exception_error /* 0xAC0 */ .long do_address_error_exec /* 0xAE0 */ .rept 8 @@ -274,6 +292,7 @@ not_a_tlb_miss: * Instead of '.space 1024-TEXT_SIZE' place the RESVEC * block making sure the final alignment is correct. */ +#ifdef CONFIG_MMU tlb_miss: synco /* TAKum03020 (but probably a good idea anyway.) */ putcon SP, KCR1 @@ -377,6 +396,9 @@ fixup_to_invoke_general_handler: getcon KCR1, SP pta handle_exception, tr0 blink tr0, ZERO +#else /* CONFIG_MMU */ + .balign 256 +#endif /* NB TAKE GREAT CARE HERE TO ENSURE THAT THE INTERRUPT CODE DOES END UP AT VBR+0x600 */ @@ -1103,6 +1125,7 @@ restore_all: * fpu_error_or_IRQ? is a helper to deflect to the right cause. * */ +#ifdef CONFIG_MMU tlb_miss_load: or SP, ZERO, r2 or ZERO, ZERO, r3 /* Read */ @@ -1132,6 +1155,7 @@ call_do_page_fault: movi do_page_fault, r6 ptabs r6, tr0 blink tr0, ZERO +#endif /* CONFIG_MMU */ fpu_error_or_IRQA: pta its_IRQ, tr0 @@ -1481,6 +1505,7 @@ poke_real_address_q: ptabs LINK, tr0 blink tr0, r63 +#ifdef CONFIG_MMU /* * --- User Access Handling Section */ @@ -1604,6 +1629,7 @@ ___clear_user_exit: ptabs LINK, tr0 blink tr0, ZERO +#endif /* CONFIG_MMU */ /* * int __strncpy_from_user(unsigned long __dest, unsigned long __src, @@ -2014,9 +2040,11 @@ sa_default_restorer: .global asm_uaccess_start /* Just a marker */ asm_uaccess_start: +#ifdef CONFIG_MMU .long ___copy_user1, ___copy_user_exit .long ___copy_user2, ___copy_user_exit .long ___clear_user1, ___clear_user_exit +#endif .long ___strncpy_from_user1, ___strncpy_from_user_exit .long ___strnlen_user1, ___strnlen_user_exit .long ___get_user_asm_b1, ___get_user_asm_b_exit diff --git a/arch/sh/kernel/cpu/sh5/probe.c b/arch/sh/kernel/cpu/sh5/probe.c index 31f8cb0..92ad844 100644 --- a/arch/sh/kernel/cpu/sh5/probe.c +++ b/arch/sh/kernel/cpu/sh5/probe.c @@ -15,6 +15,7 @@ #include <linux/string.h> #include <asm/processor.h> #include <asm/cache.h> +#include <asm/tlb.h> int __init detect_cpu_and_cache_system(void) { @@ -67,5 +68,8 @@ int __init detect_cpu_and_cache_system(void) set_bit(SH_CACHE_MODE_WB, &(boot_cpu_data.dcache.flags)); #endif + /* Setup some I/D TLB defaults */ + sh64_tlb_init(); + return 0; } diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c index 957f2561..6b7d166 100644 --- a/arch/sh/kernel/early_printk.c +++ b/arch/sh/kernel/early_printk.c @@ -141,7 +141,9 @@ static void scif_sercon_init(char *s) */ static void scif_sercon_init(char *s) { + struct uart_port *port = &scif_port; unsigned baud = DEFAULT_BAUD; + unsigned int status; char *e; if (*s == ',') @@ -160,19 +162,25 @@ static void scif_sercon_init(char *s) baud = DEFAULT_BAUD; } - ctrl_outw(0, scif_port.mapbase + 8); - ctrl_outw(0, scif_port.mapbase); + do { + status = sci_in(port, SCxSR); + } while (!(status & SCxSR_TEND(port))); + + sci_out(port, SCSCR, 0); /* TE=0, RE=0 */ + sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); + sci_out(port, SCSMR, 0); /* Set baud rate */ - ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) / - (32 * baud) - 1, scif_port.mapbase + 4); - - ctrl_outw(12, scif_port.mapbase + 24); - ctrl_outw(8, scif_port.mapbase + 24); - ctrl_outw(0, scif_port.mapbase + 32); - ctrl_outw(0x60, scif_port.mapbase + 16); - ctrl_outw(0, scif_port.mapbase + 36); - ctrl_outw(0x30, scif_port.mapbase + 8); + sci_out(port, SCBRR, (CONFIG_SH_PCLK_FREQ + 16 * baud) / + (32 * baud) - 1); + udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */ + + sci_out(port, SCSPTR, 0); + sci_out(port, SCxSR, 0x60); + sci_out(port, SCLSR, 0); + + sci_out(port, SCFCR, 0); + sci_out(port, SCSCR, 0x30); /* TE=1, RE=1 */ } #endif /* defined(CONFIG_CPU_SUBTYPE_SH7720) */ #endif /* !defined(CONFIG_SH_STANDARD_BIOS) */ diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 284f66f..516bde9 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -53,6 +53,7 @@ EXPORT_SYMBOL(cpu_data); * sh_mv= on the command line, prior to .machvec.init teardown. */ struct sh_machine_vector sh_mv = { .mv_name = "generic", }; +EXPORT_SYMBOL(sh_mv); #ifdef CONFIG_VT struct screen_info screen_info; @@ -76,11 +77,18 @@ static struct resource data_resource = { .flags = IORESOURCE_BUSY | IORESOURCE_MEM, }; +static struct resource bss_resource = { + .name = "Kernel bss", + .flags = IORESOURCE_BUSY | IORESOURCE_MEM, +}; + unsigned long memory_start; EXPORT_SYMBOL(memory_start); unsigned long memory_end = 0; EXPORT_SYMBOL(memory_end); +static struct resource mem_resources[MAX_NUMNODES]; + int l1i_cache_shape, l1d_cache_shape, l2_cache_shape; static int __init early_parse_mem(char *p) @@ -169,6 +177,40 @@ static inline void __init reserve_crashkernel(void) {} #endif +void __init __add_active_range(unsigned int nid, unsigned long start_pfn, + unsigned long end_pfn) +{ + struct resource *res = &mem_resources[nid]; + + WARN_ON(res->name); /* max one active range per node for now */ + + res->name = "System RAM"; + res->start = start_pfn << PAGE_SHIFT; + res->end = (end_pfn << PAGE_SHIFT) - 1; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&iomem_resource, res)) { + pr_err("unable to request memory_resource 0x%lx 0x%lx\n", + start_pfn, end_pfn); + return; + } + + /* + * We don't know which RAM region contains kernel data, + * so we try it repeatedly and let the resource manager + * test it. + */ + request_resource(res, &code_resource); + request_resource(res, &data_resource); + request_resource(res, &bss_resource); + +#ifdef CONFIG_KEXEC + if (crashk_res.start != crashk_res.end) + request_resource(res, &crashk_res); +#endif + + add_active_range(nid, start_pfn, end_pfn); +} + void __init setup_bootmem_allocator(unsigned long free_pfn) { unsigned long bootmap_size; @@ -181,7 +223,7 @@ void __init setup_bootmem_allocator(unsigned long free_pfn) bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn, min_low_pfn, max_low_pfn); - add_active_range(0, min_low_pfn, max_low_pfn); + __add_active_range(0, min_low_pfn, max_low_pfn); register_bootmem_low_pages(); node_set_online(0); @@ -267,6 +309,8 @@ void __init setup_arch(char **cmdline_p) code_resource.end = virt_to_phys(_etext)-1; data_resource.start = virt_to_phys(_etext); data_resource.end = virt_to_phys(_edata)-1; + bss_resource.start = virt_to_phys(__bss_start); + bss_resource.end = virt_to_phys(_ebss)-1; memory_start = (unsigned long)__va(__MEMORY_START); if (!memory_end) diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 6d40546..8f91653 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -20,8 +20,6 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); extern struct hw_interrupt_type no_irq_type; -EXPORT_SYMBOL(sh_mv); - /* platform dependent support */ EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(kernel_thread); diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index a310c97..9324d32 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c @@ -16,6 +16,7 @@ #include <linux/in6.h> #include <linux/interrupt.h> #include <linux/screen_info.h> +#include <asm/cacheflush.h> #include <asm/processor.h> #include <asm/uaccess.h> #include <asm/checksum.h> @@ -29,25 +30,50 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(kernel_thread); +#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) +EXPORT_SYMBOL(clear_user_page); +#endif + +#ifndef CONFIG_CACHE_OFF +EXPORT_SYMBOL(flush_dcache_page); +#endif + /* Networking helper routines. */ +EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy_nocheck); +#ifdef CONFIG_IPV6 +EXPORT_SYMBOL(csum_ipv6_magic); +#endif #ifdef CONFIG_VT EXPORT_SYMBOL(screen_info); #endif +EXPORT_SYMBOL(__put_user_asm_b); +EXPORT_SYMBOL(__put_user_asm_w); EXPORT_SYMBOL(__put_user_asm_l); +EXPORT_SYMBOL(__put_user_asm_q); +EXPORT_SYMBOL(__get_user_asm_b); +EXPORT_SYMBOL(__get_user_asm_w); EXPORT_SYMBOL(__get_user_asm_l); +EXPORT_SYMBOL(__get_user_asm_q); +EXPORT_SYMBOL(__strnlen_user); +EXPORT_SYMBOL(__strncpy_from_user); +EXPORT_SYMBOL(clear_page); +EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(__copy_user); EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__ndelay); +EXPORT_SYMBOL(__const_udelay); /* Ugh. These come in from libgcc.a at link time. */ #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) DECLARE_EXPORT(__sdivsi3); +DECLARE_EXPORT(__sdivsi3_2); DECLARE_EXPORT(__muldi3); DECLARE_EXPORT(__udivsi3); +DECLARE_EXPORT(__div_table); diff --git a/arch/sh/kernel/time_64.c b/arch/sh/kernel/time_64.c index 898977e..022a55f 100644 --- a/arch/sh/kernel/time_64.c +++ b/arch/sh/kernel/time_64.c @@ -172,6 +172,7 @@ void do_gettimeofday(struct timeval *tv) tv->tv_sec = sec; tv->tv_usec = usec; } +EXPORT_SYMBOL(do_gettimeofday); int do_settimeofday(struct timespec *tv) { @@ -240,7 +241,7 @@ static inline void do_timer_interrupt(void) * the irq version of write_lock because as just said we have irq * locally disabled. -arca */ - write_lock(&xtime_lock); + write_seqlock(&xtime_lock); asm ("getcon cr62, %0" : "=r" (current_ctc)); ctc_last_interrupt = (unsigned long) current_ctc; @@ -266,7 +267,7 @@ static inline void do_timer_interrupt(void) /* do it again in 60 s */ last_rtc_update = xtime.tv_sec - 600; } - write_unlock(&xtime_lock); + write_sequnlock(&xtime_lock); #ifndef CONFIG_SMP update_process_times(user_mode(get_irq_regs())); diff --git a/arch/sh/lib64/dbg.c b/arch/sh/lib64/dbg.c index 75825ef..2fb8eaf 100644 --- a/arch/sh/lib64/dbg.c +++ b/arch/sh/lib64/dbg.c @@ -186,8 +186,8 @@ void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs) rr->pc = regs->pc; if (sp < stack_bottom + 3092) { - printk("evt_debug : stack underflow report\n"); int i, j; + printk("evt_debug : stack underflow report\n"); for (j=0, i = event_ptr; j<16; j++) { rr = event_ring + i; printk("evt=%08x event=%08x tra=%08x pid=%5d sp=%08lx pc=%08lx\n", diff --git a/arch/sh/mm/Makefile_64 b/arch/sh/mm/Makefile_64 index cbd6aa3..0d92a8a 100644 --- a/arch/sh/mm/Makefile_64 +++ b/arch/sh/mm/Makefile_64 @@ -2,10 +2,11 @@ # Makefile for the Linux SuperH-specific parts of the memory manager. # -obj-y := init.o extable_64.o consistent.o +obj-y := init.o consistent.o -mmu-y := tlb-nommu.o pg-nommu.o -mmu-$(CONFIG_MMU) := fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o +mmu-y := tlb-nommu.o pg-nommu.o extable_32.o +mmu-$(CONFIG_MMU) := fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o \ + extable_64.o ifndef CONFIG_CACHE_OFF obj-y += cache-sh5.o diff --git a/arch/sh/mm/cache-sh5.c b/arch/sh/mm/cache-sh5.c index 3877321..9e277ec 100644 --- a/arch/sh/mm/cache-sh5.c +++ b/arch/sh/mm/cache-sh5.c @@ -714,6 +714,7 @@ void flush_cache_sigtramp(unsigned long vaddr) sh64_icache_inv_current_user_range(vaddr, end); } +#ifdef CONFIG_MMU /* * These *MUST* lie in an area of virtual address space that's otherwise * unused. @@ -830,3 +831,4 @@ void clear_user_page(void *to, unsigned long address, struct page *page) else sh64_clear_user_page_coloured(to, address); } +#endif diff --git a/arch/sh/mm/ioremap_64.c b/arch/sh/mm/ioremap_64.c index cea224c..6e0be24 100644 --- a/arch/sh/mm/ioremap_64.c +++ b/arch/sh/mm/ioremap_64.c @@ -343,6 +343,7 @@ unsigned long onchip_remap(unsigned long phys, unsigned long size, const char *n return shmedia_alloc_io(phys, size, name); } +EXPORT_SYMBOL(onchip_remap); void onchip_unmap(unsigned long vaddr) { @@ -370,6 +371,7 @@ void onchip_unmap(unsigned long vaddr) kfree(res); } } +EXPORT_SYMBOL(onchip_unmap); #ifdef CONFIG_PROC_FS static int diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c index 2de7302..1663199 100644 --- a/arch/sh/mm/numa.c +++ b/arch/sh/mm/numa.c @@ -59,7 +59,7 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end) free_pfn = start_pfn = start >> PAGE_SHIFT; end_pfn = end >> PAGE_SHIFT; - add_active_range(nid, start_pfn, end_pfn); + __add_active_range(nid, start_pfn, end_pfn); /* Node-local pgdat */ NODE_DATA(nid) = pfn_to_kaddr(free_pfn); diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index 987c668..1bba7d3 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -28,7 +28,6 @@ HD64465 HD64465 7751SYSTEMH SH_7751_SYSTEMH HP6XX SH_HP6XX DREAMCAST SH_DREAMCAST -MPC1211 SH_MPC1211 SNAPGEAR SH_SECUREEDGE5410 EDOSK7705 SH_EDOSK7705 SH4202_MICRODEV SH_SH4202_MICRODEV diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 3c31229..36815792 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -245,15 +245,29 @@ static inline int invalid_frame_pointer(void __user *fp, int fplen) static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) { - unsigned long sp; + unsigned long sp = regs->u_regs[UREG_FP]; - sp = regs->u_regs[UREG_FP]; + /* + * If we are on the alternate signal stack and would overflow it, don't. + * Return an always-bogus address instead so we will die with SIGSEGV. + */ + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) + return (void __user *) -1L; /* This is the X/Open sanctioned signal stack switching. */ if (sa->sa_flags & SA_ONSTACK) { - if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7)) + if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } + + /* Always align the stack frame. This handles two cases. First, + * sigaltstack need not be mindful of platform specific stack + * alignment. Second, if we took this signal because the stack + * is not aligned properly, we'd like to take the signal cleanly + * and report that. + */ + sp &= ~7UL; + return (void __user *)(sp - framesize); } diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 45d6bf6..07c0443 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -376,16 +376,29 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) { - unsigned long sp; + unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; - sp = regs->u_regs[UREG_FP] + STACK_BIAS; + /* + * If we are on the alternate signal stack and would overflow it, don't. + * Return an always-bogus address instead so we will die with SIGSEGV. + */ + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) + return (void __user *) -1L; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (!on_sig_stack(sp) && - !((current->sas_ss_sp + current->sas_ss_size) & 7)) + if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } + + /* Always align the stack frame. This handles two cases. First, + * sigaltstack need not be mindful of platform specific stack + * alignment. Second, if we took this signal because the stack + * is not aligned properly, we'd like to take the signal cleanly + * and report that. + */ + sp &= ~7UL; + return (void __user *)(sp - framesize); } diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 9415d2c..0f6b7b1 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -406,11 +406,27 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; sp = regs->u_regs[UREG_FP]; + /* + * If we are on the alternate signal stack and would overflow it, don't. + * Return an always-bogus address instead so we will die with SIGSEGV. + */ + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) + return (void __user *) -1L; + /* This is the X/Open sanctioned signal stack switching. */ if (sa->sa_flags & SA_ONSTACK) { - if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7)) + if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } + + /* Always align the stack frame. This handles two cases. First, + * sigaltstack need not be mindful of platform specific stack + * alignment. Second, if we took this signal because the stack + * is not aligned properly, we'd like to take the signal cleanly + * and report that. + */ + sp &= ~7UL; + return (void __user *)(sp - framesize); } diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 10b86e1..5047490 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -191,9 +191,9 @@ void line_flush_chars(struct tty_struct *tty) line_flush_buffer(tty); } -void line_put_char(struct tty_struct *tty, unsigned char ch) +int line_put_char(struct tty_struct *tty, unsigned char ch) { - line_write(tty, &ch, sizeof(ch)); + return line_write(tty, &ch, sizeof(ch)); } int line_write(struct tty_struct *tty, const unsigned char *buf, int len) diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 1223f2c..979b73e 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -71,7 +71,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init, char **error_out); extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); -extern void line_put_char(struct tty_struct *tty, unsigned char ch); +extern int line_put_char(struct tty_struct *tty, unsigned char ch); extern void line_set_termios(struct tty_struct *tty, struct ktermios * old); extern int line_chars_in_buffer(struct tty_struct *tty); extern void line_flush_buffer(struct tty_struct *tty); diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index bbcafaa..fe361ae 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -335,6 +335,7 @@ config X86_RDC321X select GENERIC_GPIO select LEDS_CLASS select LEDS_GPIO + select NEW_LEDS help This option is needed for RDC R-321x system-on-chip, also known as R-8610-(G). @@ -1662,7 +1663,6 @@ config GEODE_MFGPT_TIMER config OLPC bool "One Laptop Per Child support" - depends on MGEODE_LX default n help Add support for detecting the unique features of the OLPC diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index bbdacb3..5e618c3 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -83,9 +83,7 @@ obj-$(CONFIG_KVM_GUEST) += kvm.o obj-$(CONFIG_KVM_CLOCK) += kvmclock.o obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o -ifdef CONFIG_INPUT_PCSPKR -obj-y += pcspeaker.o -endif +obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o obj-$(CONFIG_SCx200) += scx200.o scx200-y += scx200_32.o diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 238468a..c2e1ce3 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -6,6 +6,7 @@ #include <linux/cpu.h> +#include <asm/pat.h> #include <asm/processor.h> struct cpuid_bit { @@ -48,3 +49,23 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) set_cpu_cap(c, cb->feature); } } + +#ifdef CONFIG_X86_PAT +void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) +{ + switch (c->x86_vendor) { + case X86_VENDOR_AMD: + if (c->x86 >= 0xf && c->x86 <= 0x11) + return; + break; + case X86_VENDOR_INTEL: + if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) + return; + break; + } + + pat_disable(cpu_has_pat ? + "PAT disabled. Not yet verified on this CPU type." : + "PAT not supported by CPU."); +} +#endif diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 35b4f6a..d0463a9 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -12,6 +12,7 @@ #include <asm/mmu_context.h> #include <asm/mtrr.h> #include <asm/mce.h> +#include <asm/pat.h> #ifdef CONFIG_X86_LOCAL_APIC #include <asm/mpspec.h> #include <asm/apic.h> @@ -308,19 +309,6 @@ static void __cpuinit early_get_cap(struct cpuinfo_x86 *c) } - clear_cpu_cap(c, X86_FEATURE_PAT); - - switch (c->x86_vendor) { - case X86_VENDOR_AMD: - if (c->x86 >= 0xf && c->x86 <= 0x11) - set_cpu_cap(c, X86_FEATURE_PAT); - break; - case X86_VENDOR_INTEL: - if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) - set_cpu_cap(c, X86_FEATURE_PAT); - break; - } - } /* @@ -409,18 +397,6 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) init_scattered_cpuid_features(c); } - clear_cpu_cap(c, X86_FEATURE_PAT); - - switch (c->x86_vendor) { - case X86_VENDOR_AMD: - if (c->x86 >= 0xf && c->x86 <= 0x11) - set_cpu_cap(c, X86_FEATURE_PAT); - break; - case X86_VENDOR_INTEL: - if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) - set_cpu_cap(c, X86_FEATURE_PAT); - break; - } } static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) @@ -651,6 +627,7 @@ void __init early_cpu_init(void) cpu_devs[cvdev->vendor] = cvdev->cpu_dev; early_cpu_detect(); + validate_pat_support(&boot_cpu_data); } /* Make sure %fs is initialized properly in idle threads */ diff --git a/arch/x86/kernel/geode_32.c b/arch/x86/kernel/geode_32.c index 9dad6ca..e8edd63 100644 --- a/arch/x86/kernel/geode_32.c +++ b/arch/x86/kernel/geode_32.c @@ -161,6 +161,25 @@ void geode_gpio_setup_event(unsigned int gpio, int pair, int pme) } EXPORT_SYMBOL_GPL(geode_gpio_setup_event); +int geode_has_vsa2(void) +{ + static int has_vsa2 = -1; + + if (has_vsa2 == -1) { + /* + * The VSA has virtual registers that we can query for a + * signature. + */ + outw(VSA_VR_UNLOCK, VSA_VRC_INDEX); + outw(VSA_VR_SIGNATURE, VSA_VRC_INDEX); + + has_vsa2 = (inw(VSA_VRC_DATA) == VSA_SIG); + } + + return has_vsa2; +} +EXPORT_SYMBOL_GPL(geode_has_vsa2); + static int __init geode_southbridge_init(void) { if (!is_geode()) diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index db6839b..e03cc95 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -450,7 +450,6 @@ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) { struct task_struct *tsk = current; - clear_fpu(tsk); return __copy_from_user(&tsk->thread.xstate->fsave, buf, sizeof(struct i387_fsave_struct)); } @@ -461,7 +460,6 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) struct user_i387_ia32_struct env; int err; - clear_fpu(tsk); err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0], sizeof(struct i387_fxsave_struct)); /* mxcsr reserved bits must be masked to zero for security reasons */ @@ -478,6 +476,16 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf) int err; if (HAVE_HWFP) { + struct task_struct *tsk = current; + + clear_fpu(tsk); + + if (!used_math()) { + err = init_fpu(tsk); + if (err) + return err; + } + if (cpu_has_fxsr) err = restore_i387_fxsave(buf); else diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index cc6f5eb..c0c68c1 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -95,7 +95,7 @@ void __init setup_per_cpu_areas(void) /* Copy section for each CPU (we discard the original) */ size = PERCPU_ENOUGH_ROOM; - printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n", + printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n", size); for_each_possible_cpu(i) { diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index 2283422..2c5f8b2 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -127,7 +127,12 @@ static struct resource standard_io_resources[] = { { }, { .name = "keyboard", .start = 0x0060, - .end = 0x006f, + .end = 0x0060, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "keyboard", + .start = 0x0064, + .end = 0x0064, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "dma page reg", diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 22c14e2..f2fc8fe 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -70,6 +70,7 @@ #include <asm/ds.h> #include <asm/topology.h> #include <asm/trampoline.h> +#include <asm/pat.h> #include <mach_apic.h> #ifdef CONFIG_PARAVIRT @@ -128,7 +129,9 @@ static struct resource standard_io_resources[] = { .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "timer1", .start = 0x50, .end = 0x53, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, - { .name = "keyboard", .start = 0x60, .end = 0x6f, + { .name = "keyboard", .start = 0x60, .end = 0x60, + .flags = IORESOURCE_BUSY | IORESOURCE_IO }, + { .name = "keyboard", .start = 0x64, .end = 0x64, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "dma page reg", .start = 0x80, .end = 0x8f, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, @@ -1063,25 +1066,19 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) if (c->extended_cpuid_level >= 0x80000007) c->x86_power = cpuid_edx(0x80000007); - - clear_cpu_cap(c, X86_FEATURE_PAT); - switch (c->x86_vendor) { case X86_VENDOR_AMD: early_init_amd(c); - if (c->x86 >= 0xf && c->x86 <= 0x11) - set_cpu_cap(c, X86_FEATURE_PAT); break; case X86_VENDOR_INTEL: early_init_intel(c); - if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) - set_cpu_cap(c, X86_FEATURE_PAT); break; case X86_VENDOR_CENTAUR: early_init_centaur(c); break; } + validate_pat_support(c); } /* diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 277446c..60adbe2 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -25,31 +25,24 @@ #include <asm/mtrr.h> #include <asm/io.h> -int pat_wc_enabled = 1; +#ifdef CONFIG_X86_PAT +int __read_mostly pat_wc_enabled = 1; -static u64 __read_mostly boot_pat_state; - -static int nopat(char *str) +void __init pat_disable(char *reason) { pat_wc_enabled = 0; - printk(KERN_INFO "x86: PAT support disabled.\n"); - - return 0; + printk(KERN_INFO "%s\n", reason); } -early_param("nopat", nopat); -static int pat_known_cpu(void) +static int nopat(char *str) { - if (!pat_wc_enabled) - return 0; - - if (cpu_has_pat) - return 1; - - pat_wc_enabled = 0; - printk(KERN_INFO "CPU and/or kernel does not support PAT.\n"); + pat_disable("PAT support disabled."); return 0; } +early_param("nopat", nopat); +#endif + +static u64 __read_mostly boot_pat_state; enum { PAT_UC = 0, /* uncached */ @@ -66,17 +59,19 @@ void pat_init(void) { u64 pat; -#ifndef CONFIG_X86_PAT - nopat(NULL); -#endif - - /* Boot CPU enables PAT based on CPU feature */ - if (!smp_processor_id() && !pat_known_cpu()) + if (!pat_wc_enabled) return; - /* APs enable PAT iff boot CPU has enabled it before */ - if (smp_processor_id() && !pat_wc_enabled) - return; + /* Paranoia check. */ + if (!cpu_has_pat) { + printk(KERN_ERR "PAT enabled, but CPU feature cleared\n"); + /* + * Panic if this happens on the secondary CPU, and we + * switched to PAT on the boot CPU. We have no way to + * undo PAT. + */ + BUG_ON(boot_pat_state); + } /* Set PWT to Write-Combining. All other bits stay the same */ /* @@ -95,9 +90,8 @@ void pat_init(void) PAT(4,WB) | PAT(5,WC) | PAT(6,UC_MINUS) | PAT(7,UC); /* Boot CPU check */ - if (!smp_processor_id()) { + if (!boot_pat_state) rdmsrl(MSR_IA32_CR_PAT, boot_pat_state); - } wrmsrl(MSR_IA32_CR_PAT, pat); printk(KERN_INFO "x86 PAT enabled: cpu %d, old 0x%Lx, new 0x%Lx\n", diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index bfa72a9..8545c8a 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -77,19 +77,6 @@ int pcibios_scanned; */ DEFINE_SPINLOCK(pci_config_lock); -static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) -{ - struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE]; - - if (rom_r->parent) - return; - if (rom_r->start) - /* we deal with BIOS assigned ROM later */ - return; - if (!(pci_probe & PCI_ASSIGN_ROMS)) - rom_r->start = rom_r->end = rom_r->flags = 0; -} - static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d) { pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; @@ -141,11 +128,7 @@ void __init dmi_check_skip_isa_align(void) void __devinit pcibios_fixup_bus(struct pci_bus *b) { - struct pci_dev *dev; - pci_read_bridge_bases(b); - list_for_each_entry(dev, &b->devices, bus_list) - pcibios_fixup_device_resources(dev); } /* diff --git a/arch/x86/pci/k8-bus_64.c b/arch/x86/pci/k8-bus_64.c index ab6d4b1..5c2799c 100644 --- a/arch/x86/pci/k8-bus_64.c +++ b/arch/x86/pci/k8-bus_64.c @@ -504,14 +504,6 @@ static int __init early_fill_mp_bus_info(void) } } -#ifdef CONFIG_NUMA - for (i = 0; i < BUS_NR; i++) { - node = mp_bus_to_node[i]; - if (node >= 0) - printk(KERN_DEBUG "bus: %02x to node: %02x\n", i, node); - } -#endif - for (i = 0; i < pci_root_num; i++) { int res_num; int busnum; |