From 46220bf0174da71f49939633b3ebf00b8ed45b47 Mon Sep 17 00:00:00 2001 From: Ryan Chen Date: Tue, 2 Nov 2021 10:17:52 +0800 Subject: aspeed: AST2600 Pinctrl Driver This driver uses Pinctrl framework and is compatible with the Linux driver for AST2600. Signed-off-by: Ryan Chen Signed-off-by: Dylan Hung --- drivers/pinctrl/Kconfig | 9 + drivers/pinctrl/aspeed/Makefile | 1 + drivers/pinctrl/aspeed/pinctrl_ast2600.c | 459 +++++++++++++++++++++++++++++++ 3 files changed, 469 insertions(+) create mode 100644 drivers/pinctrl/aspeed/pinctrl_ast2600.c (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 30eaa376c8e..42f25e24fb1 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -291,6 +291,15 @@ config ASPEED_AST2500_PINCTRL uses Generic Pinctrl framework and is compatible with the Linux driver, i.e. it uses the same device tree configuration. +config ASPEED_AST2600_PINCTRL + bool "Aspeed AST2600 pin control driver" + depends on DM && PINCTRL_GENERIC && ASPEED_AST2600 + default y + help + Support pin multiplexing control on Aspeed ast2600 SoC. The driver + uses Generic Pinctrl framework and is compatible with the Linux + driver, i.e. it uses the same device tree configuration. + config PINCTRL_K210 bool "Kendryte K210 Fully-Programmable Input/Output Array driver" depends on DM && PINCTRL_GENERIC diff --git a/drivers/pinctrl/aspeed/Makefile b/drivers/pinctrl/aspeed/Makefile index 2e6ed604c8f..a3e01ed1ca9 100644 --- a/drivers/pinctrl/aspeed/Makefile +++ b/drivers/pinctrl/aspeed/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_ASPEED_AST2500_PINCTRL) += pinctrl_ast2500.o +obj-$(CONFIG_ASPEED_AST2600_PINCTRL) += pinctrl_ast2600.o diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2600.c b/drivers/pinctrl/aspeed/pinctrl_ast2600.c new file mode 100644 index 00000000000..12cba83f6c0 --- /dev/null +++ b/drivers/pinctrl/aspeed/pinctrl_ast2600.c @@ -0,0 +1,459 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) ASPEED Technology Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This driver works with very simple configuration that has the same name + * for group and function. This way it is compatible with the Linux Kernel + * driver. + */ +struct aspeed_sig_desc { + u32 offset; + u32 reg_set; + int clr; +}; + +struct aspeed_group_config { + char *group_name; + int ndescs; + struct aspeed_sig_desc *descs; +}; + +struct ast2600_pinctrl_priv { + struct ast2600_scu *scu; +}; + +static int ast2600_pinctrl_probe(struct udevice *dev) +{ + struct ast2600_pinctrl_priv *priv = dev_get_priv(dev); + struct udevice *clk_dev; + int ret = 0; + + /* find SCU base address from clock device */ + uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(aspeed_ast2600_scu), &clk_dev); + + if (ret) + return ret; + + priv->scu = dev_read_addr_ptr(clk_dev); + if (IS_ERR(priv->scu)) + return PTR_ERR(priv->scu); + + return 0; +} + +static struct aspeed_sig_desc i2c1_link[] = { + { 0x418, GENMASK(9, 8), 1 }, + { 0x4B8, GENMASK(9, 8), 0 }, +}; + +static struct aspeed_sig_desc i2c2_link[] = { + { 0x418, GENMASK(11, 10), 1 }, + { 0x4B8, GENMASK(11, 10), 0 }, +}; + +static struct aspeed_sig_desc i2c3_link[] = { + { 0x418, GENMASK(13, 12), 1 }, + { 0x4B8, GENMASK(13, 12), 0 }, +}; + +static struct aspeed_sig_desc i2c4_link[] = { + { 0x418, GENMASK(15, 14), 1 }, + { 0x4B8, GENMASK(15, 14), 0 }, +}; + +static struct aspeed_sig_desc i2c5_link[] = { + { 0x418, GENMASK(17, 16), 0 }, +}; + +static struct aspeed_sig_desc i2c6_link[] = { + { 0x418, GENMASK(19, 18), 0 }, +}; + +static struct aspeed_sig_desc i2c7_link[] = { + { 0x418, GENMASK(21, 20), 0 }, +}; + +static struct aspeed_sig_desc i2c8_link[] = { + { 0x418, GENMASK(23, 22), 0 }, +}; + +static struct aspeed_sig_desc i2c9_link[] = { + { 0x418, GENMASK(25, 24), 0 }, +}; + +static struct aspeed_sig_desc i2c10_link[] = { + { 0x418, GENMASK(27, 26), 0 }, +}; + +static struct aspeed_sig_desc i2c11_link[] = { + { 0x410, GENMASK(1, 0), 1 }, + { 0x4B0, GENMASK(1, 0), 0 }, +}; + +static struct aspeed_sig_desc i2c12_link[] = { + { 0x410, GENMASK(3, 2), 1 }, + { 0x4B0, GENMASK(3, 2), 0 }, +}; + +static struct aspeed_sig_desc i2c13_link[] = { + { 0x410, GENMASK(5, 4), 1 }, + { 0x4B0, GENMASK(5, 4), 0 }, +}; + +static struct aspeed_sig_desc i2c14_link[] = { + { 0x410, GENMASK(7, 6), 1 }, + { 0x4B0, GENMASK(7, 6), 0 }, +}; + +static struct aspeed_sig_desc i2c15_link[] = { + { 0x414, GENMASK(29, 28), 1 }, + { 0x4B4, GENMASK(29, 28), 0 }, +}; + +static struct aspeed_sig_desc i2c16_link[] = { + { 0x414, GENMASK(31, 30), 1 }, + { 0x4B4, GENMASK(31, 30), 0 }, +}; + +static struct aspeed_sig_desc mac1_link[] = { + { 0x410, BIT(4), 0 }, + { 0x470, BIT(4), 1 }, +}; + +static struct aspeed_sig_desc mac2_link[] = { + { 0x410, BIT(5), 0 }, + { 0x470, BIT(5), 1 }, +}; + +static struct aspeed_sig_desc mac3_link[] = { + { 0x410, BIT(6), 0 }, + { 0x470, BIT(6), 1 }, +}; + +static struct aspeed_sig_desc mac4_link[] = { + { 0x410, BIT(7), 0 }, + { 0x470, BIT(7), 1 }, +}; + +static struct aspeed_sig_desc rgmii1[] = { + { 0x500, BIT(6), 0 }, + { 0x400, GENMASK(11, 0), 0 }, +}; + +static struct aspeed_sig_desc rgmii2[] = { + { 0x500, BIT(7), 0 }, + { 0x400, GENMASK(23, 12), 0 }, +}; + +static struct aspeed_sig_desc rgmii3[] = { + { 0x510, BIT(0), 0 }, + { 0x410, GENMASK(27, 16), 0 }, +}; + +static struct aspeed_sig_desc rgmii4[] = { + { 0x510, BIT(1), 0 }, + { 0x410, GENMASK(31, 28), 1 }, + { 0x4b0, GENMASK(31, 28), 0 }, + { 0x474, GENMASK(7, 0), 1 }, + { 0x414, GENMASK(7, 0), 1 }, + { 0x4b4, GENMASK(7, 0), 0 }, +}; + +static struct aspeed_sig_desc rmii1[] = { + { 0x504, BIT(6), 0 }, + { 0x400, GENMASK(3, 0), 0 }, + { 0x400, GENMASK(11, 6), 0 }, +}; + +static struct aspeed_sig_desc rmii2[] = { + { 0x504, BIT(7), 0 }, + { 0x400, GENMASK(15, 12), 0 }, + { 0x400, GENMASK(23, 18), 0 }, +}; + +static struct aspeed_sig_desc rmii3[] = { + { 0x514, BIT(0), 0 }, + { 0x410, GENMASK(27, 22), 0 }, + { 0x410, GENMASK(19, 16), 0 }, +}; + +static struct aspeed_sig_desc rmii4[] = { + { 0x514, BIT(1), 0 }, + { 0x410, GENMASK(7, 2), 1 }, + { 0x410, GENMASK(31, 28), 1 }, + { 0x414, GENMASK(7, 2), 1 }, + { 0x4B0, GENMASK(31, 28), 0 }, + { 0x4B4, GENMASK(7, 2), 0 }, +}; + +static struct aspeed_sig_desc rmii1_rclk_oe[] = { + { 0x340, BIT(29), 0 }, +}; + +static struct aspeed_sig_desc rmii2_rclk_oe[] = { + { 0x340, BIT(30), 0 }, +}; + +static struct aspeed_sig_desc rmii3_rclk_oe[] = { + { 0x350, BIT(29), 0 }, +}; + +static struct aspeed_sig_desc rmii4_rclk_oe[] = { + { 0x350, BIT(30), 0 }, +}; + +static struct aspeed_sig_desc mdio1_link[] = { + { 0x430, BIT(17) | BIT(16), 0 }, +}; + +static struct aspeed_sig_desc mdio2_link[] = { + { 0x470, BIT(13) | BIT(12), 1 }, + { 0x410, BIT(13) | BIT(12), 0 }, +}; + +static struct aspeed_sig_desc mdio3_link[] = { + { 0x470, BIT(1) | BIT(0), 1 }, + { 0x410, BIT(1) | BIT(0), 0 }, +}; + +static struct aspeed_sig_desc mdio4_link[] = { + { 0x470, BIT(3) | BIT(2), 1 }, + { 0x410, BIT(3) | BIT(2), 0 }, +}; + +static struct aspeed_sig_desc sdio2_link[] = { + { 0x414, GENMASK(23, 16), 1 }, + { 0x4B4, GENMASK(23, 16), 0 }, + { 0x450, BIT(1), 0 }, +}; + +static struct aspeed_sig_desc sdio1_link[] = { + { 0x414, GENMASK(15, 8), 0 }, +}; + +/* when sdio1 8bits, sdio2 can't use */ +static struct aspeed_sig_desc sdio1_8bit_link[] = { + { 0x414, GENMASK(15, 8), 0 }, + { 0x4b4, GENMASK(21, 18), 0 }, + { 0x450, BIT(3), 0 }, + { 0x450, BIT(1), 1 }, +}; + +static struct aspeed_sig_desc emmc_link[] = { + { 0x400, GENMASK(31, 24), 0 }, +}; + +static struct aspeed_sig_desc emmcg8_link[] = { + { 0x400, GENMASK(31, 24), 0 }, + { 0x404, GENMASK(3, 0), 0 }, +/* set SCU504 to clear the strap bits in SCU500 */ + { 0x504, BIT(3), 0 }, + { 0x504, BIT(5), 0 }, +}; + +static struct aspeed_sig_desc fmcquad_link[] = { + { 0x438, GENMASK(5, 4), 0 }, +}; + +static struct aspeed_sig_desc spi1_link[] = { + { 0x438, GENMASK(13, 11), 0 }, +}; + +static struct aspeed_sig_desc spi1abr_link[] = { + { 0x438, BIT(9), 0 }, +}; + +static struct aspeed_sig_desc spi1cs1_link[] = { + { 0x438, BIT(8), 0 }, +}; + +static struct aspeed_sig_desc spi1wp_link[] = { + { 0x438, BIT(10), 0 }, +}; + +static struct aspeed_sig_desc spi1quad_link[] = { + { 0x438, GENMASK(15, 14), 0 }, +}; + +static struct aspeed_sig_desc spi2_link[] = { + { 0x434, GENMASK(29, 27) | BIT(24), 0 }, +}; + +static struct aspeed_sig_desc spi2cs1_link[] = { + { 0x434, BIT(25), 0 }, +}; + +static struct aspeed_sig_desc spi2cs2_link[] = { + { 0x434, BIT(26), 0 }, +}; + +static struct aspeed_sig_desc spi2quad_link[] = { + { 0x434, GENMASK(31, 30), 0 }, +}; + +static struct aspeed_sig_desc fsi1[] = { + { 0xd48, GENMASK(21, 20), 0 }, +}; + +static struct aspeed_sig_desc fsi2[] = { + { 0xd48, GENMASK(23, 22), 0 }, +}; + +static struct aspeed_sig_desc usb2ad_link[] = { + { 0x440, BIT(24), 0 }, + { 0x440, BIT(25), 1 }, +}; + +static struct aspeed_sig_desc usb2ah_link[] = { + { 0x440, BIT(24), 1 }, + { 0x440, BIT(25), 0 }, +}; + +static struct aspeed_sig_desc usb2bh_link[] = { + { 0x440, BIT(28), 1 }, + { 0x440, BIT(29), 0 }, +}; + +static struct aspeed_sig_desc pcie0rc_link[] = { + { 0x40, BIT(21), 0 }, +}; + +static struct aspeed_sig_desc pcie1rc_link[] = { + { 0x40, BIT(19), 0 }, /* SSPRST# output enable */ + { 0x500, BIT(24), 0 }, /* dedicate rc reset */ +}; + +static const struct aspeed_group_config ast2600_groups[] = { + { "MAC1LINK", ARRAY_SIZE(mac1_link), mac1_link }, + { "MAC2LINK", ARRAY_SIZE(mac2_link), mac2_link }, + { "MAC3LINK", ARRAY_SIZE(mac3_link), mac3_link }, + { "MAC4LINK", ARRAY_SIZE(mac4_link), mac4_link }, + { "RGMII1", ARRAY_SIZE(rgmii1), rgmii1 }, + { "RGMII2", ARRAY_SIZE(rgmii2), rgmii2 }, + { "RGMII3", ARRAY_SIZE(rgmii3), rgmii3 }, + { "RGMII4", ARRAY_SIZE(rgmii4), rgmii4 }, + { "RMII1", ARRAY_SIZE(rmii1), rmii1 }, + { "RMII2", ARRAY_SIZE(rmii2), rmii2 }, + { "RMII3", ARRAY_SIZE(rmii3), rmii3 }, + { "RMII4", ARRAY_SIZE(rmii4), rmii4 }, + { "RMII1RCLK", ARRAY_SIZE(rmii1_rclk_oe), rmii1_rclk_oe }, + { "RMII2RCLK", ARRAY_SIZE(rmii2_rclk_oe), rmii2_rclk_oe }, + { "RMII3RCLK", ARRAY_SIZE(rmii3_rclk_oe), rmii3_rclk_oe }, + { "RMII4RCLK", ARRAY_SIZE(rmii4_rclk_oe), rmii4_rclk_oe }, + { "MDIO1", ARRAY_SIZE(mdio1_link), mdio1_link }, + { "MDIO2", ARRAY_SIZE(mdio2_link), mdio2_link }, + { "MDIO3", ARRAY_SIZE(mdio3_link), mdio3_link }, + { "MDIO4", ARRAY_SIZE(mdio4_link), mdio4_link }, + { "SD1", ARRAY_SIZE(sdio1_link), sdio1_link }, + { "SD1_8bits", ARRAY_SIZE(sdio1_8bit_link), sdio1_8bit_link }, + { "SD2", ARRAY_SIZE(sdio2_link), sdio2_link }, + { "EMMC", ARRAY_SIZE(emmc_link), emmc_link }, + { "EMMCG8", ARRAY_SIZE(emmcg8_link), emmcg8_link }, + { "FMCQUAD", ARRAY_SIZE(fmcquad_link), fmcquad_link }, + { "SPI1", ARRAY_SIZE(spi1_link), spi1_link }, + { "SPI1ABR", ARRAY_SIZE(spi1abr_link), spi1abr_link }, + { "SPI1CS1", ARRAY_SIZE(spi1cs1_link), spi1cs1_link }, + { "SPI1WP", ARRAY_SIZE(spi1wp_link), spi1wp_link }, + { "SPI1QUAD", ARRAY_SIZE(spi1quad_link), spi1quad_link }, + { "SPI2", ARRAY_SIZE(spi2_link), spi2_link }, + { "SPI2CS1", ARRAY_SIZE(spi2cs1_link), spi2cs1_link }, + { "SPI2CS2", ARRAY_SIZE(spi2cs2_link), spi2cs2_link }, + { "SPI2QUAD", ARRAY_SIZE(spi2quad_link), spi2quad_link }, + { "I2C1", ARRAY_SIZE(i2c1_link), i2c1_link }, + { "I2C2", ARRAY_SIZE(i2c2_link), i2c2_link }, + { "I2C3", ARRAY_SIZE(i2c3_link), i2c3_link }, + { "I2C4", ARRAY_SIZE(i2c4_link), i2c4_link }, + { "I2C5", ARRAY_SIZE(i2c5_link), i2c5_link }, + { "I2C6", ARRAY_SIZE(i2c6_link), i2c6_link }, + { "I2C7", ARRAY_SIZE(i2c7_link), i2c7_link }, + { "I2C8", ARRAY_SIZE(i2c8_link), i2c8_link }, + { "I2C9", ARRAY_SIZE(i2c9_link), i2c9_link }, + { "I2C10", ARRAY_SIZE(i2c10_link), i2c10_link }, + { "I2C11", ARRAY_SIZE(i2c11_link), i2c11_link }, + { "I2C12", ARRAY_SIZE(i2c12_link), i2c12_link }, + { "I2C13", ARRAY_SIZE(i2c13_link), i2c13_link }, + { "I2C14", ARRAY_SIZE(i2c14_link), i2c14_link }, + { "I2C15", ARRAY_SIZE(i2c15_link), i2c15_link }, + { "I2C16", ARRAY_SIZE(i2c16_link), i2c16_link }, + { "FSI1", ARRAY_SIZE(fsi1), fsi1 }, + { "FSI2", ARRAY_SIZE(fsi2), fsi2 }, + { "USB2AD", ARRAY_SIZE(usb2ad_link), usb2ad_link }, + { "USB2AH", ARRAY_SIZE(usb2ah_link), usb2ah_link }, + { "USB2BH", ARRAY_SIZE(usb2bh_link), usb2bh_link }, + { "PCIE0RC", ARRAY_SIZE(pcie0rc_link), pcie0rc_link }, + { "PCIE1RC", ARRAY_SIZE(pcie1rc_link), pcie1rc_link }, +}; + +static int ast2600_pinctrl_get_groups_count(struct udevice *dev) +{ + debug("PINCTRL: get_(functions/groups)_count\n"); + + return ARRAY_SIZE(ast2600_groups); +} + +static const char *ast2600_pinctrl_get_group_name(struct udevice *dev, + unsigned selector) +{ + debug("PINCTRL: get_(function/group)_name %u\n", selector); + + return ast2600_groups[selector].group_name; +} + +static int ast2600_pinctrl_group_set(struct udevice *dev, unsigned selector, unsigned func_selector) +{ + struct ast2600_pinctrl_priv *priv = dev_get_priv(dev); + const struct aspeed_group_config *config; + const struct aspeed_sig_desc *descs; + u32 ctrl_reg = (u32)priv->scu; + u32 i; + + debug("PINCTRL: group_set <%u, %u>\n", selector, func_selector); + if (selector >= ARRAY_SIZE(ast2600_groups)) + return -EINVAL; + + config = &ast2600_groups[selector]; + for (i = 0; i < config->ndescs; i++) { + descs = &config->descs[i]; + if (descs->clr) + clrbits_le32((u32)ctrl_reg + descs->offset, descs->reg_set); + else + setbits_le32((u32)ctrl_reg + descs->offset, descs->reg_set); + } + + return 0; +} + +static struct pinctrl_ops ast2600_pinctrl_ops = { + .set_state = pinctrl_generic_set_state, + .get_groups_count = ast2600_pinctrl_get_groups_count, + .get_group_name = ast2600_pinctrl_get_group_name, + .get_functions_count = ast2600_pinctrl_get_groups_count, + .get_function_name = ast2600_pinctrl_get_group_name, + .pinmux_group_set = ast2600_pinctrl_group_set, +}; + +static const struct udevice_id ast2600_pinctrl_ids[] = { + { .compatible = "aspeed,g6-pinctrl" }, + { } +}; + +U_BOOT_DRIVER(pinctrl_aspeed) = { + .name = "aspeed_ast2600_pinctrl", + .id = UCLASS_PINCTRL, + .of_match = ast2600_pinctrl_ids, + .priv_auto = sizeof(struct ast2600_pinctrl_priv), + .ops = &ast2600_pinctrl_ops, + .probe = ast2600_pinctrl_probe, +}; -- cgit v1.2.3 From b814e0007e060b5cce314edcf5c0507a67cafd73 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Tue, 2 Nov 2021 18:21:57 +0100 Subject: pinctrl: Add Apple pinctrl driver This driver supports both pin muxing and GPIO support for the pin control logic found on Apple SoCs. Signed-off-by: Mark Kettenis --- drivers/pinctrl/Kconfig | 11 +++ drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-apple.c | 207 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 219 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-apple.c (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 42f25e24fb1..03946245c7d 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -145,6 +145,17 @@ config SPL_PINCONF_RECURSIVE if PINCTRL || SPL_PINCTRL +config PINCTRL_APPLE + bool "Apple pinctrl driver" + depends on DM && PINCTRL_GENERIC && ARCH_APPLE + default y + help + Support pin multiplexing on Apple SoCs. + + The driver is controlled by a device tree node which contains + both the GPIO definitions and pin control functions for each + available multiplex function. + config PINCTRL_AR933X bool "QCA/Athores ar933x pin control driver" depends on DM && SOC_AR933X diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 05b71f2f134..fd736a7f640 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -3,6 +3,7 @@ obj-y += pinctrl-uclass.o obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC) += pinctrl-generic.o +obj-$(CONFIG_PINCTRL_APPLE) += pinctrl-apple.o obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o obj-y += nxp/ diff --git a/drivers/pinctrl/pinctrl-apple.c b/drivers/pinctrl/pinctrl-apple.c new file mode 100644 index 00000000000..62476358c34 --- /dev/null +++ b/drivers/pinctrl/pinctrl-apple.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2021 Mark Kettenis + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct apple_pinctrl_priv { + void *base; + int pin_count; +}; + +#define REG_GPIO(x) (4 * (x)) +#define REG_GPIO_DATA BIT(0) +#define REG_GPIO_MODE GENMASK(3, 1) +#define REG_GPIO_OUT 1 +#define REG_GPIO_PERIPH GENMASK(6, 5) +#define REG_GPIO_INPUT_ENABLE BIT(9) + +static void apple_pinctrl_config_pin(struct apple_pinctrl_priv *priv, + unsigned pin, u32 clr, u32 set) +{ + unsigned reg = REG_GPIO(pin); + u32 old, new; + + old = readl(priv->base + REG_GPIO(pin)); + new = (old & ~clr) | set; + writel(new, priv->base + reg); +} + +static int apple_gpio_get_value(struct udevice *dev, unsigned offset) +{ + struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent); + + return !!(readl(priv->base + REG_GPIO(offset)) & REG_GPIO_DATA); +} + +static int apple_gpio_set_value(struct udevice *dev, unsigned offset, + int value) +{ + struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent); + + apple_pinctrl_config_pin(priv, offset, REG_GPIO_DATA, + value ? REG_GPIO_DATA : 0); + return 0; +} + +static int apple_gpio_get_direction(struct udevice *dev, unsigned offset) +{ + struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent); + u32 reg = readl(priv->base + REG_GPIO(offset)); + + if (FIELD_GET(REG_GPIO_MODE, reg) == REG_GPIO_OUT) + return GPIOF_OUTPUT; + else + return GPIOF_INPUT; +} + +static int apple_gpio_direction_input(struct udevice *dev, unsigned offset) +{ + struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent); + + apple_pinctrl_config_pin(priv, offset, + REG_GPIO_PERIPH | REG_GPIO_MODE, + REG_GPIO_INPUT_ENABLE); + return 0; +} + +static int apple_gpio_direction_output(struct udevice *dev, unsigned offset, + int value) +{ + struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent); + u32 set = (value ? REG_GPIO_DATA : 0); + + apple_pinctrl_config_pin(priv, offset, REG_GPIO_DATA | + REG_GPIO_PERIPH | REG_GPIO_MODE, + set | FIELD_PREP(REG_GPIO_MODE, REG_GPIO_OUT)); + return 0; +} + +static int apple_gpio_probe(struct udevice *dev) +{ + struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent); + struct gpio_dev_priv *uc_priv; + + uc_priv = dev_get_uclass_priv(dev); + uc_priv->bank_name = "gpio"; + uc_priv->gpio_count = priv->pin_count; + + return 0; +} + +static struct dm_gpio_ops apple_gpio_ops = { + .get_value = apple_gpio_get_value, + .set_value = apple_gpio_set_value, + .get_function = apple_gpio_get_direction, + .direction_input = apple_gpio_direction_input, + .direction_output = apple_gpio_direction_output, +}; + +static struct driver apple_gpio_driver = { + .name = "apple_gpio", + .id = UCLASS_GPIO, + .probe = apple_gpio_probe, + .ops = &apple_gpio_ops, +}; + +static int apple_pinctrl_get_pins_count(struct udevice *dev) +{ + struct apple_pinctrl_priv *priv = dev_get_priv(dev); + + return priv->pin_count; +} + +static const char *apple_pinctrl_get_pin_name(struct udevice *dev, + unsigned selector) +{ + static char pin_name[PINNAME_SIZE]; + + snprintf(pin_name, PINNAME_SIZE, "pin%d", selector); + return pin_name; +} + +static int apple_pinctrl_get_pin_muxing(struct udevice *dev, unsigned selector, + char *buf, int size) +{ + struct apple_pinctrl_priv *priv = dev_get_priv(dev); + + if (readl(priv->base + REG_GPIO(selector)) & REG_GPIO_PERIPH) + strncpy(buf, "periph", size); + else + strncpy(buf, "gpio", size); + return 0; +} + +static int apple_pinctrl_pinmux_set(struct udevice *dev, unsigned pin_selector, + unsigned func_selector) +{ + struct apple_pinctrl_priv *priv = dev_get_priv(dev); + + apple_pinctrl_config_pin(priv, pin_selector, + REG_GPIO_DATA | REG_GPIO_MODE, + FIELD_PREP(REG_GPIO_PERIPH, func_selector) | + REG_GPIO_INPUT_ENABLE); + return 0; +} + +static int apple_pinctrl_pinmux_property_set(struct udevice *dev, + u32 pinmux_group) +{ + unsigned pin_selector = APPLE_PIN(pinmux_group); + unsigned func_selector = APPLE_FUNC(pinmux_group); + int ret; + + ret = apple_pinctrl_pinmux_set(dev, pin_selector, func_selector); + return ret ? ret : pin_selector; +} + +static int apple_pinctrl_probe(struct udevice *dev) +{ + struct apple_pinctrl_priv *priv = dev_get_priv(dev); + struct ofnode_phandle_args args; + struct udevice *child; + + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) + return -EINVAL; + + if (!dev_read_phandle_with_args(dev, "gpio-ranges", + NULL, 3, 0, &args)) + priv->pin_count = args.args[2]; + + device_bind(dev, &apple_gpio_driver, "apple_gpio", NULL, + dev_ofnode(dev), &child); + + return 0; +} + +static struct pinctrl_ops apple_pinctrl_ops = { + .set_state = pinctrl_generic_set_state, + .get_pins_count = apple_pinctrl_get_pins_count, + .get_pin_name = apple_pinctrl_get_pin_name, + .pinmux_set = apple_pinctrl_pinmux_set, + .pinmux_property_set = apple_pinctrl_pinmux_property_set, + .get_pin_muxing = apple_pinctrl_get_pin_muxing, +}; + +static const struct udevice_id apple_pinctrl_ids[] = { + { .compatible = "apple,pinctrl" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(pinctrl_apple) = { + .name = "apple_pinctrl", + .id = UCLASS_PINCTRL, + .of_match = apple_pinctrl_ids, + .priv_auto = sizeof(struct apple_pinctrl_priv), + .ops = &apple_pinctrl_ops, + .probe = apple_pinctrl_probe, +}; -- cgit v1.2.3 From a4bc38da27dfc170e87b5849115cc8faedb6ae90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 3 Nov 2021 01:01:05 +0100 Subject: pci: Add standard PCIe ECAM macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lot of PCIe controllers are using ECAM addressing. So add common ECAM macros into U-Boot's pci.h header file which can be suitable for most PCI controller drivers. Replace custom ECAM address macros in every PCI controller driver by new ECAM macros from U-Boot's pci.h header file. Similar macros are defined also in Linux kernel. There is a small difference between Linux and these new U-Boot macros. U-Boot's PCIE_ECAM_OFFSET() takes device and function numbers in separate arguments. Linux's PCIE_ECAM_OFFSET() takes device and function numbers encoded in one argument. The reason is that U-Boot's PCI_DEVFN() macro is different than Linux's PCI_SLOT() macro. So having device and function numbers in separate arguments makes code more straightforward. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- drivers/pci/pci-aardvark.c | 14 ++------------ drivers/pci/pcie_ecam_generic.c | 6 ++---- drivers/pci/pcie_ecam_synquacer.c | 6 ++---- drivers/pci/pcie_phytium.c | 8 ++------ drivers/pci/pcie_rockchip.c | 13 ++----------- drivers/pci/pcie_xilinx.c | 5 +---- 6 files changed, 11 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-aardvark.c b/drivers/pci/pci-aardvark.c index 4e94b776c5b..6d73aab03f9 100644 --- a/drivers/pci/pci-aardvark.c +++ b/drivers/pci/pci-aardvark.c @@ -165,16 +165,6 @@ #define PCIE_CONFIG_WR_TYPE0 0xa #define PCIE_CONFIG_WR_TYPE1 0xb -/* PCI_BDF shifts 8bit, so we need extra 4bit shift */ -#define PCIE_BDF(b, d, f) (PCI_BDF(b, d, f) << 4) -#define PCIE_CONF_BUS(bus) (((bus) & 0xff) << 20) -#define PCIE_CONF_DEV(dev) (((dev) & 0x1f) << 15) -#define PCIE_CONF_FUNC(fun) (((fun) & 0x7) << 12) -#define PCIE_CONF_REG(reg) ((reg) & 0xffc) -#define PCIE_CONF_ADDR(bus, devfn, where) \ - (PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn)) | \ - PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where)) - /* PCIe Retries & Timeout definitions */ #define PIO_MAX_RETRIES 1500 #define PIO_WAIT_TIMEOUT 1000 @@ -468,7 +458,7 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf, advk_writel(pcie, reg, PIO_CTRL); /* Program the address registers */ - reg = PCIE_BDF(busno, PCI_DEV(bdf), PCI_FUNC(bdf)) | PCIE_CONF_REG(offset); + reg = PCIE_ECAM_OFFSET(busno, PCI_DEV(bdf), PCI_FUNC(bdf), (offset & ~0x3)); advk_writel(pcie, reg, PIO_ADDR_LS); advk_writel(pcie, 0, PIO_ADDR_MS); @@ -628,7 +618,7 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf, advk_writel(pcie, reg, PIO_CTRL); /* Program the address registers */ - reg = PCIE_BDF(busno, PCI_DEV(bdf), PCI_FUNC(bdf)) | PCIE_CONF_REG(offset); + reg = PCIE_ECAM_OFFSET(busno, PCI_DEV(bdf), PCI_FUNC(bdf), (offset & ~0x3)); advk_writel(pcie, reg, PIO_ADDR_LS); advk_writel(pcie, 0, PIO_ADDR_MS); dev_dbg(pcie->dev, "\tPIO req. - addr = 0x%08x\n", reg); diff --git a/drivers/pci/pcie_ecam_generic.c b/drivers/pci/pcie_ecam_generic.c index e83e5aff206..09b6fc1fd5d 100644 --- a/drivers/pci/pcie_ecam_generic.c +++ b/drivers/pci/pcie_ecam_generic.c @@ -46,10 +46,8 @@ static int pci_generic_ecam_conf_address(const struct udevice *bus, void *addr; addr = pcie->cfg_base; - addr += (PCI_BUS(bdf) - pcie->first_busno) << 20; - addr += PCI_DEV(bdf) << 15; - addr += PCI_FUNC(bdf) << 12; - addr += offset; + addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf) - pcie->first_busno, + PCI_DEV(bdf), PCI_FUNC(bdf), offset); *paddress = addr; return 0; diff --git a/drivers/pci/pcie_ecam_synquacer.c b/drivers/pci/pcie_ecam_synquacer.c index c6e7c59f8a6..e3e22891088 100644 --- a/drivers/pci/pcie_ecam_synquacer.c +++ b/drivers/pci/pcie_ecam_synquacer.c @@ -235,10 +235,8 @@ static int pci_synquacer_ecam_conf_address(const struct udevice *bus, void *addr; addr = pcie->cfg_base; - addr += (PCI_BUS(bdf) - pcie->first_busno) << 20; - addr += PCI_DEV(bdf) << 15; - addr += PCI_FUNC(bdf) << 12; - addr += offset; + addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf) - pcie->first_busno, + PCI_DEV(bdf), PCI_FUNC(bdf), offset); *paddress = addr; return 0; diff --git a/drivers/pci/pcie_phytium.c b/drivers/pci/pcie_phytium.c index 752e1703215..a8072762542 100644 --- a/drivers/pci/pcie_phytium.c +++ b/drivers/pci/pcie_phytium.c @@ -36,9 +36,7 @@ static int phytium_pci_skip_dev(pci_dev_t parent) unsigned short capreg; unsigned char port_type; - addr += PCI_BUS(parent) << 20; - addr += PCI_DEV(parent) << 15; - addr += PCI_FUNC(parent) << 12; + addr += PCIE_ECAM_OFFSET(PCI_BUS(parent), PCI_DEV(parent), PCI_FUNC(parent), 0); pos = 0x34; while (1) { @@ -89,9 +87,7 @@ static int pci_phytium_conf_address(const struct udevice *bus, pci_dev_t bdf, bdf_parent = PCI_BDF((bus_no - 1), 0, 0); addr = pcie->cfg_base; - addr += PCI_BUS(bdf) << 20; - addr += PCI_DEV(bdf) << 15; - addr += PCI_FUNC(bdf) << 12; + addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), 0); if (bus_no > 0 && dev_no > 0) { if ((readb(addr + PCI_HEADER_TYPE) & 0x7f) != diff --git a/drivers/pci/pcie_rockchip.c b/drivers/pci/pcie_rockchip.c index b0c91c0f430..67039d2a29f 100644 --- a/drivers/pci/pcie_rockchip.c +++ b/drivers/pci/pcie_rockchip.c @@ -101,15 +101,6 @@ struct rockchip_pcie { struct phy pcie_phy; }; -static int rockchip_pcie_off_conf(pci_dev_t bdf, uint offset) -{ - unsigned int bus = PCI_BUS(bdf); - unsigned int dev = PCI_DEV(bdf); - unsigned int func = PCI_FUNC(bdf); - - return (bus << 20) | (dev << 15) | (func << 12) | (offset & ~0x3); -} - static int rockchip_pcie_rd_conf(const struct udevice *udev, pci_dev_t bdf, uint offset, ulong *valuep, enum pci_size_t size) @@ -117,7 +108,7 @@ static int rockchip_pcie_rd_conf(const struct udevice *udev, pci_dev_t bdf, struct rockchip_pcie *priv = dev_get_priv(udev); unsigned int bus = PCI_BUS(bdf); unsigned int dev = PCI_DEV(bdf); - int where = rockchip_pcie_off_conf(bdf, offset); + int where = PCIE_ECAM_OFFSET(PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), offset & ~0x3); ulong value; if (bus == priv->first_busno && dev == 0) { @@ -144,7 +135,7 @@ static int rockchip_pcie_wr_conf(struct udevice *udev, pci_dev_t bdf, struct rockchip_pcie *priv = dev_get_priv(udev); unsigned int bus = PCI_BUS(bdf); unsigned int dev = PCI_DEV(bdf); - int where = rockchip_pcie_off_conf(bdf, offset); + int where = PCIE_ECAM_OFFSET(PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), offset & ~0x3); ulong old; if (bus == priv->first_busno && dev == 0) { diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c index ae9a65b0a9e..eb9ec97b74f 100644 --- a/drivers/pci/pcie_xilinx.c +++ b/drivers/pci/pcie_xilinx.c @@ -76,10 +76,7 @@ static int pcie_xilinx_config_address(const struct udevice *udev, pci_dev_t bdf, return -ENODEV; addr = pcie->cfg_base; - addr += bus << 20; - addr += dev << 15; - addr += func << 12; - addr += offset; + addr += PCIE_ECAM_OFFSET(bus, dev, func, offset); *paddress = addr; return 0; -- cgit v1.2.3 From faf5d4d53d435bb4e15768cc135b6268b5104bbc Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Fri, 5 Nov 2021 14:34:14 +0100 Subject: mmc: mtk-sd: implement waiting for DAT0 line state With the recent changes on mmc driver, we saw that the boot is ~5 secs longer compared to v2021.07 on mediatek platforms. This regression is seen during mmc_init and caused by the following patch [1]. Indeed since we did not support poll dat0, we fulfilled the condition of [1] and a delay of 500 ms was added for every __mmc_switch call. By adding the support of wait_dat0(), we now don't need to mdelay during mmc_init anymore. [1]: https://patchwork.ozlabs.org/project/uboot/patch/1629192034-64056-1-git-send-email-ye.li@nxp.com/ Signed-off-by: Julien Masson Reviewed-by: Jaehoon Chung --- drivers/mmc/mtk-sd.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c index 8599f095bcd..97182ffd7f5 100644 --- a/drivers/mmc/mtk-sd.c +++ b/drivers/mmc/mtk-sd.c @@ -1724,6 +1724,20 @@ static int msdc_drv_bind(struct udevice *dev) return mmc_bind(dev, &plat->mmc, &plat->cfg); } +static int msdc_ops_wait_dat0(struct udevice *dev, int state, int timeout_us) +{ + struct msdc_host *host = dev_get_priv(dev); + int ret; + u32 reg; + + ret = readl_poll_sleep_timeout(&host->base->msdc_ps, reg, + !!(reg & MSDC_PS_DAT0) == !!state, + 1000, /* 1 ms */ + timeout_us); + + return ret; +} + static const struct dm_mmc_ops msdc_ops = { .send_cmd = msdc_ops_send_cmd, .set_ios = msdc_ops_set_ios, @@ -1732,6 +1746,7 @@ static const struct dm_mmc_ops msdc_ops = { #ifdef MMC_SUPPORTS_TUNING .execute_tuning = msdc_execute_tuning, #endif + .wait_dat0 = msdc_ops_wait_dat0, }; static const struct msdc_compatible mt7620_compat = { -- cgit v1.2.3 From 4080714f5ee9253715ce72ebb4da4a02f4a9b3a0 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Wed, 27 Oct 2021 14:17:26 +0800 Subject: clk: ast2600: Add YCLK control for HACE Add YCLK enable for HACE, the HW hash engine of ASPEED AST2600 SoCs. Signed-off-by: Joel Stanley Signed-off-by: Chia-Wei Wang --- drivers/clk/aspeed/clk_ast2600.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/aspeed/clk_ast2600.c b/drivers/clk/aspeed/clk_ast2600.c index 3a92739f5cf..9871a6bdbfd 100644 --- a/drivers/clk/aspeed/clk_ast2600.c +++ b/drivers/clk/aspeed/clk_ast2600.c @@ -1013,6 +1013,25 @@ static ulong ast2600_enable_usbbhclk(struct ast2600_scu *scu) return 0; } +static ulong ast2600_enable_haceclk(struct ast2600_scu *scu) +{ + uint32_t reset_bit; + uint32_t clkgate_bit; + + reset_bit = BIT(ASPEED_RESET_HACE); + clkgate_bit = SCU_CLKGATE1_HACE; + + /* + * we don't do reset assertion here as HACE + * shares the same reset control with ACRY + */ + writel(clkgate_bit, &scu->clkgate_clr1); + mdelay(20); + writel(reset_bit, &scu->modrst_clr1); + + return 0; +} + static int ast2600_clk_enable(struct clk *clk) { struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); @@ -1051,6 +1070,9 @@ static int ast2600_clk_enable(struct clk *clk) case ASPEED_CLK_GATE_USBPORT2CLK: ast2600_enable_usbbhclk(priv->scu); break; + case ASPEED_CLK_GATE_YCLK: + ast2600_enable_haceclk(priv->scu); + break; default: pr_err("can't enable clk\n"); return -ENOENT; -- cgit v1.2.3 From 9fcdd98e543abc0b5e7b1a2e05b995a5fbf1356d Mon Sep 17 00:00:00 2001 From: Johnny Huang Date: Wed, 27 Oct 2021 14:17:27 +0800 Subject: crypto: aspeed: Add AST2600 HACE support Hash and Crypto Engine (HACE) is designed to accelerate the throughput of hash data digest, and symmetric-key encryption. Signed-off-by: Johnny Huang Signed-off-by: Chia-Wei Wang Reviewed-by: Simon Glass --- drivers/crypto/Kconfig | 2 + drivers/crypto/Makefile | 1 + drivers/crypto/aspeed/Kconfig | 10 + drivers/crypto/aspeed/Makefile | 1 + drivers/crypto/aspeed/aspeed_hace.c | 381 ++++++++++++++++++++++++++++++++++++ drivers/crypto/hash/Kconfig | 8 + 6 files changed, 403 insertions(+) create mode 100644 drivers/crypto/aspeed/Kconfig create mode 100644 drivers/crypto/aspeed/Makefile create mode 100644 drivers/crypto/aspeed/aspeed_hace.c (limited to 'drivers') diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 0082177c21f..675081ecd37 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -4,4 +4,6 @@ source drivers/crypto/hash/Kconfig source drivers/crypto/fsl/Kconfig +source drivers/crypto/aspeed/Kconfig + endmenu diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index e8bae43e3f0..6b762565a1f 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_EXYNOS_ACE_SHA) += ace_sha.o obj-y += rsa_mod_exp/ obj-y += fsl/ obj-y += hash/ +obj-y += aspeed/ diff --git a/drivers/crypto/aspeed/Kconfig b/drivers/crypto/aspeed/Kconfig new file mode 100644 index 00000000000..471c06f986d --- /dev/null +++ b/drivers/crypto/aspeed/Kconfig @@ -0,0 +1,10 @@ +config ASPEED_HACE + bool "ASPEED Hash and Crypto Engine" + depends on DM_HASH + help + Select this option to enable a driver for using the SHA engine in + the ASPEED BMC SoCs. + + Enabling this allows the use of SHA operations in hardware without + requiring the SHA software implementations. It also improves performance + and saves code size. diff --git a/drivers/crypto/aspeed/Makefile b/drivers/crypto/aspeed/Makefile new file mode 100644 index 00000000000..84e6bfe82a8 --- /dev/null +++ b/drivers/crypto/aspeed/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ASPEED_HACE) += aspeed_hace.o diff --git a/drivers/crypto/aspeed/aspeed_hace.c b/drivers/crypto/aspeed/aspeed_hace.c new file mode 100644 index 00000000000..1178cc6a769 --- /dev/null +++ b/drivers/crypto/aspeed/aspeed_hace.c @@ -0,0 +1,381 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2021 ASPEED Technology Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* register offsets*/ +#define HACE_STS 0x1C +#define HACE_HASH_DATA_OVF BIT(23) +#define HACE_HASH_INT BIT(9) +#define HACE_HASH_BUSY BIT(0) +#define HACE_HASH_DATA 0x20 +#define HACE_HASH_DIGEST 0x24 +#define HACE_HASH_HMAC_KEY 0x28 +#define HACE_HASH_DATA_LEN 0x2C +#define HACE_HASH_CMD 0x30 +#define HACE_HASH_MODE_ACCUM BIT(8) +#define HACE_HASH_ALGO_SHA1 BIT(5) +#define HACE_HASH_ALGO_SHA256 (BIT(6) | BIT(4)) +#define HACE_HASH_ALGO_SHA384 (BIT(10) | BIT(6) | BIT(5)) +#define HACE_HASH_ALGO_SHA512 (BIT(6) | BIT(5)) +#define HACE_HASH_SHA_BE_EN BIT(3) + +/* buffer size based on SHA-512 need*/ +#define HASH_BLOCK_BUFSZ 128 +#define HASH_DIGEST_BUFSZ 64 + +struct aspeed_hace_ctx { + uint8_t digest[HASH_DIGEST_BUFSZ]; + + uint32_t cmd; + enum HASH_ALGO algo; + + uint32_t blk_size; + uint32_t pad_size; + uint64_t total[2]; + + uint8_t buf[HASH_BLOCK_BUFSZ]; + uint32_t buf_cnt; +} __aligned((8)); + +struct aspeed_hace { + phys_addr_t base; + struct clk clk; +}; + +static const uint32_t iv_sha1[8] = { + 0x01234567, 0x89abcdef, 0xfedcba98, 0x76543210, + 0xf0e1d2c3, 0, 0, 0 +}; + +static const uint32_t iv_sha256[8] = { + 0x67e6096a, 0x85ae67bb, 0x72f36e3c, 0x3af54fa5, + 0x7f520e51, 0x8c68059b, 0xabd9831f, 0x19cde05bUL +}; + +static const uint32_t iv_sha384[16] = { + 0x5d9dbbcb, 0xd89e05c1, 0x2a299a62, 0x07d57c36, + 0x5a015991, 0x17dd7030, 0xd8ec2f15, 0x39590ef7, + 0x67263367, 0x310bc0ff, 0x874ab48e, 0x11155868, + 0x0d2e0cdb, 0xa78ff964, 0x1d48b547, 0xa44ffabeUL +}; + +static const uint32_t iv_sha512[16] = { + 0x67e6096a, 0x08c9bcf3, 0x85ae67bb, 0x3ba7ca84, + 0x72f36e3c, 0x2bf894fe, 0x3af54fa5, 0xf1361d5f, + 0x7f520e51, 0xd182e6ad, 0x8c68059b, 0x1f6c3e2b, + 0xabd9831f, 0x6bbd41fb, 0x19cde05b, 0x79217e13UL +}; + +static int aspeed_hace_wait_completion(uint32_t reg, uint32_t flag, int timeout_us) +{ + uint32_t val; + + return readl_poll_timeout(reg, val, (val & flag) == flag, timeout_us); +} + +static int aspeed_hace_process(struct udevice *dev, void *ctx, const void *ibuf, uint32_t ilen) +{ + struct aspeed_hace *hace = dev_get_priv(dev); + struct aspeed_hace_ctx *hace_ctx = (struct aspeed_hace_ctx *)ctx; + uint32_t sts = readl(hace->base + HACE_STS); + + if (sts & HACE_HASH_BUSY) { + debug("HACE engine busy\n"); + return -EBUSY; + } + + writel(HACE_HASH_INT, hace->base + HACE_STS); + + writel((uint32_t)ibuf, hace->base + HACE_HASH_DATA); + writel((uint32_t)hace_ctx->digest, hace->base + HACE_HASH_DIGEST); + writel((uint32_t)hace_ctx->digest, hace->base + HACE_HASH_HMAC_KEY); + writel(ilen, hace->base + HACE_HASH_DATA_LEN); + writel(hace_ctx->cmd, hace->base + HACE_HASH_CMD); + + return aspeed_hace_wait_completion(hace->base + HACE_STS, + HACE_HASH_INT, + 1000 + (ilen >> 3)); +} + +static int aspeed_hace_init(struct udevice *dev, enum HASH_ALGO algo, void **ctxp) +{ + struct aspeed_hace_ctx *hace_ctx; + + hace_ctx = memalign(8, sizeof(struct aspeed_hace_ctx)); + if (!hace_ctx) + return -ENOMEM; + + memset(hace_ctx, 0, sizeof(struct aspeed_hace_ctx)); + + hace_ctx->algo = algo; + hace_ctx->cmd = HACE_HASH_MODE_ACCUM | HACE_HASH_SHA_BE_EN; + + switch (algo) { + case HASH_ALGO_SHA1: + hace_ctx->blk_size = 64; + hace_ctx->pad_size = 8; + hace_ctx->cmd |= HACE_HASH_ALGO_SHA1; + memcpy(hace_ctx->digest, iv_sha1, sizeof(iv_sha1)); + break; + case HASH_ALGO_SHA256: + hace_ctx->blk_size = 64; + hace_ctx->pad_size = 8; + hace_ctx->cmd |= HACE_HASH_ALGO_SHA256; + memcpy(hace_ctx->digest, iv_sha256, sizeof(iv_sha256)); + break; + case HASH_ALGO_SHA384: + hace_ctx->blk_size = 128; + hace_ctx->pad_size = 16; + hace_ctx->cmd |= HACE_HASH_ALGO_SHA384; + memcpy(hace_ctx->digest, iv_sha384, sizeof(iv_sha384)); + break; + case HASH_ALGO_SHA512: + hace_ctx->blk_size = 128; + hace_ctx->pad_size = 16; + hace_ctx->cmd |= HACE_HASH_ALGO_SHA512; + memcpy(hace_ctx->digest, iv_sha512, sizeof(iv_sha512)); + break; + default: + debug("Unsupported hash algorithm '%s'\n", hash_algo_name(algo)); + goto free_n_out; + }; + + *ctxp = hace_ctx; + + return 0; + +free_n_out: + free(hace_ctx); + + return -EINVAL; +} + +static int aspeed_hace_update(struct udevice *dev, void *ctx, const void *ibuf, uint32_t ilen) +{ + int rc; + uint32_t left, fill; + struct aspeed_hace_ctx *hace_ctx = ctx; + + left = hace_ctx->total[0] & (hace_ctx->blk_size - 1); + fill = hace_ctx->blk_size - left; + + hace_ctx->total[0] += ilen; + if (hace_ctx->total[0] < ilen) + hace_ctx->total[1]++; + + if (left && ilen >= fill) { + memcpy(hace_ctx->buf + left, ibuf, fill); + rc = aspeed_hace_process(dev, ctx, hace_ctx->buf, hace_ctx->blk_size); + if (rc) { + debug("failed to process hash, rc=%d\n", rc); + return rc; + } + ilen -= fill; + ibuf += fill; + left = 0; + } + + while (ilen >= hace_ctx->blk_size) { + rc = aspeed_hace_process(dev, ctx, ibuf, hace_ctx->blk_size); + if (rc) { + debug("failed to process hash, rc=%d\n", rc); + return rc; + } + + ibuf += hace_ctx->blk_size; + ilen -= hace_ctx->blk_size; + } + + if (ilen) + memcpy(hace_ctx->buf + left, ibuf, ilen); + + return 0; +} + +static int aspeed_hace_finish(struct udevice *dev, void *ctx, void *obuf) +{ + int rc = 0; + uint8_t pad[HASH_BLOCK_BUFSZ * 2]; + uint32_t last, padn; + uint64_t ibits_h, ibits_l; + uint64_t ibits_be_h, ibits_be_l; + struct aspeed_hace_ctx *hace_ctx = ctx; + + memset(pad, 0, sizeof(pad)); + pad[0] = 0x80; + + ibits_h = (hace_ctx->total[0] >> 61) | (hace_ctx->total[1] << 3); + ibits_be_h = cpu_to_be64(ibits_h); + + ibits_l = (hace_ctx->total[0] << 3); + ibits_be_l = cpu_to_be64(ibits_l); + + last = hace_ctx->total[0] & (hace_ctx->blk_size - 1); + + switch (hace_ctx->algo) { + case HASH_ALGO_SHA1: + case HASH_ALGO_SHA256: + padn = (last < 56) ? (56 - last) : (120 - last); + + rc = aspeed_hace_update(dev, ctx, pad, padn); + if (rc) { + debug("failed to append padding, rc=%d\n", rc); + goto free_n_out; + } + + rc = aspeed_hace_update(dev, ctx, &ibits_be_l, sizeof(ibits_be_l)); + if (rc) { + debug("failed to append message bits length, rc=%d\n", rc); + goto free_n_out; + } + + break; + case HASH_ALGO_SHA384: + case HASH_ALGO_SHA512: + padn = (last < 112) ? (112 - last) : (240 - last); + + rc = aspeed_hace_update(dev, ctx, pad, padn); + if (rc) { + debug("failed to append padding, rc=%d\n", rc); + goto free_n_out; + } + + rc = aspeed_hace_update(dev, ctx, &ibits_be_h, sizeof(ibits_be_h)) | + aspeed_hace_update(dev, ctx, &ibits_be_l, sizeof(ibits_be_l)); + if (rc) { + debug("failed to append message bits length, rc=%d\n", rc); + goto free_n_out; + } + + break; + default: + rc = -EINVAL; + break; + } + + memcpy(obuf, hace_ctx->digest, hash_algo_digest_size(hace_ctx->algo)); + +free_n_out: + free(ctx); + + return rc; +} + +static int aspeed_hace_digest_wd(struct udevice *dev, enum HASH_ALGO algo, + const void *ibuf, const uint32_t ilen, + void *obuf, uint32_t chunk_sz) +{ + int rc; + void *ctx; + const void *cur, *end; + uint32_t chunk; + + rc = aspeed_hace_init(dev, algo, &ctx); + if (rc) + return rc; + + if (CONFIG_IS_ENABLED(HW_WATCHDOG) || CONFIG_IS_ENABLED(WATCHDOG)) { + cur = ibuf; + end = ibuf + ilen; + + while (cur < end) { + chunk = end - cur; + if (chunk > chunk_sz) + chunk = chunk_sz; + + rc = aspeed_hace_update(dev, ctx, cur, chunk); + if (rc) + return rc; + + cur += chunk; + WATCHDOG_RESET(); + } + } else { + rc = aspeed_hace_update(dev, ctx, ibuf, ilen); + if (rc) + return rc; + } + + rc = aspeed_hace_finish(dev, ctx, obuf); + if (rc) + return rc; + + return 0; +} + +static int aspeed_hace_digest(struct udevice *dev, enum HASH_ALGO algo, + const void *ibuf, const uint32_t ilen, + void *obuf) +{ + /* re-use the watchdog version with input length as the chunk_sz */ + return aspeed_hace_digest_wd(dev, algo, ibuf, ilen, obuf, ilen); +} + +static int aspeed_hace_probe(struct udevice *dev) +{ + int rc; + struct aspeed_hace *hace = dev_get_priv(dev); + + rc = clk_get_by_index(dev, 0, &hace->clk); + if (rc < 0) { + debug("cannot get clock for %s: %d\n", dev->name, rc); + return rc; + } + + rc = clk_enable(&hace->clk); + if (rc) { + debug("cannot enable clock for %s: %d\n", dev->name, rc); + return rc; + } + + hace->base = devfdt_get_addr(dev); + + return rc; +} + +static int aspeed_hace_remove(struct udevice *dev) +{ + struct aspeed_hace *hace = dev_get_priv(dev); + + clk_disable(&hace->clk); + + return 0; +} + +static const struct hash_ops aspeed_hace_ops = { + .hash_init = aspeed_hace_init, + .hash_update = aspeed_hace_update, + .hash_finish = aspeed_hace_finish, + .hash_digest_wd = aspeed_hace_digest_wd, + .hash_digest = aspeed_hace_digest, +}; + +static const struct udevice_id aspeed_hace_ids[] = { + { .compatible = "aspeed,ast2600-hace" }, + { } +}; + +U_BOOT_DRIVER(aspeed_hace) = { + .name = "aspeed_hace", + .id = UCLASS_HASH, + .of_match = aspeed_hace_ids, + .ops = &aspeed_hace_ops, + .probe = aspeed_hace_probe, + .remove = aspeed_hace_remove, + .priv_auto = sizeof(struct aspeed_hace), + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/crypto/hash/Kconfig b/drivers/crypto/hash/Kconfig index cd29a5c6a4f..bf9540eca67 100644 --- a/drivers/crypto/hash/Kconfig +++ b/drivers/crypto/hash/Kconfig @@ -14,3 +14,11 @@ config HASH_SOFTWARE help Enable driver for hashing operations in software. Currently it support multiple hash algorithm including CRC/MD5/SHA. + +config HASH_ASPEED + bool "Enable Hash with ASPEED hash accelerator" + depends on DM_HASH + select ASPEED_HACE + help + Enable this to support HW-assisted hashing operations using ASPEED Hash + and Crypto engine - HACE -- cgit v1.2.3 From af6451187c2b93a05a03ca6e9f4f33cabf6da04a Mon Sep 17 00:00:00 2001 From: Chia-Wei Wang Date: Wed, 27 Oct 2021 14:17:29 +0800 Subject: clk: ast2600: Add RSACLK control for ACRY Add RSACLK enable for ACRY, the HW RSA/ECC crypto engine of ASPEED AST2600 SoCs. Signed-off-by: Chia-Wei Wang --- drivers/clk/aspeed/clk_ast2600.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/aspeed/clk_ast2600.c b/drivers/clk/aspeed/clk_ast2600.c index 9871a6bdbfd..42ca39421cf 100644 --- a/drivers/clk/aspeed/clk_ast2600.c +++ b/drivers/clk/aspeed/clk_ast2600.c @@ -1018,6 +1018,7 @@ static ulong ast2600_enable_haceclk(struct ast2600_scu *scu) uint32_t reset_bit; uint32_t clkgate_bit; + /* share the same reset control bit with ACRY */ reset_bit = BIT(ASPEED_RESET_HACE); clkgate_bit = SCU_CLKGATE1_HACE; @@ -1032,6 +1033,26 @@ static ulong ast2600_enable_haceclk(struct ast2600_scu *scu) return 0; } +static ulong ast2600_enable_rsaclk(struct ast2600_scu *scu) +{ + uint32_t reset_bit; + uint32_t clkgate_bit; + + /* same reset control bit with HACE */ + reset_bit = BIT(ASPEED_RESET_HACE); + clkgate_bit = SCU_CLKGATE1_ACRY; + + /* + * we don't do reset assertion here as HACE + * shares the same reset control with ACRY + */ + writel(clkgate_bit, &scu->clkgate_clr1); + mdelay(20); + writel(reset_bit, &scu->modrst_clr1); + + return 0; +} + static int ast2600_clk_enable(struct clk *clk) { struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); @@ -1073,6 +1094,9 @@ static int ast2600_clk_enable(struct clk *clk) case ASPEED_CLK_GATE_YCLK: ast2600_enable_haceclk(priv->scu); break; + case ASPEED_CLK_GATE_RSACLK: + ast2600_enable_rsaclk(priv->scu); + break; default: pr_err("can't enable clk\n"); return -ENOENT; -- cgit v1.2.3 From 89c36cca0b697d80a6ed063b945d66cc59a761a8 Mon Sep 17 00:00:00 2001 From: Chia-Wei Wang Date: Wed, 27 Oct 2021 14:17:30 +0800 Subject: crypto: aspeed: Add AST2600 ACRY support ACRY is designed to accelerate ECC/RSA digital signature generation and verification. Signed-off-by: Chia-Wei Wang --- drivers/crypto/aspeed/Kconfig | 10 ++ drivers/crypto/aspeed/Makefile | 1 + drivers/crypto/aspeed/aspeed_acry.c | 190 ++++++++++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 drivers/crypto/aspeed/aspeed_acry.c (limited to 'drivers') diff --git a/drivers/crypto/aspeed/Kconfig b/drivers/crypto/aspeed/Kconfig index 471c06f986d..9bf317177aa 100644 --- a/drivers/crypto/aspeed/Kconfig +++ b/drivers/crypto/aspeed/Kconfig @@ -8,3 +8,13 @@ config ASPEED_HACE Enabling this allows the use of SHA operations in hardware without requiring the SHA software implementations. It also improves performance and saves code size. + +config ASPEED_ACRY + bool "ASPEED RSA and ECC Engine" + depends on ASPEED_AST2600 + help + Select this option to enable a driver for using the RSA/ECC engine in + the ASPEED BMC SoCs. + + Enabling this allows the use of RSA/ECC operations in hardware without requiring the + software implementations. It also improves performance and saves code size. diff --git a/drivers/crypto/aspeed/Makefile b/drivers/crypto/aspeed/Makefile index 84e6bfe82a8..58b55fc46e4 100644 --- a/drivers/crypto/aspeed/Makefile +++ b/drivers/crypto/aspeed/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_ASPEED_HACE) += aspeed_hace.o +obj-$(CONFIG_ASPEED_ACRY) += aspeed_acry.o diff --git a/drivers/crypto/aspeed/aspeed_acry.c b/drivers/crypto/aspeed/aspeed_acry.c new file mode 100644 index 00000000000..c28cdf374b6 --- /dev/null +++ b/drivers/crypto/aspeed/aspeed_acry.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2021 ASPEED Technology Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ACRY register offsets */ +#define ACRY_CTRL1 0x00 +#define ACRY_CTRL1_RSA_DMA BIT(1) +#define ACRY_CTRL1_RSA_START BIT(0) +#define ACRY_CTRL2 0x44 +#define ACRY_CTRL3 0x48 +#define ACRY_CTRL3_SRAM_AHB_ACCESS BIT(8) +#define ACRY_CTRL3_ECC_RSA_MODE_MASK GENMASK(5, 4) +#define ACRY_CTRL3_ECC_RSA_MODE_SHIFT 4 +#define ACRY_DMA_DRAM_SADDR 0x4c +#define ACRY_DMA_DMEM_TADDR 0x50 +#define ACRY_DMA_DMEM_TADDR_LEN_MASK GENMASK(15, 0) +#define ACRY_DMA_DMEM_TADDR_LEN_SHIFT 0 +#define ACRY_RSA_PARAM 0x58 +#define ACRY_RSA_PARAM_EXP_MASK GENMASK(31, 16) +#define ACRY_RSA_PARAM_EXP_SHIFT 16 +#define ACRY_RSA_PARAM_MOD_MASK GENMASK(15, 0) +#define ACRY_RSA_PARAM_MOD_SHIFT 0 +#define ACRY_RSA_INT_EN 0x3f8 +#define ACRY_RSA_INT_EN_RSA_READY BIT(2) +#define ACRY_RSA_INT_EN_RSA_CMPLT BIT(1) +#define ACRY_RSA_INT_STS 0x3fc +#define ACRY_RSA_INT_STS_RSA_READY BIT(2) +#define ACRY_RSA_INT_STS_RSA_CMPLT BIT(1) + +/* misc. constant */ +#define ACRY_ECC_MODE 2 +#define ACRY_RSA_MODE 3 +#define ACRY_CTX_BUFSZ 0x600 + +struct aspeed_acry { + phys_addr_t base; + phys_addr_t sram_base; /* internal sram */ + struct clk clk; +}; + +static int aspeed_acry_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len, + struct key_prop *prop, uint8_t *out) +{ + int i, j; + u8 *ctx; + u8 *ptr; + u32 reg; + struct aspeed_acry *acry = dev_get_priv(dev); + + ctx = memalign(16, ACRY_CTX_BUFSZ); + if (!ctx) + return -ENOMEM; + + memset(ctx, 0, ACRY_CTX_BUFSZ); + + ptr = (u8 *)prop->public_exponent; + for (i = prop->exp_len - 1, j = 0; i >= 0; --i) { + ctx[j] = ptr[i]; + j++; + j = (j % 16) ? j : j + 32; + } + + ptr = (u8 *)prop->modulus; + for (i = (prop->num_bits >> 3) - 1, j = 0; i >= 0; --i) { + ctx[j + 16] = ptr[i]; + j++; + j = (j % 16) ? j : j + 32; + } + + ptr = (u8 *)sig; + for (i = sig_len - 1, j = 0; i >= 0; --i) { + ctx[j + 32] = ptr[i]; + j++; + j = (j % 16) ? j : j + 32; + } + + writel((u32)ctx, acry->base + ACRY_DMA_DRAM_SADDR); + + reg = (((prop->exp_len << 3) << ACRY_RSA_PARAM_EXP_SHIFT) & ACRY_RSA_PARAM_EXP_MASK) | + ((prop->num_bits << ACRY_RSA_PARAM_MOD_SHIFT) & ACRY_RSA_PARAM_MOD_MASK); + writel(reg, acry->base + ACRY_RSA_PARAM); + + reg = (ACRY_CTX_BUFSZ << ACRY_DMA_DMEM_TADDR_LEN_SHIFT) & ACRY_DMA_DMEM_TADDR_LEN_MASK; + writel(reg, acry->base + ACRY_DMA_DMEM_TADDR); + + reg = (ACRY_RSA_MODE << ACRY_CTRL3_ECC_RSA_MODE_SHIFT) & ACRY_CTRL3_ECC_RSA_MODE_MASK; + writel(reg, acry->base + ACRY_CTRL3); + + writel(ACRY_CTRL1_RSA_DMA | ACRY_CTRL1_RSA_START, acry->base + ACRY_CTRL1); + + /* polling RSA status */ + while (1) { + reg = readl(acry->base + ACRY_RSA_INT_STS); + if ((reg & ACRY_RSA_INT_STS_RSA_READY) && (reg & ACRY_RSA_INT_STS_RSA_CMPLT)) { + writel(reg, ACRY_RSA_INT_STS); + break; + } + udelay(20); + } + + /* grant SRAM access permission to CPU */ + writel(0x0, acry->base + ACRY_CTRL1); + writel(ACRY_CTRL3_SRAM_AHB_ACCESS, acry->base + ACRY_CTRL3); + udelay(20); + + for (i = (prop->num_bits / 8) - 1, j = 0; i >= 0; --i) { + out[i] = readb(acry->sram_base + (j + 32)); + j++; + j = (j % 16) ? j : j + 32; + } + + /* return SRAM access permission to ACRY */ + writel(0, acry->base + ACRY_CTRL3); + + free(ctx); + + return 0; +} + +static int aspeed_acry_probe(struct udevice *dev) +{ + struct aspeed_acry *acry = dev_get_priv(dev); + int ret; + + ret = clk_get_by_index(dev, 0, &acry->clk); + if (ret < 0) { + debug("Can't get clock for %s: %d\n", dev->name, ret); + return ret; + } + + ret = clk_enable(&acry->clk); + if (ret) { + debug("Failed to enable acry clock (%d)\n", ret); + return ret; + } + + acry->base = devfdt_get_addr_index(dev, 0); + if (acry->base == FDT_ADDR_T_NONE) { + debug("Failed to get acry base\n"); + return acry->base; + } + + acry->sram_base = devfdt_get_addr_index(dev, 1); + if (acry->sram_base == FDT_ADDR_T_NONE) { + debug("Failed to get acry SRAM base\n"); + return acry->sram_base; + } + + return ret; +} + +static int aspeed_acry_remove(struct udevice *dev) +{ + struct aspeed_acry *acry = dev_get_priv(dev); + + clk_disable(&acry->clk); + + return 0; +} + +static const struct mod_exp_ops aspeed_acry_ops = { + .mod_exp = aspeed_acry_mod_exp, +}; + +static const struct udevice_id aspeed_acry_ids[] = { + { .compatible = "aspeed,ast2600-acry" }, + { } +}; + +U_BOOT_DRIVER(aspeed_acry) = { + .name = "aspeed_acry", + .id = UCLASS_MOD_EXP, + .of_match = aspeed_acry_ids, + .probe = aspeed_acry_probe, + .remove = aspeed_acry_remove, + .priv_auto = sizeof(struct aspeed_acry), + .ops = &aspeed_acry_ops, + .flags = DM_FLAG_PRE_RELOC, +}; -- cgit v1.2.3 From 4f2e2280862aabb22cbdb39d37d524702aa57bcc Mon Sep 17 00:00:00 2001 From: Alistair Delva Date: Wed, 20 Oct 2021 21:31:34 +0000 Subject: RFC: arm: pci: Add PCI cam support to PCI-E ecam driver When booting U-Boot in crosvm, the virtual machine emulates a PCI cam device, not the PCI-E 'ecam' device normally seen on e.g. QEMU. This PCI device can be supported with only trivial changes to the ecam driver. Instead of adding a completely new driver which is identical besides the initialization step, add support for the PCI version to the existing driver. Signed-off-by: Alistair Delva Cc: Tuomas Tynkkynen Cc: Ram Muthiah --- drivers/pci/pcie_ecam_generic.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie_ecam_generic.c b/drivers/pci/pcie_ecam_generic.c index 09b6fc1fd5d..1a9f9aec2ee 100644 --- a/drivers/pci/pcie_ecam_generic.c +++ b/drivers/pci/pcie_ecam_generic.c @@ -14,6 +14,8 @@ #include +#define TYPE_PCI 0x1 + /** * struct generic_ecam_pcie - generic_ecam PCIe controller state * @cfg_base: The base address of memory mapped configuration space @@ -46,8 +48,14 @@ static int pci_generic_ecam_conf_address(const struct udevice *bus, void *addr; addr = pcie->cfg_base; - addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf) - pcie->first_busno, - PCI_DEV(bdf), PCI_FUNC(bdf), offset); + + if (dev_get_driver_data(bus) == TYPE_PCI) { + addr += ((PCI_BUS(bdf) - pcie->first_busno) << 16) | + (PCI_DEV(bdf) << 11) | (PCI_FUNC(bdf) << 8) | offset; + } else { + addr += PCIE_ECAM_OFFSET(PCI_BUS(bdf) - pcie->first_busno, + PCI_DEV(bdf), PCI_FUNC(bdf), offset); + } *paddress = addr; return 0; @@ -156,7 +164,8 @@ static const struct dm_pci_ops pci_generic_ecam_ops = { }; static const struct udevice_id pci_generic_ecam_ids[] = { - { .compatible = "pci-host-ecam-generic" }, + { .compatible = "pci-host-ecam-generic" /* PCI-E */ }, + { .compatible = "pci-host-cam-generic", .data = TYPE_PCI }, { } }; -- cgit v1.2.3 From b6bfb8971dd039a60e1cff1895ab9be8be0915b3 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Tue, 19 Oct 2021 10:40:53 +0800 Subject: nvme: Enable FUA Most NVME devcies maintain data in internal cache for an uncertain times, and u-boot has no method to force NVME to flush cache. So this patch adds FUA to avoid data loss caused by power off after data programming. Signed-off-by: Jon Lin Reviewed-by: Stefan Agner --- drivers/nvme/nvme.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 3c529a2fce2..9623c896a15 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -762,6 +762,10 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr, c.rw.appmask = 0; c.rw.metadata = 0; + /* Enable FUA for data integrity if vwc is enabled */ + if (dev->vwc) + c.rw.control |= NVME_RW_FUA; + while (total_lbas) { if (total_lbas < lbas) { lbas = (u16)total_lbas; -- cgit v1.2.3 From c4eef59faab6ae4ecb1beae6d4391b0889bc3ff3 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Tue, 19 Oct 2021 10:40:54 +0800 Subject: nvme: Fix error in nvme_setup_prps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consulting to "NVM Express® Base Specification, revision 2.0". If more PRP List pages are required, then the last entry of the PRP List contains the Page Base Address of the next PRP List page. The next PRP List page shall be memory page aligned. Signed-off-by: Jon Lin Reviewed-by: Shawn Lin --- drivers/nvme/nvme.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 9623c896a15..22ded626a52 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -100,7 +100,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, } nprps = DIV_ROUND_UP(length, page_size); - num_pages = DIV_ROUND_UP(nprps, prps_per_page); + num_pages = DIV_ROUND_UP(nprps + 1, prps_per_page); if (nprps > dev->prp_entry_num) { free(dev->prp_pool); @@ -119,10 +119,11 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, prp_pool = dev->prp_pool; i = 0; while (nprps) { - if (i == ((page_size >> 3) - 1)) { - *(prp_pool + i) = cpu_to_le64((ulong)prp_pool + + if (i == prps_per_page) { + *(prp_pool + i) = *(prp_pool + i - 1); + *(prp_pool + i - 1) = cpu_to_le64((ulong)prp_pool + page_size); - i = 0; + i = 1; prp_pool += page_size; } *(prp_pool + i++) = cpu_to_le64(dma_addr); -- cgit v1.2.3 From 82c65587f62871b53aee97423a1c87dc0f063e10 Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Wed, 20 Oct 2021 20:58:57 +0530 Subject: phy: cadence: phy-cadence-torrent: Change the name of subnode searched Search for "phy" in the subnode names, to syncup with kernel. Signed-off-by: Aswath Govindraju --- drivers/phy/cadence/phy-cadence-torrent.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c index 141ece479fe..ef924e7af50 100644 --- a/drivers/phy/cadence/phy-cadence-torrent.c +++ b/drivers/phy/cadence/phy-cadence-torrent.c @@ -616,8 +616,8 @@ static int cdns_torrent_phy_probe(struct udevice *dev) /* Going through all the available subnodes or children*/ ofnode_for_each_subnode(child, dev_ofnode(dev)) { - /* PHY subnode name must be a 'link' */ - if (!ofnode_name_eq(child, "link")) + /* PHY subnode name must be a 'phy' */ + if (!ofnode_name_eq(child, "phy")) continue; cdns_phy->phys[node].lnk_rst = devm_reset_bulk_get_by_node(dev, child); -- cgit v1.2.3 From 1ac3b720770336a58469ae9345e57dcb9ae81e44 Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Wed, 20 Oct 2021 21:02:02 +0530 Subject: usb: cdns3: cdns3-ti: Add compatible for AM64 SoC Add new compatible for AM64 SoC. Signed-off-by: Aswath Govindraju --- drivers/usb/cdns3/cdns3-ti.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c index 43171678ee1..8958f0166bd 100644 --- a/drivers/usb/cdns3/cdns3-ti.c +++ b/drivers/usb/cdns3/cdns3-ti.c @@ -180,6 +180,7 @@ static int cdns_ti_remove(struct udevice *dev) static const struct udevice_id cdns_ti_of_match[] = { { .compatible = "ti,j721e-usb", }, + { .compatible = "ti,am64-usb", }, {}, }; -- cgit v1.2.3