ASPEED soc driver updates for 5.11

New drivers:
 
  - SoC info driver to expose revision information
 
 New features:
 
  - AST2600 support for the LPC control driver. This includes
    setting the LPC2AHB bridge up in a backwards compatible manner.
 
 Cleanups:
 
  - LPC control
  - Kconfig
  - Bindings updates for AST2600 strings
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+nHMAt9PCBDH63wBa3ZZB4FHcJ4FAl/Ekp8ACgkQa3ZZB4FH
 cJ5CkA/+OqPM3CmJlxqgzy496suswaEeMlyuSECSmpQ6Z6jHIvKybzBXlf8zQXsW
 IFObgwqYdGBGOPG4HmvwJ307f2FjIgscEFJGr5kuZli47HTr288xRoAqDH7Oa5xu
 S8UcgxcpkSnAqUVErn9JplpCpKEt2Qzb4VoMZ2s5NtQDpkQUwybkO5siuG7Ck265
 9mzrQgSZ05zD+VSLA5EknQqsrtcTun7fQuBh3DW+4SUCAkzeGCTqkgT2jdvZ+TSu
 jcOMvBGu+gQ2cV2FewQroJ072cIDt6JbPiFDlg+16DoB6N4c4hLypSY62UIDk4Lt
 Y3QRrh7KKAzZ0Ofi1Hlj98/eMClK5h/W0ry3AyQtP3lwtAEVmMYiSm8xyU3lxTEi
 Ohhnwlmm+Ak00fmEKgHlTf9brIYncq3ErAjVOhDvlXBdEMXQGySoON/q81NqVWSA
 TXQXNrAUKkGMO6kHt8x8+8k07tBhqg170Wm10flQrgpP7rnsKgYxdSsQZ7dJvURI
 Ydh+E2DO2d15JDoQii+1RPalcB1AZZCC4hr4Qw0U884DM0uK0M3309vGnUy3nPHS
 vIy6QdW9QGnvsdldFeYMGVF0WAeBwIKvIFVf95hqhmqYjdUkPhomaqtWydVrpjNq
 VbF0zKKgOyDOIDpeS1k4YJ3uwps/D1rgCrer+ausclaQJJOreEw=
 =KcaK
 -----END PGP SIGNATURE-----

Merge tag 'aspeed-5.11-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/joel/aspeed into arm/drivers

ASPEED soc driver updates for 5.11

New drivers:

 - SoC info driver to expose revision information

New features:

 - AST2600 support for the LPC control driver. This includes
   setting the LPC2AHB bridge up in a backwards compatible manner.

Cleanups:

 - LPC control
 - Kconfig
 - Bindings updates for AST2600 strings

* tag 'aspeed-5.11-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/joel/aspeed:
  soc: aspeed: Enable drivers with ARCH_ASPEED
  soc: aspeed: Fix a reference leak in aspeed_socinfo_init()
  soc: aspeed: remove unneeded semicolon
  soc: aspeed-lpc-ctrl: Fix driver name
  soc: aspeed-lpc-ctrl: Fix whitespace
  soc: aspeed-lpc-ctrl: LPC to AHB mapping on ast2600
  soc: aspeed-lpc-ctrl: Fail probe of lpc-ctrl if reserved memory is not aligned
  soc: aspeed: lpc: Add AST2600 compatible strings
  dt-bindings: aspeed-lpc: Add AST2600 compatible strings
  ARM: dts: aspeed: Add silicon id node
  soc: aspeed: Add soc info driver
  dt-bindings: aspeed: Add silicon id node to SCU
  soc: aspeed: Improve kconfig

Link: https://lore.kernel.org/r/CACPK8Xe=9ezhyWRMqVOEQr7SU1YoYfVBGGdGzjmE4SiBr--vJQ@mail.gmail.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2020-11-30 17:24:21 +01:00
commit 00c543f6f3
11 changed files with 252 additions and 21 deletions

View File

