diff options
Diffstat (limited to 'drivers/soc')
34 files changed, 1208 insertions, 191 deletions
diff --git a/drivers/soc/apple/Kconfig b/drivers/soc/apple/Kconfig index 6388cbe1e56b..ad6736889231 100644 --- a/drivers/soc/apple/Kconfig +++ b/drivers/soc/apple/Kconfig @@ -8,7 +8,6 @@ config APPLE_MAILBOX tristate "Apple SoC mailboxes" depends on PM depends on ARCH_APPLE || (64BIT && COMPILE_TEST) - default ARCH_APPLE help Apple SoCs have various co-processors required for certain peripherals to work (NVMe, display controller, etc.). This @@ -21,7 +20,6 @@ config APPLE_RTKIT tristate "Apple RTKit co-processor IPC protocol" depends on APPLE_MAILBOX depends on ARCH_APPLE || COMPILE_TEST - default ARCH_APPLE help Apple SoCs such as the M1 come with various co-processors running their proprietary RTKit operating system. This option enables support @@ -33,7 +31,6 @@ config APPLE_RTKIT config APPLE_SART tristate "Apple SART DMA address filter" depends on ARCH_APPLE || COMPILE_TEST - default ARCH_APPLE help Apple SART is a simple DMA address filter used on Apple SoCs such as the M1. It is usually required for the NVMe coprocessor which does diff --git a/drivers/soc/apple/mailbox.c b/drivers/soc/apple/mailbox.c index 49a0955e82d6..8f29108dc69a 100644 --- a/drivers/soc/apple/mailbox.c +++ b/drivers/soc/apple/mailbox.c @@ -47,6 +47,9 @@ #define APPLE_ASC_MBOX_I2A_RECV0 0x830 #define APPLE_ASC_MBOX_I2A_RECV1 0x838 +#define APPLE_T8015_MBOX_A2I_CONTROL 0x108 +#define APPLE_T8015_MBOX_I2A_CONTROL 0x10c + #define APPLE_M3_MBOX_CONTROL_FULL BIT(16) #define APPLE_M3_MBOX_CONTROL_EMPTY BIT(17) @@ -382,6 +385,21 @@ static int apple_mbox_probe(struct platform_device *pdev) return 0; } +static const struct apple_mbox_hw apple_mbox_t8015_hw = { + .control_full = APPLE_ASC_MBOX_CONTROL_FULL, + .control_empty = APPLE_ASC_MBOX_CONTROL_EMPTY, + + .a2i_control = APPLE_T8015_MBOX_A2I_CONTROL, + .a2i_send0 = APPLE_ASC_MBOX_A2I_SEND0, + .a2i_send1 = APPLE_ASC_MBOX_A2I_SEND1, + + .i2a_control = APPLE_T8015_MBOX_I2A_CONTROL, + .i2a_recv0 = APPLE_ASC_MBOX_I2A_RECV0, + .i2a_recv1 = APPLE_ASC_MBOX_I2A_RECV1, + + .has_irq_controls = false, +}; + static const struct apple_mbox_hw apple_mbox_asc_hw = { .control_full = APPLE_ASC_MBOX_CONTROL_FULL, .control_empty = APPLE_ASC_MBOX_CONTROL_EMPTY, @@ -418,6 +436,7 @@ static const struct apple_mbox_hw apple_mbox_m3_hw = { static const struct of_device_id apple_mbox_of_match[] = { { .compatible = "apple,asc-mailbox-v4", .data = &apple_mbox_asc_hw }, + { .compatible = "apple,t8015-asc-mailbox", .data = &apple_mbox_t8015_hw }, { .compatible = "apple,m3-mailbox-v2", .data = &apple_mbox_m3_hw }, {} }; diff --git a/drivers/soc/apple/sart.c b/drivers/soc/apple/sart.c index afa111736899..4ff1942b82a7 100644 --- a/drivers/soc/apple/sart.c +++ b/drivers/soc/apple/sart.c @@ -25,8 +25,17 @@ #define APPLE_SART_MAX_ENTRIES 16 -/* This is probably a bitfield but the exact meaning of each bit is unknown. */ -#define APPLE_SART_FLAGS_ALLOW 0xff +/* SARTv0 registers */ +#define APPLE_SART0_CONFIG(idx) (0x00 + 4 * (idx)) +#define APPLE_SART0_CONFIG_FLAGS GENMASK(28, 24) +#define APPLE_SART0_CONFIG_SIZE GENMASK(18, 0) +#define APPLE_SART0_CONFIG_SIZE_SHIFT 12 +#define APPLE_SART0_CONFIG_SIZE_MAX GENMASK(18, 0) + +#define APPLE_SART0_PADDR(idx) (0x40 + 4 * (idx)) +#define APPLE_SART0_PADDR_SHIFT 12 + +#define APPLE_SART0_FLAGS_ALLOW 0xf /* SARTv2 registers */ #define APPLE_SART2_CONFIG(idx) (0x00 + 4 * (idx)) @@ -38,6 +47,8 @@ #define APPLE_SART2_PADDR(idx) (0x40 + 4 * (idx)) #define APPLE_SART2_PADDR_SHIFT 12 +#define APPLE_SART2_FLAGS_ALLOW 0xff + /* SARTv3 registers */ #define APPLE_SART3_CONFIG(idx) (0x00 + 4 * (idx)) @@ -48,11 +59,15 @@ #define APPLE_SART3_SIZE_SHIFT 12 #define APPLE_SART3_SIZE_MAX GENMASK(29, 0) +#define APPLE_SART3_FLAGS_ALLOW 0xff + struct apple_sart_ops { void (*get_entry)(struct apple_sart *sart, int index, u8 *flags, phys_addr_t *paddr, size_t *size); void (*set_entry)(struct apple_sart *sart, int index, u8 flags, phys_addr_t paddr_shifted, size_t size_shifted); + /* This is probably a bitfield but the exact meaning of each bit is unknown. */ + unsigned int flags_allow; unsigned int size_shift; unsigned int paddr_shift; size_t size_max; @@ -68,6 +83,39 @@ struct apple_sart { unsigned long used_entries; }; +static void sart0_get_entry(struct apple_sart *sart, int index, u8 *flags, + phys_addr_t *paddr, size_t *size) +{ + u32 cfg = readl(sart->regs + APPLE_SART0_CONFIG(index)); + phys_addr_t paddr_ = readl(sart->regs + APPLE_SART0_PADDR(index)); + size_t size_ = FIELD_GET(APPLE_SART0_CONFIG_SIZE, cfg); + + *flags = FIELD_GET(APPLE_SART0_CONFIG_FLAGS, cfg); + *size = size_ << APPLE_SART0_CONFIG_SIZE_SHIFT; + *paddr = paddr_ << APPLE_SART0_PADDR_SHIFT; +} + +static void sart0_set_entry(struct apple_sart *sart, int index, u8 flags, + phys_addr_t paddr_shifted, size_t size_shifted) +{ + u32 cfg; + + cfg = FIELD_PREP(APPLE_SART0_CONFIG_FLAGS, flags); + cfg |= FIELD_PREP(APPLE_SART0_CONFIG_SIZE, size_shifted); + + writel(paddr_shifted, sart->regs + APPLE_SART0_PADDR(index)); + writel(cfg, sart->regs + APPLE_SART0_CONFIG(index)); +} + +static struct apple_sart_ops sart_ops_v0 = { + .get_entry = sart0_get_entry, + .set_entry = sart0_set_entry, + .flags_allow = APPLE_SART0_FLAGS_ALLOW, + .size_shift = APPLE_SART0_CONFIG_SIZE_SHIFT, + .paddr_shift = APPLE_SART0_PADDR_SHIFT, + .size_max = APPLE_SART0_CONFIG_SIZE_MAX, +}; + static void sart2_get_entry(struct apple_sart *sart, int index, u8 *flags, phys_addr_t *paddr, size_t *size) { @@ -95,6 +143,7 @@ static void sart2_set_entry(struct apple_sart *sart, int index, u8 flags, static struct apple_sart_ops sart_ops_v2 = { .get_entry = sart2_get_entry, .set_entry = sart2_set_entry, + .flags_allow = APPLE_SART2_FLAGS_ALLOW, .size_shift = APPLE_SART2_CONFIG_SIZE_SHIFT, .paddr_shift = APPLE_SART2_PADDR_SHIFT, .size_max = APPLE_SART2_CONFIG_SIZE_MAX, @@ -122,6 +171,7 @@ static void sart3_set_entry(struct apple_sart *sart, int index, u8 flags, static struct apple_sart_ops sart_ops_v3 = { .get_entry = sart3_get_entry, .set_entry = sart3_set_entry, + .flags_allow = APPLE_SART3_FLAGS_ALLOW, .size_shift = APPLE_SART3_SIZE_SHIFT, .paddr_shift = APPLE_SART3_PADDR_SHIFT, .size_max = APPLE_SART3_SIZE_MAX, @@ -233,7 +283,7 @@ int apple_sart_add_allowed_region(struct apple_sart *sart, phys_addr_t paddr, if (test_and_set_bit(i, &sart->used_entries)) continue; - ret = sart_set_entry(sart, i, APPLE_SART_FLAGS_ALLOW, paddr, + ret = sart_set_entry(sart, i, sart->ops->flags_allow, paddr, size); if (ret) { dev_dbg(sart->dev, @@ -314,6 +364,10 @@ static const struct of_device_id apple_sart_of_match[] = { .compatible = "apple,t8103-sart", .data = &sart_ops_v2, }, + { + .compatible = "apple,t8015-sart", + .data = &sart_ops_v0, + }, {} }; MODULE_DEVICE_TABLE(of, apple_sart_of_match); diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c index ee58151bd69e..b7dbb12bd095 100644 --- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c +++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c @@ -10,6 +10,7 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/of_address.h> +#include <linux/of_reserved_mem.h> #include <linux/platform_device.h> #include <linux/poll.h> #include <linux/regmap.h> @@ -254,17 +255,8 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, lpc_ctrl); /* If memory-region is described in device tree then store */ - node = of_parse_phandle(dev->of_node, "memory-region", 0); - if (!node) { - dev_dbg(dev, "Didn't find reserved memory\n"); - } else { - rc = of_address_to_resource(node, 0, &resm); - of_node_put(node); - if (rc) { - dev_err(dev, "Couldn't address to resource for reserved memory\n"); - return -ENXIO; - } - + rc = of_reserved_mem_region_to_resource(dev->of_node, 0, &resm); + if (!rc) { lpc_ctrl->mem_size = resource_size(&resm); lpc_ctrl->mem_base = resm.start; diff --git a/drivers/soc/aspeed/aspeed-p2a-ctrl.c b/drivers/soc/aspeed/aspeed-p2a-ctrl.c index 6cc943744e12..3be2e1b1085b 100644 --- a/drivers/soc/aspeed/aspeed-p2a-ctrl.c +++ b/drivers/soc/aspeed/aspeed-p2a-ctrl.c @@ -19,7 +19,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> -#include <linux/of_address.h> +#include <linux/of_reserved_mem.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -334,7 +334,6 @@ static int aspeed_p2a_ctrl_probe(struct platform_device *pdev) struct aspeed_p2a_ctrl *misc_ctrl; struct device *dev; struct resource resm; - struct device_node *node; int rc = 0; dev = &pdev->dev; @@ -346,15 +345,8 @@ static int aspeed_p2a_ctrl_probe(struct platform_device *pdev) mutex_init(&misc_ctrl->tracking); /* optional. */ - node = of_parse_phandle(dev->of_node, "memory-region", 0); - if (node) { - rc = of_address_to_resource(node, 0, &resm); - of_node_put(node); - if (rc) { - dev_err(dev, "Couldn't address to resource for reserved memory\n"); - return -ENODEV; - } - + rc = of_reserved_mem_region_to_resource(dev->of_node, 0, &resm); + if (!rc) { misc_ctrl->mem_size = resource_size(&resm); misc_ctrl->mem_base = resm.start; } diff --git a/drivers/soc/aspeed/aspeed-socinfo.c b/drivers/soc/aspeed/aspeed-socinfo.c index 3f759121dc00..67e9ac3d08ec 100644 --- a/drivers/soc/aspeed/aspeed-socinfo.c +++ b/drivers/soc/aspeed/aspeed-socinfo.c @@ -27,6 +27,10 @@ static struct { { "AST2620", 0x05010203 }, { "AST2605", 0x05030103 }, { "AST2625", 0x05030403 }, + /* AST2700 */ + { "AST2750", 0x06000003 }, + { "AST2700", 0x06000103 }, + { "AST2720", 0x06000203 }, }; static const char *siliconid_to_name(u32 siliconid) diff --git a/drivers/soc/fsl/qbman/qman_test_stash.c b/drivers/soc/fsl/qbman/qman_test_stash.c index f4d3c2146f4f..6f7597950aa3 100644 --- a/drivers/soc/fsl/qbman/qman_test_stash.c +++ b/drivers/soc/fsl/qbman/qman_test_stash.c @@ -103,7 +103,7 @@ static int on_all_cpus(int (*fn)(void)) { int cpu; - for_each_cpu(cpu, cpu_online_mask) { + for_each_online_cpu(cpu) { struct bstrap bstrap = { .fn = fn, .started = ATOMIC_INIT(0) diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 8df1e8fa86a5..c54154b404df 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -12,18 +12,19 @@ #include <linux/spinlock.h> #include <linux/err.h> #include <linux/io.h> -#include <linux/of.h> -#include <linux/gpio/legacy-of-mm-gpiochip.h> #include <linux/gpio/consumer.h> #include <linux/gpio/driver.h> #include <linux/slab.h> #include <linux/export.h> -#include <linux/property.h> +#include <linux/platform_device.h> #include <soc/fsl/qe/qe.h> +#define PIN_MASK(gpio) (1UL << (QE_PIO_PINS - 1 - (gpio))) + struct qe_gpio_chip { - struct of_mm_gpio_chip mm_gc; + struct gpio_chip gc; + void __iomem *regs; spinlock_t lock; /* shadowed data register to clear/set bits safely */ @@ -33,11 +34,9 @@ struct qe_gpio_chip { struct qe_pio_regs saved_regs; }; -static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) +static void qe_gpio_save_regs(struct qe_gpio_chip *qe_gc) { - struct qe_gpio_chip *qe_gc = - container_of(mm_gc, struct qe_gpio_chip, mm_gc); - struct qe_pio_regs __iomem *regs = mm_gc->regs; + struct qe_pio_regs __iomem *regs = qe_gc->regs; qe_gc->cpdata = ioread32be(®s->cpdata); qe_gc->saved_regs.cpdata = qe_gc->cpdata; @@ -50,20 +49,19 @@ static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct qe_pio_regs __iomem *regs = mm_gc->regs; - u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); + struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); + struct qe_pio_regs __iomem *regs = qe_gc->regs; + u32 pin_mask = PIN_MASK(gpio); return !!(ioread32be(®s->cpdata) & pin_mask); } static int qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); - struct qe_pio_regs __iomem *regs = mm_gc->regs; + struct qe_pio_regs __iomem *regs = qe_gc->regs; unsigned long flags; - u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); + u32 pin_mask = PIN_MASK(gpio); spin_lock_irqsave(&qe_gc->lock, flags); @@ -82,9 +80,8 @@ static int qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static int qe_gpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); - struct qe_pio_regs __iomem *regs = mm_gc->regs; + struct qe_pio_regs __iomem *regs = qe_gc->regs; unsigned long flags; int i; @@ -95,9 +92,9 @@ static int qe_gpio_set_multiple(struct gpio_chip *gc, break; if (__test_and_clear_bit(i, mask)) { if (test_bit(i, bits)) - qe_gc->cpdata |= (1U << (QE_PIO_PINS - 1 - i)); + qe_gc->cpdata |= PIN_MASK(i); else - qe_gc->cpdata &= ~(1U << (QE_PIO_PINS - 1 - i)); + qe_gc->cpdata &= ~PIN_MASK(i); } } @@ -110,13 +107,12 @@ static int qe_gpio_set_multiple(struct gpio_chip *gc, static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); unsigned long flags; spin_lock_irqsave(&qe_gc->lock, flags); - __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_IN, 0, 0, 0); + __par_io_config_pin(qe_gc->regs, gpio, QE_PIO_DIR_IN, 0, 0, 0); spin_unlock_irqrestore(&qe_gc->lock, flags); @@ -125,7 +121,6 @@ static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc); unsigned long flags; @@ -133,7 +128,7 @@ static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) spin_lock_irqsave(&qe_gc->lock, flags); - __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0); + __par_io_config_pin(qe_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0); spin_unlock_irqrestore(&qe_gc->lock, flags); @@ -239,7 +234,7 @@ EXPORT_SYMBOL(qe_pin_free); void qe_pin_set_dedicated(struct qe_pin *qe_pin) { struct qe_gpio_chip *qe_gc = qe_pin->controller; - struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs; + struct qe_pio_regs __iomem *regs = qe_gc->regs; struct qe_pio_regs *sregs = &qe_gc->saved_regs; int pin = qe_pin->num; u32 mask1 = 1 << (QE_PIO_PINS - (pin + 1)); @@ -268,7 +263,6 @@ void qe_pin_set_dedicated(struct qe_pin *qe_pin) iowrite32be(qe_gc->cpdata, ®s->cpdata); qe_clrsetbits_be32(®s->cpodr, mask1, sregs->cpodr & mask1); - spin_unlock_irqrestore(&qe_gc->lock, flags); } EXPORT_SYMBOL(qe_pin_set_dedicated); @@ -283,7 +277,7 @@ EXPORT_SYMBOL(qe_pin_set_dedicated); void qe_pin_set_gpio(struct qe_pin *qe_pin) { struct qe_gpio_chip *qe_gc = qe_pin->controller; - struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs; + struct qe_pio_regs __iomem *regs = qe_gc->regs; unsigned long flags; spin_lock_irqsave(&qe_gc->lock, flags); @@ -295,45 +289,62 @@ void qe_pin_set_gpio(struct qe_pin *qe_pin) } EXPORT_SYMBOL(qe_pin_set_gpio); -static int __init qe_add_gpiochips(void) +static int qe_gpio_probe(struct platform_device *ofdev) { - struct device_node *np; - - for_each_compatible_node(np, NULL, "fsl,mpc8323-qe-pario-bank") { - int ret; - struct qe_gpio_chip *qe_gc; - struct of_mm_gpio_chip *mm_gc; - struct gpio_chip *gc; - - qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL); - if (!qe_gc) { - ret = -ENOMEM; - goto err; - } + struct device *dev = &ofdev->dev; + struct device_node *np = dev->of_node; + struct qe_gpio_chip *qe_gc; + struct gpio_chip *gc; - spin_lock_init(&qe_gc->lock); - - mm_gc = &qe_gc->mm_gc; - gc = &mm_gc->gc; - - mm_gc->save_regs = qe_gpio_save_regs; - gc->ngpio = QE_PIO_PINS; - gc->direction_input = qe_gpio_dir_in; - gc->direction_output = qe_gpio_dir_out; - gc->get = qe_gpio_get; - gc->set = qe_gpio_set; - gc->set_multiple = qe_gpio_set_multiple; - - ret = of_mm_gpiochip_add_data(np, mm_gc, qe_gc); - if (ret) - goto err; - continue; -err: - pr_err("%pOF: registration failed with status %d\n", - np, ret); - kfree(qe_gc); - /* try others anyway */ - } - return 0; + qe_gc = devm_kzalloc(dev, sizeof(*qe_gc), GFP_KERNEL); + if (!qe_gc) + return -ENOMEM; + + spin_lock_init(&qe_gc->lock); + + gc = &qe_gc->gc; + + gc->base = -1; + gc->ngpio = QE_PIO_PINS; + gc->direction_input = qe_gpio_dir_in; + gc->direction_output = qe_gpio_dir_out; + gc->get = qe_gpio_get; + gc->set = qe_gpio_set; + gc->set_multiple = qe_gpio_set_multiple; + gc->parent = dev; + gc->owner = THIS_MODULE; + + gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np); + if (!gc->label) + return -ENOMEM; + + qe_gc->regs = devm_of_iomap(dev, np, 0, NULL); + if (IS_ERR(qe_gc->regs)) + return PTR_ERR(qe_gc->regs); + + qe_gpio_save_regs(qe_gc); + + return devm_gpiochip_add_data(dev, gc, qe_gc); +} + +static const struct of_device_id qe_gpio_match[] = { + { + .compatible = "fsl,mpc8323-qe-pario-bank", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, qe_gpio_match); + +static struct platform_driver qe_gpio_driver = { + .probe = qe_gpio_probe, + .driver = { + .name = "qe-gpio", + .of_match_table = qe_gpio_match, + }, +}; + +static int __init qe_gpio_init(void) +{ + return platform_driver_register(&qe_gpio_driver); } -arch_initcall(qe_add_gpiochips); +arch_initcall(qe_gpio_init); diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 36c0ccc06151..da5ea6d35618 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -461,9 +461,16 @@ int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, ctrl = qmc_read16(&bd->cbd_sc); if (ctrl & (QMC_BD_TX_R | QMC_BD_TX_UB)) { - /* We are full ... */ - ret = -EBUSY; - goto end; + if (!(ctrl & (QMC_BD_TX_R | QMC_BD_TX_I)) && bd == chan->txbd_done) { + if (ctrl & QMC_BD_TX_W) + chan->txbd_done = chan->txbds; + else + chan->txbd_done++; + } else { + /* We are full ... */ + ret = -EBUSY; + goto end; + } } qmc_write16(&bd->cbd_datlen, length); @@ -475,6 +482,10 @@ int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, /* Activate the descriptor */ ctrl |= (QMC_BD_TX_R | QMC_BD_TX_UB); + if (complete) + ctrl |= QMC_BD_TX_I; + else + ctrl &= ~QMC_BD_TX_I; wmb(); /* Be sure to flush the descriptor before control update */ qmc_write16(&bd->cbd_sc, ctrl); @@ -569,9 +580,16 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, ctrl = qmc_read16(&bd->cbd_sc); if (ctrl & (QMC_BD_RX_E | QMC_BD_RX_UB)) { - /* We are full ... */ - ret = -EBUSY; - goto end; + if (!(ctrl & (QMC_BD_RX_E | QMC_BD_RX_I)) && bd == chan->rxbd_done) { + if (ctrl & QMC_BD_RX_W) + chan->rxbd_done = chan->rxbds; + else + chan->rxbd_done++; + } else { + /* We are full ... */ + ret = -EBUSY; + goto end; + } } qmc_write16(&bd->cbd_datlen, 0); /* data length is updated by the QMC */ @@ -587,6 +605,10 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length, /* Activate the descriptor */ ctrl |= (QMC_BD_RX_E | QMC_BD_RX_UB); + if (complete) + ctrl |= QMC_BD_RX_I; + else + ctrl &= ~QMC_BD_RX_I; wmb(); /* Be sure to flush data before descriptor activation */ qmc_write16(&bd->cbd_sc, ctrl); @@ -1482,19 +1504,19 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan) /* Init Rx BDs and set Wrap bit on last descriptor */ BUILD_BUG_ON(QMC_NB_RXBDS == 0); - val = QMC_BD_RX_I; for (i = 0; i < QMC_NB_RXBDS; i++) { bd = chan->rxbds + i; - qmc_write16(&bd->cbd_sc, val); + qmc_write16(&bd->cbd_sc, 0); } bd = chan->rxbds + QMC_NB_RXBDS - 1; - qmc_write16(&bd->cbd_sc, val | QMC_BD_RX_W); + qmc_write16(&bd->cbd_sc, QMC_BD_RX_W); /* Init Tx BDs and set Wrap bit on last descriptor */ BUILD_BUG_ON(QMC_NB_TXBDS == 0); - val = QMC_BD_TX_I; if (chan->mode == QMC_HDLC) - val |= QMC_BD_TX_L | QMC_BD_TX_TC; + val = QMC_BD_TX_L | QMC_BD_TX_TC; + else + val = 0; for (i = 0; i < QMC_NB_TXBDS; i++) { bd = chan->txbds + i; qmc_write16(&bd->cbd_sc, val); diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index 65ff45fdcac7..006fec47ea10 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -1464,7 +1464,7 @@ static ssize_t dec_lane_of_type_store(struct kobject *kobj, struct kobj_attribut goto out; if (!all_in_idle) { ret = -EBUSY; - dev_err(hdev->dev, "please don't decrese lanes on high load with %s, ret = %d.\n", + dev_err(hdev->dev, "please don't decrease lanes on high load with %s, ret = %d.\n", hccs_port_type_to_name(hdev, port_type), ret); goto out; } diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index 7c349a94b45c..f45537546553 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -2165,10 +2165,18 @@ static struct device *svs_add_device_link(struct svs_platform *svsp, return dev; } +static void svs_put_device(void *_dev) +{ + struct device *dev = _dev; + + put_device(dev); +} + static int svs_mt8192_platform_probe(struct svs_platform *svsp) { struct device *dev; u32 idx; + int ret; svsp->rst = devm_reset_control_get_optional(svsp->dev, "svs_rst"); if (IS_ERR(svsp->rst)) @@ -2179,6 +2187,7 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp) if (IS_ERR(dev)) return dev_err_probe(svsp->dev, PTR_ERR(dev), "failed to get lvts device\n"); + put_device(dev); for (idx = 0; idx < svsp->bank_max; idx++) { struct svs_bank *svsb = &svsp->banks[idx]; @@ -2188,6 +2197,7 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp) case SVSB_SWID_CPU_LITTLE: case SVSB_SWID_CPU_BIG: svsb->opp_dev = get_cpu_device(bdata->cpu_id); + get_device(svsb->opp_dev); break; case SVSB_SWID_CCI: svsb->opp_dev = svs_add_device_link(svsp, "cci"); @@ -2207,6 +2217,11 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp) return dev_err_probe(svsp->dev, PTR_ERR(svsb->opp_dev), "failed to get OPP device for bank %d\n", idx); + + ret = devm_add_action_or_reset(svsp->dev, svs_put_device, + svsb->opp_dev); + if (ret) + return ret; } return 0; @@ -2216,11 +2231,13 @@ static int svs_mt8183_platform_probe(struct svs_platform *svsp) { struct device *dev; u32 idx; + int ret; dev = svs_add_device_link(svsp, "thermal-sensor"); if (IS_ERR(dev)) return dev_err_probe(svsp->dev, PTR_ERR(dev), "failed to get thermal device\n"); + put_device(dev); for (idx = 0; idx < svsp->bank_max; idx++) { struct svs_bank *svsb = &svsp->banks[idx]; @@ -2230,6 +2247,7 @@ static int svs_mt8183_platform_probe(struct svs_platform *svsp) case SVSB_SWID_CPU_LITTLE: case SVSB_SWID_CPU_BIG: svsb->opp_dev = get_cpu_device(bdata->cpu_id); + get_device(svsb->opp_dev); break; case SVSB_SWID_CCI: svsb->opp_dev = svs_add_device_link(svsp, "cci"); @@ -2246,6 +2264,11 @@ static int svs_mt8183_platform_probe(struct svs_platform *svsp) return dev_err_probe(svsp->dev, PTR_ERR(svsb->opp_dev), "failed to get OPP device for bank %d\n", idx); + + ret = devm_add_action_or_reset(svsp->dev, svs_put_device, + svsb->opp_dev); + if (ret) + return ret; } return 0; diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 3dfa448bf8cf..597f9025e422 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -656,6 +656,9 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id) if (IS_ERR(target_opp) && PTR_ERR(target_opp) == -ERANGE) target_opp = dev_pm_opp_find_bw_floor(bwmon->dev, &bw_kbps, 0); + if (IS_ERR(target_opp)) + return IRQ_HANDLED; + bwmon->target_kbps = bw_kbps; bw_kbps--; diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 192edc3f64dc..857ead56b37d 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -4409,7 +4409,6 @@ static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev, u8 index .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .fast_io = true, }; base = devm_platform_ioremap_resource(pdev, index); diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index 0ca268bdf1f8..a5c80d4fcc36 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -39,12 +39,14 @@ static bool mdt_header_valid(const struct firmware *fw) if (phend > fw->size) return false; - if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) - return false; + if (ehdr->e_shentsize || ehdr->e_shnum) { + if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) + return false; - shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); - if (shend > fw->size) - return false; + shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); + if (shend > fw->size) + return false; + } return true; } @@ -302,7 +304,7 @@ out: } EXPORT_SYMBOL_GPL(qcom_mdt_pas_init); -static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_name) +static bool qcom_mdt_bins_are_split(const struct firmware *fw) { const struct elf32_phdr *phdrs; const struct elf32_hdr *ehdr; @@ -331,9 +333,9 @@ static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_na } static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, - const char *fw_name, int pas_id, void *mem_region, + const char *fw_name, void *mem_region, phys_addr_t mem_phys, size_t mem_size, - phys_addr_t *reloc_base, bool pas_init) + phys_addr_t *reloc_base) { const struct elf32_phdr *phdrs; const struct elf32_phdr *phdr; @@ -353,7 +355,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, if (!mdt_header_valid(fw)) return -EINVAL; - is_split = qcom_mdt_bins_are_split(fw, fw_name); + is_split = qcom_mdt_bins_are_split(fw); ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); @@ -458,8 +460,8 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw, if (ret) return ret; - return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys, - mem_size, reloc_base, true); + return __qcom_mdt_load(dev, fw, firmware, mem_region, mem_phys, + mem_size, reloc_base); } EXPORT_SYMBOL_GPL(qcom_mdt_load); @@ -468,7 +470,6 @@ EXPORT_SYMBOL_GPL(qcom_mdt_load); * @dev: device handle to associate resources with * @fw: firmware object for the mdt file * @firmware: name of the firmware, for construction of segment file names - * @pas_id: PAS identifier * @mem_region: allocated memory region to load firmware into * @mem_phys: physical address of allocated memory region * @mem_size: size of the allocated memory region @@ -477,12 +478,11 @@ EXPORT_SYMBOL_GPL(qcom_mdt_load); * Returns 0 on success, negative errno otherwise. */ int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw, - const char *firmware, int pas_id, - void *mem_region, phys_addr_t mem_phys, + const char *firmware, void *mem_region, phys_addr_t mem_phys, size_t mem_size, phys_addr_t *reloc_base) { - return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys, - mem_size, reloc_base, false); + return __qcom_mdt_load(dev, fw, firmware, mem_region, mem_phys, + mem_size, reloc_base); } EXPORT_SYMBOL_GPL(qcom_mdt_load_no_init); diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 3c3b796333a6..cd1779b6a91a 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -1,11 +1,16 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ /* Disable MMIO tracing to prevent excessive logging of unwanted MMIO traces */ #define __DISABLE_TRACE_MMIO__ #include <linux/acpi.h> +#include <linux/bitfield.h> #include <linux/clk.h> +#include <linux/firmware.h> #include <linux/slab.h> #include <linux/dma-mapping.h> #include <linux/io.h> @@ -110,22 +115,94 @@ struct geni_se_desc { static const char * const icc_path_names[] = {"qup-core", "qup-config", "qup-memory"}; -#define QUP_HW_VER_REG 0x4 +static const char * const protocol_name[] = { "None", "SPI", "UART", "I2C", "I3C", "SPI SLAVE" }; + +/** + * struct se_fw_hdr - Serial Engine firmware configuration header + * + * This structure defines the SE firmware header, which together with the + * firmware payload is stored in individual ELF segments. + * + * @magic: Set to 'SEFW'. + * @version: Structure version number. + * @core_version: QUPV3 hardware version. + * @serial_protocol: Encoded in GENI_FW_REVISION. + * @fw_version: Firmware version, from GENI_FW_REVISION. + * @cfg_version: Configuration version, from GENI_INIT_CFG_REVISION. + * @fw_size_in_items: Number of 32-bit words in GENI_FW_RAM. + * @fw_offset: Byte offset to GENI_FW_RAM array. + * @cfg_size_in_items: Number of GENI_FW_CFG index/value pairs. + * @cfg_idx_offset: Byte offset to GENI_FW_CFG index array. + * @cfg_val_offset: Byte offset to GENI_FW_CFG values array. + */ +struct se_fw_hdr { + __le32 magic; + __le32 version; + __le32 core_version; + __le16 serial_protocol; + __le16 fw_version; + __le16 cfg_version; + __le16 fw_size_in_items; + __le16 fw_offset; + __le16 cfg_size_in_items; + __le16 cfg_idx_offset; + __le16 cfg_val_offset; +}; + +/*Magic numbers*/ +#define SE_MAGIC_NUM 0x57464553 + +#define MAX_GENI_CFG_RAMn_CNT 455 + +#define MI_PBT_NON_PAGED_SEGMENT 0x0 +#define MI_PBT_HASH_SEGMENT 0x2 +#define MI_PBT_NOTUSED_SEGMENT 0x3 +#define MI_PBT_SHARED_SEGMENT 0x4 + +#define MI_PBT_FLAG_PAGE_MODE BIT(20) +#define MI_PBT_FLAG_SEGMENT_TYPE GENMASK(26, 24) +#define MI_PBT_FLAG_ACCESS_TYPE GENMASK(23, 21) + +#define MI_PBT_PAGE_MODE_VALUE(x) FIELD_GET(MI_PBT_FLAG_PAGE_MODE, x) + +#define MI_PBT_SEGMENT_TYPE_VALUE(x) FIELD_GET(MI_PBT_FLAG_SEGMENT_TYPE, x) + +#define MI_PBT_ACCESS_TYPE_VALUE(x) FIELD_GET(MI_PBT_FLAG_ACCESS_TYPE, x) + +#define M_COMMON_GENI_M_IRQ_EN (GENMASK(6, 1) | \ + M_IO_DATA_DEASSERT_EN | \ + M_IO_DATA_ASSERT_EN | M_RX_FIFO_RD_ERR_EN | \ + M_RX_FIFO_WR_ERR_EN | M_TX_FIFO_RD_ERR_EN | \ + M_TX_FIFO_WR_ERR_EN) + +/* Common QUPV3 registers */ +#define QUPV3_HW_VER_REG 0x4 +#define QUPV3_SE_AHB_M_CFG 0x118 +#define QUPV3_COMMON_CFG 0x120 +#define QUPV3_COMMON_CGC_CTRL 0x21c + +/* QUPV3_COMMON_CFG fields */ +#define FAST_SWITCH_TO_HIGH_DISABLE BIT(0) + +/* QUPV3_SE_AHB_M_CFG fields */ +#define AHB_M_CLK_CGC_ON BIT(0) + +/* QUPV3_COMMON_CGC_CTRL fields */ +#define COMMON_CSR_SLV_CLK_CGC_ON BIT(0) /* Common SE registers */ -#define GENI_INIT_CFG_REVISION 0x0 -#define GENI_S_INIT_CFG_REVISION 0x4 -#define GENI_OUTPUT_CTRL 0x24 -#define GENI_CGC_CTRL 0x28 -#define GENI_CLK_CTRL_RO 0x60 -#define GENI_FW_S_REVISION_RO 0x6c +#define SE_GENI_INIT_CFG_REVISION 0x0 +#define SE_GENI_S_INIT_CFG_REVISION 0x4 +#define SE_GENI_CGC_CTRL 0x28 +#define SE_GENI_CLK_CTRL_RO 0x60 +#define SE_GENI_FW_S_REVISION_RO 0x6c +#define SE_GENI_CFG_REG0 0x100 #define SE_GENI_BYTE_GRAN 0x254 #define SE_GENI_TX_PACKING_CFG0 0x260 #define SE_GENI_TX_PACKING_CFG1 0x264 #define SE_GENI_RX_PACKING_CFG0 0x284 #define SE_GENI_RX_PACKING_CFG1 0x288 -#define SE_GENI_M_GP_LENGTH 0x910 -#define SE_GENI_S_GP_LENGTH 0x914 +#define SE_GENI_S_IRQ_ENABLE 0x644 #define SE_DMA_TX_PTR_L 0xc30 #define SE_DMA_TX_PTR_H 0xc34 #define SE_DMA_TX_ATTR 0xc38 @@ -142,12 +219,20 @@ static const char * const icc_path_names[] = {"qup-core", "qup-config", #define SE_DMA_RX_IRQ_EN 0xd48 #define SE_DMA_RX_IRQ_EN_SET 0xd4c #define SE_DMA_RX_IRQ_EN_CLR 0xd50 -#define SE_DMA_RX_LEN_IN 0xd54 #define SE_DMA_RX_MAX_BURST 0xd5c #define SE_DMA_RX_FLUSH 0xd60 #define SE_GSI_EVENT_EN 0xe18 #define SE_IRQ_EN 0xe1c #define SE_DMA_GENERAL_CFG 0xe30 +#define SE_GENI_FW_REVISION 0x1000 +#define SE_GENI_S_FW_REVISION 0x1004 +#define SE_GENI_CFG_RAMN 0x1010 +#define SE_GENI_CLK_CTRL 0x2000 +#define SE_DMA_IF_EN 0x2004 +#define SE_FIFO_IF_DISABLE 0x2008 + +/* GENI_FW_REVISION_RO fields */ +#define FW_REV_VERSION_MSK GENMASK(7, 0) /* GENI_OUTPUT_CTRL fields */ #define DEFAULT_IO_OUTPUT_CTRL_MSK GENMASK(6, 0) @@ -179,13 +264,22 @@ static const char * const icc_path_names[] = {"qup-core", "qup-config", /* SE_DMA_GENERAL_CFG */ #define DMA_RX_CLK_CGC_ON BIT(0) #define DMA_TX_CLK_CGC_ON BIT(1) -#define DMA_AHB_SLV_CFG_ON BIT(2) +#define DMA_AHB_SLV_CLK_CGC_ON BIT(2) #define AHB_SEC_SLV_CLK_CGC_ON BIT(3) #define DUMMY_RX_NON_BUFFERABLE BIT(4) #define RX_DMA_ZERO_PADDING_EN BIT(5) #define RX_DMA_IRQ_DELAY_MSK GENMASK(8, 6) #define RX_DMA_IRQ_DELAY_SHFT 6 +/* GENI_CLK_CTRL fields */ +#define SER_CLK_SEL BIT(0) + +/* GENI_DMA_IF_EN fields */ +#define DMA_IF_EN BIT(0) + +#define geni_setbits32(_addr, _v) writel(readl(_addr) | (_v), _addr) +#define geni_clrbits32(_addr, _v) writel(readl(_addr) & ~(_v), _addr) + /** * geni_se_get_qup_hw_version() - Read the QUP wrapper Hardware version * @se: Pointer to the corresponding serial engine. @@ -196,7 +290,7 @@ u32 geni_se_get_qup_hw_version(struct geni_se *se) { struct geni_wrapper *wrapper = se->wrapper; - return readl_relaxed(wrapper->base + QUP_HW_VER_REG); + return readl_relaxed(wrapper->base + QUPV3_HW_VER_REG); } EXPORT_SYMBOL_GPL(geni_se_get_qup_hw_version); @@ -220,12 +314,12 @@ static void geni_se_io_init(void __iomem *base) { u32 val; - val = readl_relaxed(base + GENI_CGC_CTRL); + val = readl_relaxed(base + SE_GENI_CGC_CTRL); val |= DEFAULT_CGC_EN; - writel_relaxed(val, base + GENI_CGC_CTRL); + writel_relaxed(val, base + SE_GENI_CGC_CTRL); val = readl_relaxed(base + SE_DMA_GENERAL_CFG); - val |= AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CFG_ON; + val |= AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CLK_CGC_ON; val |= DMA_TX_CLK_CGC_ON | DMA_RX_CLK_CGC_ON; writel_relaxed(val, base + SE_DMA_GENERAL_CFG); @@ -658,9 +752,12 @@ int geni_se_clk_freq_match(struct geni_se *se, unsigned long req_freq, } EXPORT_SYMBOL_GPL(geni_se_clk_freq_match); -#define GENI_SE_DMA_DONE_EN BIT(0) -#define GENI_SE_DMA_EOT_EN BIT(1) -#define GENI_SE_DMA_AHB_ERR_EN BIT(2) +#define GENI_SE_DMA_DONE_EN BIT(0) +#define GENI_SE_DMA_EOT_EN BIT(1) +#define GENI_SE_DMA_AHB_ERR_EN BIT(2) +#define GENI_SE_DMA_RESET_DONE_EN BIT(3) +#define GENI_SE_DMA_FLUSH_DONE BIT(4) + #define GENI_SE_DMA_EOT_BUF BIT(0) /** @@ -891,6 +988,377 @@ int geni_icc_disable(struct geni_se *se) } EXPORT_SYMBOL_GPL(geni_icc_disable); +/** + * geni_find_protocol_fw() - Locate and validate SE firmware for a protocol. + * @dev: Pointer to the device structure. + * @fw: Pointer to the firmware image. + * @protocol: Expected serial engine protocol type. + * + * Identifies the appropriate firmware image or configuration required for a + * specific communication protocol instance running on a Qualcomm GENI + * controller. + * + * Return: pointer to a valid 'struct se_fw_hdr' if found, or NULL otherwise. + */ +static struct se_fw_hdr *geni_find_protocol_fw(struct device *dev, const struct firmware *fw, + enum geni_se_protocol_type protocol) +{ + const struct elf32_hdr *ehdr; + const struct elf32_phdr *phdrs; + const struct elf32_phdr *phdr; + struct se_fw_hdr *sefw; + u32 fw_end, cfg_idx_end, cfg_val_end; + u16 fw_size; + int i; + + if (!fw || fw->size < sizeof(struct elf32_hdr)) + return NULL; + + ehdr = (const struct elf32_hdr *)fw->data; + phdrs = (const struct elf32_phdr *)(fw->data + ehdr->e_phoff); + + /* + * The firmware is expected to have at least two program headers (segments). + * One for metadata and the other for the actual protocol-specific firmware. + */ + if (ehdr->e_phnum < 2) { + dev_err(dev, "Invalid firmware: less than 2 program headers\n"); + return NULL; + } + + for (i = 0; i < ehdr->e_phnum; i++) { + phdr = &phdrs[i]; + + if (fw->size < phdr->p_offset + phdr->p_filesz) { + dev_err(dev, "Firmware size (%zu) < expected offset (%u) + size (%u)\n", + fw->size, phdr->p_offset, phdr->p_filesz); + return NULL; + } + + if (phdr->p_type != PT_LOAD || !phdr->p_memsz) + continue; + + if (MI_PBT_PAGE_MODE_VALUE(phdr->p_flags) != MI_PBT_NON_PAGED_SEGMENT || + MI_PBT_SEGMENT_TYPE_VALUE(phdr->p_flags) == MI_PBT_HASH_SEGMENT || + MI_PBT_ACCESS_TYPE_VALUE(phdr->p_flags) == MI_PBT_NOTUSED_SEGMENT || + MI_PBT_ACCESS_TYPE_VALUE(phdr->p_flags) == MI_PBT_SHARED_SEGMENT) + continue; + + if (phdr->p_filesz < sizeof(struct se_fw_hdr)) + continue; + + sefw = (struct se_fw_hdr *)(fw->data + phdr->p_offset); + fw_size = le16_to_cpu(sefw->fw_size_in_items); + fw_end = le16_to_cpu(sefw->fw_offset) + fw_size * sizeof(u32); + cfg_idx_end = le16_to_cpu(sefw->cfg_idx_offset) + + le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u8); + cfg_val_end = le16_to_cpu(sefw->cfg_val_offset) + + le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u32); + + if (le32_to_cpu(sefw->magic) != SE_MAGIC_NUM || le32_to_cpu(sefw->version) != 1) + continue; + + if (le32_to_cpu(sefw->serial_protocol) != protocol) + continue; + + if (fw_size % 2 != 0) { + fw_size++; + sefw->fw_size_in_items = cpu_to_le16(fw_size); + } + + if (fw_size >= MAX_GENI_CFG_RAMn_CNT) { + dev_err(dev, + "Firmware size (%u) exceeds max allowed RAMn count (%u)\n", + fw_size, MAX_GENI_CFG_RAMn_CNT); + continue; + } + + if (fw_end > phdr->p_filesz || cfg_idx_end > phdr->p_filesz || + cfg_val_end > phdr->p_filesz) { + dev_err(dev, "Truncated or corrupt SE FW segment found at index %d\n", i); + continue; + } + + return sefw; + } + + dev_err(dev, "Failed to get %s protocol firmware\n", protocol_name[protocol]); + return NULL; +} + +/** + * geni_configure_xfer_mode() - Set the transfer mode. + * @se: Pointer to the concerned serial engine. + * @mode: SE data transfer mode. + * + * Set the transfer mode to either FIFO or DMA according to the mode specified + * by the protocol driver. + * + * Return: 0 if successful, otherwise return an error value. + */ +static int geni_configure_xfer_mode(struct geni_se *se, enum geni_se_xfer_mode mode) +{ + /* Configure SE FIFO, DMA or GSI mode. */ + switch (mode) { + case GENI_GPI_DMA: + geni_setbits32(se->base + SE_GENI_DMA_MODE_EN, GENI_DMA_MODE_EN); + writel(0x0, se->base + SE_IRQ_EN); + writel(DMA_RX_EVENT_EN | DMA_TX_EVENT_EN | GENI_M_EVENT_EN | GENI_S_EVENT_EN, + se->base + SE_GSI_EVENT_EN); + break; + + case GENI_SE_FIFO: + geni_clrbits32(se->base + SE_GENI_DMA_MODE_EN, GENI_DMA_MODE_EN); + writel(DMA_RX_IRQ_EN | DMA_TX_IRQ_EN | GENI_M_IRQ_EN | GENI_S_IRQ_EN, + se->base + SE_IRQ_EN); + writel(0x0, se->base + SE_GSI_EVENT_EN); + break; + + case GENI_SE_DMA: + geni_setbits32(se->base + SE_GENI_DMA_MODE_EN, GENI_DMA_MODE_EN); + writel(DMA_RX_IRQ_EN | DMA_TX_IRQ_EN | GENI_M_IRQ_EN | GENI_S_IRQ_EN, + se->base + SE_IRQ_EN); + writel(0x0, se->base + SE_GSI_EVENT_EN); + break; + + default: + dev_err(se->dev, "Invalid geni-se transfer mode: %d\n", mode); + return -EINVAL; + } + return 0; +} + +/** + * geni_enable_interrupts() - Enable interrupts. + * @se: Pointer to the concerned serial engine. + * + * Enable the required interrupts during the firmware load process. + */ +static void geni_enable_interrupts(struct geni_se *se) +{ + u32 val; + + /* Enable required interrupts. */ + writel(M_COMMON_GENI_M_IRQ_EN, se->base + SE_GENI_M_IRQ_EN); + + val = S_CMD_OVERRUN_EN | S_ILLEGAL_CMD_EN | S_CMD_CANCEL_EN | S_CMD_ABORT_EN | + S_GP_IRQ_0_EN | S_GP_IRQ_1_EN | S_GP_IRQ_2_EN | S_GP_IRQ_3_EN | + S_RX_FIFO_WR_ERR_EN | S_RX_FIFO_RD_ERR_EN; + writel(val, se->base + SE_GENI_S_IRQ_ENABLE); + + /* DMA mode configuration. */ + val = GENI_SE_DMA_RESET_DONE_EN | GENI_SE_DMA_AHB_ERR_EN | GENI_SE_DMA_DONE_EN; + writel(val, se->base + SE_DMA_TX_IRQ_EN_SET); + val = GENI_SE_DMA_FLUSH_DONE | GENI_SE_DMA_RESET_DONE_EN | GENI_SE_DMA_AHB_ERR_EN | + GENI_SE_DMA_DONE_EN; + writel(val, se->base + SE_DMA_RX_IRQ_EN_SET); +} + +/** + * geni_write_fw_revision() - Write the firmware revision. + * @se: Pointer to the concerned serial engine. + * @serial_protocol: serial protocol type. + * @fw_version: QUP firmware version. + * + * Write the firmware revision and protocol into the respective register. + */ +static void geni_write_fw_revision(struct geni_se *se, u16 serial_protocol, u16 fw_version) +{ + u32 reg; + + reg = FIELD_PREP(FW_REV_PROTOCOL_MSK, serial_protocol); + reg |= FIELD_PREP(FW_REV_VERSION_MSK, fw_version); + + writel(reg, se->base + SE_GENI_FW_REVISION); + writel(reg, se->base + SE_GENI_S_FW_REVISION); +} + +/** + * geni_load_se_fw() - Load Serial Engine specific firmware. + * @se: Pointer to the concerned serial engine. + * @fw: Pointer to the firmware structure. + * @mode: SE data transfer mode. + * @protocol: Protocol type to be used with the SE (e.g., UART, SPI, I2C). + * + * Load the protocol firmware into the IRAM of the Serial Engine. + * + * Return: 0 if successful, otherwise return an error value. + */ +static int geni_load_se_fw(struct geni_se *se, const struct firmware *fw, + enum geni_se_xfer_mode mode, enum geni_se_protocol_type protocol) +{ + const u32 *fw_data, *cfg_val_arr; + const u8 *cfg_idx_arr; + u32 i, reg_value; + int ret; + struct se_fw_hdr *hdr; + + hdr = geni_find_protocol_fw(se->dev, fw, protocol); + if (!hdr) + return -EINVAL; + + fw_data = (const u32 *)((u8 *)hdr + le16_to_cpu(hdr->fw_offset)); + cfg_idx_arr = (const u8 *)hdr + le16_to_cpu(hdr->cfg_idx_offset); + cfg_val_arr = (const u32 *)((u8 *)hdr + le16_to_cpu(hdr->cfg_val_offset)); + + ret = geni_icc_set_bw(se); + if (ret) + return ret; + + ret = geni_icc_enable(se); + if (ret) + return ret; + + ret = geni_se_resources_on(se); + if (ret) + goto out_icc_disable; + + /* + * Disable high-priority interrupts until all currently executing + * low-priority interrupts have been fully handled. + */ + geni_setbits32(se->wrapper->base + QUPV3_COMMON_CFG, FAST_SWITCH_TO_HIGH_DISABLE); + + /* Set AHB_M_CLK_CGC_ON to indicate hardware controls se-wrapper cgc clock. */ + geni_setbits32(se->wrapper->base + QUPV3_SE_AHB_M_CFG, AHB_M_CLK_CGC_ON); + + /* Let hardware to control common cgc. */ + geni_setbits32(se->wrapper->base + QUPV3_COMMON_CGC_CTRL, COMMON_CSR_SLV_CLK_CGC_ON); + + /* + * Setting individual bits in GENI_OUTPUT_CTRL activates corresponding output lines, + * allowing the hardware to drive data as configured. + */ + writel(0x0, se->base + GENI_OUTPUT_CTRL); + + /* Set SCLK and HCLK to program RAM */ + geni_setbits32(se->base + SE_GENI_CGC_CTRL, PROG_RAM_SCLK_OFF | PROG_RAM_HCLK_OFF); + writel(0x0, se->base + SE_GENI_CLK_CTRL); + geni_clrbits32(se->base + SE_GENI_CGC_CTRL, PROG_RAM_SCLK_OFF | PROG_RAM_HCLK_OFF); + + /* Enable required clocks for DMA CSR, TX and RX. */ + reg_value = AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CLK_CGC_ON | + DMA_TX_CLK_CGC_ON | DMA_RX_CLK_CGC_ON; + geni_setbits32(se->base + SE_DMA_GENERAL_CFG, reg_value); + + /* Let hardware control CGC by default. */ + writel(DEFAULT_CGC_EN, se->base + SE_GENI_CGC_CTRL); + + /* Set version of the configuration register part of firmware. */ + writel(le16_to_cpu(hdr->cfg_version), se->base + SE_GENI_INIT_CFG_REVISION); + writel(le16_to_cpu(hdr->cfg_version), se->base + SE_GENI_S_INIT_CFG_REVISION); + + /* Configure GENI primitive table. */ + for (i = 0; i < le16_to_cpu(hdr->cfg_size_in_items); i++) + writel(cfg_val_arr[i], + se->base + SE_GENI_CFG_REG0 + (cfg_idx_arr[i] * sizeof(u32))); + + /* Configure condition for assertion of RX_RFR_WATERMARK condition. */ + reg_value = geni_se_get_rx_fifo_depth(se); + writel(reg_value - 2, se->base + SE_GENI_RX_RFR_WATERMARK_REG); + + /* Let hardware control CGC */ + geni_setbits32(se->base + GENI_OUTPUT_CTRL, DEFAULT_IO_OUTPUT_CTRL_MSK); + + ret = geni_configure_xfer_mode(se, mode); + if (ret) + goto out_resources_off; + + geni_enable_interrupts(se); + + geni_write_fw_revision(se, le16_to_cpu(hdr->serial_protocol), le16_to_cpu(hdr->fw_version)); + + /* Program RAM address space. */ + memcpy_toio(se->base + SE_GENI_CFG_RAMN, fw_data, + le16_to_cpu(hdr->fw_size_in_items) * sizeof(u32)); + + /* Put default values on GENI's output pads. */ + writel_relaxed(0x1, se->base + GENI_FORCE_DEFAULT_REG); + + /* Toggle SCLK/HCLK from high to low to finalize RAM programming and apply config. */ + geni_setbits32(se->base + SE_GENI_CGC_CTRL, PROG_RAM_SCLK_OFF | PROG_RAM_HCLK_OFF); + geni_setbits32(se->base + SE_GENI_CLK_CTRL, SER_CLK_SEL); + geni_clrbits32(se->base + SE_GENI_CGC_CTRL, PROG_RAM_SCLK_OFF | PROG_RAM_HCLK_OFF); + + /* Serial engine DMA interface is enabled. */ + geni_setbits32(se->base + SE_DMA_IF_EN, DMA_IF_EN); + + /* Enable or disable FIFO interface of the serial engine. */ + if (mode == GENI_SE_FIFO) + geni_clrbits32(se->base + SE_FIFO_IF_DISABLE, FIFO_IF_DISABLE); + else + geni_setbits32(se->base + SE_FIFO_IF_DISABLE, FIFO_IF_DISABLE); + +out_resources_off: + geni_se_resources_off(se); + +out_icc_disable: + geni_icc_disable(se); + return ret; +} + +/** + * geni_load_se_firmware() - Load firmware for SE based on protocol + * @se: Pointer to the concerned serial engine. + * @protocol: Protocol type to be used with the SE (e.g., UART, SPI, I2C). + * + * Retrieves the firmware name from device properties and sets the transfer mode + * (FIFO or GSI DMA) based on device tree configuration. Enforces FIFO mode for + * UART protocol due to lack of GSI DMA support. Requests the firmware and loads + * it into the SE. + * + * Return: 0 on success, negative error code on failure. + */ +int geni_load_se_firmware(struct geni_se *se, enum geni_se_protocol_type protocol) +{ + const char *fw_name; + const struct firmware *fw; + enum geni_se_xfer_mode mode = GENI_SE_FIFO; + int ret; + + if (protocol >= ARRAY_SIZE(protocol_name)) { + dev_err(se->dev, "Invalid geni-se protocol: %d", protocol); + return -EINVAL; + } + + ret = device_property_read_string(se->wrapper->dev, "firmware-name", &fw_name); + if (ret) { + dev_err(se->dev, "Failed to read firmware-name property: %d\n", ret); + return -EINVAL; + } + + if (of_property_read_bool(se->dev->of_node, "qcom,enable-gsi-dma")) + mode = GENI_GPI_DMA; + + /* GSI mode is not supported by the UART driver; therefore, setting FIFO mode */ + if (protocol == GENI_SE_UART) + mode = GENI_SE_FIFO; + + ret = request_firmware(&fw, fw_name, se->dev); + if (ret) { + if (ret == -ENOENT) + return -EPROBE_DEFER; + + dev_err(se->dev, "Failed to request firmware '%s' for protocol %d: ret: %d\n", + fw_name, protocol, ret); + return ret; + } + + ret = geni_load_se_fw(se, fw, mode, protocol); + release_firmware(fw); + + if (ret) { + dev_err(se->dev, "Failed to load SE firmware for protocol %d: ret: %d\n", + protocol, ret); + return ret; + } + + dev_dbg(se->dev, "Firmware load for %s protocol is successful for xfer mode: %d\n", + protocol_name[protocol], mode); + return 0; +} +EXPORT_SYMBOL_GPL(geni_load_se_firmware); + static int geni_se_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index 3abea241b1c4..6384f271953d 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -584,6 +584,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,sm8450", .data = sm8350_domains, }, { .compatible = "qcom,sm8550", .data = sm8550_domains, }, { .compatible = "qcom,sm8650", .data = sm8550_domains, }, + { .compatible = "qcom,sm8750", .data = sm8550_domains, }, { .compatible = "qcom,x1e80100", .data = x1e80100_domains, }, { .compatible = "qcom,x1p42100", .data = x1e80100_domains, }, {}, diff --git a/drivers/soc/qcom/ramp_controller.c b/drivers/soc/qcom/ramp_controller.c index 349bdfbc61ef..15782bed2925 100644 --- a/drivers/soc/qcom/ramp_controller.c +++ b/drivers/soc/qcom/ramp_controller.c @@ -229,7 +229,6 @@ static const struct regmap_config qrc_regmap_config = { .reg_stride = 4, .val_bits = 32, .max_register = 0x68, - .fast_io = true, }; static const struct reg_sequence msm8976_cfg_dfs_sid[] = { diff --git a/drivers/soc/qcom/rpm_master_stats.c b/drivers/soc/qcom/rpm_master_stats.c index 49e4f9457279..c7788337e164 100644 --- a/drivers/soc/qcom/rpm_master_stats.c +++ b/drivers/soc/qcom/rpm_master_stats.c @@ -78,7 +78,7 @@ static int master_stats_probe(struct platform_device *pdev) if (count < 0) return count; - data = devm_kzalloc(dev, count * sizeof(*data), GFP_KERNEL); + data = devm_kcalloc(dev, count, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index fdab2b1067db..c6f7d5c9c493 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -453,13 +453,10 @@ static irqreturn_t tcs_tx_done(int irq, void *p) trace_rpmh_tx_done(drv, i, req); - /* - * If wake tcs was re-purposed for sending active - * votes, clear AMC trigger & enable modes and + /* Clear AMC trigger & enable modes and * disable interrupt for this TCS */ - if (!drv->tcs[ACTIVE_TCS].num_tcs) - __tcs_set_trigger(drv, i, false); + __tcs_set_trigger(drv, i, false); skip: /* Reclaim the TCS */ write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], i, 0); diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index cf425930539e..c4c45f15dca4 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -898,7 +898,7 @@ static u32 qcom_smem_get_item_count(struct qcom_smem *smem) if (IS_ERR_OR_NULL(ptable)) return SMEM_ITEM_COUNT; - info = (struct smem_info *)&ptable->entry[ptable->num_entries]; + info = (struct smem_info *)&ptable->entry[le32_to_cpu(ptable->num_entries)]; if (memcmp(info->magic, SMEM_INFO_MAGIC, sizeof(info->magic))) return SMEM_ITEM_COUNT; diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 719b7f4f376f..340a1ff7e92b 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -39,6 +39,10 @@ config ARCH_RCAR_GEN4 bool select ARCH_RCAR_GEN3 +config ARCH_RCAR_GEN5 + bool + select ARCH_RCAR_GEN4 + config ARCH_RMOBILE bool select PM @@ -348,6 +352,14 @@ config ARCH_R8A779H0 help This enables support for the Renesas R-Car V4M SoC. +config ARCH_R8A78000 + bool "ARM64 Platform support for R8A78000 (R-Car X5H)" + default y if ARCH_RENESAS + default ARCH_RENESAS + select ARCH_RCAR_GEN5 + help + This enables support for the Renesas R-Car X5H SoC. + config ARCH_R9A07G043 bool "ARM64 Platform support for R9A07G043U (RZ/G2UL)" default y if ARCH_RENESAS @@ -449,6 +461,7 @@ config RST_RCAR config SYSC_RZ bool "System controller for RZ SoCs" if COMPILE_TEST + select MFD_SYSCON config SYSC_R9A08G045 bool "Renesas System controller support for R9A08G045 (RZ/G3S)" if COMPILE_TEST diff --git a/drivers/soc/renesas/r9a08g045-sysc.c b/drivers/soc/renesas/r9a08g045-sysc.c index f4db1431e036..0504d4e68761 100644 --- a/drivers/soc/renesas/r9a08g045-sysc.c +++ b/drivers/soc/renesas/r9a08g045-sysc.c @@ -20,4 +20,5 @@ static const struct rz_sysc_soc_id_init_data rzg3s_sysc_soc_id_init_data __initc const struct rz_sysc_init_data rzg3s_sysc_init_data __initconst = { .soc_id_init_data = &rzg3s_sysc_soc_id_init_data, + .max_register = 0xe20, }; diff --git a/drivers/soc/renesas/r9a09g047-sys.c b/drivers/soc/renesas/r9a09g047-sys.c index cd2eb7782cfe..2e8426c03050 100644 --- a/drivers/soc/renesas/r9a09g047-sys.c +++ b/drivers/soc/renesas/r9a09g047-sys.c @@ -64,4 +64,5 @@ static const struct rz_sysc_soc_id_init_data rzg3e_sys_soc_id_init_data __initco const struct rz_sysc_init_data rzg3e_sys_init_data = { .soc_id_init_data = &rzg3e_sys_soc_id_init_data, + .max_register = 0x170c, }; diff --git a/drivers/soc/renesas/r9a09g057-sys.c b/drivers/soc/renesas/r9a09g057-sys.c index 4c21cc29edbc..e3390e7c7fe5 100644 --- a/drivers/soc/renesas/r9a09g057-sys.c +++ b/drivers/soc/renesas/r9a09g057-sys.c @@ -64,4 +64,5 @@ static const struct rz_sysc_soc_id_init_data rzv2h_sys_soc_id_init_data __initco const struct rz_sysc_init_data rzv2h_sys_init_data = { .soc_id_init_data = &rzv2h_sys_soc_id_init_data, + .max_register = 0x170c, }; diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index df2b38417b80..1eb52356b996 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -36,6 +36,10 @@ static const struct renesas_family fam_rcar_gen4 __initconst __maybe_unused = { .name = "R-Car Gen4", }; +static const struct renesas_family fam_rcar_gen5 __initconst __maybe_unused = { + .name = "R-Car Gen5", +}; + static const struct renesas_family fam_rmobile __initconst __maybe_unused = { .name = "R-Mobile", .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */ @@ -266,6 +270,11 @@ static const struct renesas_soc soc_rcar_v4m __initconst __maybe_unused = { .id = 0x5d, }; +static const struct renesas_soc soc_rcar_x5h __initconst __maybe_unused = { + .family = &fam_rcar_gen5, + .id = 0x60, +}; + static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = { .family = &fam_shmobile, .id = 0x37, @@ -378,6 +387,9 @@ static const struct of_device_id renesas_socs[] __initconst __maybe_unused = { #ifdef CONFIG_ARCH_R8A779H0 { .compatible = "renesas,r8a779h0", .data = &soc_rcar_v4m }, #endif +#ifdef CONFIG_ARCH_R8A78000 + { .compatible = "renesas,r8a78000", .data = &soc_rcar_x5h }, +#endif #ifdef CONFIG_ARCH_R9A07G043 #ifdef CONFIG_RISCV { .compatible = "renesas,r9a07g043", .data = &soc_rz_five }, diff --git a/drivers/soc/renesas/rz-sysc.c b/drivers/soc/renesas/rz-sysc.c index ffa65fb4dade..9f79e299e6f4 100644 --- a/drivers/soc/renesas/rz-sysc.c +++ b/drivers/soc/renesas/rz-sysc.c @@ -5,9 +5,13 @@ * Copyright (C) 2024 Renesas Electronics Corp. */ +#include <linux/cleanup.h> #include <linux/io.h> +#include <linux/mfd/syscon.h> #include <linux/of.h> #include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/slab.h> #include <linux/sys_soc.h> #include "rz-sysc.h" @@ -100,14 +104,23 @@ MODULE_DEVICE_TABLE(of, rz_sysc_match); static int rz_sysc_probe(struct platform_device *pdev) { + const struct rz_sysc_init_data *data; const struct of_device_id *match; struct device *dev = &pdev->dev; + struct regmap *regmap; struct rz_sysc *sysc; + int ret; + + struct regmap_config *regmap_cfg __free(kfree) = kzalloc(sizeof(*regmap_cfg), GFP_KERNEL); + if (!regmap_cfg) + return -ENOMEM; match = of_match_node(rz_sysc_match, dev->of_node); if (!match) return -ENODEV; + data = match->data; + sysc = devm_kzalloc(dev, sizeof(*sysc), GFP_KERNEL); if (!sysc) return -ENOMEM; @@ -117,7 +130,22 @@ static int rz_sysc_probe(struct platform_device *pdev) return PTR_ERR(sysc->base); sysc->dev = dev; - return rz_sysc_soc_init(sysc, match); + ret = rz_sysc_soc_init(sysc, match); + if (ret) + return ret; + + regmap_cfg->name = "rz_sysc_regs"; + regmap_cfg->reg_bits = 32; + regmap_cfg->reg_stride = 4; + regmap_cfg->val_bits = 32; + regmap_cfg->fast_io = true; + regmap_cfg->max_register = data->max_register; + + regmap = devm_regmap_init_mmio(dev, sysc->base, regmap_cfg); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return of_syscon_register_regmap(dev->of_node, regmap); } static struct platform_driver rz_sysc_driver = { diff --git a/drivers/soc/renesas/rz-sysc.h b/drivers/soc/renesas/rz-sysc.h index 56bc047a1bff..8eec355d5d56 100644 --- a/drivers/soc/renesas/rz-sysc.h +++ b/drivers/soc/renesas/rz-sysc.h @@ -34,9 +34,11 @@ struct rz_sysc_soc_id_init_data { /** * struct rz_sysc_init_data - RZ SYSC initialization data * @soc_id_init_data: RZ SYSC SoC ID initialization data + * @max_register: Maximum SYSC register offset to be used by the regmap config */ struct rz_sysc_init_data { const struct rz_sysc_soc_id_init_data *soc_id_init_data; + u32 max_register; }; extern const struct rz_sysc_init_data rzg3e_sys_init_data; diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c index 1eab4bb0eacf..344870da7675 100644 --- a/drivers/soc/rockchip/grf.c +++ b/drivers/soc/rockchip/grf.c @@ -6,13 +6,12 @@ */ #include <linux/err.h> +#include <linux/hw_bitfield.h> #include <linux/mfd/syscon.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> -#define HIWORD_UPDATE(val, mask, shift) \ - ((val) << (shift) | (mask) << ((shift) + 16)) struct rockchip_grf_value { const char *desc; @@ -32,7 +31,7 @@ static const struct rockchip_grf_value rk3036_defaults[] __initconst = { * Disable auto jtag/sdmmc switching that causes issues with the * clock-framework and the mmc controllers making them unreliable. */ - { "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) }, + { "jtag switching", RK3036_GRF_SOC_CON0, FIELD_PREP_WM16_CONST(BIT(11), 0) }, }; static const struct rockchip_grf_info rk3036_grf __initconst = { @@ -44,8 +43,8 @@ static const struct rockchip_grf_info rk3036_grf __initconst = { #define RK3128_GRF_SOC_CON1 0x144 static const struct rockchip_grf_value rk3128_defaults[] __initconst = { - { "jtag switching", RK3128_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 8) }, - { "vpu main clock", RK3128_GRF_SOC_CON1, HIWORD_UPDATE(0, 1, 10) }, + { "jtag switching", RK3128_GRF_SOC_CON0, FIELD_PREP_WM16_CONST(BIT(8), 0) }, + { "vpu main clock", RK3128_GRF_SOC_CON1, FIELD_PREP_WM16_CONST(BIT(10), 0) }, }; static const struct rockchip_grf_info rk3128_grf __initconst = { @@ -56,7 +55,7 @@ static const struct rockchip_grf_info rk3128_grf __initconst = { #define RK3228_GRF_SOC_CON6 0x418 static const struct rockchip_grf_value rk3228_defaults[] __initconst = { - { "jtag switching", RK3228_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 8) }, + { "jtag switching", RK3228_GRF_SOC_CON6, FIELD_PREP_WM16_CONST(BIT(8), 0) }, }; static const struct rockchip_grf_info rk3228_grf __initconst = { @@ -68,8 +67,8 @@ static const struct rockchip_grf_info rk3228_grf __initconst = { #define RK3288_GRF_SOC_CON2 0x24c static const struct rockchip_grf_value rk3288_defaults[] __initconst = { - { "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) }, - { "pwm select", RK3288_GRF_SOC_CON2, HIWORD_UPDATE(1, 1, 0) }, + { "jtag switching", RK3288_GRF_SOC_CON0, FIELD_PREP_WM16_CONST(BIT(12), 0) }, + { "pwm select", RK3288_GRF_SOC_CON2, FIELD_PREP_WM16_CONST(BIT(0), 1) }, }; static const struct rockchip_grf_info rk3288_grf __initconst = { @@ -80,7 +79,7 @@ static const struct rockchip_grf_info rk3288_grf __initconst = { #define RK3328_GRF_SOC_CON4 0x410 static const struct rockchip_grf_value rk3328_defaults[] __initconst = { - { "jtag switching", RK3328_GRF_SOC_CON4, HIWORD_UPDATE(0, 1, 12) }, + { "jtag switching", RK3328_GRF_SOC_CON4, FIELD_PREP_WM16_CONST(BIT(12), 0) }, }; static const struct rockchip_grf_info rk3328_grf __initconst = { @@ -91,7 +90,7 @@ static const struct rockchip_grf_info rk3328_grf __initconst = { #define RK3368_GRF_SOC_CON15 0x43c static const struct rockchip_grf_value rk3368_defaults[] __initconst = { - { "jtag switching", RK3368_GRF_SOC_CON15, HIWORD_UPDATE(0, 1, 13) }, + { "jtag switching", RK3368_GRF_SOC_CON15, FIELD_PREP_WM16_CONST(BIT(13), 0) }, }; static const struct rockchip_grf_info rk3368_grf __initconst = { @@ -102,7 +101,7 @@ static const struct rockchip_grf_info rk3368_grf __initconst = { #define RK3399_GRF_SOC_CON7 0xe21c static const struct rockchip_grf_value rk3399_defaults[] __initconst = { - { "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) }, + { "jtag switching", RK3399_GRF_SOC_CON7, FIELD_PREP_WM16_CONST(BIT(12), 0) }, }; static const struct rockchip_grf_info rk3399_grf __initconst = { @@ -113,9 +112,9 @@ static const struct rockchip_grf_info rk3399_grf __initconst = { #define RK3566_GRF_USB3OTG0_CON1 0x0104 static const struct rockchip_grf_value rk3566_defaults[] __initconst = { - { "usb3otg port switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(0, 1, 12) }, - { "usb3otg clock switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 7) }, - { "usb3otg disable usb3", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 0) }, + { "usb3otg port switch", RK3566_GRF_USB3OTG0_CON1, FIELD_PREP_WM16_CONST(BIT(12), 0) }, + { "usb3otg clock switch", RK3566_GRF_USB3OTG0_CON1, FIELD_PREP_WM16_CONST(BIT(7), 1) }, + { "usb3otg disable usb3", RK3566_GRF_USB3OTG0_CON1, FIELD_PREP_WM16_CONST(BIT(0), 1) }, }; static const struct rockchip_grf_info rk3566_pipegrf __initconst = { @@ -126,8 +125,8 @@ static const struct rockchip_grf_info rk3566_pipegrf __initconst = { #define RK3576_SYSGRF_SOC_CON1 0x0004 static const struct rockchip_grf_value rk3576_defaults_sys_grf[] __initconst = { - { "i3c0 weakpull", RK3576_SYSGRF_SOC_CON1, HIWORD_UPDATE(3, 3, 6) }, - { "i3c1 weakpull", RK3576_SYSGRF_SOC_CON1, HIWORD_UPDATE(3, 3, 8) }, + { "i3c0 weakpull", RK3576_SYSGRF_SOC_CON1, FIELD_PREP_WM16_CONST(GENMASK(7, 6), 3) }, + { "i3c1 weakpull", RK3576_SYSGRF_SOC_CON1, FIELD_PREP_WM16_CONST(GENMASK(9, 8), 3) }, }; static const struct rockchip_grf_info rk3576_sysgrf __initconst = { @@ -138,7 +137,7 @@ static const struct rockchip_grf_info rk3576_sysgrf __initconst = { #define RK3576_IOCGRF_MISC_CON 0x04F0 static const struct rockchip_grf_value rk3576_defaults_ioc_grf[] __initconst = { - { "jtag switching", RK3576_IOCGRF_MISC_CON, HIWORD_UPDATE(0, 1, 1) }, + { "jtag switching", RK3576_IOCGRF_MISC_CON, FIELD_PREP_WM16_CONST(BIT(1), 0) }, }; static const struct rockchip_grf_info rk3576_iocgrf __initconst = { @@ -149,7 +148,7 @@ static const struct rockchip_grf_info rk3576_iocgrf __initconst = { #define RK3588_GRF_SOC_CON6 0x0318 static const struct rockchip_grf_value rk3588_defaults[] __initconst = { - { "jtag switching", RK3588_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 14) }, + { "jtag switching", RK3588_GRF_SOC_CON6, FIELD_PREP_WM16_CONST(BIT(14), 0) }, }; static const struct rockchip_grf_info rk3588_sysgrf __initconst = { diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c index a77288f49d24..22c50ca2aa79 100644 --- a/drivers/soc/samsung/exynos-pmu.c +++ b/drivers/soc/samsung/exynos-pmu.c @@ -7,7 +7,9 @@ #include <linux/array_size.h> #include <linux/arm-smccc.h> +#include <linux/bitmap.h> #include <linux/cpuhotplug.h> +#include <linux/cpu_pm.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/mfd/core.h> @@ -15,6 +17,7 @@ #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/delay.h> +#include <linux/reboot.h> #include <linux/regmap.h> #include <linux/soc/samsung/exynos-regs-pmu.h> @@ -35,6 +38,15 @@ struct exynos_pmu_context { const struct exynos_pmu_data *pmu_data; struct regmap *pmureg; struct regmap *pmuintrgen; + /* + * Serialization lock for CPU hot plug and cpuidle ACPM hint + * programming. Also protects in_cpuhp, sys_insuspend & sys_inreboot + * flags. + */ + raw_spinlock_t cpupm_lock; + unsigned long *in_cpuhp; + bool sys_insuspend; + bool sys_inreboot; }; void __iomem *pmu_base_addr; @@ -221,6 +233,15 @@ static const struct regmap_config regmap_smccfg = { .reg_read = tensor_sec_reg_read, .reg_write = tensor_sec_reg_write, .reg_update_bits = tensor_sec_update_bits, + .use_raw_spinlock = true, +}; + +static const struct regmap_config regmap_pmu_intr = { + .name = "pmu_intr_gen", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .use_raw_spinlock = true, }; static const struct exynos_pmu_data gs101_pmu_data = { @@ -330,13 +351,19 @@ struct regmap *exynos_get_pmu_regmap_by_phandle(struct device_node *np, EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap_by_phandle); /* - * CPU_INFORM register hint values which are used by - * EL3 firmware (el3mon). + * CPU_INFORM register "hint" values are required to be programmed in addition to + * the standard PSCI calls to have functional CPU hotplug and CPU idle states. + * This is required to workaround limitations in the el3mon/ACPM firmware. */ #define CPU_INFORM_CLEAR 0 #define CPU_INFORM_C2 1 -static int gs101_cpuhp_pmu_online(unsigned int cpu) +/* + * __gs101_cpu_pmu_ prefix functions are common code shared by CPU PM notifiers + * (CPUIdle) and CPU hotplug callbacks. Functions should be called with IRQs + * disabled and cpupm_lock held. + */ +static int __gs101_cpu_pmu_online(unsigned int cpu) { unsigned int cpuhint = smp_processor_id(); u32 reg, mask; @@ -358,10 +385,48 @@ static int gs101_cpuhp_pmu_online(unsigned int cpu) return 0; } -static int gs101_cpuhp_pmu_offline(unsigned int cpu) +/* Called from CPU PM notifier (CPUIdle code path) with IRQs disabled */ +static int gs101_cpu_pmu_online(void) +{ + int cpu; + + raw_spin_lock(&pmu_context->cpupm_lock); + + if (pmu_context->sys_inreboot) { + raw_spin_unlock(&pmu_context->cpupm_lock); + return NOTIFY_OK; + } + + cpu = smp_processor_id(); + __gs101_cpu_pmu_online(cpu); + raw_spin_unlock(&pmu_context->cpupm_lock); + + return NOTIFY_OK; +} + +/* Called from CPU hot plug callback with IRQs enabled */ +static int gs101_cpuhp_pmu_online(unsigned int cpu) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&pmu_context->cpupm_lock, flags); + + __gs101_cpu_pmu_online(cpu); + /* + * Mark this CPU as having finished the hotplug. + * This means this CPU can now enter C2 idle state. + */ + clear_bit(cpu, pmu_context->in_cpuhp); + raw_spin_unlock_irqrestore(&pmu_context->cpupm_lock, flags); + + return 0; +} + +/* Common function shared by both CPU hot plug and CPUIdle */ +static int __gs101_cpu_pmu_offline(unsigned int cpu) { - u32 reg, mask; unsigned int cpuhint = smp_processor_id(); + u32 reg, mask; /* set cpu inform hint */ regmap_write(pmu_context->pmureg, GS101_CPU_INFORM(cpuhint), @@ -379,6 +444,165 @@ static int gs101_cpuhp_pmu_offline(unsigned int cpu) regmap_read(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_UPEND, ®); regmap_write(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_CLEAR, reg & mask); + + return 0; +} + +/* Called from CPU PM notifier (CPUIdle code path) with IRQs disabled */ +static int gs101_cpu_pmu_offline(void) +{ + int cpu; + + raw_spin_lock(&pmu_context->cpupm_lock); + cpu = smp_processor_id(); + + if (test_bit(cpu, pmu_context->in_cpuhp)) { + raw_spin_unlock(&pmu_context->cpupm_lock); + return NOTIFY_BAD; + } + + /* Ignore CPU_PM_ENTER event in reboot or suspend sequence. */ + if (pmu_context->sys_insuspend || pmu_context->sys_inreboot) { + raw_spin_unlock(&pmu_context->cpupm_lock); + return NOTIFY_OK; + } + + __gs101_cpu_pmu_offline(cpu); + raw_spin_unlock(&pmu_context->cpupm_lock); + + return NOTIFY_OK; +} + +/* Called from CPU hot plug callback with IRQs enabled */ +static int gs101_cpuhp_pmu_offline(unsigned int cpu) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&pmu_context->cpupm_lock, flags); + /* + * Mark this CPU as entering hotplug. So as not to confuse + * ACPM the CPU entering hotplug should not enter C2 idle state. + */ + set_bit(cpu, pmu_context->in_cpuhp); + __gs101_cpu_pmu_offline(cpu); + + raw_spin_unlock_irqrestore(&pmu_context->cpupm_lock, flags); + + return 0; +} + +static int gs101_cpu_pm_notify_callback(struct notifier_block *self, + unsigned long action, void *v) +{ + switch (action) { + case CPU_PM_ENTER: + return gs101_cpu_pmu_offline(); + + case CPU_PM_EXIT: + return gs101_cpu_pmu_online(); + } + + return NOTIFY_OK; +} + +static struct notifier_block gs101_cpu_pm_notifier = { + .notifier_call = gs101_cpu_pm_notify_callback, + /* + * We want to be called first, as the ACPM hint and handshake is what + * puts the CPU into C2. + */ + .priority = INT_MAX +}; + +static int exynos_cpupm_reboot_notifier(struct notifier_block *nb, + unsigned long event, void *v) +{ + unsigned long flags; + + switch (event) { + case SYS_POWER_OFF: + case SYS_RESTART: + raw_spin_lock_irqsave(&pmu_context->cpupm_lock, flags); + pmu_context->sys_inreboot = true; + raw_spin_unlock_irqrestore(&pmu_context->cpupm_lock, flags); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block exynos_cpupm_reboot_nb = { + .priority = INT_MAX, + .notifier_call = exynos_cpupm_reboot_notifier, +}; + +static int setup_cpuhp_and_cpuidle(struct device *dev) +{ + struct device_node *intr_gen_node; + struct resource intrgen_res; + void __iomem *virt_addr; + int ret, cpu; + + intr_gen_node = of_parse_phandle(dev->of_node, + "google,pmu-intr-gen-syscon", 0); + if (!intr_gen_node) { + /* + * To maintain support for older DTs that didn't specify syscon + * phandle just issue a warning rather than fail to probe. + */ + dev_warn(dev, "pmu-intr-gen syscon unavailable\n"); + return 0; + } + + /* + * To avoid lockdep issues (CPU PM notifiers use raw spinlocks) create + * a mmio regmap for pmu-intr-gen that uses raw spinlocks instead of + * syscon provided regmap. + */ + ret = of_address_to_resource(intr_gen_node, 0, &intrgen_res); + of_node_put(intr_gen_node); + + virt_addr = devm_ioremap(dev, intrgen_res.start, + resource_size(&intrgen_res)); + if (!virt_addr) + return -ENOMEM; + + pmu_context->pmuintrgen = devm_regmap_init_mmio(dev, virt_addr, + ®map_pmu_intr); + if (IS_ERR(pmu_context->pmuintrgen)) { + dev_err(dev, "failed to initialize pmu-intr-gen regmap\n"); + return PTR_ERR(pmu_context->pmuintrgen); + } + + /* register custom mmio regmap with syscon */ + ret = of_syscon_register_regmap(intr_gen_node, + pmu_context->pmuintrgen); + if (ret) + return ret; + + pmu_context->in_cpuhp = devm_bitmap_zalloc(dev, num_possible_cpus(), + GFP_KERNEL); + if (!pmu_context->in_cpuhp) + return -ENOMEM; + + raw_spin_lock_init(&pmu_context->cpupm_lock); + pmu_context->sys_inreboot = false; + pmu_context->sys_insuspend = false; + + /* set PMU to power on */ + for_each_online_cpu(cpu) + gs101_cpuhp_pmu_online(cpu); + + /* register CPU hotplug callbacks */ + cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "soc/exynos-pmu:prepare", + gs101_cpuhp_pmu_online, NULL); + + cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/exynos-pmu:online", + NULL, gs101_cpuhp_pmu_offline); + + /* register CPU PM notifiers for cpuidle */ + cpu_pm_register_notifier(&gs101_cpu_pm_notifier); + register_reboot_notifier(&exynos_cpupm_reboot_nb); return 0; } @@ -435,23 +659,9 @@ static int exynos_pmu_probe(struct platform_device *pdev) pmu_context->dev = dev; if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp) { - pmu_context->pmuintrgen = syscon_regmap_lookup_by_phandle(dev->of_node, - "google,pmu-intr-gen-syscon"); - if (IS_ERR(pmu_context->pmuintrgen)) { - /* - * To maintain support for older DTs that didn't specify syscon phandle - * just issue a warning rather than fail to probe. - */ - dev_warn(&pdev->dev, "pmu-intr-gen syscon unavailable\n"); - } else { - cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, - "soc/exynos-pmu:prepare", - gs101_cpuhp_pmu_online, NULL); - - cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, - "soc/exynos-pmu:online", - NULL, gs101_cpuhp_pmu_offline); - } + ret = setup_cpuhp_and_cpuidle(dev); + if (ret) + return ret; } if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_init) @@ -471,10 +681,32 @@ static int exynos_pmu_probe(struct platform_device *pdev) return 0; } +static int exynos_cpupm_suspend_noirq(struct device *dev) +{ + raw_spin_lock(&pmu_context->cpupm_lock); + pmu_context->sys_insuspend = true; + raw_spin_unlock(&pmu_context->cpupm_lock); + return 0; +} + +static int exynos_cpupm_resume_noirq(struct device *dev) +{ + raw_spin_lock(&pmu_context->cpupm_lock); + pmu_context->sys_insuspend = false; + raw_spin_unlock(&pmu_context->cpupm_lock); + return 0; +} + +static const struct dev_pm_ops cpupm_pm_ops = { + NOIRQ_SYSTEM_SLEEP_PM_OPS(exynos_cpupm_suspend_noirq, + exynos_cpupm_resume_noirq) +}; + static struct platform_driver exynos_pmu_driver = { .driver = { .name = "exynos-pmu", .of_match_table = exynos_pmu_of_device_ids, + .pm = pm_sleep_ptr(&cpupm_pm_ops), }, .probe = exynos_pmu_probe, }; diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 2781a091a6a6..446b9fc1f175 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -12,6 +12,7 @@ #include <linux/debugfs.h> #include <linux/io.h> +#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> @@ -310,6 +311,10 @@ static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { .has_ths_offset = true, }; +static const struct sunxi_sramc_variant sun55i_a523_sramc_variant = { + .num_emac_clocks = 2, +}; + #define SUNXI_SRAM_THS_OFFSET_REG 0x0 #define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 #define SUNXI_SYS_LDO_CTRL_REG 0x150 @@ -363,6 +368,7 @@ static int __init sunxi_sram_probe(struct platform_device *pdev) const struct sunxi_sramc_variant *variant; struct device *dev = &pdev->dev; struct regmap *regmap; + int ret; sram_dev = &pdev->dev; @@ -380,6 +386,10 @@ static int __init sunxi_sram_probe(struct platform_device *pdev) regmap = devm_regmap_init_mmio(dev, base, &sunxi_sram_regmap_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); + + ret = of_syscon_register_regmap(dev->of_node, regmap); + if (ret) + return ret; } of_platform_populate(dev->of_node, NULL, NULL, dev); @@ -430,6 +440,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = { .compatible = "allwinner,sun50i-h616-system-control", .data = &sun50i_h616_sramc_variant, }, + { + .compatible = "allwinner,sun55i-a523-system-control", + .data = &sun55i_a523_sramc_variant, + }, { }, }; MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match); diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index 9392c2c43cc8..c0fc54c3cd35 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -96,6 +96,7 @@ config ARCH_TEGRA_210_SOC config ARCH_TEGRA_186_SOC bool "NVIDIA Tegra186 SoC" depends on !CPU_BIG_ENDIAN + select PINCTRL_TEGRA186 select MAILBOX select SOC_TEGRA_PMC help diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index e24ab5f7d2bf..524fa1b0cd3d 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -117,6 +117,124 @@ const struct tegra_fuse_soc tegra30_fuse_soc = { #endif #ifdef CONFIG_ARCH_TEGRA_114_SOC +static const struct nvmem_cell_info tegra114_fuse_cells[] = { + { + .name = "tsensor-cpu1", + .offset = 0x084, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-cpu2", + .offset = 0x088, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-common", + .offset = 0x08c, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-cpu0", + .offset = 0x098, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "xusb-pad-calibration", + .offset = 0x0f0, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-cpu3", + .offset = 0x12c, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-gpu", + .offset = 0x154, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-mem0", + .offset = 0x158, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-mem1", + .offset = 0x15c, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-pllx", + .offset = 0x160, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, +}; + +static const struct nvmem_cell_lookup tegra114_fuse_lookups[] = { + { + .nvmem_name = "fuse", + .cell_name = "xusb-pad-calibration", + .dev_id = "7009f000.padctl", + .con_id = "calibration", + }, { + .nvmem_name = "fuse", + .cell_name = "tsensor-common", + .dev_id = "700e2000.thermal-sensor", + .con_id = "common", + }, { + .nvmem_name = "fuse", + .cell_name = "tsensor-cpu0", + .dev_id = "700e2000.thermal-sensor", + .con_id = "cpu0", + }, { + .nvmem_name = "fuse", + .cell_name = "tsensor-cpu1", + .dev_id = "700e2000.thermal-sensor", + .con_id = "cpu1", + }, { + .nvmem_name = "fuse", + .cell_name = "tsensor-cpu2", + .dev_id = "700e2000.thermal-sensor", + .con_id = "cpu2", + }, { + .nvmem_name = "fuse", + .cell_name = "tsensor-cpu3", + .dev_id = "700e2000.thermal-sensor", + .con_id = "cpu3", + }, { + .nvmem_name = "fuse", + .cell_name = "tsensor-mem0", + .dev_id = "700e2000.thermal-sensor", + .con_id = "mem0", + }, { + .nvmem_name = "fuse", + .cell_name = "tsensor-mem1", + .dev_id = "700e2000.thermal-sensor", + .con_id = "mem1", + }, { + .nvmem_name = "fuse", + .cell_name = "tsensor-gpu", + .dev_id = "700e2000.thermal-sensor", + .con_id = "gpu", + }, { + .nvmem_name = "fuse", + .cell_name = "tsensor-pllx", + .dev_id = "700e2000.thermal-sensor", + .con_id = "pllx", + }, +}; + static const struct tegra_fuse_info tegra114_fuse_info = { .read = tegra30_fuse_read, .size = 0x2a0, @@ -127,6 +245,10 @@ const struct tegra_fuse_soc tegra114_fuse_soc = { .init = tegra30_fuse_init, .speedo_init = tegra114_init_speedo_data, .info = &tegra114_fuse_info, + .lookups = tegra114_fuse_lookups, + .num_lookups = ARRAY_SIZE(tegra114_fuse_lookups), + .cells = tegra114_fuse_cells, + .num_cells = ARRAY_SIZE(tegra114_fuse_cells), .soc_attr_group = &tegra_soc_attr_group, .clk_suspend_on = false, }; diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c index d716be113c84..50c170a995f9 100644 --- a/drivers/soc/ti/k3-socinfo.c +++ b/drivers/soc/ti/k3-socinfo.c @@ -66,6 +66,10 @@ static const char * const j721e_rev_string_map[] = { "1.0", "1.1", "2.0", }; +static const char * const am62lx_rev_string_map[] = { + "1.0", "1.1", +}; + static int k3_chipinfo_partno_to_names(unsigned int partno, struct soc_device_attribute *soc_dev_attr) @@ -92,6 +96,12 @@ k3_chipinfo_variant_to_sr(unsigned int partno, unsigned int variant, soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%s", j721e_rev_string_map[variant]); break; + case JTAG_ID_PARTNO_AM62LX: + if (variant >= ARRAY_SIZE(am62lx_rev_string_map)) + goto err_unknown_variant; + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%s", + am62lx_rev_string_map[variant]); + break; default: variant++; soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%x.0", diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index d7634bf5413a..038576805bfa 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -449,7 +449,7 @@ static int pruss_of_setup_memories(struct device *dev, struct pruss *pruss) pruss->mem_regions[i].pa = res.start; pruss->mem_regions[i].size = resource_size(&res); - dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %pK\n", + dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %p\n", mem_names[i], &pruss->mem_regions[i].pa, pruss->mem_regions[i].size, pruss->mem_regions[i].va); } |