diff options
Diffstat (limited to 'drivers/soc')
67 files changed, 2840 insertions, 321 deletions
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 36452bed86ef..8fa43a2d17e7 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -4,7 +4,7 @@ # obj-$(CONFIG_ARCH_ACTIONS) += actions/ -obj-$(CONFIG_SOC_ASPEED) += aspeed/ +obj-y += aspeed/ obj-$(CONFIG_ARCH_AT91) += atmel/ obj-y += bcm/ obj-$(CONFIG_ARCH_DOVE) += dove/ diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig index 321c5e26a268..174a9b011461 100644 --- a/drivers/soc/amlogic/Kconfig +++ b/drivers/soc/amlogic/Kconfig @@ -9,7 +9,7 @@ config MESON_CANVAS Say yes to support the canvas IP for Amlogic SoCs. config MESON_CLK_MEASURE - bool "Amlogic Meson SoC Clock Measure driver" + tristate "Amlogic Meson SoC Clock Measure driver" depends on ARCH_MESON || COMPILE_TEST default ARCH_MESON select REGMAP_MMIO @@ -19,7 +19,7 @@ config MESON_CLK_MEASURE config MESON_GX_SOCINFO bool "Amlogic Meson GX SoC Information driver" - depends on ARCH_MESON || COMPILE_TEST + depends on (ARM64 && ARCH_MESON) || COMPILE_TEST default ARCH_MESON select SOC_BUS help @@ -27,7 +27,7 @@ config MESON_GX_SOCINFO information about the type, package and version. config MESON_GX_PM_DOMAINS - bool "Amlogic Meson GX Power Domains driver" + tristate "Amlogic Meson GX Power Domains driver" depends on ARCH_MESON || COMPILE_TEST depends on PM && OF default ARCH_MESON @@ -38,7 +38,7 @@ config MESON_GX_PM_DOMAINS Generic Power Domains. config MESON_EE_PM_DOMAINS - bool "Amlogic Meson Everything-Else Power Domains driver" + tristate "Amlogic Meson Everything-Else Power Domains driver" depends on ARCH_MESON || COMPILE_TEST depends on PM && OF default ARCH_MESON @@ -49,7 +49,7 @@ config MESON_EE_PM_DOMAINS Generic Power Domains. config MESON_SECURE_PM_DOMAINS - bool "Amlogic Meson Secure Power Domains driver" + tristate "Amlogic Meson Secure Power Domains driver" depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM depends on PM && OF depends on HAVE_ARM_SMCCC @@ -63,7 +63,7 @@ config MESON_SECURE_PM_DOMAINS config MESON_MX_SOCINFO bool "Amlogic Meson MX SoC Information driver" - depends on ARCH_MESON || COMPILE_TEST + depends on (ARM && ARCH_MESON) || COMPILE_TEST default ARCH_MESON select SOC_BUS help diff --git a/drivers/soc/amlogic/meson-canvas.c b/drivers/soc/amlogic/meson-canvas.c index c655f5f92b12..d0329ad170d1 100644 --- a/drivers/soc/amlogic/meson-canvas.c +++ b/drivers/soc/amlogic/meson-canvas.c @@ -72,8 +72,10 @@ struct meson_canvas *meson_canvas_get(struct device *dev) * current state, this driver probe cannot return -EPROBE_DEFER */ canvas = dev_get_drvdata(&canvas_pdev->dev); - if (!canvas) + if (!canvas) { + put_device(&canvas_pdev->dev); return ERR_PTR(-EINVAL); + } return canvas; } diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c index 0fa47d77577d..e1957476a006 100644 --- a/drivers/soc/amlogic/meson-clk-measure.c +++ b/drivers/soc/amlogic/meson-clk-measure.c @@ -10,6 +10,7 @@ #include <linux/seq_file.h> #include <linux/debugfs.h> #include <linux/regmap.h> +#include <linux/module.h> static DEFINE_MUTEX(measure_lock); @@ -681,6 +682,7 @@ static const struct of_device_id meson_msr_match_table[] = { }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, meson_msr_match_table); static struct platform_driver meson_msr_driver = { .probe = meson_msr_probe, @@ -689,4 +691,5 @@ static struct platform_driver meson_msr_driver = { .of_match_table = meson_msr_match_table, }, }; -builtin_platform_driver(meson_msr_driver); +module_platform_driver(meson_msr_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/amlogic/meson-ee-pwrc.c b/drivers/soc/amlogic/meson-ee-pwrc.c index 5164a4dc2352..50bf5d2b828b 100644 --- a/drivers/soc/amlogic/meson-ee-pwrc.c +++ b/drivers/soc/amlogic/meson-ee-pwrc.c @@ -14,6 +14,7 @@ #include <linux/reset-controller.h> #include <linux/reset.h> #include <linux/clk.h> +#include <linux/module.h> #include <dt-bindings/power/meson8-power.h> #include <dt-bindings/power/meson-axg-power.h> #include <dt-bindings/power/meson-g12a-power.h> @@ -412,8 +413,7 @@ static int meson_ee_pwrc_init_domain(struct platform_device *pdev, dev_warn(&pdev->dev, "Invalid resets count %d for domain %s\n", count, dom->desc.name); - dom->rstc = devm_reset_control_array_get(&pdev->dev, false, - false); + dom->rstc = devm_reset_control_array_get_exclusive(&pdev->dev); if (IS_ERR(dom->rstc)) return PTR_ERR(dom->rstc); } @@ -602,6 +602,7 @@ static const struct of_device_id meson_ee_pwrc_match_table[] = { }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, meson_ee_pwrc_match_table); static struct platform_driver meson_ee_pwrc_driver = { .probe = meson_ee_pwrc_probe, @@ -611,4 +612,5 @@ static struct platform_driver meson_ee_pwrc_driver = { .of_match_table = meson_ee_pwrc_match_table, }, }; -builtin_platform_driver(meson_ee_pwrc_driver); +module_platform_driver(meson_ee_pwrc_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c index 21b4bc811c00..b4615b288625 100644 --- a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c +++ b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c @@ -14,6 +14,7 @@ #include <linux/of_device.h> #include <linux/reset.h> #include <linux/clk.h> +#include <linux/module.h> /* AO Offsets */ @@ -303,7 +304,7 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev) return PTR_ERR(regmap_hhi); } - rstc = devm_reset_control_array_get(&pdev->dev, false, false); + rstc = devm_reset_control_array_get_exclusive(&pdev->dev); if (IS_ERR(rstc)) { if (PTR_ERR(rstc) != -EPROBE_DEFER) dev_err(&pdev->dev, "failed to get reset lines\n"); @@ -364,6 +365,7 @@ static const struct of_device_id meson_gx_pwrc_vpu_match_table[] = { }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, meson_gx_pwrc_vpu_match_table); static struct platform_driver meson_gx_pwrc_vpu_driver = { .probe = meson_gx_pwrc_vpu_probe, @@ -373,4 +375,5 @@ static struct platform_driver meson_gx_pwrc_vpu_driver = { .of_match_table = meson_gx_pwrc_vpu_match_table, }, }; -builtin_platform_driver(meson_gx_pwrc_vpu_driver); +module_platform_driver(meson_gx_pwrc_vpu_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/amlogic/meson-secure-pwrc.c b/drivers/soc/amlogic/meson-secure-pwrc.c index 5fb29a475879..59bd195fa9c9 100644 --- a/drivers/soc/amlogic/meson-secure-pwrc.c +++ b/drivers/soc/amlogic/meson-secure-pwrc.c @@ -13,6 +13,7 @@ #include <dt-bindings/power/meson-a1-power.h> #include <linux/arm-smccc.h> #include <linux/firmware/meson/meson_sm.h> +#include <linux/module.h> #define PWRC_ON 1 #define PWRC_OFF 0 @@ -193,6 +194,7 @@ static const struct of_device_id meson_secure_pwrc_match_table[] = { }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, meson_secure_pwrc_match_table); static struct platform_driver meson_secure_pwrc_driver = { .probe = meson_secure_pwrc_probe, @@ -201,4 +203,5 @@ static struct platform_driver meson_secure_pwrc_driver = { .of_match_table = meson_secure_pwrc_match_table, }, }; -builtin_platform_driver(meson_secure_pwrc_driver); +module_platform_driver(meson_secure_pwrc_driver); +MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig index c95fa30f1a76..243ca196e6ad 100644 --- a/drivers/soc/aspeed/Kconfig +++ b/drivers/soc/aspeed/Kconfig @@ -1,32 +1,47 @@ # SPDX-License-Identifier: GPL-2.0-only -menu "Aspeed SoC drivers" -config SOC_ASPEED - def_bool y - depends on ARCH_ASPEED || COMPILE_TEST +if ARCH_ASPEED || COMPILE_TEST + +menu "ASPEED SoC drivers" config ASPEED_LPC_CTRL - depends on SOC_ASPEED && REGMAP && MFD_SYSCON - tristate "Aspeed ast2400/2500 HOST LPC to BMC bridge control" + tristate "ASPEED LPC firmware cycle control" + select REGMAP + select MFD_SYSCON + default ARCH_ASPEED help - Control Aspeed ast2400/2500 HOST LPC to BMC mappings through - ioctl()s, the driver also provides a read/write interface to a BMC ram - region where the host LPC read/write region can be buffered. + Control LPC firmware cycle mappings through ioctl()s. The driver + also provides a read/write interface to a BMC ram region where the + host LPC read/write region can be buffered. config ASPEED_LPC_SNOOP - tristate "Aspeed ast2500 HOST LPC snoop support" - depends on SOC_ASPEED && REGMAP && MFD_SYSCON + tristate "ASPEED LPC snoop support" + select REGMAP + select MFD_SYSCON + default ARCH_ASPEED help Provides a driver to control the LPC snoop interface which allows the BMC to listen on and save the data written by the host to an arbitrary LPC I/O port. config ASPEED_P2A_CTRL - depends on SOC_ASPEED && REGMAP && MFD_SYSCON - tristate "Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC bridge control" + tristate "ASPEED P2A (VGA MMIO to BMC) bridge control" + select REGMAP + select MFD_SYSCON + default ARCH_ASPEED + help + Control ASPEED P2A VGA MMIO to BMC mappings through ioctl()s. The + driver also provides an interface for userspace mappings to a + pre-defined region. + +config ASPEED_SOCINFO + bool "ASPEED SoC Information driver" + default ARCH_ASPEED + select SOC_BUS + default ARCH_ASPEED help - Control Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC mappings through - ioctl()s, the driver also provides an interface for userspace mappings to - a pre-defined region. + Say yes to support decoding of ASPEED BMC information. endmenu + +endif diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile index b64be47f2b1f..fcab7192e1a4 100644 --- a/drivers/soc/aspeed/Makefile +++ b/drivers/soc/aspeed/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o +obj-$(CONFIG_ASPEED_SOCINFO) += aspeed-socinfo.o diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c index 01ed21e8bfee..439bcd6b8c4a 100644 --- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c +++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c @@ -4,6 +4,7 @@ */ #include <linux/clk.h> +#include <linux/log2.h> #include <linux/mfd/syscon.h> #include <linux/miscdevice.h> #include <linux/mm.h> @@ -21,6 +22,9 @@ #define HICR5_ENL2H BIT(8) #define HICR5_ENFWH BIT(10) +#define HICR6 0x4 +#define SW_FWH2AHB BIT(17) + #define HICR7 0x8 #define HICR8 0xc @@ -30,8 +34,9 @@ struct aspeed_lpc_ctrl { struct clk *clk; phys_addr_t mem_base; resource_size_t mem_size; - u32 pnor_size; - u32 pnor_base; + u32 pnor_size; + u32 pnor_base; + bool fwh2ahb; }; static struct aspeed_lpc_ctrl *file_aspeed_lpc_ctrl(struct file *file) @@ -177,6 +182,16 @@ static long aspeed_lpc_ctrl_ioctl(struct file *file, unsigned int cmd, return rc; /* + * Switch to FWH2AHB mode, AST2600 only. + * + * The other bits in this register are interrupt status bits + * that are cleared by writing 1. As we don't want to clear + * them, set only the bit of interest. + */ + if (lpc_ctrl->fwh2ahb) + regmap_write(lpc_ctrl->regmap, HICR6, SW_FWH2AHB); + + /* * Enable LPC FHW cycles. This is required for the host to * access the regions specified. */ @@ -241,6 +256,18 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) lpc_ctrl->mem_size = resource_size(&resm); lpc_ctrl->mem_base = resm.start; + + if (!is_power_of_2(lpc_ctrl->mem_size)) { + dev_err(dev, "Reserved memory size must be a power of 2, got %u\n", + (unsigned int)lpc_ctrl->mem_size); + return -EINVAL; + } + + if (!IS_ALIGNED(lpc_ctrl->mem_base, lpc_ctrl->mem_size)) { + dev_err(dev, "Reserved memory must be naturally aligned for size %u\n", + (unsigned int)lpc_ctrl->mem_size); + return -EINVAL; + } } lpc_ctrl->regmap = syscon_node_to_regmap( @@ -261,6 +288,9 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) return rc; } + if (of_device_is_compatible(dev->of_node, "aspeed,ast2600-lpc-ctrl")) + lpc_ctrl->fwh2ahb = true; + lpc_ctrl->miscdev.minor = MISC_DYNAMIC_MINOR; lpc_ctrl->miscdev.name = DEVICE_NAME; lpc_ctrl->miscdev.fops = &aspeed_lpc_ctrl_fops; @@ -291,6 +321,7 @@ static int aspeed_lpc_ctrl_remove(struct platform_device *pdev) static const struct of_device_id aspeed_lpc_ctrl_match[] = { { .compatible = "aspeed,ast2400-lpc-ctrl" }, { .compatible = "aspeed,ast2500-lpc-ctrl" }, + { .compatible = "aspeed,ast2600-lpc-ctrl" }, { }, }; @@ -308,4 +339,4 @@ module_platform_driver(aspeed_lpc_ctrl_driver); MODULE_DEVICE_TABLE(of, aspeed_lpc_ctrl_match); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Cyril Bur <cyrilbur@gmail.com>"); -MODULE_DESCRIPTION("Control for aspeed 2400/2500 LPC HOST to BMC mappings"); +MODULE_DESCRIPTION("Control for ASPEED LPC HOST to BMC mappings"); diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c index f3d8d53ab84d..682ba0eb4eba 100644 --- a/drivers/soc/aspeed/aspeed-lpc-snoop.c +++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c @@ -325,6 +325,8 @@ static const struct of_device_id aspeed_lpc_snoop_match[] = { .data = &ast2400_model_data }, { .compatible = "aspeed,ast2500-lpc-snoop", .data = &ast2500_model_data }, + { .compatible = "aspeed,ast2600-lpc-snoop", + .data = &ast2500_model_data }, { }, }; diff --git a/drivers/soc/aspeed/aspeed-socinfo.c b/drivers/soc/aspeed/aspeed-socinfo.c new file mode 100644 index 000000000000..773930e0cb10 --- /dev/null +++ b/drivers/soc/aspeed/aspeed-socinfo.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Copyright 2019 IBM Corp. */ + +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/sys_soc.h> + +static struct { + const char *name; + const u32 id; +} const rev_table[] = { + /* AST2400 */ + { "AST2400", 0x02000303 }, + { "AST1400", 0x02010103 }, + { "AST1250", 0x02010303 }, + /* AST2500 */ + { "AST2500", 0x04000303 }, + { "AST2510", 0x04000103 }, + { "AST2520", 0x04000203 }, + { "AST2530", 0x04000403 }, + /* AST2600 */ + { "AST2600", 0x05000303 }, + { "AST2620", 0x05010203 }, +}; + +static const char *siliconid_to_name(u32 siliconid) +{ + unsigned int id = siliconid & 0xff00ffff; + unsigned int i; + + for (i = 0 ; i < ARRAY_SIZE(rev_table) ; ++i) { + if (rev_table[i].id == id) + return rev_table[i].name; + } + + return "Unknown"; +} + +static const char *siliconid_to_rev(u32 siliconid) +{ + unsigned int rev = (siliconid >> 16) & 0xff; + + switch (rev) { + case 0: + return "A0"; + case 1: + return "A1"; + case 3: + return "A2"; + } + + return "??"; +} + +static int __init aspeed_socinfo_init(void) +{ + struct soc_device_attribute *attrs; + struct soc_device *soc_dev; + struct device_node *np; + void __iomem *reg; + bool has_chipid = false; + u32 siliconid; + u32 chipid[2]; + const char *machine = NULL; + + np = of_find_compatible_node(NULL, NULL, "aspeed,silicon-id"); + if (!of_device_is_available(np)) { + of_node_put(np); + return -ENODEV; + } + + reg = of_iomap(np, 0); + if (!reg) { + of_node_put(np); + return -ENODEV; + } + siliconid = readl(reg); + iounmap(reg); + + /* This is optional, the ast2400 does not have it */ + reg = of_iomap(np, 1); + if (reg) { + has_chipid = true; + chipid[0] = readl(reg); + chipid[1] = readl(reg + 4); + iounmap(reg); + } + of_node_put(np); + + attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); + if (!attrs) + return -ENODEV; + |