[PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping

Cédric Le Goater clg at kaod.org
Thu Nov 24 06:08:37 AEDT 2016


On 11/23/2016 10:33 AM, Cédric Le Goater wrote:
> On 11/23/2016 02:22 AM, Andrew Jeffery wrote:
>> On Tue, 2016-11-22 at 08:21 +0100, Cédric Le Goater wrote:
>>>>> So we should set or unset these SCU regs when the SoC is created
>>>>> and 
>>>>> derive the wdt2 enablement from them. I suppose that the helper
>>>>> routine 
>>>>> to check for the conditions would be under SCU. 
>>>>>
>>>>> or do we start a simple pinctrl model and slowly add the
>>>>> enablement
>>>>> of the pins we need ? 
>>>>>
>>>>
>>>> From the discussion on IRC last night between Cédric, Joel and
>>>> myself
>>>> we decided to start on a pinmux backend to help manage these
>>>> issues.
>>>
>>> Do you have a rough idea of an API that the SoC could use ? 
>>>
>>> 	enum AspeedAST2500Function {
>>> 		FWSPICS0,
>>> 		FWSPICS1,
>>> 		FWSPICS2,
>>> 	};
>>>
>>> 	enum AspeedAST2400Function {
>>> 		ROMCS1,
>>> 		ROMCS2,
>>> 		ROMCS3,
>>> 		ROMCS4,
>>> 	};
>>>
>>> 	bool aspeed_pin_is_enabled(AspeedPinmux *p, int func);
>>
>> Largely this looks good.
>>
>> But bikeshedding a bit, but I think the function name should focus on
>> functions, not pins. The function maps to some pin in the physical
>> case, but for qemu's purposes we don't care about that just yet. Even
>> if we do care in the future we can internally map functions to pins
>> behind a pinmux abstraction. As such I think we can get away with a
>> small tweak:
>>
>> bool aspeed_pinmux_is_enabled(AspeedPinmux *p, int func);
> 
> ok Looks good to me. I will fake this in the patchset to ease the 
> change in the future.
> 
>> Did you have any thought about how we hoist ourselves from a
>> AspeedPinmux to say an AspeedAST2500Pinmux with this interface? 
> 
> There are different solutions. We could introduce a class like
> 
> #define TYPE_ASPEED_PINMUX "aspeed-pinmux"
> #define ASPEED_PINMUX(obj)
>      OBJECT_CHECK(AspeedPinmux, (obj), TYPE_ASPEED_PINMUX)
> #define ASPEED_PINMUX_CLASS(klass) \
>      OBJECT_CLASS_CHECK(AspeedPinmuxClass, (klass), TYPE_ASPEED_PINMUX)
> #define ASPEED_PINMUX_GET_CLASS(obj) \
>      OBJECT_GET_CLASS(AspeedPinmuxClass, (obj), TYPE_ASPEED_PINMUX)
> 
> typedef struct AspeedPinmux {
> 	...
> } AspeedPinmux;
> 
> typedef struct AspeedPinmuxClass {
> 	...
> 	AspeedPinmuxType pinmux_type;
>         ... 
> 
> or
> 	... 
>         bool (*is_enabled)(AspeedPinmux *pmux, int func);
> 	....
> } AspeedPinmuxClass;
> 
> #define TYPE_ASPEED_PINMUX_POWER8E TYPE_ASPEED_PINMUX "-ast2500"
> #define ASPEED_PINMUX_AST2500(obj) \
>     OBJECT_CHECK(AspeedPinmux, (obj), TYPE_ASPEED_PINMUX_AST2500)
> 
> #define TYPE_ASPEED_PINMUX_POWER8E TYPE_ASPEED_PINMUX "-ast2400"
> #define ASPEED_PINMUX_AST2400(obj) \
>     OBJECT_CHECK(AspeedPinmux, (obj), TYPE_ASPEED_PINMUX_AST2400)
> 
> 
> and use 'pinmux_type' to dispatch to specific handlers or directly
> include the handlers we need under the class. 
> 
> If we only have handlers and no state, we could define a Interface
> and tie it to the soc object.
> 
> typedef struct AspeedPinmuxInterface {
>     Object parent;
> } AspeedPinmuxInterface;
> 
> #define TYPE_ASPEED_PINMUX_INTERFACE "aspeed-pinmux-interface"
> #define ASPEED_PINMUX_INTERFACE(obj) \
>      OBJECT_CHECK(AspeedPinmuxInterface, (obj), TYPE_ASPEED_PINMUX_INTERFACE)
> #define ASPEED_PINMUX_INTERFACE_CLASS(klass)                \
>     OBJECT_CLASS_CHECK(AspeedPinmuxInterfaceClass, (klass), \
>                        TYPE_ASPEED_PINMUX_INTERFACE)
> #define ASPEED_PINMUX_INTERFACE_GET_CLASS(obj) \
>      OBJECT_GET_CLASS(AspeedPinmuxInterfaceClass, (obj), TYPE_ASPEED_PINMUX_INTERFACE)
> 
> typedef struct AspeedPinmuxInterfaceClass {
>     InterfaceClass parent;
>     bool (*is_enabled)(AspeedPinmuxInterface *dev, int func);
>     ...
> } AspeedPinmuxInterfaceClass;
> 
> 
> Conceptually, the SoC object would have a set of routines to handle
> muxing. that seems ok to me as pinmux is a rather invasive component 
> needing access to all controllers to be able to set the functions. 

Here is a quick patch for it to get an overall feeling.

C.


Signed-off-by: Cédric Le Goater <clg at kaod.org>
---
 hw/arm/aspeed.c              |    6 +++
 hw/arm/aspeed_soc.c          |   86 ++++++++++++++++++++++++++++++++++++++++++-
 hw/misc/aspeed_scu.c         |    2 +
 include/hw/arm/aspeed_soc.h  |    2 +
 include/hw/misc/aspeed_scu.h |    1 
 5 files changed, 96 insertions(+), 1 deletion(-)

Index: qemu-aspeed.git/hw/arm/aspeed_soc.c
===================================================================
--- qemu-aspeed.git.orig/hw/arm/aspeed_soc.c
+++ qemu-aspeed.git/hw/arm/aspeed_soc.c
@@ -47,6 +47,9 @@ static const hwaddr aspeed_soc_ast2500_s
 static const char *aspeed_soc_ast2500_typenames[] = {
     "aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
 
+static bool aspeed_soc_ast2400_is_enabled(AspeedSoCState *obj, int func);
+static bool aspeed_soc_ast2500_is_enabled(AspeedSoCState *obj, int func);
+
 static const AspeedSoCInfo aspeed_socs[] = {
     {
         .name         = "ast2400-a0",
@@ -58,6 +61,7 @@ static const AspeedSoCInfo aspeed_socs[]
         .spi_bases    = aspeed_soc_ast2400_spi_bases,
         .fmc_typename = "aspeed.smc.fmc",
         .spi_typename = aspeed_soc_ast2400_typenames,
+        .is_enabled   = aspeed_soc_ast2400_is_enabled,
     }, {
         .name         = "ast2400-a1",
         .cpu_model    = "arm926",
@@ -68,6 +72,7 @@ static const AspeedSoCInfo aspeed_socs[]
         .spi_bases    = aspeed_soc_ast2400_spi_bases,
         .fmc_typename = "aspeed.smc.fmc",
         .spi_typename = aspeed_soc_ast2400_typenames,
+        .is_enabled   = aspeed_soc_ast2400_is_enabled,
     }, {
         .name         = "ast2400",
         .cpu_model    = "arm926",
@@ -78,6 +83,7 @@ static const AspeedSoCInfo aspeed_socs[]
         .spi_bases    = aspeed_soc_ast2400_spi_bases,
         .fmc_typename = "aspeed.smc.fmc",
         .spi_typename = aspeed_soc_ast2400_typenames,
+        .is_enabled   = aspeed_soc_ast2500_is_enabled,
     }, {
         .name         = "ast2500-a1",
         .cpu_model    = "arm1176",
@@ -88,6 +94,7 @@ static const AspeedSoCInfo aspeed_socs[]
         .spi_bases    = aspeed_soc_ast2500_spi_bases,
         .fmc_typename = "aspeed.smc.ast2500-fmc",
         .spi_typename = aspeed_soc_ast2500_typenames,
+        .is_enabled   = aspeed_soc_ast2500_is_enabled,
     },
 };
 
@@ -149,6 +156,8 @@ static void aspeed_soc_init(Object *obj)
                               "hw-strap1", &error_abort);
     object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
                               "hw-strap2", &error_abort);
