Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'at91-soc-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux into arm/soc

AT91 & POLARFIRE SoC #1 for 5.18:

- sama7g5: CPU idle support with CPUFreq operating points defined in DT
- polarfire: addition of the soc system controller

* tag 'at91-soc-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux:
soc: add microchip polarfire soc system controller
ARM: at91: Kconfig: select PM_OPP
ARM: at91: PM: add cpu idle support for sama7g5
ARM: at91: ddr: fix typo to align with datasheet naming
ARM: at91: ddr: align macro definitions
ARM: at91: ddr: remove CONFIG_SOC_SAMA7 dependency

Link: https://lore.kernel.org/r/20220225121943.71494-1-nicolas.ferre@microchip.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+248 -14
+1
arch/arm/mach-at91/Kconfig
··· 63 63 select HAVE_AT91_GENERATED_CLK 64 64 select HAVE_AT91_SAM9X60_PLL 65 65 select HAVE_AT91_UTMI 66 + select PM_OPP 66 67 select SOC_SAMA7 67 68 help 68 69 Select this if you are using one of Microchip's SAMA7G5 family SoC.
+26 -1
arch/arm/mach-at91/pm.c
··· 605 605 at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); 606 606 } 607 607 608 + static void sama7g5_standby(void) 609 + { 610 + int pwrtmg, ratio; 611 + 612 + pwrtmg = readl(soc_pm.data.ramc[0] + UDDRC_PWRCTL); 613 + ratio = readl(soc_pm.data.pmc + AT91_PMC_RATIO); 614 + 615 + /* 616 + * Place RAM into self-refresh after a maximum idle clocks. The maximum 617 + * idle clocks is configured by bootloader in 618 + * UDDRC_PWRMGT.SELFREF_TO_X32. 619 + */ 620 + writel(pwrtmg | UDDRC_PWRCTL_SELFREF_EN, 621 + soc_pm.data.ramc[0] + UDDRC_PWRCTL); 622 + /* Divide CPU clock by 16. */ 623 + writel(ratio & ~AT91_PMC_RATIO_RATIO, soc_pm.data.pmc + AT91_PMC_RATIO); 624 + 625 + cpu_do_idle(); 626 + 627 + /* Restore previous configuration. */ 628 + writel(ratio, soc_pm.data.pmc + AT91_PMC_RATIO); 629 + writel(pwrtmg, soc_pm.data.ramc[0] + UDDRC_PWRCTL); 630 + } 631 + 608 632 struct ramc_info { 609 633 void (*idle)(void); 610 634 unsigned int memctrl; ··· 639 615 { .idle = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC}, 640 616 { .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR}, 641 617 { .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR}, 618 + { .idle = sama7g5_standby, }, 642 619 }; 643 620 644 621 static const struct of_device_id ramc_ids[] __initconst = { ··· 647 622 { .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] }, 648 623 { .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] }, 649 624 { .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] }, 650 - { .compatible = "microchip,sama7g5-uddrc", }, 625 + { .compatible = "microchip,sama7g5-uddrc", .data = &ramc_infos[4], }, 651 626 { /*sentinel*/ } 652 627 }; 653 628
+2 -2
arch/arm/mach-at91/pm_suspend.S
··· 159 159 160 160 /* Switch to self-refresh. */ 161 161 ldr tmp1, [r2, #UDDRC_PWRCTL] 162 - orr tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW 162 + orr tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW 163 163 str tmp1, [r2, #UDDRC_PWRCTL] 164 164 165 165 sr_ena_2: ··· 276 276 277 277 /* Trigger self-refresh exit. */ 278 278 ldr tmp1, [r2, #UDDRC_PWRCTL] 279 - bic tmp1, tmp1, #UDDRC_PWRCTRL_SELFREF_SW 279 + bic tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW 280 280 str tmp1, [r2, #UDDRC_PWRCTL] 281 281 282 282 sr_dis_6:
+1
drivers/soc/Kconfig
··· 13 13 source "drivers/soc/ixp4xx/Kconfig" 14 14 source "drivers/soc/litex/Kconfig" 15 15 source "drivers/soc/mediatek/Kconfig" 16 + source "drivers/soc/microchip/Kconfig" 16 17 source "drivers/soc/qcom/Kconfig" 17 18 source "drivers/soc/renesas/Kconfig" 18 19 source "drivers/soc/rockchip/Kconfig"
+1
drivers/soc/Makefile
··· 18 18 obj-$(CONFIG_SOC_XWAY) += lantiq/ 19 19 obj-$(CONFIG_LITEX_SOC_CONTROLLER) += litex/ 20 20 obj-y += mediatek/ 21 + obj-y += microchip/ 21 22 obj-y += amlogic/ 22 23 obj-y += qcom/ 23 24 obj-y += renesas/
+10
drivers/soc/microchip/Kconfig
··· 1 + config POLARFIRE_SOC_SYS_CTRL 2 + tristate "POLARFIRE_SOC_SYS_CTRL" 3 + depends on POLARFIRE_SOC_MAILBOX 4 + help 5 + This driver adds support for the PolarFire SoC (MPFS) system controller. 6 + 7 + To compile this driver as a module, choose M here. the 8 + module will be called mpfs_system_controller. 9 + 10 + If unsure, say N.
+1
drivers/soc/microchip/Makefile
··· 1 + obj-$(CONFIG_POLARFIRE_SOC_SYS_CTRL) += mpfs-sys-controller.o
+194
drivers/soc/microchip/mpfs-sys-controller.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Microchip PolarFire SoC (MPFS) system controller driver 4 + * 5 + * Copyright (c) 2020-2021 Microchip Corporation. All rights reserved. 6 + * 7 + * Author: Conor Dooley <conor.dooley@microchip.com> 8 + * 9 + */ 10 + 11 + #include <linux/slab.h> 12 + #include <linux/kref.h> 13 + #include <linux/module.h> 14 + #include <linux/interrupt.h> 15 + #include <linux/of_platform.h> 16 + #include <linux/mailbox_client.h> 17 + #include <linux/platform_device.h> 18 + #include <soc/microchip/mpfs.h> 19 + 20 + static DEFINE_MUTEX(transaction_lock); 21 + 22 + struct mpfs_sys_controller { 23 + struct mbox_client client; 24 + struct mbox_chan *chan; 25 + struct completion c; 26 + struct kref consumers; 27 + }; 28 + 29 + int mpfs_blocking_transaction(struct mpfs_sys_controller *sys_controller, struct mpfs_mss_msg *msg) 30 + { 31 + int ret, err; 32 + 33 + err = mutex_lock_interruptible(&transaction_lock); 34 + if (err) 35 + return err; 36 + 37 + reinit_completion(&sys_controller->c); 38 + 39 + ret = mbox_send_message(sys_controller->chan, msg); 40 + if (ret >= 0) { 41 + if (wait_for_completion_timeout(&sys_controller->c, HZ)) { 42 + ret = 0; 43 + } else { 44 + ret = -ETIMEDOUT; 45 + dev_warn(sys_controller->client.dev, 46 + "MPFS sys controller transaction timeout\n"); 47 + } 48 + } else { 49 + dev_err(sys_controller->client.dev, 50 + "mpfs sys controller transaction returned %d\n", ret); 51 + } 52 + 53 + mutex_unlock(&transaction_lock); 54 + 55 + return ret; 56 + } 57 + EXPORT_SYMBOL(mpfs_blocking_transaction); 58 + 59 + static void rx_callback(struct mbox_client *client, void *msg) 60 + { 61 + struct mpfs_sys_controller *sys_controller = 62 + container_of(client, struct mpfs_sys_controller, client); 63 + 64 + complete(&sys_controller->c); 65 + } 66 + 67 + static void mpfs_sys_controller_delete(struct kref *kref) 68 + { 69 + struct mpfs_sys_controller *sys_controller = container_of(kref, struct mpfs_sys_controller, 70 + consumers); 71 + 72 + mbox_free_channel(sys_controller->chan); 73 + kfree(sys_controller); 74 + } 75 + 76 + void mpfs_sys_controller_put(void *data) 77 + { 78 + struct mpfs_sys_controller *sys_controller = data; 79 + 80 + kref_put(&sys_controller->consumers, mpfs_sys_controller_delete); 81 + } 82 + EXPORT_SYMBOL(mpfs_sys_controller_put); 83 + 84 + static struct platform_device subdevs[] = { 85 + { 86 + .name = "mpfs-rng", 87 + .id = -1, 88 + }, 89 + { 90 + .name = "mpfs-generic-service", 91 + .id = -1, 92 + } 93 + }; 94 + 95 + static int mpfs_sys_controller_probe(struct platform_device *pdev) 96 + { 97 + struct device *dev = &pdev->dev; 98 + struct mpfs_sys_controller *sys_controller; 99 + int i; 100 + 101 + sys_controller = devm_kzalloc(dev, sizeof(*sys_controller), GFP_KERNEL); 102 + if (!sys_controller) 103 + return -ENOMEM; 104 + 105 + sys_controller->client.dev = dev; 106 + sys_controller->client.rx_callback = rx_callback; 107 + sys_controller->client.tx_block = 1U; 108 + 109 + sys_controller->chan = mbox_request_channel(&sys_controller->client, 0); 110 + if (IS_ERR(sys_controller->chan)) 111 + return dev_err_probe(dev, PTR_ERR(sys_controller->chan), 112 + "Failed to get mbox channel\n"); 113 + 114 + init_completion(&sys_controller->c); 115 + kref_init(&sys_controller->consumers); 116 + 117 + platform_set_drvdata(pdev, sys_controller); 118 + 119 + dev_info(&pdev->dev, "Registered MPFS system controller\n"); 120 + 121 + for (i = 0; i < ARRAY_SIZE(subdevs); i++) { 122 + subdevs[i].dev.parent = dev; 123 + if (platform_device_register(&subdevs[i])) 124 + dev_warn(dev, "Error registering sub device %s\n", subdevs[i].name); 125 + } 126 + 127 + return 0; 128 + } 129 + 130 + static int mpfs_sys_controller_remove(struct platform_device *pdev) 131 + { 132 + struct mpfs_sys_controller *sys_controller = platform_get_drvdata(pdev); 133 + 134 + mpfs_sys_controller_put(sys_controller); 135 + 136 + return 0; 137 + } 138 + 139 + static const struct of_device_id mpfs_sys_controller_of_match[] = { 140 + {.compatible = "microchip,mpfs-sys-controller", }, 141 + {}, 142 + }; 143 + MODULE_DEVICE_TABLE(of, mpfs_sys_controller_of_match); 144 + 145 + struct mpfs_sys_controller *mpfs_sys_controller_get(struct device *dev) 146 + { 147 + const struct of_device_id *match; 148 + struct mpfs_sys_controller *sys_controller; 149 + int ret; 150 + 151 + if (!dev->parent) 152 + goto err_no_device; 153 + 154 + match = of_match_node(mpfs_sys_controller_of_match, dev->parent->of_node); 155 + of_node_put(dev->parent->of_node); 156 + if (!match) 157 + goto err_no_device; 158 + 159 + sys_controller = dev_get_drvdata(dev->parent); 160 + if (!sys_controller) 161 + goto err_bad_device; 162 + 163 + if (!kref_get_unless_zero(&sys_controller->consumers)) 164 + goto err_bad_device; 165 + 166 + ret = devm_add_action_or_reset(dev, mpfs_sys_controller_put, sys_controller); 167 + if (ret) 168 + return ERR_PTR(ret); 169 + 170 + return sys_controller; 171 + 172 + err_no_device: 173 + dev_dbg(dev, "Parent device was not an MPFS system controller\n"); 174 + return ERR_PTR(-ENODEV); 175 + 176 + err_bad_device: 177 + dev_dbg(dev, "MPFS system controller found but could not register as a sub device\n"); 178 + return ERR_PTR(-EPROBE_DEFER); 179 + } 180 + EXPORT_SYMBOL(mpfs_sys_controller_get); 181 + 182 + static struct platform_driver mpfs_sys_controller_driver = { 183 + .driver = { 184 + .name = "mpfs-sys-controller", 185 + .of_match_table = mpfs_sys_controller_of_match, 186 + }, 187 + .probe = mpfs_sys_controller_probe, 188 + .remove = mpfs_sys_controller_remove, 189 + }; 190 + module_platform_driver(mpfs_sys_controller_driver); 191 + 192 + MODULE_LICENSE("GPL v2"); 193 + MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>"); 194 + MODULE_DESCRIPTION("MPFS system controller driver");
+4
include/linux/clk/at91_pmc.h
··· 78 78 #define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */ 79 79 80 80 #define AT91_CKGR_PLLAR 0x28 /* PLL A Register */ 81 + 82 + #define AT91_PMC_RATIO 0x2c /* Processor clock ratio register [SAMA7G5 only] */ 83 + #define AT91_PMC_RATIO_RATIO (0xf) /* CPU clock ratio. */ 84 + 81 85 #define AT91_CKGR_PLLBR 0x2c /* PLL B Register */ 82 86 #define AT91_PMC_DIV (0xff << 0) /* Divider */ 83 87 #define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */
+6 -9
include/soc/at91/sama7-ddr.h
··· 11 11 #ifndef __SAMA7_DDR_H__ 12 12 #define __SAMA7_DDR_H__ 13 13 14 - #ifdef CONFIG_SOC_SAMA7 15 - 16 14 /* DDR3PHY */ 17 15 #define DDR3PHY_PIR (0x04) /* DDR3PHY PHY Initialization Register */ 18 - #define DDR3PHY_PIR_DLLBYP (1 << 17) /* DLL Bypass */ 16 + #define DDR3PHY_PIR_DLLBYP (1 << 17) /* DLL Bypass */ 19 17 #define DDR3PHY_PIR_ITMSRST (1 << 4) /* Interface Timing Module Soft Reset */ 20 - #define DDR3PHY_PIR_DLLLOCK (1 << 2) /* DLL Lock */ 18 + #define DDR3PHY_PIR_DLLLOCK (1 << 2) /* DLL Lock */ 21 19 #define DDR3PHY_PIR_DLLSRST (1 << 1) /* DLL Soft Rest */ 22 - #define DDR3PHY_PIR_INIT (1 << 0) /* Initialization Trigger */ 20 + #define DDR3PHY_PIR_INIT (1 << 0) /* Initialization Trigger */ 23 21 24 22 #define DDR3PHY_PGCR (0x08) /* DDR3PHY PHY General Configuration Register */ 25 23 #define DDR3PHY_PGCR_CKDV1 (1 << 13) /* CK# Disable Value */ ··· 53 55 #define UDDRC_STAT_OPMODE_MSK (0x7 << 0) /* Operating mode mask */ 54 56 55 57 #define UDDRC_PWRCTL (0x30) /* UDDRC Low Power Control Register */ 56 - #define UDDRC_PWRCTRL_SELFREF_SW (1 << 5) /* Software self-refresh */ 58 + #define UDDRC_PWRCTL_SELFREF_EN (1 << 0) /* Automatic self-refresh */ 59 + #define UDDRC_PWRCTL_SELFREF_SW (1 << 5) /* Software self-refresh */ 57 60 58 61 #define UDDRC_DFIMISC (0x1B0) /* UDDRC DFI Miscellaneous Control Register */ 59 62 #define UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN (1 << 0) /* PHY initialization complete enable signal */ ··· 66 67 #define UDDRC_SWSTAT_SW_DONE_ACK (1 << 0) /* Register programming done */ 67 68 68 69 #define UDDRC_PSTAT (0x3FC) /* UDDRC Port Status Register */ 69 - #define UDDRC_PSTAT_ALL_PORTS (0x1F001F) /* Read + writes outstanding transactions on all ports */ 70 + #define UDDRC_PSTAT_ALL_PORTS (0x1F001F) /* Read + writes outstanding transactions on all ports */ 70 71 71 72 #define UDDRC_PCTRL_0 (0x490) /* UDDRC Port 0 Control Register */ 72 73 #define UDDRC_PCTRL_1 (0x540) /* UDDRC Port 1 Control Register */ 73 74 #define UDDRC_PCTRL_2 (0x5F0) /* UDDRC Port 2 Control Register */ 74 75 #define UDDRC_PCTRL_3 (0x6A0) /* UDDRC Port 3 Control Register */ 75 76 #define UDDRC_PCTRL_4 (0x750) /* UDDRC Port 4 Control Register */ 76 - 77 - #endif /* CONFIG_SOC_SAMA7 */ 78 77 79 78 #endif /* __SAMA7_DDR_H__ */
+2 -2
include/soc/microchip/mpfs.h
··· 34 34 35 35 #if IS_ENABLED(CONFIG_POLARFIRE_SOC_SYS_CTRL) 36 36 37 - int mpfs_blocking_transaction(struct mpfs_sys_controller *mpfs_client, void *msg); 37 + int mpfs_blocking_transaction(struct mpfs_sys_controller *mpfs_client, struct mpfs_mss_msg *msg); 38 38 39 - struct mpfs_sys_controller *mpfs_sys_controller_get(struct device_node *mailbox_node); 39 + struct mpfs_sys_controller *mpfs_sys_controller_get(struct device *dev); 40 40 41 41 #endif /* if IS_ENABLED(CONFIG_POLARFIRE_SOC_SYS_CTRL) */ 42 42