diff options
Diffstat (limited to 'arch/arm/mach-shmobile')
53 files changed, 995 insertions, 757 deletions
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 0df5ae6740c..fe2c97c179d 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -3,7 +3,7 @@ # # Common objects -obj-y := timer.o console.o clock.o common.o +obj-y := timer.o console.o clock.o # CPU objects obj-$(CONFIG_ARCH_SH7367) += setup-sh7367.o clock-sh7367.o intc-sh7367.o diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index d82c010fdfc..25eb88a923e 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -40,7 +40,6 @@ #include <linux/mmc/sh_mobile_sdhi.h> #include <linux/mfd/tmio.h> #include <linux/sh_clk.h> -#include <linux/videodev2.h> #include <video/sh_mobile_lcdc.h> #include <video/sh_mipi_dsi.h> #include <sound/sh_fsi.h> @@ -650,6 +649,7 @@ static void __init ag5evm_init(void) } MACHINE_START(AG5EVM, "ag5evm") + .smp = smp_ops(sh73a0_smp_ops), .map_io = sh73a0_map_io, .init_early = sh73a0_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index f172ca85905..790dc68c431 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -66,6 +66,8 @@ #include <asm/mach/arch.h> #include <asm/setup.h> +#include "sh-gpio.h" + /* * Address Interface BusWidth note * ------------------------------------------------------------------ @@ -432,7 +434,7 @@ static void usb1_host_port_power(int port, int power) return; /* set VBOUT/PWEN and EXTLP1 in DVSTCTR */ - __raw_writew(__raw_readw(0xE68B0008) | 0x600, 0xE68B0008); + __raw_writew(__raw_readw(IOMEM(0xE68B0008)) | 0x600, IOMEM(0xE68B0008)); } static struct r8a66597_platdata usb1_host_data = { @@ -1224,11 +1226,20 @@ static struct i2c_board_info i2c1_devices[] = { }; -#define GPIO_PORT9CR 0xE6051009 -#define GPIO_PORT10CR 0xE605100A -#define USCCR1 0xE6058144 +#define GPIO_PORT9CR IOMEM(0xE6051009) +#define GPIO_PORT10CR IOMEM(0xE605100A) +#define USCCR1 IOMEM(0xE6058144) static void __init ap4evb_init(void) { + struct pm_domain_device domain_devices[] = { + { "A4LC", &lcdc1_device, }, + { "A4LC", &lcdc_device, }, + { "A4MP", &fsi_device, }, + { "A3SP", &sh_mmcif_device, }, + { "A3SP", &sdhi0_device, }, + { "A3SP", &sdhi1_device, }, + { "A4R", &ceu_device, }, + }; u32 srcr4; struct clk *clk; @@ -1304,7 +1315,7 @@ static void __init ap4evb_init(void) gpio_request(GPIO_FN_OVCN2_1, NULL); /* setup USB phy */ - __raw_writew(0x8a0a, 0xE6058130); /* USBCR4 */ + __raw_writew(0x8a0a, IOMEM(0xE6058130)); /* USBCR4 */ /* enable FSI2 port A (ak4643) */ gpio_request(GPIO_FN_FSIAIBT, NULL); @@ -1453,7 +1464,7 @@ static void __init ap4evb_init(void) gpio_request(GPIO_FN_HDMI_CEC, NULL); /* Reset HDMI, must be held at least one EXTALR (32768Hz) period */ -#define SRCR4 0xe61580bc +#define SRCR4 IOMEM(0xe61580bc) srcr4 = __raw_readl(SRCR4); __raw_writel(srcr4 | (1 << 13), SRCR4); udelay(50); @@ -1461,14 +1472,8 @@ static void __init ap4evb_init(void) platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); - rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc1_device); - rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device); - rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device); - - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device); - rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device); + rmobile_add_devices_to_domains(domain_devices, + ARRAY_SIZE(domain_devices)); hdmi_init_pm_clock(); fsi_init_pm_clock(); @@ -1483,6 +1488,6 @@ MACHINE_START(AP4EVB, "ap4evb") .init_irq = sh7372_init_irq, .handle_irq = shmobile_handle_irq_intc, .init_machine = ap4evb_init, - .init_late = shmobile_init_late, + .init_late = sh7372_pm_init_late, .timer = &shmobile_timer, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 453a6e50db8..2912eab3b96 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -37,6 +37,7 @@ #include <linux/mmc/host.h> #include <linux/mmc/sh_mmcif.h> #include <linux/mmc/sh_mobile_sdhi.h> +#include <linux/i2c-gpio.h> #include <mach/common.h> #include <mach/irqs.h> #include <mach/r8a7740.h> @@ -54,6 +55,8 @@ #include <sound/sh_fsi.h> #include <sound/simple_card.h> +#include "sh-gpio.h" + /* * CON1 Camera Module * CON2 Extension Bus @@ -135,7 +138,7 @@ * usbhsf_power_ctrl() */ #define IRQ7 evt2irq(0x02e0) -#define USBCR1 0xe605810a +#define USBCR1 IOMEM(0xe605810a) #define USBH 0xC6700000 #define USBH_USBCTR 0x10834 @@ -877,6 +880,21 @@ static struct platform_device fsi_hdmi_device = { }, }; +/* RTC: RTC connects i2c-gpio. */ +static struct i2c_gpio_platform_data i2c_gpio_data = { + .sda_pin = GPIO_PORT208, + .scl_pin = GPIO_PORT91, + .udelay = 5, /* 100 kHz */ +}; + +static struct platform_device i2c_gpio_device = { + .name = "i2c-gpio", + .id = 2, + .dev = { + .platform_data = &i2c_gpio_data, + }, +}; + /* I2C */ static struct i2c_board_info i2c0_devices[] = { { @@ -888,6 +906,13 @@ static struct i2c_board_info i2c0_devices[] = { }, }; +static struct i2c_board_info i2c2_devices[] = { + { + I2C_BOARD_INFO("s35390a", 0x30), + .type = "s35390a", + }, +}; + /* * board devices */ @@ -904,6 +929,7 @@ static struct platform_device *eva_devices[] __initdata = { &fsi_device, &fsi_wm8978_device, &fsi_hdmi_device, + &i2c_gpio_device, }; static void __init eva_clock_init(void) @@ -950,8 +976,8 @@ clock_error: /* * board init */ -#define GPIO_PORT7CR 0xe6050007 -#define GPIO_PORT8CR 0xe6050008 +#define GPIO_PORT7CR IOMEM(0xe6050007) +#define GPIO_PORT8CR IOMEM(0xe6050008) static void __init eva_init(void) { struct platform_device *usb = NULL; @@ -1174,6 +1200,7 @@ static void __init eva_init(void) #endif i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); + i2c_register_board_info(2, i2c2_devices, ARRAY_SIZE(i2c2_devices)); r8a7740_add_standard_devices(); @@ -1182,10 +1209,10 @@ static void __init eva_init(void) eva_clock_init(); - rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device); - rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device); + rmobile_add_device_to_domain("A4LC", &lcdc0_device); + rmobile_add_device_to_domain("A4LC", &hdmi_lcdc_device); if (usb) - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, usb); + rmobile_add_device_to_domain("A3SP", usb); } static void __init eva_earlytimer_init(void) diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c index 4129008eae2..cb8c994e143 100644 --- a/arch/arm/mach-shmobile/board-bonito.c +++ b/arch/arm/mach-shmobile/board-bonito.c @@ -108,12 +108,12 @@ static struct regulator_consumer_supply dummy_supplies[] = { #define FPGA_ETH_IRQ (FPGA_IRQ0 + 15) static u16 bonito_fpga_read(u32 offset) { - return __raw_readw(0xf0003000 + offset); + return __raw_readw(IOMEM(0xf0003000) + offset); } static void bonito_fpga_write(u32 offset, u16 val) { - __raw_writew(val, 0xf0003000 + offset); + __raw_writew(val, IOMEM(0xf0003000) + offset); } static void bonito_fpga_irq_disable(struct irq_data *data) @@ -361,8 +361,8 @@ static void __init bonito_map_io(void) #define BIT_ON(sw, bit) (sw & (1 << bit)) #define BIT_OFF(sw, bit) (!(sw & (1 << bit))) -#define VCCQ1CR 0xE6058140 -#define VCCQ1LCDCR 0xE6058186 +#define VCCQ1CR IOMEM(0xE6058140) +#define VCCQ1LCDCR IOMEM(0xE6058186) static void __init bonito_init(void) { diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c index 796fa00ad3c..b179d4c213b 100644 --- a/arch/arm/mach-shmobile/board-g3evm.c +++ b/arch/arm/mach-shmobile/board-g3evm.c @@ -106,7 +106,7 @@ static void usb_host_port_power(int port, int power) return; /* set VBOUT/PWEN and EXTLP0 in DVSTCTR */ - __raw_writew(__raw_readw(0xe6890008) | 0x600, 0xe6890008); + __raw_writew(__raw_readw(IOMEM(0xe6890008)) | 0x600, IOMEM(0xe6890008)); } static struct r8a66597_platdata usb_host_data = { @@ -279,10 +279,10 @@ static void __init g3evm_init(void) gpio_request(GPIO_FN_IDIN, NULL); /* setup USB phy */ - __raw_writew(0x0300, 0xe605810a); /* USBCR1 */ - __raw_writew(0x00e0, 0xe60581c0); /* CPFCH */ - __raw_writew(0x6010, 0xe60581c6); /* CGPOSR */ - __raw_writew(0x8a0a, 0xe605810c); /* USBCR2 */ + __raw_writew(0x0300, IOMEM(0xe605810a)); /* USBCR1 */ + __raw_writew(0x00e0, IOMEM(0xe60581c0)); /* CPFCH */ + __raw_writew(0x6010, IOMEM(0xe60581c6)); /* CGPOSR */ + __raw_writew(0x8a0a, IOMEM(0xe605810c)); /* USBCR2 */ /* KEYSC @ CN7 */ gpio_request(GPIO_FN_PORT42_KEYOUT0, NULL); @@ -320,7 +320,7 @@ static void __init g3evm_init(void) gpio_request(GPIO_FN_WE0_XWR0_FWE, NULL); gpio_request(GPIO_FN_FRB, NULL); /* FOE, FCDE, FSC on dedicated pins */ - __raw_writel(__raw_readl(0xe6158048) & ~(1 << 15), 0xe6158048); + __raw_writel(__raw_readl(IOMEM(0xe6158048)) & ~(1 << 15), IOMEM(0xe6158048)); /* IrDA */ gpio_request(GPIO_FN_IRDA_OUT, NULL); diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c index fa5dfc5c8ed..35c126caa4d 100644 --- a/arch/arm/mach-shmobile/board-g4evm.c +++ b/arch/arm/mach-shmobile/board-g4evm.c @@ -42,6 +42,8 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> +#include "sh-gpio.h" + /* * SDHI * @@ -126,7 +128,7 @@ static void usb_host_port_power(int port, int power) return; /* set VBOUT/PWEN and EXTLP0 in DVSTCTR */ - __raw_writew(__raw_readw(0xe6890008) | 0x600, 0xe6890008); + __raw_writew(__raw_readw(IOMEM(0xe6890008)) | 0x600, IOMEM(0xe6890008)); } static struct r8a66597_platdata usb_host_data = { @@ -270,17 +272,17 @@ static struct platform_device *g4evm_devices[] __initdata = { &sdhi1_device, }; -#define GPIO_SDHID0_D0 0xe60520fc -#define GPIO_SDHID0_D1 0xe60520fd -#define GPIO_SDHID0_D2 0xe60520fe -#define GPIO_SDHID0_D3 0xe60520ff -#define GPIO_SDHICMD0 0xe6052100 +#define GPIO_SDHID0_D0 IOMEM(0xe60520fc) +#define GPIO_SDHID0_D1 IOMEM(0xe60520fd) +#define GPIO_SDHID0_D2 IOMEM(0xe60520fe) +#define GPIO_SDHID0_D3 IOMEM(0xe60520ff) +#define GPIO_SDHICMD0 IOMEM(0xe6052100) -#define GPIO_SDHID1_D0 0xe6052103 -#define GPIO_SDHID1_D1 0xe6052104 -#define GPIO_SDHID1_D2 0xe6052105 -#define GPIO_SDHID1_D3 0xe6052106 -#define GPIO_SDHICMD1 0xe6052107 +#define GPIO_SDHID1_D0 IOMEM(0xe6052103) +#define GPIO_SDHID1_D1 IOMEM(0xe6052104) +#define GPIO_SDHID1_D2 IOMEM(0xe6052105) +#define GPIO_SDHID1_D3 IOMEM(0xe6052106) +#define GPIO_SDHICMD1 IOMEM(0xe6052107) static void __init g4evm_init(void) { @@ -318,10 +320,10 @@ static void __init g4evm_init(void) gpio_request(GPIO_FN_IDIN, NULL); /* setup USB phy */ - __raw_writew(0x0200, 0xe605810a); /* USBCR1 */ - __raw_writew(0x00e0, 0xe60581c0); /* CPFCH */ - __raw_writew(0x6010, 0xe60581c6); /* CGPOSR */ - __raw_writew(0x8a0a, 0xe605810c); /* USBCR2 */ + __raw_writew(0x0200, IOMEM(0xe605810a)); /* USBCR1 */ + __raw_writew(0x00e0, IOMEM(0xe60581c0)); /* CPFCH */ + __raw_writew(0x6010, IOMEM(0xe60581c6)); /* CGPOSR */ + __raw_writew(0x8a0a, IOMEM(0xe605810c)); /* USBCR2 */ /* KEYSC @ CN31 */ gpio_request(GPIO_FN_PORT60_KEYOUT5, NULL); diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c index 21dbe54304d..bf88f9a8b7a 100644 --- a/arch/arm/mach-shmobile/board-kota2.c +++ b/arch/arm/mach-shmobile/board-kota2.c @@ -545,6 +545,7 @@ static void __init kota2_init(void) } MACHINE_START(KOTA2, "kota2") + .smp = smp_ops(sh73a0_smp_ops), .map_io = sh73a0_map_io, .init_early = sh73a0_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c index 2c986eaae7b..b52bc0d1273 100644 --- a/arch/arm/mach-shmobile/board-kzm9d.c +++ b/arch/arm/mach-shmobile/board-kzm9d.c @@ -84,6 +84,7 @@ static const char *kzm9d_boards_compat_dt[] __initdata = { }; DT_MACHINE_START(KZM9D_DT, "kzm9d") + .smp = smp_ops(emev2_smp_ops), .map_io = emev2_map_io, .init_early = emev2_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index 3b8a0171c3c..0a43f3189c2 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -133,8 +133,8 @@ static struct platform_device usb_host_device = { /* USB Func CN17 */ struct usbhs_private { - unsigned int phy; - unsigned int cr2; + void __iomem *phy; + void __iomem *cr2; struct renesas_usbhs_platform_info info; }; @@ -232,8 +232,8 @@ static u32 usbhs_pipe_cfg[] = { }; static struct usbhs_private usbhs_private = { - .phy = 0xe60781e0, /* USBPHYINT */ - .cr2 = 0xe605810c, /* USBCR2 */ + .phy = IOMEM(0xe60781e0), /* USBPHYINT */ + .cr2 = IOMEM(0xe605810c), /* USBCR2 */ .info = { .platform_callback = { .hardware_init = usbhs_hardware_init, @@ -482,12 +482,10 @@ static struct gpio_keys_button gpio_buttons[] = { static struct gpio_keys_platform_data gpio_key_info = { .buttons = gpio_buttons, .nbuttons = ARRAY_SIZE(gpio_buttons), - .poll_interval = 250, /* poling at this point */ }; static struct platform_device gpio_keys_device = { - /* gpio-pcf857x.c driver doesn't support gpio_to_irq() */ - .name = "gpio-keys-polled", + .name = "gpio-keys", .dev = { .platform_data = &gpio_key_info, }, @@ -550,6 +548,7 @@ static struct platform_device fsi_ak4648_device = { /* I2C */ static struct pcf857x_platform_data pcf8575_pdata = { .gpio_base = GPIO_PCF8575_BASE, + .irq = intcs_evt2irq(0x3260), /* IRQ19 */ }; static struct i2c_board_info i2c0_devices[] = { @@ -763,12 +762,20 @@ static void __init kzm_init(void) platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices)); } +static void kzm9g_restart(char mode, const char *cmd) +{ +#define RESCNT2 IOMEM(0xe6188020) + /* Do soft power on reset */ + writel((1 << 31), RESCNT2); +} + static const char *kzm9g_boards_compat_dt[] __initdata = { "renesas,kzm9g", NULL, }; DT_MACHINE_START(KZM9G_DT, "kzm9g") + .smp = smp_ops(sh73a0_smp_ops), .map_io = sh73a0_map_io, .init_early = sh73a0_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, @@ -777,5 +784,6 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g") .init_machine = kzm_init, .init_late = shmobile_init_late, .timer = &shmobile_timer, + .restart = kzm9g_restart, .dt_compat = kzm9g_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index c129542f6ae..0c27c810cf9 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -64,6 +64,8 @@ #include <asm/mach/arch.h> #include <asm/mach-types.h> +#include "sh-gpio.h" + /* * Address Interface BusWidth note * ------------------------------------------------------------------ @@ -583,8 +585,8 @@ out: #define USBHS0_POLL_INTERVAL (HZ * 5) struct usbhs_private { - unsigned int usbphyaddr; - unsigned int usbcrcaddr; + void __iomem *usbphyaddr; + void __iomem *usbcrcaddr; struct renesas_usbhs_platform_info info; struct delayed_work work; struct platform_device *pdev; @@ -642,7 +644,7 @@ static void usbhs0_hardware_exit(struct platform_device *pdev) } static struct usbhs_private usbhs0_private = { - .usbcrcaddr = 0xe605810c, /* USBCR2 */ + .usbcrcaddr = IOMEM(0xe605810c), /* USBCR2 */ .info = { .platform_callback = { .hardware_init = usbhs0_hardware_init, @@ -776,8 +778,8 @@ static u32 usbhs1_pipe_cfg[] = { }; static struct usbhs_private usbhs1_private = { - .usbphyaddr = 0xe60581e2, /* USBPHY1INTAP */ - .usbcrcaddr = 0xe6058130, /* USBCR4 */ + .usbphyaddr = IOMEM(0xe60581e2), /* USBPHY1INTAP */ + .usbcrcaddr = IOMEM(0xe6058130), /* USBCR4 */ .info = { .platform_callback = { .hardware_init = usbhs1_hardware_init, @@ -1402,14 +1404,30 @@ static struct i2c_board_info i2c1_devices[] = { }, }; -#define GPIO_PORT9CR 0xE6051009 -#define GPIO_PORT10CR 0xE605100A -#define GPIO_PORT167CR 0xE60520A7 -#define GPIO_PORT168CR 0xE60520A8 -#define SRCR4 0xe61580bc -#define USCCR1 0xE6058144 +#define GPIO_PORT9CR IOMEM(0xE6051009) +#define GPIO_PORT10CR IOMEM(0xE605100A) +#define GPIO_PORT167CR IOMEM(0xE60520A7) +#define GPIO_PORT168CR IOMEM(0xE60520A8) +#define SRCR4 IOMEM(0xe61580bc) +#define USCCR1 IOMEM(0xE6058144) static void __init mackerel_init(void) { + struct pm_domain_device domain_devices[] = { + { "A4LC", &lcdc_device, }, + { "A4LC", &hdmi_lcdc_device, }, + { "A4LC", &meram_device, }, + { "A4MP", &fsi_device, }, + { "A3SP", &usbhs0_device, }, + { "A3SP", &usbhs1_device, }, + { "A3SP", &nand_flash_device, }, + { "A3SP", &sh_mmcif_device, }, + { "A3SP", &sdhi0_device, }, +#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) + { "A3SP", &sdhi1_device, }, +#endif + { "A3SP", &sdhi2_device, }, + { "A4R", &ceu_device, }, + }; u32 srcr4; struct clk *clk; @@ -1624,20 +1642,8 @@ static void __init mackerel_init(void) platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices)); - rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device); - rmobile_add_device_to_domain(&sh7372_pd_a4lc, &hdmi_lcdc_device); - rmobile_add_device_to_domain(&sh7372_pd_a4lc, &meram_device); - rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs0_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs1_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &nand_flash_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device); -#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device); -#endif - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi2_device); - rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device); + rmobile_add_devices_to_domains(domain_devices, + ARRAY_SIZE(domain_devices)); hdmi_init_pm_clock(); sh7372_pm_init(); @@ -1651,6 +1657,6 @@ MACHINE_START(MACKEREL, "mackerel") .init_irq = sh7372_init_irq, .handle_irq = shmobile_handle_irq_intc, .init_machine = mackerel_init, - .init_late = shmobile_init_late, + .init_late = sh7372_pm_init_late, .timer = &shmobile_timer, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c index fcf5a47f477..b8a7525a4e2 100644 --- a/arch/arm/mach-shmobile/board-marzen.c +++ b/arch/arm/mach-shmobile/board-marzen.c @@ -30,6 +30,8 @@ #include <linux/regulator/fixed.h> #include <linux/regulator/machine.h> #include <linux/smsc911x.h> +#include <linux/mmc/sh_mobile_sdhi.h> +#include <linux/mfd/tmio.h> #include <mach/hardware.h> #include <mach/r8a7779.h> #include <mach/common.h> @@ -39,6 +41,12 @@ #include <asm/hardware/gic.h> #include <asm/traps.h> +/* Fixed 3.3V regulator to be used by SDHI0 */ +static struct regulator_consumer_supply fixed3v3_power_consumers[] = { + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), +}; + /* Dummy supplies, where voltage doesn't matter */ static struct regulator_consumer_supply dummy_supplies[] = { REGULATOR_SUPPLY("vddvario", "smsc911x"), @@ -75,13 +83,61 @@ static struct platform_device eth_device = { .num_resources = ARRAY_SIZE(smsc911x_resources), }; +static struct resource sdhi0_resources[] = { + [0] = { + .name = "sdhi0", + .start = 0xffe4c000, + .end = 0xffe4c0ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = gic_spi(104), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct sh_mobile_sdhi_info sdhi0_platform_data = { + .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT, + .tmio_caps = MMC_CAP_SD_HIGHSPEED, +}; + +static struct platform_device sdhi0_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(sdhi0_resources), + .resource = sdhi0_resources, + .id = 0, + .dev = { + .platform_data = &sdhi0_platform_data, + } +}; + +/* Thermal */ +static struct resource thermal_resources[] = { + [0] = { + .start = 0xFFC48000, + .end = 0xFFC48038 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device thermal_device = { + .name = "rcar_thermal", + .resource = thermal_resources, + .num_resources = ARRAY_SIZE(thermal_resources), +}; + static struct platform_device *marzen_devices[] __initdata = { ð_device, + &sdhi0_device, + &thermal_device, }; static void __init marzen_init(void) { - regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers, + ARRAY_SIZE(fixed3v3_power_consumers), 3300000); + regulator_register_fixed(1, dummy_supplies, + ARRAY_SIZE(dummy_supplies)); r8a7779_pinmux_init(); @@ -97,11 +153,22 @@ static void __init marzen_init(void) gpio_request(GPIO_FN_EX_CS0, NULL); /* nCS */ gpio_request(GPIO_FN_IRQ1_B, NULL); /* IRQ + PME */ + /* SD0 (CN20) */ + gpio_request(GPIO_FN_SD0_CLK, NULL); + gpio_request(GPIO_FN_SD0_CMD, NULL); + gpio_request(GPIO_FN_SD0_DAT0, NULL); + gpio_request(GPIO_FN_SD0_DAT1, NULL); + gpio_request(GPIO_FN_SD0_DAT2, NULL); + gpio_request(GPIO_FN_SD0_DAT3, NULL); + gpio_request(GPIO_FN_SD0_CD, NULL); + gpio_request(GPIO_FN_SD0_WP, NULL); + r8a7779_add_standard_devices(); platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices)); } MACHINE_START(MARZEN, "marzen") + .smp = smp_ops(r8a7779_smp_ops), .map_io = r8a7779_map_io, .init_early = r8a7779_add_early_devices, .nr_irqs = NR_IRQS_LEGACY, diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index ad5fccc7b5e..6729e003218 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c @@ -41,29 +41,29 @@ */ /* CPG registers */ -#define FRQCRA 0xe6150000 -#define FRQCRB 0xe6150004 -#define VCLKCR1 0xE6150008 -#define VCLKCR2 0xE615000c -#define FRQCRC 0xe61500e0 -#define FSIACKCR 0xe6150018 -#define PLLC01CR 0xe6150028 - -#define SUBCKCR 0xe6150080 -#define USBCKCR 0xe615008c - -#define MSTPSR0 0xe6150030 -#define MSTPSR1 0xe6150038 -#define MSTPSR2 0xe6150040 -#define MSTPSR3 0xe6150048 -#define MSTPSR4 0xe615004c -#define FSIBCKCR 0xe6150090 -#define HDMICKCR 0xe6150094 -#define SMSTPCR0 0xe6150130 -#define SMSTPCR1 0xe6150134 -#define SMSTPCR2 0xe6150138 -#define SMSTPCR3 0xe615013c -#define SMSTPCR4 0xe6150140 +#define FRQCRA IOMEM(0xe6150000) +#define FRQCRB IOMEM(0xe6150004) +#define VCLKCR1 IOMEM(0xE6150008) +#define VCLKCR2 IOMEM(0xE615000c) +#define FRQCRC IOMEM(0xe61500e0) +#define FSIACKCR IOMEM(0xe6150018) +#define PLLC01CR IOMEM(0xe6150028) + +#define SUBCKCR IOMEM(0xe6150080) +#define USBCKCR IOMEM(0xe615008c) + +#define MSTPSR0 IOMEM(0xe6150030) +#define MSTPSR1 IOMEM(0xe6150038) +#define MSTPSR2 IOMEM(0xe6150040) +#define MSTPSR3 IOMEM(0xe6150048) +#define MSTPSR4 IOMEM(0xe615004c) +#define FSIBCKCR IOMEM(0xe6150090) +#define HDMICKCR IOMEM(0xe6150094) +#define SMSTPCR0 IOMEM(0xe6150130) +#define SMSTPCR1 IOMEM(0xe6150134) +#define SMSTPCR2 IOMEM(0xe6150138) +#define SMSTPCR3 IOMEM(0xe615013c) +#define SMSTPCR4 IOMEM(0xe6150140) /* Fixed 32 KHz root clock from EXTALR pin */ static struct clk extalr_clk = { diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c index 339c62c824d..3cafb6ab5e9 100644 --- a/arch/arm/mach-shmobile/clock-r8a7779.c +++ b/arch/arm/mach-shmobile/clock-r8a7779.c @@ -86,11 +86,16 @@ static struct clk div4_clks[DIV4_NR] = { 0x0300, CLK_ENABLE_ON_INIT), }; -enum { MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, +enum { MSTP323, MSTP322, MSTP321, MSTP320, + MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, MSTP016, MSTP015, MSTP014, MSTP_NR }; static struct clk mstp_clks[MSTP_NR] = { + [MSTP323] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 23, 0), /* SDHI0 */ + [MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0), /* SDHI1 */ + [MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0), /* SDHI2 */ + [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0), /* SDHI3 */ [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), /* SCIF0 */ [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), /* SCIF1 */ [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), /* SCIF2 */ @@ -149,6 +154,10 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */ CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */ + CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */ + CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */ + CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */ + CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */ }; void __init r8a7779_clock_init(void) diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c index 162b791b898..ef0a95e592c 100644 --- a/arch/arm/mach-shmobile/clock-sh7367.c +++ b/arch/arm/mach-shmobile/clock-sh7367.c @@ -24,28 +24,28 @@ #include <mach/common.h> /* SH7367 registers */ -#define RTFRQCR 0xe6150000 -#define SYFRQCR 0xe6150004 -#define CMFRQCR 0xe61500E0 -#define VCLKCR1 0xe6150008 -#define VCLKCR2 0xe615000C -#define VCLKCR3 0xe615001C -#define SCLKACR 0xe6150010 -#define SCLKBCR 0xe6150014 -#define SUBUSBCKCR 0xe6158080 -#define SPUCKCR 0xe6150084 -#define MSUCKCR 0xe6150088 -#define MVI3CKCR 0xe6150090 -#define VOUCKCR 0xe6150094 -#define MFCK1CR 0xe6150098 -#define MFCK2CR 0xe615009C -#define PLLC1CR 0xe6150028 -#define PLLC2CR 0xe615002C -#define RTMSTPCR0 0xe6158030 -#define RTMSTPCR2 0xe6158038 -#define SYMSTPCR0 0xe6158040 -#define SYMSTPCR2 0xe6158048 -#define CMMSTPCR0 0xe615804c +#define RTFRQCR IOMEM(0xe6150000) +#define SYFRQCR IOMEM(0xe6150004) +#define CMFRQCR IOMEM(0xe61500E0) +#define VCLKCR1 IOMEM(0xe6150008) +#define VCLKCR2 IOMEM(0xe615000C) +#define VCLKCR3 IOMEM(0xe615001C) +#define SCLKACR IOMEM(0xe6150010) +#define SCLKBCR IOMEM(0xe6150014) +#define SUBUSBCKCR IOMEM(0xe6158080) +#define SPUCKCR IOMEM(0xe6150084) +#define MSUCKCR IOMEM(0xe6150088) +#define MVI3CKCR IOMEM(0xe6150090) +#define VOUCKCR IOMEM(0xe6150094) +#define MFCK1CR IOMEM(0xe6150098) +#define MFCK2CR IOMEM(0xe615009C) +#define PLLC1CR IOMEM(0xe6150028) +#define PLLC2CR IOMEM(0xe615002C) +#define RTMSTPCR0 IOMEM(0xe6158030) +#define RTMSTPCR2 IOMEM(0xe6158038) +#define SYMSTPCR0 IOMEM(0xe6158040) +#define SYMSTPCR2 IOMEM(0xe6158048) +#define CMMSTPCR0 IOMEM(0xe615804c) /* Fixed 32 KHz root clock from EXTALR pin */ static struct clk r_clk = { diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 5a2894b1c96..430a90ffa12 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -24,36 +24,36 @@ #include <mach/common.h> /* SH7372 registers */ -#define FRQCRA 0xe6150000 -#define FRQCRB 0xe6150004 -#define FRQCRC 0xe61500e0 -#define FRQCRD 0xe61500e4 -#define VCLKCR1 0xe6150008 -#define VCLKCR2 0xe615000c -#define VCLKCR3 0xe615001c -#define FMSICKCR 0xe6150010 -#define FMSOCKCR 0xe6150014 -#define FSIACKCR 0xe6150018 -#define FSIBCKCR 0xe6150090 -#define SUBCKCR 0xe6150080 -#define SPUCKCR 0xe6150084 -#define VOUCKCR 0xe6150088 -#define HDMICKCR 0xe6150094 -#define DSITCKCR 0xe6150060 -#define DSI0PCKCR 0xe6150064 -#define DSI1PCKCR 0xe6150098 -#define PLLC01CR 0xe6150028 -#define PLLC2CR 0xe615002c -#define RMSTPCR0 0xe6150110 -#define RMSTPCR1 0xe6150114 -#define RMSTPCR2 0xe6150118 -#define RMSTPCR3 0xe615011c -#define RMSTPCR4 0xe6150120 -#define SMSTPCR0 0xe6150130 -#define SMSTPCR1 0xe6150134 -#define SMSTPCR2 0xe6150138 -#define SMSTPCR3 0xe615013c -#define SMSTPCR4 0xe6150140 +#define FRQCRA IOMEM(0xe6150000) +#define FRQCRB IOMEM(0xe6150004) +#define FRQCRC IOMEM(0xe61500e0) +#define FRQCRD IOMEM(0xe61500e4) +#define VCLKCR1 IOMEM(0xe6150008) +#define VCLKCR2 IOMEM(0xe615000c) +#define VCLKCR3 IOMEM(0xe615001c) +#define FMSICKCR IOMEM(0xe6150010) +#define FMSOCKCR IOMEM(0xe6150014) +#define FSIACKCR IOMEM(0xe6150018) +#define FSIBCKCR IOMEM(0xe6150090) +#define SUBCKCR IOMEM(0xe6150080) +#define SPUCKCR IOMEM(0xe6150084) +#define VOUCKCR IOMEM(0xe6150088) +#define HDMICKCR IOMEM(0xe6150094) +#define DSITCKCR IOMEM(0xe6150060) +#define DSI0PCKCR IOMEM(0xe6150064) +#define DSI1PCKCR IOMEM(0xe6150098) +#define PLLC01CR IOMEM(0xe6150028) +#define PLLC2CR IOMEM(0xe615002c) +#define RMSTPCR0 IOMEM(0xe6150110) +#define RMSTPCR1 IOMEM(0xe6150114) +#define RMSTPCR2 IOMEM(0xe6150118) +#define RMSTPCR3 IOMEM(0xe615011c) +#define RMSTPCR4 IOMEM(0xe6150120) +#define SMSTPCR0 IOMEM(0xe6150130) +#define SMSTPCR1 IOMEM(0xe6150134) +#define SMSTPCR2 IOMEM(0xe6150138) +#define SMSTPCR3 IOMEM(0xe615013c) +#define SMSTPCR4 IOMEM(0xe6150140) #define FSIDIVA 0xFE1F8000 #define FSIDIVB 0xFE1F8008 diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c index 85f2a3ec2c4..b8480d19e1c 100644 --- a/arch/arm/mach-shmobile/clock-sh7377.c +++ b/arch/arm/mach-shmobile/clock-sh7377.c @@ -24,31 +24,31 @@ #include <mach/common.h> /* SH7377 registers */ -#define RTFRQCR 0xe6150000 -#define SYFRQCR 0xe6150004 -#define CMFRQCR 0xe61500E0 -#define VCLKCR1 0xe6150008 -#define VCLKCR2 0xe615000C -#define VCLKCR3 0xe615001C -#define FMSICKCR 0xe6150010 -#define FMSOCKCR 0xe6150014 -#define FSICKCR 0xe6150018 -#define PLLC1CR 0xe6150028 -#define PLLC2CR 0xe615002C -#define SUBUSBCKCR 0xe6150080 -#define SPUCKCR 0xe6150084 -#define MSUCKCR 0xe6150088 -#define MVI3CKCR 0xe6150090 -#define HDMICKCR 0xe6150094 -#define MFCK1CR 0xe6150098 -#define MFCK2CR 0xe615009C -#define DSITCKCR 0xe6150060 -#define DSIPCKCR 0xe6150064 -#define SMSTPCR0 0xe6150130 -#define SMSTPCR1 0xe6150134 -#define SMSTPCR2 0xe6150138 -#define SMSTPCR3 0xe615013C -#define SMSTPCR4 0xe6150140 +#define RTFRQCR IOMEM(0xe6150000) +#define SYFRQCR IOMEM(0xe6150004) +#define CMFRQCR IOMEM(0xe61500E0) +#define VCLKCR1 IOMEM(0xe6150008) +#define VCLKCR2 IOMEM(0xe615000C) +#define VCLKCR3 IOMEM(0xe615001C) +#define FMSICKCR IOMEM(0xe6150010) +#define FMSOCKCR IOMEM(0xe6150014) +#define FSICKCR IOMEM(0xe6150018) +#define PLLC1CR IOMEM(0xe6150028) +#define PLLC2CR IOMEM(0xe615002C) +#define SUBUSBCKCR IOMEM(0xe6150080) +#define SPUCKCR IOMEM(0xe6150084) +#define MSUCKCR IOMEM(0xe6150088) +#define MVI3CKCR IOMEM(0xe6150090) +#define HDMICKCR IOMEM(0xe6150094) +#define MFCK1CR IOMEM(0xe6150098) +#define MFCK2CR IOMEM(0xe615009C) +#define DSITCKCR IOMEM(0xe6150060) +#define DSIPCKCR IOMEM(0xe6150064) +#define SMSTPCR0 IOMEM(0xe6150130) +#define SMSTPCR1 IOMEM(0xe6150134) +#define SMSTPCR2 IOMEM(0xe6150138) +#define SMSTPCR3 IOMEM(0xe615013C) +#define SMSTPCR4 IOMEM(0xe6150140) /* Fixed 32 KHz root clock from EXTALR pin */ static struct clk r_clk = { diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 7f8da18a858..516ff7f3e43 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -23,43 +23,43 @@ #include <linux/clkdev.h> #include <mach/common.h> -#define FRQCRA 0xe6150000 -#define FRQCRB 0xe6150004 -#define FRQCRD 0xe61500e4 -#define VCLKCR1 0xe6150008 -#define VCLKCR2 0xe615000C -#define VCLKCR3 0xe615001C -#define ZBCKCR 0xe6150010 -#define FLCKCR 0xe6150014 -#define SD0CKCR 0xe6150074 -#define SD1CKCR 0xe6150078 -#define SD2CKCR 0xe615007C -#define FSIACKCR 0xe6150018 -#define FSIBCKCR 0xe6150090 -#define SUBCKCR 0xe6150080 -#define SPUACKCR 0xe6150084 -#define SPUVCKCR 0xe6150094 -#define MSUCKCR 0xe6150088 -#define HSICKCR 0xe615008C -#define MFCK1CR 0xe6150098 -#define MFCK2CR 0xe615009C -#define DSITCKCR 0xe6150060 -#define DSI0PCKCR 0xe6150064 -#define DSI1PCKCR 0xe6150068 +#define FRQCRA IOMEM(0xe6150000) +#define FRQCRB IOMEM(0xe6150004) +#define FRQCRD IOMEM(0xe61500e4) +#define VCLKCR1 IOMEM(0xe6150008) +#define VCLKCR2 IOMEM(0xe615000C) +#define VCLKCR3 IOMEM(0xe615001C) +#define ZBCKCR IOMEM(0xe6150010) +#define FLCKCR IOMEM(0xe6150014) +#define SD0CKCR IOMEM(0xe6150074) +#define SD1CKCR IOMEM(0xe6150078) +#define SD2CKCR IOMEM(0xe615007C) +#define FSIACKCR IOMEM(0xe6150018) +#define FSIBCKCR IOMEM(0xe6150090) +#define SUBCKCR IOMEM(0xe6150080) +#define SPUACKCR IOMEM(0xe6150084) +#define SPUVCKCR IOMEM(0xe6150094) +#define MSUCKCR IOMEM(0xe6150088) +#define HSICKCR IOMEM(0xe615008C) +#define MFCK1CR IOMEM(0xe6150098) +#define MFCK2CR IOMEM(0xe615009C) +#define DSITCKCR IOMEM(0xe6150060) +#define DSI0PCKCR IOMEM(0xe6150064) +#define DSI1PCKCR IOMEM(0xe6150068) #define DSI0PHYCR 0xe615006C #define DSI1PHYCR 0xe6150070 -#define PLLECR 0xe61500d0 -#define PLL0CR 0xe61500d8 -#define PLL1CR 0xe6150028 -#define PLL2CR 0xe615002c -#define PLL3CR 0xe61500dc -#define SMSTPCR0 0xe6150130 -#define SMSTPCR1 0xe6150134 -#define SMSTPCR2 0xe6150138 -#define SMSTPCR3 0xe615013c -#define SMSTPCR4 0xe6150140 -#define SMSTPCR5 0xe6150144 -#define CKSCR 0xe61500c0 +#define PLLECR IOMEM(0xe61500d0) +#define PLL0CR IOMEM(0xe61500d8) +#define PLL1CR IOMEM(0xe6150028) +#define PLL2CR IOMEM(0xe615002c) +#define PLL3CR IOMEM(0xe61500dc) +#define SMSTPCR0 IOMEM(0xe6150130) +#define SMSTPCR1 IOMEM(0xe6150134) +#define SMSTPCR2 IOMEM(0xe6150138) +#define SMSTPCR3 IOMEM(0xe615013c) +#define SMSTPCR4 IOMEM(0xe6150140) +#define SMSTPCR5 IOMEM(0xe6150144) +#define CKSCR IOMEM(0xe61500c0) /* Fixed 32 KHz root clock from EXTALR pin */ static struct clk r_clk = { diff --git a/arch/arm/mach-shmobile/common.c b/arch/arm/mach-shmobile/common.c deleted file mode 100644 index 608aba9d60d..00000000000 --- a/arch/arm/mach-shmobile/common.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <mach/common.h> - -void __init shmobile_init_late(void) -{ - shmobile_suspend_init(); - shmobile_cpuidle_init(); -} diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c index 7b541e911ab..9e050268cde 100644 --- a/arch/arm/mach-shmobile/cpuidle.c +++ b/arch/arm/mach-shmobile/cpuidle.c @@ -16,51 +16,38 @@ #include <asm/cpuidle.h> #include <asm/io.h> -static void shmobile_enter_wfi(void) +int shmobile_enter_wfi(struct cpuidle_device *dev, struct cpuidle_driver *drv, + int index) { cpu_do_idle(); -} - -void (*shmobile_cpuidle_modes[CPUIDLE_STATE_MAX])(void) = { - shmobile_enter_wfi, /* regular sleep mode */ -}; - -static int shmobile_cpuidle_enter(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) -{ - shmobile_cpuidle_modes[index](); - - return index; + return 0; } static struct cpuidle_device shmobile_cpuidle_dev; -static struct cpuidle_driver shmobile_cpuidle_driver = { +static struct cpuidle_driver shmobile_cpuidle_default_driver = { .name = "shmobile_cpuidle", .owner = THIS_MODULE, .en_core_tk_irqen = 1, .states[0] = ARM_CPUIDLE_WFI_STATE, + .states[0].enter = shmobile_enter_wfi, .safe_state_index = 0, /* C1 */ .state_count = 1, }; -void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); +static struct cpuidle_driver *cpuidle_drv = &shmobile_cpuidle_default_driver; + +void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv) +{ + cpuidle_drv = drv; +} int shmobile_cpuidle_init(void) { struct cpuidle_device *dev = &shmobile_cpuidle_dev; - struct cpuidle_driver *drv = &shmobile_cpuidle_driver; - int i; - - for (i = 0; i < CPUIDLE_STATE_MAX; i++) - drv->states[i].enter = shmobile_cpuidle_enter; - - if (shmobile_cpuidle_setup) - shmobile_cpuidle_setup(drv); - cpuidle_register_driver(drv); + cpuidle_register_driver(cpuidle_drv); - dev->state_count = drv->state_count; + dev->state_count = cpuidle_drv->state_count; cpuidle_register_device(dev); return 0; diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c index 828d22f3af5..b09a0bdbf81 100644 --- a/arch/arm/mach-shmobile/hotplug.c +++ b/arch/arm/mach-shmobile/hotplug.c @@ -14,30 +14,16 @@ #include <linux/smp.h> #include <linux/cpumask.h> #include <linux/delay.h> +#include <linux/of.h> #include <mach/common.h> +#include <mach/r8a7779.h> +#include <mach/emev2.h> #include <asm/cacheflush.h> +#include <asm/mach-types.h> static cpumask_t dead_cpus; -int platform_cpu_kill(unsigned int cpu) -{ - int k; - - /* this function is running on another CPU than the offline target, - * here we need wait for shutdown code in platform_cpu_die() to - * finish before asking SoC-specific code to power off the CPU core. - */ - for (k = 0; k < 1000; k++) { - if (cpumask_test_cpu(cpu, &dead_cpus)) - return shmobile_platform_cpu_kill(cpu); - - mdelay(1); - } - - return 0; -} - -void platform_cpu_die(unsigned int cpu) +void shmobile_cpu_die(unsigned int cpu) { /* hardware shutdown code running on the CPU that is being offlined */ flush_cache_all(); @@ -60,7 +46,7 @@ void platform_cpu_die(unsigned int cpu) } } -int platform_cpu_disable(unsigned int cpu) +int shmobile_cpu_disable(unsigned int cpu) { cpumask_clear_cpu(cpu, &dead_cpus); /* @@ -69,3 +55,8 @@ int platform_cpu_disable(unsigned int cpu) */ return cpu == 0 ? -EPERM : 0; } + +int shmobile_cpu_is_dead(unsigned int cpu) +{ + return cpumask_test_cpu(cpu, &dead_cpus); +} diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 45e61dada03..ed77ab8c914 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -4,18 +4,19 @@ extern void shmobile_earlytimer_init(void); extern struct sys_timer shmobile_timer; extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz, - unsigned int mult, unsigned int div); + unsigned int mult, unsigned int div); struct twd_local_timer; extern void shmobile_setup_console(void); extern void shmobile_secondary_vector(void); -extern int shmobile_platform_cpu_kill(unsigned int cpu); struct clk; extern int shmobile_clk_init(void); extern void shmobile_handle_irq_intc(struct pt_regs *); extern struct platform_suspend_ops shmobile_suspend_ops; struct cpuidle_driver; -extern void (*shmobile_cpuidle_modes[])(void); -extern void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); +struct cpuidle_device; +extern int shmobile_enter_wfi(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index); +extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv); extern void sh7367_init_irq(void); extern void sh7367_map_io(void); @@ -58,11 +59,6 @@ extern struct clk sh73a0_extal2_clk; extern struct clk sh73a0_extcki_clk; extern struct clk sh73a0_extalr_clk; -extern unsigned int sh73a0_get_core_count(void); -extern void sh73a0_secondary_init(unsigned int cpu); -extern int sh73a0_boot_secondary(unsigned int cpu); -extern void sh73a0_smp_prepare_cpus(void); - extern void r8a7740_init_irq(void); extern void r8a7740_map_io(void); extern void r8a7740_add_early_devices(void); @@ -79,15 +75,8 @@ extern void r8a7779_pinmux_init(void); extern void r8a7779_pm_init(void); extern void r8a7740_meram_workaround(void); -extern unsigned int r8a7779_get_core_count(void); -extern int r8a7779_platform_cpu_kill(unsigned int cpu); -extern void r8a7779_secondary_init(unsigned int cpu); -extern int r8a7779_boot_secondary(unsigned int cpu); -extern void r8a7779_smp_prepare_cpus(void); extern void r8a7779_register_twd(void); -extern void shmobile_init_late(void); - #ifdef CONFIG_SUSPEND int shmobile_suspend_init(void); #else @@ -100,4 +89,21 @@ int shmobile_cpuidle_init(void); static inline int shmobile_cpuidle_init(void) { return 0; } #endif +extern void shmobile_cpu_die(unsigned int cpu); +extern int shmobile_cpu_disable(unsigned int cpu); + +#ifdef CONFIG_HOTPLUG_CPU +extern int shmobile_cpu_is_dead(unsigned int cpu); +#else +static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; } +#endif + +extern void shmobile_smp_init_cpus(unsigned int ncores); + +static inline void shmobile_init_late(void) +{ + shmobile_suspend_init(); + shmobile_cpuidle_init(); +} + #endif /* __ARCH_MACH_COMMON_H */ diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h index e6b0c1bf4b7..ac3751705ca 100644 --- a/arch/arm/mach-shmobile/include/mach/emev2.h +++ b/arch/arm/mach-shmobile/include/mach/emev2.h @@ -7,13 +7,10 @@ extern void emev2_add_early_devices(void); extern void emev2_add_standard_devices(void); extern void emev2_clock_init(void); extern void emev2_set_boot_vector(unsigned long value); -extern unsigned int emev2_get_core_count(void); -extern int emev2_platform_cpu_kill(unsigned int cpu); -extern void emev2_secondary_init(unsigned int cpu); -extern int emev2_boot_secondary(unsigned int cpu); -extern void emev2_smp_prepare_cpus(void); #define EMEV2_GPIO_BASE 200 #define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n)) +extern struct smp_operations emev2_smp_ops; + #endif /* __ASM_EMEV2_H__ */ diff --git a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h index 5a402840fe2..690553a0688 100644 --- a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h +++ b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h @@ -12,6 +12,8 @@ #include <linux/pm_domain.h> +#define DEFAULT_DEV_LATENCY_NS 250000 + struct platform_device; struct rmobile_pm_domain { @@ -29,16 +31,33 @@ struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) return container_of(d, struct rmobile_pm_domain, genpd); } +struct pm_domain_device { + const char *domain_name; + struct platform_device *pdev; +}; + #ifdef CONFIG_PM -extern void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd); -extern void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd, - struct platform_device *pdev); -extern void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd, - struct rmobile_pm_domain *rmobile_sd); +extern void rmobile_init_domains(struct rmobile_pm_domain domains[], int num); +extern void rmobile_add_device_to_domain_td(const char *domain_name, + struct platform_device *pdev, + struct gpd_timing_data *td); + +static inline void rmobile_add_device_to_domain(const char *domain_name, + struct platform_device *pdev) +{ + rmobile_add_device_to_domain_td(domain_name, pdev, NULL); +} + +extern void rmobile_add_devices_to_domains(struct pm_domain_device data[], + int size); #else -#define rmobile_init_pm_domain(pd) do { } while (0) -#define rmobile_add_device_to_domain(pd, pdev) do { } while (0) -#define rmobile_pm_add_subdomain(pd, sd) do { } while (0) + +#define rmobile_init_domains(domains, num) do { } while (0) +#define rmobile_add_device_to_domain_td(name, pdev, td) do { } while (0) +#define rmobile_add_device_to_domain(name, pdev) do { } while (0) + +static inline void rmobile_add_devices_to_domains(struct pm_domain_device d[], + int size) {} #endif /* CONFIG_PM */ #endif /* PM_RMOBILE_H */ diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h index 7143147780d..59d252f4cf9 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7740.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h @@ -607,9 +607,9 @@ enum { }; #ifdef CONFIG_PM -extern struct rmobile_pm_domain r8a7740_pd_a4s; -extern struct rmobile_pm_domain r8a7740_pd_a3sp; -extern struct rmobile_pm_domain r8a7740_pd_a4lc; +extern void __init r8a7740_init_pm_domains(void); +#else +static inline void r8a7740_init_pm_domains(void) {} #endif /* CONFIG_PM */ #endif /* __ASM_R8A7740_H__ */ diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h index b07ad318eb2..499f52d2a4a 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7779.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h @@ -347,17 +347,11 @@ extern int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch); extern int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch); #ifdef CONFIG_PM -extern struct r8a7779_pm_domain r8a7779_sh4a; -extern struct r8a7779_pm_domain r8a7779_sgx; -extern struct r8a7779_pm_domain r8a7779_vdp1; -extern struct r8a7779_pm_domain r8a7779_impx3; - -extern void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd); -extern void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd, - struct platform_device *pdev); +extern void __init r8a7779_init_pm_domains(void); #else -#define r8a7779_init_pm_domain(pd) do { } while (0) -#define r8a7779_add_device_to_domain(pd, pdev) do { } while (0) +static inline void r8a7779_init_pm_domains(void) {} #endif /* CONFIG_PM */ +extern struct smp_operations r8a7779_smp_ops; + #endif /* __ASM_R8A7779_H__ */ diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index b59048e6d8f..eb98b45c508 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h @@ -478,21 +478,17 @@ extern struct clk sh7372_fsibck_clk; extern struct clk sh7372_fsidiva_clk; extern struct clk sh7372_fsidivb_clk; -#ifdef CONFIG_PM -extern struct rmobile_pm_domain sh7372_pd_a4lc; -extern struct rmobile_pm_domain sh7372_pd_a4mp; -extern struct rmobile_pm_domain sh7372_pd_d4; -extern struct rmobile_pm_domain sh7372_pd_a4r; -extern struct rmobile_pm_domain sh7372_pd_a3rv; -extern struct rmobile_pm_domain sh7372_pd_a3ri; -extern struct rmobile_pm_domain sh7372_pd_a4s; -extern struct rmobile_pm_domain sh7372_pd_a3sp; -extern struct rmobile_pm_domain sh7372_pd_a3sg; -#endif /* CONFIG_PM */ - extern void sh7372_intcs_suspend(void); extern void sh7372_intcs_resume(void); extern void sh7372_intca_suspend(void); extern void sh7372_intca_resume(void); +#ifdef CONFIG_PM +extern void __init sh7372_init_pm_domains(void); +#else +static inline void sh7372_init_pm_domains(void) {} +#endif + +extern void __init sh7372_pm_init_late(void); + #endif /* __ASM_SH7372_H__ */ diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h index fe950f25d79..606d31d02a4 100644 --- a/arch/arm/mach-shmobile/include/mach/sh73a0.h +++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h @@ -557,4 +557,6 @@ enum { #define SH73A0_PINT0_IRQ(irq) ((irq) + 700) #define SH73A0_PINT1_IRQ(irq) ((irq) + 732) +extern struct smp_operations sh73a0_smp_ops; + #endif /* __ASM_SH73A0_H__ */ diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c index f04fad4ec4f..ef66f1a8aa2 100644 --- a/arch/arm/mach-shmobile/intc-r8a7779.c +++ b/arch/arm/mach-shmobile/intc-r8a7779.c @@ -29,14 +29,14 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> -#define INT2SMSKCR0 0xfe7822a0 -#define INT2SMSKCR1 0xfe7822a4 -#define INT2SMSKCR2 0xfe7822a8 -#define INT2SMSKCR3 0xfe7822ac -#define INT2SMSKCR4 0xfe7822b0 +#define INT2SMSKCR0 IOMEM(0xfe7822a0) +#define INT2SMSKCR1 IOMEM(0xfe7822a4) +#define INT2SMSKCR2 IOMEM(0xfe7822a8) +#define INT2SMSKCR3 IOMEM(0xfe7822ac) +#define INT2SMSKCR4 IOMEM(0xfe7822b0) -#define INT2NTSR0 0xfe700060 -#define INT2NTSR1 0xfe700064 +#define INT2NTSR0 IOMEM(0xfe700060) +#define INT2NTSR1 IOMEM(0xfe700064) static int r8a7779_set_wake(struct irq_data *data, unsigned int on) { diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c index 2587a22842f..a91caad7db7 100644 --- a/arch/arm/mach-shmobile/intc-sh7372.c +++ b/arch/arm/mach-shmobile/intc-sh7372.c @@ -624,6 +624,9 @@ void sh7372_intcs_resume(void) __raw_writeb(ffd5[k], intcs_ffd5 + k); } +#define E694_BASE IOMEM(0xe6940000) +#define E695_BASE IOMEM(0xe6950000) + static unsigned short e694[0x200]; static unsigned short e695[0x200]; @@ -632,22 +635,22 @@ void sh7372_intca_suspend(void) int k; for (k = 0x00; k <= 0x38; k += 4) - e694[k] = __raw_readw(0xe6940000 + k); + e694[k] = __raw_readw(E694_BASE + k); for (k = 0x80; k <= 0xb4; k += 4) - e694[k] = __raw_readb(0xe6940000 + k); + e694[k] = __raw_readb(E694_BASE + k); for (k = 0x180; k <= 0x1b4; k += 4) - e694[k] = __raw_readb(0xe6940000 + k); + e694[k] = __raw_readb(E694_BASE + k); for (k = 0x00; k <= 0x50; k += 4) - e695[k] = __raw_readw(0xe6950000 + k); + e695[k] = __raw_readw(E695_BASE + k); for (k = 0x80; k <= 0xa8; k += 4) - e695[k] = __raw_readb(0xe6950000 + k); + e695[k] = __raw_readb(E695_BASE + k); for (k = 0x180; k <= 0x1a8; k += 4) - e695[k] = __raw_readb(0xe6950000 + k); + e695[k] = __raw_readb(E695_BASE + k); } void sh7372_intca_resume(void) @@ -655,20 +658,20 @@ void sh7372_intca_resume(void) int k; for (k = 0x00; k <= 0x38; k += 4) - __raw_writew(e694[k], 0xe6940000 + k); + __raw_writew(e694[k], E694_BASE + k); for (k = 0x80; k <= 0xb4; k += 4) - __raw_writeb(e694[k], 0xe6940000 + k); + __raw_writeb(e694[k], E694_BASE + k); for (k = 0x180; k <= 0x1b4; k += 4) - __raw_writeb(e694[k], 0xe6940000 + k); + __raw_writeb(e694[k], E694_BASE + k); for (k = 0x00; k <= 0x50; k += 4) - __raw_writew(e695[k], 0xe6950000 + k); + __raw_writew(e695[k], E695_BASE + k); for (k = 0x80; k <= 0xa8; k += 4) - __raw_writeb(e695[k], 0xe6950000 + k); + __raw_writeb(e695[k], E695_BASE + k); for (k = 0x180; k <= 0x1a8; k += 4) - __raw_writeb(e695[k], 0xe6950000 + k); + __raw_writeb(e695[k], E695_BASE + k); } diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index 588555a67d9..f0c5e519060 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c @@ -366,10 +366,12 @@ static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id) static struct irqaction sh73a0_irq_pin_cascade[32]; -#define PINTER0 0xe69000a0 -#define PINTER1 0xe69000a4 -#define PINTRR0 0xe69000d0 -#define PINTRR1 0xe69000d4 +#define PINTER0_PHYS 0xe69000a0 +#define PINTER1_PHYS 0xe69000a4 +#define PINTER0_VIRT IOMEM(0xe69000a0) +#define PINTER1_VIRT IOMEM(0xe69000a4) +#define PINTRR0 IOMEM(0xe69000d0) +#define PINTRR1 IOMEM(0xe69000d4) #define PINT0A_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq)) #define PINT0B_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 8)) @@ -377,14 +379,14 @@ static struct irqaction sh73a0_irq_pin_cascade[32]; #define PINT0D_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 24)) #define PINT1E_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT1_IRQ(irq)) -INTC_PINT(intc_pint0, PINTER0, 0xe69000b0, "sh73a0-pint0", \ +INTC_PINT(intc_pint0, PINTER0_PHYS, 0xe69000b0, "sh73a0-pint0", \ INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D), \ INTC_PINT_V(A, PINT0A_IRQ), INTC_PINT_V(B, PINT0B_IRQ), \ INTC_PINT_V(C, PINT0C_IRQ), INTC_PINT_V(D, PINT0D_IRQ), \ INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D), \ INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D)); -INTC_PINT(intc_pint1, PINTER1, 0xe69000c0, "sh73a0-pint1", \ +INTC_PINT(intc_pint1, PINTER1_PHYS, 0xe69000c0, "sh73a0-pint1", \ INTC_PINT_E(E), INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, \ INTC_PINT_V(E, PINT1E_IRQ), INTC_PINT_V_NONE, \ INTC_PINT_V_NONE, INTC_PINT_V_NONE, \ @@ -394,7 +396,7 @@ INTC_PINT(intc_pint1, PINTER1, 0xe69000c0, "sh73a0-pint1", \ static struct irqaction sh73a0_pint0_cascade; static struct irqaction sh73a0_pint1_cascade; -static void pint_demux(unsigned long rr, unsigned long er, int base_irq) +static void pint_demux(void __iomem *rr, void __iomem *er, int base_irq) { unsigned long value = ioread32(rr) & ioread32(er); int k; @@ -409,13 +411,13 @@ static void pint_demux(unsigned long rr, unsigned long er, int base_irq) static irqreturn_t sh73a0_pint0_demux(int irq, void *dev_id) { - pint_demux(PINTRR0, PINTER0, SH73A0_PINT0_IRQ(0)); + pint_demux(PINTRR0, PINTER0_VIRT, SH73A0_PINT0_IRQ(0)); return IRQ_HANDLED; } static irqreturn_t sh73a0_pint1_demux(int irq, void *dev_id) { - pint_demux(PINTRR1, PINTER1, SH73A0_PINT1_IRQ(0)); + pint_demux(PINTRR1, PINTER1_VIRT, SH73A0_PINT1_IRQ(0)); return IRQ_HANDLED; } diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c index ce9e7fa5cc8..134d1b9a882 100644 --- a/arch/arm/mach-shmobile/pfc-r8a7740.c +++ b/arch/arm/mach-shmobile/pfc-r8a7740.c @@ -20,7 +20,7 @@ */ #include <linux/init.h> #include <linux/kernel.h> -#include <linux/gpio.h> +#include <linux/sh_pfc.h> #include <mach/r8a7740.h> #include <mach/irqs.h> diff --git a/arch/arm/mach-shmobile/pfc-r8a7779.c b/arch/arm/mach-shmobile/pfc-r8a7779.c index d14c9b04807..cbc26ba2a0a 100644 --- a/arch/arm/mach-shmobile/pfc-r8a7779.c +++ b/arch/arm/mach-shmobile/pfc-r8a7779.c @@ -19,7 +19,7 @@ */ #include <linux/init.h> #include <linux/kernel.h> -#include <linux/gpio.h> +#include <linux/sh_pfc.h> #include <linux/ioport.h> #include <mach/r8a7779.h> diff --git a/arch/arm/mach-shmobile/pfc-sh7367.c b/arch/arm/mach-shmobile/pfc-sh7367.c index e6e524654e6..c0c137f3905 100644 --- a/arch/arm/mach-shmobile/pfc-sh7367.c +++ b/arch/arm/mach-shmobile/pfc-sh7367.c @@ -18,7 +18,7 @@ */ #include <linux/init.h> #include <linux/kernel.h> -#include <linux/gpio.h> +#include <linux/sh_pfc.h> #include <mach/sh7367.h> #define CPU_ALL_PORT(fn, pfx, sfx) \ diff --git a/arch/arm/mach-shmobile/pfc-sh7372.c b/arch/arm/mach-shmobile/pfc-sh7372.c index 336093f9210..7a1525fd6ad 100644 --- a/arch/arm/mach-shmobile/pfc-sh7372.c +++ b/arch/arm/mach-shmobile/pfc-sh7372.c @@ -22,7 +22,7 @@ */ #include <linux/init.h> #include <linux/kernel.h> -#include <linux/gpio.h> +#include <linux/sh_pfc.h> #include <mach/irqs.h> #include <mach/sh7372.h> diff --git a/arch/arm/mach-shmobile/pfc-sh7377.c b/arch/arm/mach-shmobile/pfc-sh7377.c index 2f10511946a..f3117f67fa2 100644 --- a/arch/arm/mach-shmobile/pfc-sh7377.c +++ b/arch/arm/mach-shmobile/pfc-sh7377.c @@ -19,7 +19,7 @@ */ #include <linux/init.h> #include <linux/kernel.h> -#include <linux/gpio.h> +#include <linux/sh_pfc.h> #include <mach/sh7377.h> #define CPU_ALL_PORT(fn, pfx, sfx) \ diff --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c index 4a547b80326..b442f9d8c71 100644 --- a/arch/arm/mach-shmobile/pfc-sh73a0.c +++ b/arch/arm/mach-shmobile/pfc-sh73a0.c @@ -20,7 +20,7 @@ */ #include <linux/init.h> #include <linux/kernel.h> -#include <linux/gpio.h> +#include <linux/sh_pfc.h> #include <mach/sh73a0.h> #include <mach/irqs.h> diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index fde0d23121d..ed8d2351915 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -11,100 +11,11 @@ * published by the Free Software Foundation. */ #include <linux/init.h> -#include <linux/errno.h> -#include <linux/delay.h> -#include <linux/device.h> #include <linux/smp.h> -#include <linux/io.h> -#include <linux/of.h> #include <asm/hardware/gic.h> -#include <asm/mach-types.h> -#include <mach/common.h> -#include <mach/emev2.h> -#ifdef CONFIG_ARCH_SH73A0 -#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \ - of_machine_is_compatible("renesas,sh73a0")) -#else -#define is_sh73a0() (0) -#endif - -#define is_r8a7779() machine_is_marzen() - -#ifdef CONFIG_ARCH_EMEV2 -#define is_emev2() of_machine_is_compatible("renesas,emev2") -#else -#define is_emev2() (0) -#endif - -static unsigned int __init shmobile_smp_get_core_count(void) -{ - if (is_sh73a0()) - return sh73a0_get_core_count(); - - if (is_r8a7779()) - return r8a7779_get_core_count(); - - if (is_emev2()) - return emev2_get_core_count(); - - return 1; -} - -static void __init shmobile_smp_prepare_cpus(void) -{ - if (is_sh73a0()) - sh73a0_smp_prepare_cpus(); - - if (is_r8a7779()) - r8a7779_smp_prepare_cpus(); - - if (is_emev2()) - emev2_smp_prepare_cpus(); -} - -int shmobile_platform_cpu_kill(unsigned int cpu) -{ - if (is_r8a7779()) - return r8a7779_platform_cpu_kill(cpu); - - if (is_emev2()) - return emev2_platform_cpu_kill(cpu); - - return 1; -} - -void __cpuinit platform_secondary_init(unsigned int cpu) +void __init shmobile_smp_init_cpus(unsigned int ncores) { - trace_hardirqs_off(); - - if (is_sh73a0()) - sh73a0_secondary_init(cpu); - - if (is_r8a7779()) - r8a7779_secondary_init(cpu); - - if (is_emev2()) - emev2_secondary_init(cpu); -} - -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) -{ - if (is_sh73a0()) - return sh73a0_boot_secondary(cpu); - - if (is_r8a7779()) - return r8a7779_boot_secondary(cpu); - - if (is_emev2()) - return emev2_boot_secondary(cpu); - - return -ENOSYS; -} - -void __init smp_init_cpus(void) -{ - unsigned int ncores = shmobile_smp_get_core_count(); unsigned int i; if (ncores > nr_cpu_ids) { @@ -118,8 +29,3 @@ void __init smp_init_cpus(void) set_smp_cross_call(gic_raise_softirq); } - -void __init platform_smp_prepare_cpus(unsigned int max_cpus) -{ - shmobile_smp_prepare_cpus(); -} diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c index 893504d012a..21e5316d2d8 100644 --- a/arch/arm/mach-shmobile/pm-r8a7740.c +++ b/arch/arm/mach-shmobile/pm-r8a7740.c @@ -21,14 +21,6 @@ static int r8a7740_pd_a4s_suspend(void) return -EBUSY; } -struct rmobile_pm_domain r8a7740_pd_a4s = { - .genpd.name = "A4S", - .bit_shift = 10, - .gov = &pm_domain_always_on_gov, - .no_debug = true, - .suspend = r8a7740_pd_a4s_suspend, -}; - static int r8a7740_pd_a3sp_suspend(void) { /* @@ -38,17 +30,31 @@ static int r8a7740_pd_a3sp_suspend(void) return console_suspend_enabled ? 0 : -EBUSY; } -struct rmobile_pm_domain r8a7740_pd_a3sp = { - .genpd.name = "A3SP", - .bit_shift = 11, - .gov = &pm_domain_always_on_gov, - .no_debug = true, - .suspend = r8a7740_pd_a3sp_suspend, +static struct rmobile_pm_domain r8a7740_pm_domains[] = { + { + .genpd.name = "A4S", + .bit_shift = 10, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = r8a7740_pd_a4s_suspend, + }, + { + .genpd.name = "A3SP", + .bit_shift = 11, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = r8a7740_pd_a3sp_suspend, + }, + { + .genpd.name = "A4LC", + .bit_shift = 1, + }, }; -struct rmobile_pm_domain r8a7740_pd_a4lc = { - .genpd.name = "A4LC", - .bit_shift = 1, -}; +void __init r8a7740_init_pm_domains(void) +{ + rmobile_init_domains(r8a7740_pm_domains, ARRAY_SIZE(r8a7740_pm_domains)); + pm_genpd_add_subdomain_names("A4S", "A3SP"); +} #endif /* CONFIG_PM */ diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c index a18a4ae16d2..d50a8e9b94a 100644 --- a/arch/arm/mach-shmobile/pm-r8a7779.c +++ b/arch/arm/mach-shmobile/pm-r8a7779.c @@ -183,7 +183,7 @@ static bool pd_active_wakeup(struct device *dev) return true; } -void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd) +static void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd) { struct generic_pm_domain *genpd = &r8a7779_pd->genpd; @@ -199,43 +199,44 @@ void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd) pd_power_up(&r8a7779_pd->genpd); } -void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd, - struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - - pm_genpd_add_device(&r8a7779_pd->genpd, dev); - if (pm_clk_no_clocks(dev)) - pm_clk_add(dev, NULL); -} - -struct r8a7779_pm_domain r8a7779_sh4a = { - .ch = { - .chan_offs = 0x80, /* PWRSR1 .. PWRER1 */ - .isr_bit = 16, /* SH4A */ - } -}; - -struct r8a7779_pm_domain r8a7779_sgx = { - .ch = { - .chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */ - .isr_bit = 20, /* SGX */ - } +static struct r8a7779_pm_domain r8a7779_pm_domains[] = { + { + .genpd.name = "SH4A", + .ch = { + .chan_offs = 0x80, /* PWRSR1 .. PWRER1 */ + .isr_bit = 16, /* SH4A */ + }, + }, + { + .genpd.name = "SGX", + .ch = { + .chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */ + .isr_bit = 20, /* SGX */ + }, + }, + { + .genpd.name = "VDP1", + .ch = { + .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */ + .isr_bit = 21, /* VDP */ + }, + }, + { + .genpd.name = "IMPX3", + .ch = { + .chan_offs = 0x140, /* PWRSR4 .. PWRER4 */ + .isr_bit = 24, /* IMP */ + }, + }, }; -struct r8a7779_pm_domain r8a7779_vdp1 = { - .ch = { - .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */ - .isr_bit = 21, /* VDP */ - } -}; +void __init r8a7779_init_pm_domains(void) +{ + int j; -struct r8a7779_pm_domain r8a7779_impx3 = { - .ch = { - .chan_offs = 0x140, /* PWRSR4 .. PWRER4 */ - .isr_bit = 24, /* IMP */ - } -}; + for (j = 0; j < ARRAY_SIZE(r8a7779_pm_domains); j++) + r8a7779_init_pm_domain(&r8a7779_pm_domains[j]); +} #endif /* CONFIG_PM */ diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index a8562540f1d..1fc05d9453d 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -20,9 +20,9 @@ #include <mach/pm-rmobile.h> /* SYSC */ -#define SPDCR 0xe6180008 -#define SWUCR 0xe6180014 -#define PSTR 0xe6180080 +#define SPDCR IOMEM(0xe6180008) +#define SWUCR IOMEM(0xe6180014) +#define PSTR IOMEM(0xe6180080) #define PSTR_RETRIES 100 #define PSTR_DELAY_US 10 @@ -134,7 +134,7 @@ static int rmobile_pd_start_dev(struct device *dev) return ret; } -void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) +static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) { struct generic_pm_domain *genpd = &rmobile_pd->genpd; struct dev_power_governor *gov = rmobile_pd->gov; @@ -149,19 +149,38 @@ void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) __rmobile_pd_power_up(rmobile_pd, false); } -void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd, - struct platform_device *pdev) +void rmobile_init_domains(struct rmobile_pm_domain domains[], int num) +{ + int j; + + for (j = 0; j < num; j++) + rmobile_init_pm_domain(&domains[j]); +} + +void rmobile_add_device_to_domain_td(const char *domain_name, + struct platform_device *pdev, + struct gpd_timing_data *td) { struct device *dev = &pdev->dev; - pm_genpd_add_device(&rmobile_pd->genpd, dev); + __pm_genpd_name_add_device(domain_name, dev, td); if (pm_clk_no_clocks(dev)) pm_clk_add(dev, NULL); } -void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd, - struct rmobile_pm_domain *rmobile_sd) +void rmobile_add_devices_to_domains(struct pm_domain_device data[], + int size) { - pm_genpd_add_subdomain(&rmobile_pd->genpd, &rmobile_sd->genpd); + struct gpd_timing_data latencies = { + .stop_latency_ns = DEFAULT_DEV_LATENCY_NS, + .start_latency_ns = DEFAULT_DEV_LATENCY_NS, + .save_state_latency_ns = DEFAULT_DEV_LATENCY_NS, + .restore_state_latency_ns = DEFAULT_DEV_LATENCY_NS, + }; + int j; + + for (j = 0; j < size; j++) + rmobile_add_device_to_domain_td(data[j].domain_name, + data[j].pdev, &latencies); } #endif /* CONFIG_PM */ diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 79203706922..a0826a48dd0 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -21,6 +21,7 @@ #include <linux/irq.h> #include <linux/bitrev.h> #include <linux/console.h> +#include <asm/cpuidle.h> #include <asm/io.h> #include <asm/tlbflush.h> #include <asm/suspend.h> @@ -29,62 +30,50 @@ #include <mach/pm-rmobile.h> /* DBG */ -#define DBGREG1 0xe6100020 -#define DBGREG9 0xe6100040 +#define DBGREG1 IOMEM(0xe6100020) +#define DBGREG9 IOMEM(0xe6100040) /* CPGA */ -#define SYSTBCR 0xe6150024 -#define MSTPSR0 0xe6150030 -#define MSTPSR1 0xe6150038 -#define MSTPSR2 0xe6150040 -#define MSTPSR3 0xe6150048 -#define MSTPSR4 0xe615004c -#define PLLC01STPCR 0xe61500c8 +#define SYSTBCR IOMEM(0xe6150024) +#define MSTPSR0 IOMEM(0xe6150030) +#define MSTPSR1 IOMEM(0xe6150038) +#define MSTPSR2 IOMEM(0xe6150040) +#define MSTPSR3 IOMEM(0xe6150048) +#define MSTPSR4 IOMEM(0xe615004c) +#define PLLC01STPCR IOMEM(0xe61500c8) /* SYSC */ -#define SBAR 0xe6180020 -#define WUPRMSK 0xe6180028 -#define WUPSMSK 0xe618002c -#define WUPSMSK2 0xe6180048 -#define WUPSFAC 0xe6180098 -#define IRQCR 0xe618022c -#define IRQCR2 0xe6180238 -#define IRQCR3 0xe6180244 -#define IRQCR4 0xe6180248 -#define PDNSEL 0xe6180254 +#define SBAR IOMEM(0xe6180020) +#define WUPRMSK IOMEM(0xe6180028) +#define WUPSMSK IOMEM(0xe618002c) +#define WUPSMSK2 IOMEM(0xe6180048) +#define WUPSFAC IOMEM(0xe6180098) +#define IRQCR IOMEM(0xe618022c) +#define IRQCR2 IOMEM(0xe6180238) +#define IRQCR3 IOMEM(0xe6180244) +#define IRQCR4 IOMEM(0xe6180248) +#define PDNSEL IOMEM(0xe6180254) /* INTC */ -#define ICR1A 0xe6900000 -#define ICR2A 0xe6900004 -#define ICR3A 0xe6900008 -#define ICR4A 0xe690000c -#define INTMSK00A 0xe6900040 -#define INTMSK10A 0xe6900044 -#define INTMSK20A 0xe6900048 -#define INTMSK30A 0xe690004c +#define ICR1A IOMEM(0xe6900000) +#define ICR2A IOMEM(0xe6900004) +#define ICR3A IOMEM(0xe6900008) +#define ICR4A IOMEM(0xe690000c) +#define INTMSK00A IOMEM(0xe6900040) +#define INTMSK10A IOMEM(0xe6900044) +#define INTMSK20A IOMEM(0xe6900048) +#define INTMSK30A IOMEM(0xe690004c) /* MFIS */ +/* FIXME: pointing where? */ #define SMFRAM 0xe6a70000 /* AP-System Core */ -#define APARMBAREA 0xe6f10020 +#define APARMBAREA IOMEM(0xe6f10020) #ifdef CONFIG_PM -struct rmobile_pm_domain sh7372_pd_a4lc = { - .genpd.name = "A4LC", - .bit_shift = 1, -}; - -struct rmobile_pm_domain sh7372_pd_a4mp = { - .genpd.name = "A4MP", - .bit_shift = 2, -}; - -struct rmobile_pm_domain sh7372_pd_d4 = { - .genpd.name = "D4", - .bit_shift = 3, -}; +#define PM_DOMAIN_ON_OFF_LATENCY_NS 250000 static int sh7372_a4r_pd_suspend(void) { @@ -93,39 +82,25 @@ static int sh7372_a4r_pd_suspend(void) return 0; } -struct rmobile_pm_domain sh7372_pd_a4r = { - .genpd.name = "A4R", - .bit_shift = 5, - .suspend = sh7372_a4r_pd_suspend, - .resume = sh7372_intcs_resume, -}; +static bool a4s_suspend_ready; -struct rmobile_pm_domain sh7372_pd_a3rv = { - .genpd.name = "A3RV", - .bit_shift = 6, -}; - -struct rmobile_pm_domain sh7372_pd_a3ri = { - .genpd.name = "A3RI", - .bit_shift = 8, -}; - -static int sh7372_pd_a4s_suspend(void) +static int sh7372_a4s_pd_suspend(void) { /* * The A4S domain contains the CPU core and therefore it should - * only be turned off if the CPU is in use. + * only be turned off if the CPU is not in use. This may happen + * during system suspend, when SYSC is going to be used for generating + * resume signals and a4s_suspend_ready is set to let + * sh7372_enter_suspend() know that it can turn A4S off. */ + a4s_suspend_ready = true; return -EBUSY; } -struct rmobile_pm_domain sh7372_pd_a4s = { - .genpd.name = "A4S", - .bit_shift = 10, - .gov = &pm_domain_always_on_gov, - .no_debug = true, - .suspend = sh7372_pd_a4s_suspend, -}; +static void sh7372_a4s_pd_resume(void) +{ + a4s_suspend_ready = false; +} static int sh7372_a3sp_pd_suspend(void) { @@ -136,18 +111,80 @@ static int sh7372_a3sp_pd_suspend(void) return console_suspend_enabled ? 0 : -EBUSY; } -struct rmobile_pm_domain sh7372_pd_a3sp = { - .genpd.name = "A3SP", - .bit_shift = 11, - .gov = &pm_domain_always_on_gov, - .no_debug = true, - .suspend = sh7372_a3sp_pd_suspend, +static struct rmobile_pm_domain sh7372_pm_domains[] = { + { + .genpd.name = "A4LC", + .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .bit_shift = 1, + }, + { + .genpd.name = "A4MP", + .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .bit_shift = 2, + }, + { + .genpd.name = "D4", + .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .bit_shift = 3, + }, + { + .genpd.name = "A4R", + .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .bit_shift = 5, + .suspend = sh7372_a4r_pd_suspend, + .resume = sh7372_intcs_resume, + }, + { + .genpd.name = "A3RV", + .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .bit_shift = 6, + }, + { + .genpd.name = "A3RI", + .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .bit_shift = 8, + }, + { + .genpd.name = "A4S", + .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .bit_shift = 10, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = sh7372_a4s_pd_suspend, + .resume = sh7372_a4s_pd_resume, + }, + { + .genpd.name = "A3SP", + .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .bit_shift = 11, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = sh7372_a3sp_pd_suspend, + }, + { + .genpd.name = "A3SG", + .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .bit_shift = 13, + }, }; -struct rmobile_pm_domain sh7372_pd_a3sg = { - .genpd.name = "A3SG", - .bit_shift = 13, -}; +void __init sh7372_init_pm_domains(void) +{ + rmobile_init_domains(sh7372_pm_domains, ARRAY_SIZE(sh7372_pm_domains)); + pm_genpd_add_subdomain_names("A4LC", "A3RV"); + pm_genpd_add_subdomain_names("A4R", "A4LC"); + pm_genpd_add_subdomain_names("A4S", "A3SG"); + pm_genpd_add_subdomain_names("A4S", "A3SP"); +} #endif /* CONFIG_PM */ @@ -303,6 +340,21 @@ static void sh7372_enter_a3sm_common(int pllc0_on) sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); sh7372_enter_sysc(pllc0_on, 1 << 12); } + +static void sh7372_enter_a4s_common(int pllc0_on) +{ + sh7372_intca_suspend(); + sh7372_set_reset_vector(SMFRAM); + sh7372_enter_sysc(pllc0_on, 1 << 10); + sh7372_intca_resume(); +} + +static void sh7372_pm_setup_smfram(void) +{ + memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100); +} +#else +static inline void sh7372_pm_setup_smfram(void) {} #endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */ #ifdef CONFIG_CPU_IDLE @@ -312,7 +364,8 @@ static int sh7372_do_idle_core_standby(unsigned long unused) return 0; } -static void sh7372_enter_core_standby(void) +static int sh7372_enter_core_standby(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); @@ -323,83 +376,102 @@ static void sh7372_enter_core_standby(void) /* disable reset vector translation */ __raw_writel(0, SBAR); + + return 1; } -static void sh7372_enter_a3sm_pll_on(void) +static int sh7372_enter_a3sm_pll_on(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { sh7372_enter_a3sm_common(1); + return 2; } -static void sh7372_enter_a3sm_pll_off(void) +static int sh7372_enter_a3sm_pll_off(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { sh7372_enter_a3sm_common(0); + return 3; } -static void sh7372_cpuidle_setup(struct cpuidle_driver *drv) +static int sh7372_enter_a4s(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { - struct cpuidle_state *state = &drv->states[drv->state_count]; - - snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); - strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN); - state->exit_latency = 10; - state->target_residency = 20 + 10; - state->flags = CPUIDLE_FLAG_TIME_VALID; - shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby; - drv->state_count++; - - state = &drv->states[drv->state_count]; - snprintf(state->name, CPUIDLE_NAME_LEN, "C3"); - strncpy(state->desc, "A3SM PLL ON", CPUIDLE_DESC_LEN); - state->exit_latency = 20; - state->target_residency = 30 + 20; - state->flags = CPUIDLE_FLAG_TIME_VALID; - shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_on; - drv->state_count++; - - state = &drv->states[drv->state_count]; - snprintf(state->name, CPUIDLE_NAME_LEN, "C4"); - strncpy(state->desc, "A3SM PLL OFF", CPUIDLE_DESC_LEN); - state->exit_latency = 120; - state->target_residency = 30 + 120; - state->flags = CPUIDLE_FLAG_TIME_VALID; - shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_off; - drv->state_count++; + unsigned long msk, msk2; + + if (!sh7372_sysc_valid(&msk, &msk2)) + return sh7372_enter_a3sm_pll_off(dev, drv, index); + + sh7372_setup_sysc(msk, msk2); + sh7372_enter_a4s_common(0); + return 4; } +static struct cpuidle_driver sh7372_cpuidle_driver = { + .name = "sh7372_cpuidle", + .owner = THIS_MODULE, + .en_core_tk_irqen = 1, + .state_count = 5, + .safe_state_index = 0, /* C1 */ + .states[0] = ARM_CPUIDLE_WFI_STATE, + .states[0].enter = shmobile_enter_wfi, + .states[1] = { + .name = "C2", + .desc = "Core Standby Mode", + .exit_latency = 10, + .target_residency = 20 + 10, + .flags = CPUIDLE_FLAG_TIME_VALID, + .enter = sh7372_enter_core_standby, + }, + .states[2] = { + .name = "C3", + .desc = "A3SM PLL ON", + .exit_latency = 20, + .target_residency = 30 + 20, + .flags = CPUIDLE_FLAG_TIME_VALID, + .enter = sh7372_enter_a3sm_pll_on, + }, + .states[3] = { + .name = "C4", + .desc = "A3SM PLL OFF", + .exit_latency = 120, + .target_residency = 30 + 120, + .flags = CPUIDLE_FLAG_TIME_VALID, + .enter = sh7372_enter_a3sm_pll_off, + }, + .states[4] = { + .name = "C5", + .desc = "A4S PLL OFF", + .exit_latency = 240, + .target_residency = 30 + 240, + .flags = CPUIDLE_FLAG_TIME_VALID, + .enter = sh7372_enter_a4s, + .disabled = true, + }, +}; + static void sh7372_cpuidle_init(void) { - shmobile_cpuidle_setup = sh7372_cpuidle_setup; + shmobile_cpuidle_set_driver(&sh7372_cpuidle_driver); } #else static void sh7372_cpuidle_init(void) {} #endif #ifdef CONFIG_SUSPEND -static void sh7372_enter_a4s_common(int pllc0_on) -{ - sh7372_intca_suspend(); - memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100); - sh7372_set_reset_vector(SMFRAM); - sh7372_enter_sysc(pllc0_on, 1 << 10); - sh7372_intca_resume(); -} - static int sh7372_enter_suspend(suspend_state_t suspend_state) { unsigned long msk, msk2; /* check active clocks to determine potential wakeup sources */ - if (sh7372_sysc_valid(&msk, &msk2)) { - if (!console_suspend_enabled && - sh7372_pd_a4s.genpd.status == GPD_STATE_POWER_OFF) { - /* convert INTC mask/sense to SYSC mask/sense */ - sh7372_setup_sysc(msk, msk2); - - /* enter A4S sleep with PLLC0 off */ - pr_debug("entering A4S\n"); - sh7372_enter_a4s_common(0); - return 0; - } + if (sh7372_sysc_valid(&msk, &msk2) && a4s_suspend_ready) { + /* convert INTC mask/sense to SYSC mask/sense */ + sh7372_setup_sysc(msk, msk2); + + /* enter A4S sleep with PLLC0 off */ + pr_debug("entering A4S\n"); + sh7372_enter_a4s_common(0); + return 0; } /* default to enter A3SM sleep with PLLC0 off */ @@ -425,7 +497,7 @@ static int sh7372_pm_notifier_fn(struct notifier_block *notifier, * executed during system suspend and resume, respectively, so * that those functions don't crash while accessing the INTCS. */ - pm_genpd_poweron(&sh7372_pd_a4r.genpd); + pm_genpd_name_poweron("A4R"); break; case PM_POST_SUSPEND: pm_genpd_poweroff_unused(); @@ -454,6 +526,14 @@ void __init sh7372_pm_init(void) /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ __raw_writel(0, PDNSEL); + sh7372_pm_setup_smfram(); + sh7372_suspend_init(); sh7372_cpuidle_init(); } + +void __init sh7372_pm_init_late(void) +{ + shmobile_init_late(); + pm_genpd_name_attach_cpuidle("A4S", 4); +} diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c index dae9aa68bb0..a47beeb1828 100644 --- a/arch/arm/mach-shmobile/setup-emev2.c +++ b/arch/arm/mach-shmobile/setup-emev2.c @@ -356,6 +356,26 @@ static struct platform_device gio4_device = { }, }; +static struct resource pmu_resources[] = { + [0] = { + .start = 152, + .end = 152, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .start = 153, + .end = 153, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = -1, + .num_resources = ARRAY_SIZE(pmu_resources), + .resource = pmu_resources, +}; + static struct platform_device *emev2_early_devices[] __initdata = { &uart0_device, &uart1_device, @@ -370,6 +390,7 @@ static struct platform_device *emev2_late_devices[] __initdata = { &gio2_device, &gio3_device, &gio4_device, + &pmu_device, }; void __init emev2_add_standard_devices(void) @@ -440,6 +461,7 @@ void __init emev2_init_irq_dt(void) } DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)") + .smp = smp_ops(emev2_smp_ops), .init_early = emev2_init_delay, .nr_irqs = NR_IRQS_LEGACY, .init_irq = emev2_init_irq_dt, diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 78948a9dba0..11bb1d98419 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -673,12 +673,7 @@ void __init r8a7740_add_standard_devices(void) r8a7740_i2c_workaround(&i2c0_device); r8a7740_i2c_workaround(&i2c1_device); - /* PM domain */ - rmobile_init_pm_domain(&r8a7740_pd_a4s); - rmobile_init_pm_domain(&r8a7740_pd_a3sp); - rmobile_init_pm_domain(&r8a7740_pd_a4lc); - - rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp); + r8a7740_init_pm_domains(); /* add devices */ platform_add_devices(r8a7740_early_devices, @@ -688,16 +683,16 @@ void __init r8a7740_add_standard_devices(void) /* add devices to PM domain */ - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif0_device); - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif1_device); - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif2_device); - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif3_device); - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif4_device); - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif5_device); - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif6_device); - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif7_device); - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scifb_device); - rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &i2c1_device); + rmobile_add_device_to_domain("A3SP", &scif0_device); + rmobile_add_device_to_domain("A3SP", &scif1_device); + rmobile_add_device_to_domain("A3SP", &scif2_device); + rmobile_add_device_to_domain("A3SP", &scif3_device); + rmobile_add_device_to_domain("A3SP", &scif4_device); + rmobile_add_device_to_domain("A3SP", &scif5_device); + rmobile_add_device_to_domain("A3SP", &scif6_device); + rmobile_add_device_to_domain("A3SP", &scif7_device); + rmobile_add_device_to_domain("A3SP", &scifb_device); + rmobile_add_device_to_domain("A3SP", &i2c1_device); } static void __init r8a7740_earlytimer_init(void) diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index e98e46f6cf5..2917668f009 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -251,10 +251,7 @@ void __init r8a7779_add_standard_devices(void) #endif r8a7779_pm_init(); - r8a7779_init_pm_domain(&r8a7779_sh4a); - r8a7779_init_pm_domain(&r8a7779_sgx); - r8a7779_init_pm_domain(&r8a7779_vdp1); - r8a7779_init_pm_domain(&r8a7779_impx3); + r8a7779_init_pm_domains(); platform_add_devices(r8a7779_early_devices, ARRAY_SIZE(r8a7779_early_devices)); diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c index 2e3074ab75b..e647f541087 100644 --- a/arch/arm/mach-shmobile/setup-sh7367.c +++ b/arch/arm/mach-shmobile/setup-sh7367.c @@ -462,7 +462,7 @@ static void __init sh7367_earlytimer_init(void) shmobile_earlytimer_init(); } -#define SYMSTPCR2 0xe6158048 +#define SYMSTPCR2 IOMEM(0xe6158048) #define SYMSTPCR2_CMT1 (1 << 29) void __init sh7367_add_early_devices(void) diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 838a87be1d5..a07954fbcd2 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -1001,21 +1001,34 @@ static struct platform_device *sh7372_late_devices[] __initdata = { void __init sh7372_add_standard_devices(void) { - rmobile_init_pm_domain(&sh7372_pd_a4lc); - rmobile_init_pm_domain(&sh7372_pd_a4mp); - rmobile_init_pm_domain(&sh7372_pd_d4); - rmobile_init_pm_domain(&sh7372_pd_a4r); - rmobile_init_pm_domain(&sh7372_pd_a3rv); - rmobile_init_pm_domain(&sh7372_pd_a3ri); - rmobile_init_pm_domain(&sh7372_pd_a4s); - rmobile_init_pm_domain(&sh7372_pd_a3sp); - rmobile_init_pm_domain(&sh7372_pd_a3sg); - - rmobile_pm_add_subdomain(&sh7372_pd_a4lc, &sh7372_pd_a3rv); - rmobile_pm_add_subdomain(&sh7372_pd_a4r, &sh7372_pd_a4lc); - - rmobile_pm_add_subdomain(&sh7372_pd_a4s, &sh7372_pd_a3sg); - rmobile_pm_add_subdomain(&sh7372_pd_a4s, &sh7372_pd_a3sp); + struct pm_domain_device domain_devices[] = { + { "A3RV", &vpu_device, }, + { "A4MP", &spu0_device, }, + { "A4MP", &spu1_device, }, + { "A3SP", &scif0_device, }, + { "A3SP", &scif1_device, }, + { "A3SP", &scif2_device, }, + { "A3SP", &scif3_device, }, + { "A3SP", &scif4_device, }, + { "A3SP", &scif5_device, }, + { "A3SP", &scif6_device, }, + { "A3SP", &iic1_device, }, + { "A3SP", &dma0_device, }, + { "A3SP", &dma1_device, }, + { "A3SP", &dma2_device, }, + { "A3SP", &usb_dma0_device, }, + { "A3SP", &usb_dma1_device, }, + { "A4R", &iic0_device, }, + { "A4R", &veu0_device, }, + { "A4R", &veu1_device, }, + { "A4R", &veu2_device, }, + { "A4R", &veu3_device, }, + { "A4R", &jpu_device, }, + { "A4R", &tmu00_device, }, + { "A4R", &tmu01_device, }, + }; + + sh7372_init_pm_domains(); platform_add_devices(sh7372_early_devices, ARRAY_SIZE(sh7372_early_devices)); @@ -1023,30 +1036,8 @@ void __init sh7372_add_standard_devices(void) platform_add_devices(sh7372_late_devices, ARRAY_SIZE(sh7372_late_devices)); - rmobile_add_device_to_domain(&sh7372_pd_a3rv, &vpu_device); - rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu0_device); - rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu1_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif0_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif1_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif2_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif3_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif4_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif5_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif6_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &iic1_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma0_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma1_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma2_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usb_dma0_device); - rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usb_dma1_device); - rmobile_add_device_to_domain(&sh7372_pd_a4r, &iic0_device); - rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu0_device); - rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu1_device); - rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu2_device); - rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu3_device); - rmobile_add_device_to_domain(&sh7372_pd_a4r, &jpu_device); - rmobile_add_device_to_domain(&sh7372_pd_a4r, &tmu00_device); - rmobile_add_device_to_domain(&sh7372_pd_a4r, &tmu01_device); + rmobile_add_devices_to_domains(domain_devices, + ARRAY_SIZE(domain_devices)); } static void __init sh7372_earlytimer_init(void) diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c index 855b1506caf..edcf98bb701 100644 --- a/arch/arm/mach-shmobile/setup-sh7377.c +++ b/arch/arm/mach-shmobile/setup-sh7377.c @@ -484,7 +484,7 @@ static void __init sh7377_earlytimer_init(void) shmobile_earlytimer_init(); } -#define SMSTPCR3 0xe615013c +#define SMSTPCR3 IOMEM(0xe615013c) #define SMSTPCR3_CMT1 (1 << 29) void __init sh7377_add_early_devices(void) diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index d230af656fc..db99a4ade80 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -734,6 +734,26 @@ static struct platform_device mpdma0_device = { }, }; +static struct resource pmu_resources[] = { + [0] = { + .start = gic_spi(55), + .end = gic_spi(55), + .flags = IORESOURCE_IRQ, + }, + [1] = { + .start = gic_spi(56), + .end = gic_spi(56), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = -1, + .num_resources = ARRAY_SIZE(pmu_resources), + .resource = pmu_resources, +}; + static struct platform_device *sh73a0_early_devices[] __initdata = { &scif0_device, &scif1_device, @@ -757,9 +777,10 @@ static struct platform_device *sh73a0_late_devices[] __initdata = { &i2c4_device, &dma0_device, &mpdma0_device, + &pmu_device, }; -#define SRCR2 0xe61580b0 +#define SRCR2 IOMEM(0xe61580b0) void __init sh73a0_add_standard_devices(void) { diff --git a/arch/arm/mach-shmobile/include/mach/gpio.h b/arch/arm/mach-shmobile/sh-gpio.h index 844507d937c..e834763ac2a 100644 --- a/arch/arm/mach-shmobile/include/mach/gpio.h +++ b/arch/arm/mach-shmobile/sh-gpio.h @@ -12,22 +12,8 @@ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/sh_pfc.h> #include <linux/io.h> -#ifdef CONFIG_GPIOLIB - -static inline int irq_to_gpio(unsigned int irq) -{ - return -ENOSYS; -} - -#else - -#define __ARM_GPIOLIB_COMPLEX - -#endif /* CONFIG_GPIOLIB */ - /* * FIXME !! * @@ -35,12 +21,12 @@ static inline int irq_to_gpio(unsigned int irq) * the method to control only pull up/down/free. * this function should be replaced by correct gpio function */ -static inline void __init gpio_direction_none(u32 addr) +static inline void __init gpio_direction_none(void __iomem * addr) { __raw_writeb(0x00, addr); } -static inline void __init gpio_request_pullup(u32 addr) +static inline void __init gpio_request_pullup(void __iomem * addr) { u8 data = __raw_readb(addr); @@ -49,7 +35,7 @@ static inline void __init gpio_request_pullup(u32 addr) __raw_writeb(data, addr); } -static inline void __init gpio_request_pulldown(u32 addr) +static inline void __init gpio_request_pulldown(void __iomem * addr) { u8 data = __raw_readb(addr); diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c index 6a35c4a31e6..f978c5d0e1a 100644 --- a/arch/arm/mach-shmobile/smp-emev2.c +++ b/arch/arm/mach-shmobile/smp-emev2.c @@ -50,7 +50,7 @@ static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) } -unsigned int __init emev2_get_core_count(void) +static unsigned int __init emev2_get_core_count(void) { if (!scu_base) { scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE); @@ -62,17 +62,35 @@ unsigned int __init emev2_get_core_count(void) return scu_base ? scu_get_core_count(scu_base) : 1; } -int emev2_platform_cpu_kill(unsigned int cpu) +static int emev2_platform_cpu_kill(unsigned int cpu) { return 0; /* not supported yet */ } -void __cpuinit emev2_secondary_init(unsigned int cpu) +static int __maybe_unused emev2_cpu_kill(unsigned int cpu) +{ + int k; + + /* this function is running on another CPU than the offline target, + * here we need wait for shutdown code in platform_cpu_die() to + * finish before asking SoC-specific code to power off the CPU core. + */ + for (k = 0; k < 1000; k++) { + if (shmobile_cpu_is_dead(cpu)) + return emev2_platform_cpu_kill(cpu); + mdelay(1); + } + + return 0; +} + + +static void __cpuinit emev2_secondary_init(unsigned int cpu) { gic_secondary_init(0); } -int __cpuinit emev2_boot_secondary(unsigned int cpu) +static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle) { cpu = cpu_logical_map(cpu); @@ -86,7 +104,7 @@ int __cpuinit emev2_boot_secondary(unsigned int cpu) return 0; } -void __init emev2_smp_prepare_cpus(void) +static void __init emev2_smp_prepare_cpus(unsigned int max_cpus) { int cpu = cpu_logical_map(0); @@ -95,3 +113,22 @@ void __init emev2_smp_prepare_cpus(void) /* enable cache coherency on CPU0 */ modify_scu_cpu_psr(0, 3 << (cpu * 8)); } + +static void __init emev2_smp_init_cpus(void) +{ + unsigned int ncores = emev2_get_core_count(); + + shmobile_smp_init_cpus(ncores); +} + +struct smp_operations emev2_smp_ops __initdata = { + .smp_init_cpus = emev2_smp_init_cpus, + .smp_prepare_cpus = emev2_smp_prepare_cpus, + .smp_secondary_init = emev2_secondary_init, + .smp_boot_secondary = emev2_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_kill = emev2_cpu_kill, + .cpu_die = shmobile_cpu_die, + .cpu_disable = shmobile_cpu_disable, +#endif +}; diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 6d1d0238cbf..2ce6af9a6a3 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -87,14 +87,14 @@ static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) __raw_writel(tmp, scu_base + 8); } -unsigned int __init r8a7779_get_core_count(void) +static unsigned int __init r8a7779_get_core_count(void) { void __iomem *scu_base = scu_base_addr(); return scu_get_core_count(scu_base); } -int r8a7779_platform_cpu_kill(unsigned int cpu) +static int r8a7779_platform_cpu_kill(unsigned int cpu) { struct r8a7779_pm_ch *ch = NULL; int ret = -EIO; @@ -113,12 +113,31 @@ int r8a7779_platform_cpu_kill(unsigned int cpu) return ret ? ret : 1; } -void __cpuinit r8a7779_secondary_init(unsigned int cpu) +static int __maybe_unused r8a7779_cpu_kill(unsigned int cpu) +{ + int k; + + /* this function is running on another CPU than the offline target, + * here we need wait for shutdown code in platform_cpu_die() to + * finish before asking SoC-specific code to power off the CPU core. + */ + for (k = 0; k < 1000; k++) { + if (shmobile_cpu_is_dead(cpu)) + return r8a7779_platform_cpu_kill(cpu); + + mdelay(1); + } + + return 0; +} + + +static void __cpuinit r8a7779_secondary_init(unsigned int cpu) { gic_secondary_init(0); } -int __cpuinit r8a7779_boot_secondary(unsigned int cpu) +static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle) { struct r8a7779_pm_ch *ch = NULL; int ret = -EIO; @@ -137,7 +156,7 @@ int __cpuinit r8a7779_boot_secondary(unsigned int cpu) return ret; } -void __init r8a7779_smp_prepare_cpus(void) +static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus) { int cpu = cpu_logical_map(0); @@ -156,3 +175,22 @@ void __init r8a7779_smp_prepare_cpus(void) r8a7779_platform_cpu_kill(2); r8a7779_platform_cpu_kill(3); } + +static void __init r8a7779_smp_init_cpus(void) +{ + unsigned int ncores = r8a7779_get_core_count(); + + shmobile_smp_init_cpus(ncores); +} + +struct smp_operations r8a7779_smp_ops __initdata = { + .smp_init_cpus = r8a7779_smp_init_cpus, + .smp_prepare_cpus = r8a7779_smp_prepare_cpus, + .smp_secondary_init = r8a7779_secondary_init, + .smp_boot_secondary = r8a7779_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_kill = r8a7779_cpu_kill, + .cpu_die = shmobile_cpu_die, + .cpu_disable = shmobile_cpu_disable, +#endif +}; diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index e36c41c4ab4..624f00f70ab 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -22,8 +22,10 @@ #include <linux/smp.h> #include <linux/spinlock.h> #include <linux/io.h> +#include <linux/delay.h> #include <mach/common.h> #include <asm/smp_plat.h> +#include <mach/sh73a0.h> #include <asm/smp_scu.h> #include <asm/smp_twd.h> #include <asm/hardware/gic.h> @@ -64,19 +66,19 @@ static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) __raw_writel(tmp, scu_base + 8); } -unsigned int __init sh73a0_get_core_count(void) +static unsigned int __init sh73a0_get_core_count(void) { void __iomem *scu_base = scu_base_addr(); return scu_get_core_count(scu_base); } -void __cpuinit sh73a0_secondary_init(unsigned int cpu) +static void __cpuinit sh73a0_secondary_init(unsigned int cpu) { gic_secondary_init(0); } -int __cpuinit sh73a0_boot_secondary(unsigned int cpu) +static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle) { cpu = cpu_logical_map(cpu); @@ -91,7 +93,7 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu) return 0; } -void __init sh73a0_smp_prepare_cpus(void) +static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus) { int cpu = cpu_logical_map(0); @@ -104,3 +106,41 @@ void __init sh73a0_smp_prepare_cpus(void) /* enable cache coherency on CPU0 */ modify_scu_cpu_psr(0, 3 << (cpu * 8)); } + +static void __init sh73a0_smp_init_cpus(void) +{ + unsigned int ncores = sh73a0_get_core_count(); + + shmobile_smp_init_cpus(ncores); +} + +static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu) +{ + int k; + + /* this function is running on another CPU than the offline target, + * here we need wait for shutdown code in platform_cpu_die() to + * finish before asking SoC-specific code to power off the CPU core. + */ + for (k = 0; k < 1000; k++) { + if (shmobile_cpu_is_dead(cpu)) + return 1; + + mdelay(1); + } + + return 0; +} + + +struct smp_operations sh73a0_smp_ops __initdata = { + .smp_init_cpus = sh73a0_smp_init_cpus, + .smp_prepare_cpus = sh73a0_smp_prepare_cpus, + .smp_secondary_init = sh73a0_secondary_init, + .smp_boot_secondary = sh73a0_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_kill = sh73a0_cpu_kill, + .cpu_die = shmobile_cpu_die, + .cpu_disable = shmobile_cpu_disable, +#endif +}; |