From dc3005703f8cd893d325081c20b400e08377d9bb Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 13 Jan 2022 16:48:51 +0200 Subject: ARM: at91: ddr: remove CONFIG_SOC_SAMA7 dependency Remove CONFIG_SOC_SAMA7 dependency to avoid having #ifdef preprocessor directives in driver code (arch/arm/mach-at91/pm.c). This prepares the code for next commits. Signed-off-by: Claudiu Beznea Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/20220113144900.906370-2-claudiu.beznea@microchip.com --- include/soc/at91/sama7-ddr.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/soc/at91/sama7-ddr.h b/include/soc/at91/sama7-ddr.h index f6542584ca13..13b47e26cdbe 100644 --- a/include/soc/at91/sama7-ddr.h +++ b/include/soc/at91/sama7-ddr.h @@ -11,8 +11,6 @@ #ifndef __SAMA7_DDR_H__ #define __SAMA7_DDR_H__ -#ifdef CONFIG_SOC_SAMA7 - /* DDR3PHY */ #define DDR3PHY_PIR (0x04) /* DDR3PHY PHY Initialization Register */ #define DDR3PHY_PIR_DLLBYP (1 << 17) /* DLL Bypass */ @@ -75,6 +73,4 @@ #define UDDRC_PCTRL_3 (0x6A0) /* UDDRC Port 3 Control Register */ #define UDDRC_PCTRL_4 (0x750) /* UDDRC Port 4 Control Register */ -#endif /* CONFIG_SOC_SAMA7 */ - #endif /* __SAMA7_DDR_H__ */ -- cgit v1.2.3 From 55614e682a2c9fac12a0f121b43b93ff4915d0e6 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 13 Jan 2022 16:48:52 +0200 Subject: ARM: at91: ddr: align macro definitions Align all macro definitions. Signed-off-by: Claudiu Beznea Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/20220113144900.906370-3-claudiu.beznea@microchip.com --- include/soc/at91/sama7-ddr.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/soc/at91/sama7-ddr.h b/include/soc/at91/sama7-ddr.h index 13b47e26cdbe..817b360efbb8 100644 --- a/include/soc/at91/sama7-ddr.h +++ b/include/soc/at91/sama7-ddr.h @@ -13,11 +13,11 @@ /* DDR3PHY */ #define DDR3PHY_PIR (0x04) /* DDR3PHY PHY Initialization Register */ -#define DDR3PHY_PIR_DLLBYP (1 << 17) /* DLL Bypass */ +#define DDR3PHY_PIR_DLLBYP (1 << 17) /* DLL Bypass */ #define DDR3PHY_PIR_ITMSRST (1 << 4) /* Interface Timing Module Soft Reset */ -#define DDR3PHY_PIR_DLLLOCK (1 << 2) /* DLL Lock */ +#define DDR3PHY_PIR_DLLLOCK (1 << 2) /* DLL Lock */ #define DDR3PHY_PIR_DLLSRST (1 << 1) /* DLL Soft Rest */ -#define DDR3PHY_PIR_INIT (1 << 0) /* Initialization Trigger */ +#define DDR3PHY_PIR_INIT (1 << 0) /* Initialization Trigger */ #define DDR3PHY_PGCR (0x08) /* DDR3PHY PHY General Configuration Register */ #define DDR3PHY_PGCR_CKDV1 (1 << 13) /* CK# Disable Value */ @@ -65,7 +65,7 @@ #define UDDRC_SWSTAT_SW_DONE_ACK (1 << 0) /* Register programming done */ #define UDDRC_PSTAT (0x3FC) /* UDDRC Port Status Register */ -#define UDDRC_PSTAT_ALL_PORTS (0x1F001F) /* Read + writes outstanding transactions on all ports */ +#define UDDRC_PSTAT_ALL_PORTS (0x1F001F) /* Read + writes outstanding transactions on all ports */ #define UDDRC_PCTRL_0 (0x490) /* UDDRC Port 0 Control Register */ #define UDDRC_PCTRL_1 (0x540) /* UDDRC Port 1 Control Register */ -- cgit v1.2.3 From 9a0775c9cd3d89d1fe957a137131681a33f5736b Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 13 Jan 2022 16:48:53 +0200 Subject: ARM: at91: ddr: fix typo to align with datasheet naming Fix typo on UDDRC_PWRCTL.SELFREF_SW bitmask to align with datasheet naming. Signed-off-by: Claudiu Beznea Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/20220113144900.906370-4-claudiu.beznea@microchip.com --- arch/arm/mach-at91/pm_suspend.S | 4 ++-- include/soc/at91/sama7-ddr.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index fdb4f63ecde4..abe4ced33eda 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -159,7 +159,7 @@ sr_ena_1: /* Switch to self-refresh. */ ldr tmp1, [r2, #UDDRC_PWRCTL] - orr tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW + orr tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW str tmp1, [r2, #UDDRC_PWRCTL] sr_ena_2: @@ -276,7 +276,7 @@ sr_dis_5: /* Trigger self-refresh exit. */ ldr tmp1, [r2, #UDDRC_PWRCTL] - bic tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW + bic tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW str tmp1, [r2, #UDDRC_PWRCTL] sr_dis_6: diff --git a/include/soc/at91/sama7-ddr.h b/include/soc/at91/sama7-ddr.h index 817b360efbb8..fee1b11bddca 100644 --- a/include/soc/at91/sama7-ddr.h +++ b/include/soc/at91/sama7-ddr.h @@ -53,7 +53,7 @@ #define UDDRC_STAT_OPMODE_MSK (0x7 << 0) /* Operating mode mask */ #define UDDRC_PWRCTL (0x30) /* UDDRC Low Power Control Register */ -#define UDDRC_PWRCTRL_SELFREF_SW (1 << 5) /* Software self-refresh */ +#define UDDRC_PWRCTL_SELFREF_SW (1 << 5) /* Software self-refresh */ #define UDDRC_DFIMISC (0x1B0) /* UDDRC DFI Miscellaneous Control Register */ #define UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN (1 << 0) /* PHY initialization complete enable signal */ -- cgit v1.2.3 From 9584e7263e9ebcd94b184dc3efc847355a624220 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 13 Jan 2022 16:48:54 +0200 Subject: ARM: at91: PM: add cpu idle support for sama7g5 Add CPU idle support for SAMA7G5. Support will make use of PMC_CPU_RATIO register to divide the CPU clock by 16 before switching it to idle and use automatic self-refresh option of DDR controller. Signed-off-by: Claudiu Beznea Acked-by: Stephen Boyd Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/20220113144900.906370-5-claudiu.beznea@microchip.com --- arch/arm/mach-at91/pm.c | 27 ++++++++++++++++++++++++++- include/linux/clk/at91_pmc.h | 4 ++++ include/soc/at91/sama7-ddr.h | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index dd6f4ce3f766..0fd609e26615 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -605,6 +605,30 @@ static void at91sam9_sdram_standby(void) at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); } +static void sama7g5_standby(void) +{ + int pwrtmg, ratio; + + pwrtmg = readl(soc_pm.data.ramc[0] + UDDRC_PWRCTL); + ratio = readl(soc_pm.data.pmc + AT91_PMC_RATIO); + + /* + * Place RAM into self-refresh after a maximum idle clocks. The maximum + * idle clocks is configured by bootloader in + * UDDRC_PWRMGT.SELFREF_TO_X32. + */ + writel(pwrtmg | UDDRC_PWRCTL_SELFREF_EN, + soc_pm.data.ramc[0] + UDDRC_PWRCTL); + /* Divide CPU clock by 16. */ + writel(ratio & ~AT91_PMC_RATIO_RATIO, soc_pm.data.pmc + AT91_PMC_RATIO); + + cpu_do_idle(); + + /* Restore previous configuration. */ + writel(ratio, soc_pm.data.pmc + AT91_PMC_RATIO); + writel(pwrtmg, soc_pm.data.ramc[0] + UDDRC_PWRCTL); +} + struct ramc_info { void (*idle)(void); unsigned int memctrl; @@ -615,6 +639,7 @@ static const struct ramc_info ramc_infos[] __initconst = { { .idle = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC}, { .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR}, { .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR}, + { .idle = sama7g5_standby, }, }; static const struct of_device_id ramc_ids[] __initconst = { @@ -622,7 +647,7 @@ static const struct of_device_id ramc_ids[] __initconst = { { .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] }, { .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] }, { .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] }, - { .compatible = "microchip,sama7g5-uddrc", }, + { .compatible = "microchip,sama7g5-uddrc", .data = &ramc_infos[4], }, { /*sentinel*/ } }; diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h index ccb3f034bfa9..3484309b59bf 100644 --- a/include/linux/clk/at91_pmc.h +++ b/include/linux/clk/at91_pmc.h @@ -78,6 +78,10 @@ #define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */ #define AT91_CKGR_PLLAR 0x28 /* PLL A Register */ + +#define AT91_PMC_RATIO 0x2c /* Processor clock ratio register [SAMA7G5 only] */ +#define AT91_PMC_RATIO_RATIO (0xf) /* CPU clock ratio. */ + #define AT91_CKGR_PLLBR 0x2c /* PLL B Register */ #define AT91_PMC_DIV (0xff << 0) /* Divider */ #define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */ diff --git a/include/soc/at91/sama7-ddr.h b/include/soc/at91/sama7-ddr.h index fee1b11bddca..9e17247474fa 100644 --- a/include/soc/at91/sama7-ddr.h +++ b/include/soc/at91/sama7-ddr.h @@ -53,6 +53,7 @@ #define UDDRC_STAT_OPMODE_MSK (0x7 << 0) /* Operating mode mask */ #define UDDRC_PWRCTL (0x30) /* UDDRC Low Power Control Register */ +#define UDDRC_PWRCTL_SELFREF_EN (1 << 0) /* Automatic self-refresh */ #define UDDRC_PWRCTL_SELFREF_SW (1 << 5) /* Software self-refresh */ #define UDDRC_DFIMISC (0x1B0) /* UDDRC DFI Miscellaneous Control Register */ -- cgit v1.2.3 From f8e0f301c46112a15d0b9ab792602875f00010ef Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 13 Jan 2022 16:48:55 +0200 Subject: ARM: at91: Kconfig: select PM_OPP Select PM_OPP. This is requested for CPUFreq driver. Signed-off-by: Claudiu Beznea Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/20220113144900.906370-6-claudiu.beznea@microchip.com --- arch/arm/mach-at91/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 02f6b108fd5d..279810381256 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -63,6 +63,7 @@ config SOC_SAMA7G5 select HAVE_AT91_GENERATED_CLK select HAVE_AT91_SAM9X60_PLL select HAVE_AT91_UTMI + select PM_OPP select SOC_SAMA7 help Select this if you are using one of Microchip's SAMA7G5 family SoC. -- cgit v1.2.3 From d0054a470c33902f5ae88835ed8a8ecc3cf8faa4 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Thu, 17 Feb 2022 10:13:50 +0000 Subject: soc: add microchip polarfire soc system controller This driver provides an interface for other drivers to access the functions of the system controller on the Microchip PolarFire SoC. Signed-off-by: Conor Dooley Signed-off-by: Nicolas Ferre Link: https://lore.kernel.org/r/20220217101349.2374873-2-conor.dooley@microchip.com --- drivers/soc/Kconfig | 1 + drivers/soc/Makefile | 1 + drivers/soc/microchip/Kconfig | 10 ++ drivers/soc/microchip/Makefile | 1 + drivers/soc/microchip/mpfs-sys-controller.c | 194 ++++++++++++++++++++++++++++ include/soc/microchip/mpfs.h | 4 +- 6 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 drivers/soc/microchip/Kconfig create mode 100644 drivers/soc/microchip/Makefile create mode 100644 drivers/soc/microchip/mpfs-sys-controller.c diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index a8562678c437..c5aae42673d3 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -13,6 +13,7 @@ source "drivers/soc/imx/Kconfig" source "drivers/soc/ixp4xx/Kconfig" source "drivers/soc/litex/Kconfig" source "drivers/soc/mediatek/Kconfig" +source "drivers/soc/microchip/Kconfig" source "drivers/soc/qcom/Kconfig" source "drivers/soc/renesas/Kconfig" source "drivers/soc/rockchip/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index adb30c2d4fea..904eec2a7871 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -18,6 +18,7 @@ obj-y += ixp4xx/ obj-$(CONFIG_SOC_XWAY) += lantiq/ obj-$(CONFIG_LITEX_SOC_CONTROLLER) += litex/ obj-y += mediatek/ +obj-y += microchip/ obj-y += amlogic/ obj-y += qcom/ obj-y += renesas/ diff --git a/drivers/soc/microchip/Kconfig b/drivers/soc/microchip/Kconfig new file mode 100644 index 000000000000..eb656b33156b --- /dev/null +++ b/drivers/soc/microchip/Kconfig @@ -0,0 +1,10 @@ +config POLARFIRE_SOC_SYS_CTRL + tristate "POLARFIRE_SOC_SYS_CTRL" + depends on POLARFIRE_SOC_MAILBOX + help + This driver adds support for the PolarFire SoC (MPFS) system controller. + + To compile this driver as a module, choose M here. the + module will be called mpfs_system_controller. + + If unsure, say N. diff --git a/drivers/soc/microchip/Makefile b/drivers/soc/microchip/Makefile new file mode 100644 index 000000000000..14489919fe4b --- /dev/null +++ b/drivers/soc/microchip/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_POLARFIRE_SOC_SYS_CTRL) += mpfs-sys-controller.o diff --git a/drivers/soc/microchip/mpfs-sys-controller.c b/drivers/soc/microchip/mpfs-sys-controller.c new file mode 100644 index 000000000000..2f4535929762 --- /dev/null +++ b/drivers/soc/microchip/mpfs-sys-controller.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Microchip PolarFire SoC (MPFS) system controller driver + * + * Copyright (c) 2020-2021 Microchip Corporation. All rights reserved. + * + * Author: Conor Dooley + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_MUTEX(transaction_lock); + +struct mpfs_sys_controller { + struct mbox_client client; + struct mbox_chan *chan; + struct completion c; + struct kref consumers; +}; + +int mpfs_blocking_transaction(struct mpfs_sys_controller *sys_controller, struct mpfs_mss_msg *msg) +{ + int ret, err; + + err = mutex_lock_interruptible(&transaction_lock); + if (err) + return err; + + reinit_completion(&sys_controller->c); + + ret = mbox_send_message(sys_controller->chan, msg); + if (ret >= 0) { + if (wait_for_completion_timeout(&sys_controller->c, HZ)) { + ret = 0; + } else { + ret = -ETIMEDOUT; + dev_warn(sys_controller->client.dev, + "MPFS sys controller transaction timeout\n"); + } + } else { + dev_err(sys_controller->client.dev, + "mpfs sys controller transaction returned %d\n", ret); + } + + mutex_unlock(&transaction_lock); + + return ret; +} +EXPORT_SYMBOL(mpfs_blocking_transaction); + +static void rx_callback(struct mbox_client *client, void *msg) +{ + struct mpfs_sys_controller *sys_controller = + container_of(client, struct mpfs_sys_controller, client); + + complete(&sys_controller->c); +} + +static void mpfs_sys_controller_delete(struct kref *kref) +{ + struct mpfs_sys_controller *sys_controller = container_of(kref, struct mpfs_sys_controller, + consumers); + + mbox_free_channel(sys_controller->chan); + kfree(sys_controller); +} + +void mpfs_sys_controller_put(void *data) +{ + struct mpfs_sys_controller *sys_controller = data; + + kref_put(&sys_controller->consumers, mpfs_sys_controller_delete); +} +EXPORT_SYMBOL(mpfs_sys_controller_put); + +static struct platform_device subdevs[] = { + { + .name = "mpfs-rng", + .id = -1, + }, + { + .name = "mpfs-generic-service", + .id = -1, + } +}; + +static int mpfs_sys_controller_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mpfs_sys_controller *sys_controller; + int i; + + sys_controller = devm_kzalloc(dev, sizeof(*sys_controller), GFP_KERNEL); + if (!sys_controller) + return -ENOMEM; + + sys_controller->client.dev = dev; + sys_controller->client.rx_callback = rx_callback; + sys_controller->client.tx_block = 1U; + + sys_controller->chan = mbox_request_channel(&sys_controller->client, 0); + if (IS_ERR(sys_controller->chan)) + return dev_err_probe(dev, PTR_ERR(sys_controller->chan), + "Failed to get mbox channel\n"); + + init_completion(&sys_controller->c); + kref_init(&sys_controller->consumers); + + platform_set_drvdata(pdev, sys_controller); + + dev_info(&pdev->dev, "Registered MPFS system controller\n"); + + for (i = 0; i < ARRAY_SIZE(subdevs); i++) { + subdevs[i].dev.parent = dev; + if (platform_device_register(&subdevs[i])) + dev_warn(dev, "Error registering sub device %s\n", subdevs[i].name); + } + + return 0; +} + +static int mpfs_sys_controller_remove(struct platform_device *pdev) +{ + struct mpfs_sys_controller *sys_controller = platform_get_drvdata(pdev); + + mpfs_sys_controller_put(sys_controller); + + return 0; +} + +static const struct of_device_id mpfs_sys_controller_of_match[] = { + {.compatible = "microchip,mpfs-sys-controller", }, + {}, +}; +MODULE_DEVICE_TABLE(of, mpfs_sys_controller_of_match); + +struct mpfs_sys_controller *mpfs_sys_controller_get(struct device *dev) +{ + const struct of_device_id *match; + struct mpfs_sys_controller *sys_controller; + int ret; + + if (!dev->parent) + goto err_no_device; + + match = of_match_node(mpfs_sys_controller_of_match, dev->parent->of_node); + of_node_put(dev->parent->of_node); + if (!match) + goto err_no_device; + + sys_controller = dev_get_drvdata(dev->parent); + if (!sys_controller) + goto err_bad_device; + + if (!kref_get_unless_zero(&sys_controller->consumers)) + goto err_bad_device; + + ret = devm_add_action_or_reset(dev, mpfs_sys_controller_put, sys_controller); + if (ret) + return ERR_PTR(ret); + + return sys_controller; + +err_no_device: + dev_dbg(dev, "Parent device was not an MPFS system controller\n"); + return ERR_PTR(-ENODEV); + +err_bad_device: + dev_dbg(dev, "MPFS system controller found but could not register as a sub device\n"); + return ERR_PTR(-EPROBE_DEFER); +} +EXPORT_SYMBOL(mpfs_sys_controller_get); + +static struct platform_driver mpfs_sys_controller_driver = { + .driver = { + .name = "mpfs-sys-controller", + .of_match_table = mpfs_sys_controller_of_match, + }, + .probe = mpfs_sys_controller_probe, + .remove = mpfs_sys_controller_remove, +}; +module_platform_driver(mpfs_sys_controller_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Conor Dooley "); +MODULE_DESCRIPTION("MPFS system controller driver"); diff --git a/include/soc/microchip/mpfs.h b/include/soc/microchip/mpfs.h index 2b64c95f3be5..6466515262bd 100644 --- a/include/soc/microchip/mpfs.h +++ b/include/soc/microchip/mpfs.h @@ -34,9 +34,9 @@ struct mpfs_mss_response { #if IS_ENABLED(CONFIG_POLARFIRE_SOC_SYS_CTRL) -int mpfs_blocking_transaction(struct mpfs_sys_controller *mpfs_client, void *msg); +int mpfs_blocking_transaction(struct mpfs_sys_controller *mpfs_client, struct mpfs_mss_msg *msg); -struct mpfs_sys_controller *mpfs_sys_controller_get(struct device_node *mailbox_node); +struct mpfs_sys_controller *mpfs_sys_controller_get(struct device *dev); #endif /* if IS_ENABLED(CONFIG_POLARFIRE_SOC_SYS_CTRL) */ -- cgit v1.2.3