@ -46,6 +46,7 @@ Required properties
- compatible: One of: - compatible: One of:
"aspeed,ast2400-lpc", "simple-mfd" "aspeed,ast2400-lpc", "simple-mfd"
"aspeed,ast2500-lpc", "simple-mfd" "aspeed,ast2500-lpc", "simple-mfd"
"aspeed,ast2600-lpc", "simple-mfd"
- reg: contains the physical address and length values of the Aspeed - reg: contains the physical address and length values of the Aspeed
LPC memory region. LPC memory region.
@ -64,6 +65,7 @@ BMC Node
- compatible: One of: - compatible: One of:
"aspeed,ast2400-lpc-bmc" "aspeed,ast2400-lpc-bmc"
"aspeed,ast2500-lpc-bmc" "aspeed,ast2500-lpc-bmc"
"aspeed,ast2600-lpc-bmc"
- reg: contains the physical address and length values of the - reg: contains the physical address and length values of the
H8S/2168-compatible LPC controller memory region H8S/2168-compatible LPC controller memory region
@ -74,6 +76,7 @@ Host Node
- compatible: One of: - compatible: One of:
"aspeed,ast2400-lpc-host", "simple-mfd", "syscon" "aspeed,ast2400-lpc-host", "simple-mfd", "syscon"
"aspeed,ast2500-lpc-host", "simple-mfd", "syscon" "aspeed,ast2500-lpc-host", "simple-mfd", "syscon"
"aspeed,ast2600-lpc-host", "simple-mfd", "syscon"
- reg: contains the address and length values of the host-related - reg: contains the address and length values of the host-related
register space for the Aspeed LPC controller register space for the Aspeed LPC controller
@ -128,6 +131,7 @@ Required properties:
- compatible: One of: - compatible: One of:
"aspeed,ast2400-lpc-ctrl"; "aspeed,ast2400-lpc-ctrl";
"aspeed,ast2500-lpc-ctrl"; "aspeed,ast2500-lpc-ctrl";
"aspeed,ast2600-lpc-ctrl";
- reg: contains offset/length values of the host interface controller - reg: contains offset/length values of the host interface controller
memory regions memory regions
@ -168,6 +172,7 @@ Required properties:
- compatible: One of: - compatible: One of:
"aspeed,ast2400-lhc"; "aspeed,ast2400-lhc";
"aspeed,ast2500-lhc"; "aspeed,ast2500-lhc";
"aspeed,ast2600-lhc";
- reg: contains offset/length values of the LHC memory regions. In the - reg: contains offset/length values of the LHC memory regions. In the
AST2400 and AST2500 there are two regions. AST2400 and AST2500 there are two regions.
@ -187,7 +192,8 @@ state of the LPC bus. Some systems may chose to modify this configuration.
Required properties: Required properties:
- compatible: "aspeed,ast2500-lpc-reset" or - compatible: "aspeed,ast2600-lpc-reset" or
"aspeed,ast2500-lpc-reset"
"aspeed,ast2400-lpc-reset" "aspeed,ast2400-lpc-reset"
- reg: offset and length of the IP in the LHC memory region - reg: offset and length of the IP in the LHC memory region
- #reset-controller indicates the number of reset cells expected - #reset-controller indicates the number of reset cells expected

View File

@ -20,3 +20,29 @@ syscon: syscon@1e6e2000 {
#clock-cells = <1>; #clock-cells = <1>;
#reset-cells = <1>; #reset-cells = <1>;
}; };
Silicon ID
-----------------
Families have unique hardware silicon identifiers within the SoC.
Required properties:
- compatible: "aspeed,silicon-id" or:
"aspeed,ast2400-silicon-id" or
"aspeed,ast2500-silicon-id" or
"aspeed,ast2600-silicon-id"
- reg: offset and length of the silicon id information
optionally, a second offset and length describes the unique chip id
The reg should be the unique silicon id register, and
not backwards compatible one in eg. the 2600.
Example:
silicon-id@7c {
compatible = "aspeed,ast2500-silicon-id", "aspeed,silicon-id";
reg = <0x7c 0x4 0x150 0x8>;
};

View File

