diff options
Diffstat (limited to 'arch')
131 files changed, 1870 insertions, 927 deletions
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index d9ee81769899..940dfb406591 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -157,14 +157,16 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data) static inline int read_int(struct task_struct *task, unsigned long addr, int * data) { - int copied = access_process_vm(task, addr, data, sizeof(int), 0); + int copied = access_process_vm(task, addr, data, sizeof(int), + FOLL_FORCE); return (copied == sizeof(int)) ? 0 : -EIO; } static inline int write_int(struct task_struct *task, unsigned long addr, int data) { - int copied = access_process_vm(task, addr, &data, sizeof(int), 1); + int copied = access_process_vm(task, addr, &data, sizeof(int), + FOLL_FORCE | FOLL_WRITE); return (copied == sizeof(int)) ? 0 : -EIO; } @@ -281,7 +283,8 @@ long arch_ptrace(struct task_struct *child, long request, /* When I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), + FOLL_FORCE); ret = -EIO; if (copied != sizeof(tmp)) break; diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b5d529fdffab..4353765a592f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -887,6 +887,11 @@ config MACH_STM32F429 depends on ARCH_STM32 default y +config MACH_STM32F746 + bool "STMicrolectronics STM32F746" + depends on ARCH_STM32 + default y + config ARCH_MPS2 bool "ARM MPS2 platform" depends on ARM_SINGLE_ARMV7M diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 03e9273f1876..08bb84f2ad58 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -1312,6 +1312,13 @@ static int init_hyp_mode(void) goto out_err; } + err = create_hyp_mappings(kvm_ksym_ref(__bss_start), + kvm_ksym_ref(__bss_stop), PAGE_HYP_RO); + if (err) { + kvm_err("Cannot map bss section\n"); + goto out_err; + } + /* * Map the Hyp stack pages */ diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 3d8cf8cbd98a..5db09014f55a 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -27,6 +27,7 @@ #include <linux/platform_data/mtd-davinci-aemif.h> #include <linux/platform_data/spi-davinci.h> #include <linux/platform_data/usb-davinci.h> +#include <linux/regulator/machine.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -106,43 +107,24 @@ static irqreturn_t da830_evm_usb_ocic_irq(int irq, void *dev_id) static __init void da830_evm_usb_init(void) { - u32 cfgchip2; int ret; - /* - * Set up USB clock/mode in the CFGCHIP2 register. - * FYI: CFGCHIP2 is 0x0000ef00 initially. - */ - cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); - - /* USB2.0 PHY reference clock is 24 MHz */ - cfgchip2 &= ~CFGCHIP2_REFFREQ; - cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ; - - /* - * Select internal reference clock for USB 2.0 PHY - * and use it as a clock source for USB 1.1 PHY - * (this is the default setting anyway). - */ - cfgchip2 &= ~CFGCHIP2_USB1PHYCLKMUX; - cfgchip2 |= CFGCHIP2_USB2PHYCLKMUX; - - /* - * We have to override VBUS/ID signals when MUSB is configured into the - * host-only mode -- ID pin will float if no cable is connected, so the - * controller won't be able to drive VBUS thinking that it's a B-device. - * Otherwise, we want to use the OTG mode and enable VBUS comparators. - */ - cfgchip2 &= ~CFGCHIP2_OTGMODE; -#ifdef CONFIG_USB_MUSB_HOST - cfgchip2 |= CFGCHIP2_FORCE_HOST; -#else - cfgchip2 |= CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN; -#endif + /* USB_REFCLKIN is not used. */ + ret = da8xx_register_usb20_phy_clk(false); + if (ret) + pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n", + __func__, ret); + + ret = da8xx_register_usb11_phy_clk(false); + if (ret) + pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n", + __func__, ret); - __raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); + ret = da8xx_register_usb_phy(); + if (ret) + pr_warn("%s: USB PHY registration failed: %d\n", + __func__, ret); - /* USB_REFCLKIN is not used. */ ret = davinci_cfg_reg(DA830_USB0_DRVVBUS); if (ret) pr_warn("%s: USB 2.0 PinMux setup failed: %d\n", __func__, ret); @@ -588,6 +570,10 @@ static __init void da830_evm_init(void) struct davinci_soc_info *soc_info = &davinci_soc_info; int ret; + ret = da8xx_register_cfgchip(); + if (ret) + pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret); + ret = da830_register_gpio(); if (ret) pr_warn("%s: GPIO init failed: %d\n", __func__, ret); @@ -647,6 +633,8 @@ static __init void da830_evm_init(void) ret = da8xx_register_spi_bus(0, ARRAY_SIZE(da830evm_spi_info)); if (ret) pr_warn("%s: spi 0 registration failed: %d\n", __func__, ret); + + regulator_has_full_constraints(); } #ifdef CONFIG_SERIAL_8250_CONSOLE diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 8e4539f69fdc..ec5cb105e1d6 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -1345,6 +1345,10 @@ static __init void da850_evm_init(void) { int ret; + ret = da8xx_register_cfgchip(); + if (ret) + pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret); + ret = da850_register_gpio(); if (ret) pr_warn("%s: GPIO init failed: %d\n", __func__, ret); diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index bc4e63fa9808..1a6d430742d4 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -514,6 +514,10 @@ static void __init mityomapl138_init(void) { int ret; + ret = da8xx_register_cfgchip(); + if (ret) + pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret); + /* for now, no special EDMA channels are reserved */ ret = da850_register_edma(NULL); if (ret) diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index ee624861ca66..a4e87264ebd7 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -14,6 +14,7 @@ #include <linux/console.h> #include <linux/gpio.h> #include <linux/platform_data/gpio-davinci.h> +#include <linux/regulator/machine.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -243,7 +244,6 @@ static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id) static __init void omapl138_hawk_usb_init(void) { int ret; - u32 cfgchip2; ret = davinci_cfg_reg_list(da850_hawk_usb11_pins); if (ret) { @@ -251,12 +251,20 @@ static __init void omapl138_hawk_usb_init(void) return; } - /* Setup the Ref. clock frequency for the HAWK at 24 MHz. */ + ret = da8xx_register_usb20_phy_clk(false); + if (ret) + pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n", + __func__, ret); + + ret = da8xx_register_usb11_phy_clk(false); + if (ret) + pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n", + __func__, ret); - cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); - cfgchip2 &= ~CFGCHIP2_REFFREQ; - cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ; - __raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); + ret = da8xx_register_usb_phy(); + if (ret) + pr_warn("%s: USB PHY registration failed: %d\n", + __func__, ret); ret = gpio_request_one(DA850_USB1_VBUS_PIN, GPIOF_DIR_OUT, "USB1 VBUS"); @@ -292,6 +300,10 @@ static __init void omapl138_hawk_init(void) { int ret; + ret = da8xx_register_cfgchip(); + if (ret) + pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret); + ret = da850_register_gpio(); if (ret) pr_warn("%s: GPIO init failed: %d\n", __func__, ret); @@ -317,6 +329,8 @@ static __init void omapl138_hawk_init(void) if (ret) pr_warn("%s: dsp/rproc registration failed: %d\n", __func__, ret); + + regulator_has_full_constraints(); } #ifdef CONFIG_SERIAL_8250_CONSOLE diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 426fd7477357..41459bd91c85 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -412,7 +412,7 @@ static struct clk_lookup da830_clks[] = { CLK("davinci-mcasp.0", NULL, &mcasp0_clk), CLK("davinci-mcasp.1", NULL, &mcasp1_clk), CLK("davinci-mcasp.2", NULL, &mcasp2_clk), - CLK(NULL, "usb20", &usb20_clk), + CLK("musb-da8xx", "usb20", &usb20_clk), CLK(NULL, "aemif", &aemif_clk), CLK(NULL, "aintc", &aintc_clk), CLK(NULL, "secu_mgr", &secu_mgr_clk), @@ -420,7 +420,7 @@ static struct clk_lookup da830_clks[] = { CLK("davinci_mdio.0", "fck", &emac_clk), CLK(NULL, "gpio", &gpio_clk), CLK("i2c_davinci.2", NULL, &i2c1_clk), - CLK(NULL, "usb11", &usb11_clk), + CLK("ohci", "usb11", &usb11_clk), CLK(NULL, "emif3", &emif3_clk), CLK(NULL, "arm", &arm_clk), CLK(NULL, "rmii", &rmii_clk), diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index ed3d0e9f72ac..196e262b7147 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -503,8 +503,8 @@ static struct clk_lookup da850_clks[] = { CLK("da830-mmc.1", NULL, &mmcsd1_clk), CLK("ti-aemif", NULL, &aemif_clk), CLK(NULL, "aemif", &aemif_clk), - CLK(NULL, "usb11", &usb11_clk), - CLK(NULL, "usb20", &usb20_clk), + CLK("ohci", "usb11", &usb11_clk), + CLK("musb-da8xx", "usb20", &usb20_clk), CLK("spi_davinci.0", NULL, &spi0_clk), CLK("spi_davinci.1", NULL, &spi1_clk), CLK("vpif", NULL, &vpif_clk), diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c index c9f7e9274aa8..92ae093a2120 100644 --- a/arch/arm/mach-davinci/da8xx-dt.c +++ b/arch/arm/mach-davinci/da8xx-dt.c @@ -38,6 +38,10 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = { NULL), OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL), OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", NULL), + OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL), + OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci", NULL), + OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL), + OF_DEV_AUXDATA("ti,da830-usb-phy", 0x01c1417c, "da8xx-usb-phy", NULL), {} }; @@ -45,6 +49,17 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = { static void __init da850_init_machine(void) { + int ret; + + ret = da8xx_register_usb20_phy_clk(false); + if (ret) + pr_warn("%s: registering USB 2.0 PHY clock failed: %d", + __func__, ret); + ret = da8xx_register_usb11_phy_clk(false); + if (ret) + pr_warn("%s: registering USB 1.1 PHY clock failed: %d", + __func__, ret); + of_platform_default_populate(NULL, da850_auxdata_lookup, NULL); } diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index add3771d38f6..c2457b3fdb5f 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -11,6 +11,7 @@ * (at your option) any later version. */ #include <linux/init.h> +#include <linux/platform_data/syscon.h> #include <linux/platform_device.h> #include <linux/dma-contiguous.h> #include <linux/serial_8250.h> @@ -57,15 +58,6 @@ #define DA8XX_EMAC_RAM_OFFSET 0x0000 #define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K -#define DA8XX_DMA_SPI0_RX EDMA_CTLR_CHAN(0, 14) -#define DA8XX_DMA_SPI0_TX EDMA_CTLR_CHAN(0, 15) -#define DA8XX_DMA_MMCSD0_RX EDMA_CTLR_CHAN(0, 16) -#define DA8XX_DMA_MMCSD0_TX EDMA_CTLR_CHAN(0, 17) -#define DA8XX_DMA_SPI1_RX EDMA_CTLR_CHAN(0, 18) -#define DA8XX_DMA_SPI1_TX EDMA_CTLR_CHAN(0, 19) -#define DA850_DMA_MMCSD1_RX EDMA_CTLR_CHAN(1, 28) -#define DA850_DMA_MMCSD1_TX EDMA_CTLR_CHAN(1, 29) - void __iomem *da8xx_syscfg0_base; void __iomem *da8xx_syscfg1_base; @@ -964,16 +956,6 @@ static struct resource da8xx_spi0_resources[] = { .end = IRQ_DA8XX_SPINT0, .flags = IORESOURCE_IRQ, }, - [2] = { - .start = DA8XX_DMA_SPI0_RX, - .end = DA8XX_DMA_SPI0_RX, - .flags = IORESOURCE_DMA, - }, - [3] = { - .start = DA8XX_DMA_SPI0_TX, - .end = DA8XX_DMA_SPI0_TX, - .flags = IORESOURCE_DMA, - }, }; static struct resource da8xx_spi1_resources[] = { @@ -987,16 +969,6 @@ static struct resource da8xx_spi1_resources[] = { .end = IRQ_DA8XX_SPINT1, .flags = IORESOURCE_IRQ, }, - [2] = { - .start = DA8XX_DMA_SPI1_RX, - .end = DA8XX_DMA_SPI1_RX, - .flags = IORESOURCE_DMA, - }, - [3] = { - .start = DA8XX_DMA_SPI1_TX, - .end = DA8XX_DMA_SPI1_TX, - .flags = IORESOURCE_DMA, - }, }; static struct davinci_spi_platform_data da8xx_spi_pdata[] = { @@ -1089,3 +1061,30 @@ int __init da850_register_sata(unsigned long refclkpn) return platform_device_register(&da850_sata_device); } #endif + +static struct syscon_platform_data da8xx_cfgchip_platform_data = { + .label = "cfgchip", +}; + +static struct resource da8xx_cfgchip_resources[] = { + { + .start = DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP0_REG, + .end = DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP4_REG + 3, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device da8xx_cfgchip_device = { + .name = "syscon", + .id = -1, + .dev = { + .platform_data = &da8xx_cfgchip_platform_data, + }, + .num_resources = ARRAY_SIZE(da8xx_cfgchip_resources), + .resource = da8xx_cfgchip_resources, +}; + +int __init da8xx_register_cfgchip(void) +{ + return platform_device_register(&da8xx_cfgchip_device); +} diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 67d26c5bda0b..3ae70f2909b0 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -36,9 +36,6 @@ #define DM365_MMCSD0_BASE 0x01D11000 #define DM365_MMCSD1_BASE 0x01D00000 -#define DAVINCI_DMA_MMCRXEVT 26 -#define DAVINCI_DMA_MMCTXEVT 27 - void __iomem *davinci_sysmod_base; void davinci_map_sysmod(void) diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index d33322ddedab..bd50367f654e 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -397,14 +397,6 @@ static struct resource dm355_spi0_resources[] = { .start = IRQ_DM355_SPINT0_0, .flags = IORESOURCE_IRQ, }, - { - .start = 17, - .flags = IORESOURCE_DMA, - }, - { - .start = 16, - .flags = IORESOURCE_DMA, - }, }; static struct davinci_spi_platform_data dm355_spi0_pdata = { diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index ef3add999263..8be04ec95adf 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -660,14 +660,6 @@ static struct resource dm365_spi0_resources[] = { .start = IRQ_DM365_SPIINT0_0, .flags = IORESOURCE_IRQ, }, - { - .start = 17, - .flags = IORESOURCE_DMA, - }, - { - .start = 16, - .flags = IORESOURCE_DMA, - }, }; static struct platform_device dm365_spi0_device = { diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index f9f9713aacdd..43322be26bd5 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -61,6 +61,7 @@ extern unsigned int da850_max_speed; #define DA8XX_CFGCHIP1_REG 0x180 #define DA8XX_CFGCHIP2_REG 0x184 #define DA8XX_CFGCHIP3_REG 0x188 +#define DA8XX_CFGCHIP4_REG 0x18c #define DA8XX_SYSCFG1_BASE (IO_PHYS + 0x22C000) #define DA8XX_SYSCFG1_VIRT(x) (da8xx_syscfg1_base + (x)) @@ -88,8 +89,12 @@ int da850_register_edma(struct edma_rsv_info *rsv[2]); int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata); int da8xx_register_spi_bus(int instance, unsigned num_chipselect); int da8xx_register_watchdog(void); +int da8xx_register_usb_phy(void); int da8xx_register_usb20(unsigned mA, unsigned potpgt); int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata); +int da8xx_register_usb_refclkin(int rate); +int da8xx_register_usb20_phy_clk(bool use_usb_refclkin); +int da8xx_register_usb11_phy_clk(bool use_usb_refclkin); int da8xx_register_emac(void); int da8xx_register_uio_pruss(void); int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata); @@ -113,6 +118,7 @@ void da8xx_rproc_reserve_cma(void); int da8xx_register_rproc(void); int da850_register_gpio(void); int da830_register_gpio(void); +int da8xx_register_cfgchip(void); extern struct platform_device da8xx_serial_device[]; extern struct emac_platform_data da8xx_emac_pdata; diff --git a/arch/arm/mach-davinci/usb-da8xx.c b/arch/arm/mach-davinci/usb-da8xx.c index f141f5171906..b010e5f80c5f 100644 --- a/arch/arm/mach-davinci/usb-da8xx.c +++ b/arch/arm/mach-davinci/usb-da8xx.c @@ -1,21 +1,44 @@ /* * DA8xx USB */ +#include <linux/clk.h> +#include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/init.h> +#include <linux/mfd/da8xx-cfgchip.h> +#include <linux/phy/phy.h> #include <linux/platform_data/usb-davinci.h> #include <linux/platform_device.h> #include <linux/usb/musb.h> +#include <mach/clock.h> #include <mach/common.h> #include <mach/cputype.h> #include <mach/da8xx.h> #include <mach/irqs.h> +#include "clock.h" + #define DA8XX_USB0_BASE 0x01e00000 #define DA8XX_USB1_BASE 0x01e25000 -#if IS_ENABLED(CONFIG_USB_MUSB_HDRC) +static struct platform_device da8xx_usb_phy = { + .name = "da8xx-usb-phy", + .id = -1, + .dev = { + /* + * Setting init_name so that clock lookup will work in + * da8xx_register_usb11_phy_clk() even if this device is not + * registered yet. + */ + .init_name = "da8xx-usb-phy", + }, +}; + +int __init da8xx_register_usb_phy(void) +{ + return platform_device_register(&da8xx_usb_phy); +} static struct musb_hdrc_config musb_config = { .multipoint = true, @@ -45,10 +68,15 @@ static struct resource da8xx_usb20_resources[] = { static u64 usb_dmamask = DMA_BIT_MASK(32); -static struct platform_device usb_dev = { +static struct platform_device da8xx_usb20_dev = { .name = "musb-da8xx", .id = -1, .dev = { + /* + * Setting init_name so that clock lookup will work in + * usb20_phy_clk_enable() even if this device is not registered. + */ + .init_name = "musb-da8xx", .platform_data = &usb_data, .dma_mask = &usb_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), @@ -62,18 +90,9 @@ int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt) usb_data.power = mA > 510 ? 255 : mA / 2; usb_data.potpgt = (potpgt + 1) / 2; - return platform_device_register(&usb_dev); -} - -#else - -int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt) -{ - return 0; + return platform_device_register(&da8xx_usb20_dev); } -#endif /* CONFIG_USB_MUSB_HDRC */ - static struct resource da8xx_usb11_resources[] = { [0] = { .start = DA8XX_USB1_BASE, @@ -105,3 +124,236 @@ int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata) da8xx_usb11_device.dev.platform_data = pdata; return platform_device_register(&da8xx_usb11_device); } + +static struct clk usb_refclkin = { + .name = "usb_refclkin", + .set_rate = davinci_simple_set_rate, +}; + +static struct clk_lookup usb_refclkin_lookup = + CLK(NULL, "usb_refclkin", &usb_refclkin); + +/** + * da8xx_register_usb_refclkin - register USB_REFCLKIN clock + * + * @rate: The clock rate in Hz + * + * This clock is only needed if the board provides an external USB_REFCLKIN + * signal, in which case it will be used as the parent of usb20_phy_clk and/or + * usb11_phy_clk. + */ +int __init da8xx_register_usb_refclkin(int rate) +{ + int ret; + + usb_refclkin.rate = rate; + ret = clk_register(&usb_refclkin); + if (ret) + return ret; + + clkdev_add(&usb_refclkin_lookup); + + return 0; +} + +static void usb20_phy_clk_enable(struct clk *clk) +{ + struct clk *usb20_clk; + int err; + u32 val; + u32 timeout = 500000; /* 500 msec */ + + val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); + + usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20"); + if (IS_ERR(usb20_clk)) { + pr_err("could not get usb20 clk: %ld\n", PTR_ERR(usb20_clk)); + return; + } + + /* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */ + err = clk_prepare_enable(usb20_clk); + if (err) { + pr_err("failed to enable usb20 clk: %d\n", err); + clk_put(usb20_clk); + return; + } + + /* + * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1 + * host may use the PLL clock without USB 2.0 OTG being used. + */ + val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN); + val |= CFGCHIP2_PHY_PLLON; + + writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); + + while (--timeout) { + val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); + if (val & CFGCHIP2_PHYCLKGD) + goto done; + udelay(1); + } + + pr_err("Timeout waiting for USB 2.0 PHY clock good\n"); +done: + clk_disable_unprepare(usb20_clk); + clk_put(usb20_clk); +} + +static void usb20_phy_clk_disable(struct clk *clk) +{ + u32 val; + + val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); + val |= CFGCHIP2_PHYPWRDN; + writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); +} + +static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent) +{ + u32 val; + + val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); + + /* Set the mux depending on the parent clock. */ + if (parent == &usb_refclkin) { + val &= ~CFGCHIP2_USB2PHYCLKMUX; + } else if (strcmp(parent->name, "pll0_aux_clk") == 0) { + val |= CFGCHIP2_USB2PHYCLKMUX; + } else { + pr_err("Bad parent on USB 2.0 PHY clock\n"); + return -EINVAL; + } + + /* reference frequency also comes from parent clock */ + val &= ~CFGCHIP2_REFFREQ_MASK; + switch (clk_get_rate(parent)) { + case 12000000: + val |= CFGCHIP2_REFFREQ_12MHZ; + break; + case 13000000: + val |= CFGCHIP2_REFFREQ_13MHZ; + break; + case 19200000: + val |= CFGCHIP2_REFFREQ_19_2MHZ; + break; + case 20000000: + val |= CFGCHIP2_REFFREQ_20MHZ; + break; + case 24000000: + val |= CFGCHIP2_REFFREQ_24MHZ; + break; + case 26000000: + val |= CFGCHIP2_REFFREQ_26MHZ; + break; + case 38400000: + val |= CFGCHIP2_REFFREQ_38_4MHZ; + break; + case 40000000: + val |= CFGCHIP2_REFFREQ_40MHZ; + break; + case 48000000: + val |= CFGCHIP2_REFFREQ_48MHZ; + break; + default: + pr_err("Bad parent clock rate on USB 2.0 PHY clock\n"); + return -EINVAL; + } + + writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); + + return 0; +} + +static struct clk usb20_phy_clk = { + .name = "usb20_phy", + .clk_enable = usb20_phy_clk_enable, + .clk_disable = usb20_phy_clk_disable, + .set_parent = usb20_phy_clk_set_parent, +}; + +static struct clk_lookup usb20_phy_clk_lookup = + CLK("da8xx-usb-phy", "usb20_phy", &usb20_phy_clk); + +/** + * da8xx_register_usb20_phy_clk - register USB0PHYCLKMUX clock + * + * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true + * or "pll0_aux" if false. + */ +int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin) +{ + struct clk *parent; + int ret = 0; + + parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux"); + if (IS_ERR(parent)) + return PTR_ERR(parent); + + usb20_phy_clk.parent = parent; + ret = clk_register(&usb20_phy_clk); + if (!ret) + clkdev_add(&usb20_phy_clk_lookup); + + clk_put(parent); + + return ret; +} + +static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent) +{ + u32 val; + + val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); + + /* Set the USB 1.1 PHY clock mux based on the parent clock. */ + if (parent == &usb20_phy_clk) { + val &= ~CFGCHIP2_USB1PHYCLKMUX; + } else if (parent == &usb_refclkin) { + val |= CFGCHIP2_USB1PHYCLKMUX; + } else { + pr_err("Bad parent on USB 1.1 PHY clock\n"); + return -EINVAL; + } + + writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); + + return 0; +} + +static struct clk usb11_phy_clk = { + .name = "usb11_phy", + .set_parent = usb11_phy_clk_set_parent, +}; + +static struct clk_lookup usb11_phy_clk_lookup = + CLK("da8xx-usb-phy", "usb11_phy", &usb11_phy_clk); + +/** + * da8xx_register_usb11_phy_clk - register USB1PHYCLKMUX clock + * + * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true + * or "usb20_phy" if false. + */ +int __init da8xx_register_usb11_phy_clk(bool use_usb_refclkin) +{ + struct clk *parent; + int ret = 0; + + if (use_usb_refclkin) + parent = clk_get(NULL, "usb_refclkin"); + else + parent = clk_get(&da8xx_usb_phy.dev, "usb20_phy"); + if (IS_ERR(parent)) + return PTR_ERR(parent); + + usb11_phy_clk.parent = parent; + ret = clk_register(&usb11_phy_clk); + if (!ret) + clkdev_add(&usb11_phy_clk_lookup); + + clk_put(parent); + + return ret; +} diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 9155b639c9aa..936c59d0e18b 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -557,7 +557,6 @@ config SOC_VF610 bool "Vybrid Family VF610 support" select ARM_GIC if ARCH_MULTI_V7 select PINCTRL_VF610 - select PL310_ERRATA_769419 if CACHE_L2X0 help This enables support for Freescale Vybrid VF610 processor. diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c index 58a2b88233e6..6cb8a22b617d 100644 --- a/arch/arm/mach-imx/mach-imx6ul.c +++ b/arch/arm/mach-imx/mach-imx6ul.c @@ -89,6 +89,7 @@ static void __init imx6ul_init_late(void) static const char * const imx6ul_dt_compat[] __initconst = { "fsl,imx6ul", + "fsl,imx6ull", NULL, }; diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c index db9621c718ec..ba96bf979625 100644 --- a/arch/arm/mach-imx/mmdc.c +++ b/arch/arm/mach-imx/mmdc.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011,2016 Freescale Semiconductor, Inc. * Copyright 2011 Linaro Ltd. * * The code contained herein is licensed under the GNU General Public @@ -10,12 +10,16 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include <linux/hrtimer.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/perf_event.h> +#include <linux/slab.h> #include "common.h" @@ -27,8 +31,489 @@ #define BM_MMDC_MDMISC_DDR_TYPE 0x18 #define BP_MMDC_MDMISC_DDR_TYPE 0x3 +#define TOTAL_CYCLES 0x0 +#define BUSY_CYCLES 0x1 +#define READ_ACCESSES 0x2 +#define WRITE_ACCESSES 0x3 +#define READ_BYTES 0x4 +#define WRITE_BYTES 0x5 + +/* Enables, resets, freezes, overflow profiling*/ +#define DBG_DIS 0x0 +#define DBG_EN 0x1 +#define DBG_RST 0x2 +#define PRF_FRZ 0x4 +#define CYC_OVF 0x8 +#define PROFILE_SEL 0x10 + +#define MMDC_MADPCR0 0x410 +#define MMDC_MADPSR0 0x418 +#define MMDC_MADPSR1 0x41C +#define MMDC_MADPSR2 0x420 +#define MMDC_MADPSR3 0x424 +#define MMDC_MADPSR4 0x428 +#define MMDC_MADPSR5 0x42C + +#define MMDC_NUM_COUNTERS 6 + +#define MMDC_FLAG_PROFILE_SEL 0x1 + +#define to_mmdc_pmu(p) container_of(p, struct mmdc_pmu, pmu) + static int ddr_type; +struct fsl_mmdc_devtype_data { + unsigned int flags; +}; + +static const struct fsl_mmdc_devtype_data imx6q_data = { +}; + +static const struct fsl_mmdc_devtype_data imx6qp_data = { + .flags = MMDC_FLAG_PROFILE_SEL, +}; + +static const struct of_device_id imx_mmdc_dt_ids[] = { + { .compatible = "fsl,imx6q-mmdc", .data = (void *)&imx6q_data}, + { .compatible = "fsl,imx6qp-mmdc", .data = (void *)&imx6qp_data}, + { /* sentinel */ } +}; + +#ifdef CONFIG_PERF_EVENTS + +static DEFINE_IDA(mmdc_ida); + +PMU_EVENT_ATTR_STRING(total-cycles, mmdc_pmu_total_cycles, "event=0x00") +PMU_EVENT_ATTR_STRING(busy-cycles, mmdc_pmu_busy_cycles, "event=0x01") +PMU_EVENT_ATTR_STRING(read-accesses, mmdc_pmu_read_accesses, "event=0x02") +PMU_EVENT_ATTR_STRING(write-accesses, mmdc_pmu_write_accesses, "config=0x03") +PMU_EVENT_ATTR_STRING(read-bytes, mmdc_pmu_read_bytes, "event=0x04") +PMU_EVENT_ATTR_STRING(read-bytes.unit, mmdc_pmu_read_bytes_unit, "MB"); +PMU_EVENT_ATTR_STRING(read-bytes.scale, mmdc_pmu_read_bytes_scale, "0.000001"); +PMU_EVENT_ATTR_STRING(write-bytes, mmdc_pmu_write_bytes, "event=0x05") +PMU_EVENT_ATTR_STRING(write-bytes.unit, mmdc_pmu_write_bytes_unit, "MB"); +PMU_EVENT_ATTR_STRING(write-bytes.scale, mmdc_pmu_write_bytes_scale, "0.000001"); + +struct mmdc_pmu { + struct pmu pmu; + void __iomem *mmdc_base; + cpumask_t cpu; + struct hrtimer hrtimer; + unsigned int active_events; + struct device *dev; + struct perf_event *mmdc_events[MMDC_NUM_COUNTERS]; + struct hlist_node node; + struct fsl_mmdc_devtype_data *devtype_data; +}; + +/* + * Polling period is set to one second, overflow of total-cycles (the fastest + * increasing counter) takes ten seconds so one second is safe + */ +static unsigned int mmdc_pmu_poll_period_us = 1000000; + +module_param_named(pmu_pmu_poll_period_us, mmdc_pmu_poll_period_us, uint, + S_IRUGO | S_IWUSR); + +static ktime_t mmdc_pmu_timer_period(void) +{ + return ns_to_ktime((u64)mmdc_pmu_poll_period_us * 1000); +} + +static ssize_t mmdc_pmu_cpumask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mmdc_pmu *pmu_mmdc = dev_get_drvdata(dev); + + return cpumap_print_to_pagebuf(true, buf, &pmu_mmdc->cpu); +} + +static struct device_attribute mmdc_pmu_cpumask_attr = + __ATTR(cpumask, S_IRUGO, mmdc_pmu_cpumask_show, NULL); + +static struct attribute *mmdc_pmu_cpumask_attrs[] = { + &mmdc_pmu_cpumask_attr.attr, + NULL, +}; + +static struct attribute_group mmdc_pmu_cpumask_attr_group = { + .attrs = mmdc_pmu_cpumask_attrs, +}; + +static struct attribute *mmdc_pmu_events_attrs[] = { + &mmdc_pmu_total_cycles.attr.attr, + &mmdc_pmu_busy_cycles.attr.attr, + &mmdc_pmu_read_accesses.attr.attr, + &mmdc_pmu_write_accesses.attr.attr, + &mmdc_pmu_read_bytes.attr.attr, + &mmdc_pmu_read_bytes_unit.attr.attr, + &mmdc_pmu_read_bytes_scale.attr.attr, + &mmdc_pmu_write_bytes.attr.attr, + &mmdc_pmu_write_bytes_unit.attr.attr, + &mmdc_pmu_write_bytes_scale.attr.attr, + NULL, +}; + +static struct attribute_group mmdc_pmu_events_attr_group = { + .name = "events", + .attrs = mmdc_pmu_events_attrs, +}; + +PMU_FORMAT_ATTR(event, "config:0-63"); +static struct attribute *mmdc_pmu_format_attrs[] = { + &format_attr_event.attr, + NULL, +}; + +static struct attribute_group mmdc_pmu_format_attr_group = { + .name = "format", + .attrs = mmdc_pmu_format_attrs, +}; + +static const struct attribute_group *attr_groups[] = { + &mmdc_pmu_events_attr_group, + &mmdc_pmu_format_attr_group, + &mmdc_pmu_cpumask_attr_group, + NULL, +}; + +static u32 mmdc_pmu_read_counter(struct mmdc_pmu *pmu_mmdc, int cfg) +{ + void __iomem *mmdc_base, *reg; + + mmdc_base = pmu_mmdc->mmdc_base; + + switch (cfg) { + case TOTAL_CYCLES: + reg = mmdc_base + MMDC_MADPSR0; + break; + case BUSY_CYCLES: + reg = mmdc_base + MMDC_MADPSR1; + break; + case READ_ACCESSES: + reg = mmdc_base + MMDC_MADPSR2; + break; + case WRITE_ACCESSES: + reg = mmdc_base + MMDC_MADPSR3; + break; + case READ_BYTES: + reg = mmdc_base + MMDC_MADPSR4; + break; + case WRITE_BYTES: + reg = mmdc_base + MMDC_MADPSR5; + break; + default: + return WARN_ONCE(1, + "invalid configuration %d for mmdc counter", cfg); + } + return readl(reg); +} + +static int mmdc_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) +{ + struct mmdc_pmu *pmu_mmdc = hlist_entry_safe(node, struct mmdc_pmu, node); + int target; + + if (!cpumask_test_and_clear_cpu(cpu, &pmu_mmdc->cpu)) + return 0; + + target = cpumask_any_but(cpu_online_mask, cpu); + if (target >= nr_cpu_ids) + return 0; + + perf_pmu_migrate_context(&pmu_mmdc->pmu, cpu, target); + cpumask_set_cpu(target, &pmu_mmdc->cpu); + + return 0; +} + +static bool mmdc_pmu_group_event_is_valid(struct perf_event *event, + struct pmu *pmu, + unsigned long *used_counters) +{ + int cfg = event->attr.config; + + if (is_software_event(event)) + return true; + + if (event->pmu != pmu) + return false; + + return !test_and_set_bit(cfg, used_counters); +} + +/* + * Each event has a single fixed-purpose counter, so we can only have a + * single active event for each at any point in time. Here we just check + * for duplicates, and rely on mmdc_pmu_event_init to verify that the HW + * event numbers are valid. + */ +static bool mmdc_pmu_group_is_valid(struct perf_event *event) +{ + struct pmu *pmu = event->pmu; + struct perf_event *leader = event->group_leader; + struct perf_event *sibling; + unsigned long counter_mask = 0; + + set_bit(leader->attr.config, &counter_mask); + + if (event != leader) { + if (!mmdc_pmu_group_event_is_valid(event, pmu, &counter_mask)) + return false; + } + + list_for_each_entry(sibling, &leader->sibling_list, group_entry) { + if (!mmdc_pmu_group_event_is_valid(sibling, pmu, &counter_mask)) + return false; + } + + return true; +} + +static int mmdc_pmu_event_init(struct perf_event *event) +{ + struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu); + int cfg = event->attr.config; + + if (event->attr.type != event->pmu->type) + return -ENOENT; + + if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) + return -EOPNOTSUPP; + + if (event->cpu < 0) { + dev_warn(pmu_mmdc->dev, "Can't provide per-task data!\n"); + return -EOPNOTSUPP; + } + + if (event->attr.exclude_user || + event->attr.exclude_kernel || + event->attr.exclude_hv || + event->attr.exclude_idle || + event->attr.exclude_host || + event->attr.exclude_guest || + event->attr.sample_period) + return -EINVAL; + + if (cfg < 0 || cfg >= MMDC_NUM_COUNTERS) + return -EINVAL; + + if (!mmdc_pmu_group_is_valid(event)) + return -EINVAL; + + event->cpu = cpumask_first(&pmu_mmdc->cpu); + return 0; +} + +static void mmdc_pmu_event_update(struct perf_event *event) +{ + struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + u64 delta, prev_raw_count, new_raw_count; + + do { + prev_raw_count = local64_read(&hwc->prev_count); + new_raw_count = mmdc_pmu_read_counter(pmu_mmdc, + event->attr.config); + } while (local64_cmpxchg(&hwc->prev_count, prev_raw_count, + new_raw_count) != prev_raw_count); + + delta = (new_raw_count - prev_raw_count) & 0xFFFFFFFF; + + local64_add(delta, &event->count); +} + +static void mmdc_pmu_event_start(struct perf_event *event, int flags) +{ + struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + void __iomem *mmdc_base, *reg; + u32 val; + + mmdc_base = pmu_mmdc->mmdc_base; + reg = mmdc_base + MMDC_MADPCR0; + + /* + * hrtimer is required because mmdc does not provide an interrupt so + * polling is necessary + */ + hrtimer_start(&pmu_mmdc->hrtimer, mmdc_pmu_timer_period(), + HRTIMER_MODE_REL_PINNED); + + local64_set(&hwc->prev_count, 0); + + writel(DBG_RST, reg); + + val = DBG_EN; + if (pmu_mmdc->devtype_data->flags & MMDC_FLAG_PROFILE_SEL) + val |= PROFILE_SEL; + + writel(val, reg); +} + +static int mmdc_pmu_event_add(struct perf_event *event, int flags) +{ + struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; + + int cfg = event->attr.config; + + if (flags & PERF_EF_START) + mmdc_pmu_event_start(event, flags); + + if (pmu_mmdc->mmdc_events[cfg] != NULL) + return -EAGAIN; + + pmu_mmdc->mmdc_events[cfg] = event; + pmu_mmdc->active_events++; + + local64_set(&hwc->prev_count, mmdc_pmu_read_counter(pmu_mmdc, cfg)); + + return 0; +} + +static void mmdc_pmu_event_stop(struct perf_event *event, int flags) +{ + struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu); + void __iomem *mmdc_base, *reg; + + mmdc_base = pmu_mmdc->mmdc_base; + reg = mmdc_base + MMDC_MADPCR0; + + writel(PRF_FRZ, reg); + mmdc_pmu_event_update(event); +} + +static void mmdc_pmu_event_del(struct perf_event *event, int flags) +{ + struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu); + int cfg = event->attr.config; + + pmu_mmdc->mmdc_events[cfg] = NULL; + pmu_mmdc->active_events--; + + if (pmu_mmdc->active_events == 0) + hrtimer_cancel(&pmu_mmdc->hrtimer); + + mmdc_pmu_event_stop(event, PERF_EF_UPDATE); +} + +static void mmdc_pmu_overflow_handler(struct mmdc_pmu *pmu_mmdc) +{ + int i; + + for (i = 0; i < MMDC_NUM_COUNTERS; i++) { + struct perf_event *event = pmu_mmdc->mmdc_events[i]; + + if (event) + mmdc_pmu_event_update(event); + } +} + +static enum hrtimer_restart mmdc_pmu_timer_handler(struct hrtimer *hrtimer) +{ + struct mmdc_pmu *pmu_mmdc = container_of(hrtimer, struct mmdc_pmu, + hrtimer); + + mmdc_pmu_overflow_handler(pmu_mmdc); + hrtimer_forward_now(hrtimer, mmdc_pmu_timer_period()); + + return HRTIMER_RESTART; +} + +static int mmdc_pmu_init(struct mmdc_pmu *pmu_mmdc, + void __iomem *mmdc_base, struct device *dev) +{ + int mmdc_num; + + *pmu_mmdc = (struct mmdc_pmu) { + .pmu = (struct pmu) { + .task_ctx_nr = perf_invalid_context, + .attr_groups = attr_groups, + .event_init = mmdc_pmu_event_init, + .add = mmdc_pmu_event_add, + .del = mmdc_pmu_event_del, + .start = mmdc_pmu_event_start, + .stop = mmdc_pmu_event_stop, + .read = mmdc_pmu_event_update, + }, + .mmdc_base = mmdc_base, + .dev = dev, + .active_events = 0, + }; + + mmdc_num = ida_simple_get(&mmdc_ida, 0, 0, GFP_KERNEL); + + return mmdc_num; +} + +static int imx_mmdc_remove(struct platform_device *pdev) +{ + struct mmdc_pmu *pmu_mmdc = platform_get_drvdata(pdev); + + perf_pmu_unregister(&pmu_mmdc->pmu); + cpuhp_remove_state_nocalls(CPUHP_ONLINE); + kfree(pmu_mmdc); + return 0; +} + +static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_base) +{ + struct mmdc_pmu *pmu_mmdc; + char *name; + int mmdc_num; + int ret; + const struct of_device_id *of_id = + of_match_device(imx_mmdc_dt_ids, &pdev->dev); + + pmu_mmdc = kzalloc(sizeof(*pmu_mmdc), GFP_KERNEL); + if (!pmu_mmdc) { + pr_err("failed to allocate PMU device!\n"); + return -ENOMEM; + } + + mmdc_num = mmdc_pmu_init(pmu_mmdc, mmdc_base, &pdev->dev); + if (mmdc_num == 0) + name = "mmdc"; + else + name = devm_kasprintf(&pdev->dev, + GFP_KERNEL, "mmdc%d", mmdc_num); + + pmu_mmdc->devtype_data = (struct fsl_mmdc_devtype_data *)of_id->data; + + hrtimer_init(&pmu_mmdc->hrtimer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + pmu_mmdc->hrtimer.function = mmdc_pmu_timer_handler; + + cpuhp_state_add_instance_nocalls(CPUHP_ONLINE, + &pmu_mmdc->node); + cpumask_set_cpu(smp_processor_id(), &pmu_mmdc->cpu); + ret = cpuhp_setup_state_multi(CPUHP_AP_NOTIFY_ONLINE, + "MMDC_ONLINE", NULL, + mmdc_pmu_offline_cpu); + if (ret) { + pr_err("cpuhp_setup_state_multi failure\n"); + goto pmu_register_err; + } + + ret = perf_pmu_register(&(pmu_mmdc->pmu), name, -1); + platform_set_drvdata(pdev, pmu_mmdc); + if (ret) + goto pmu_register_err; + return 0; + +pmu_register_err: + pr_warn("MMDC Perf PMU failed (%d), disabled\n", ret); + hrtimer_cancel(&pmu_mmdc->hrtimer); + kfree(pmu_mmdc); + return ret; +} + +#else +#define imx_mmdc_remove NULL +#define imx_mmdc_perf_init(pdev, mmdc_base) 0 +#endif + static int imx_mmdc_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -62,7 +547,7 @@ static int imx_mmdc_probe(struct platform_device *pdev) return -EBUSY; } - return 0; + return imx_mmdc_perf_init(pdev, mmdc_base); } int imx_mmdc_get_ddr_type(void) @@ -70,17 +555,13 @@ int imx_mmdc_get_ddr_type(void) return ddr_type; } -static const struct of_device_id imx_mmdc_dt_ids[] = { - { .compatible = "fsl,imx6q-mmdc", }, - { /* sentinel */ } -}; - static struct platform_driver imx_mmdc_driver = { .driver = { .name = "imx-mmdc", .of_match_table = imx_mmdc_dt_ids, }, .probe = imx_mmdc_probe, + .remove = imx_mmdc_remove, }; static int __init imx_mmdc_init(void) diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 23b98fd414bf..a1af634f8709 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -27,6 +27,8 @@ #include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/termios.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -37,11 +39,8 @@ #include "pci_v3.h" #include "lm.h" -/* Base address to the AP system controller */ -void __iomem *ap_syscon_base; -/* Base address to the external bus interface */ -static void __iomem *ebi_base; - +/* Regmap to the AP system controller */ +static struct regmap *ap_syscon_map; /* * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx @@ -125,6 +124,7 @@ static void integrator_uart_set_mctrl(struct amba_device *dev, { unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask; u32 phybase = dev->res.start; + int ret; if (phybase == INTEGRATOR_UART0_BASE) { /* UART0 */ @@ -146,8 +146,17 @@ static void integrator_uart_set_mctrl(struct amba_device *dev, else ctrls |= dtr_mask; - __raw_writel(ctrls, ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET); - __raw_writel(ctrlc, ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); + ret = regmap_write(ap_syscon_map, + INTEGRATOR_SC_CTRLS_OFFSET, + ctrls); + if (ret) + pr_err("MODEM: unable to write PL010 UART CTRLS\n"); + + ret = regmap_write(ap_syscon_map, + INTEGRATOR_SC_CTRLC_OFFSET, + ctrlc); + if (ret) + pr_err("MODEM: unable to write PL010 UART CRTLC\n"); } struct amba_pl010_data ap_uart_data = { @@ -178,35 +187,32 @@ static const struct of_device_id ap_syscon_match[] = { { }, }; -static const struct of_device_id ebi_match[] = { - { .compatible = "arm,external-bus-interface"}, - { }, -}; - static void __init ap_init_of(void) { - unsigned long sc_dec; + u32 sc_dec; struct device_node *syscon; - struct device_node *ebi; + int ret; int i; + of_platform_default_populate(NULL, ap_auxdata_lookup, NULL); + syscon = of_find_matching_node(NULL, ap_syscon_match); if (!syscon) return; - ebi = of_find_matching_node(NULL, ebi_match); - if (!ebi) + ap_syscon_map = syscon_node_to_regmap(syscon); + if (IS_ERR(ap_syscon_map)) { + pr_crit("could not find Integrator/AP system controller\n"); return; + } - ap_syscon_base = of_iomap(syscon, 0); - if (!ap_syscon_base) - return; - ebi_base = of_iomap(ebi, 0); - if (!ebi_base) + ret = regmap_read(ap_syscon_map, + INTEGRATOR_SC_DEC_OFFSET, + &sc_dec); + if (ret) { + pr_crit("could not read from Integrator/AP syscon\n"); return; + } - of_platform_default_populate(NULL, ap_auxdata_lookup, NULL); - - sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET); for (i = 0; i < 4; i++) { struct lm_device *lmdev; diff --git a/arch/arm/mach-lpc32xx/clock.h b/arch/arm/mach-lpc32xx/clock.h deleted file mode 100644 index c0a8434307f7..000000000000 --- a/arch/arm/mach-lpc32xx/clock.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * arch/arm/mach-lpc32xx/clock.h - * - * Author: Kevin Wells <kevin.wells@nxp.com> - * - * Copyright (C) 2010 NXP Semiconductors - * - * 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. - */ - -#ifndef __LPC32XX_CLOCK_H -#define __LPC32XX_CLOCK_H - -struct clk { - struct list_head node; - struct clk *parent; - u32 rate; - u32 usecount; - - int (*set_rate) (struct clk *, unsigned long); - unsigned long (*round_rate) (struct clk *, unsigned long); - unsigned long (*get_rate) (struct clk *clk); - int (*enable) (struct clk *, int); - - /* Register address and bit mask for simple clocks */ - void __iomem *enable_reg; - u32 enable_mask; -}; - -#endif diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h index 30c9e64fc65b..02575c2444e4 100644 --- a/arch/arm/mach-lpc32xx/common.h +++ b/arch/arm/mach-lpc32xx/common.h @@ -24,7 +24,6 @@ /* * Other arch specific structures and functions */ -extern void __init lpc32xx_init_irq(void); extern void __init lpc32xx_map_io(void); extern void __init lpc32xx_serial_init(void); diff --git a/arch/arm/mach-lpc32xx/include/mach/irqs.h b/arch/arm/mach-lpc32xx/include/mach/irqs.h deleted file mode 100644 index 00190535df90..000000000000 --- a/arch/arm/mach-lpc32xx/include/mach/irqs.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * arch/arm/mach-lpc32xx/include/mach/irqs.h - * - * Author: Kevin Wells <kevin.wells@nxp.com> - * - * Copyright (C) 2010 NXP Semiconductors - * - * 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. - */ - -#ifndef __ASM_ARM_ARCH_IRQS_H -#define __ASM_ARM_ARCH_IRQS_H - -#define LPC32XX_SIC1_IRQ(n) (32 + (n)) -#define LPC32XX_SIC2_IRQ(n) (64 + (n)) - -/* - * MIC interrupts - */ -#define IRQ_LPC32XX_SUB1IRQ 0 -#define IRQ_LPC32XX_SUB2IRQ 1 -#define IRQ_LPC32XX_PWM3 3 -#define IRQ_LPC32XX_PWM4 4 -#define IRQ_LPC32XX_HSTIMER 5 -#define IRQ_LPC32XX_WATCH 6 -#define IRQ_LPC32XX_UART_IIR3 7 -#define IRQ_LPC32XX_UART_IIR4 8 -#define IRQ_LPC32XX_UART_IIR5 9 -#define IRQ_LPC32XX_UART_IIR6 10 -#define IRQ_LPC32XX_FLASH 11 -#define IRQ_LPC32XX_SD1 13 -#define IRQ_LPC32XX_LCD 14 -#define IRQ_LPC32XX_SD0 15 -#define IRQ_LPC32XX_TIMER0 16 -#define IRQ_LPC32XX_TIMER1 17 -#define IRQ_LPC32XX_TIMER2 18 -#define IRQ_LPC32XX_TIMER3 19 -#define IRQ_LPC32XX_SSP0 20 -#define IRQ_LPC32XX_SSP1 21 -#define IRQ_LPC32XX_I2S0 22 -#define IRQ_LPC32XX_I2S1 23 -#define IRQ_LPC32XX_UART_IIR7 24 -#define IRQ_LPC32XX_UART_IIR2 25 -#define IRQ_LPC32XX_UART_IIR1 26 -#define IRQ_LPC32XX_MSTIMER 27 -#define IRQ_LPC32XX_DMA 28 -#define IRQ_LPC32XX_ETHERNET 29 -#define IRQ_LPC32XX_SUB1FIQ 30 -#define IRQ_LPC32XX_SUB2FIQ 31 - -/* - * SIC1 interrupts start at offset 32 - */ -#define IRQ_LPC32XX_JTAG_COMM_TX LPC32XX_SIC1_IRQ(1) -#define IRQ_LPC32XX_JTAG_COMM_RX LPC32XX_SIC1_IRQ(2) -#define IRQ_LPC32XX_GPI_28 LPC32XX_SIC1_IRQ(4) -#define IRQ_LPC32XX_TS_P LPC32XX_SIC1_IRQ(6) -#define IRQ_LPC32XX_TS_IRQ LPC32XX_SIC1_IRQ(7) -#define IRQ_LPC32XX_TS_AUX LPC32XX_SIC1_IRQ(8) -#define IRQ_LPC32XX_SPI2 LPC32XX_SIC1_IRQ(12) -#define IRQ_LPC32XX_PLLUSB LPC32XX_SIC1_IRQ(13) -#define IRQ_LPC32XX_PLLHCLK LPC32XX_SIC1_IRQ(14) -#define IRQ_LPC32XX_PLL397 LPC32XX_SIC1_IRQ(17) -#define IRQ_LPC32XX_I2C_2 LPC32XX_SIC1_IRQ(18) -#define IRQ_LPC32XX_I2C_1 LPC32XX_SIC1_IRQ(19) -#define IRQ_LPC32XX_RTC LPC32XX_SIC1_IRQ(20) -#define IRQ_LPC32XX_KEY LPC32XX_SIC1_IRQ(22) -#define IRQ_LPC32XX_SPI1 LPC32XX_SIC1_IRQ(23) -#define IRQ_LPC32XX_SW LPC32XX_SIC1_IRQ(24) -#define IRQ_LPC32XX_USB_OTG_TIMER LPC32XX_SIC1_IRQ(25) -#define IRQ_LPC32XX_USB_OTG_ATX LPC32XX_SIC1_IRQ(26) -#define IRQ_LPC32XX_USB_HOST LPC32XX_SIC1_IRQ(27) -#define IRQ_LPC32XX_USB_DEV_DMA LPC32XX_SIC1_IRQ(28) -#define IRQ_LPC32XX_USB_DEV_LP LPC32XX_SIC1_IRQ(29) -#define IRQ_LPC32XX_USB_DEV_HP LPC32XX_SIC1_IRQ(30) -#define IRQ_LPC32XX_USB_I2C LPC32XX_SIC1_IRQ(31) - -/* - * SIC2 interrupts start at offset 64 - */ -#define IRQ_LPC32XX_GPIO_00 LPC32XX_SIC2_IRQ(0) -#define IRQ_LPC32XX_GPIO_01 LPC32XX_SIC2_IRQ(1) -#define IRQ_LPC32XX_GPIO_02 LPC32XX_SIC2_IRQ(2) -#define IRQ_LPC32XX_GPIO_03 LPC32XX_SIC2_IRQ(3) -#define IRQ_LPC32XX_GPIO_04 LPC32XX_SIC2_IRQ(4) -#define IRQ_LPC32XX_GPIO_05 LPC32XX_SIC2_IRQ(5) -#define IRQ_LPC32XX_SPI2_DATAIN LPC32XX_SIC2_IRQ(6) -#define IRQ_LPC32XX_U2_HCTS LPC32XX_SIC2_IRQ(7) -#define IRQ_LPC32XX_P0_P1_IRQ LPC32XX_SIC2_IRQ(8) -#define IRQ_LPC32XX_GPI_08 LPC32XX_SIC2_IRQ(9) -#define IRQ_LPC32XX_GPI_09 LPC32XX_SIC2_IRQ(10) -#define IRQ_LPC32XX_GPI_19 LPC32XX_SIC2_IRQ(11) -#define IRQ_LPC32XX_U7_HCTS LPC32XX_SIC2_IRQ(12) -#define IRQ_LPC32XX_GPI_07 LPC32XX_SIC2_IRQ(15) -#define IRQ_LPC32XX_SDIO LPC32XX_SIC2_IRQ(18) -#define IRQ_LPC32XX_U5_RX LPC32XX_SIC2_IRQ(19) -#define IRQ_LPC32XX_SPI1_DATAIN LPC32XX_SIC2_IRQ(20) -#define IRQ_LPC32XX_GPI_00 LPC32XX_SIC2_IRQ(22) -#define IRQ_LPC32XX_GPI_01 LPC32XX_SIC2_IRQ(23) -#define IRQ_LPC32XX_GPI_02 LPC32XX_SIC2_IRQ(24) -#define IRQ_LPC32XX_GPI_03 LPC32XX_SIC2_IRQ(25) -#define IRQ_LPC32XX_GPI_04 LPC32XX_SIC2_IRQ(26) -#define IRQ_LPC32XX_GPI_05 LPC32XX_SIC2_IRQ(27) -#define IRQ_LPC32XX_GPI_06 LPC32XX_SIC2_IRQ(28) -#define IRQ_LPC32XX_SYSCLK LPC32XX_SIC2_IRQ(31) - -#define LPC32XX_NR_IRQS 96 - -#endif diff --git a/arch/arm/mach-lpc32xx/pm.c b/arch/arm/mach-lpc32xx/pm.c index 207e81275ff0..62471570d586 100644 --- a/arch/arm/mach-lpc32xx/pm.c +++ b/arch/arm/mach-lpc32xx/pm.c @@ -73,7 +73,6 @@ #include <mach/hardware.h> #include <mach/platform.h> #include "common.h" -#include "clock.h" #define TEMP_IRAM_AREA IO_ADDRESS(LPC32XX_IRAM_BASE) diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile index 21164605b83f..dadae67d79b7 100644 --- a/arch/arm/mach-mediatek/Makefile +++ b/arch/arm/mach-mediatek/Makefile @@ -1,4 +1,2 @@ -ifeq ($(CONFIG_SMP),y) -obj-$(CONFIG_ARCH_MEDIATEK) += platsmp.o -endif -obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o +obj-$(CONFIG_SMP) += platsmp.o +obj-y += mediatek.o diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 9b1ef53c16d0..469894082fea 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -77,7 +77,7 @@ endif # Power Management omap-4-5-pm-common = omap-mpuss-lowpower.o obj-$(CONFIG_ARCH_OMAP4) += $(omap-4-5-pm-common) -obj-$(CONFIG_ARCH_OMAP5) += $(omap-4-5-pm-common) +obj-$(CONFIG_SOC_OMAP5) += $(omap-4-5-pm-common) obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o ifeq ($(CONFIG_PM),y) diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index bab814d2f37d..981b23a39f29 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -341,6 +341,7 @@ static const char *const dra72x_boards_compat[] __initconst = { "ti,am5718", "ti,am5716", "ti,dra722", + "ti,dra718", NULL, }; diff --git a/arch/arm/mach-omap2/clockdomains7xx_data.c b/arch/arm/mach-omap2/clockdomains7xx_data.c index ef9ed36e8a61..6c679659cda5 100644 --- a/arch/arm/mach-omap2/clockdomains7xx_data.c +++ b/arch/arm/mach-omap2/clockdomains7xx_data.c @@ -409,7 +409,7 @@ static struct clockdomain l4sec_7xx_clkdm = { .dep_bit = DRA7XX_L4SEC_STATDEP_SHIFT, .wkdep_srcs = l4sec_wkup_sleep_deps, .sleepdep_srcs = l4sec_wkup_sleep_deps, - .flags = CLKDM_CAN_HWSUP_SWSUP, + .flags = CLKDM_CAN_SWSUP, }; static struct clockdomain l3main1_7xx_clkdm = { diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index 4aec2723ece7..14652e78bde7 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -253,8 +253,6 @@ extern void __iomem *omap4_get_sar_ram_base(void); extern void omap4_mpuss_early_init(void); extern void omap_do_wfi(void); -extern void omap4_secondary_startup(void); -extern void omap4460_secondary_startup(void); #ifdef CONFIG_SMP /* Needed for secondary core boot */ @@ -266,16 +264,11 @@ extern void omap4_cpu_die(unsigned int cpu); extern int omap4_cpu_kill(unsigned int cpu); extern const struct smp_operations omap4_smp_ops; - -extern void omap5_secondary_startup(void); -extern void omap5_secondary_hyp_startup(void); #endif #if defined(CONFIG_SMP) && defined(CONFIG_PM) extern int omap4_mpuss_init(void); extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state); -extern int omap4_finish_suspend(unsigned long cpu_state); -extern void omap4_cpu_resume(void); extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); #else static inline int omap4_enter_lowpower(unsigned int cpu, @@ -296,14 +289,41 @@ static inline int omap4_mpuss_init(void) return 0; } +#endif + +#ifdef CONFIG_ARCH_OMAP4 +void omap4_secondary_startup(void); +void omap4460_secondary_startup(void); +int omap4_finish_suspend(unsigned long cpu_state); +void omap4_cpu_resume(void); +#else +static inline void omap4_secondary_startup(void) +{ +} + +static inline void omap4460_secondary_startup(void) +{ +} static inline int omap4_finish_suspend(unsigned long cpu_state) { return 0; } - static inline void omap4_cpu_resume(void) -{} +{ +} +#endif +#if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX) +void omap5_secondary_startup(void); +void omap5_secondary_hyp_startup(void); +#else +static inline void omap5_secondary_startup(void) +{ +} + +static inline void omap5_secondary_hyp_startup(void) +{ +} #endif void pdata_quirks_init(const struct of_device_id *); diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index fa138d4032b6..a8b291f00109 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c @@ -21,6 +21,7 @@ #include "common.h" #include "pm.h" #include "prm.h" +#include "soc.h" #include "clockdomain.h" #define MAX_CPUS 2 @@ -30,6 +31,7 @@ struct idle_statedata { u32 cpu_state; u32 mpu_logic_state; u32 mpu_state; + u32 mpu_state_vote; }; static struct idle_statedata omap4_idle_data[] = { @@ -50,12 +52,26 @@ static struct idle_statedata omap4_idle_data[] = { }, }; +static struct idle_statedata omap5_idle_data[] = { + { + .cpu_state = PWRDM_POWER_ON, + .mpu_state = PWRDM_POWER_ON, + .mpu_logic_state = PWRDM_POWER_ON, + }, + { + .cpu_state = PWRDM_POWER_RET, + .mpu_state = PWRDM_POWER_RET, + .mpu_logic_state = PWRDM_POWER_RET, + }, +}; + static struct powerdomain *mpu_pd, *cpu_pd[MAX_CPUS]; static struct clockdomain *cpu_clkdm[MAX_CPUS]; static atomic_t abort_barrier; static bool cpu_done[MAX_CPUS]; static struct idle_statedata *state_ptr = &omap4_idle_data[0]; +static DEFINE_RAW_SPINLOCK(mpu_lock); /* Private functions */ @@ -77,6 +93,32 @@ static int omap_enter_idle_simple(struct cpuidle_device *dev, return index; } +static int omap_enter_idle_smp(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + struct idle_statedata *cx = state_ptr + index; + unsigned long flag; + + raw_spin_lock_irqsave(&mpu_lock, flag); + cx->mpu_state_vote++; + if (cx->mpu_state_vote == num_online_cpus()) { + pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state); + omap_set_pwrdm_state(mpu_pd, cx->mpu_state); + } + raw_spin_unlock_irqrestore(&mpu_lock, flag); + + omap4_enter_lowpower(dev->cpu, cx->cpu_state); + + raw_spin_lock_irqsave(&mpu_lock, flag); + if (cx->mpu_state_vote == num_online_cpus()) + omap_set_pwrdm_state(mpu_pd, PWRDM_POWER_ON); + cx->mpu_state_vote--; + raw_spin_unlock_irqrestore(&mpu_lock, flag); + + return index; +} + static int omap_enter_idle_coupled(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -220,6 +262,32 @@ static struct cpuidle_driver omap4_idle_driver = { .safe_state_index = 0, }; +static struct cpuidle_driver omap5_idle_driver = { + .name = "omap5_idle", + .owner = THIS_MODULE, + .states = { + { + /* C1 - CPU0 ON + CPU1 ON + MPU ON */ + .exit_latency = 2 + 2, + .target_residency = 5, + .enter = omap_enter_idle_simple, + .name = "C1", + .desc = "CPUx WFI, MPUSS ON" + }, + { + /* C2 - CPU0 RET + CPU1 RET + MPU CSWR */ + .exit_latency = 48 + 60, + .target_residency = 100, + .flags = CPUIDLE_FLAG_TIMER_STOP, + .enter = omap_enter_idle_smp, + .name = "C2", + .desc = "CPUx CSWR, MPUSS CSWR", + }, + }, + .state_count = ARRAY_SIZE(omap5_idle_data), + .safe_state_index = 0, +}; + /* Public functions */ /** @@ -230,6 +298,16 @@ static struct cpuidle_driver omap4_idle_driver = { */ int __init omap4_idle_init(void) { + struct cpuidle_driver *idle_driver; + + if (soc_is_omap54xx()) { + state_ptr = &omap5_idle_data[0]; + idle_driver = &omap5_idle_driver; + } else { + state_ptr = &omap4_idle_data[0]; + idle_driver = &omap4_idle_driver; + } + mpu_pd = pwrdm_lookup("mpu_pwrdm"); cpu_pd[0] = pwrdm_lookup("cpu0_pwrdm"); cpu_pd[1] = pwrdm_lookup("cpu1_pwrdm"); @@ -244,5 +322,5 @@ int __init omap4_idle_init(void) /* Configure the broadcast timer on each cpu */ on_each_cpu(omap_setup_broadcast_timer, NULL, 1); - return cpuidle_register(&omap4_idle_driver, cpu_online_mask); + return cpuidle_register(idle_driver, cpu_online_mask); } diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index b7a467651427..5aafb8449c40 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -716,10 +716,11 @@ void __init omap5_init_early(void) OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE)); omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE)); omap2_control_base_init(); - omap4_pm_init_early(); omap2_prcm_base_init(); omap5xxx_check_revision(); omap4_sar_ram_init(); + omap4_mpuss_early_init(); + omap4_pm_init_early(); omap54xx_voltagedomains_init(); omap54xx_powerdomains_init(); omap54xx_clockdomains_init(); diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index ad982465efd0..7d62ad48c7c9 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -48,6 +48,7 @@ #include <asm/smp_scu.h> #include <asm/pgalloc.h> #include <asm/suspend.h> +#include <asm/virt.h> #include <asm/hardware/cache-l2x0.h> #include "soc.h" @@ -244,10 +245,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) save_state = 1; break; case PWRDM_POWER_RET: - if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) { + if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) save_state = 0; - break; - } + break; default: /* * CPUx CSWR is invalid hardware state. Also CPUx OSWR @@ -371,8 +371,12 @@ int __init omap4_mpuss_init(void) pm_info = &per_cpu(omap4_pm_info, 0x0); if (sar_base) { pm_info->scu_sar_addr = sar_base + SCU_OFFSET0; - pm_info->wkup_sar_addr = sar_base + - CPU0_WAKEUP_NS_PA_ADDR_OFFSET; + if (cpu_is_omap44xx()) + pm_info->wkup_sar_addr = sar_base + + CPU0_WAKEUP_NS_PA_ADDR_OFFSET; + else + pm_info->wkup_sar_addr = sar_base + + OMAP5_CPU0_WAKEUP_NS_PA_ADDR_OFFSET; pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0; } pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm"); @@ -391,8 +395,12 @@ int __init omap4_mpuss_init(void) pm_info = &per_cpu(omap4_pm_info, 0x1); if (sar_base) { pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; - pm_info->wkup_sar_addr = sar_base + - CPU1_WAKEUP_NS_PA_ADDR_OFFSET; + if (cpu_is_omap44xx()) + pm_info->wkup_sar_addr = sar_base + + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; + else + pm_info->wkup_sar_addr = sar_base + + OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET; pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; } @@ -453,15 +461,24 @@ void __init omap4_mpuss_early_init(void) { unsigned long startup_pa; - if (!cpu_is_omap44xx()) + if (!(cpu_is_omap44xx() || soc_is_omap54xx())) return; sar_base = omap4_get_sar_ram_base(); if (cpu_is_omap443x()) startup_pa = virt_to_phys(omap4_secondary_startup); - else + else if (cpu_is_omap446x()) startup_pa = virt_to_phys(omap4460_secondary_startup); + else if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE) + startup_pa = virt_to_phys(omap5_secondary_hyp_startup); + else + startup_pa = virt_to_phys(omap5_secondary_startup); - writel_relaxed(startup_pa, sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET); + if (cpu_is_omap44xx()) + writel_relaxed(startup_pa, sar_base + + CPU1_WAKEUP_NS_PA_ADDR_OFFSET); + else + writel_relaxed(startup_pa, sar_base + + OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET); } diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h index 792b1069f724..5b2966a0f733 100644 --- a/arch/arm/mach-omap2/omap4-sar-layout.h +++ b/arch/arm/mach-omap2/omap4-sar-layout.h @@ -31,6 +31,8 @@ /* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */ #define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04 #define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08 +#define OMAP5_CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xe00 +#define OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xe04 #define SAR_BACKUP_STATUS_OFFSET (SAR_BANK3_OFFSET + 0x500) #define SAR_SECURE_RAM_SIZE_OFFSET (SAR_BANK3_OFFSET + 0x504) diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h index d3e61d1a02d7..434bd1a77229 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h @@ -68,6 +68,7 @@ extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart6; extern struct omap_hwmod_ocp_if am33xx_l3_main__ocmc; extern struct omap_hwmod_ocp_if am33xx_l3_main__sha0; extern struct omap_hwmod_ocp_if am33xx_l3_main__aes0; +extern struct omap_hwmod_ocp_if am33xx_l4_per__rng; extern struct omap_hwmod am33xx_l3_main_hwmod; extern struct omap_hwmod am33xx_l3_s_hwmod; @@ -80,6 +81,7 @@ extern struct omap_hwmod am33xx_gfx_hwmod; extern struct omap_hwmod am33xx_prcm_hwmod; extern struct omap_hwmod am33xx_aes0_hwmod; extern struct omap_hwmod am33xx_sha0_hwmod; +extern struct omap_hwmod am33xx_rng_hwmod; extern struct omap_hwmod am33xx_ocmcram_hwmod; extern struct omap_hwmod am33xx_smartreflex0_hwmod; extern struct omap_hwmod am33xx_smartreflex1_hwmod; diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c index 10dff2f0086a..8236e5c49ec3 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c @@ -547,3 +547,11 @@ struct omap_hwmod_ocp_if am33xx_l3_main__aes0 = { .addr = am33xx_aes0_addrs, .user = OCP_USER_MPU | OCP_USER_SDMA, }; + +/* l4 per -> rng */ +struct omap_hwmod_ocp_if am33xx_l4_per__rng = { + .master = &am33xx_l4_ls_hwmod, + .slave = &am33xx_rng_hwmod, + .clk = "rng_fck", + .user = OCP_USER_MPU, +}; diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c index e2d84aa7f595..de06a1d5ffab 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c @@ -268,6 +268,33 @@ struct omap_hwmod am33xx_sha0_hwmod = { }, }; +/* rng */ +static struct omap_hwmod_class_sysconfig am33xx_rng_sysc = { + .rev_offs = 0x1fe0, + .sysc_offs = 0x1fe4, + .sysc_flags = SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE, + .idlemodes = SIDLE_FORCE | SIDLE_NO, + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class am33xx_rng_hwmod_class = { + .name = "rng", + .sysc = &am33xx_rng_sysc, +}; + +struct omap_hwmod am33xx_rng_hwmod = { + .name = "rng", + .class = &am33xx_rng_hwmod_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_SWSUP_SIDLE, + .main_clk = "rng_fck", + .prcm = { + .omap4 = { + .modulemode = MODULEMODE_SWCTRL, + }, + }, +}; + /* ocmcram */ static struct omap_hwmod_class am33xx_ocmcram_hwmod_class = { .name = "ocmcram", @@ -1315,6 +1342,7 @@ static void omap_hwmod_am33xx_clkctrl(void) CLKCTRL(am33xx_ocmcram_hwmod , AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET); CLKCTRL(am33xx_sha0_hwmod , AM33XX_CM_PER_SHA0_CLKCTRL_OFFSET); CLKCTRL(am33xx_aes0_hwmod , AM33XX_CM_PER_AES0_CLKCTRL_OFFSET); + CLKCTRL(am33xx_rng_hwmod, AM33XX_CM_PER_RNG_CLKCTRL_OFFSET); } static void omap_hwmod_am33xx_rst(void) @@ -1388,6 +1416,7 @@ static void omap_hwmod_am43xx_clkctrl(void) CLKCTRL(am33xx_ocmcram_hwmod , AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET); CLKCTRL(am33xx_sha0_hwmod , AM43XX_CM_PER_SHA0_CLKCTRL_OFFSET); CLKCTRL(am33xx_aes0_hwmod , AM43XX_CM_PER_AES0_CLKCTRL_OFFSET); + CLKCTRL(am33xx_rng_hwmod, AM43XX_CM_PER_RNG_CLKCTRL_OFFSET); } static void omap_hwmod_am43xx_rst(void) diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c index e1c2025d6d3e..6dc51a774a26 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c @@ -503,41 +503,6 @@ static struct omap_hwmod_ocp_if am33xx_l3_s__usbss = { .flags = OCPIF_SWSUP_IDLE, }; -/* rng */ -static struct omap_hwmod_class_sysconfig am33xx_rng_sysc = { - .rev_offs = 0x1fe0, - .sysc_offs = 0x1fe4, - .sysc_flags = SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE, - .idlemodes = SIDLE_FORCE | SIDLE_NO, - .sysc_fields = &omap_hwmod_sysc_type1, -}; - -static struct omap_hwmod_class am33xx_rng_hwmod_class = { - .name = "rng", - .sysc = &am33xx_rng_sysc, -}; - -static struct omap_hwmod am33xx_rng_hwmod = { - .name = "rng", - .class = &am33xx_rng_hwmod_class, - .clkdm_name = "l4ls_clkdm", - .flags = HWMOD_SWSUP_SIDLE, - .main_clk = "rng_fck", - .prcm = { - .omap4 = { - .clkctrl_offs = AM33XX_CM_PER_RNG_CLKCTRL_OFFSET, - .modulemode = MODULEMODE_SWCTRL, - }, - }, -}; - -static struct omap_hwmod_ocp_if am33xx_l4_per__rng = { - .master = &am33xx_l4_ls_hwmod, - .slave = &am33xx_rng_hwmod, - .clk = "rng_fck", - .user = OCP_USER_MPU, -}; - static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l3_main__emif, &am33xx_mpu__l3_main, diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c index 61f2f301d739..afbce1f6f641 100644 --- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c @@ -442,6 +442,31 @@ static struct omap_hwmod am43xx_adc_tsc_hwmod = { }, }; +static struct omap_hwmod_class_sysconfig am43xx_des_sysc = { + .rev_offs = 0x30, + .sysc_offs = 0x34, + .syss_offs = 0x38, + .sysc_flags = SYSS_HAS_RESET_STATUS, +}; + +static struct omap_hwmod_class am43xx_des_hwmod_class = { + .name = "des", + .sysc = &am43xx_des_sysc, +}; + +static struct omap_hwmod am43xx_des_hwmod = { + .name = "des", + .class = &am43xx_des_hwmod_class, + .clkdm_name = "l3_clkdm", + .main_clk = "l3_gclk", + .prcm = { + .omap4 = { + .clkctrl_offs = AM43XX_CM_PER_DES_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +}; + /* dss */ static struct omap_hwmod am43xx_dss_core_hwmod = { @@ -870,6 +895,13 @@ static struct omap_hwmod_ocp_if am43xx_l4_ls__vpfe1 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +static struct omap_hwmod_ocp_if am43xx_l3_main__des = { + .master = &am33xx_l3_main_hwmod, + .slave = &am43xx_des_hwmod, + .clk = "l3_gclk", + .user = OCP_USER_MPU, +}; + static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l4_wkup__synctimer, &am43xx_l4_ls__timer8, @@ -917,6 +949,7 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l4_per__i2c2, &am33xx_l4_per__i2c3, &am33xx_l4_per__mailbox, + &am33xx_l4_per__rng, &am33xx_l4_ls__mcasp0, &am33xx_l4_ls__mcasp1, &am33xx_l4_ls__mmc0, @@ -950,6 +983,7 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { &am33xx_cpgmac0__mdio, &am33xx_l3_main__sha0, &am33xx_l3_main__aes0, + &am43xx_l3_main__des, &am43xx_l4_ls__ocp2scp0, &am43xx_l4_ls__ocp2scp1, &am43xx_l3_s__usbotgss0, diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index 1ab7096af8e2..d0585293a381 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -690,6 +690,78 @@ static struct omap_hwmod dra7xx_dss_hdmi_hwmod = { .parent_hwmod = &dra7xx_dss_hwmod, }; +/* AES (the 'P' (public) device) */ +static struct omap_hwmod_class_sysconfig dra7xx_aes_sysc = { + .rev_offs = 0x0080, + .sysc_offs = 0x0084, + .syss_offs = 0x0088, + .sysc_flags = SYSS_HAS_RESET_STATUS, +}; + +static struct omap_hwmod_class dra7xx_aes_hwmod_class = { + .name = "aes", + .sysc = &dra7xx_aes_sysc, + .rev = 2, +}; + +/* AES1 */ +static struct omap_hwmod dra7xx_aes1_hwmod = { + .name = "aes1", + .class = &dra7xx_aes_hwmod_class, + .clkdm_name = "l4sec_clkdm", + .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4SEC_AES1_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4SEC_AES1_CONTEXT_OFFSET, + .modulemode = MODULEMODE_HWCTRL, + }, + }, +}; + +/* AES2 */ +static struct omap_hwmod dra7xx_aes2_hwmod = { + .name = "aes2", + .class = &dra7xx_aes_hwmod_class, + .clkdm_name = "l4sec_clkdm", + .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4SEC_AES2_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4SEC_AES2_CONTEXT_OFFSET, + .modulemode = MODULEMODE_HWCTRL, + }, + }, +}; + +/* sha0 HIB2 (the 'P' (public) device) */ +static struct omap_hwmod_class_sysconfig dra7xx_sha0_sysc = { + .rev_offs = 0x100, + .sysc_offs = 0x110, + .syss_offs = 0x114, + .sysc_flags = SYSS_HAS_RESET_STATUS, +}; + +static struct omap_hwmod_class dra7xx_sha0_hwmod_class = { + .name = "sham", + .sysc = &dra7xx_sha0_sysc, + .rev = 2, +}; + +struct omap_hwmod dra7xx_sha0_hwmod = { + .name = "sham", + .class = &dra7xx_sha0_hwmod_class, + .clkdm_name = "l4sec_clkdm", + .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4SEC_SHA2MD51_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4SEC_SHA2MD51_CONTEXT_OFFSET, + .modulemode = MODULEMODE_HWCTRL, + }, + }, +}; + /* * 'elm' class * @@ -2541,6 +2613,62 @@ static struct omap_hwmod dra7xx_uart10_hwmod = { }, }; +/* DES (the 'P' (public) device) */ +static struct omap_hwmod_class_sysconfig dra7xx_des_sysc = { + .rev_offs = 0x0030, + .sysc_offs = 0x0034, + .syss_offs = 0x0038, + .sysc_flags = SYSS_HAS_RESET_STATUS, +}; + +static struct omap_hwmod_class dra7xx_des_hwmod_class = { + .name = "des", + .sysc = &dra7xx_des_sysc, +}; + +/* DES */ +static struct omap_hwmod dra7xx_des_hwmod = { + .name = "des", + .class = &dra7xx_des_hwmod_class, + .clkdm_name = "l4sec_clkdm", + .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4SEC_DES3DES_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4SEC_DES3DES_CONTEXT_OFFSET, + .modulemode = MODULEMODE_HWCTRL, + }, + }, +}; + +/* rng */ +static struct omap_hwmod_class_sysconfig dra7xx_rng_sysc = { + .rev_offs = 0x1fe0, + .sysc_offs = 0x1fe4, + .sysc_flags = SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE, + .idlemodes = SIDLE_FORCE | SIDLE_NO, + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class dra7xx_rng_hwmod_class = { + .name = "rng", + .sysc = &dra7xx_rng_sysc, +}; + +static struct omap_hwmod dra7xx_rng_hwmod = { + .name = "rng", + .class = &dra7xx_rng_hwmod_class, + .flags = HWMOD_SWSUP_SIDLE, + .clkdm_name = "l4sec_clkdm", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4SEC_RNG_CLKCTRL_OFFSET, + .context_offs = DRA7XX_RM_L4SEC_RNG_CONTEXT_OFFSET, + .modulemode = MODULEMODE_HWCTRL, + }, + }, +}; + /* * 'usb_otg_ss' class * @@ -2929,6 +3057,30 @@ static struct omap_hwmod_ocp_if dra7xx_l3_main_1__hdmi = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* l3_main_1 -> aes1 */ +static struct omap_hwmod_ocp_if dra7xx_l3_main_1__aes1 = { + .master = &dra7xx_l3_main_1_hwmod, + .slave = &dra7xx_aes1_hwmod, + .clk = "l3_iclk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* l3_main_1 -> aes2 */ +static struct omap_hwmod_ocp_if dra7xx_l3_main_1__aes2 = { + .master = &dra7xx_l3_main_1_hwmod, + .slave = &dra7xx_aes2_hwmod, + .clk = "l3_iclk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* l3_main_1 -> sha0 */ +static struct omap_hwmod_ocp_if dra7xx_l3_main_1__sha0 = { + .master = &dra7xx_l3_main_1_hwmod, + .slave = &dra7xx_sha0_hwmod, + .clk = "l3_iclk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* l4_per2 -> mcasp1 */ static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp1 = { .master = &dra7xx_l4_per2_hwmod, @@ -3642,6 +3794,14 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per2__uart7 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* l4_per1 -> des */ +static struct omap_hwmod_ocp_if dra7xx_l4_per1__des = { + .master = &dra7xx_l4_per1_hwmod, + .slave = &dra7xx_des_hwmod, + .clk = "l3_iclk_div", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* l4_per2 -> uart8 */ static struct omap_hwmod_ocp_if dra7xx_l4_per2__uart8 = { .master = &dra7xx_l4_per2_hwmod, @@ -3666,6 +3826,13 @@ static struct omap_hwmod_ocp_if dra7xx_l4_wkup__uart10 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* l4_per1 -> rng */ +static struct omap_hwmod_ocp_if dra7xx_l4_per1__rng = { + .master = &dra7xx_l4_per1_hwmod, + .slave = &dra7xx_rng_hwmod, + .user = OCP_USER_MPU, +}; + /* l4_per3 -> usb_otg_ss1 */ static struct omap_hwmod_ocp_if dra7xx_l4_per3__usb_otg_ss1 = { .master = &dra7xx_l4_per3_hwmod, @@ -3800,6 +3967,9 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { &dra7xx_l3_main_1__dss, &dra7xx_l3_main_1__dispc, &dra7xx_l3_main_1__hdmi, + &dra7xx_l3_main_1__aes1, + &dra7xx_l3_main_1__aes2, + &dra7xx_l3_main_1__sha0, &dra7xx_l4_per1__elm, &dra7xx_l4_wkup__gpio1, &dra7xx_l4_per1__gpio2, @@ -3845,7 +4015,6 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { &dra7xx_l3_main_1__pciess2, &dra7xx_l4_cfg__pciess2, &dra7xx_l3_main_1__qspi, - &dra7xx_l4_per3__rtcss, &dra7xx_l4_cfg__sata, &dra7xx_l4_cfg__smartreflex_core, &dra7xx_l4_cfg__smartreflex_mpu, @@ -3875,6 +4044,7 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { &dra7xx_l4_per2__uart8, &dra7xx_l4_per2__uart9, &dra7xx_l4_wkup__uart10, + &dra7xx_l4_per1__des, &dra7xx_l4_per3__usb_otg_ss1, &dra7xx_l4_per3__usb_otg_ss2, &dra7xx_l4_per3__usb_otg_ss3, @@ -3892,6 +4062,7 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { /* GP-only hwmod links */ static struct omap_hwmod_ocp_if *dra7xx_gp_hwmod_ocp_ifs[] __initdata = { &dra7xx_l4_wkup__timer12, + &dra7xx_l4_per1__rng, NULL, }; @@ -3905,6 +4076,11 @@ static struct omap_hwmod_ocp_if *dra72x_hwmod_ocp_ifs[] __initdata = { NULL, }; +static struct omap_hwmod_ocp_if *dra74x_dra72x_hwmod_ocp_ifs[] __initdata = { + &dra7xx_l4_per3__rtcss, + NULL, +}; + int __init dra7xx_hwmod_init(void) { int ret; @@ -3920,5 +4096,9 @@ int __init dra7xx_hwmod_init(void) if (!ret && omap_type() == OMAP2_DEVICE_TYPE_GP) ret = omap_hwmod_register_links(dra7xx_gp_hwmod_ocp_ifs); + /* now for the IPs *NOT* in dra71 */ + if (!ret && !of_machine_is_compatible("ti,dra718")) + ret = omap_hwmod_register_links(dra74x_dra72x_hwmod_ocp_ifs); + return ret; } diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 178e22c146b7..b3870220612e 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -287,7 +287,7 @@ int __init omap4_pm_init(void) /* Overwrite the default cpu_do_idle() */ arm_pm_idle = omap_default_idle; - if (cpu_is_omap44xx()) + if (cpu_is_omap44xx() || soc_is_omap54xx()) omap4_idle_init(); err2: diff --git a/arch/arm/mach-omap2/prcm43xx.h b/arch/arm/mach-omap2/prcm43xx.h index babb5db5a3a4..e2ad14e77064 100644 --- a/arch/arm/mach-omap2/prcm43xx.h +++ b/arch/arm/mach-omap2/prcm43xx.h @@ -92,6 +92,7 @@ #define AM43XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET 0x04b8 #define AM43XX_CM_PER_MMC0_CLKCTRL_OFFSET 0x04c0 #define AM43XX_CM_PER_MMC1_CLKCTRL_OFFSET 0x04c8 +#define AM43XX_CM_PER_RNG_CLKCTRL_OFFSET 0x04e0 #define AM43XX_CM_PER_SPI0_CLKCTRL_OFFSET 0x0500 #define AM43XX_CM_PER_SPI1_CLKCTRL_OFFSET 0x0508 #define AM43XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET 0x0528 @@ -133,6 +134,7 @@ #define AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET 0x0050 #define AM43XX_CM_PER_SHA0_CLKCTRL_OFFSET 0x0058 #define AM43XX_CM_PER_AES0_CLKCTRL_OFFSET 0x0028 +#define AM43XX_CM_PER_DES_CLKCTRL_OFFSET 0x0030 #define AM43XX_CM_PER_TIMER8_CLKCTRL_OFFSET 0x0560 #define AM43XX_CM_PER_TIMER9_CLKCTRL_OFFSET 0x0568 #define AM43XX_CM_PER_TIMER10_CLKCTRL_OFFSET 0x0570 diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 10bfdb169366..183cd3446f25 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -35,7 +35,6 @@ #include <linux/mtd/sharpsl.h> #include <linux/input/matrix_keypad.h> #include <linux/gpio_keys.h> -#include <linux/module.h> #include <linux/memblock.h> #include <video/w100fb.h> diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 03354c21e1f2..811a7317f3ea 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -23,6 +23,7 @@ #include <linux/gpio.h> #include <linux/mfd/da903x.h> #include <linux/regulator/machine.h> +#include <linux/regulator/fixed.h> #include <linux/spi/spi.h> #include <linux/spi/tdo24m.h> #include <linux/spi/libertas_spi.h> @@ -34,8 +35,6 @@ #include <linux/i2c/pxa-i2c.h> #include <linux/regulator/userspace-consumer.h> -#include <media/soc_camera.h> - #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -958,8 +957,6 @@ static inline void em_x270_init_gpio_keys(void) {} /* Quick Capture Interface and sensor setup */ #if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE) -static struct regulator *em_x270_camera_ldo; - static int em_x270_sensor_init(void) { int ret; @@ -969,81 +966,53 @@ static int em_x270_sensor_init(void) return ret; gpio_direction_output(cam_reset, 0); - - em_x270_camera_ldo = regulator_get(NULL, "vcc cam"); - if (em_x270_camera_ldo == NULL) { - gpio_free(cam_reset); - return -ENODEV; - } - - ret = regulator_enable(em_x270_camera_ldo); - if (ret) { - regulator_put(em_x270_camera_ldo); - gpio_free(cam_reset); - return ret; - } - gpio_set_value(cam_reset, 1); return 0; } -struct pxacamera_platform_data em_x270_camera_platform_data = { - .flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | - PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN, - .mclk_10khz = 2600, +static struct regulator_consumer_supply camera_dummy_supplies[] = { + REGULATOR_SUPPLY("vdd", "0-005d"), }; -static int em_x270_sensor_power(struct device *dev, int on) -{ - int ret; - int is_on = regulator_is_enabled(em_x270_camera_ldo); - - if (on == is_on) - return 0; - - gpio_set_value(cam_reset, !on); - - if (on) - ret = regulator_enable(em_x270_camera_ldo); - else - ret = regulator_disable(em_x270_camera_ldo); - - if (ret) - return ret; - - gpio_set_value(cam_reset, on); - - return 0; -} - -static struct i2c_board_info em_x270_i2c_cam_info[] = { - { - I2C_BOARD_INFO("mt9m111", 0x48), +static struct regulator_init_data camera_dummy_initdata = { + .consumer_supplies = camera_dummy_supplies, + .num_consumer_supplies = ARRAY_SIZE(camera_dummy_supplies), + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, }; -static struct soc_camera_link iclink = { - .bus_id = 0, - .power = em_x270_sensor_power, - .board_info = &em_x270_i2c_cam_info[0], - .i2c_adapter_id = 0, +static struct fixed_voltage_config camera_dummy_config = { + .supply_name = "camera_vdd", + .input_supply = "vcc cam", + .microvolts = 2800000, + .gpio = -1, + .enable_high = 0, + .init_data = &camera_dummy_initdata, }; -static struct platform_device em_x270_camera = { - .name = "soc-camera-pdrv", - .id = -1, +static struct platform_device camera_supply_dummy_device = { + .name = "reg-fixed-voltage", + .id = 1, .dev = { - .platform_data = &iclink, + .platform_data = &camera_dummy_config, }, }; +struct pxacamera_platform_data em_x270_camera_platform_data = { + .flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | + PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN, + .mclk_10khz = 2600, + .sensor_i2c_adapter_id = 0, + .sensor_i2c_address = 0x5d, +}; + static void __init em_x270_init_camera(void) { - if (em_x270_sensor_init() == 0) { + if (em_x270_sensor_init() == 0) pxa_set_camera_info(&em_x270_camera_platform_data); - platform_device_register(&em_x270_camera); - } + platform_device_register(&camera_supply_dummy_device); } #else static inline void em_x270_init_camera(void) {} diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c index 34ad0a89d4a9..0b8300e6fca3 100644 --- a/arch/arm/mach-pxa/ezx.c +++ b/arch/arm/mach-pxa/ezx.c @@ -17,14 +17,14 @@ #include <linux/delay.h> #include <linux/pwm.h> #include <linux/pwm_backlight.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/fixed.h> #include <linux/input.h> #include <linux/gpio.h> #include <linux/gpio_keys.h> #include <linux/leds-lp3944.h> #include <linux/i2c/pxa-i2c.h> -#include <media/soc_camera.h> - #include <asm/setup.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -723,6 +723,42 @@ static struct platform_device a780_gpio_keys = { }; /* camera */ +static struct regulator_consumer_supply camera_dummy_supplies[] = { + REGULATOR_SUPPLY("vdd", "0-005d"), +}; + +static struct regulator_init_data camera_dummy_initdata = { + .consumer_supplies = camera_dummy_supplies, + .num_consumer_supplies = ARRAY_SIZE(camera_dummy_supplies), + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +static struct fixed_voltage_config camera_dummy_config = { + .supply_name = "camera_vdd", + .microvolts = 2800000, + .gpio = GPIO50_nCAM_EN, + .enable_high = 0, + .init_data = &camera_dummy_initdata, +}; + +static struct platform_device camera_supply_dummy_device = { + .name = "reg-fixed-voltage", + .id = 1, + .dev = { + .platform_data = &camera_dummy_config, + }, +}; +static int a780_camera_reset(struct device *dev) +{ + gpio_set_value(GPIO19_GEN1_CAM_RST, 0); + msleep(10); + gpio_set_value(GPIO19_GEN1_CAM_RST, 1); + + return 0; +} + static int a780_camera_init(void) { int err; @@ -731,73 +767,36 @@ static int a780_camera_init(void) * GPIO50_nCAM_EN is active low * GPIO19_GEN1_CAM_RST is active on rising edge */ - err = gpio_request(GPIO50_nCAM_EN, "nCAM_EN"); - if (err) { - pr_err("%s: Failed to request nCAM_EN\n", __func__); - goto fail; - } - err = gpio_request(GPIO19_GEN1_CAM_RST, "CAM_RST"); if (err) { pr_err("%s: Failed to request CAM_RST\n", __func__); - goto fail_gpio_cam_rst; + return err; } - gpio_direction_output(GPIO50_nCAM_EN, 1); gpio_direction_output(GPIO19_GEN1_CAM_RST, 0); - - return 0; - -fail_gpio_cam_rst: - gpio_free(GPIO50_nCAM_EN); -fail: - return err; -} - -static int a780_camera_power(struct device *dev, int on) -{ - gpio_set_value(GPIO50_nCAM_EN, !on); - return 0; -} - -static int a780_camera_reset(struct device *dev) -{ - gpio_set_value(GPIO19_GEN1_CAM_RST, 0); - msleep(10); - gpio_set_value(GPIO19_GEN1_CAM_RST, 1); + a780_camera_reset(NULL); return 0; } struct pxacamera_platform_data a780_pxacamera_platform_data = { .flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | - PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN, + PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN | + PXA_CAMERA_PCP, .mclk_10khz = 5000, + .sensor_i2c_adapter_id = 0, + .sensor_i2c_address = 0x5d, }; -static struct i2c_board_info a780_camera_i2c_board_info = { - I2C_BOARD_INFO("mt9m111", 0x5d), -}; - -static struct soc_camera_link a780_iclink = { - .bus_id = 0, - .flags = SOCAM_SENSOR_INVERT_PCLK, - .i2c_adapter_id = 0, - .board_info = &a780_camera_i2c_board_info, - .power = a780_camera_power, - .reset = a780_camera_reset, -}; - -static struct platform_device a780_camera = { - .name = "soc-camera-pdrv", - .id = 0, - .dev = { - .platform_data = &a780_iclink, +static struct i2c_board_info a780_i2c_board_info[] = { + { + I2C_BOARD_INFO("mt9m111", 0x5d), }, }; static struct platform_device *a780_devices[] __initdata = { &a780_gpio_keys, + &camera_supply_dummy_device, }; static void __init a780_init(void) @@ -811,19 +810,19 @@ static void __init a780_init(void) pxa_set_stuart_info(NULL); pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(a780_i2c_board_info)); pxa_set_fb_info(NULL, &ezx_fb_info_1); pxa_set_keypad_info(&a780_keypad_platform_data); - if (a780_camera_init() == 0) { + if (a780_camera_init() == 0) pxa_set_camera_info(&a780_pxacamera_platform_data); - platform_device_register(&a780_camera); - } pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup)); platform_add_devices(ARRAY_AND_SIZE(ezx_devices)); platform_add_devices(ARRAY_AND_SIZE(a780_devices)); + regulator_has_full_constraints(); } MACHINE_START(EZX_A780, "Motorola EZX A780") @@ -1001,6 +1000,15 @@ static struct platform_device a910_gpio_keys = { }; /* camera */ +static int a910_camera_reset(struct device *dev) +{ + gpio_set_value(GPIO28_GEN2_CAM_RST, 0); + msleep(10); + gpio_set_value(GPIO28_GEN2_CAM_RST, 1); + + return 0; +} + static int a910_camera_init(void) { int err; @@ -1009,68 +1017,25 @@ static int a910_camera_init(void) * GPIO50_nCAM_EN is active low * GPIO28_GEN2_CAM_RST is active on rising edge */ - err = gpio_request(GPIO50_nCAM_EN, "nCAM_EN"); - if (err) { - pr_err("%s: Failed to request nCAM_EN\n", __func__); - goto fail; - } - err = gpio_request(GPIO28_GEN2_CAM_RST, "CAM_RST"); if (err) { pr_err("%s: Failed to request CAM_RST\n", __func__); - goto fail_gpio_cam_rst; + return err; } - gpio_direction_output(GPIO50_nCAM_EN, 1); gpio_direction_output(GPIO28_GEN2_CAM_RST, 0); - - return 0; - -fail_gpio_cam_rst: - gpio_free(GPIO50_nCAM_EN); -fail: - return err; -} - -static int a910_camera_power(struct device *dev, int on) -{ - gpio_set_value(GPIO50_nCAM_EN, !on); - return 0; -} - -static int a910_camera_reset(struct device *dev) -{ - gpio_set_value(GPIO28_GEN2_CAM_RST, 0); - msleep(10); - gpio_set_value(GPIO28_GEN2_CAM_RST, 1); + a910_camera_reset(NULL); return 0; } struct pxacamera_platform_data a910_pxacamera_platform_data = { .flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | - PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN, + PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN | + PXA_CAMERA_PCP, .mclk_10khz = 5000, -}; - -static struct i2c_board_info a910_camera_i2c_board_info = { - I2C_BOARD_INFO("mt9m111", 0x5d), -}; - -static struct soc_camera_link a910_iclink = { - .bus_id = 0, - .i2c_adapter_id = 0, - .board_info = &a910_camera_i2c_board_info, - .power = a910_camera_power, - .reset = a910_camera_reset, -}; - -static struct platform_device a910_camera = { - .name = "soc-camera-pdrv", - .id = 0, - .dev = { - .platform_data = &a910_iclink, - }, + .sensor_i2c_adapter_id = 0, + .sensor_i2c_address = 0x5d, }; /* leds-lp3944 */ @@ -1122,10 +1087,14 @@ static struct i2c_board_info __initdata a910_i2c_board_info[] = { I2C_BOARD_INFO("lp3944", 0x60), .platform_data = &a910_lp3944_leds, }, + { + I2C_BOARD_INFO("mt9m111", 0x5d), + }, }; static struct platform_device *a910_devices[] __initdata = { &a910_gpio_keys, + &camera_supply_dummy_device, }; static void __init a910_init(void) @@ -1145,14 +1114,13 @@ static void __init a910_init(void) pxa_set_keypad_info(&a910_keypad_platform_data); - if (a910_camera_init() == 0) { + if (a910_camera_init() == 0) pxa_set_camera_info(&a910_pxacamera_platform_data); - platform_device_register(&a910_camera); - } pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup)); platform_add_devices(ARRAY_AND_SIZE(ezx_devices)); platform_add_devices(ARRAY_AND_SIZE(a910_devices)); + regulator_has_full_constraints(); } MACHINE_START(EZX_A910, "Motorola EZX A910") diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index ec510ecf8370..cb73a9723d0e 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -43,21 +43,6 @@ void clear_reset_status(unsigned int mask) } } -unsigned long get_clock_tick_rate(void) -{ - unsigned long clock_tick_rate; - - if (cpu_is_pxa25x()) - clock_tick_rate = 3686400; - else if (machine_is_mainstone()) - clock_tick_rate = 3249600; - else - clock_tick_rate = 3250000; - - return clock_tick_rate; -} -EXPORT_SYMBOL(get_clock_tick_rate); - /* * For non device-tree builds, keep legacy timer init */ @@ -69,8 +54,7 @@ void __init pxa_timer_init(void) pxa27x_clocks_init(); if (cpu_is_pxa3xx()) pxa3xx_clocks_init(); - pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000), - get_clock_tick_rate()); + pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000)); } /* diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h index 8d63c211b22f..55064124ca4e 100644 --- a/arch/arm/mach-pxa/include/mach/hardware.h +++ b/arch/arm/mach-pxa/include/mach/hardware.h @@ -303,8 +303,6 @@ */ extern unsigned int get_memclk_frequency_10khz(void); -/* return the clock tick rate of the OS timer */ -extern unsigned long get_clock_tick_rate(void); #endif #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index 38a96a193dc4..8a5d0491e73c 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -57,7 +57,6 @@ #include <linux/platform_data/media/camera-pxa.h> #include <mach/audio.h> #include <mach/smemc.h> -#include <media/soc_camera.h> #include "mioa701.h" @@ -627,6 +626,8 @@ struct pxacamera_platform_data mioa701_pxacamera_platform_data = { .flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN, .mclk_10khz = 5000, + .sensor_i2c_adapter_id = 0, + .sensor_i2c_address = 0x5d, }; static struct i2c_board_info __initdata mioa701_pi2c_devices[] = { @@ -643,12 +644,6 @@ static struct i2c_board_info mioa701_i2c_devices[] = { }, }; -static struct soc_camera_link iclink = { - .bus_id = 0, /* Match id in pxa27x_device_camera in device.c */ - .board_info = &mioa701_i2c_devices[0], - .i2c_adapter_id = 0, -}; - struct i2c_pxa_platform_data i2c_pdata = { .fast_mode = 1, }; @@ -684,7 +679,6 @@ MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL) MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL) MIO_SIMPLE_DEV(wm9713_acodec, "wm9713-codec", NULL); MIO_SIMPLE_DEV(gpio_vbus, "gpio-vbus", &gpio_vbus_data); -MIO_SIMPLE_DEV(mioa701_camera, "soc-camera-pdrv",&iclink); static struct platform_device *devices[] __initdata = { &mioa701_gpio_keys, @@ -696,7 +690,6 @@ static struct platform_device *devices[] __initdata = { &power_dev, &docg3, &gpio_vbus, - &mioa701_camera, &mioa701_board, }; @@ -761,6 +754,7 @@ static void __init mioa701_machine_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); gsm_init(); + i2c_register_board_info(0, ARRAY_AND_SIZE(mioa701_i2c_devices)); i2c_register_board_info(1, ARRAY_AND_SIZE(mioa701_pi2c_devices)); pxa_set_i2c_info(&i2c_pdata); pxa27x_set_i2c_power_info(NULL); @@ -769,6 +763,7 @@ static void __init mioa701_machine_init(void) regulator_register_always_on(0, "fixed-5.0V", fixed_5v0_consumers, ARRAY_SIZE(fixed_5v0_consumers), 5000000); + regulator_has_full_constraints(); } static void mioa701_machine_exit(void) diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 12b94357fbc1..c725baf119e1 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -156,7 +156,7 @@ static int __init __init pxa25x_dt_init_irq(struct device_node *node, struct device_node *parent) { pxa_dt_irq_init(pxa25x_set_wake); - set_handle_irq(ichp_handle_irq); + set_handle_irq(icip_handle_irq); return 0; } diff --git a/arch/arm/mach-pxa/pxa_cplds_irqs.c b/arch/arm/mach-pxa/pxa_cplds_irqs.c index e362f865fcd2..941508585e34 100644 --- a/arch/arm/mach-pxa/pxa_cplds_irqs.c +++ b/arch/arm/mach-pxa/pxa_cplds_irqs.c @@ -120,13 +120,9 @@ static int cplds_probe(struct platform_device *pdev) if (!fpga) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res) { - fpga->irq = (unsigned int)res->start; - irqflags = res->flags; - } - if (!fpga->irq) - return -ENODEV; + fpga->irq = platform_get_irq(pdev, 0); + if (fpga->irq <= 0) + return fpga->irq; base_irq = platform_get_irq(pdev, 1); if (base_irq < 0) @@ -142,6 +138,7 @@ static int cplds_probe(struct platform_device *pdev) writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN); writel(0, fpga->base + FPGA_IRQ_SET_CLR); + irqflags = irq_get_trigger_type(fpga->irq); ret = devm_request_irq(&pdev->dev, fpga->irq, cplds_irq_handler, irqflags, dev_name(&pdev->dev), fpga); if (ret == -ENOSYS) diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 2c150bfc0cd5..67d66c702574 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -31,7 +31,6 @@ #include <linux/input/matrix_keypad.h> #include <linux/regulator/machine.h> #include <linux/io.h> -#include <linux/module.h> #include <linux/reboot.h> #include <linux/memblock.h> diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 3e09beddb6e8..2eb00691b07d 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -378,7 +378,7 @@ void __init sa1100_map_io(void) void __init sa1100_timer_init(void) { - pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x90000000), 3686400); + pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x90000000)); } static struct resource irq_resource = diff --git a/arch/arm/mach-sa1100/include/mach/hardware.h b/arch/arm/mach-sa1100/include/mach/hardware.h index d944fd7e464f..52b8f6d25bef 100644 --- a/arch/arm/mach-sa1100/include/mach/hardware.h +++ b/arch/arm/mach-sa1100/include/mach/hardware.h @@ -43,10 +43,6 @@ # define __REG(x) (*((volatile unsigned long __iomem *)io_p2v(x))) # define __PREG(x) (io_v2p((unsigned long)&(x))) -static inline unsigned long get_clock_tick_rate(void) -{ - return 3686400; -} #else # define __REG(x) io_p2v(x) diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 09817bae4558..6fbd9b7d2d67 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -32,15 +32,15 @@ config ARCH_RMOBILE menuconfig ARCH_RENESAS bool "Renesas ARM SoCs" depends on ARCH_MULTI_V7 && MMU + select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select ARCH_SHMOBILE select ARCH_SHMOBILE_MULTI + select ARM_GIC + select GPIOLIB select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP - select ARM_GIC - select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select NO_IOPORT_MAP select PINCTRL - select GPIOLIB select ZONE_DMA if ARM_LPAE if ARCH_RENESAS @@ -60,6 +60,7 @@ config ARCH_R7S72100 config ARCH_R8A73A4 bool "R-Mobile APE6 (R8A73A40)" select ARCH_RMOBILE + select ARM_ERRATA_798181 if SMP select RENESAS_IRQC config ARCH_R8A7740 @@ -67,6 +68,11 @@ config ARCH_R8A7740 select ARCH_RMOBILE select RENESAS_INTC_IRQPIN +config ARCH_R8A7743 + bool "RZ/G1M (R8A77430)" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + config ARCH_R8A7778 bool "R-Car M1A (R8A77781)" select ARCH_RCAR_GEN1 @@ -78,20 +84,24 @@ config ARCH_R8A7779 config ARCH_R8A7790 bool "R-Car H2 (R8A77900)" select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP select I2C config ARCH_R8A7791 bool "R-Car M2-W (R8A77910)" select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP select I2C config ARCH_R8A7792 bool "R-Car V2H (R8A77920)" select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP config ARCH_R8A7793 bool "R-Car M2-N (R8A7793)" select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP select I2C config ARCH_R8A7794 diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 3fc48b02eb4f..64611a1b4276 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -13,9 +13,6 @@ obj-$(CONFIG_ARCH_R8A7778) += setup-r8a7778.o obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o pm-r8a7779.o obj-$(CONFIG_ARCH_R8A7790) += setup-r8a7790.o obj-$(CONFIG_ARCH_R8A7791) += setup-r8a7791.o -obj-$(CONFIG_ARCH_R8A7792) += setup-r8a7792.o -obj-$(CONFIG_ARCH_R8A7793) += setup-r8a7793.o -obj-$(CONFIG_ARCH_R8A7794) += setup-r8a7794.o obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o obj-$(CONFIG_ARCH_R7S72100) += setup-r7s72100.o diff --git a/arch/arm/mach-shmobile/setup-r8a7792.c b/arch/arm/mach-shmobile/setup-r8a7792.c deleted file mode 100644 index a0910395da09..000000000000 --- a/arch/arm/mach-shmobile/setup-r8a7792.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * r8a7792 processor support - * - * Copyright (C) 2014 Renesas Electronics Corporation - * Copyright (C) 2016 Cogent Embedded, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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. - */ - -#include <linux/of_platform.h> - -#include <asm/mach/arch.h> - -#include "common.h" -#include "rcar-gen2.h" - -static const char * const r8a7792_boards_compat_dt[] __initconst = { - "renesas,r8a7792", - NULL, -}; - -DT_MACHINE_START(R8A7792_DT, "Generic R8A7792 (Flattened Device Tree)") - .init_early = shmobile_init_delay, - .init_late = shmobile_init_late, - .init_time = rcar_gen2_timer_init, - .reserve = rcar_gen2_reserve, - .dt_compat = r8a7792_boards_compat_dt, -MACHINE_END diff --git a/arch/arm/mach-shmobile/setup-r8a7793.c b/arch/arm/mach-shmobile/setup-r8a7793.c deleted file mode 100644 index 5fce87f7f254..000000000000 --- a/arch/arm/mach-shmobile/setup-r8a7793.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * r8a7793 processor support - * - * Copyright (C) 2015 Ulrich Hecht - * - * 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; version 2 of the License. - * - * 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. - */ - -#include <linux/init.h> -#include <asm/mach/arch.h> - -#include "common.h" -#include "rcar-gen2.h" - -static const char * const r8a7793_boards_compat_dt[] __initconst = { - "renesas,r8a7793", - NULL, -}; - -DT_MACHINE_START(R8A7793_DT, "Generic R8A7793 (Flattened Device Tree)") - .init_early = shmobile_init_delay, - .init_time = rcar_gen2_timer_init, - .init_late = shmobile_init_late, - .reserve = rcar_gen2_reserve, - .dt_compat = r8a7793_boards_compat_dt, -MACHINE_END diff --git a/arch/arm/mach-shmobile/setup-r8a7794.c b/arch/arm/mach-shmobile/setup-r8a7794.c deleted file mode 100644 index d2b093033132..000000000000 --- a/arch/arm/mach-shmobile/setup-r8a7794.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * r8a7794 processor support - * - * Copyright (C) 2014 Renesas Electronics Corporation - * Copyright (C) 2014 Ulrich Hecht - * - * 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; version 2 of the License. - * - * 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. - */ - -#include <linux/of_platform.h> -#include "common.h" -#include "rcar-gen2.h" -#include <asm/mach/arch.h> - -static const char * const r8a7794_boards_compat_dt[] __initconst = { - "renesas,r8a7794", - NULL, -}; - -DT_MACHINE_START(R8A7794_DT, "Generic R8A7794 (Flattened Device Tree)") - .init_early = shmobile_init_delay, - .init_late = shmobile_init_late, - .init_time = rcar_gen2_timer_init, - .reserve = rcar_gen2_reserve, - .dt_compat = r8a7794_boards_compat_dt, -MACHINE_END diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index afb9fdcd3d90..d6b4841e51a9 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -15,6 +15,7 @@ * GNU General Public License for more details. */ +#include <linux/clk-provider.h> #include <linux/clk/renesas.h> #include <linux/clocksource.h> #include <linux/device.h> @@ -24,6 +25,7 @@ #include <linux/memblock.h> #include <linux/of.h> #include <linux/of_fdt.h> +#include <linux/of_platform.h> #include <asm/mach/arch.h> #include "common.h" #include "rcar-gen2.h" @@ -130,7 +132,15 @@ void __init rcar_gen2_timer_init(void) iounmap(base); #endif /* CONFIG_ARM_ARCH_TIMER */ - rcar_gen2_clocks_init(mode); + if (IS_ENABLED(CONFIG_ARCH_R8A7790) || + IS_ENABLED(CONFIG_ARCH_R8A7791) || + IS_ENABLED(CONFIG_ARCH_R8A7792) || + IS_ENABLED(CONFIG_ARCH_R8A7793) || + IS_ENABLED(CONFIG_ARCH_R8A7794)) + rcar_gen2_clocks_init(mode); + else + of_clk_init(NULL); + clocksource_probe(); } @@ -203,3 +213,35 @@ void __init rcar_gen2_reserve(void) } #endif } + +static const char * const rcar_gen2_boards_compat_dt[] __initconst = { + /* + * R8A7790 and R8A7791 can't be handled here as long as they need SMP + * initialization fallback. + */ + "renesas,r8a7792", + "renesas,r8a7793", + "renesas,r8a7794", + NULL, +}; + +DT_MACHINE_START(RCAR_GEN2_DT, "Generic R-Car Gen2 (Flattened Device Tree)") + .init_early = shmobile_init_delay, + .init_late = shmobile_init_late, + .init_time = rcar_gen2_timer_init, + .reserve = rcar_gen2_reserve, + .dt_compat = rcar_gen2_boards_compat_dt, +MACHINE_END + +static const char * const rz_g1_boards_compat_dt[] __initconst = { + "renesas,r8a7743", + NULL, +}; + +DT_MACHINE_START(RZ_G1_DT, "Generic RZ/G1 (Flattened Device Tree)") + .init_early = shmobile_init_delay, + .init_late = shmobile_init_late, + .init_time = rcar_gen2_timer_init, + .reserve = rcar_gen2_reserve, + .dt_compat = rz_g1_boards_compat_dt, +MACHINE_END diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c index ceee47735eec..c354222a4158 100644 --- a/arch/arm/mach-stm32/board-dt.c +++ b/arch/arm/mach-stm32/board-dt.c @@ -11,6 +11,7 @@ static const char *const stm32_compat[] __initconst = { "st,stm32f429", "st,stm32f469", + "st,stm32f746", NULL }; diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index 8b8d0724f6c6..98e29dee91e8 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c @@ -26,19 +26,37 @@ bool __init vexpress_smp_init_ops(void) { #ifdef CONFIG_MCPM + int cpu; + struct device_node *cpu_node, *cci_node; + /* - * The best way to detect a multi-cluster configuration at the moment - * is to look for the presence of a CCI in the system. + * The best way to detect a multi-cluster configuration + * is to detect if the kernel can take over CCI ports + * control. Loop over possible CPUs and check if CCI + * port control is available. * Override the default vexpress_smp_ops if so. */ - struct device_node *node; - node = of_find_compatible_node(NULL, NULL, "arm,cci-400"); - if (node && of_device_is_available(node)) { - mcpm_smp_set_ops(); - return true; + for_each_possible_cpu(cpu) { + bool available; + + cpu_node = of_get_cpu_node(cpu, NULL); + if (WARN(!cpu_node, "Missing cpu device node!")) + return false; + + cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0); + available = cci_node && of_device_is_available(cci_node); + of_node_put(cci_node); + of_node_put(cpu_node); + + if (!available) + return false; } -#endif + + mcpm_smp_set_ops(); + return true; +#else return false; +#endif } static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = { diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 30398dbc940a..969ef880d234 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -915,7 +915,7 @@ config RANDOMIZE_BASE config RANDOMIZE_MODULE_REGION_FULL bool "Randomize the module region independently from the core kernel" - depends on RANDOMIZE_BASE + depends on RANDOMIZE_BASE && !DYNAMIC_FTRACE default y help Randomizes the location of the module region without considering the diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index ab51aed6b6c1..3635b8662724 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -15,7 +15,7 @@ CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) GZFLAGS :=-9 ifneq ($(CONFIG_RELOCATABLE),) -LDFLAGS_vmlinux += -pie -Bsymbolic +LDFLAGS_vmlinux += -pie -shared -Bsymbolic endif ifeq ($(CONFIG_ARM64_ERRATUM_843419),y) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 758d74fedfad..a27c3245ba21 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -94,7 +94,7 @@ struct arm64_cpu_capabilities { u16 capability; int def_scope; /* default scope */ bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope); - void (*enable)(void *); /* Called on all active CPUs */ + int (*enable)(void *); /* Called on all active CPUs */ union { struct { /* To be used for erratum handling only */ u32 midr_model; diff --git a/arch/arm64/include/asm/exec.h b/arch/arm64/include/asm/exec.h index db0563c23482..f7865dd9d868 100644 --- a/arch/arm64/include/asm/exec.h +++ b/arch/arm64/include/asm/exec.h @@ -18,6 +18,9 @@ #ifndef __ASM_EXEC_H #define __ASM_EXEC_H +#include <linux/sched.h> + extern unsigned long arch_align_stack(unsigned long sp); +void uao_thread_switch(struct task_struct *next); #endif /* __ASM_EXEC_H */ diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index fd9d5fd788f5..f5ea0ba70f07 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -178,11 +178,6 @@ static inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu) return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISV); } -static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu) -{ - return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR); -} - static inline bool kvm_vcpu_dabt_issext(const struct kvm_vcpu *vcpu) { return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SSE); @@ -203,6 +198,12 @@ static inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu) return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_S1PTW); } +static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu) +{ + return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR) || + kvm_vcpu_dabt_iss1tw(vcpu); /* AF/DBM update */ +} + static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu) { return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_CM); diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h index e12af6754634..06ff7fd9e81f 100644 --- a/arch/arm64/include/asm/module.h +++ b/arch/arm64/include/asm/module.h @@ -17,6 +17,7 @@ #define __ASM_MODULE_H #include <asm-generic/module.h> +#include <asm/memory.h> #define MODULE_ARCH_VERMAGIC "aarch64" @@ -32,6 +33,10 @@ u64 module_emit_plt_entry(struct module *mod, const Elf64_Rela *rela, Elf64_Sym *sym); #ifdef CONFIG_RANDOMIZE_BASE +#ifdef CONFIG_MODVERSIONS +#define ARCH_RELOCATES_KCRCTAB +#define reloc_start (kimage_vaddr - KIMAGE_VADDR) +#endif extern u64 module_alloc_base; #else #define module_alloc_base ((u64)_etext - MODULES_VSIZE) diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h index 2fee2f59288c..5394c8405e66 100644 --- a/arch/arm64/include/asm/percpu.h +++ b/arch/arm64/include/asm/percpu.h @@ -44,48 +44,44 @@ static inline unsigned long __percpu_##op(void *ptr, \ \ switch (size) { \ case 1: \ - do { \ - asm ("//__per_cpu_" #op "_1\n" \ - "ldxrb %w[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_1\n" \ + "1: ldxrb %w[ret], %[ptr]\n" \ #asm_op " %w[ret], %w[ret], %w[val]\n" \ - "stxrb %w[loop], %w[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u8 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxrb %w[loop], %w[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u8 *)ptr) \ + : [val] "Ir" (val)); \ break; \ case 2: \ - do { \ - asm ("//__per_cpu_" #op "_2\n" \ - "ldxrh %w[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_2\n" \ + "1: ldxrh %w[ret], %[ptr]\n" \ #asm_op " %w[ret], %w[ret], %w[val]\n" \ - "stxrh %w[loop], %w[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u16 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxrh %w[loop], %w[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u16 *)ptr) \ + : [val] "Ir" (val)); \ break; \ case 4: \ - do { \ - asm ("//__per_cpu_" #op "_4\n" \ - "ldxr %w[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_4\n" \ + "1: ldxr %w[ret], %[ptr]\n" \ #asm_op " %w[ret], %w[ret], %w[val]\n" \ - "stxr %w[loop], %w[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u32 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxr %w[loop], %w[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u32 *)ptr) \ + : [val] "Ir" (val)); \ break; \ case 8: \ - do { \ - asm ("//__per_cpu_" #op "_8\n" \ - "ldxr %[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_8\n" \ + "1: ldxr %[ret], %[ptr]\n" \ #asm_op " %[ret], %[ret], %[val]\n" \ - "stxr %w[loop], %[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u64 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxr %w[loop], %[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u64 *)ptr) \ + : [val] "Ir" (val)); \ break; \ default: \ BUILD_BUG(); \ @@ -150,44 +146,40 @@ static inline unsigned long __percpu_xchg(void *ptr, unsigned long val, switch (size) { case 1: - do { - asm ("//__percpu_xchg_1\n" - "ldxrb %w[ret], %[ptr]\n" - "stxrb %w[loop], %w[val], %[ptr]\n" - : [loop] "=&r"(loop), [ret] "=&r"(ret), - [ptr] "+Q"(*(u8 *)ptr) - : [val] "r" (val)); - } while (loop); + asm ("//__percpu_xchg_1\n" + "1: ldxrb %w[ret], %[ptr]\n" + " stxrb %w[loop], %w[val], %[ptr]\n" + " cbnz %w[loop], 1b" + : [loop] "=&r"(loop), [ret] "=&r"(ret), + [ptr] "+Q"(*(u8 *)ptr) + : [val] "r" (val)); break; case 2: - do { - asm ("//__percpu_xchg_2\n" - "ldxrh %w[ret], %[ptr]\n" - "stxrh %w[loop], %w[val], %[ptr]\n" - : [loop] "=&r"(loop), [ret] "=&r"(ret), - [ptr] "+Q"(*(u16 *)ptr) - : [val] "r" (val)); - } while (loop); + asm ("//__percpu_xchg_2\n" + "1: ldxrh %w[ret], %[ptr]\n" + " stxrh %w[loop], %w[val], %[ptr]\n" + " cbnz %w[loop], 1b" + : [loop] "=&r"(loop), [ret] "=&r"(ret), + [ptr] "+Q"(*(u16 *)ptr) + : [val] "r" (val)); break; case 4: - do { - asm ("//__percpu_xchg_4\n" - "ldxr %w[ret], %[ptr]\n" - "stxr %w[loop], %w[val], %[ptr]\n" - : [loop] "=&r"(loop), [ret] "=&r"(ret), - [ptr] "+Q"(*(u32 *)ptr) - : [val] "r" (val)); - } while (loop); + asm ("//__percpu_xchg_4\n" + "1: ldxr %w[ret], %[ptr]\n" + " stxr %w[loop], %w[val], %[ptr]\n" + " cbnz %w[loop], 1b" + : [loop] "=&r"(loop), [ret] "=&r"(ret), + [ptr] "+Q"(*(u32 *)ptr) + : [val] "r" (val)); break; case 8: - do { - asm ("//__percpu_xchg_8\n" - "ldxr %[ret], %[ptr]\n" - "stxr %w[loop], %[val], %[ptr]\n" - : [loop] "=&r"(loop), [ret] "=&r"(ret), - [ptr] "+Q"(*(u64 *)ptr) - : [val] "r" (val)); - } while (loop); + asm ("//__percpu_xchg_8\n" + "1: ldxr %[ret], %[ptr]\n" + " stxr %w[loop], %[val], %[ptr]\n" + " cbnz %w[loop], 1b" + : [loop] "=&r"(loop), [ret] "=&r"(ret), + [ptr] "+Q"(*(u64 *)ptr) + : [val] "r" (val)); break; default: BUILD_BUG(); diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index df2e53d3a969..60e34824e18c 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -188,8 +188,8 @@ static inline void spin_lock_prefetch(const void *ptr) #endif -void cpu_enable_pan(void *__unused); -void cpu_enable_uao(void *__unused); -void cpu_enable_cache_maint_trap(void *__unused); +int cpu_enable_pan(void *__unused); +int cpu_enable_uao(void *__unused); +int cpu_enable_cache_maint_trap(void *__unused); #endif /* __ASM_PROCESSOR_H */ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index e8d46e8e6079..6c80b3699cb8 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -286,7 +286,7 @@ asm( #define write_sysreg_s(v, r) do { \ u64 __val = (u64)v; \ - asm volatile("msr_s " __stringify(r) ", %0" : : "rZ" (__val)); \ + asm volatile("msr_s " __stringify(r) ", %x0" : : "rZ" (__val)); \ } while (0) static inline void config_sctlr_el1(u32 clear, u32 set) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index bcaf6fba1b65..55d0adbf6509 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -21,6 +21,7 @@ /* * User space memory access functions */ +#include <linux/bitops.h> #include <linux/kasan-checks.h> #include <linux/string.h> #include <linux/thread_info.h> @@ -102,6 +103,13 @@ static inline void set_fs(mm_segment_t fs) flag; \ }) +/* + * When dealing with data aborts or instruction traps we may end up with + * a tagged userland pointer. Clear the tag to get a sane pointer to pass + * on to access_ok(), for instance. + */ +#define untagged_addr(addr) sign_extend64(addr, 55) + #define access_ok(type, addr, size) __range_ok(addr, size) #define user_addr_max get_fs diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c index 42ffdb54e162..b0988bb1bf64 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c @@ -280,35 +280,43 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table) /* * Error-checking SWP macros implemented using ldxr{b}/stxr{b} */ -#define __user_swpX_asm(data, addr, res, temp, B) \ + +/* Arbitrary constant to ensure forward-progress of the LL/SC loop */ +#define __SWP_LL_SC_LOOPS 4 + +#define __user_swpX_asm(data, addr, res, temp, temp2, B) \ __asm__ __volatile__( \ + " mov %w3, %w7\n" \ ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \ CONFIG_ARM64_PAN) \ - "0: ldxr"B" %w2, [%3]\n" \ - "1: stxr"B" %w0, %w1, [%3]\n" \ + "0: ldxr"B" %w2, [%4]\n" \ + "1: stxr"B" %w0, %w1, [%4]\n" \ " cbz %w0, 2f\n" \ - " mov %w0, %w4\n" \ + " sub %w3, %w3, #1\n" \ + " cbnz %w3, 0b\n" \ + " mov %w0, %w5\n" \ " b 3f\n" \ "2:\n" \ " mov %w1, %w2\n" \ "3:\n" \ " .pushsection .fixup,\"ax\"\n" \ " .align 2\n" \ - "4: mov %w0, %w5\n" \ + "4: mov %w0, %w6\n" \ " b 3b\n" \ " .popsection" \ _ASM_EXTABLE(0b, 4b) \ _ASM_EXTABLE(1b, 4b) \ ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ CONFIG_ARM64_PAN) \ - : "=&r" (res), "+r" (data), "=&r" (temp) \ - : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ + : "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2) \ + : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT), \ + "i" (__SWP_LL_SC_LOOPS) \ : "memory") -#define __user_swp_asm(data, addr, res, temp) \ - __user_swpX_asm(data, addr, res, temp, "") -#define __user_swpb_asm(data, addr, res, temp) \ - __user_swpX_asm(data, addr, res, temp, "b") +#define __user_swp_asm(data, addr, res, temp, temp2) \ + __user_swpX_asm(data, addr, res, temp, temp2, "") +#define __user_swpb_asm(data, addr, res, temp, temp2) \ + __user_swpX_asm(data, addr, res, temp, temp2, "b") /* * Bit 22 of the instruction encoding distinguishes between @@ -328,12 +336,12 @@ static int emulate_swpX(unsigned int address, unsigned int *data, } while (1) { - unsigned long temp; + unsigned long temp, temp2; if (type == TYPE_SWPB) - __user_swpb_asm(*data, address, res, temp); + __user_swpb_asm(*data, address, res, temp, temp2); else - __user_swp_asm(*data, address, res, temp); + __user_swp_asm(*data, address, res, temp, temp2); if (likely(res != -EAGAIN) || signal_pending(current)) break; diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 0150394f4cab..b75e917aac46 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -39,10 +39,11 @@ has_mismatched_cache_line_size(const struct arm64_cpu_capabilities *entry, (arm64_ftr_reg_ctrel0.sys_val & arm64_ftr_reg_ctrel0.strict_mask); } -static void cpu_enable_trap_ctr_access(void *__unused) +static int cpu_enable_trap_ctr_access(void *__unused) { /* Clear SCTLR_EL1.UCT */ config_sctlr_el1(SCTLR_EL1_UCT, 0); + return 0; } #define MIDR_RANGE(model, min, max) \ diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index d577f263cc4a..c02504ea304b 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -19,7 +19,9 @@ #define pr_fmt(fmt) "CPU features: " fmt #include <linux/bsearch.h> +#include <linux/cpumask.h> #include <linux/sort.h> +#include <linux/stop_machine.h> #include <linux/types.h> #include <asm/cpu.h> #include <asm/cpufeature.h> @@ -941,7 +943,13 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) { for (; caps->matches; caps++) if (caps->enable && cpus_have_cap(caps->capability)) - on_each_cpu(caps->enable, NULL, true); + /* + * Use stop_machine() as it schedules the work allowing + * us to modify PSTATE, instead of on_each_cpu() which + * uses an IPI, giving us a PSTATE that disappears when + * we return. + */ + stop_machine(caps->enable, NULL, cpu_online_mask); } /* diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 427f6d3f084c..332e33193ccf 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -586,8 +586,9 @@ CPU_LE( movk x0, #0x30d0, lsl #16 ) // Clear EE and E0E on LE systems b.lt 4f // Skip if no PMU present mrs x0, pmcr_el0 // Disable debug access traps ubfx x0, x0, #11, #5 // to EL2 and allow access to - msr mdcr_el2, x0 // all PMU counters from EL1 4: + csel x0, xzr, x0, lt // all PMU counters from EL1 + msr mdcr_el2, x0 // (if they exist) /* Stage-2 translation */ msr vttbr_el2, xzr diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 27b2f1387df4..01753cd7d3f0 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -49,6 +49,7 @@ #include <asm/alternative.h> #include <asm/compat.h> #include <asm/cacheflush.h> +#include <asm/exec.h> #include <asm/fpsimd.h> #include <asm/mmu_context.h> #include <asm/processor.h> @@ -186,10 +187,19 @@ void __show_regs(struct pt_regs *regs) printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", regs->pc, lr, regs->pstate); printk("sp : %016llx\n", sp); - for (i = top_reg; i >= 0; i--) { + + i = top_reg; + + while (i >= 0) { printk("x%-2d: %016llx ", i, regs->regs[i]); - if (i % 2 == 0) - printk("\n"); + i--; + + if (i % 2 == 0) { + pr_cont("x%-2d: %016llx ", i, regs->regs[i]); + i--; + } + + pr_cont("\n"); } printk("\n"); } @@ -301,7 +311,7 @@ static void tls_thread_switch(struct task_struct *next) } /* Restore the UAO state depending on next's addr_limit */ -static void uao_thread_switch(struct task_struct *next) +void uao_thread_switch(struct task_struct *next) { if (IS_ENABLED(CONFIG_ARM64_UAO)) { if (task_thread_info(next)->addr_limit == KERNEL_DS) diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S index b8799e7c79de..1bec41b5fda3 100644 --- a/arch/arm64/kernel/sleep.S +++ b/arch/arm64/kernel/sleep.S @@ -135,7 +135,7 @@ ENTRY(_cpu_resume) #ifdef CONFIG_KASAN mov x0, sp - bl kasan_unpoison_remaining_stack + bl kasan_unpoison_task_stack_below #endif ldp x19, x20, [x29, #16] diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index d3f151cfd4a1..8507703dabe4 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -544,6 +544,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) return; } bootcpu_valid = true; + early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid)); return; } diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c index ad734142070d..bb0cd787a9d3 100644 --- a/arch/arm64/kernel/suspend.c +++ b/arch/arm64/kernel/suspend.c @@ -1,8 +1,11 @@ #include <linux/ftrace.h> #include <linux/percpu.h> #include <linux/slab.h> +#include <asm/alternative.h> #include <asm/cacheflush.h> +#include <asm/cpufeature.h> #include <asm/debug-monitors.h> +#include <asm/exec.h> #include <asm/pgtable.h> #include <asm/memory.h> #include <asm/mmu_context.h> @@ -50,6 +53,14 @@ void notrace __cpu_suspend_exit(void) set_my_cpu_offset(per_cpu_offset(cpu)); /* + * PSTATE was not saved over suspend/resume, re-enable any detected + * features that might not have been set correctly. + */ + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, + CONFIG_ARM64_PAN)); + uao_thread_switch(current); + + /* * Restore HW breakpoint registers to sane values * before debug exceptions are possibly reenabled * through local_dbg_restore. diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 5ff020f8fb7f..c9986b3e0a96 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -428,24 +428,28 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0); } -void cpu_enable_cache_maint_trap(void *__unused) +int cpu_enable_cache_maint_trap(void *__unused) { config_sctlr_el1(SCTLR_EL1_UCI, 0); + return 0; } #define __user_cache_maint(insn, address, res) \ - asm volatile ( \ - "1: " insn ", %1\n" \ - " mov %w0, #0\n" \ - "2:\n" \ - " .pushsection .fixup,\"ax\"\n" \ - " .align 2\n" \ - "3: mov %w0, %w2\n" \ - " b 2b\n" \ - " .popsection\n" \ - _ASM_EXTABLE(1b, 3b) \ - : "=r" (res) \ - : "r" (address), "i" (-EFAULT) ) + if (untagged_addr(address) >= user_addr_max()) \ + res = -EFAULT; \ + else \ + asm volatile ( \ + "1: " insn ", %1\n" \ + " mov %w0, #0\n" \ + "2:\n" \ + " .pushsection .fixup,\"ax\"\n" \ + " .align 2\n" \ + "3: mov %w0, %w2\n" \ + " b 2b\n" \ + " .popsection\n" \ + _ASM_EXTABLE(1b, 3b) \ + : "=r" (res) \ + : "r" (address), "i" (-EFAULT) ) static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs) { diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 53d9159662fe..0f8788374815 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -29,7 +29,9 @@ #include <linux/sched.h> #include <linux/highmem.h> #include <linux/perf_event.h> +#include <linux/preempt.h> +#include <asm/bug.h> #include <asm/cpufeature.h> #include <asm/exception.h> #include <asm/debug-monitors.h> @@ -670,9 +672,17 @@ asmlinkage int __exception do_debug_exception(unsigned long addr, NOKPROBE_SYMBOL(do_debug_exception); #ifdef CONFIG_ARM64_PAN -void cpu_enable_pan(void *__unused) +int cpu_enable_pan(void *__unused) { + /* + * We modify PSTATE. This won't work from irq context as the PSTATE + * is discarded once we return from the exception. + */ + WARN_ON_ONCE(in_interrupt()); + config_sctlr_el1(SCTLR_EL1_SPAN, 0); + asm(SET_PSTATE_PAN(1)); + return 0; } #endif /* CONFIG_ARM64_PAN */ @@ -683,8 +693,9 @@ void cpu_enable_pan(void *__unused) * We need to enable the feature at runtime (instead of adding it to * PSR_MODE_EL1h) as the feature may not be implemented by the cpu. */ -void cpu_enable_uao(void *__unused) +int cpu_enable_uao(void *__unused) { asm(SET_PSTATE_UAO(1)); + return 0; } #endif /* CONFIG_ARM64_UAO */ diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 21c489bdeb4e..212c4d1e2f26 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -421,35 +421,35 @@ void __init mem_init(void) pr_notice("Virtual kernel memory layout:\n"); #ifdef CONFIG_KASAN - pr_cont(" kasan : 0x%16lx - 0x%16lx (%6ld GB)\n", + pr_notice(" kasan : 0x%16lx - 0x%16lx (%6ld GB)\n", MLG(KASAN_SHADOW_START, KASAN_SHADOW_END)); #endif - pr_cont(" modules : 0x%16lx - 0x%16lx (%6ld MB)\n", + pr_notice(" modules : 0x%16lx - 0x%16lx (%6ld MB)\n", MLM(MODULES_VADDR, MODULES_END)); - pr_cont(" vmalloc : 0x%16lx - 0x%16lx (%6ld GB)\n", + pr_notice(" vmalloc : 0x%16lx - 0x%16lx (%6ld GB)\n", MLG(VMALLOC_START, VMALLOC_END)); - pr_cont(" .text : 0x%p" " - 0x%p" " (%6ld KB)\n", + pr_notice(" .text : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(_text, _etext)); - pr_cont(" .rodata : 0x%p" " - 0x%p" " (%6ld KB)\n", + pr_notice(" .rodata : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(__start_rodata, __init_begin)); - pr_cont(" .init : 0x%p" " - 0x%p" " (%6ld KB)\n", + pr_notice(" .init : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(__init_begin, __init_end)); - pr_cont(" .data : 0x%p" " - 0x%p" " (%6ld KB)\n", + pr_notice(" .data : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(_sdata, _edata)); - pr_cont(" .bss : 0x%p" " - 0x%p" " (%6ld KB)\n", + pr_notice(" .bss : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(__bss_start, __bss_stop)); - pr_cont(" fixed : 0x%16lx - 0x%16lx (%6ld KB)\n", + pr_notice(" fixed : 0x%16lx - 0x%16lx (%6ld KB)\n", MLK(FIXADDR_START, FIXADDR_TOP)); - pr_cont(" PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n", + pr_notice(" PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n", MLM(PCI_IO_START, PCI_IO_END)); #ifdef CONFIG_SPARSEMEM_VMEMMAP - pr_cont(" vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n", + pr_notice(" vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n", MLG(VMEMMAP_START, VMEMMAP_START + VMEMMAP_SIZE)); - pr_cont(" 0x%16lx - 0x%16lx (%6ld MB actual)\n", + pr_notice(" 0x%16lx - 0x%16lx (%6ld MB actual)\n", MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()), (unsigned long)virt_to_page(high_memory))); #endif - pr_cont(" memory : 0x%16lx - 0x%16lx (%6ld MB)\n", + pr_notice(" memory : 0x%16lx - 0x%16lx (%6ld MB)\n", MLM(__phys_to_virt(memblock_start_of_DRAM()), (unsigned long)high_memory)); diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 8b8fe671b1a6..8d79286ee4e8 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -271,7 +271,7 @@ long arch_ptrace(struct task_struct *child, long request, case BFIN_MEM_ACCESS_CORE: case BFIN_MEM_ACCESS_CORE_ONLY: copied = access_process_vm(child, addr, &tmp, - to_copy, 0); + to_copy, FOLL_FORCE); if (copied) break; @@ -324,7 +324,8 @@ long arch_ptrace(struct task_struct *child, long request, case BFIN_MEM_ACCESS_CORE: case BFIN_MEM_ACCESS_CORE_ONLY: copied = access_process_vm(child, addr, &data, - to_copy, 1); + to_copy, + FOLL_FORCE | FOLL_WRITE); break; case BFIN_MEM_ACCESS_DMA: if (safe_dma_memcpy(paddr, &data, to_copy)) diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c index b5698c876fcc..099e170a93ee 100644 --- a/arch/cris/arch-v32/drivers/cryptocop.c +++ b/arch/cris/arch-v32/drivers/cryptocop.c @@ -2722,7 +2722,6 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig err = get_user_pages((unsigned long int)(oper.indata + prev_ix), noinpages, 0, /* read access only for in data */ - 0, /* no force */ inpages, NULL); @@ -2736,8 +2735,7 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig if (oper.do_cipher){ err = get_user_pages((unsigned long int)oper.cipher_outdata, nooutpages, - 1, /* write access for out data */ - 0, /* no force */ + FOLL_WRITE, /* write access for out data */ outpages, NULL); up_read(¤t->mm->mmap_sem); diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index f085229cf870..f0df654ac6fc 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c @@ -147,7 +147,7 @@ long arch_ptrace(struct task_struct *child, long request, /* The trampoline page is globally mapped, no page table to traverse.*/ tmp = *(unsigned long*)addr; } else { - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), FOLL_FORCE); if (copied != sizeof(tmp)) break; @@ -279,7 +279,7 @@ static int insn_size(struct task_struct *child, unsigned long pc) int opsize = 0; /* Read the opcode at pc (do what PTRACE_PEEKTEXT would do). */ - copied = access_process_vm(child, pc, &opcode, sizeof(opcode), 0); + copied = access_process_vm(child, pc, &opcode, sizeof(opcode), FOLL_FORCE); if (copied != sizeof(opcode)) return 0; diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c index 09f845793d12..5ed0ea92c5bf 100644 --- a/arch/ia64/kernel/err_inject.c +++ b/arch/ia64/kernel/err_inject.c @@ -142,7 +142,7 @@ store_virtual_to_phys(struct device *dev, struct device_attribute *attr, u64 virt_addr=simple_strtoull(buf, NULL, 16); int ret; - ret = get_user_pages(virt_addr, 1, VM_READ, 0, NULL, NULL); + ret = get_user_pages(virt_addr, 1, FOLL_WRITE, NULL, NULL); if (ret<=0) { #ifdef ERR_INJ_DEBUG printk("Virtual address %lx is not existing.\n",virt_addr); diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 6f54d511cc50..31aa8c0f68e1 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -453,7 +453,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack, return 0; } } - copied = access_process_vm(child, addr, &ret, sizeof(ret), 0); + copied = access_process_vm(child, addr, &ret, sizeof(ret), FOLL_FORCE); if (copied != sizeof(ret)) return -EIO; *val = ret; @@ -489,7 +489,8 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack, *ia64_rse_skip_regs(krbs, regnum) = val; } } - } else if (access_process_vm(child, addr, &val, sizeof(val), 1) + } else if (access_process_vm(child, addr, &val, sizeof(val), + FOLL_FORCE | FOLL_WRITE) != sizeof(val)) return -EIO; return 0; @@ -543,7 +544,8 @@ ia64_sync_user_rbs (struct task_struct *child, struct switch_stack *sw, ret = ia64_peek(child, sw, user_rbs_end, addr, &val); if (ret < 0) return ret; - if (access_process_vm(child, addr, &val, sizeof(val), 1) + if (access_process_vm(child, addr, &val, sizeof(val), + FOLL_FORCE | FOLL_WRITE) != sizeof(val)) return -EIO; } @@ -559,7 +561,8 @@ ia64_sync_kernel_rbs (struct task_struct *child, struct switch_stack *sw, /* now copy word for word from user rbs to kernel rbs: */ for (addr = user_rbs_start; addr < user_rbs_end; addr += 8) { - if (access_process_vm(child, addr, &val, sizeof(val), 0) + if (access_process_vm(child, addr, &val, sizeof(val), + FOLL_FORCE) != sizeof(val)) return -EIO; @@ -1156,7 +1159,8 @@ arch_ptrace (struct task_struct *child, long request, case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: /* read word at location addr */ - if (access_process_vm(child, addr, &data, sizeof(data), 0) + if (access_process_vm(child, addr, &data, sizeof(data), + FOLL_FORCE) != sizeof(data)) return -EIO; /* ensure return value is not mistaken for error code */ diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 51f5e9aa4901..c145605a981f 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -493,7 +493,8 @@ unregister_all_debug_traps(struct task_struct *child) int i; for (i = 0; i < p->nr_trap; i++) - access_process_vm(child, p->addr[i], &p->insn[i], sizeof(p->insn[i]), 1); + access_process_vm(child, p->addr[i], &p->insn[i], sizeof(p->insn[i]), + FOLL_FORCE | FOLL_WRITE); p->nr_trap = 0; } @@ -537,7 +538,8 @@ embed_debug_trap(struct task_struct *child, unsigned long next_pc) unsigned long next_insn, code; unsigned long addr = next_pc & ~3; - if (access_process_vm(child, addr, &next_insn, sizeof(next_insn), 0) + if (access_process_vm(child, addr, &next_insn, sizeof(next_insn), + FOLL_FORCE) != sizeof(next_insn)) { return -1; /* error */ } @@ -546,7 +548,8 @@ embed_debug_trap(struct task_struct *child, unsigned long next_pc) if (register_debug_trap(child, next_pc, next_insn, &code)) { return -1; /* error */ } - if (access_process_vm(child, addr, &code, sizeof(code), 1) + if (access_process_vm(child, addr, &code, sizeof(code), + FOLL_FORCE | FOLL_WRITE) != sizeof(code)) { return -1; /* error */ } @@ -562,7 +565,8 @@ withdraw_debug_trap(struct pt_regs *regs) addr = (regs->bpc - 2) & ~3; regs->bpc -= 2; if (unregister_debug_trap(current, addr, &code)) { - access_process_vm(current, addr, &code, sizeof(code), 1); + access_process_vm(current, addr, &code, sizeof(code), + FOLL_FORCE | FOLL_WRITE); invalidate_cache(); } } @@ -589,7 +593,8 @@ void user_enable_single_step(struct task_struct *child) /* Compute next pc. */ pc = get_stack_long(child, PT_BPC); - if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) + if (access_process_vm(child, pc&~3, &insn, sizeof(insn), + FOLL_FORCE) != sizeof(insn)) return; diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 283b5a1967d1..7e71a4e0281b 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -70,7 +70,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, break; copied = access_process_vm(child, (u64)addrOthers, &tmp, - sizeof(tmp), 0); + sizeof(tmp), FOLL_FORCE); if (copied != sizeof(tmp)) break; ret = put_user(tmp, (u32 __user *) (unsigned long) data); @@ -179,7 +179,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, break; ret = 0; if (access_process_vm(child, (u64)addrOthers, &data, - sizeof(data), 1) == sizeof(data)) + sizeof(data), + FOLL_FORCE | FOLL_WRITE) == sizeof(data)) break; ret = -EIO; break; diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index ce961495b5e1..622037d851a3 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -14,6 +14,7 @@ #include <linux/err.h> #include <linux/kdebug.h> #include <linux/module.h> +#include <linux/uaccess.h> #include <linux/vmalloc.h> #include <linux/fs.h> #include <linux/bootmem.h> diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c index 42d124fb6474..d8c3c159289a 100644 --- a/arch/mips/mm/gup.c +++ b/arch/mips/mm/gup.c @@ -287,7 +287,7 @@ slow_irqon: pages += nr; ret = get_user_pages_unlocked(start, (end - start) >> PAGE_SHIFT, - write, 0, pages); + pages, write ? FOLL_WRITE : 0); /* Have to be a bit careful with return values */ if (nr > 0) { diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index f7a184b6c35b..57d42d129033 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c @@ -32,9 +32,16 @@ static struct addr_range prep_kernel(void) void *addr = 0; struct elf_info ei; long len; + int uncompressed_image = 0; - partial_decompress(vmlinuz_addr, vmlinuz_size, + len = partial_decompress(vmlinuz_addr, vmlinuz_size, elfheader, sizeof(elfheader), 0); + /* assume uncompressed data if -1 is returned */ + if (len == -1) { + uncompressed_image = 1; + memcpy(elfheader, vmlinuz_addr, sizeof(elfheader)); + printf("No valid compressed data found, assume uncompressed data\n\r"); + } if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei)) fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r"); @@ -67,6 +74,13 @@ static struct addr_range prep_kernel(void) "device tree\n\r"); } + if (uncompressed_image) { + memcpy(addr, vmlinuz_addr + ei.elfoffset, ei.loadsize); + printf("0x%lx bytes of uncompressed data copied\n\r", + ei.loadsize); + goto out; + } + /* Finally, decompress the kernel */ printf("Decompressing (0x%p <- 0x%p:0x%p)...\n\r", addr, vmlinuz_addr, vmlinuz_addr+vmlinuz_size); @@ -82,7 +96,7 @@ static struct addr_range prep_kernel(void) len, ei.loadsize); printf("Done! Decompressed 0x%lx bytes\n\r", len); - +out: flush_cache(addr, ei.loadsize); return (struct addr_range){addr, ei.memsize}; diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index cf12c580f6b2..e8cdfec8d512 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -16,6 +16,10 @@ #define __NR__exit __NR_exit +#define __IGNORE_pkey_mprotect +#define __IGNORE_pkey_alloc +#define __IGNORE_pkey_free + #ifndef __ASSEMBLY__ #include <linux/types.h> diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index f52b7db327c8..010b7b310237 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c @@ -74,7 +74,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, break; copied = access_process_vm(child, (u64)addrOthers, &tmp, - sizeof(tmp), 0); + sizeof(tmp), FOLL_FORCE); if (copied != sizeof(tmp)) break; ret = put_user(tmp, (u32 __user *)data); @@ -179,7 +179,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, break; ret = 0; if (access_process_vm(child, (u64)addrOthers, &tmp, - sizeof(tmp), 1) == sizeof(tmp)) + sizeof(tmp), + FOLL_FORCE | FOLL_WRITE) == sizeof(tmp)) break; ret = -EIO; break; diff --git a/arch/powerpc/mm/copro_fault.c b/arch/powerpc/mm/copro_fault.c index bb0354222b11..362954f98029 100644 --- a/arch/powerpc/mm/copro_fault.c +++ b/arch/powerpc/mm/copro_fault.c @@ -106,6 +106,8 @@ int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb) switch (REGION_ID(ea)) { case USER_REGION_ID: pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea); + if (mm == NULL) + return 1; psize = get_slice_psize(mm, ea); ssize = user_segment_size(ea); vsid = get_vsid(mm->context.id, ea, ssize); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 75b9cd6150cc..a51c188b81f3 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -845,7 +845,7 @@ void __init dump_numa_cpu_topology(void) return; for_each_online_node(node) { - printk(KERN_DEBUG "Node %d CPUs:", node); + pr_info("Node %d CPUs:", node); count = 0; /* @@ -856,52 +856,18 @@ void __init dump_numa_cpu_topology(void) if (cpumask_test_cpu(cpu, node_to_cpumask_map[node])) { if (count == 0) - printk(" %u", cpu); + pr_cont(" %u", cpu); ++count; } else { if (count > 1) - printk("-%u", cpu - 1); + pr_cont("-%u", cpu - 1); count = 0; } } if (count > 1) - printk("-%u", nr_cpu_ids - 1); - printk("\n"); - } -} - -static void __init dump_numa_memory_topology(void) -{ - unsigned int node; - unsigned int count; - - if (min_common_depth == -1 || !numa_enabled) - return; - - for_each_online_node(node) { - unsigned long i; - - printk(KERN_DEBUG "Node %d Memory:", node); - - count = 0; - - for (i = 0; i < memblock_end_of_DRAM(); - i += (1 << SECTION_SIZE_BITS)) { - if (early_pfn_to_nid(i >> PAGE_SHIFT) == node) { - if (count == 0) - printk(" 0x%lx", i); - ++count; - } else { - if (count > 0) - printk("-0x%lx", i); - count = 0; - } - } - - if (count > 0) - printk("-0x%lx", i); - printk("\n"); + pr_cont("-%u", nr_cpu_ids - 1); + pr_cont("\n"); } } @@ -947,8 +913,6 @@ void __init initmem_init(void) if (parse_numa_properties()) setup_nonnuma(); - else - dump_numa_memory_topology(); memblock_dump_all(); diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 1cab8a177d0e..7a27eebab28a 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -119,8 +119,13 @@ static int handle_validity(struct kvm_vcpu *vcpu) vcpu->stat.exit_validity++; trace_kvm_s390_intercept_validity(vcpu, viwhy); - WARN_ONCE(true, "kvm: unhandled validity intercept 0x%x\n", viwhy); - return -EOPNOTSUPP; + KVM_EVENT(3, "validity intercept 0x%x for pid %u (kvm 0x%pK)", viwhy, + current->pid, vcpu->kvm); + + /* do not warn on invalid runtime instrumentation mode */ + WARN_ONCE(viwhy != 0x44, "kvm: unhandled validity intercept 0x%x\n", + viwhy); + return -EINVAL; } static int handle_instruction(struct kvm_vcpu *vcpu) diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index adb0c34bf431..18d4107e10ee 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -266,7 +266,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, /* Try to get the remaining pages with get_user_pages */ start += nr << PAGE_SHIFT; pages += nr; - ret = get_user_pages_unlocked(start, nr_pages - nr, write, 0, pages); + ret = get_user_pages_unlocked(start, nr_pages - nr, pages, + write ? FOLL_WRITE : 0); /* Have to be a bit careful with return values */ if (nr > 0) ret = (ret < 0) ? nr : ret + nr; diff --git a/arch/score/kernel/ptrace.c b/arch/score/kernel/ptrace.c index 55836188b217..4f7314d5f334 100644 --- a/arch/score/kernel/ptrace.c +++ b/arch/score/kernel/ptrace.c @@ -131,7 +131,7 @@ read_tsk_long(struct task_struct *child, { int copied; - copied = access_process_vm(child, addr, res, sizeof(*res), 0); + copied = access_process_vm(child, addr, res, sizeof(*res), FOLL_FORCE); return copied != sizeof(*res) ? -EIO : 0; } @@ -142,7 +142,7 @@ read_tsk_short(struct task_struct *child, { int copied; - copied = access_process_vm(child, addr, res, sizeof(*res), 0); + copied = access_process_vm(child, addr, res, sizeof(*res), FOLL_FORCE); return copied != sizeof(*res) ? -EIO : 0; } @@ -153,7 +153,8 @@ write_tsk_short(struct task_struct *child, { int copied; - copied = access_process_vm(child, addr, &val, sizeof(val), 1); + copied = access_process_vm(child, addr, &val, sizeof(val), + FOLL_FORCE | FOLL_WRITE); return copied != sizeof(val) ? -EIO : 0; } @@ -164,7 +165,8 @@ write_tsk_long(struct task_struct *child, { int copied; - copied = access_process_vm(child, addr, &val, sizeof(val), 1); + copied = access_process_vm(child, addr, &val, sizeof(val), + FOLL_FORCE | FOLL_WRITE); return copied != sizeof(val) ? -EIO : 0; } diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 00476662ac2c..336f33a419d9 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -31,7 +31,7 @@ isa-y := $(isa-y)-up endif cflags-$(CONFIG_CPU_SH2) := $(call cc-option,-m2,) -cflags-$(CONFIG_CPU_J2) := $(call cc-option,-mj2,) +cflags-$(CONFIG_CPU_J2) += $(call cc-option,-mj2,) cflags-$(CONFIG_CPU_SH2A) += $(call cc-option,-m2a,) \ $(call cc-option,-m2a-nofpu,) \ $(call cc-option,-m4-nofpu,) diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index e9c2c42031fe..4e21949593cf 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -22,6 +22,16 @@ config SH_DEVICE_TREE have sufficient driver coverage to use this option; do not select it if you are using original SuperH hardware. +config SH_JCORE_SOC + bool "J-Core SoC" + depends on SH_DEVICE_TREE && (CPU_SH2 || CPU_J2) + select CLKSRC_JCORE_PIT + select JCORE_AIC + default y if CPU_J2 + help + Select this option to include drivers core components of the + J-Core SoC, including interrupt controllers and timers. + config SH_SOLUTION_ENGINE bool "SolutionEngine" select SOLUTION_ENGINE diff --git a/arch/sh/configs/j2_defconfig b/arch/sh/configs/j2_defconfig index 94d1eca52f72..2eb81ebe3888 100644 --- a/arch/sh/configs/j2_defconfig +++ b/arch/sh/configs/j2_defconfig @@ -8,6 +8,7 @@ CONFIG_MEMORY_START=0x10000000 CONFIG_MEMORY_SIZE=0x04000000 CONFIG_CPU_BIG_ENDIAN=y CONFIG_SH_DEVICE_TREE=y +CONFIG_SH_JCORE_SOC=y CONFIG_HZ_100=y CONFIG_CMDLINE_OVERWRITE=y CONFIG_CMDLINE="console=ttyUL0 earlycon" @@ -20,6 +21,7 @@ CONFIG_INET=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_NETDEVICES=y +CONFIG_SERIAL_EARLYCON=y CONFIG_SERIAL_UARTLITE=y CONFIG_SERIAL_UARTLITE_CONSOLE=y CONFIG_I2C=y diff --git a/arch/sh/mm/gup.c b/arch/sh/mm/gup.c index 40fa6c8adc43..063c298ba56c 100644 --- a/arch/sh/mm/gup.c +++ b/arch/sh/mm/gup.c @@ -258,7 +258,8 @@ slow_irqon: pages += nr; ret = get_user_pages_unlocked(start, - (end - start) >> PAGE_SHIFT, write, 0, pages); + (end - start) >> PAGE_SHIFT, pages, + write ? FOLL_WRITE : 0); /* Have to be a bit careful with return values */ if (nr > 0) { diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index 9ddc4928a089..ac082dd8c67d 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c @@ -127,7 +127,8 @@ static int get_from_target(struct task_struct *target, unsigned long uaddr, if (copy_from_user(kbuf, (void __user *) uaddr, len)) return -EFAULT; } else { - int len2 = access_process_vm(target, uaddr, kbuf, len, 0); + int len2 = access_process_vm(target, uaddr, kbuf, len, + FOLL_FORCE); if (len2 != len) return -EFAULT; } @@ -141,7 +142,8 @@ static int set_to_target(struct task_struct *target, unsigned long uaddr, if (copy_to_user((void __user *) uaddr, kbuf, len)) return -EFAULT; } else { - int len2 = access_process_vm(target, uaddr, kbuf, len, 1); + int len2 = access_process_vm(target, uaddr, kbuf, len, + FOLL_FORCE | FOLL_WRITE); if (len2 != len) return -EFAULT; } @@ -505,7 +507,8 @@ static int genregs32_get(struct task_struct *target, if (access_process_vm(target, (unsigned long) ®_window[pos], - k, sizeof(*k), 0) + k, sizeof(*k), + FOLL_FORCE) != sizeof(*k)) return -EFAULT; k++; @@ -531,12 +534,14 @@ static int genregs32_get(struct task_struct *target, if (access_process_vm(target, (unsigned long) ®_window[pos], - ®, sizeof(reg), 0) + ®, sizeof(reg), + FOLL_FORCE) != sizeof(reg)) return -EFAULT; if (access_process_vm(target, (unsigned long) u, - ®, sizeof(reg), 1) + ®, sizeof(reg), + FOLL_FORCE | FOLL_WRITE) != sizeof(reg)) return -EFAULT; pos++; @@ -615,7 +620,8 @@ static int genregs32_set(struct task_struct *target, (unsigned long) ®_window[pos], (void *) k, - sizeof(*k), 1) + sizeof(*k), + FOLL_FORCE | FOLL_WRITE) != sizeof(*k)) return -EFAULT; k++; @@ -642,13 +648,15 @@ static int genregs32_set(struct task_struct *target, if (access_process_vm(target, (unsigned long) u, - ®, sizeof(reg), 0) + ®, sizeof(reg), + FOLL_FORCE) != sizeof(reg)) return -EFAULT; if (access_process_vm(target, (unsigned long) ®_window[pos], - ®, sizeof(reg), 1) + ®, sizeof(reg), + FOLL_FORCE | FOLL_WRITE) != sizeof(reg)) return -EFAULT; pos++; diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c index 4e06750a5d29..cd0e32bbcb1d 100644 --- a/arch/sparc/mm/gup.c +++ b/arch/sparc/mm/gup.c @@ -238,7 +238,8 @@ slow: pages += nr; ret = get_user_pages_unlocked(start, - (end - start) >> PAGE_SHIFT, write, 0, pages); + (end - start) >> PAGE_SHIFT, pages, + write ? FOLL_WRITE : 0); /* Have to be a bit careful with return values */ if (nr > 0) { diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index ff6ef7b30822..2b3618542544 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -389,5 +389,3 @@ 380 i386 pkey_mprotect sys_pkey_mprotect 381 i386 pkey_alloc sys_pkey_alloc 382 i386 pkey_free sys_pkey_free -#383 i386 pkey_get sys_pkey_get -#384 i386 pkey_set sys_pkey_set diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 2f024d02511d..e93ef0b38db8 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -338,8 +338,6 @@ 329 common pkey_mprotect sys_pkey_mprotect 330 common pkey_alloc sys_pkey_alloc 331 common pkey_free sys_pkey_free -#332 common pkey_get sys_pkey_get -#333 common pkey_set sys_pkey_set # # x32-specific system call numbers start at 512 to avoid cache impact diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index a3a9eb84b5cf..eab0915f5995 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -3898,6 +3898,7 @@ __init int intel_pmu_init(void) break; case INTEL_FAM6_XEON_PHI_KNL: + case INTEL_FAM6_XEON_PHI_KNM: memcpy(hw_cache_event_ids, slm_hw_cache_event_ids, sizeof(hw_cache_event_ids)); memcpy(hw_cache_extra_regs, @@ -3912,7 +3913,7 @@ __init int intel_pmu_init(void) x86_pmu.flags |= PMU_FL_HAS_RSP_1; x86_pmu.flags |= PMU_FL_NO_HT_SHARING; - pr_cont("Knights Landing events, "); + pr_cont("Knights Landing/Mill events, "); break; case INTEL_FAM6_SKYLAKE_MOBILE: diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index fc6cf21c535e..81b321ace8e0 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -458,8 +458,8 @@ void intel_pmu_lbr_del(struct perf_event *event) if (!x86_pmu.lbr_nr) return; - if (branch_user_callstack(cpuc->br_sel) && event->ctx && - event->ctx->task_ctx_data) { + if (branch_user_callstack(cpuc->br_sel) && + event->ctx->task_ctx_data) { task_ctx = event->ctx->task_ctx_data; task_ctx->lbr_callstack_users--; } diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index b0f0e835a770..0a535cea8ff3 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c @@ -763,6 +763,7 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = { X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsw_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_rapl_init), + X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNM, knl_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, skl_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP, skl_rapl_init), diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index d9844cc74486..efca2685d876 100644 --- a/arch/x86/events/intel/uncore.c +++ b/arch/x86/events/intel/uncore.c @@ -1349,6 +1349,7 @@ static const struct x86_cpu_id intel_uncore_match[] __initconst = { X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL_X, bdx_uncore_init), X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, bdx_uncore_init), X86_UNCORE_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_uncore_init), + X86_UNCORE_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNM, knl_uncore_init), X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP,skl_uncore_init), X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, skl_uncore_init), X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X, skx_uncore_init), diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 1188bc849ee3..a39629206864 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -194,6 +194,8 @@ #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ #define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ +#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */ +#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */ /* Virtualization flags: Linux defined, word 8 */ #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h index 9ae5ab80a497..34a46dc076d3 100644 --- a/arch/x86/include/asm/intel-family.h +++ b/arch/x86/include/asm/intel-family.h @@ -64,5 +64,6 @@ /* Xeon Phi */ #define INTEL_FAM6_XEON_PHI_KNL 0x57 /* Knights Landing */ +#define INTEL_FAM6_XEON_PHI_KNM 0x85 /* Knights Mill */ #endif /* _ASM_X86_INTEL_FAMILY_H */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 56f4c6676b29..78f3760ca1f2 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -88,7 +88,6 @@ #define MSR_IA32_RTIT_CTL 0x00000570 #define MSR_IA32_RTIT_STATUS 0x00000571 -#define MSR_IA32_RTIT_STATUS 0x00000571 #define MSR_IA32_RTIT_ADDR0_A 0x00000580 #define MSR_IA32_RTIT_ADDR0_B 0x00000581 #define MSR_IA32_RTIT_ADDR1_A 0x00000582 diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h index 3d33a719f5c1..a34e0d4b957d 100644 --- a/arch/x86/include/asm/rwsem.h +++ b/arch/x86/include/asm/rwsem.h @@ -103,8 +103,10 @@ static inline bool __down_read_trylock(struct rw_semaphore *sem) ({ \ long tmp; \ struct rw_semaphore* ret; \ + register void *__sp asm(_ASM_SP); \ + \ asm volatile("# beginning down_write\n\t" \ - LOCK_PREFIX " xadd %1,(%3)\n\t" \ + LOCK_PREFIX " xadd %1,(%4)\n\t" \ /* adds 0xffff0001, returns the old value */ \ " test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" \ /* was the active mask 0 before? */\ @@ -112,7 +114,7 @@ static inline bool __down_read_trylock(struct rw_semaphore *sem) " call " slow_path "\n" \ "1:\n" \ "# ending down_write" \ - : "+m" (sem->count), "=d" (tmp), "=a" (ret) \ + : "+m" (sem->count), "=d" (tmp), "=a" (ret), "+r" (__sp) \ : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) \ : "memory", "cc"); \ ret; \ diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 2aaca53c0974..ad6f5eb07a95 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -52,6 +52,15 @@ struct task_struct; #include <asm/cpufeature.h> #include <linux/atomic.h> +struct thread_info { + unsigned long flags; /* low level flags */ +}; + +#define INIT_THREAD_INFO(tsk) \ +{ \ + .flags = 0, \ +} + #define init_stack (init_thread_union.stack) #else /* !__ASSEMBLY__ */ diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index 8cb57df9398d..1db8dc490b66 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -32,6 +32,8 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c) static const struct cpuid_bit cpuid_bits[] = { { X86_FEATURE_INTEL_PT, CR_EBX,25, 0x00000007, 0 }, + { X86_FEATURE_AVX512_4VNNIW, CR_EDX, 2, 0x00000007, 0 }, + { X86_FEATURE_AVX512_4FMAPS, CR_EDX, 3, 0x00000007, 0 }, { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 }, { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 }, { X86_FEATURE_HW_PSTATE, CR_EDX, 7, 0x80000007, 0 }, diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 81160578b91a..5130985b758b 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -27,6 +27,7 @@ #include <asm/div64.h> #include <asm/x86_init.h> #include <asm/hypervisor.h> +#include <asm/timer.h> #include <asm/apic.h> #define CPUID_VMWARE_INFO_LEAF 0x40000000 @@ -94,6 +95,10 @@ static void __init vmware_platform_setup(void) } else { pr_warn("Failed to get TSC freq from the hypervisor\n"); } + +#ifdef CONFIG_X86_IO_APIC + no_timer_check = 1; +#endif } /* diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index b85fe5f91c3f..90e8dde3ec26 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -350,7 +350,7 @@ int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, * continue building up new bios map based on this * information */ - if (current_type != last_type) { + if (current_type != last_type || current_type == E820_PRAM) { if (last_type != 0) { new_bios[new_bios_entry].size = change_point[chgidx]->addr - last_addr; diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index 124aa5c593f8..095ef7ddd6ae 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -74,6 +74,8 @@ void fpu__xstate_clear_all_cpu_caps(void) setup_clear_cpu_cap(X86_FEATURE_MPX); setup_clear_cpu_cap(X86_FEATURE_XGETBV1); setup_clear_cpu_cap(X86_FEATURE_PKU); + setup_clear_cpu_cap(X86_FEATURE_AVX512_4VNNIW); + setup_clear_cpu_cap(X86_FEATURE_AVX512_4FMAPS); } /* diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 28cee019209c..d9d8d16b69db 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -50,6 +50,7 @@ #include <linux/kallsyms.h> #include <linux/ftrace.h> #include <linux/frame.h> +#include <linux/kasan.h> #include <asm/text-patching.h> #include <asm/cacheflush.h> @@ -1057,9 +1058,10 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) * tailcall optimization. So, to be absolutely safe * we also save and restore enough stack bytes to cover * the argument area. + * Use __memcpy() to avoid KASAN stack out-of-bounds reports as we copy + * raw stack chunk with redzones: */ - memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, - MIN_STACK_SIZE(addr)); + __memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, MIN_STACK_SIZE(addr)); regs->flags &= ~X86_EFLAGS_IF; trace_hardirqs_off(); regs->ip = (unsigned long)(jp->entry); @@ -1080,6 +1082,9 @@ void jprobe_return(void) { struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + /* Unpoison stack redzones in the frames we are going to jump over. */ + kasan_unpoison_stack_above_sp_to(kcb->jprobe_saved_sp); + asm volatile ( #ifdef CONFIG_X86_64 " xchg %%rbx,%%rsp \n" @@ -1118,7 +1123,7 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) /* It's OK to start function graph tracing again */ unpause_graph_tracing(); *regs = kcb->jprobe_saved_regs; - memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp)); + __memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp)); preempt_enable_no_resched(); return 1; } diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c index 40df33753bae..ec1f756f9dc9 100644 --- a/arch/x86/kernel/signal_compat.c +++ b/arch/x86/kernel/signal_compat.c @@ -105,9 +105,6 @@ void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact) /* Don't let flags to be set from userspace */ act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI); - if (user_64bit_mode(current_pt_regs())) - return; - if (in_ia32_syscall()) act->sa.sa_flags |= SA_IA32_ABI; if (in_x32_syscall()) diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 68f8cc222f25..c00cb64bc0a1 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -261,8 +261,10 @@ static inline void __smp_reschedule_interrupt(void) __visible void smp_reschedule_interrupt(struct pt_regs *regs) { + irq_enter(); ack_APIC_irq(); __smp_reschedule_interrupt(); + irq_exit(); /* * KVM uses this interrupt to force a cpu out of guest mode */ diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 951f093a96fe..42f5eb7b4f6c 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1409,15 +1409,17 @@ __init void prefill_possible_map(void) /* No boot processor was found in mptable or ACPI MADT */ if (!num_processors) { - int apicid = boot_cpu_physical_apicid; - int cpu = hard_smp_processor_id(); + if (boot_cpu_has(X86_FEATURE_APIC)) { + int apicid = boot_cpu_physical_apicid; + int cpu = hard_smp_processor_id(); - pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu); + pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu); - /* Make sure boot cpu is enumerated */ - if (apic->cpu_present_to_apicid(0) == BAD_APICID && - apic->apic_id_valid(apicid)) - generic_processor_info(apicid, boot_cpu_apic_version); + /* Make sure boot cpu is enumerated */ + if (apic->cpu_present_to_apicid(0) == BAD_APICID && + apic->apic_id_valid(apicid)) + generic_processor_info(apicid, boot_cpu_apic_version); + } if (!num_processors) num_processors = 1; diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index c9a073866ca7..a23ce84a3f6c 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c @@ -57,7 +57,8 @@ static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs) unsigned char opcode[15]; unsigned long addr = convert_ip_to_linear(child, regs); - copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0); + copied = access_process_vm(child, addr, opcode, sizeof(opcode), + FOLL_FORCE); for (i = 0; i < copied; i++) { switch (opcode[i]) { /* popf and iret */ diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c index c7220ba94aa7..1a22de70f7f7 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c @@ -594,7 +594,7 @@ static void kvm_ioapic_reset(struct kvm_ioapic *ioapic) ioapic->irr = 0; ioapic->irr_delivered = 0; ioapic->id = 0; - memset(ioapic->irq_eoi, 0x00, IOAPIC_NUM_PINS); + memset(ioapic->irq_eoi, 0x00, sizeof(ioapic->irq_eoi)); rtc_irq_eoi_tracking_reset(ioapic); } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 6c633de84dd7..e375235d81c9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5733,13 +5733,13 @@ static int kvmclock_cpu_online(unsigned int cpu) static void kvm_timer_init(void) { - int cpu; - max_tsc_khz = tsc_khz; if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) { #ifdef CONFIG_CPU_FREQ struct cpufreq_policy policy; + int cpu; + memset(&policy, 0, sizeof(policy)); cpu = get_cpu(); cpufreq_get_policy(&policy, cpu); diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index b8b6a60b32cf..0d4fb3ebbbac 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c @@ -435,7 +435,7 @@ slow_irqon: ret = get_user_pages_unlocked(start, (end - start) >> PAGE_SHIFT, - write, 0, pages); + pages, write ? FOLL_WRITE : 0); /* Have to be a bit careful with return values */ if (nr > 0) { diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c index 80476878eb4c..e4f800999b32 100644 --- a/arch/x86/mm/mpx.c +++ b/arch/x86/mm/mpx.c @@ -544,10 +544,9 @@ static int mpx_resolve_fault(long __user *addr, int write) { long gup_ret; int nr_pages = 1; - int force = 0; - gup_ret = get_user_pages((unsigned long)addr, nr_pages, write, - force, NULL, NULL); + gup_ret = get_user_pages((unsigned long)addr, nr_pages, + write ? FOLL_WRITE : 0, NULL, NULL); /* * get_user_pages() returns number of pages gotten. * 0 means we failed to fault in and get anything, diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c index b4d5e95fe4df..4a6a5a26c582 100644 --- a/arch/x86/platform/uv/bios_uv.c +++ b/arch/x86/platform/uv/bios_uv.c @@ -40,7 +40,15 @@ s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5) */ return BIOS_STATUS_UNIMPLEMENTED; - ret = efi_call_virt_pointer(tab, function, (u64)which, a1, a2, a3, a4, a5); + /* + * If EFI_OLD_MEMMAP is set, we need to fall back to using our old EFI + * callback method, which uses efi_call() directly, with the kernel page tables: + */ + if (unlikely(test_bit(EFI_OLD_MEMMAP, &efi.flags))) + ret = efi_call((void *)__va(tab->function), (u64)which, a1, a2, a3, a4, a5); + else + ret = efi_call_virt_pointer(tab, function, (u64)which, a1, a2, a3, a4, a5); + return ret; } EXPORT_SYMBOL_GPL(uv_bios_call); diff --git a/arch/x86/um/ptrace_32.c b/arch/x86/um/ptrace_32.c index 5766ead6fdb9..60a5a5a85505 100644 --- a/arch/x86/um/ptrace_32.c +++ b/arch/x86/um/ptrace_32.c @@ -36,7 +36,8 @@ int is_syscall(unsigned long addr) * slow, but that doesn't matter, since it will be called only * in case of singlestepping, if copy_from_user failed. */ - n = access_process_vm(current, addr, &instr, sizeof(instr), 0); + n = access_process_vm(current, addr, &instr, sizeof(instr), + FOLL_FORCE); if (n != sizeof(instr)) { printk(KERN_ERR "is_syscall : failed to read " "instruction from 0x%lx\n", addr); diff --git a/arch/x86/um/ptrace_64.c b/arch/x86/um/ptrace_64.c index 0b5c184dd5b3..e30202b1716e 100644 --- a/arch/x86/um/ptrace_64.c +++ b/arch/x86/um/ptrace_64.c @@ -212,7 +212,8 @@ int is_syscall(unsigned long addr) * slow, but that doesn't matter, since it will be called only * in case of singlestepping, if copy_from_user failed. */ - n = access_process_vm(current, addr, &instr, sizeof(instr), 0); + n = access_process_vm(current, addr, &instr, sizeof(instr), + FOLL_FORCE); if (n != sizeof(instr)) { printk("is_syscall : failed to read instruction from " "0x%lx\n", addr); |