[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 3/4] xen/arm: pl011: Use correct accessors


  • To: <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Michal Orzel <michal.orzel@xxxxxxx>
  • Date: Wed, 7 Jun 2023 11:27:26 +0200
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=lists.xenproject.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=SCI9MwarsbRlj2FJ9hBho2GnuBuTU9RG25ioTaHG3ao=; b=SPHBuI9u3zdrWmfrZBT2sqAh38updItX+sdSX6yQzqlc+ud1RHUn16y3HYrvbY9hc9Pzu8PF4jr6sNRvEC261reWNV7Jomm4Tf2ErbY1AVzOzr4qaGusnHe70MnlF022v4U3RGet7ZCGKHC2EoYg0KKmddfhPTGgQE8MYE9Hmizl0+xRcYqT4vlO/xTAo8EZTvlTWebTG5f0DHkwXJZfRjrS0pU+8jYZ2dU071HfSIrSw9DdehBLlUCA/Drwf9QkIbOie8gbRW0Uea/z7Gx47+h0KbGSqebATug1Ab3HrzMEcFIlYx63CNbUC00pl9i6YFvb9t3HyUsABi+q6oDHfg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=d5NxaWmhfcIBjwqdl2ZCR8gdUbJQ1d0kZbg1HfIYiV1O28f8uXe3NT3detUltOiHAf3dT+osibjO+XIe/ejs+UVjFlIIhRq+9b8C/eWMwh5s8shiNgxzlgzrjAOseaWGrEK+o2jthjMGJ7g+POPh0Fem0VX06ZTXFR27nWmJ2u+mMBxcRZbcy3aI1iEx89RzourLBIqd7NUoykgPUb6nUAXsHqOHhfGTn/G4GcpQ+U4Erp60Hpv6ETOL707DzrWS6c0yEU72ssRJdSWu0gdoiRz/m946twkJW3Q2MwgkmuutuJ8XHf3Mpsy8ysbtj1JkMkyfPRdCGfZUDe2bGL7r/A==
  • Cc: Michal Orzel <michal.orzel@xxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Wed, 07 Jun 2023 09:28:02 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

At the moment, we use 32-bit only accessors (i.e. readl/writel) to match
the SBSA v2.x requirement. This should not be the default case for normal
PL011 where accesses shall be 8/16-bit (max register size is 16-bit).
There are however implementations of this UART that can only handle 32-bit
MMIO. This is advertised by dt property "reg-io-width" set to 4.

Introduce new struct pl011 member mmio32 and replace pl011_{read/write}
macros with static inline helpers that use 32-bit or 16-bit accessors
(largest-common not to end up using different ones depending on the actual
register size) according to mmio32 value. By default this property is set
to false, unless:
 - reg-io-width is specified with value 4,
 - SBSA UART is in use.

For now, no changes done for ACPI due to lack of testing possibilities
(i.e. current behavior maintained resulting in 32-bit accesses).

Signed-off-by: Michal Orzel <michal.orzel@xxxxxxx>
---
 xen/drivers/char/pl011.c | 53 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 6 deletions(-)

diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 052a6512515c..403b1ac06551 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -41,6 +41,7 @@ static struct pl011 {
     /* unsigned int timeout_ms; */
     /* bool_t probing, intr_works; */
     bool sbsa;  /* ARM SBSA generic interface */
+    bool mmio32; /* 32-bit only MMIO */
 } pl011_com = {0};
 
 /* These parity settings can be ORed directly into the LCR. */
@@ -50,9 +51,30 @@ static struct pl011 {
 #define PARITY_MARK  (PEN|SPS)
 #define PARITY_SPACE (PEN|EPS|SPS)
 
-/* SBSA v2.x document requires, all reads/writes must be 32-bit accesses */
-#define pl011_read(uart, off)           readl((uart)->regs + (off))
-#define pl011_write(uart, off,val)      writel((val), (uart)->regs + (off))
+/*
+ * By default, PL011 accesses shall be done using 8/16-bit accessors to
+ * support legacy devices that cannot cope with 32-bit. On the other hand,
+ * there are implementations of PL011 that can only handle 32-bit MMIO. Also,
+ * SBSA v2.x requires 32-bit accesses. Note that for default case, we use
+ * largest-common accessors (i.e. 16-bit) not to end up using different ones
+ * depending on the actual register size.
+ */
+static inline void
+pl011_write(struct pl011 *uart, unsigned int offset, unsigned int val)
+{
+    if ( uart->mmio32 )
+        writel(val, uart->regs + offset);
+    else
+        writew(val, uart->regs + offset);
+}
+
+static inline unsigned int pl011_read(struct pl011 *uart, unsigned int offset)
+{
+    if ( uart->mmio32 )
+        return readl(uart->regs + offset);
+
+    return readw(uart->regs + offset);
+}
 
 static unsigned int pl011_intr_status(struct pl011 *uart)
 {
@@ -222,7 +244,8 @@ static struct uart_driver __read_mostly pl011_driver = {
     .vuart_info   = pl011_vuart,
 };
 
-static int __init pl011_uart_init(int irq, paddr_t addr, paddr_t size, bool 
sbsa)
+static int __init
+pl011_uart_init(int irq, paddr_t addr, paddr_t size, bool sbsa, bool mmio32)
 {
     struct pl011 *uart;
 
@@ -233,6 +256,9 @@ static int __init pl011_uart_init(int irq, paddr_t addr, 
paddr_t size, bool sbsa
     uart->stop_bits = 1;
     uart->sbsa      = sbsa;
 
+    /* Set 32-bit MMIO also for SBSA since v2.x requires it */
+    uart->mmio32 = (mmio32 || sbsa);
+
     uart->regs = ioremap_nocache(addr, size);
     if ( !uart->regs )
     {
@@ -259,6 +285,8 @@ static int __init pl011_dt_uart_init(struct dt_device_node 
*dev,
     const char *config = data;
     int res;
     paddr_t addr, size;
+    uint32_t io_width;
+    bool mmio32 = false;
 
     if ( strcmp(config, "") )
     {
@@ -280,7 +308,19 @@ static int __init pl011_dt_uart_init(struct dt_device_node 
*dev,
         return -EINVAL;
     }
 
-    res = pl011_uart_init(res, addr, size, false);
+    /* See linux Documentation/devicetree/bindings/serial/pl011.yaml */
+    if ( dt_property_read_u32(dev, "reg-io-width", &io_width) )
+    {
+        if ( io_width == 4 )
+            mmio32 = true;
+        else if ( io_width != 1 )
+        {
+            printk("pl011: Unsupported reg-io-width (%"PRIu32")\n", io_width);
+            return -EINVAL;
+        }
+    }
+
+    res = pl011_uart_init(res, addr, size, false, mmio32);
     if ( res < 0 )
     {
         printk("pl011: Unable to initialize\n");
@@ -328,8 +368,9 @@ static int __init pl011_acpi_uart_init(const void *data)
     /* trigger/polarity information is not available in spcr */
     irq_set_type(spcr->interrupt, IRQ_TYPE_LEVEL_HIGH);
 
+    /* TODO - mmio32 proper handling (for now set to true) */
     res = pl011_uart_init(spcr->interrupt, spcr->serial_port.address,
-                          PAGE_SIZE, sbsa);
+                          PAGE_SIZE, sbsa, true);
     if ( res < 0 )
     {
         printk("pl011: Unable to initialize\n");
-- 
2.25.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.