From: "Cédric Le Goater" <clg@kaod.org>
To: Peter Maydell <peter.maydell@linaro.org>,
Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org,
"Andrew Jeffery" <andrew@aj.id.au>,
"Joel Stanley" <joel@jms.id.au>,
"Cédric Le Goater" <clg@kaod.org>
Subject: [Qemu-devel] [PATCH 2/4] ast2400: add SPI flash slave object
Date: Fri, 17 Jun 2016 10:35:53 +0200 [thread overview]
Message-ID: <1466152555-10406-3-git-send-email-clg@kaod.org> (raw)
In-Reply-To: <1466152555-10406-1-git-send-email-clg@kaod.org>
Each SPI flash slave can operate in two modes: Command and User. When
in User mode, accesses to the memory segment of the slaves are
translated in SPI transfers. When in Command mode, the HW generates
the SPI commands automatically and the memory segment is accessed as
if doing a MMIO. Other SPI controllers call that mode linear
addressing mode.
This object is a model proposal for a SPI flash module, gathering SPI
slave properties and a MemoryRegion handling the memory accesses.
Only the User mode is supported for now but we are preparing ground
for the Command mode.
The framework below is sufficient to support Linux which only uses
User Mode.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
Is that the right approach or should we just use simple structs under
AspeedSMCState and attach the memory region to the Aspeed SMC
controller SysBus object ? Please advise.
hw/ssi/aspeed_smc.c | 97 +++++++++++++++++++++++++++++++++++++++++++++
include/hw/ssi/aspeed_smc.h | 16 ++++++++
2 files changed, 113 insertions(+)
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 7937a9030903..6a02906c8f97 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -112,6 +112,21 @@ static bool aspeed_smc_is_ce_stop_active(AspeedSMCState *s, int cs)
return s->regs[s->r_ctrl0 + cs] & CTRL_CE_STOP_ACTIVE;
}
+static inline int aspeed_smc_flash_mode(AspeedSMCState *s, int cs)
+{
+ return s->regs[s->r_ctrl0 + cs] & CTRL_CMD_MODE_MASK;
+}
+
+static inline bool aspeed_smc_is_usermode(AspeedSMCState *s, int cs)
+{
+ return (aspeed_smc_flash_mode(s, cs) == CTRL_USERMODE);
+}
+
+static inline bool aspeed_smc_is_writable(AspeedSMCState *s, int cs)
+{
+ return s->regs[s->r_conf] & (1 << (s->conf_enable_w0 + cs));
+}
+
static void aspeed_smc_update_cs(AspeedSMCState *s)
{
int i;
@@ -298,3 +313,85 @@ static void aspeed_smc_register_types(void)
}
type_init(aspeed_smc_register_types)
+
+static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
+{
+ AspeedSMCFlashState *fl = ASPEED_SMC_FLASH(opaque);
+ AspeedSMCState *s = fl->controller;
+ uint64_t ret = 0;
+ int i;
+
+ if (aspeed_smc_is_usermode(s, fl->id)) {
+ for (i = 0; i < size; i++) {
+ ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
+ }
+ } else {
+ error_report("%s: flash not in usermode", __func__);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ AspeedSMCFlashState *fl = ASPEED_SMC_FLASH(opaque);
+ AspeedSMCState *s = fl->controller;
+ int i;
+
+ if (!aspeed_smc_is_writable(s, fl->id)) {
+ error_report("%s: flash is not writable", __func__);
+ return;
+ }
+
+ if (!aspeed_smc_is_usermode(s, fl->id)) {
+ error_report("%s: flash not in usermode", __func__);
+ return;
+ }
+
+ for (i = 0; i < size; i++) {
+ ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
+ }
+}
+
+static const MemoryRegionOps aspeed_smc_flash_ops = {
+ .read = aspeed_smc_flash_read,
+ .write = aspeed_smc_flash_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ },
+};
+
+static const VMStateDescription vmstate_aspeed_smc_flash = {
+ .name = "aspeed.smc_flash",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(id, AspeedSMCFlashState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void aspeed_smc_flash_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->vmsd = &vmstate_aspeed_smc_flash;
+}
+
+static const TypeInfo aspeed_smc_flash_info = {
+ .name = TYPE_ASPEED_SMC_FLASH,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(AspeedSMCState),
+ .class_init = aspeed_smc_flash_class_init,
+};
+
+static void aspeed_smc_flash_register_types(void)
+{
+ type_register_static(&aspeed_smc_flash_info);
+}
+
+type_init(aspeed_smc_flash_register_types)
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index 2d3e9f6b46d5..abd0005b01c2 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -27,6 +27,22 @@
#include "hw/ssi/ssi.h"
+struct AspeedSMCState;
+
+typedef struct AspeedSMCFlashState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+ uint8_t id;
+ size_t size;
+ struct AspeedSMCState *controller;
+ DeviceState *flash;
+} AspeedSMCFlashState;
+
+#define TYPE_ASPEED_SMC_FLASH "aspeed.smc.flash"
+#define ASPEED_SMC_FLASH(obj) \
+ OBJECT_CHECK(AspeedSMCFlashState, (obj), TYPE_ASPEED_SMC_FLASH)
+
typedef struct AspeedSMCController {
const char *name;
uint8_t r_conf;
--
2.1.4
next prev parent reply other threads:[~2016-06-17 8:50 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-17 8:35 [Qemu-devel] [PATCH 0/4] ast2400: SMC controllers Cédric Le Goater
2016-06-17 8:35 ` [Qemu-devel] [PATCH 1/4] ast2400: add SMC controllers (FMC and SPI) Cédric Le Goater
2016-06-17 8:35 ` Cédric Le Goater [this message]
2016-06-17 8:35 ` [Qemu-devel] [PATCH 3/4] ast2400: create SPI flash slaves Cédric Le Goater
2016-06-17 10:11 ` Paolo Bonzini
2016-06-17 10:27 ` Cédric Le Goater
2016-06-17 8:35 ` [Qemu-devel] [PATCH 4/4] tests: add a m25p80 test Cédric Le Goater
2016-06-17 9:53 ` Paolo Bonzini
2016-06-20 15:43 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1466152555-10406-3-git-send-email-clg@kaod.org \
--to=clg@kaod.org \
--cc=andrew@aj.id.au \
--cc=crosthwaite.peter@gmail.com \
--cc=joel@jms.id.au \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).