Message ID | 1417616421-6968-1-git-send-email-geert+renesas@glider.be (mailing list archive) |
---|---|
State | Rejected |
Delegated to: | Simon Horman |
Headers | show |
On Wed, Dec 03, 2014 at 03:20:21PM +0100, Geert Uytterhoeven wrote: > Add all hierarchical PM domains that exist on SH-Mobile AG5 (sh730a), > and register all platform devices to the appropriate PM domains. > > Special handling is required for the following PM domains: > - A4BC0 and A4BC1 contain the SDRAM Bus State Controllers, and thus > should not be turned off, > - A3SP contains the serial console, and should not be turned off if > no_console_suspend is set, > - A2SL contains the CPU core, and should not be turned off if the CPU > is in use. > > Note that PM domain D4 can be powered down without ill effects on s2ram > behavior, just like on SH-Mobile AP4 (sh7372), but unlike on R-Mobile A1 > (r8a7740). > > Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> > --- > v2: > - The smsc911x is not located in A4S (the Bus State Controller it is > connected to is, but we don't cover that device in legacy code), > - Move domain_devices[] next to tables with platform devices. In general I'm not adding new legacy board support. I'm happy to make exceptions but its not obvious to me that this should be one. > --- > arch/arm/mach-shmobile/board-kzm9g.c | 14 ++++ > arch/arm/mach-shmobile/pm-sh73a0.c | 131 ++++++++++++++++++++++++++++++++++ > arch/arm/mach-shmobile/setup-sh73a0.c | 31 ++++++++ > arch/arm/mach-shmobile/sh73a0.h | 7 ++ > 4 files changed, 183 insertions(+) > > diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c > index 7c9b63bdde9fa458..a4fbd02f1ddbdbc6 100644 > --- a/arch/arm/mach-shmobile/board-kzm9g.c > +++ b/arch/arm/mach-shmobile/board-kzm9g.c > @@ -48,6 +48,7 @@ > #include "common.h" > #include "intc.h" > #include "irqs.h" > +#include "pm-rmobile.h" > #include "sh73a0.h" > > /* > @@ -798,6 +799,16 @@ static struct platform_device *kzm_devices[] __initdata = { > &fsi_ak4648_device, > }; > > +static struct pm_domain_device kzm_domain_devices[] __initdata = { > + { "A4LC0", &lcdc_device }, > + { "A4MP", &fsi_device }, > + { "A4S", &usb_host_device }, > + { "A3SP", &usbhs_device }, > + { "A3SP", &mmc_device }, > + { "A3SP", &sdhi0_device }, > + { "A3SP", &sdhi2_device }, > +}; > + > static unsigned long pin_pullup_conf[] = { > PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0), > }; > @@ -888,6 +899,9 @@ static void __init kzm_init(void) > sh73a0_add_standard_devices(); > platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices)); > > + rmobile_add_devices_to_domains(kzm_domain_devices, > + ARRAY_SIZE(kzm_domain_devices)); > + > sh73a0_pm_init(); > } > > diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c > index a7e466817965e3b8..06d2d98a355a0b70 100644 > --- a/arch/arm/mach-shmobile/pm-sh73a0.c > +++ b/arch/arm/mach-shmobile/pm-sh73a0.c > @@ -2,14 +2,145 @@ > * sh73a0 Power management support > * > * Copyright (C) 2012 Bastian Hecht <hechtb+renesas@gmail.com> > + * Copyright (C) 2014 Glider bvba > * > * This file is subject to the terms and conditions of the GNU General Public > * License. See the file "COPYING" in the main directory of this archive > * for more details. > */ > > +#include <linux/console.h> > +#include <linux/io.h> > #include <linux/suspend.h> > + > #include "common.h" > +#include "pm-rmobile.h" > + > +#define SYSC_BASE IOMEM(0xe6180000) > + > +#if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM) > +static int sh73a0_pd_a4bc_suspend(void) > +{ > + /* > + * The A4BC0 and A4BC1 domains contain the SDRAM Bus State Controllers > + * (SBSC1 and SBSC2) and therefore they should only be turned off if > + * SDRAM is not in use. > + */ > + return -EBUSY; > +} > + > +static int sh73a0_pd_a3sp_suspend(void) > +{ > + /* > + * Serial consoles make use of SCIF hardware located in A3SP, > + * keep such power domain on if "no_console_suspend" is set. > + */ > + return console_suspend_enabled ? 0 : -EBUSY; > +} > + > +static int sh73a0_pd_a2sl_suspend(void) > +{ > + /* > + * The A2SL domain contains the CPU core and therefore it should > + * only be turned off if the CPU is not in use. > + */ > + return -EBUSY; > +} > + > +static struct rmobile_pm_domain sh73a0_pm_domains[] = { > + { > + .genpd.name = "C4", > + .base = SYSC_BASE, > + .bit_shift = 0, > + }, { > + .genpd.name = "D4", > + .base = SYSC_BASE, > + .bit_shift = 1, > + }, { > + .genpd.name = "A4BC0", > + .base = SYSC_BASE, > + .bit_shift = 4, > + .gov = &pm_domain_always_on_gov, > + .suspend = sh73a0_pd_a4bc_suspend, > + }, { > + .genpd.name = "A4BC1", > + .base = SYSC_BASE, > + .bit_shift = 5, > + .gov = &pm_domain_always_on_gov, > + .suspend = sh73a0_pd_a4bc_suspend, > + }, { > + .genpd.name = "A4LC0", > + .base = SYSC_BASE, > + .bit_shift = 6, > + }, { > + .genpd.name = "A4LC1", > + .base = SYSC_BASE, > + .bit_shift = 7, > + }, { > + .genpd.name = "A4MP", > + .base = SYSC_BASE, > + .bit_shift = 8, > + }, { > + .genpd.name = "A3MP", > + .base = SYSC_BASE, > + .bit_shift = 9, > + }, { > + .genpd.name = "A3VC", > + .base = SYSC_BASE, > + .bit_shift = 10, > + }, { > + .genpd.name = "A4RM", > + .base = SYSC_BASE, > + .bit_shift = 12, > + }, { > + .genpd.name = "A3R", > + .base = SYSC_BASE, > + .bit_shift = 13, > + }, { > + .genpd.name = "A2RV", > + .base = SYSC_BASE, > + .bit_shift = 14, > + }, { > + .genpd.name = "A4S", > + .base = SYSC_BASE, > + .bit_shift = 16, > + }, { > + .genpd.name = "A3SP", > + .base = SYSC_BASE, > + .bit_shift = 17, > + .gov = &pm_domain_always_on_gov, > + .no_debug = true, > + .suspend = sh73a0_pd_a3sp_suspend, > + }, { > + .genpd.name = "A3SG", > + .base = SYSC_BASE, > + .bit_shift = 18, > + }, { > + .genpd.name = "A3SM", > + .base = SYSC_BASE, > + .bit_shift = 19, > + }, { > + .genpd.name = "A2SL", > + .base = SYSC_BASE, > + .bit_shift = 20, > + .gov = &pm_domain_always_on_gov, > + .suspend = sh73a0_pd_a2sl_suspend, > + } > +}; > + > +void __init sh73a0_init_pm_domains(void) > +{ > + rmobile_init_domains(sh73a0_pm_domains, ARRAY_SIZE(sh73a0_pm_domains)); > + pm_genpd_add_subdomain_names("A4MP", "A3MP"); > + pm_genpd_add_subdomain_names("A4MP", "A3VC"); > + pm_genpd_add_subdomain_names("A4RM", "A3R"); > + pm_genpd_add_subdomain_names("A3R", "A2RV"); > + pm_genpd_add_subdomain_names("A4S", "A3SP"); > + pm_genpd_add_subdomain_names("A4S", "A3SG"); > + pm_genpd_add_subdomain_names("A4S", "A3SM"); > + pm_genpd_add_subdomain_names("A3SM", "A2SL"); > +} > +#endif /* CONFIG_PM && !CONFIG_ARCH_MULTIPLATFORM */ > > #ifdef CONFIG_SUSPEND > static int sh73a0_enter_suspend(suspend_state_t suspend_state) > diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c > index 93ebe3430bfe707a..2ec702c51dd25050 100644 > --- a/arch/arm/mach-shmobile/setup-sh73a0.c > +++ b/arch/arm/mach-shmobile/setup-sh73a0.c > @@ -39,6 +39,7 @@ > #include "dma-register.h" > #include "intc.h" > #include "irqs.h" > +#include "pm-rmobile.h" > #include "sh73a0.h" > > static struct map_desc sh73a0_io_desc[] __initdata = { > @@ -744,6 +745,30 @@ static struct platform_device *sh73a0_late_devices[] __initdata = { > &irqpin3_device, > }; > > +static struct pm_domain_device sh73a0_domain_devices[] __initdata = { > + { "A4MP", &mpdma0_device }, > + { "A3R", &tmu0_device }, > + { "A4S", &irqpin0_device }, > + { "A4S", &irqpin1_device }, > + { "A4S", &irqpin2_device }, > + { "A4S", &irqpin3_device }, > + { "A3SP", &dma0_device }, > + { "A3SP", &i2c0_device }, > + { "A3SP", &i2c1_device }, > + { "A3SP", &i2c2_device }, > + { "A3SP", &i2c3_device }, > + { "A3SP", &ipmmu_device }, > + { "A3SP", &scif0_device }, > + { "A3SP", &scif1_device }, > + { "A3SP", &scif2_device }, > + { "A3SP", &scif3_device }, > + { "A3SP", &scif4_device }, > + { "A3SP", &scif5_device }, > + { "A3SP", &scif6_device }, > + { "A3SP", &scif7_device }, > + { "A3SP", &scif8_device }, > +}; > + > #define SRCR2 IOMEM(0xe61580b0) > > void __init sh73a0_add_standard_devices(void) > @@ -751,10 +776,16 @@ void __init sh73a0_add_standard_devices(void) > /* Clear software reset bit on SY-DMAC module */ > __raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2); > > + sh73a0_init_pm_domains(); > + > platform_add_devices(sh73a0_early_devices, > ARRAY_SIZE(sh73a0_early_devices)); > platform_add_devices(sh73a0_late_devices, > ARRAY_SIZE(sh73a0_late_devices)); > + > + /* add devices to PM domain */ > + rmobile_add_devices_to_domains(sh73a0_domain_devices, > + ARRAY_SIZE(sh73a0_domain_devices)); > } > > /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ > diff --git a/arch/arm/mach-shmobile/sh73a0.h b/arch/arm/mach-shmobile/sh73a0.h > index f037c64b14fc0767..1a68a132bd516e00 100644 > --- a/arch/arm/mach-shmobile/sh73a0.h > +++ b/arch/arm/mach-shmobile/sh73a0.h > @@ -81,6 +81,13 @@ extern void sh73a0_add_standard_devices_dt(void); > extern void sh73a0_clock_init(void); > extern void sh73a0_pinmux_init(void); > extern void sh73a0_pm_init(void); > + > +#if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM) > +extern void sh73a0_init_pm_domains(void); > +#else > +static inline void sh73a0_init_pm_domains(void) {} > +#endif > + > extern struct clk sh73a0_extal1_clk; > extern struct clk sh73a0_extal2_clk; > extern struct clk sh73a0_extcki_clk; > -- > 1.9.1 > -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Simon, On Thu, Dec 4, 2014 at 8:36 AM, Simon Horman <horms@verge.net.au> wrote: > On Wed, Dec 03, 2014 at 03:20:21PM +0100, Geert Uytterhoeven wrote: >> Add all hierarchical PM domains that exist on SH-Mobile AG5 (sh730a), >> and register all platform devices to the appropriate PM domains. >> >> Special handling is required for the following PM domains: >> - A4BC0 and A4BC1 contain the SDRAM Bus State Controllers, and thus >> should not be turned off, >> - A3SP contains the serial console, and should not be turned off if >> no_console_suspend is set, >> - A2SL contains the CPU core, and should not be turned off if the CPU >> is in use. >> >> Note that PM domain D4 can be powered down without ill effects on s2ram >> behavior, just like on SH-Mobile AP4 (sh7372), but unlike on R-Mobile A1 >> (r8a7740). >> >> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> >> --- >> v2: >> - The smsc911x is not located in A4S (the Bus State Controller it is >> connected to is, but we don't cover that device in legacy code), >> - Move domain_devices[] next to tables with platform devices. > > In general I'm not adding new legacy board support. > I'm happy to make exceptions but its not obvious to me that this should > be one. So please just ignore this one. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index 7c9b63bdde9fa458..a4fbd02f1ddbdbc6 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -48,6 +48,7 @@ #include "common.h" #include "intc.h" #include "irqs.h" +#include "pm-rmobile.h" #include "sh73a0.h" /* @@ -798,6 +799,16 @@ static struct platform_device *kzm_devices[] __initdata = { &fsi_ak4648_device, }; +static struct pm_domain_device kzm_domain_devices[] __initdata = { + { "A4LC0", &lcdc_device }, + { "A4MP", &fsi_device }, + { "A4S", &usb_host_device }, + { "A3SP", &usbhs_device }, + { "A3SP", &mmc_device }, + { "A3SP", &sdhi0_device }, + { "A3SP", &sdhi2_device }, +}; + static unsigned long pin_pullup_conf[] = { PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0), }; @@ -888,6 +899,9 @@ static void __init kzm_init(void) sh73a0_add_standard_devices(); platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices)); + rmobile_add_devices_to_domains(kzm_domain_devices, + ARRAY_SIZE(kzm_domain_devices)); + sh73a0_pm_init(); } diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c index a7e466817965e3b8..06d2d98a355a0b70 100644 --- a/arch/arm/mach-shmobile/pm-sh73a0.c +++ b/arch/arm/mach-shmobile/pm-sh73a0.c @@ -2,14 +2,145 @@ * sh73a0 Power management support * * Copyright (C) 2012 Bastian Hecht <hechtb+renesas@gmail.com> + * Copyright (C) 2014 Glider bvba * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. */ +#include <linux/console.h> +#include <linux/io.h> #include <linux/suspend.h> + #include "common.h" +#include "pm-rmobile.h" + +#define SYSC_BASE IOMEM(0xe6180000) + +#if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM) +static int sh73a0_pd_a4bc_suspend(void) +{ + /* + * The A4BC0 and A4BC1 domains contain the SDRAM Bus State Controllers + * (SBSC1 and SBSC2) and therefore they should only be turned off if + * SDRAM is not in use. + */ + return -EBUSY; +} + +static int sh73a0_pd_a3sp_suspend(void) +{ + /* + * Serial consoles make use of SCIF hardware located in A3SP, + * keep such power domain on if "no_console_suspend" is set. + */ + return console_suspend_enabled ? 0 : -EBUSY; +} + +static int sh73a0_pd_a2sl_suspend(void) +{ + /* + * The A2SL domain contains the CPU core and therefore it should + * only be turned off if the CPU is not in use. + */ + return -EBUSY; +} + +static struct rmobile_pm_domain sh73a0_pm_domains[] = { + { + .genpd.name = "C4", + .base = SYSC_BASE, + .bit_shift = 0, + }, { + .genpd.name = "D4", + .base = SYSC_BASE, + .bit_shift = 1, + }, { + .genpd.name = "A4BC0", + .base = SYSC_BASE, + .bit_shift = 4, + .gov = &pm_domain_always_on_gov, + .suspend = sh73a0_pd_a4bc_suspend, + }, { + .genpd.name = "A4BC1", + .base = SYSC_BASE, + .bit_shift = 5, + .gov = &pm_domain_always_on_gov, + .suspend = sh73a0_pd_a4bc_suspend, + }, { + .genpd.name = "A4LC0", + .base = SYSC_BASE, + .bit_shift = 6, + }, { + .genpd.name = "A4LC1", + .base = SYSC_BASE, + .bit_shift = 7, + }, { + .genpd.name = "A4MP", + .base = SYSC_BASE, + .bit_shift = 8, + }, { + .genpd.name = "A3MP", + .base = SYSC_BASE, + .bit_shift = 9, + }, { + .genpd.name = "A3VC", + .base = SYSC_BASE, + .bit_shift = 10, + }, { + .genpd.name = "A4RM", + .base = SYSC_BASE, + .bit_shift = 12, + }, { + .genpd.name = "A3R", + .base = SYSC_BASE, + .bit_shift = 13, + }, { + .genpd.name = "A2RV", + .base = SYSC_BASE, + .bit_shift = 14, + }, { + .genpd.name = "A4S", + .base = SYSC_BASE, + .bit_shift = 16, + }, { + .genpd.name = "A3SP", + .base = SYSC_BASE, + .bit_shift = 17, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = sh73a0_pd_a3sp_suspend, + }, { + .genpd.name = "A3SG", + .base = SYSC_BASE, + .bit_shift = 18, + }, { + .genpd.name = "A3SM", + .base = SYSC_BASE, + .bit_shift = 19, + }, { + .genpd.name = "A2SL", + .base = SYSC_BASE, + .bit_shift = 20, + .gov = &pm_domain_always_on_gov, + .suspend = sh73a0_pd_a2sl_suspend, + } +}; + +void __init sh73a0_init_pm_domains(void) +{ + rmobile_init_domains(sh73a0_pm_domains, ARRAY_SIZE(sh73a0_pm_domains)); + pm_genpd_add_subdomain_names("A4MP", "A3MP"); + pm_genpd_add_subdomain_names("A4MP", "A3VC"); + pm_genpd_add_subdomain_names("A4RM", "A3R"); + pm_genpd_add_subdomain_names("A3R", "A2RV"); + pm_genpd_add_subdomain_names("A4S", "A3SP"); + pm_genpd_add_subdomain_names("A4S", "A3SG"); + pm_genpd_add_subdomain_names("A4S", "A3SM"); + pm_genpd_add_subdomain_names("A3SM", "A2SL"); +} +#endif /* CONFIG_PM && !CONFIG_ARCH_MULTIPLATFORM */ #ifdef CONFIG_SUSPEND static int sh73a0_enter_suspend(suspend_state_t suspend_state) diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index 93ebe3430bfe707a..2ec702c51dd25050 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -39,6 +39,7 @@ #include "dma-register.h" #include "intc.h" #include "irqs.h" +#include "pm-rmobile.h" #include "sh73a0.h" static struct map_desc sh73a0_io_desc[] __initdata = { @@ -744,6 +745,30 @@ static struct platform_device *sh73a0_late_devices[] __initdata = { &irqpin3_device, }; +static struct pm_domain_device sh73a0_domain_devices[] __initdata = { + { "A4MP", &mpdma0_device }, + { "A3R", &tmu0_device }, + { "A4S", &irqpin0_device }, + { "A4S", &irqpin1_device }, + { "A4S", &irqpin2_device }, + { "A4S", &irqpin3_device }, + { "A3SP", &dma0_device }, + { "A3SP", &i2c0_device }, + { "A3SP", &i2c1_device }, + { "A3SP", &i2c2_device }, + { "A3SP", &i2c3_device }, + { "A3SP", &ipmmu_device }, + { "A3SP", &scif0_device }, + { "A3SP", &scif1_device }, + { "A3SP", &scif2_device }, + { "A3SP", &scif3_device }, + { "A3SP", &scif4_device }, + { "A3SP", &scif5_device }, + { "A3SP", &scif6_device }, + { "A3SP", &scif7_device }, + { "A3SP", &scif8_device }, +}; + #define SRCR2 IOMEM(0xe61580b0) void __init sh73a0_add_standard_devices(void) @@ -751,10 +776,16 @@ void __init sh73a0_add_standard_devices(void) /* Clear software reset bit on SY-DMAC module */ __raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2); + sh73a0_init_pm_domains(); + platform_add_devices(sh73a0_early_devices, ARRAY_SIZE(sh73a0_early_devices)); platform_add_devices(sh73a0_late_devices, ARRAY_SIZE(sh73a0_late_devices)); + + /* add devices to PM domain */ + rmobile_add_devices_to_domains(sh73a0_domain_devices, + ARRAY_SIZE(sh73a0_domain_devices)); } /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ diff --git a/arch/arm/mach-shmobile/sh73a0.h b/arch/arm/mach-shmobile/sh73a0.h index f037c64b14fc0767..1a68a132bd516e00 100644 --- a/arch/arm/mach-shmobile/sh73a0.h +++ b/arch/arm/mach-shmobile/sh73a0.h @@ -81,6 +81,13 @@ extern void sh73a0_add_standard_devices_dt(void); extern void sh73a0_clock_init(void); extern void sh73a0_pinmux_init(void); extern void sh73a0_pm_init(void); + +#if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM) +extern void sh73a0_init_pm_domains(void); +#else +static inline void sh73a0_init_pm_domains(void) {} +#endif + extern struct clk sh73a0_extal1_clk; extern struct clk sh73a0_extal2_clk; extern struct clk sh73a0_extcki_clk;
Add all hierarchical PM domains that exist on SH-Mobile AG5 (sh730a), and register all platform devices to the appropriate PM domains. Special handling is required for the following PM domains: - A4BC0 and A4BC1 contain the SDRAM Bus State Controllers, and thus should not be turned off, - A3SP contains the serial console, and should not be turned off if no_console_suspend is set, - A2SL contains the CPU core, and should not be turned off if the CPU is in use. Note that PM domain D4 can be powered down without ill effects on s2ram behavior, just like on SH-Mobile AP4 (sh7372), but unlike on R-Mobile A1 (r8a7740). Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> --- v2: - The smsc911x is not located in A4S (the Bus State Controller it is connected to is, but we don't cover that device in legacy code), - Move domain_devices[] next to tables with platform devices. --- arch/arm/mach-shmobile/board-kzm9g.c | 14 ++++ arch/arm/mach-shmobile/pm-sh73a0.c | 131 ++++++++++++++++++++++++++++++++++ arch/arm/mach-shmobile/setup-sh73a0.c | 31 ++++++++ arch/arm/mach-shmobile/sh73a0.h | 7 ++ 4 files changed, 183 insertions(+)