@ -192,6 +192,11 @@
status = "disabled"; status = "disabled";
}; };
silicon-id@7c {
compatible = "aspeed,ast2400-silicon-id", "aspeed,silicon-id";
reg = <0x7c 0x4>;
};
pinctrl: pinctrl@80 { pinctrl: pinctrl@80 {
reg = <0x80 0x18>, <0xa0 0x10>; reg = <0x80 0x18>, <0xa0 0x10>;
compatible = "aspeed,ast2400-pinctrl"; compatible = "aspeed,ast2400-pinctrl";

View File

@ -239,6 +239,11 @@
status = "disabled"; status = "disabled";
}; };
silicon-id@7c {
compatible = "aspeed,ast2500-silicon-id", "aspeed,silicon-id";
reg = <0x7c 0x4 0x150 0x8>;
};
pinctrl: pinctrl@80 { pinctrl: pinctrl@80 {
compatible = "aspeed,ast2500-pinctrl"; compatible = "aspeed,ast2500-pinctrl";
reg = <0x80 0x18>, <0xa0 0x10>; reg = <0x80 0x18>, <0xa0 0x10>;

View File

@ -311,6 +311,11 @@
compatible = "aspeed,ast2600-pinctrl"; compatible = "aspeed,ast2600-pinctrl";
}; };
silicon-id@14 {
compatible = "aspeed,ast2600-silicon-id", "aspeed,silicon-id";
reg = <0x14 0x4 0x5b0 0x8>;
};
smp-memram@180 { smp-memram@180 {
compatible = "aspeed,ast2600-smpmem"; compatible = "aspeed,ast2600-smpmem";
reg = <0x180 0x40>; reg = <0x180 0x40>;

View File

@ -4,7 +4,7 @@
# #
obj-$(CONFIG_ARCH_ACTIONS) += actions/ obj-$(CONFIG_ARCH_ACTIONS) += actions/
obj-$(CONFIG_SOC_ASPEED) += aspeed/ obj-y += aspeed/
obj-$(CONFIG_ARCH_AT91) += atmel/ obj-$(CONFIG_ARCH_AT91) += atmel/
obj-y += bcm/ obj-y += bcm/
obj-$(CONFIG_ARCH_DOVE) += dove/ obj-$(CONFIG_ARCH_DOVE) += dove/

View File

@ -1,32 +1,47 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
menu "Aspeed SoC drivers"
config SOC_ASPEED if ARCH_ASPEED || COMPILE_TEST
def_bool y
depends on ARCH_ASPEED || COMPILE_TEST menu "ASPEED SoC drivers"
config ASPEED_LPC_CTRL config ASPEED_LPC_CTRL
depends on SOC_ASPEED && REGMAP && MFD_SYSCON tristate "ASPEED LPC firmware cycle control"
tristate "Aspeed ast2400/2500 HOST LPC to BMC bridge control" select REGMAP
select MFD_SYSCON
default ARCH_ASPEED
help help
Control Aspeed ast2400/2500 HOST LPC to BMC mappings through Control LPC firmware cycle mappings through ioctl()s. The driver
ioctl()s, the driver also provides a read/write interface to a BMC ram also provides a read/write interface to a BMC ram region where the
region where the host LPC read/write region can be buffered. host LPC read/write region can be buffered.
config ASPEED_LPC_SNOOP config ASPEED_LPC_SNOOP
tristate "Aspeed ast2500 HOST LPC snoop support" tristate "ASPEED LPC snoop support"
depends on SOC_ASPEED && REGMAP && MFD_SYSCON select REGMAP
select MFD_SYSCON
default ARCH_ASPEED
help help
Provides a driver to control the LPC snoop interface which Provides a driver to control the LPC snoop interface which
allows the BMC to listen on and save the data written by allows the BMC to listen on and save the data written by
the host to an arbitrary LPC I/O port. the host to an arbitrary LPC I/O port.
config ASPEED_P2A_CTRL config ASPEED_P2A_CTRL
depends on SOC_ASPEED && REGMAP && MFD_SYSCON tristate "ASPEED P2A (VGA MMIO to BMC) bridge control"
tristate "Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC bridge control" select REGMAP
select MFD_SYSCON
default ARCH_ASPEED
help help
Control Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC mappings through Control ASPEED P2A VGA MMIO to BMC mappings through ioctl()s. The
ioctl()s, the driver also provides an interface for userspace mappings to driver also provides an interface for userspace mappings to a
a pre-defined region. pre-defined region.
config ASPEED_SOCINFO
bool "ASPEED SoC Information driver"
default ARCH_ASPEED
select SOC_BUS
default ARCH_ASPEED
help
Say yes to support decoding of ASPEED BMC information.
endmenu endmenu
endif

View File

@ -2,3 +2,4 @@
obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o
obj-$(CONFIG_ASPEED_SOCINFO) += aspeed-socinfo.o

View File

@ -4,6 +4,7 @@
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/log2.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/mm.h> #include <linux/mm.h>
@ -21,6 +22,9 @@
#define HICR5_ENL2H BIT(8) #define HICR5_ENL2H BIT(8)
#define HICR5_ENFWH BIT(10) #define HICR5_ENFWH BIT(10)
#define HICR6 0x4
#define SW_FWH2AHB BIT(17)
#define HICR7 0x8 #define HICR7 0x8
#define HICR8 0xc #define HICR8 0xc
@ -32,6 +36,7 @@ struct aspeed_lpc_ctrl {
resource_size_t mem_size; resource_size_t mem_size;
u32 pnor_size; u32 pnor_size;
u32 pnor_base; u32 pnor_base;
bool fwh2ahb;
}; };
static struct aspeed_lpc_ctrl *file_aspeed_lpc_ctrl(struct file *file) static struct aspeed_lpc_ctrl *file_aspeed_lpc_ctrl(struct file *file)
@ -176,6 +181,16 @@ static long aspeed_lpc_ctrl_ioctl(struct file *file, unsigned int cmd,
if (rc) if (rc)
return rc; 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 * Enable LPC FHW cycles. This is required for the host to
* access the regions specified. * 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_size = resource_size(&resm);
lpc_ctrl->mem_base = resm.start; 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( lpc_ctrl->regmap = syscon_node_to_regmap(
@ -261,6 +288,9 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev)
return rc; 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.minor = MISC_DYNAMIC_MINOR;
lpc_ctrl->miscdev.name = DEVICE_NAME; lpc_ctrl->miscdev.name = DEVICE_NAME;
lpc_ctrl->miscdev.fops = &aspeed_lpc_ctrl_fops; 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[] = { static const struct of_device_id aspeed_lpc_ctrl_match[] = {
{ .compatible = "aspeed,ast2400-lpc-ctrl" }, { .compatible = "aspeed,ast2400-lpc-ctrl" },
{ .compatible = "aspeed,ast2500-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_DEVICE_TABLE(of, aspeed_lpc_ctrl_match);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Cyril Bur <cyrilbur@gmail.com>"); 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");

View File

@ -325,6 +325,8 @@ static const struct of_device_id aspeed_lpc_snoop_match[] = {
.data = &ast2400_model_data }, .data = &ast2400_model_data },
{ .compatible = "aspeed,ast2500-lpc-snoop", { .compatible = "aspeed,ast2500-lpc-snoop",
.data = &ast2500_model_data }, .data = &ast2500_model_data },
{ .compatible = "aspeed,ast2600-lpc-snoop",
.data = &ast2500_model_data },
{ }, { },
}; };

View File

@ -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;
/*
* Machine: Romulus BMC
* Family: AST2500
* Revision: A1
* SoC ID: raw silicon revision id
* Serial Number: 64-bit chipid
*/
np = of_find_node_by_path("/");
of_property_read_string(np, "model", &machine);
if (machine)
attrs->machine = kstrdup(machine, GFP_KERNEL);
of_node_put(np);
attrs->family = siliconid_to_name(siliconid);
attrs->revision = siliconid_to_rev(siliconid);
attrs->soc_id = kasprintf(GFP_KERNEL, "%08x", siliconid);
if (has_chipid)
attrs->serial_number = kasprintf(GFP_KERNEL, "%08x%08x",
chipid[1], chipid[0]);
soc_dev = soc_device_register(attrs);
if (IS_ERR(soc_dev)) {
kfree(attrs->soc_id);
kfree(attrs->serial_number);
kfree(attrs);
return PTR_ERR(soc_dev);
}
pr_info("ASPEED %s rev %s (%s)\n",
attrs->family,
attrs->revision,
attrs->soc_id);
return 0;
}
early_initcall(aspeed_socinfo_init);