提交 b8ce9fb8 编写于 作者: T Tony Lindgren

Merge branch 'fixes-v3.0-rc3' into devel-fixes

...@@ -518,6 +518,14 @@ N: Zach Brown ...@@ -518,6 +518,14 @@ N: Zach Brown
E: zab@zabbo.net E: zab@zabbo.net
D: maestro pci sound D: maestro pci sound
M: David Brownell
D: Kernel engineer, mentor, and friend. Maintained USB EHCI and
D: gadget layers, SPI subsystem, GPIO subsystem, and more than a few
D: device drivers. His encouragement also helped many engineers get
D: started working on the Linux kernel. David passed away in early
D: 2011, and will be greatly missed.
W: https://lkml.org/lkml/2011/4/5/36
N: Gary Brubaker N: Gary Brubaker
E: xavyer@ix.netcom.com E: xavyer@ix.netcom.com
D: USB Serial Empeg Empeg-car Mark I/II Driver D: USB Serial Empeg Empeg-car Mark I/II Driver
......
...@@ -2598,6 +2598,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -2598,6 +2598,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
unlock ejectable media); unlock ejectable media);
m = MAX_SECTORS_64 (don't transfer more m = MAX_SECTORS_64 (don't transfer more
than 64 sectors = 32 KB at a time); than 64 sectors = 32 KB at a time);
n = INITIAL_READ10 (force a retry of the
initial READ(10) command);
o = CAPACITY_OK (accept the capacity o = CAPACITY_OK (accept the capacity
reported by the device); reported by the device);
r = IGNORE_RESIDUE (the device reports r = IGNORE_RESIDUE (the device reports
......
...@@ -1739,7 +1739,7 @@ S: Supported ...@@ -1739,7 +1739,7 @@ S: Supported
F: drivers/net/enic/ F: drivers/net/enic/
CIRRUS LOGIC EP93XX ETHERNET DRIVER CIRRUS LOGIC EP93XX ETHERNET DRIVER
M: Lennert Buytenhek <kernel@wantstofly.org> M: Hartley Sweeten <hsweeten@visionengravers.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/arm/ep93xx_eth.c F: drivers/net/arm/ep93xx_eth.c
...@@ -4252,8 +4252,7 @@ F: drivers/mmc/ ...@@ -4252,8 +4252,7 @@ F: drivers/mmc/
F: include/linux/mmc/ F: include/linux/mmc/
MULTIMEDIA CARD (MMC) ETC. OVER SPI MULTIMEDIA CARD (MMC) ETC. OVER SPI
M: David Brownell <dbrownell@users.sourceforge.net> S: Orphan
S: Odd Fixes
F: drivers/mmc/host/mmc_spi.c F: drivers/mmc/host/mmc_spi.c
F: include/linux/spi/mmc_spi.h F: include/linux/spi/mmc_spi.h
...@@ -4603,7 +4602,6 @@ F: drivers/media/video/omap3isp/* ...@@ -4603,7 +4602,6 @@ F: drivers/media/video/omap3isp/*
OMAP USB SUPPORT OMAP USB SUPPORT
M: Felipe Balbi <balbi@ti.com> M: Felipe Balbi <balbi@ti.com>
M: David Brownell <dbrownell@users.sourceforge.net>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
L: linux-omap@vger.kernel.org L: linux-omap@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
...@@ -4947,6 +4945,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.gi ...@@ -4947,6 +4945,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.gi
F: drivers/input/serio/i8042-unicore32io.h F: drivers/input/serio/i8042-unicore32io.h
F: drivers/i2c/busses/i2c-puv3.c F: drivers/i2c/busses/i2c-puv3.c
F: drivers/video/fb-puv3.c F: drivers/video/fb-puv3.c
F: drivers/rtc/rtc-puv3.c
PMC SIERRA MaxRAID DRIVER PMC SIERRA MaxRAID DRIVER
M: Anil Ravindranath <anil_ravindranath@pmc-sierra.com> M: Anil Ravindranath <anil_ravindranath@pmc-sierra.com>
...@@ -5984,7 +5983,6 @@ F: Documentation/serial/specialix.txt ...@@ -5984,7 +5983,6 @@ F: Documentation/serial/specialix.txt
F: drivers/staging/tty/specialix* F: drivers/staging/tty/specialix*
SPI SUBSYSTEM SPI SUBSYSTEM
M: David Brownell <dbrownell@users.sourceforge.net>
M: Grant Likely <grant.likely@secretlab.ca> M: Grant Likely <grant.likely@secretlab.ca>
L: spi-devel-general@lists.sourceforge.net L: spi-devel-general@lists.sourceforge.net
Q: http://patchwork.kernel.org/project/spi-devel-general/list/ Q: http://patchwork.kernel.org/project/spi-devel-general/list/
...@@ -6432,9 +6430,8 @@ S: Maintained ...@@ -6432,9 +6430,8 @@ S: Maintained
F: drivers/usb/misc/rio500* F: drivers/usb/misc/rio500*
USB EHCI DRIVER USB EHCI DRIVER
M: David Brownell <dbrownell@users.sourceforge.net>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
S: Odd Fixes S: Orphan
F: Documentation/usb/ehci.txt F: Documentation/usb/ehci.txt
F: drivers/usb/host/ehci* F: drivers/usb/host/ehci*
...@@ -6448,9 +6445,10 @@ S: Maintained ...@@ -6448,9 +6445,10 @@ S: Maintained
F: drivers/media/video/et61x251/ F: drivers/media/video/et61x251/
USB GADGET/PERIPHERAL SUBSYSTEM USB GADGET/PERIPHERAL SUBSYSTEM
M: David Brownell <dbrownell@users.sourceforge.net> M: Felipe Balbi <balbi@ti.com>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
W: http://www.linux-usb.org/gadget W: http://www.linux-usb.org/gadget
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained S: Maintained
F: drivers/usb/gadget/ F: drivers/usb/gadget/
F: include/linux/usb/gadget* F: include/linux/usb/gadget*
...@@ -6492,9 +6490,8 @@ S: Maintained ...@@ -6492,9 +6490,8 @@ S: Maintained
F: sound/usb/midi.* F: sound/usb/midi.*
USB OHCI DRIVER USB OHCI DRIVER
M: David Brownell <dbrownell@users.sourceforge.net>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
S: Odd Fixes S: Orphan
F: Documentation/usb/ohci.txt F: Documentation/usb/ohci.txt
F: drivers/usb/host/ohci* F: drivers/usb/host/ohci*
......
VERSION = 3 VERSION = 3
PATCHLEVEL = 0 PATCHLEVEL = 0
SUBLEVEL = 0 SUBLEVEL = 0
EXTRAVERSION = -rc2 EXTRAVERSION = -rc3
NAME = Sneaky Weasel NAME = Sneaky Weasel
# *DOCUMENTATION* # *DOCUMENTATION*
...@@ -378,7 +378,7 @@ KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds ...@@ -378,7 +378,7 @@ KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
# Read KERNELRELEASE from include/config/kernel.release (if it exists) # Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
...@@ -1005,7 +1005,7 @@ endef ...@@ -1005,7 +1005,7 @@ endef
define filechk_version.h define filechk_version.h
(echo \#define LINUX_VERSION_CODE $(shell \ (echo \#define LINUX_VERSION_CODE $(shell \
expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + $(SUBLEVEL)); \ expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \
echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';) echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
endef endef
...@@ -1110,11 +1110,6 @@ modules_install: _modinst_ _modinst_post ...@@ -1110,11 +1110,6 @@ modules_install: _modinst_ _modinst_post
PHONY += _modinst_ PHONY += _modinst_
_modinst_: _modinst_:
@if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
echo "Warning: you may need to install module-init-tools"; \
echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
sleep 1; \
fi
@rm -rf $(MODLIB)/kernel @rm -rf $(MODLIB)/kernel
@rm -f $(MODLIB)/source @rm -f $(MODLIB)/source
@mkdir -p $(MODLIB)/kernel @mkdir -p $(MODLIB)/kernel
...@@ -1531,12 +1526,7 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)) ...@@ -1531,12 +1526,7 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files))
# Run depmod only if we have System.map and depmod is executable # Run depmod only if we have System.map and depmod is executable
quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) quiet_cmd_depmod = DEPMOD $(KERNELRELEASE)
cmd_depmod = \ cmd_depmod = $(srctree)/scripts/depmod.sh $(DEPMOD) $(KERNELRELEASE)
if [ -r System.map -a -x $(DEPMOD) ]; then \
$(DEPMOD) -ae -F System.map \
$(if $(strip $(INSTALL_MOD_PATH)), -b $(INSTALL_MOD_PATH) ) \
$(KERNELRELEASE); \
fi
# Create temporary dir for module support files # Create temporary dir for module support files
# clean it up only when building all modules # clean it up only when building all modules
......
...@@ -402,11 +402,15 @@ static struct resource ep93xx_eth_resource[] = { ...@@ -402,11 +402,15 @@ static struct resource ep93xx_eth_resource[] = {
} }
}; };
static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32);
static struct platform_device ep93xx_eth_device = { static struct platform_device ep93xx_eth_device = {
.name = "ep93xx-eth", .name = "ep93xx-eth",
.id = -1, .id = -1,
.dev = { .dev = {
.platform_data = &ep93xx_eth_data, .platform_data = &ep93xx_eth_data,
.coherent_dma_mask = DMA_BIT_MASK(32),
.dma_mask = &ep93xx_eth_dma_mask,
}, },
.num_resources = ARRAY_SIZE(ep93xx_eth_resource), .num_resources = ARRAY_SIZE(ep93xx_eth_resource),
.resource = ep93xx_eth_resource, .resource = ep93xx_eth_resource,
......
...@@ -91,6 +91,11 @@ config EXYNOS4_SETUP_FIMC ...@@ -91,6 +91,11 @@ config EXYNOS4_SETUP_FIMC
help help
Common setup code for the camera interfaces. Common setup code for the camera interfaces.
config EXYNOS4_SETUP_USB_PHY
bool
help
Common setup code for USB PHY controller
# machine support # machine support
menu "EXYNOS4 Machines" menu "EXYNOS4 Machines"
...@@ -176,6 +181,7 @@ config MACH_NURI ...@@ -176,6 +181,7 @@ config MACH_NURI
select EXYNOS4_SETUP_I2C3 select EXYNOS4_SETUP_I2C3
select EXYNOS4_SETUP_I2C5 select EXYNOS4_SETUP_I2C5
select EXYNOS4_SETUP_SDHCI select EXYNOS4_SETUP_SDHCI
select EXYNOS4_SETUP_USB_PHY
select SAMSUNG_DEV_PWM select SAMSUNG_DEV_PWM
help help
Machine support for Samsung Mobile NURI Board. Machine support for Samsung Mobile NURI Board.
......
...@@ -56,4 +56,4 @@ obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o ...@@ -56,4 +56,4 @@ obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o
obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
obj-$(CONFIG_USB_SUPPORT) += usb-phy.o obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY) += setup-usb-phy.o
...@@ -98,7 +98,7 @@ static struct map_desc exynos4_iodesc[] __initdata = { ...@@ -98,7 +98,7 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.length = SZ_4K, .length = SZ_4K,
.type = MT_DEVICE, .type = MT_DEVICE,
}, { }, {
.virtual = (unsigned long)S5P_VA_USB_HSPHY, .virtual = (unsigned long)S3C_VA_USB_HSPHY,
.pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY), .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
.length = SZ_4K, .length = SZ_4K,
.type = MT_DEVICE, .type = MT_DEVICE,
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#ifndef __PLAT_S5P_REGS_USB_PHY_H #ifndef __PLAT_S5P_REGS_USB_PHY_H
#define __PLAT_S5P_REGS_USB_PHY_H #define __PLAT_S5P_REGS_USB_PHY_H
#define EXYNOS4_HSOTG_PHYREG(x) ((x) + S5P_VA_USB_HSPHY) #define EXYNOS4_HSOTG_PHYREG(x) ((x) + S3C_VA_USB_HSPHY)
#define EXYNOS4_PHYPWR EXYNOS4_HSOTG_PHYREG(0x00) #define EXYNOS4_PHYPWR EXYNOS4_HSOTG_PHYREG(0x00)
#define PHY1_HSIC_NORMAL_MASK (0xf << 9) #define PHY1_HSIC_NORMAL_MASK (0xf << 9)
......
...@@ -206,6 +206,7 @@ static cycle_t exynos4_pwm4_read(struct clocksource *cs) ...@@ -206,6 +206,7 @@ static cycle_t exynos4_pwm4_read(struct clocksource *cs)
return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40)); return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40));
} }
#ifdef CONFIG_PM
static void exynos4_pwm4_resume(struct clocksource *cs) static void exynos4_pwm4_resume(struct clocksource *cs)
{ {
unsigned long pclk; unsigned long pclk;
...@@ -218,6 +219,7 @@ static void exynos4_pwm4_resume(struct clocksource *cs) ...@@ -218,6 +219,7 @@ static void exynos4_pwm4_resume(struct clocksource *cs)
exynos4_pwm_init(4, ~0); exynos4_pwm_init(4, ~0);
exynos4_pwm_start(4, 1); exynos4_pwm_start(4, 1);
} }
#endif
struct clocksource pwm_clocksource = { struct clocksource pwm_clocksource = {
.name = "pwm_timer4", .name = "pwm_timer4",
......
...@@ -4,14 +4,14 @@ ...@@ -4,14 +4,14 @@
# Common support # Common support
obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
obj-y += clock.o clock_data.o opp_data.o reset.o obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
# Power Management # Power Management
obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o obj-$(CONFIG_PM) += pm.o sleep.o
# DSP # DSP
obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
......
...@@ -284,14 +284,15 @@ static int __init omap1_system_dma_init(void) ...@@ -284,14 +284,15 @@ static int __init omap1_system_dma_init(void)
dma_base = ioremap(res[0].start, resource_size(&res[0])); dma_base = ioremap(res[0].start, resource_size(&res[0]));
if (!dma_base) { if (!dma_base) {
pr_err("%s: Unable to ioremap\n", __func__); pr_err("%s: Unable to ioremap\n", __func__);
return -ENODEV; ret = -ENODEV;
goto exit_device_put;
} }
ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
if (ret) { if (ret) {
dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
__func__, pdev->name, pdev->id); __func__, pdev->name, pdev->id);
goto exit_device_del; goto exit_device_put;
} }
p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
...@@ -299,7 +300,7 @@ static int __init omap1_system_dma_init(void) ...@@ -299,7 +300,7 @@ static int __init omap1_system_dma_init(void)
dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n", dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n",
__func__, pdev->name); __func__, pdev->name);
ret = -ENOMEM; ret = -ENOMEM;
goto exit_device_put; goto exit_device_del;
} }
d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL); d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
...@@ -380,10 +381,10 @@ static int __init omap1_system_dma_init(void) ...@@ -380,10 +381,10 @@ static int __init omap1_system_dma_init(void)
kfree(d); kfree(d);
exit_release_p: exit_release_p:
kfree(p); kfree(p);
exit_device_put:
platform_device_put(pdev);
exit_device_del: exit_device_del:
platform_device_del(pdev); platform_device_del(pdev);
exit_device_put:
platform_device_put(pdev);
return ret; return ret;
} }
......
...@@ -56,9 +56,13 @@ static struct dev_power_domain default_power_domain = { ...@@ -56,9 +56,13 @@ static struct dev_power_domain default_power_domain = {
USE_PLATFORM_PM_SLEEP_OPS USE_PLATFORM_PM_SLEEP_OPS
}, },
}; };
#define OMAP1_PWR_DOMAIN (&default_power_domain)
#else
#define OMAP1_PWR_DOMAIN NULL
#endif /* CONFIG_PM_RUNTIME */
static struct pm_clk_notifier_block platform_bus_notifier = { static struct pm_clk_notifier_block platform_bus_notifier = {
.pwr_domain = &default_power_domain, .pwr_domain = OMAP1_PWR_DOMAIN,
.con_ids = { "ick", "fck", NULL, }, .con_ids = { "ick", "fck", NULL, },
}; };
...@@ -72,4 +76,4 @@ static int __init omap1_pm_runtime_init(void) ...@@ -72,4 +76,4 @@ static int __init omap1_pm_runtime_init(void)
return 0; return 0;
} }
core_initcall(omap1_pm_runtime_init); core_initcall(omap1_pm_runtime_init);
#endif /* CONFIG_PM_RUNTIME */
...@@ -26,13 +26,13 @@ ...@@ -26,13 +26,13 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <mach/gpio.h>
#include <plat/board.h> #include <plat/board.h>
#include <plat/common.h> #include <plat/common.h>
#include <plat/gpmc.h> #include <plat/gpmc.h>
......
...@@ -622,19 +622,19 @@ static struct omap_device_pad serial3_pads[] __initdata = { ...@@ -622,19 +622,19 @@ static struct omap_device_pad serial3_pads[] __initdata = {
OMAP_MUX_MODE0), OMAP_MUX_MODE0),
}; };
static struct omap_board_data serial1_data = { static struct omap_board_data serial1_data __initdata = {
.id = 0, .id = 0,
.pads = serial1_pads, .pads = serial1_pads,
.pads_cnt = ARRAY_SIZE(serial1_pads), .pads_cnt = ARRAY_SIZE(serial1_pads),
}; };
static struct omap_board_data serial2_data = { static struct omap_board_data serial2_data __initdata = {
.id = 1, .id = 1,
.pads = serial2_pads, .pads = serial2_pads,
.pads_cnt = ARRAY_SIZE(serial2_pads), .pads_cnt = ARRAY_SIZE(serial2_pads),
}; };
static struct omap_board_data serial3_data = { static struct omap_board_data serial3_data __initdata = {
.id = 2, .id = 2,
.pads = serial3_pads, .pads = serial3_pads,
.pads_cnt = ARRAY_SIZE(serial3_pads), .pads_cnt = ARRAY_SIZE(serial3_pads),
......
...@@ -258,7 +258,7 @@ static struct gpio sdp4430_eth_gpios[] __initdata = { ...@@ -258,7 +258,7 @@ static struct gpio sdp4430_eth_gpios[] __initdata = {
{ ETH_KS8851_IRQ, GPIOF_IN, "eth_irq" }, { ETH_KS8851_IRQ, GPIOF_IN, "eth_irq" },
}; };
static int omap_ethernet_init(void) static int __init omap_ethernet_init(void)
{ {
int status; int status;
...@@ -322,6 +322,7 @@ static struct omap2_hsmmc_info mmc[] = { ...@@ -322,6 +322,7 @@ static struct omap2_hsmmc_info mmc[] = {
.gpio_wp = -EINVAL, .gpio_wp = -EINVAL,
.nonremovable = true, .nonremovable = true,
.ocr_mask = MMC_VDD_29_30, .ocr_mask = MMC_VDD_29_30,
.no_off_init = true,
}, },
{ {
.mmc = 1, .mmc = 1,
...@@ -681,19 +682,19 @@ static struct omap_device_pad serial4_pads[] __initdata = { ...@@ -681,19 +682,19 @@ static struct omap_device_pad serial4_pads[] __initdata = {
OMAP_PIN_OUTPUT | OMAP_MUX_MODE0), OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
}; };
static struct omap_board_data serial2_data = { static struct omap_board_data serial2_data __initdata = {
.id = 1, .id = 1,
.pads = serial2_pads, .pads = serial2_pads,
.pads_cnt = ARRAY_SIZE(serial2_pads), .pads_cnt = ARRAY_SIZE(serial2_pads),
}; };
static struct omap_board_data serial3_data = { static struct omap_board_data serial3_data __initdata = {
.id = 2, .id = 2,
.pads = serial3_pads, .pads = serial3_pads,
.pads_cnt = ARRAY_SIZE(serial3_pads), .pads_cnt = ARRAY_SIZE(serial3_pads),
}; };
static struct omap_board_data serial4_data = { static struct omap_board_data serial4_data __initdata = {
.id = 3, .id = 3,
.pads = serial4_pads, .pads = serial4_pads,
.pads_cnt = ARRAY_SIZE(serial4_pads), .pads_cnt = ARRAY_SIZE(serial4_pads),
...@@ -729,7 +730,7 @@ static void __init omap_4430sdp_init(void) ...@@ -729,7 +730,7 @@ static void __init omap_4430sdp_init(void)
if (omap_rev() == OMAP4430_REV_ES1_0) if (omap_rev() == OMAP4430_REV_ES1_0)
package = OMAP_PACKAGE_CBL; package = OMAP_PACKAGE_CBL;
omap4_mux_init(board_mux, package); omap4_mux_init(board_mux, NULL, package);
omap_board_config = sdp4430_config; omap_board_config = sdp4430_config;
omap_board_config_size = ARRAY_SIZE(sdp4430_config); omap_board_config_size = ARRAY_SIZE(sdp4430_config);
......
...@@ -27,13 +27,13 @@ ...@@ -27,13 +27,13 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/smc91x.h> #include <linux/smc91x.h>
#include <linux/gpio.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/flash.h> #include <asm/mach/flash.h>
#include <mach/gpio.h>
#include <plat/led.h> #include <plat/led.h>
#include <plat/usb.h> #include <plat/usb.h>
#include <plat/board.h> #include <plat/board.h>
......
...@@ -63,8 +63,6 @@ ...@@ -63,8 +63,6 @@
#define SB_T35_SMSC911X_CS 4 #define SB_T35_SMSC911X_CS 4
#define SB_T35_SMSC911X_GPIO 65 #define SB_T35_SMSC911X_GPIO 65
#define NAND_BLOCK_SIZE SZ_128K
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
#include <linux/smsc911x.h> #include <linux/smsc911x.h>
#include <plat/gpmc-smsc911x.h> #include <plat/gpmc-smsc911x.h>
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "mux.h" #include "mux.h"
#include "control.h" #include "control.h"
#include "common-board-devices.h"
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
static struct gpio_led cm_t3517_leds[] = { static struct gpio_led cm_t3517_leds[] = {
...@@ -177,7 +178,7 @@ static struct usbhs_omap_board_data cm_t3517_ehci_pdata __initdata = { ...@@ -177,7 +178,7 @@ static struct usbhs_omap_board_data cm_t3517_ehci_pdata __initdata = {
.reset_gpio_port[2] = -EINVAL, .reset_gpio_port[2] = -EINVAL,
}; };
static int cm_t3517_init_usbh(void) static int __init cm_t3517_init_usbh(void)
{ {
int err; int err;
...@@ -203,8 +204,6 @@ static inline int cm_t3517_init_usbh(void) ...@@ -203,8 +204,6 @@ static inline int cm_t3517_init_usbh(void)
#endif #endif
#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
#define NAND_BLOCK_SIZE SZ_128K
static struct mtd_partition cm_t3517_nand_partitions[] = { static struct mtd_partition cm_t3517_nand_partitions[] = {
{ {
.name = "xloader", .name = "xloader",
......
...@@ -61,8 +61,6 @@ ...@@ -61,8 +61,6 @@
#include "timer-gp.h" #include "timer-gp.h"
#include "common-board-devices.h" #include "common-board-devices.h"
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP_DM9000_GPIO_IRQ 25 #define OMAP_DM9000_GPIO_IRQ 25
#define OMAP3_DEVKIT_TS_GPIO 27 #define OMAP3_DEVKIT_TS_GPIO 27
......
...@@ -54,8 +54,6 @@ ...@@ -54,8 +54,6 @@
#include "pm.h" #include "pm.h"
#include "common-board-devices.h" #include "common-board-devices.h"
#define NAND_BLOCK_SIZE SZ_128K
/* /*
* OMAP3 Beagle revision * OMAP3 Beagle revision
* Run time detection of Beagle revision is done by reading GPIO. * Run time detection of Beagle revision is done by reading GPIO.
...@@ -106,6 +104,9 @@ static void __init omap3_beagle_init_rev(void) ...@@ -106,6 +104,9 @@ static void __init omap3_beagle_init_rev(void)
beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1) beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1)
| (gpio_get_value(173) << 2); | (gpio_get_value(173) << 2);
gpio_free_array(omap3_beagle_rev_gpios,
ARRAY_SIZE(omap3_beagle_rev_gpios));
switch (beagle_rev) { switch (beagle_rev) {
case 7: case 7:
printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n"); printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
...@@ -579,6 +580,9 @@ static void __init omap3_beagle_init(void) ...@@ -579,6 +580,9 @@ static void __init omap3_beagle_init(void)
omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions, omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
ARRAY_SIZE(omap3beagle_nand_partitions)); ARRAY_SIZE(omap3beagle_nand_partitions));
/* Ensure msecure is mux'd to be able to set the RTC. */
omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
/* Ensure SDRC pins are mux'd for self-refresh */ /* Ensure SDRC pins are mux'd for self-refresh */
omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/matrix_keypad.h> #include <linux/input/matrix_keypad.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/card.h> #include <linux/mmc/card.h>
...@@ -41,7 +42,6 @@ ...@@ -41,7 +42,6 @@
#include <plat/board.h> #include <plat/board.h>
#include <plat/common.h> #include <plat/common.h>
#include <mach/gpio.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <plat/mcspi.h> #include <plat/mcspi.h>
#include <plat/usb.h> #include <plat/usb.h>
...@@ -57,8 +57,6 @@ ...@@ -57,8 +57,6 @@
#define PANDORA_WIFI_NRESET_GPIO 23 #define PANDORA_WIFI_NRESET_GPIO 23
#define OMAP3_PANDORA_TS_GPIO 94 #define OMAP3_PANDORA_TS_GPIO 94
#define NAND_BLOCK_SIZE SZ_128K
static struct mtd_partition omap3pandora_nand_partitions[] = { static struct mtd_partition omap3pandora_nand_partitions[] = {
{ {
.name = "xloader", .name = "xloader",
......
...@@ -56,8 +56,6 @@ ...@@ -56,8 +56,6 @@
#include <asm/setup.h> #include <asm/setup.h>
#define NAND_BLOCK_SIZE SZ_128K
#define OMAP3_AC_GPIO 136 #define OMAP3_AC_GPIO 136
#define OMAP3_TS_GPIO 162 #define OMAP3_TS_GPIO 162
#define TB_BL_PWM_TIMER 9 #define TB_BL_PWM_TIMER 9
......
...@@ -526,19 +526,19 @@ static struct omap_device_pad serial4_pads[] __initdata = { ...@@ -526,19 +526,19 @@ static struct omap_device_pad serial4_pads[] __initdata = {
OMAP_PIN_OUTPUT | OMAP_MUX_MODE0), OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
}; };
static struct omap_board_data serial2_data = { static struct omap_board_data serial2_data __initdata = {
.id = 1, .id = 1,
.pads = serial2_pads, .pads = serial2_pads,
.pads_cnt = ARRAY_SIZE(serial2_pads), .pads_cnt = ARRAY_SIZE(serial2_pads),
}; };
static struct omap_board_data serial3_data = { static struct omap_board_data serial3_data __initdata = {
.id = 2, .id = 2,
.pads = serial3_pads, .pads = serial3_pads,
.pads_cnt = ARRAY_SIZE(serial3_pads), .pads_cnt = ARRAY_SIZE(serial3_pads),
}; };
static struct omap_board_data serial4_data = { static struct omap_board_data serial4_data __initdata = {
.id = 3, .id = 3,
.pads = serial4_pads, .pads = serial4_pads,
.pads_cnt = ARRAY_SIZE(serial4_pads), .pads_cnt = ARRAY_SIZE(serial4_pads),
...@@ -687,7 +687,7 @@ static void __init omap4_panda_init(void) ...@@ -687,7 +687,7 @@ static void __init omap4_panda_init(void)
if (omap_rev() == OMAP4430_REV_ES1_0) if (omap_rev() == OMAP4430_REV_ES1_0)
package = OMAP_PACKAGE_CBL; package = OMAP_PACKAGE_CBL;
omap4_mux_init(board_mux, package); omap4_mux_init(board_mux, NULL, package);
if (wl12xx_set_platform_data(&omap_panda_wlan_data)) if (wl12xx_set_platform_data(&omap_panda_wlan_data))
pr_err("error setting wl12xx data\n"); pr_err("error setting wl12xx data\n");
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c/twl.h> #include <linux/i2c/twl.h>
...@@ -45,7 +46,6 @@ ...@@ -45,7 +46,6 @@
#include <plat/common.h> #include <plat/common.h>
#include <video/omapdss.h> #include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h> #include <video/omap-panel-generic-dpi.h>
#include <mach/gpio.h>
#include <plat/gpmc.h> #include <plat/gpmc.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <plat/nand.h> #include <plat/nand.h>
...@@ -65,8 +65,6 @@ ...@@ -65,8 +65,6 @@
#define OVERO_GPIO_USBH_CPEN 168 #define OVERO_GPIO_USBH_CPEN 168
#define OVERO_GPIO_USBH_NRESET 183 #define OVERO_GPIO_USBH_NRESET 183
#define NAND_BLOCK_SIZE SZ_128K
#define OVERO_SMSC911X_CS 5 #define OVERO_SMSC911X_CS 5
#define OVERO_SMSC911X_GPIO 176 #define OVERO_SMSC911X_GPIO 176
#define OVERO_SMSC911X2_CS 4 #define OVERO_SMSC911X2_CS 4
......
...@@ -488,6 +488,7 @@ static struct regulator_init_data rx51_vmmc2 = { ...@@ -488,6 +488,7 @@ static struct regulator_init_data rx51_vmmc2 = {
.name = "V28_A", .name = "V28_A",
.min_uV = 2800000, .min_uV = 2800000,
.max_uV = 3000000, .max_uV = 3000000,
.always_on = true, /* due VIO leak to AIC34 VDDs */
.apply_uV = true, .apply_uV = true,
.valid_modes_mask = REGULATOR_MODE_NORMAL .valid_modes_mask = REGULATOR_MODE_NORMAL
| REGULATOR_MODE_STANDBY, | REGULATOR_MODE_STANDBY,
...@@ -582,7 +583,7 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n) ...@@ -582,7 +583,7 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
{ {
/* FIXME this gpio setup is just a placeholder for now */ /* FIXME this gpio setup is just a placeholder for now */
gpio_request_one(gpio + 6, GPIOF_OUT_INIT_LOW, "backlight_pwm"); gpio_request_one(gpio + 6, GPIOF_OUT_INIT_LOW, "backlight_pwm");
gpio_request_one(gpio + 7, GPIOF_OUT_INIT_HIGH, "speaker_en"); gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "speaker_en");
return 0; return 0;
} }
......
...@@ -26,7 +26,7 @@ static struct gpio zoom_lcd_gpios[] __initdata = { ...@@ -26,7 +26,7 @@ static struct gpio zoom_lcd_gpios[] __initdata = {
{ LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "lcd qvga" }, { LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "lcd qvga" },
}; };
static void zoom_lcd_panel_init(void) static void __init zoom_lcd_panel_init(void)
{ {
zoom_lcd_gpios[0].gpio = (omap_rev() > OMAP3430_REV_ES3_0) ? zoom_lcd_gpios[0].gpio = (omap_rev() > OMAP3430_REV_ES3_0) ?
LCD_PANEL_RESET_GPIO_PROD : LCD_PANEL_RESET_GPIO_PROD :
......
...@@ -85,17 +85,17 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, ...@@ -85,17 +85,17 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
struct spi_board_info *spi_bi = &ads7846_spi_board_info; struct spi_board_info *spi_bi = &ads7846_spi_board_info;
int err; int err;
err = gpio_request(gpio_pendown, "TS PenDown"); if (board_pdata && board_pdata->get_pendown_state) {
if (err) { err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
pr_err("Could not obtain gpio for TS PenDown: %d\n", err); if (err) {
return; pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
} return;
}
gpio_direction_input(gpio_pendown); gpio_export(gpio_pendown, 0);
gpio_export(gpio_pendown, 0);
if (gpio_debounce) if (gpio_debounce)
gpio_set_debounce(gpio_pendown, gpio_debounce); gpio_set_debounce(gpio_pendown, gpio_debounce);
}
ads7846_config.gpio_pendown = gpio_pendown; ads7846_config.gpio_pendown = gpio_pendown;
......
#ifndef __OMAP_COMMON_BOARD_DEVICES__ #ifndef __OMAP_COMMON_BOARD_DEVICES__
#define __OMAP_COMMON_BOARD_DEVICES__ #define __OMAP_COMMON_BOARD_DEVICES__
#define NAND_BLOCK_SIZE SZ_128K
struct twl4030_platform_data; struct twl4030_platform_data;
struct mtd_partition; struct mtd_partition;
......
...@@ -97,7 +97,7 @@ static int __init omap4_l3_init(void) ...@@ -97,7 +97,7 @@ static int __init omap4_l3_init(void)
WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name); WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
return PTR_ERR(od); return IS_ERR(od) ? PTR_ERR(od) : 0;
} }
postcore_initcall(omap4_l3_init); postcore_initcall(omap4_l3_init);
......
...@@ -145,6 +145,7 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot, ...@@ -145,6 +145,7 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
int power_on, int vdd) int power_on, int vdd)
{ {
u32 reg; u32 reg;
unsigned long timeout;
if (power_on) { if (power_on) {
reg = omap4_ctrl_pad_readl(control_pbias_offset); reg = omap4_ctrl_pad_readl(control_pbias_offset);
...@@ -157,9 +158,15 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot, ...@@ -157,9 +158,15 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
OMAP4_MMC1_PWRDNZ_MASK | OMAP4_MMC1_PWRDNZ_MASK |
OMAP4_USBC1_ICUSB_PWRDNZ_MASK); OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
omap4_ctrl_pad_writel(reg, control_pbias_offset); omap4_ctrl_pad_writel(reg, control_pbias_offset);
/* 4 microsec delay for comparator to generate an error*/
udelay(4); timeout = jiffies + msecs_to_jiffies(5);
reg = omap4_ctrl_pad_readl(control_pbias_offset); do {
reg = omap4_ctrl_pad_readl(control_pbias_offset);
if (!(reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK))
break;
usleep_range(100, 200);
} while (!time_after(jiffies, timeout));
if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK) { if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK) {
pr_err("Pbias Voltage is not same as LDO\n"); pr_err("Pbias Voltage is not same as LDO\n");
/* Caution : On VMODE_ERROR Power Down MMC IO */ /* Caution : On VMODE_ERROR Power Down MMC IO */
...@@ -331,6 +338,9 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, ...@@ -331,6 +338,9 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
if (c->no_off) if (c->no_off)
mmc->slots[0].no_off = 1; mmc->slots[0].no_off = 1;
if (c->no_off_init)
mmc->slots[0].no_regulator_off_init = c->no_off_init;
if (c->vcc_aux_disable_is_sleep) if (c->vcc_aux_disable_is_sleep)
mmc->slots[0].vcc_aux_disable_is_sleep = 1; mmc->slots[0].vcc_aux_disable_is_sleep = 1;
......
...@@ -18,6 +18,7 @@ struct omap2_hsmmc_info { ...@@ -18,6 +18,7 @@ struct omap2_hsmmc_info {
bool nonremovable; /* Nonremovable e.g. eMMC */ bool nonremovable; /* Nonremovable e.g. eMMC */
bool power_saving; /* Try to sleep or power off when possible */ bool power_saving; /* Try to sleep or power off when possible */
bool no_off; /* power_saving and power is not to go off */ bool no_off; /* power_saving and power is not to go off */
bool no_off_init; /* no power off when not in MMC sleep state */
bool vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */ bool vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */
int gpio_cd; /* or -EINVAL */ int gpio_cd; /* or -EINVAL */
int gpio_wp; /* or -EINVAL */ int gpio_wp; /* or -EINVAL */
......
...@@ -83,6 +83,9 @@ void omap_mux_write(struct omap_mux_partition *partition, u16 val, ...@@ -83,6 +83,9 @@ void omap_mux_write(struct omap_mux_partition *partition, u16 val,
void omap_mux_write_array(struct omap_mux_partition *partition, void omap_mux_write_array(struct omap_mux_partition *partition,
struct omap_board_mux *board_mux) struct omap_board_mux *board_mux)
{ {
if (!board_mux)
return;
while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) { while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) {
omap_mux_write(partition, board_mux->value, omap_mux_write(partition, board_mux->value,
board_mux->reg_offset); board_mux->reg_offset);
...@@ -906,7 +909,7 @@ static struct omap_mux *omap_mux_get_by_gpio( ...@@ -906,7 +909,7 @@ static struct omap_mux *omap_mux_get_by_gpio(
u16 omap_mux_get_gpio(int gpio) u16 omap_mux_get_gpio(int gpio)
{ {
struct omap_mux_partition *partition; struct omap_mux_partition *partition;
struct omap_mux *m; struct omap_mux *m = NULL;
list_for_each_entry(partition, &mux_partitions, node) { list_for_each_entry(partition, &mux_partitions, node) {
m = omap_mux_get_by_gpio(partition, gpio); m = omap_mux_get_by_gpio(partition, gpio);
......
...@@ -323,10 +323,12 @@ int omap3_mux_init(struct omap_board_mux *board_mux, int flags); ...@@ -323,10 +323,12 @@ int omap3_mux_init(struct omap_board_mux *board_mux, int flags);
/** /**
* omap4_mux_init() - initialize mux system with board specific set * omap4_mux_init() - initialize mux system with board specific set
* @board_mux: Board specific mux table * @board_subset: Board specific mux table
* @board_wkup_subset: Board specific mux table for wakeup instance
* @flags: OMAP package type used for the board * @flags: OMAP package type used for the board
*/ */
int omap4_mux_init(struct omap_board_mux *board_mux, int flags); int omap4_mux_init(struct omap_board_mux *board_subset,
struct omap_board_mux *board_wkup_subset, int flags);
/** /**
* omap_mux_init - private mux init function, do not call * omap_mux_init - private mux init function, do not call
......
...@@ -1309,7 +1309,8 @@ static struct omap_ball __initdata omap4_wkup_cbl_cbs_ball[] = { ...@@ -1309,7 +1309,8 @@ static struct omap_ball __initdata omap4_wkup_cbl_cbs_ball[] = {
#define omap4_wkup_cbl_cbs_ball NULL #define omap4_wkup_cbl_cbs_ball NULL
#endif #endif
int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags) int __init omap4_mux_init(struct omap_board_mux *board_subset,
struct omap_board_mux *board_wkup_subset, int flags)
{ {
struct omap_ball *package_balls_core; struct omap_ball *package_balls_core;
struct omap_ball *package_balls_wkup = omap4_wkup_cbl_cbs_ball; struct omap_ball *package_balls_wkup = omap4_wkup_cbl_cbs_ball;
...@@ -1347,7 +1348,7 @@ int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags) ...@@ -1347,7 +1348,7 @@ int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags)
OMAP_MUX_GPIO_IN_MODE3, OMAP_MUX_GPIO_IN_MODE3,
OMAP4_CTRL_MODULE_PAD_WKUP_MUX_PBASE, OMAP4_CTRL_MODULE_PAD_WKUP_MUX_PBASE,
OMAP4_CTRL_MODULE_PAD_WKUP_MUX_SIZE, OMAP4_CTRL_MODULE_PAD_WKUP_MUX_SIZE,
omap4_wkup_muxmodes, NULL, board_subset, omap4_wkup_muxmodes, NULL, board_wkup_subset,
package_balls_wkup); package_balls_wkup);
return ret; return ret;
......
...@@ -1628,7 +1628,7 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), ...@@ -1628,7 +1628,7 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
void *data) void *data)
{ {
struct omap_hwmod *temp_oh; struct omap_hwmod *temp_oh;
int ret; int ret = 0;
if (!fn) if (!fn)
return -EINVAL; return -EINVAL;
......
...@@ -5109,7 +5109,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { ...@@ -5109,7 +5109,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
&omap44xx_iva_seq1_hwmod, &omap44xx_iva_seq1_hwmod,
/* kbd class */ /* kbd class */
/* &omap44xx_kbd_hwmod, */ &omap44xx_kbd_hwmod,
/* mailbox class */ /* mailbox class */
&omap44xx_mailbox_hwmod, &omap44xx_mailbox_hwmod,
......
...@@ -56,8 +56,10 @@ int omap4430_phy_init(struct device *dev) ...@@ -56,8 +56,10 @@ int omap4430_phy_init(struct device *dev)
/* Power down the phy */ /* Power down the phy */
__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF); __raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
if (!dev) if (!dev) {
iounmap(ctrl_base);
return 0; return 0;
}
phyclk = clk_get(dev, "ocp2scp_usb_phy_ick"); phyclk = clk_get(dev, "ocp2scp_usb_phy_ick");
if (IS_ERR(phyclk)) { if (IS_ERR(phyclk)) {
......
...@@ -10,7 +10,6 @@ obj-n := ...@@ -10,7 +10,6 @@ obj-n :=
obj- := obj- :=
obj-$(CONFIG_CPU_S3C2410) += s3c2410.o obj-$(CONFIG_CPU_S3C2410) += s3c2410.o
obj-$(CONFIG_CPU_S3C2410) += irq.o
obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o
......
/* linux/arch/arm/mach-s3c2410/irq.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/syscore_ops.h>
#include <plat/cpu.h>
#include <plat/pm.h>
struct syscore_ops s3c24xx_irq_syscore_ops = {
.suspend = s3c24xx_irq_suspend,
.resume = s3c24xx_irq_resume,
};
...@@ -101,12 +101,14 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq) ...@@ -101,12 +101,14 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
unsigned long tmp, tmp1; unsigned long tmp, tmp1;
void __iomem *reg = NULL; void __iomem *reg = NULL;
if (ch == DMC0) if (ch == DMC0) {
reg = (S5P_VA_DMC0 + 0x30); reg = (S5P_VA_DMC0 + 0x30);
else if (ch == DMC1) } else if (ch == DMC1) {
reg = (S5P_VA_DMC1 + 0x30); reg = (S5P_VA_DMC1 + 0x30);
else } else {
printk(KERN_ERR "Cannot find DMC port\n"); printk(KERN_ERR "Cannot find DMC port\n");
return;
}
/* Find current DRAM frequency */ /* Find current DRAM frequency */
tmp = s5pv210_dram_conf[ch].freq; tmp = s5pv210_dram_conf[ch].freq;
......
...@@ -159,6 +159,9 @@ static void __init db8500_add_gpios(void) ...@@ -159,6 +159,9 @@ static void __init db8500_add_gpios(void)
/* No custom data yet */ /* No custom data yet */
}; };
if (cpu_is_u8500v2())
pdata.supports_sleepmode = true;
dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base),
IRQ_DB8500_GPIO0, &pdata); IRQ_DB8500_GPIO0, &pdata);
} }
......
...@@ -90,6 +90,7 @@ struct nmk_gpio_platform_data { ...@@ -90,6 +90,7 @@ struct nmk_gpio_platform_data {
int num_gpio; int num_gpio;
u32 (*get_secondary_status)(unsigned int bank); u32 (*get_secondary_status)(unsigned int bank);
void (*set_ioforce)(bool enable); void (*set_ioforce)(bool enable);
bool supports_sleepmode;
}; };
#endif /* __ASM_PLAT_GPIO_H */ #endif /* __ASM_PLAT_GPIO_H */
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/mtd/map.h> #include <linux/mtd/map.h>
struct platform_device;
extern void omap1_set_vpp(struct platform_device *pdev, int enable); extern void omap1_set_vpp(struct platform_device *pdev, int enable);
#endif #endif
...@@ -29,9 +29,6 @@ struct iovm_struct { ...@@ -29,9 +29,6 @@ struct iovm_struct {
* lower 16 bit is used for h/w and upper 16 bit is for s/w. * lower 16 bit is used for h/w and upper 16 bit is for s/w.
*/ */
#define IOVMF_SW_SHIFT 16 #define IOVMF_SW_SHIFT 16
#define IOVMF_HW_SIZE (1 << IOVMF_SW_SHIFT)
#define IOVMF_HW_MASK (IOVMF_HW_SIZE - 1)
#define IOVMF_SW_MASK (~IOVMF_HW_MASK)UL
/* /*
* iovma: h/w flags derived from cam and ram attribute * iovma: h/w flags derived from cam and ram attribute
......
...@@ -101,6 +101,9 @@ struct omap_mmc_platform_data { ...@@ -101,6 +101,9 @@ struct omap_mmc_platform_data {
/* If using power_saving and the MMC power is not to go off */ /* If using power_saving and the MMC power is not to go off */
unsigned no_off:1; unsigned no_off:1;
/* eMMC does not handle power off when not in sleep state */
unsigned no_regulator_off_init:1;
/* Regulator off remapped to sleep */ /* Regulator off remapped to sleep */
unsigned vcc_aux_disable_is_sleep:1; unsigned vcc_aux_disable_is_sleep:1;
......
...@@ -648,7 +648,6 @@ u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt, ...@@ -648,7 +648,6 @@ u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
return PTR_ERR(va); return PTR_ERR(va);
} }
flags &= IOVMF_HW_MASK;
flags |= IOVMF_DISCONT; flags |= IOVMF_DISCONT;
flags |= IOVMF_MMIO; flags |= IOVMF_MMIO;
...@@ -706,7 +705,6 @@ u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) ...@@ -706,7 +705,6 @@ u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
if (!va) if (!va)
return -ENOMEM; return -ENOMEM;
flags &= IOVMF_HW_MASK;
flags |= IOVMF_DISCONT; flags |= IOVMF_DISCONT;
flags |= IOVMF_ALLOC; flags |= IOVMF_ALLOC;
...@@ -795,7 +793,6 @@ u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes, ...@@ -795,7 +793,6 @@ u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
if (!va) if (!va)
return -ENOMEM; return -ENOMEM;
flags &= IOVMF_HW_MASK;
flags |= IOVMF_LINEAR; flags |= IOVMF_LINEAR;
flags |= IOVMF_MMIO; flags |= IOVMF_MMIO;
...@@ -853,7 +850,6 @@ u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) ...@@ -853,7 +850,6 @@ u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
return -ENOMEM; return -ENOMEM;
pa = virt_to_phys(va); pa = virt_to_phys(va);
flags &= IOVMF_HW_MASK;
flags |= IOVMF_LINEAR; flags |= IOVMF_LINEAR;
flags |= IOVMF_ALLOC; flags |= IOVMF_ALLOC;
......
...@@ -166,7 +166,7 @@ static void __init omap_detect_sram(void) ...@@ -166,7 +166,7 @@ static void __init omap_detect_sram(void)
else if (cpu_is_omap1611()) else if (cpu_is_omap1611())
omap_sram_size = SZ_256K; omap_sram_size = SZ_256K;
else { else {
printk(KERN_ERR "Could not detect SRAM size\n"); pr_err("Could not detect SRAM size\n");
omap_sram_size = 0x4000; omap_sram_size = 0x4000;
} }
} }
...@@ -221,10 +221,10 @@ static void __init omap_map_sram(void) ...@@ -221,10 +221,10 @@ static void __init omap_map_sram(void)
omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE); omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE);
iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", pr_info("SRAM: Mapped pa 0x%08llx to va 0x%08lx size: 0x%lx\n",
__pfn_to_phys(omap_sram_io_desc[0].pfn), (long long) __pfn_to_phys(omap_sram_io_desc[0].pfn),
omap_sram_io_desc[0].virtual, omap_sram_io_desc[0].virtual,
omap_sram_io_desc[0].length); omap_sram_io_desc[0].length);
/* /*
* Normally devicemaps_init() would flush caches and tlb after * Normally devicemaps_init() would flush caches and tlb after
...@@ -252,7 +252,7 @@ static void __init omap_map_sram(void) ...@@ -252,7 +252,7 @@ static void __init omap_map_sram(void)
void *omap_sram_push_address(unsigned long size) void *omap_sram_push_address(unsigned long size)
{ {
if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) { if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
printk(KERN_ERR "Not enough space in SRAM\n"); pr_err("Not enough space in SRAM\n");
return NULL; return NULL;
} }
......
...@@ -1199,7 +1199,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition); ...@@ -1199,7 +1199,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition);
#ifdef CONFIG_PM #ifdef CONFIG_PM
static void s3c2410_dma_suspend_chan(s3c2410_dma_chan *cp) static void s3c2410_dma_suspend_chan(struct s3c2410_dma_chan *cp)
{ {
printk(KERN_DEBUG "suspending dma channel %d\n", cp->number); printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/sysdev.h> #include <linux/sysdev.h>
#include <linux/syscore_ops.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
...@@ -668,3 +669,8 @@ void __init s3c24xx_init_irq(void) ...@@ -668,3 +669,8 @@ void __init s3c24xx_init_irq(void)
irqdbf("s3c2410: registered interrupt handlers\n"); irqdbf("s3c2410: registered interrupt handlers\n");
} }
struct syscore_ops s3c24xx_irq_syscore_ops = {
.suspend = s3c24xx_irq_suspend,
.resume = s3c24xx_irq_resume,
};
...@@ -15,8 +15,6 @@ ...@@ -15,8 +15,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#include <mach/map.h> #include <mach/map.h>
...@@ -45,13 +43,3 @@ struct platform_device s5p_device_onenand = { ...@@ -45,13 +43,3 @@ struct platform_device s5p_device_onenand = {
.num_resources = ARRAY_SIZE(s5p_onenand_resources), .num_resources = ARRAY_SIZE(s5p_onenand_resources),
.resource = s5p_onenand_resources, .resource = s5p_onenand_resources,
}; };
void s5p_onenand_set_platdata(struct onenand_platform_data *pdata)
{
struct onenand_platform_data *pd;
pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL);
if (!pd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
s5p_device_onenand.dev.platform_data = pd;
}
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#define S5P_VA_TWD S5P_VA_COREPERI(0x600) #define S5P_VA_TWD S5P_VA_COREPERI(0x600)
#define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000) #define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000)
#define S5P_VA_USB_HSPHY S3C_ADDR(0x02900000) #define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000)
#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
#define VA_VIC0 VA_VIC(0) #define VA_VIC0 VA_VIC(0)
......
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#include <mach/map.h> #include <mach/map.h>
...@@ -43,13 +41,3 @@ struct platform_device s3c_device_onenand = { ...@@ -43,13 +41,3 @@ struct platform_device s3c_device_onenand = {
.num_resources = ARRAY_SIZE(s3c_onenand_resources), .num_resources = ARRAY_SIZE(s3c_onenand_resources),
.resource = s3c_onenand_resources, .resource = s3c_onenand_resources,
}; };
void s3c_onenand_set_platdata(struct onenand_platform_data *pdata)
{
struct onenand_platform_data *pd;
pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL);
if (!pd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
s3c_device_onenand.dev.platform_data = pd;
}
...@@ -75,10 +75,8 @@ extern struct platform_device s5pc100_device_spi1; ...@@ -75,10 +75,8 @@ extern struct platform_device s5pc100_device_spi1;
extern struct platform_device s5pc100_device_spi2; extern struct platform_device s5pc100_device_spi2;
extern struct platform_device s5pv210_device_spi0; extern struct platform_device s5pv210_device_spi0;
extern struct platform_device s5pv210_device_spi1; extern struct platform_device s5pv210_device_spi1;
extern struct platform_device s5p6440_device_spi0; extern struct platform_device s5p64x0_device_spi0;
extern struct platform_device s5p6440_device_spi1; extern struct platform_device s5p64x0_device_spi1;
extern struct platform_device s5p6450_device_spi0;
extern struct platform_device s5p6450_device_spi1;
extern struct platform_device s3c_device_hwmon; extern struct platform_device s3c_device_hwmon;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/smp.h> #include <asm/smp.h>
...@@ -156,7 +156,7 @@ int die_if_no_fixup(const char *str, struct pt_regs *regs, ...@@ -156,7 +156,7 @@ int die_if_no_fixup(const char *str, struct pt_regs *regs,
case EXCEP_TRAP: case EXCEP_TRAP:
case EXCEP_UNIMPINS: case EXCEP_UNIMPINS:
if (get_user(opcode, (uint8_t __user *)regs->pc) != 0) if (probe_kernel_read(&opcode, (u8 *)regs->pc, 1) < 0)
break; break;
if (opcode == 0xff) { if (opcode == 0xff) {
if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0)) if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0))
......
...@@ -44,6 +44,7 @@ SECTIONS ...@@ -44,6 +44,7 @@ SECTIONS
RO_DATA(PAGE_SIZE) RO_DATA(PAGE_SIZE)
/* writeable */ /* writeable */
_sdata = .; /* Start of rw data section */
RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE) RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE)
_edata = .; _edata = .;
......
...@@ -120,14 +120,14 @@ debugger_local_cache_flushinv_one: ...@@ -120,14 +120,14 @@ debugger_local_cache_flushinv_one:
# conditionally purge this line in all ways # conditionally purge this line in all ways
mov d1,(L1_CACHE_WAYDISP*0,a0) mov d1,(L1_CACHE_WAYDISP*0,a0)
debugger_local_cache_flushinv_no_dcache: debugger_local_cache_flushinv_one_no_dcache:
# #
# now try to flush the icache # now try to flush the icache
# #
mov CHCTR,a0 mov CHCTR,a0
movhu (a0),d0 movhu (a0),d0
btst CHCTR_ICEN,d0 btst CHCTR_ICEN,d0
beq mn10300_local_icache_inv_range_reg_end beq debugger_local_cache_flushinv_one_end
LOCAL_CLI_SAVE(d1) LOCAL_CLI_SAVE(d1)
......
addnote addnote
dtc
empty.c empty.c
hack-coff hack-coff
infblock.c infblock.c
......
dtc-lexer.lex.c
dtc-parser.tab.c
dtc-parser.tab.h
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#define ASM_PPC_RIO_H #define ASM_PPC_RIO_H
extern void platform_rio_init(void); extern void platform_rio_init(void);
#ifdef CONFIG_RAPIDIO #ifdef CONFIG_FSL_RIO
extern int fsl_rio_mcheck_exception(struct pt_regs *); extern int fsl_rio_mcheck_exception(struct pt_regs *);
#else #else
static inline int fsl_rio_mcheck_exception(struct pt_regs *regs) {return 0; } static inline int fsl_rio_mcheck_exception(struct pt_regs *regs) {return 0; }
......
...@@ -1979,7 +1979,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -1979,7 +1979,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.pvr_value = 0x80240000, .pvr_value = 0x80240000,
.cpu_name = "e5500", .cpu_name = "e5500",
.cpu_features = CPU_FTRS_E5500, .cpu_features = CPU_FTRS_E5500,
.cpu_user_features = COMMON_USER_BOOKE, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
MMU_FTR_USE_TLBILX, MMU_FTR_USE_TLBILX,
.icache_bsize = 64, .icache_bsize = 64,
......
...@@ -82,11 +82,29 @@ static int __init early_parse_mem(char *p) ...@@ -82,11 +82,29 @@ static int __init early_parse_mem(char *p)
} }
early_param("mem", early_parse_mem); early_param("mem", early_parse_mem);
/*
* overlaps_initrd - check for overlap with page aligned extension of
* initrd.
*/
static inline int overlaps_initrd(unsigned long start, unsigned long size)
{
#ifdef CONFIG_BLK_DEV_INITRD
if (!initrd_start)
return 0;
return (start + size) > _ALIGN_DOWN(initrd_start, PAGE_SIZE) &&
start <= _ALIGN_UP(initrd_end, PAGE_SIZE);
#else
return 0;
#endif
}
/** /**
* move_device_tree - move tree to an unused area, if needed. * move_device_tree - move tree to an unused area, if needed.
* *
* The device tree may be allocated beyond our memory limit, or inside the * The device tree may be allocated beyond our memory limit, or inside the
* crash kernel region for kdump. If so, move it out of the way. * crash kernel region for kdump, or within the page aligned range of initrd.
* If so, move it out of the way.
*/ */
static void __init move_device_tree(void) static void __init move_device_tree(void)
{ {
...@@ -99,7 +117,8 @@ static void __init move_device_tree(void) ...@@ -99,7 +117,8 @@ static void __init move_device_tree(void)
size = be32_to_cpu(initial_boot_params->totalsize); size = be32_to_cpu(initial_boot_params->totalsize);
if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) || if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) ||
overlaps_crashkernel(start, size)) { overlaps_crashkernel(start, size) ||
overlaps_initrd(start, size)) {
p = __va(memblock_alloc(size, PAGE_SIZE)); p = __va(memblock_alloc(size, PAGE_SIZE));
memcpy(p, initial_boot_params, size); memcpy(p, initial_boot_params, size);
initial_boot_params = (struct boot_param_header *)p; initial_boot_params = (struct boot_param_header *)p;
...@@ -555,7 +574,9 @@ static void __init early_reserve_mem(void) ...@@ -555,7 +574,9 @@ static void __init early_reserve_mem(void)
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */ /* then reserve the initrd, if any */
if (initrd_start && (initrd_end > initrd_start)) if (initrd_start && (initrd_end > initrd_start))
memblock_reserve(__pa(initrd_start), initrd_end - initrd_start); memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE),
_ALIGN_UP(initrd_end, PAGE_SIZE) -
_ALIGN_DOWN(initrd_start, PAGE_SIZE));
#endif /* CONFIG_BLK_DEV_INITRD */ #endif /* CONFIG_BLK_DEV_INITRD */
#ifdef CONFIG_PPC32 #ifdef CONFIG_PPC32
......
...@@ -223,21 +223,6 @@ void free_initmem(void) ...@@ -223,21 +223,6 @@ void free_initmem(void)
#undef FREESEC #undef FREESEC
} }
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
if (start < end)
printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
free_page(start);
totalram_pages++;
}
}
#endif
#ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */ #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
void setup_initial_memory_limit(phys_addr_t first_memblock_base, void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size) phys_addr_t first_memblock_size)
......
...@@ -99,20 +99,6 @@ void free_initmem(void) ...@@ -99,20 +99,6 @@ void free_initmem(void)
((unsigned long)__init_end - (unsigned long)__init_begin) >> 10); ((unsigned long)__init_end - (unsigned long)__init_begin) >> 10);
} }
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
if (start < end)
printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
free_page(start);
totalram_pages++;
}
}
#endif
static void pgd_ctor(void *addr) static void pgd_ctor(void *addr)
{ {
memset(addr, 0, PGD_TABLE_SIZE); memset(addr, 0, PGD_TABLE_SIZE);
......
...@@ -382,6 +382,25 @@ void __init mem_init(void) ...@@ -382,6 +382,25 @@ void __init mem_init(void)
mem_init_done = 1; mem_init_done = 1;
} }
#ifdef CONFIG_BLK_DEV_INITRD
void __init free_initrd_mem(unsigned long start, unsigned long end)
{
if (start >= end)
return;
start = _ALIGN_DOWN(start, PAGE_SIZE);
end = _ALIGN_UP(end, PAGE_SIZE);
pr_info("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
free_page(start);
totalram_pages++;
}
}
#endif
/* /*
* This is called when a page has been modified by the kernel. * This is called when a page has been modified by the kernel.
* It just marks the page as not i-cache clean. We do the i-cache * It just marks the page as not i-cache clean. We do the i-cache
......
...@@ -196,9 +196,6 @@ static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl, ...@@ -196,9 +196,6 @@ static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl,
out_be32(&lbc->lteccr, LTECCR_CLEAR); out_be32(&lbc->lteccr, LTECCR_CLEAR);
out_be32(&lbc->ltedr, LTEDR_ENABLE); out_be32(&lbc->ltedr, LTEDR_ENABLE);
/* Enable interrupts for any detected events */
out_be32(&lbc->lteir, LTEIR_ENABLE);
/* Set the monitor timeout value to the maximum for erratum A001 */ /* Set the monitor timeout value to the maximum for erratum A001 */
if (of_device_is_compatible(node, "fsl,elbc")) if (of_device_is_compatible(node, "fsl,elbc"))
clrsetbits_be32(&lbc->lbcr, LBCR_BMT, LBCR_BMTPS); clrsetbits_be32(&lbc->lbcr, LBCR_BMT, LBCR_BMTPS);
...@@ -322,6 +319,9 @@ static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev) ...@@ -322,6 +319,9 @@ static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
goto err; goto err;
} }
/* Enable interrupts for any detected events */
out_be32(&fsl_lbc_ctrl_dev->regs->lteir, LTEIR_ENABLE);
return 0; return 0;
err: err:
......
...@@ -89,6 +89,7 @@ config S390 ...@@ -89,6 +89,7 @@ config S390
select HAVE_GET_USER_PAGES_FAST select HAVE_GET_USER_PAGES_FAST
select HAVE_ARCH_MUTEX_CPU_RELAX select HAVE_ARCH_MUTEX_CPU_RELAX
select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
select HAVE_RCU_TABLE_FREE if SMP
select ARCH_INLINE_SPIN_TRYLOCK select ARCH_INLINE_SPIN_TRYLOCK
select ARCH_INLINE_SPIN_TRYLOCK_BH select ARCH_INLINE_SPIN_TRYLOCK_BH
select ARCH_INLINE_SPIN_LOCK select ARCH_INLINE_SPIN_LOCK
......
...@@ -17,15 +17,15 @@ ...@@ -17,15 +17,15 @@
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/mm.h> #include <linux/mm.h>
#define check_pgt_cache() do {} while (0)
unsigned long *crst_table_alloc(struct mm_struct *); unsigned long *crst_table_alloc(struct mm_struct *);
void crst_table_free(struct mm_struct *, unsigned long *); void crst_table_free(struct mm_struct *, unsigned long *);
void crst_table_free_rcu(struct mm_struct *, unsigned long *);
unsigned long *page_table_alloc(struct mm_struct *); unsigned long *page_table_alloc(struct mm_struct *);
void page_table_free(struct mm_struct *, unsigned long *); void page_table_free(struct mm_struct *, unsigned long *);
void page_table_free_rcu(struct mm_struct *, unsigned long *); #ifdef CONFIG_HAVE_RCU_TABLE_FREE
void page_table_free_rcu(struct mmu_gather *, unsigned long *);
void __tlb_remove_table(void *_table);
#endif
static inline void clear_table(unsigned long *s, unsigned long val, size_t n) static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
{ {
......
...@@ -293,19 +293,6 @@ extern unsigned long VMALLOC_START; ...@@ -293,19 +293,6 @@ extern unsigned long VMALLOC_START;
* swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid. * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid.
*/ */
/* Page status table bits for virtualization */
#define RCP_ACC_BITS 0xf000000000000000UL
#define RCP_FP_BIT 0x0800000000000000UL
#define RCP_PCL_BIT 0x0080000000000000UL
#define RCP_HR_BIT 0x0040000000000000UL
#define RCP_HC_BIT 0x0020000000000000UL
#define RCP_GR_BIT 0x0004000000000000UL
#define RCP_GC_BIT 0x0002000000000000UL
/* User dirty / referenced bit for KVM's migration feature */
#define KVM_UR_BIT 0x0000800000000000UL
#define KVM_UC_BIT 0x0000400000000000UL
#ifndef __s390x__ #ifndef __s390x__
/* Bits in the segment table address-space-control-element */ /* Bits in the segment table address-space-control-element */
...@@ -325,6 +312,19 @@ extern unsigned long VMALLOC_START; ...@@ -325,6 +312,19 @@ extern unsigned long VMALLOC_START;
#define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PTL) #define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PTL)
#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV) #define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV)
/* Page status table bits for virtualization */
#define RCP_ACC_BITS 0xf0000000UL
#define RCP_FP_BIT 0x08000000UL
#define RCP_PCL_BIT 0x00800000UL
#define RCP_HR_BIT 0x00400000UL
#define RCP_HC_BIT 0x00200000UL
#define RCP_GR_BIT 0x00040000UL
#define RCP_GC_BIT 0x00020000UL
/* User dirty / referenced bit for KVM's migration feature */
#define KVM_UR_BIT 0x00008000UL
#define KVM_UC_BIT 0x00004000UL
#else /* __s390x__ */ #else /* __s390x__ */
/* Bits in the segment/region table address-space-control-element */ /* Bits in the segment/region table address-space-control-element */
...@@ -367,6 +367,19 @@ extern unsigned long VMALLOC_START; ...@@ -367,6 +367,19 @@ extern unsigned long VMALLOC_START;
#define _SEGMENT_ENTRY_LARGE 0x400 /* STE-format control, large page */ #define _SEGMENT_ENTRY_LARGE 0x400 /* STE-format control, large page */
#define _SEGMENT_ENTRY_CO 0x100 /* change-recording override */ #define _SEGMENT_ENTRY_CO 0x100 /* change-recording override */
/* Page status table bits for virtualization */
#define RCP_ACC_BITS 0xf000000000000000UL
#define RCP_FP_BIT 0x0800000000000000UL
#define RCP_PCL_BIT 0x0080000000000000UL
#define RCP_HR_BIT 0x0040000000000000UL
#define RCP_HC_BIT 0x0020000000000000UL
#define RCP_GR_BIT 0x0004000000000000UL
#define RCP_GC_BIT 0x0002000000000000UL
/* User dirty / referenced bit for KVM's migration feature */
#define KVM_UR_BIT 0x0000800000000000UL
#define KVM_UC_BIT 0x0000400000000000UL
#endif /* __s390x__ */ #endif /* __s390x__ */
/* /*
......
...@@ -139,110 +139,47 @@ struct slib { ...@@ -139,110 +139,47 @@ struct slib {
struct slibe slibe[QDIO_MAX_BUFFERS_PER_Q]; struct slibe slibe[QDIO_MAX_BUFFERS_PER_Q];
} __attribute__ ((packed, aligned(2048))); } __attribute__ ((packed, aligned(2048)));
/** #define SBAL_EFLAGS_LAST_ENTRY 0x40
* struct sbal_flags - storage block address list flags #define SBAL_EFLAGS_CONTIGUOUS 0x20
* @last: last entry #define SBAL_EFLAGS_FIRST_FRAG 0x04
* @cont: contiguous storage #define SBAL_EFLAGS_MIDDLE_FRAG 0x08
* @frag: fragmentation #define SBAL_EFLAGS_LAST_FRAG 0x0c
*/ #define SBAL_EFLAGS_MASK 0x6f
struct sbal_flags {
u8 : 1;
u8 last : 1;
u8 cont : 1;
u8 : 1;
u8 frag : 2;
u8 : 2;
} __attribute__ ((packed));
#define SBAL_FLAGS_FIRST_FRAG 0x04000000UL
#define SBAL_FLAGS_MIDDLE_FRAG 0x08000000UL
#define SBAL_FLAGS_LAST_FRAG 0x0c000000UL
#define SBAL_FLAGS_LAST_ENTRY 0x40000000UL
#define SBAL_FLAGS_CONTIGUOUS 0x20000000UL
#define SBAL_FLAGS0_DATA_CONTINUATION 0x20UL #define SBAL_SFLAGS0_PCI_REQ 0x40
#define SBAL_SFLAGS0_DATA_CONTINUATION 0x20
/* Awesome OpenFCP extensions */ /* Awesome OpenFCP extensions */
#define SBAL_FLAGS0_TYPE_STATUS 0x00UL #define SBAL_SFLAGS0_TYPE_STATUS 0x00
#define SBAL_FLAGS0_TYPE_WRITE 0x08UL #define SBAL_SFLAGS0_TYPE_WRITE 0x08
#define SBAL_FLAGS0_TYPE_READ 0x10UL #define SBAL_SFLAGS0_TYPE_READ 0x10
#define SBAL_FLAGS0_TYPE_WRITE_READ 0x18UL #define SBAL_SFLAGS0_TYPE_WRITE_READ 0x18
#define SBAL_FLAGS0_MORE_SBALS 0x04UL #define SBAL_SFLAGS0_MORE_SBALS 0x04
#define SBAL_FLAGS0_COMMAND 0x02UL #define SBAL_SFLAGS0_COMMAND 0x02
#define SBAL_FLAGS0_LAST_SBAL 0x00UL #define SBAL_SFLAGS0_LAST_SBAL 0x00
#define SBAL_FLAGS0_ONLY_SBAL SBAL_FLAGS0_COMMAND #define SBAL_SFLAGS0_ONLY_SBAL SBAL_SFLAGS0_COMMAND
#define SBAL_FLAGS0_MIDDLE_SBAL SBAL_FLAGS0_MORE_SBALS #define SBAL_SFLAGS0_MIDDLE_SBAL SBAL_SFLAGS0_MORE_SBALS
#define SBAL_FLAGS0_FIRST_SBAL SBAL_FLAGS0_MORE_SBALS | SBAL_FLAGS0_COMMAND #define SBAL_SFLAGS0_FIRST_SBAL (SBAL_SFLAGS0_MORE_SBALS | SBAL_SFLAGS0_COMMAND)
#define SBAL_FLAGS0_PCI 0x40
/**
* struct sbal_sbalf_0 - sbal flags for sbale 0
* @pci: PCI indicator
* @cont: data continuation
* @sbtype: storage-block type (FCP)
*/
struct sbal_sbalf_0 {
u8 : 1;
u8 pci : 1;
u8 cont : 1;
u8 sbtype : 2;
u8 : 3;
} __attribute__ ((packed));
/**
* struct sbal_sbalf_1 - sbal flags for sbale 1
* @key: storage key
*/
struct sbal_sbalf_1 {
u8 : 4;
u8 key : 4;
} __attribute__ ((packed));
/**
* struct sbal_sbalf_14 - sbal flags for sbale 14
* @erridx: error index
*/
struct sbal_sbalf_14 {
u8 : 4;
u8 erridx : 4;
} __attribute__ ((packed));
/**
* struct sbal_sbalf_15 - sbal flags for sbale 15
* @reason: reason for error state
*/
struct sbal_sbalf_15 {
u8 reason;
} __attribute__ ((packed));
/**
* union sbal_sbalf - storage block address list flags
* @i0: sbalf0
* @i1: sbalf1
* @i14: sbalf14
* @i15: sblaf15
* @value: raw value
*/
union sbal_sbalf {
struct sbal_sbalf_0 i0;
struct sbal_sbalf_1 i1;
struct sbal_sbalf_14 i14;
struct sbal_sbalf_15 i15;
u8 value;
};
/** /**
* struct qdio_buffer_element - SBAL entry * struct qdio_buffer_element - SBAL entry
* @flags: flags * @eflags: SBAL entry flags
* @scount: SBAL count
* @sflags: whole SBAL flags
* @length: length * @length: length
* @addr: address * @addr: address
*/ */
struct qdio_buffer_element { struct qdio_buffer_element {
u32 flags; u8 eflags;
/* private: */
u8 res1;
/* public: */
u8 scount;
u8 sflags;
u32 length; u32 length;
#ifdef CONFIG_32BIT #ifdef CONFIG_32BIT
/* private: */ /* private: */
void *reserved; void *res2;
/* public: */ /* public: */
#endif #endif
void *addr; void *addr;
......
...@@ -26,67 +26,60 @@ ...@@ -26,67 +26,60 @@
#include <linux/swap.h> #include <linux/swap.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/smp.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
struct mmu_gather { struct mmu_gather {
struct mm_struct *mm; struct mm_struct *mm;
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
struct mmu_table_batch *batch;
#endif
unsigned int fullmm; unsigned int fullmm;
unsigned int nr_ptes; unsigned int need_flush;
unsigned int nr_pxds;
unsigned int max;
void **array;
void *local[8];
}; };
static inline void __tlb_alloc_page(struct mmu_gather *tlb) #ifdef CONFIG_HAVE_RCU_TABLE_FREE
{ struct mmu_table_batch {
unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); struct rcu_head rcu;
unsigned int nr;
void *tables[0];
};
if (addr) { #define MAX_TABLE_BATCH \
tlb->array = (void *) addr; ((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *))
tlb->max = PAGE_SIZE / sizeof(void *);
} extern void tlb_table_flush(struct mmu_gather *tlb);
} extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
#endif
static inline void tlb_gather_mmu(struct mmu_gather *tlb, static inline void tlb_gather_mmu(struct mmu_gather *tlb,
struct mm_struct *mm, struct mm_struct *mm,
unsigned int full_mm_flush) unsigned int full_mm_flush)
{ {
tlb->mm = mm; tlb->mm = mm;
tlb->max = ARRAY_SIZE(tlb->local);
tlb->array = tlb->local;
tlb->fullmm = full_mm_flush; tlb->fullmm = full_mm_flush;
tlb->need_flush = 0;
#ifdef CONFIG_HAVE_RCU_TABLE_FREE
tlb->batch = NULL;
#endif
if (tlb->fullmm) if (tlb->fullmm)
__tlb_flush_mm(mm); __tlb_flush_mm(mm);
else
__tlb_alloc_page(tlb);
tlb->nr_ptes = 0;
tlb->nr_pxds = tlb->max;
} }
static inline void tlb_flush_mmu(struct mmu_gather *tlb) static inline void tlb_flush_mmu(struct mmu_gather *tlb)
{ {
if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pxds < tlb->max)) if (!tlb->need_flush)
__tlb_flush_mm(tlb->mm); return;
while (tlb->nr_ptes > 0) tlb->need_flush = 0;
page_table_free_rcu(tlb->mm, tlb->array[--tlb->nr_ptes]); __tlb_flush_mm(tlb->mm);
while (tlb->nr_pxds < tlb->max) #ifdef CONFIG_HAVE_RCU_TABLE_FREE
crst_table_free_rcu(tlb->mm, tlb->array[tlb->nr_pxds++]); tlb_table_flush(tlb);
#endif
} }
static inline void tlb_finish_mmu(struct mmu_gather *tlb, static inline void tlb_finish_mmu(struct mmu_gather *tlb,
unsigned long start, unsigned long end) unsigned long start, unsigned long end)
{ {
tlb_flush_mmu(tlb); tlb_flush_mmu(tlb);
rcu_table_freelist_finish();
/* keep the page table cache within bounds */
check_pgt_cache();
if (tlb->array != tlb->local)
free_pages((unsigned long) tlb->array, 0);
} }
/* /*
...@@ -112,12 +105,11 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) ...@@ -112,12 +105,11 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
unsigned long address) unsigned long address)
{ {
if (!tlb->fullmm) { #ifdef CONFIG_HAVE_RCU_TABLE_FREE
tlb->array[tlb->nr_ptes++] = pte; if (!tlb->fullmm)
if (tlb->nr_ptes >= tlb->nr_pxds) return page_table_free_rcu(tlb, (unsigned long *) pte);
tlb_flush_mmu(tlb); #endif
} else page_table_free(tlb->mm, (unsigned long *) pte);
page_table_free(tlb->mm, (unsigned long *) pte);
} }
/* /*
...@@ -133,12 +125,11 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, ...@@ -133,12 +125,11 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
#ifdef __s390x__ #ifdef __s390x__
if (tlb->mm->context.asce_limit <= (1UL << 31)) if (tlb->mm->context.asce_limit <= (1UL << 31))
return; return;
if (!tlb->fullmm) { #ifdef CONFIG_HAVE_RCU_TABLE_FREE
tlb->array[--tlb->nr_pxds] = pmd; if (!tlb->fullmm)
if (tlb->nr_ptes >= tlb->nr_pxds) return tlb_remove_table(tlb, pmd);
tlb_flush_mmu(tlb); #endif
} else crst_table_free(tlb->mm, (unsigned long *) pmd);
crst_table_free(tlb->mm, (unsigned long *) pmd);
#endif #endif
} }
...@@ -155,12 +146,11 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, ...@@ -155,12 +146,11 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
#ifdef __s390x__ #ifdef __s390x__
if (tlb->mm->context.asce_limit <= (1UL << 42)) if (tlb->mm->context.asce_limit <= (1UL << 42))
return; return;
if (!tlb->fullmm) { #ifdef CONFIG_HAVE_RCU_TABLE_FREE
tlb->array[--tlb->nr_pxds] = pud; if (!tlb->fullmm)
if (tlb->nr_ptes >= tlb->nr_pxds) return tlb_remove_table(tlb, pud);
tlb_flush_mmu(tlb); #endif
} else crst_table_free(tlb->mm, (unsigned long *) pud);
crst_table_free(tlb->mm, (unsigned long *) pud);
#endif #endif
} }
......
...@@ -731,6 +731,7 @@ static int __init kvm_s390_init(void) ...@@ -731,6 +731,7 @@ static int __init kvm_s390_init(void)
} }
memcpy(facilities, S390_lowcore.stfle_fac_list, 16); memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
facilities[0] &= 0xff00fff3f47c0000ULL; facilities[0] &= 0xff00fff3f47c0000ULL;
facilities[1] &= 0x201c000000000000ULL;
return 0; return 0;
} }
......
...@@ -93,4 +93,6 @@ sie_err: ...@@ -93,4 +93,6 @@ sie_err:
.section __ex_table,"a" .section __ex_table,"a"
.quad sie_inst,sie_err .quad sie_inst,sie_err
.quad sie_exit,sie_err
.quad sie_reenter,sie_err
.previous .previous
...@@ -24,94 +24,12 @@ ...@@ -24,94 +24,12 @@
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
struct rcu_table_freelist {
struct rcu_head rcu;
struct mm_struct *mm;
unsigned int pgt_index;
unsigned int crst_index;
unsigned long *table[0];
};
#define RCU_FREELIST_SIZE \
((PAGE_SIZE - sizeof(struct rcu_table_freelist)) \
/ sizeof(unsigned long))
static DEFINE_PER_CPU(struct rcu_table_freelist *, rcu_table_freelist);
static void __page_table_free(struct mm_struct *mm, unsigned long *table);
static struct rcu_table_freelist *rcu_table_freelist_get(struct mm_struct *mm)
{
struct rcu_table_freelist **batchp = &__get_cpu_var(rcu_table_freelist);
struct rcu_table_freelist *batch = *batchp;
if (batch)
return batch;
batch = (struct rcu_table_freelist *) __get_free_page(GFP_ATOMIC);
if (batch) {
batch->mm = mm;
batch->pgt_index = 0;
batch->crst_index = RCU_FREELIST_SIZE;
*batchp = batch;
}
return batch;
}
static void rcu_table_freelist_callback(struct rcu_head *head)
{
struct rcu_table_freelist *batch =
container_of(head, struct rcu_table_freelist, rcu);
while (batch->pgt_index > 0)
__page_table_free(batch->mm, batch->table[--batch->pgt_index]);
while (batch->crst_index < RCU_FREELIST_SIZE)
crst_table_free(batch->mm, batch->table[batch->crst_index++]);
free_page((unsigned long) batch);
}
void rcu_table_freelist_finish(void)
{
struct rcu_table_freelist **batchp = &get_cpu_var(rcu_table_freelist);
struct rcu_table_freelist *batch = *batchp;
if (!batch)
goto out;
call_rcu(&batch->rcu, rcu_table_freelist_callback);
*batchp = NULL;
out:
put_cpu_var(rcu_table_freelist);
}
static void smp_sync(void *arg)
{
}
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
#define ALLOC_ORDER 1 #define ALLOC_ORDER 1
#define TABLES_PER_PAGE 4 #define FRAG_MASK 0x0f
#define FRAG_MASK 15UL
#define SECOND_HALVES 10UL
void clear_table_pgstes(unsigned long *table)
{
clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/4);
memset(table + 256, 0, PAGE_SIZE/4);
clear_table(table + 512, _PAGE_TYPE_EMPTY, PAGE_SIZE/4);
memset(table + 768, 0, PAGE_SIZE/4);
}
#else #else
#define ALLOC_ORDER 2 #define ALLOC_ORDER 2
#define TABLES_PER_PAGE 2 #define FRAG_MASK 0x03
#define FRAG_MASK 3UL
#define SECOND_HALVES 2UL
void clear_table_pgstes(unsigned long *table)
{
clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2);
memset(table + 256, 0, PAGE_SIZE/2);
}
#endif #endif
unsigned long VMALLOC_START = VMALLOC_END - VMALLOC_SIZE; unsigned long VMALLOC_START = VMALLOC_END - VMALLOC_SIZE;
...@@ -140,29 +58,6 @@ void crst_table_free(struct mm_struct *mm, unsigned long *table) ...@@ -140,29 +58,6 @@ void crst_table_free(struct mm_struct *mm, unsigned long *table)
free_pages((unsigned long) table, ALLOC_ORDER); free_pages((unsigned long) table, ALLOC_ORDER);
} }
void crst_table_free_rcu(struct mm_struct *mm, unsigned long *table)
{
struct rcu_table_freelist *batch;
preempt_disable();
if (atomic_read(&mm->mm_users) < 2 &&
cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
crst_table_free(mm, table);
goto out;
}
batch = rcu_table_freelist_get(mm);
if (!batch) {
smp_call_function(smp_sync, NULL, 1);
crst_table_free(mm, table);
goto out;
}
batch->table[--batch->crst_index] = table;
if (batch->pgt_index >= batch->crst_index)
rcu_table_freelist_finish();
out:
preempt_enable();
}
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
int crst_table_upgrade(struct mm_struct *mm, unsigned long limit) int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
{ {
...@@ -238,124 +133,175 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit) ...@@ -238,124 +133,175 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
} }
#endif #endif
static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
{
unsigned int old, new;
do {
old = atomic_read(v);
new = old ^ bits;
} while (atomic_cmpxchg(v, old, new) != old);
return new;
}
/* /*
* page table entry allocation/free routines. * page table entry allocation/free routines.
*/ */
#ifdef CONFIG_PGSTE
static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm)
{
struct page *page;
unsigned long *table;
page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
if (!page)
return NULL;
pgtable_page_ctor(page);
atomic_set(&page->_mapcount, 3);
table = (unsigned long *) page_to_phys(page);
clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2);
clear_table(table + PTRS_PER_PTE, 0, PAGE_SIZE/2);
return table;
}
static inline void page_table_free_pgste(unsigned long *table)
{
struct page *page;
page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
pgtable_page_ctor(page);
atomic_set(&page->_mapcount, -1);
__free_page(page);
}
#endif
unsigned long *page_table_alloc(struct mm_struct *mm) unsigned long *page_table_alloc(struct mm_struct *mm)
{ {
struct page *page; struct page *page;
unsigned long *table; unsigned long *table;
unsigned long bits; unsigned int mask, bit;
bits = (mm->context.has_pgste) ? 3UL : 1UL; #ifdef CONFIG_PGSTE
if (mm_has_pgste(mm))
return page_table_alloc_pgste(mm);
#endif
/* Allocate fragments of a 4K page as 1K/2K page table */
spin_lock_bh(&mm->context.list_lock); spin_lock_bh(&mm->context.list_lock);
page = NULL; mask = FRAG_MASK;
if (!list_empty(&mm->context.pgtable_list)) { if (!list_empty(&mm->context.pgtable_list)) {
page = list_first_entry(&mm->context.pgtable_list, page = list_first_entry(&mm->context.pgtable_list,
struct page, lru); struct page, lru);
if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1)) table = (unsigned long *) page_to_phys(page);
page = NULL; mask = atomic_read(&page->_mapcount);
mask = mask | (mask >> 4);
} }
if (!page) { if ((mask & FRAG_MASK) == FRAG_MASK) {
spin_unlock_bh(&mm->context.list_lock); spin_unlock_bh(&mm->context.list_lock);
page = alloc_page(GFP_KERNEL|__GFP_REPEAT); page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
if (!page) if (!page)
return NULL; return NULL;
pgtable_page_ctor(page); pgtable_page_ctor(page);
page->flags &= ~FRAG_MASK; atomic_set(&page->_mapcount, 1);
table = (unsigned long *) page_to_phys(page); table = (unsigned long *) page_to_phys(page);
if (mm->context.has_pgste) clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
clear_table_pgstes(table);
else
clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
spin_lock_bh(&mm->context.list_lock); spin_lock_bh(&mm->context.list_lock);
list_add(&page->lru, &mm->context.pgtable_list); list_add(&page->lru, &mm->context.pgtable_list);
} else {
for (bit = 1; mask & bit; bit <<= 1)
table += PTRS_PER_PTE;
mask = atomic_xor_bits(&page->_mapcount, bit);
if ((mask & FRAG_MASK) == FRAG_MASK)
list_del(&page->lru);
} }
table = (unsigned long *) page_to_phys(page);
while (page->flags & bits) {
table += 256;
bits <<= 1;
}
page->flags |= bits;
if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1))
list_move_tail(&page->lru, &mm->context.pgtable_list);
spin_unlock_bh(&mm->context.list_lock); spin_unlock_bh(&mm->context.list_lock);
return table; return table;
} }
static void __page_table_free(struct mm_struct *mm, unsigned long *table) void page_table_free(struct mm_struct *mm, unsigned long *table)
{ {
struct page *page; struct page *page;
unsigned long bits; unsigned int bit, mask;
bits = ((unsigned long) table) & 15; #ifdef CONFIG_PGSTE
table = (unsigned long *)(((unsigned long) table) ^ bits); if (mm_has_pgste(mm))
return page_table_free_pgste(table);
#endif
/* Free 1K/2K page table fragment of a 4K page */
page = pfn_to_page(__pa(table) >> PAGE_SHIFT); page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
page->flags ^= bits; bit = 1 << ((__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t)));
if (!(page->flags & FRAG_MASK)) { spin_lock_bh(&mm->context.list_lock);
if ((atomic_read(&page->_mapcount) & FRAG_MASK) != FRAG_MASK)
list_del(&page->lru);
mask = atomic_xor_bits(&page->_mapcount, bit);
if (mask & FRAG_MASK)
list_add(&page->lru, &mm->context.pgtable_list);
spin_unlock_bh(&mm->context.list_lock);
if (mask == 0) {
pgtable_page_dtor(page); pgtable_page_dtor(page);
atomic_set(&page->_mapcount, -1);
__free_page(page); __free_page(page);
} }
} }
void page_table_free(struct mm_struct *mm, unsigned long *table) #ifdef CONFIG_HAVE_RCU_TABLE_FREE
static void __page_table_free_rcu(void *table, unsigned bit)
{ {
struct page *page; struct page *page;
unsigned long bits;
bits = (mm->context.has_pgste) ? 3UL : 1UL; #ifdef CONFIG_PGSTE
bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long); if (bit == FRAG_MASK)
return page_table_free_pgste(table);
#endif
/* Free 1K/2K page table fragment of a 4K page */
page = pfn_to_page(__pa(table) >> PAGE_SHIFT); page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
spin_lock_bh(&mm->context.list_lock); if (atomic_xor_bits(&page->_mapcount, bit) == 0) {
page->flags ^= bits;
if (page->flags & FRAG_MASK) {
/* Page now has some free pgtable fragments. */
if (!list_empty(&page->lru))
list_move(&page->lru, &mm->context.pgtable_list);
page = NULL;
} else
/* All fragments of the 4K page have been freed. */
list_del(&page->lru);
spin_unlock_bh(&mm->context.list_lock);
if (page) {
pgtable_page_dtor(page); pgtable_page_dtor(page);
atomic_set(&page->_mapcount, -1);
__free_page(page); __free_page(page);
} }
} }
void page_table_free_rcu(struct mm_struct *mm, unsigned long *table) void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table)
{ {
struct rcu_table_freelist *batch; struct mm_struct *mm;
struct page *page; struct page *page;
unsigned long bits; unsigned int bit, mask;
preempt_disable(); mm = tlb->mm;
if (atomic_read(&mm->mm_users) < 2 && #ifdef CONFIG_PGSTE
cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) { if (mm_has_pgste(mm)) {
page_table_free(mm, table); table = (unsigned long *) (__pa(table) | FRAG_MASK);
goto out; tlb_remove_table(tlb, table);
} return;
batch = rcu_table_freelist_get(mm);
if (!batch) {
smp_call_function(smp_sync, NULL, 1);
page_table_free(mm, table);
goto out;
} }
bits = (mm->context.has_pgste) ? 3UL : 1UL; #endif
bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long); bit = 1 << ((__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t)));
page = pfn_to_page(__pa(table) >> PAGE_SHIFT); page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
spin_lock_bh(&mm->context.list_lock); spin_lock_bh(&mm->context.list_lock);
/* Delayed freeing with rcu prevents reuse of pgtable fragments */ if ((atomic_read(&page->_mapcount) & FRAG_MASK) != FRAG_MASK)
list_del_init(&page->lru); list_del(&page->lru);
mask = atomic_xor_bits(&page->_mapcount, bit | (bit << 4));
if (mask & FRAG_MASK)
list_add_tail(&page->lru, &mm->context.pgtable_list);
spin_unlock_bh(&mm->context.list_lock); spin_unlock_bh(&mm->context.list_lock);
table = (unsigned long *)(((unsigned long) table) | bits); table = (unsigned long *) (__pa(table) | (bit << 4));
batch->table[batch->pgt_index++] = table; tlb_remove_table(tlb, table);
if (batch->pgt_index >= batch->crst_index)
rcu_table_freelist_finish();
out:
preempt_enable();
} }
void __tlb_remove_table(void *_table)
{
void *table = (void *)((unsigned long) _table & PAGE_MASK);
unsigned type = (unsigned long) _table & ~PAGE_MASK;
if (type)
__page_table_free_rcu(table, type);
else
free_pages((unsigned long) table, ALLOC_ORDER);
}
#endif
/* /*
* switch on pgstes for its userspace process (for kvm) * switch on pgstes for its userspace process (for kvm)
*/ */
...@@ -369,7 +315,7 @@ int s390_enable_sie(void) ...@@ -369,7 +315,7 @@ int s390_enable_sie(void)
return -EINVAL; return -EINVAL;
/* Do we have pgstes? if yes, we are done */ /* Do we have pgstes? if yes, we are done */
if (tsk->mm->context.has_pgste) if (mm_has_pgste(tsk->mm))
return 0; return 0;
/* lets check if we are allowed to replace the mm */ /* lets check if we are allowed to replace the mm */
......
...@@ -26,7 +26,6 @@ config SPARC ...@@ -26,7 +26,6 @@ config SPARC
select HAVE_DMA_API_DEBUG select HAVE_DMA_API_DEBUG
select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL
select HAVE_GENERIC_HARDIRQS select HAVE_GENERIC_HARDIRQS
select GENERIC_HARDIRQS_NO_DEPRECATED
select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW
select USE_GENERIC_SMP_HELPERS if SMP select USE_GENERIC_SMP_HELPERS if SMP
...@@ -528,6 +527,23 @@ config PCI_DOMAINS ...@@ -528,6 +527,23 @@ config PCI_DOMAINS
config PCI_SYSCALL config PCI_SYSCALL
def_bool PCI def_bool PCI
config PCIC_PCI
bool
depends on PCI && SPARC32 && !SPARC_LEON
default y
config LEON_PCI
bool
depends on PCI && SPARC_LEON
default y
config GRPCI2
bool "GRPCI2 Host Bridge Support"
depends on LEON_PCI
default y
help
Say Y here to include the GRPCI2 Host Bridge Driver.
source "drivers/pci/Kconfig" source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig" source "drivers/pcmcia/Kconfig"
......
...@@ -138,7 +138,7 @@ static unsigned char sun_82072_fd_inb(int port) ...@@ -138,7 +138,7 @@ static unsigned char sun_82072_fd_inb(int port)
return sun_fdc->data_82072; return sun_fdc->data_82072;
case 7: /* FD_DIR */ case 7: /* FD_DIR */
return sun_read_dir(); return sun_read_dir();
}; }
panic("sun_82072_fd_inb: How did I get here?"); panic("sun_82072_fd_inb: How did I get here?");
} }
...@@ -161,7 +161,7 @@ static void sun_82072_fd_outb(unsigned char value, int port) ...@@ -161,7 +161,7 @@ static void sun_82072_fd_outb(unsigned char value, int port)
case 4: /* FD_STATUS */ case 4: /* FD_STATUS */
sun_fdc->status_82072 = value; sun_fdc->status_82072 = value;
break; break;
}; }
return; return;
} }
...@@ -186,7 +186,7 @@ static unsigned char sun_82077_fd_inb(int port) ...@@ -186,7 +186,7 @@ static unsigned char sun_82077_fd_inb(int port)
return sun_fdc->data_82077; return sun_fdc->data_82077;
case 7: /* FD_DIR */ case 7: /* FD_DIR */
return sun_read_dir(); return sun_read_dir();
}; }
panic("sun_82077_fd_inb: How did I get here?"); panic("sun_82077_fd_inb: How did I get here?");
} }
...@@ -212,7 +212,7 @@ static void sun_82077_fd_outb(unsigned char value, int port) ...@@ -212,7 +212,7 @@ static void sun_82077_fd_outb(unsigned char value, int port)
case 3: /* FD_TDR */ case 3: /* FD_TDR */
sun_fdc->tapectl_82077 = value; sun_fdc->tapectl_82077 = value;
break; break;
}; }
return; return;
} }
......
...@@ -111,7 +111,7 @@ static unsigned char sun_82077_fd_inb(unsigned long port) ...@@ -111,7 +111,7 @@ static unsigned char sun_82077_fd_inb(unsigned long port)
case 7: /* FD_DIR */ case 7: /* FD_DIR */
/* XXX: Is DCL on 0x80 in sun4m? */ /* XXX: Is DCL on 0x80 in sun4m? */
return sbus_readb(&sun_fdc->dir_82077); return sbus_readb(&sun_fdc->dir_82077);
}; }
panic("sun_82072_fd_inb: How did I get here?"); panic("sun_82072_fd_inb: How did I get here?");
} }
...@@ -135,7 +135,7 @@ static void sun_82077_fd_outb(unsigned char value, unsigned long port) ...@@ -135,7 +135,7 @@ static void sun_82077_fd_outb(unsigned char value, unsigned long port)
case 4: /* FD_STATUS */ case 4: /* FD_STATUS */
sbus_writeb(value, &sun_fdc->status_82077); sbus_writeb(value, &sun_fdc->status_82077);
break; break;
}; }
return; return;
} }
......
...@@ -318,6 +318,9 @@ struct device_node; ...@@ -318,6 +318,9 @@ struct device_node;
extern unsigned int leon_build_device_irq(unsigned int real_irq, extern unsigned int leon_build_device_irq(unsigned int real_irq,
irq_flow_handler_t flow_handler, irq_flow_handler_t flow_handler,
const char *name, int do_ack); const char *name, int do_ack);
extern void leon_update_virq_handling(unsigned int virq,
irq_flow_handler_t flow_handler,
const char *name, int do_ack);
extern void leon_clear_clock_irq(void); extern void leon_clear_clock_irq(void);
extern void leon_load_profile_irq(int cpu, unsigned int limit); extern void leon_load_profile_irq(int cpu, unsigned int limit);
extern void leon_init_timers(irq_handler_t counter_fn); extern void leon_init_timers(irq_handler_t counter_fn);
......
/*
* asm/leon_pci.h
*
* Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom
*/
#ifndef _ASM_LEON_PCI_H_
#define _ASM_LEON_PCI_H_
/* PCI related definitions */
struct leon_pci_info {
struct pci_ops *ops;
struct resource io_space;
struct resource mem_space;
int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
};
extern void leon_pci_init(struct platform_device *ofdev,
struct leon_pci_info *info);
#endif /* _ASM_LEON_PCI_H_ */
...@@ -47,7 +47,31 @@ extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev); ...@@ -47,7 +47,31 @@ extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#ifndef CONFIG_LEON_PCI
/* generic pci stuff */ /* generic pci stuff */
#include <asm-generic/pci.h> #include <asm-generic/pci.h>
#else
/*
* On LEON PCI Memory space is mapped 1:1 with physical address space.
*
* I/O space is located at low 64Kbytes in PCI I/O space. The I/O addresses
* are converted into CPU addresses to virtual addresses that are mapped with
* MMU to the PCI Host PCI I/O space window which are translated to the low
* 64Kbytes by the Host controller.
*/
extern void
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res);
extern void
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region);
static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
{
return PCI_IRQ_NONE;
}
#endif
#endif /* __SPARC_PCI_H */ #endif /* __SPARC_PCI_H */
...@@ -29,7 +29,7 @@ struct linux_pcic { ...@@ -29,7 +29,7 @@ struct linux_pcic {
int pcic_imdim; int pcic_imdim;
}; };
#ifdef CONFIG_PCI #ifdef CONFIG_PCIC_PCI
extern int pcic_present(void); extern int pcic_present(void);
extern int pcic_probe(void); extern int pcic_probe(void);
extern void pci_time_init(void); extern void pci_time_init(void);
......
...@@ -220,7 +220,7 @@ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int ...@@ -220,7 +220,7 @@ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int
switch (size) { switch (size) {
case 4: case 4:
return xchg_u32(ptr, x); return xchg_u32(ptr, x);
}; }
__xchg_called_with_bad_pointer(); __xchg_called_with_bad_pointer();
return x; return x;
} }
......
...@@ -234,7 +234,7 @@ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, ...@@ -234,7 +234,7 @@ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
return xchg32(ptr, x); return xchg32(ptr, x);
case 8: case 8:
return xchg64(ptr, x); return xchg64(ptr, x);
}; }
__xchg_called_with_bad_pointer(); __xchg_called_with_bad_pointer();
return x; return x;
} }
......
...@@ -73,7 +73,9 @@ obj-$(CONFIG_SPARC64_SMP) += cpumap.o ...@@ -73,7 +73,9 @@ obj-$(CONFIG_SPARC64_SMP) += cpumap.o
obj-y += dma.o obj-y += dma.o
obj-$(CONFIG_SPARC32_PCI) += pcic.o obj-$(CONFIG_PCIC_PCI) += pcic.o
obj-$(CONFIG_LEON_PCI) += leon_pci.o
obj-$(CONFIG_GRPCI2) += leon_pci_grpci2.o
obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o
obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o
......
...@@ -123,7 +123,7 @@ static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg) ...@@ -123,7 +123,7 @@ static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg)
default: default:
return -EINVAL; return -EINVAL;
}; }
return 0; return 0;
} }
......
...@@ -101,7 +101,7 @@ void set_auxio(unsigned char bits_on, unsigned char bits_off) ...@@ -101,7 +101,7 @@ void set_auxio(unsigned char bits_on, unsigned char bits_off)
break; break;
default: default:
panic("Can't set AUXIO register on this machine."); panic("Can't set AUXIO register on this machine.");
}; }
spin_unlock_irqrestore(&auxio_lock, flags); spin_unlock_irqrestore(&auxio_lock, flags);
} }
EXPORT_SYMBOL(set_auxio); EXPORT_SYMBOL(set_auxio);
......
...@@ -664,7 +664,7 @@ static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 va ...@@ -664,7 +664,7 @@ static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 va
case 0x0: case 0x0:
bp->interleave = 16; bp->interleave = 16;
break; break;
}; }
/* UK[10] is reserved, and UK[11] is not set for the SDRAM /* UK[10] is reserved, and UK[11] is not set for the SDRAM
* bank size definition. * bank size definition.
......
...@@ -229,7 +229,7 @@ real_irq_entry: ...@@ -229,7 +229,7 @@ real_irq_entry:
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
.globl patchme_maybe_smp_msg .globl patchme_maybe_smp_msg
cmp %l7, 12 cmp %l7, 11
patchme_maybe_smp_msg: patchme_maybe_smp_msg:
bgu maybe_smp4m_msg bgu maybe_smp4m_msg
nop nop
...@@ -293,7 +293,7 @@ maybe_smp4m_msg: ...@@ -293,7 +293,7 @@ maybe_smp4m_msg:
WRITE_PAUSE WRITE_PAUSE
wr %l4, PSR_ET, %psr wr %l4, PSR_ET, %psr
WRITE_PAUSE WRITE_PAUSE
sll %o2, 28, %o2 ! shift for simpler checks below sll %o3, 28, %o2 ! shift for simpler checks below
maybe_smp4m_msg_check_single: maybe_smp4m_msg_check_single:
andcc %o2, 0x1, %g0 andcc %o2, 0x1, %g0
beq,a maybe_smp4m_msg_check_mask beq,a maybe_smp4m_msg_check_mask
...@@ -1604,7 +1604,7 @@ restore_current: ...@@ -1604,7 +1604,7 @@ restore_current:
retl retl
nop nop
#ifdef CONFIG_PCI #ifdef CONFIG_PCIC_PCI
#include <asm/pcic.h> #include <asm/pcic.h>
.align 4 .align 4
...@@ -1650,7 +1650,7 @@ pcic_nmi_trap_patch: ...@@ -1650,7 +1650,7 @@ pcic_nmi_trap_patch:
rd %psr, %l0 rd %psr, %l0
.word 0 .word 0
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCIC_PCI */
.globl flushw_all .globl flushw_all
flushw_all: flushw_all:
......
...@@ -236,6 +236,21 @@ static unsigned int _leon_build_device_irq(struct platform_device *op, ...@@ -236,6 +236,21 @@ static unsigned int _leon_build_device_irq(struct platform_device *op,
return leon_build_device_irq(real_irq, handle_simple_irq, "edge", 0); return leon_build_device_irq(real_irq, handle_simple_irq, "edge", 0);
} }
void leon_update_virq_handling(unsigned int virq,
irq_flow_handler_t flow_handler,
const char *name, int do_ack)
{
unsigned long mask = (unsigned long)irq_get_chip_data(virq);
mask &= ~LEON_DO_ACK_HW;
if (do_ack)
mask |= LEON_DO_ACK_HW;
irq_set_chip_and_handler_name(virq, &leon_irq,
flow_handler, name);
irq_set_chip_data(virq, (void *)mask);
}
void __init leon_init_timers(irq_handler_t counter_fn) void __init leon_init_timers(irq_handler_t counter_fn)
{ {
int irq, eirq; int irq, eirq;
...@@ -361,6 +376,22 @@ void __init leon_init_timers(irq_handler_t counter_fn) ...@@ -361,6 +376,22 @@ void __init leon_init_timers(irq_handler_t counter_fn)
prom_halt(); prom_halt();
} }
#ifdef CONFIG_SMP
{
unsigned long flags;
/*
* In SMP, sun4m adds a IPI handler to IRQ trap handler that
* LEON never must take, sun4d and LEON overwrites the branch
* with a NOP.
*/
local_irq_save(flags);
patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
local_flush_cache_all();
local_irq_restore(flags);
}
#endif
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
LEON3_GPTIMER_EN | LEON3_GPTIMER_EN |
LEON3_GPTIMER_RL | LEON3_GPTIMER_RL |
......
/*
* leon_pci.c: LEON Host PCI support
*
* Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom
*
* Code is partially derived from pcic.c
*/
#include <linux/of_device.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/leon.h>
#include <asm/leon_pci.h>
/* The LEON architecture does not rely on a BIOS or bootloader to setup
* PCI for us. The Linux generic routines are used to setup resources,
* reset values of confuration-space registers settings ae preseved.
*/
void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
{
struct pci_bus *root_bus;
root_bus = pci_scan_bus_parented(&ofdev->dev, 0, info->ops, info);
if (root_bus) {
root_bus->resource[0] = &info->io_space;
root_bus->resource[1] = &info->mem_space;
root_bus->resource[2] = NULL;
/* Init all PCI devices into PCI tree */
pci_bus_add_devices(root_bus);
/* Setup IRQs of all devices using custom routines */
pci_fixup_irqs(pci_common_swizzle, info->map_irq);
/* Assign devices with resources */
pci_assign_unassigned_resources();
}
}
/* PCI Memory and Prefetchable Memory is direct-mapped. However I/O Space is
* accessed through a Window which is translated to low 64KB in PCI space, the
* first 4KB is not used so 60KB is available.
*
* This function is used by generic code to translate resource addresses into
* PCI addresses.
*/
void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
{
struct leon_pci_info *info = dev->bus->sysdata;
region->start = res->start;
region->end = res->end;
if (res->flags & IORESOURCE_IO) {
region->start -= (info->io_space.start - 0x1000);
region->end -= (info->io_space.start - 0x1000);
}
}
EXPORT_SYMBOL(pcibios_resource_to_bus);
/* see pcibios_resource_to_bus() comment */
void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region)
{
struct leon_pci_info *info = dev->bus->sysdata;
res->start = region->start;
res->end = region->end;
if (res->flags & IORESOURCE_IO) {
res->start += (info->io_space.start - 0x1000);
res->end += (info->io_space.start - 0x1000);
}
}
EXPORT_SYMBOL(pcibios_bus_to_resource);
void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
{
struct leon_pci_info *info = pbus->sysdata;
struct pci_dev *dev;
int i, has_io, has_mem;
u16 cmd;
/* Generic PCI bus probing sets these to point at
* &io{port,mem}_resouce which is wrong for us.
*/
if (pbus->self == NULL) {
pbus->resource[0] = &info->io_space;
pbus->resource[1] = &info->mem_space;
pbus->resource[2] = NULL;
}
list_for_each_entry(dev, &pbus->devices, bus_list) {
/*
* We can not rely on that the bootloader has enabled I/O
* or memory access to PCI devices. Instead we enable it here
* if the device has BARs of respective type.
*/
has_io = has_mem = 0;
for (i = 0; i < PCI_ROM_RESOURCE; i++) {
unsigned long f = dev->resource[i].flags;
if (f & IORESOURCE_IO)
has_io = 1;
else if (f & IORESOURCE_MEM)
has_mem = 1;
}
/* ROM BARs are mapped into 32-bit memory space */
if (dev->resource[PCI_ROM_RESOURCE].end != 0) {
dev->resource[PCI_ROM_RESOURCE].flags |=
IORESOURCE_ROM_ENABLE;
has_mem = 1;
}
pci_bus_read_config_word(pbus, dev->devfn, PCI_COMMAND, &cmd);
if (has_io && !(cmd & PCI_COMMAND_IO)) {
#ifdef CONFIG_PCI_DEBUG
printk(KERN_INFO "LEONPCI: Enabling I/O for dev %s\n",
pci_name(dev));
#endif
cmd |= PCI_COMMAND_IO;
pci_bus_write_config_word(pbus, dev->devfn, PCI_COMMAND,
cmd);
}
if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
#ifdef CONFIG_PCI_DEBUG
printk(KERN_INFO "LEONPCI: Enabling MEMORY for dev"
"%s\n", pci_name(dev));
#endif
cmd |= PCI_COMMAND_MEMORY;
pci_bus_write_config_word(pbus, dev->devfn, PCI_COMMAND,
cmd);
}
}
}
/*
* Other archs parse arguments here.
*/
char * __devinit pcibios_setup(char *str)
{
return str;
}
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return res->start;
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
return pci_enable_resources(dev, mask);
}
struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
{
/*
* Currently the OpenBoot nodes are not connected with the PCI device,
* this is because the LEON PROM does not create PCI nodes. Eventually
* this will change and the same approach as pcic.c can be used to
* match PROM nodes with pci devices.
*/
return NULL;
}
EXPORT_SYMBOL(pci_device_to_OF_node);
void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
{
#ifdef CONFIG_PCI_DEBUG
printk(KERN_DEBUG "LEONPCI: Assigning IRQ %02d to %s\n", irq,
pci_name(dev));
#endif
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
/* in/out routines taken from pcic.c
*
* This probably belongs here rather than ioport.c because
* we do not want this crud linked into SBus kernels.
* Also, think for a moment about likes of floppy.c that
* include architecture specific parts. They may want to redefine ins/outs.
*
* We do not use horrible macros here because we want to
* advance pointer by sizeof(size).
*/
void outsb(unsigned long addr, const void *src, unsigned long count)
{
while (count) {
count -= 1;
outb(*(const char *)src, addr);
src += 1;
/* addr += 1; */
}
}
EXPORT_SYMBOL(outsb);
void outsw(unsigned long addr, const void *src, unsigned long count)
{
while (count) {
count -= 2;
outw(*(const short *)src, addr);
src += 2;
/* addr += 2; */
}
}
EXPORT_SYMBOL(outsw);
void outsl(unsigned long addr, const void *src, unsigned long count)
{
while (count) {
count -= 4;
outl(*(const long *)src, addr);
src += 4;
/* addr += 4; */
}
}
EXPORT_SYMBOL(outsl);
void insb(unsigned long addr, void *dst, unsigned long count)
{
while (count) {
count -= 1;
*(unsigned char *)dst = inb(addr);
dst += 1;
/* addr += 1; */
}
}
EXPORT_SYMBOL(insb);
void insw(unsigned long addr, void *dst, unsigned long count)
{
while (count) {
count -= 2;
*(unsigned short *)dst = inw(addr);
dst += 2;
/* addr += 2; */
}
}
EXPORT_SYMBOL(insw);
void insl(unsigned long addr, void *dst, unsigned long count)
{
while (count) {
count -= 4;
/*
* XXX I am sure we are in for an unaligned trap here.
*/
*(unsigned long *)dst = inl(addr);
dst += 4;
/* addr += 4; */
}
}
EXPORT_SYMBOL(insl);
此差异已折叠。
...@@ -214,7 +214,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, ...@@ -214,7 +214,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
me->name, me->name,
(int) (ELF_R_TYPE(rel[i].r_info) & 0xff)); (int) (ELF_R_TYPE(rel[i].r_info) & 0xff));
return -ENOEXEC; return -ENOEXEC;
}; }
} }
return 0; return 0;
} }
......
...@@ -281,7 +281,7 @@ static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, ...@@ -281,7 +281,7 @@ static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
case 4: case 4:
*value = ret & 0xffffffff; *value = ret & 0xffffffff;
break; break;
}; }
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
...@@ -456,7 +456,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) ...@@ -456,7 +456,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
default: default:
break; break;
}; }
} }
if (!saw_io || !saw_mem) { if (!saw_io || !saw_mem) {
......
...@@ -264,7 +264,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, ...@@ -264,7 +264,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
default: default:
type_string = "ECC Error"; type_string = "ECC Error";
break; break;
}; }
printk("%s: IOMMU Error, type[%s]\n", printk("%s: IOMMU Error, type[%s]\n",
pbm->name, type_string); pbm->name, type_string);
...@@ -319,7 +319,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, ...@@ -319,7 +319,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
default: default:
type_string = "ECC Error"; type_string = "ECC Error";
break; break;
}; }
printk("%s: IOMMU TAG(%d)[error(%s) ctx(%x) wr(%d) str(%d) " printk("%s: IOMMU TAG(%d)[error(%s) ctx(%x) wr(%d) str(%d) "
"sz(%dK) vpg(%08lx)]\n", "sz(%dK) vpg(%08lx)]\n",
pbm->name, i, type_string, pbm->name, i, type_string,
...@@ -1328,7 +1328,7 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, ...@@ -1328,7 +1328,7 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm,
default: default:
chipset_name = "SCHIZO"; chipset_name = "SCHIZO";
break; break;
}; }
/* For SCHIZO, three OBP regs: /* For SCHIZO, three OBP regs:
* 1) PBM controller regs * 1) PBM controller regs
......
...@@ -694,7 +694,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp, ...@@ -694,7 +694,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp,
case 3: case 3:
iclr = reg_base + SYSIO_ICLR_SLOT3; iclr = reg_base + SYSIO_ICLR_SLOT3;
break; break;
}; }
iclr += ((unsigned long)sbus_level - 1UL) * 8UL; iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
} }
......
...@@ -228,7 +228,7 @@ void psycho_check_iommu_error(struct pci_pbm_info *pbm, ...@@ -228,7 +228,7 @@ void psycho_check_iommu_error(struct pci_pbm_info *pbm,
default: default:
type_str = "ECC Error"; type_str = "ECC Error";
break; break;
}; }
printk(KERN_ERR "%s: IOMMU Error, type[%s]\n", printk(KERN_ERR "%s: IOMMU Error, type[%s]\n",
pbm->name, type_str); pbm->name, type_str);
......
...@@ -97,7 +97,7 @@ void sbus_set_sbus64(struct device *dev, int bursts) ...@@ -97,7 +97,7 @@ void sbus_set_sbus64(struct device *dev, int bursts)
default: default:
return; return;
}; }
val = upa_readq(cfg_reg); val = upa_readq(cfg_reg);
if (val & (1UL << 14UL)) { if (val & (1UL << 14UL)) {
...@@ -244,7 +244,7 @@ static unsigned int sbus_build_irq(struct platform_device *op, unsigned int ino) ...@@ -244,7 +244,7 @@ static unsigned int sbus_build_irq(struct platform_device *op, unsigned int ino)
case 3: case 3:
iclr = reg_base + SYSIO_ICLR_SLOT3; iclr = reg_base + SYSIO_ICLR_SLOT3;
break; break;
}; }
iclr += ((unsigned long)sbus_level - 1UL) * 8UL; iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
} }
......
...@@ -267,7 +267,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -267,7 +267,7 @@ void __init setup_arch(char **cmdline_p)
default: default:
printk("UNKNOWN!\n"); printk("UNKNOWN!\n");
break; break;
}; }
#ifdef CONFIG_DUMMY_CONSOLE #ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con; conswitchp = &dummy_con;
......
...@@ -209,7 +209,7 @@ void __init per_cpu_patch(void) ...@@ -209,7 +209,7 @@ void __init per_cpu_patch(void)
default: default:
prom_printf("Unknown cpu type, halting.\n"); prom_printf("Unknown cpu type, halting.\n");
prom_halt(); prom_halt();
}; }
*(unsigned int *) (addr + 0) = insns[0]; *(unsigned int *) (addr + 0) = insns[0];
wmb(); wmb();
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册