+    object_property_add_alias(obj, "pinmux-ctrl3", OBJECT(&s->scu),
+                              "pinmux-ctrl3", &error_abort);
 
     object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename);
     object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL);
@@ -170,12 +179,81 @@ static void aspeed_soc_init(Object *obj)
                               "ram-size", &error_abort);
 }
 
+/* AST2400 */
+enum {
+    ROMCS1,
+    ROMCS2,
+    ROMCS3,
+    ROMCS4,
+};
+
+static bool aspeed_soc_ast2400_is_enabled(AspeedSoCState *soc, int function)
+{
+    switch (function) {
+    case ROMCS1:
+        return soc->scu.pinmux_ctrl3 & (1 << 24);
+    case ROMCS2:
+        return soc->scu.pinmux_ctrl3 & (1 << 25);
+    case ROMCS3:
+        return soc->scu.pinmux_ctrl3 & (1 << 26);
+    case ROMCS4:
+        return soc->scu.pinmux_ctrl3 & (1 << 27);
+    default:
+        return false;
+    }
+}
+
+/* AST2500 */
+enum {
+    FWSPICS1,
+    FWSPICS2,
+};
+
+static bool aspeed_soc_ast2500_is_enabled(AspeedSoCState *soc, int function)
+{
+    bool cond2 = !(soc->scu.regs[0x94 >> 2] & 0x3);
+
+    switch (function) {
+    case FWSPICS1:
+        return (soc->scu.pinmux_ctrl3 & (1 << 24)) && cond2;
+    case FWSPICS2:
+        return (soc->scu.pinmux_ctrl3 & (1 << 25)) && cond2;
+    default:
+        return false;
+    }
+}
+
+static int aspeed_fmc_get_cs(AspeedSoCState *soc, Error **errp)
+{
+    AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc);
+    int cs = 1;
+
+    switch (sc->info->silicon_rev) {
+    case AST2400_A0_SILICON_REV:
+    case AST2400_A1_SILICON_REV:
+        cs += sc->info->is_enabled(soc, ROMCS1);
+        cs += sc->info->is_enabled(soc, ROMCS2);
+        cs += sc->info->is_enabled(soc, ROMCS3);
+        cs += sc->info->is_enabled(soc, ROMCS4);
+        break;
+    case AST2500_A0_SILICON_REV:
+    case AST2500_A1_SILICON_REV:
+        cs += sc->info->is_enabled(soc, FWSPICS1);
+        cs += sc->info->is_enabled(soc, FWSPICS2);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    return cs;
+}
+
 static void aspeed_soc_realize(DeviceState *dev, Error **errp)
 {
     int i;
     AspeedSoCState *s = ASPEED_SOC(dev);
     AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
     Error *err = NULL, *local_err = NULL;
+    int fmc_num_cs;
 
     /* IO space */
     memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
@@ -251,7 +329,13 @@ static void aspeed_soc_realize(DeviceSta
                        qdev_get_gpio_in(DEVICE(&s->vic), 12));
 
     /* FMC */
-    object_property_set_int(OBJECT(&s->fmc), 1, "num-cs", &err);
+    fmc_num_cs = aspeed_fmc_get_cs(s, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    object_property_set_int(OBJECT(&s->fmc), fmc_num_cs, "num-cs", &err);
     object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
     error_propagate(&err, local_err);
     if (err) {
Index: qemu-aspeed.git/include/hw/arm/aspeed_soc.h
===================================================================
--- qemu-aspeed.git.orig/include/hw/arm/aspeed_soc.h
+++ qemu-aspeed.git/include/hw/arm/aspeed_soc.h
@@ -52,6 +52,8 @@ typedef struct AspeedSoCInfo {
     const hwaddr *spi_bases;
     const char *fmc_typename;
     const char **spi_typename;
+
+    bool (*is_enabled)(AspeedSoCState *obj, int function);
 } AspeedSoCInfo;
 
 typedef struct AspeedSoCClass {
Index: qemu-aspeed.git/hw/misc/aspeed_scu.c
===================================================================
--- qemu-aspeed.git.orig/hw/misc/aspeed_scu.c
+++ qemu-aspeed.git/hw/misc/aspeed_scu.c
@@ -246,6 +246,7 @@ static void aspeed_scu_reset(DeviceState
     s->regs[SILICON_REV] = s->silicon_rev;
     s->regs[HW_STRAP1] = s->hw_strap1;
     s->regs[HW_STRAP2] = s->hw_strap2;
+    s->regs[PINMUX_CTRL3] = s->pinmux_ctrl3;
 }
 
 static uint32_t aspeed_silicon_revs[] = {
@@ -299,6 +300,7 @@ static Property aspeed_scu_properties[]
     DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
     DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
     DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
+    DEFINE_PROP_UINT32("pinmux-ctrl3", AspeedSCUState, pinmux_ctrl3, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
Index: qemu-aspeed.git/include/hw/misc/aspeed_scu.h
===================================================================
--- qemu-aspeed.git.orig/include/hw/misc/aspeed_scu.h
+++ qemu-aspeed.git/include/hw/misc/aspeed_scu.h
@@ -29,6 +29,7 @@ typedef struct AspeedSCUState {
     uint32_t silicon_rev;
     uint32_t hw_strap1;
     uint32_t hw_strap2;
+    uint32_t pinmux_ctrl3;
 } AspeedSCUState;
 
 #define AST2400_A0_SILICON_REV   0x02000303U
Index: qemu-aspeed.git/hw/arm/aspeed.c
===================================================================
--- qemu-aspeed.git.orig/hw/arm/aspeed.c
+++ qemu-aspeed.git/hw/arm/aspeed.c
@@ -34,6 +34,7 @@ typedef struct AspeedBoardState {
 typedef struct AspeedBoardConfig {
     const char *soc_name;
     uint32_t hw_strap1;
+    uint32_t pinmux_ctrl3;
     const char *fmc_model;
     const char *spi_model;
 } AspeedBoardConfig;
@@ -84,18 +85,21 @@ static const AspeedBoardConfig aspeed_bo
     [PALMETTO_BMC] = {
         .soc_name  = "ast2400-a1",
         .hw_strap1 = PALMETTO_BMC_HW_STRAP1,
+        .pinmux_ctrl3 = 0x00000000U,
         .fmc_model = "n25q256a",
         .spi_model = "mx25l25635e",
     },
     [AST2500_EVB]  = {
         .soc_name  = "ast2500-a1",
         .hw_strap1 = AST2500_EVB_HW_STRAP1,
+        .pinmux_ctrl3 = 0x00000000U,
         .fmc_model = "n25q256a",
         .spi_model = "mx25l25635e",
     },
     [ROMULUS_BMC]  = {
         .soc_name  = "ast2500-a1",
         .hw_strap1 = ROMULUS_BMC_HW_STRAP1,
+        .pinmux_ctrl3 = 0x01000000U,
         .fmc_model = "n25q256a",
         .spi_model = "mx66l1g45g",
     },
@@ -144,6 +148,8 @@ static void aspeed_board_init(MachineSta
                            &error_abort);
     object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
                             &error_abort);
+    object_property_set_int(OBJECT(&bmc->soc), cfg->pinmux_ctrl3,
+                            "pinmux-ctrl3", &error_abort);
     object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
                              &error_abort);
 




More information about the openbmc mailing list