All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH linux 0/3] [PATCH v3 0/3] Aspeed spi nor 3
@ 2016-01-22  3:50 OpenBMC Patches
  2016-01-22  3:50 ` [PATCH linux 1/3] mtd/spi-nor: Add SPI memory controllers for ASPEED AST2400 OpenBMC Patches
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: OpenBMC Patches @ 2016-01-22  3:50 UTC (permalink / raw)
  To: openbmc

Changes from aspeed-flash branch
Factor dts updates into a dtsi for the flash partitions

Changes from aspeed-spi-nor proposed commit:


Assign label property value to mtd->name before spi_nor_scan, update binding.
turn off DEBUG
removed conditional controller mutex locking (was plannd to eliminate redundant
	chip level locking on one chip controllers but decided not worthwhile)adjust first comment block
use bool and uchar8 vs 1, 3, and 5 bit fields in aspeed_smc_info
make info struct fields explict vs E macro with position data
just make structs, not a table we follow the info pointer
move structs to just before match table
check match data exists
removed unsed smc_controller_type for instance types, dt binding will choose.
add flash type enum instance to struct chip for later teardown of mixed types
todo set controller type to match device tree value


https://github.com/openbmc/linux/pull/43

Milton D. Miller II (3):
  mtd/spi-nor: Add SPI memory controllers for ASPEED AST2400
  aspeed: update bmc dts with attached flash
  aspeed: update defconfig

 .../devicetree/bindings/mtd/aspeed-smc.txt         |  69 +++
 arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts     |  35 ++
 arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi |  28 ++
 arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts      |  35 ++
 arch/arm/configs/aspeed_defconfig                  |   7 +
 drivers/mtd/spi-nor/Kconfig                        |   9 +
 drivers/mtd/spi-nor/Makefile                       |   1 +
 drivers/mtd/spi-nor/aspeed-smc.c                   | 547 +++++++++++++++++++++
 8 files changed, 731 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/aspeed-smc.txt
 create mode 100644 arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi
 create mode 100644 drivers/mtd/spi-nor/aspeed-smc.c

-- 
2.6.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH linux 1/3] mtd/spi-nor: Add SPI memory controllers for ASPEED AST2400
  2016-01-22  3:50 [PATCH linux 0/3] [PATCH v3 0/3] Aspeed spi nor 3 OpenBMC Patches
@ 2016-01-22  3:50 ` OpenBMC Patches
  2016-01-25 12:28   ` Andrew Jeffery
  2016-01-22  3:50 ` [PATCH linux 2/3] aspeed: update bmc dts with attached flash OpenBMC Patches
  2016-01-22  3:50 ` [PATCH linux 3/3] aspeed: update defconfig OpenBMC Patches
  2 siblings, 1 reply; 7+ messages in thread
From: OpenBMC Patches @ 2016-01-22  3:50 UTC (permalink / raw)
  To: openbmc; +Cc: Milton D. Miller II

From: "Milton D. Miller II" <miltonm@us.ibm.com>

This driver adds mtd support for spi-nor attached to either or
both of the Static Memory Controller (new registers) or the SPI
Memory Controller.

The Static Memory Controller is the boot soruce for the SOC.
The controller supports upto 5 chip selects in any combination of
NAND, NOR, and SPI.  The memory controller registers were updated
in the AST2300 and this fmc binding is for the registers in the
new mode.  This driver currently supports only SPI-NOR attached
memory, but has some consierations to support the others later
(including choice of the Kconfig symbol).

There is also a similar register set to suport the Static Memory
Controller in a legacy address mode.   That mode is not currently
supported because it is expected that the system will run with the
fmc binding supporting multiple chip selects.

The normal aplication of the SPI Memory Controller is designated
for use by the host system either for video bios or system bios
and can be accessed over either an LPC bus and/or a PCIe bus or via
a SPI passthough.  The SOC can also access this chip for firmware
updates when not in passthrough mode.  It is expected the passthru
mode and the alternate chip select will be controlled by a future
pinmux driver.

This driver has only been tested with the ast2400 SOC.

Signed-off-by: Milton Miller <miltonm@us.ibm.com>
---
 .../devicetree/bindings/mtd/aspeed-smc.txt         |  69 +++
 drivers/mtd/spi-nor/Kconfig                        |   9 +
 drivers/mtd/spi-nor/Makefile                       |   1 +
 drivers/mtd/spi-nor/aspeed-smc.c                   | 547 +++++++++++++++++++++
 4 files changed, 626 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/aspeed-smc.txt
 create mode 100644 drivers/mtd/spi-nor/aspeed-smc.c

diff --git a/Documentation/devicetree/bindings/mtd/aspeed-smc.txt b/Documentation/devicetree/bindings/mtd/aspeed-smc.txt
new file mode 100644
index 0000000..01e25de
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/aspeed-smc.txt
@@ -0,0 +1,69 @@
+* Aspeed Static Memory controller in SPI mode
+* Aspeed SPI Flash Controller
+
+Required properties:
+  - compatible : Should be "aspeed,fmc" for Static Memory Controller (AST2400, AST2300?), or
+		 "aspeed,smc" for the SPI flash controller
+  - reg : the first contains the register location and length,
+          the second through nth contains the memory mapping address and length
+	  for the access window for each chips select
+  - interrupts : Should contain the interrupt for the dma device if fmc
+  - clocks : The APB clock input to the controller
+  - #address-cells : must be 1 corresponding to chip select child binding
+  - #size-cells : must be 0 corresponding to chip select child binding
+
+
+Child node required properties:
+  - reg : must contain chip select number in first cell of address, must
+	  be 1 tuple long
+  - compatible : may contain "vendor,part", must include "jedec,spi-nor"
+		(see spi-nor.txt binding).
+
+Child node optional properties:
+  - label           - (optional) name to assign to mtd, default os assigned
+  - spi-max-frequency - (optional) max frequency of spi bus (XXX max if missing)
+  - spi-cpol        - (optional) Empty property indicating device requires
+    	 		inverse clock polarity (CPOL) mode (boolean)
+  - spi-cpha        - (optional) Empty property indicating device requires
+    			shifted clock phase (CPHA) mode (boolean)
+  - spi-tx-bus-width - (optional) The bus width(number of data wires) that
+                        used for MOSI. Defaults to 1 if not present.
+  - spi-rx-bus-width - (optional) The bus width(number of data wires) that
+                        used for MOSI. Defaults to 1 if not present.
+
+Child node optional properties:
+ - see mtd/partiton.txt for partitioning bindings and mtd naming
+
+
+Example:
+
+fmc: fmc@1e620000 {
+	compatible = "aspeed,fmc";
+	reg = < 0x1e620000 0x94
+		0x20000000 0x02000000
+		0x22000000 0x02000000 >;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	bmc@0 {
+		reg = < 0 >;
+		compatible = "jedec,spi-nor" ;
+		label = "bmc0";
+		/* spi-max-frequency = <>; */
+		/* m25p,fast-read; */
+		#address-cells = <1>;
+		#size-cells = <1>;
+			bootloader {
+				label = "boot";
+				reg = < 0 0x8000 >
+			}
+	};
+	alt@1 {
+		reg = < 1 >;
+		compatible = "jedec,spi-nor" ;
+		label = "bmc1";
+		/* spi-max-frequency = <>; */
+		status = "fail";
+		/* m25p,fast-read; */
+	};
+};
+
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 89bf4c1..c7554d8 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -40,4 +40,13 @@ config SPI_NXP_SPIFI
 	  Flash. Enable this option if you have a device with a SPIFI
 	  controller and want to access the Flash as a mtd device.
 
+config ASPEED_FLASH_SPI
+	tristate "Aspeed flash controllers in SPI mode"
+	depends on HAS_IOMEM && OF
+	depends on ARCH_ASPEED || COMPILE_TEST
+	help
+	  This enables support for the New Static Memory Controller (FMC)
+	  in the AST2400 when attached to SPI nor chips, and support for
+	  the SPI Memory controller (SPI) for the BIOS.
+
 endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index e53333e..ec28610 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
 obj-$(CONFIG_SPI_FSL_QUADSPI)	+= fsl-quadspi.o
+obj-$(CONFIG_ASPEED_FLASH_SPI)	+= aspeed-smc.o
 obj-$(CONFIG_SPI_NXP_SPIFI)	+= nxp-spifi.o
diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
new file mode 100644
index 0000000..6909de7
--- /dev/null
+++ b/drivers/mtd/spi-nor/aspeed-smc.c
@@ -0,0 +1,547 @@
+/*
+ * ASPEED Static Memory Controller driver
+ * Copyright 2016 IBM Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/sysfs.h>
+
+enum smc_flash_type {
+	smc_type_nor = 0,	/* controller connected to nor flash */
+	smc_type_nand = 1,	/* controller connected to nand flash */
+	smc_type_spi = 2,	/* controller connected to spi flash */
+};
+
+struct aspeed_smc_info {
+	u8 nce;			/* number of chip enables */
+	u8 maxwidth;		/* max width of spi bus */
+	bool hasdma;		/* has dma engine */
+	bool hastype;		/* type shift for ce 0 in cfg reg */
+	u8 we0;			/* we shift for ce 0 in cfg reg */
+	u8 ctl0;		/* offset in regs of ctl for ce 0 */
+	u8 cfg;			/* offset in regs of cfg */
+	u8 time;		/* offset in regs of timing */
+	u8 misc;		/* offset in regs of misc settings */
+};
+
+static struct aspeed_smc_info fmc_info = {
+	.nce = 5,
+	.maxwidth = 4,
+	.hasdma = true,
+	.hastype = true,
+	.we0 = 16,
+	.ctl0 = 0x10,
+	.cfg = 0x00,
+	.time = 0x54,
+	.misc = 0x50,
+};
+
+static struct aspeed_smc_info smc_info = {
+	.nce = 1,
+	.maxwidth = 2,
+	.hasdma = false,
+	.hastype = false,
+	.we0 = 0,
+	.ctl0 = 0x04,
+	.cfg = 0x00,
+	.time = 0x14,
+	.misc = 0x10,
+};
+
+enum smc_ctl_reg_value {
+	smc_base,		/* base value without mode for other commands */
+	smc_read,		/* command reg for (maybe fast) reads */
+	smc_write,		/* command reg for writes with timings */
+	smc_num_ctl_reg_values	/* last value to get count of commands */
+};
+
+struct aspeed_smc_controller;
+
+struct aspeed_smc_chip {
+	struct aspeed_smc_controller *controller;
+	__le32 __iomem *ctl;			/* control register */
+	void __iomem *base;			/* base of chip window */
+	struct mtd_info mtd;
+	__le32 ctl_val[smc_num_ctl_reg_values];	/* controls with timing */
+	enum smc_flash_type type;		/* what type of flash */
+	struct spi_nor nor;
+};
+
+struct aspeed_smc_controller {
+	struct mutex mutex;			/* controller access mutex */
+	const struct aspeed_smc_info *info;	/* type info of controller */
+	void __iomem *regs;			/* controller registers */
+	struct aspeed_smc_chip *chips[0];	/* attached chips */
+};
+
+#define CONTROL_SPI_AAF_MODE BIT(31)
+#define CONTROL_SPI_IO_MODE_MASK GENMAASK(30, 28)
+#define CONTROL_SPI_IO_DUAL_DATA BIT(29)
+#define CONTROL_SPI_IO_DUAL_ADDR_DATA (BIT(29) | BIT(28))
+#define CONTROL_SPI_IO_QUAD_DATA BIT(30)
+#define CONTROL_SPI_IO_QUAD_ADDR_DATA (BIT(30) | BIT(28))
+#define CONTROL_SPI_CE_INACTIVE_SHIFT 24
+#define CONTROL_SPI_CE_INACTIVE_MASK GENMASK(27, CONTROL_SPI_CE_INACTIVE_SHIFT)
+/* 0 = 16T ... 15 = 1T   T=HCLK */
+#define CONTROL_SPI_COMMAND_SHIFT 16
+#define CONTROL_SPI_DUMMY_CYCLE_COMMAND_OUTPUT BIT(15)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_HI BIT(14)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT (14 - 2)
+#define CONTROL_SPI_IO_ADDRESS_4B BIT(13) /* FMC, LEGACY */
+#define CONTROL_SPI_CLK_DIV4 BIT(13) /* BIOS */
+#define CONTROL_SPI_RW_MERGE BIT(12)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT 6
+#define CONTROL_SPI_IO_DUMMY_CYCLES_LO GENMASK(7, CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_MASK (CONTROL_SPI_IO_DUMMY_CYCLES_HI | \
+					  CONTROL_SPI_IO_DUMMY_CYCLES_LO)
+#define CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT 8
+#define CONTROL_SPI_CLOCK_FREQ_SEL_MASK GENMASK(11, CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT)
+#define CONTROL_SPI_LSB_FIRST BIT(5)
+#define CONTROL_SPI_CLOCK_MODE_3 BIT(4)
+#define CONTROL_SPI_IN_DUAL_DATA BIT(3)
+#define CONTROL_SPI_CE_STOP_ACTIVE_CONTROL BIT(2)
+#define CONTROL_SPI_COMMAND_MODE_MASK GENMASK(1, 0)
+#define CONTROL_SPI_COMMAND_MODE_NORMAL (0)
+#define CONTROL_SPI_COMMAND_MODE_FREAD (1)
+#define CONTROL_SPI_COMMAND_MODE_WRITE (2)
+#define CONTROL_SPI_COMMAND_MODE_USER (3)
+
+#define CONTROL_SPI_KEEP_MASK (CONTROL_SPI_AAF_MODE | \
+	CONTROL_SPI_CE_INACTIVE_MASK | CONTROL_SPI_IO_ADDRESS_4B | \
+	CONTROL_SPI_IO_DUMMY_CYCLES_MASK | CONTROL_SPI_CLOCK_FREQ_SEL_MASK | \
+	CONTROL_SPI_LSB_FIRST | CONTROL_SPI_CLOCK_MODE_3)
+
+#define CONTROL_SPI_CLK_DIV4 BIT(13) /* BIOS */
+
+static u32 spi_control_fill_opcode(u8 opcode)
+{
+	return ((u32)(opcode)) << CONTROL_SPI_COMMAND_SHIFT;
+}
+
+#if 0 /* ATTR */
+static u32 spi_control_to_freq_div(u32 control)
+{
+	u32 sel;
+
+	sel = control & CONTROL_SPI_CLOCK_FREQ_SEL_MASK;
+	sel >>= CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT;
+
+	/* 16, 14, 12, 10, 8, 6, 4, 2, 15, 13, 11, 9, 7, 5, 3, 1 */
+	return 16 - (((sel & 7) << 1) + ((sel & 8) >> 1));
+}
+
+static u32 spi_control_to_dummy_bytes(u32 control)
+{
+
+	return ((control & CONTROL_SPI_IO_DUMMY_CYCLES_LO) >>
+			CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT) |
+		((control & CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT) >>
+			CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT);
+}
+
+static size_t show_ctl_div(u32 control, char *buf)
+{
+	return sprintf(buf, "%u\n", spi_control_to_freq_div(control));
+}
+
+static size_t show_ctl_dummy_bytes(u32 control, char *buf)
+{
+	return sprintf(buf, "%u\n", spi_control_to_dummy_bytes(control));
+}
+#endif /* ATTR */
+
+static void aspeed_smc_start_user(struct spi_nor *nor)
+{
+	struct aspeed_smc_chip *chip = nor->priv;
+	u32 ctl = chip->ctl_val[smc_base];
+
+	mutex_lock(&chip->controller->mutex);
+
+	ctl |= CONTROL_SPI_COMMAND_MODE_USER |
+		CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
+	writel(ctl, chip->ctl);
+
+	ctl &= ~CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
+	writel(ctl, chip->ctl);
+}
+
+static void aspeed_smc_stop_user(struct spi_nor *nor)
+{
+	struct aspeed_smc_chip *chip = nor->priv;
+
+	u32 ctl = chip->ctl_val[smc_read];
+	u32 ctl2 = ctl | CONTROL_SPI_COMMAND_MODE_USER |
+		CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
+
+	writel(ctl2, chip->ctl);	/* stop user CE control */
+	writel(ctl, chip->ctl);		/* default to fread or read */
+
+	mutex_unlock(&chip->controller->mutex);
+}
+
+#if 0 /* memcpy */
+static void aspeed_smc_start_write(struct spi_nor *nor)
+{
+	struct aspeed_smc_chip *chip = nor->priv;
+	u32 ctl = chip->ctl_val[smc_write];
+
+	mutex_lock(&chip->controller->mutex);
+
+	writel(ctl | CONTROL_SPI_CE_STOP_ACTIVE_CONTROL,  chip->ctl);
+
+	writel(ctl, chip->ctl);
+}
+
+static void aspeed_smc_stop_write(struct spi_nor *nor)
+{
+	aspeed_smc_stop_user(nor);
+}
+#endif
+
+static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
+{
+	struct aspeed_smc_chip *chip = nor->priv;
+
+	aspeed_smc_start_user(nor);
+	writeb(opcode, chip->base);
+	_memcpy_fromio(buf, chip->base, len);
+	aspeed_smc_stop_user(nor);
+
+	return 0;
+}
+
+static int aspeed_smc_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
+				int len, int write_enable)
+{
+	struct aspeed_smc_chip *chip = nor->priv;
+
+	aspeed_smc_start_user(nor);
+	writeb(opcode, chip->base);
+	_memcpy_toio(chip->base, buf, len);
+	aspeed_smc_stop_user(nor);
+
+	return 0;
+}
+
+static void aspeed_smc_send_cmd_addr(struct spi_nor *nor, u8 cmd, u32 addr)
+{
+	struct aspeed_smc_chip *chip = nor->priv;
+	__be32 temp;
+	u32 cmdaddr;
+
+	switch (nor->addr_width) {
+	default:
+		WARN_ONCE(1, "Unexpected address width %u, defaulting to 3\n",
+			  nor->addr_width);
+		/* FALLTHROUGH */
+	case 3:
+		cmdaddr = addr & 0xFFFFFF;
+
+		cmdaddr |= (u32)cmd << 24;
+
+		temp = cpu_to_be32(cmdaddr);
+		memcpy_toio(chip->base, &temp, 4);
+		break;
+	case 4:
+		temp = cpu_to_be32(addr);
+		writeb(cmd, chip->base);
+		memcpy_toio(chip->base, &temp, 4);
+		break;
+	}
+}
+
+#if 0 /* memcpy */
+static int aspeed_smc_read_memcpy(struct spi_nor *nor, loff_t from, size_t len,
+				  size_t *retlen, u_char *read_buf)
+{
+	struct aspeed_smc_chip *chip = nor->priv;
+
+	mutex_lock(&chip->controller->mutex);
+
+	memcpy_fromio(read_buf, chip->base, len);
+	*retlen += len;
+
+	mutex_unlock(&chip->controller->mutex);
+
+	return 0;
+}
+
+static void aspeed_smc_write_memcpy(struct spi_nor *nor, loff_t to, size_t len,
+				    size_t *retlen, const u_char *write_buf)
+{
+	struct aspeed_smc_chip *chip = nor->priv;
+
+	aspeed_smc_start_write(nor);
+	memcpy_toio(chip->base, write_buf, len);
+	*retlen += len;
+	aspeed_smc_stop_write(nor);
+}
+#endif
+
+static int aspeed_smc_read_user(struct spi_nor *nor, loff_t from, size_t len,
+				size_t *retlen, u_char *read_buf)
+{
+	struct aspeed_smc_chip *chip = nor->priv;
+
+	aspeed_smc_start_user(nor);
+	aspeed_smc_send_cmd_addr(nor, nor->read_opcode, from);
+	memcpy_fromio(read_buf, chip->base, len);
+	*retlen += len;
+	aspeed_smc_stop_user(nor);
+
+	return 0;
+}
+
+static void aspeed_smc_write_user(struct spi_nor *nor, loff_t to, size_t len,
+				  size_t *retlen, const u_char *write_buf)
+{
+	struct aspeed_smc_chip *chip = nor->priv;
+
+	aspeed_smc_start_user(nor);
+	aspeed_smc_send_cmd_addr(nor, nor->program_opcode, to);
+	memcpy_toio(chip->base, write_buf, len);
+	*retlen += len;
+	aspeed_smc_stop_user(nor);
+}
+
+static int aspeed_smc_erase(struct spi_nor *nor, loff_t offs)
+{
+	aspeed_smc_start_user(nor);
+	aspeed_smc_send_cmd_addr(nor, nor->erase_opcode, offs);
+	aspeed_smc_stop_user(nor);
+
+	return 0;
+}
+
+static int aspeed_smc_remove(struct platform_device *dev)
+{
+	struct aspeed_smc_chip *chip;
+	struct aspeed_smc_controller *controller = platform_get_drvdata(dev);
+	int n;
+
+	for (n = 0; n < controller->info->nce; n++) {
+		chip = controller->chips[n];
+		if (chip)
+			mtd_device_unregister(&chip->mtd);
+	}
+
+	return 0;
+}
+
+const struct of_device_id aspeed_smc_matches[] = {
+	{ .compatible = "aspeed,fmc", .data = &fmc_info },
+	{ .compatible = "aspeed,smc", .data = &smc_info },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, aspeed_smc_matches);
+
+static struct platform_device *
+of_platform_device_create_or_find(struct device_node *child,
+				  struct device *parent)
+{
+	struct platform_device *cdev;
+
+	cdev = of_platform_device_create(child, NULL, parent);
+	if (!cdev)
+		cdev = of_find_device_by_node(child);
+	return cdev;
+}
+
+static int aspeed_smc_probe(struct platform_device *dev)
+{
+	struct aspeed_smc_controller *controller;
+	const struct of_device_id *match;
+	const struct aspeed_smc_info *info;
+	struct resource *r;
+	void __iomem *regs;
+	struct device_node *child;
+	int err = 0;
+	unsigned int n;
+
+	match = of_match_device(aspeed_smc_matches, &dev->dev);
+	if (!match || !match->data)
+		return -ENODEV;
+	info = match->data;
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(&dev->dev, r);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	controller = devm_kzalloc(&dev->dev, sizeof(*controller) +
+		info->nce * sizeof(controller->chips[0]), GFP_KERNEL);
+	if (!controller)
+		return -ENOMEM;
+	platform_set_drvdata(dev, controller);
+	controller->regs = regs;
+	controller->info = info;
+	mutex_init(&controller->mutex);
+
+	/* XXX turn off legacy mode if fmc ? */
+	/* XXX handshake to enable access to SMC (bios) controller w/ host? */
+
+	for_each_available_child_of_node(dev->dev.of_node, child) {
+		struct mtd_part_parser_data ppdata;
+		struct platform_device *cdev;
+		struct aspeed_smc_chip *chip;
+		u32 reg;
+
+		if (!of_device_is_compatible(child, "jedec,spi-nor"))
+			continue;	/* XXX consider nand, nor children */
+
+
+		/*
+		 * create a platform device from the of node.
+		 * if the device already was created (eg from
+		 * a prior bind/unbind cycle) use it
+		 *
+		 * XXX The child name will become the default mtd
+		 * name in ioctl and /proc/mtd.  Should we default
+		 * to node->name (without unit)?  The name must be
+		 * unique among all platform devices.  (Name would
+		 * replace NULL in create call below).
+		 * ... Or we can just encourage the label attribute.
+		 *
+		 * The only reason to do the child here is to use it in
+		 * dev_err below for duplicate chip id.  We could use
+		 * the controller dev.
+		 */
+		cdev = of_platform_device_create_or_find(child, &dev->dev);
+		if (!cdev)
+			continue;
+
+		err = of_property_read_u32(child, "reg", &n);
+		if (err == -EINVAL && info->nce == 1)
+			n = 0;
+		else if (err || n >= info->nce)
+			continue;
+		if (controller->chips[n]) {
+			dev_err(&cdev->dev,
+				"chip-id %u already in use in use by %s\n",
+				n, dev_name(controller->chips[n]->nor.dev));
+			continue;
+		}
+		chip = devm_kzalloc(&dev->dev, sizeof(*chip), GFP_KERNEL);
+		if (!chip)
+			continue;
+
+		r = platform_get_resource(dev, IORESOURCE_MEM, n + 1);
+		chip->base = devm_ioremap_resource(&dev->dev, r);
+
+		if (!chip->base)
+			continue;
+		chip->controller = controller;
+		chip->ctl = controller->regs + info->ctl0 + n * 4;
+
+		/* dt said its spi.  Shoud set in controller if has_type */
+		chip->type = smc_type_spi;
+
+		/*
+		 * Always turn on write enable bit in config register to
+		 * allow opcodes to be sent in user mode.
+		 */
+		mutex_lock(&controller->mutex);
+		reg = readl(controller->regs + info->cfg);
+		dev_dbg(&dev->dev, "flash config was %08x\n", reg);
+		reg |= 1 << (info->we0 + n); /* WEn */
+		writel(reg, controller->regs + info->cfg);
+		mutex_unlock(&controller->mutex);
+
+		/* XXX check resource within fmc CEx Segment Address Register */
+		/* XXX -- see dt vs jedec id vs bootloader */
+		/* XXX check / program clock phase/polarity,  only 0 or 3 */
+
+		/*
+		 * Read the existing control register to get basic values.
+		 *
+		 * XXX probably need more sanitation.
+		 * XXX do we trust the bootloader or the device tree?
+		 * spi-nor.c trusts jtag id over passed ids.
+		 */
+		reg = readl(chip->ctl);
+		chip->ctl_val[smc_base] = reg & CONTROL_SPI_KEEP_MASK;
+
+		if ((reg & CONTROL_SPI_COMMAND_MODE_MASK) ==
+		    CONTROL_SPI_COMMAND_MODE_NORMAL)
+			chip->ctl_val[smc_read] = reg;
+#if 0 /* should we inherit fast read (fread) from boot ?  or id tables?*/
+		else if ((reg & CONTROL_SPI_COMMAND_MODE_MASK) ==
+			 CONTROL_SPI_COMMAND_MODE_FREAD)
+			chip->ctl_val[smc_read] = reg;
+#endif
+		else
+			chip->ctl_val[smc_read] = chip->ctl_val[smc_base] |
+				CONTROL_SPI_COMMAND_MODE_NORMAL;
+
+		chip->nor.dev = &cdev->dev;
+		chip->nor.priv = chip;
+		chip->nor.mtd = &chip->mtd;
+		chip->mtd.priv = &chip->nor; /* should be in spi_nor_scan()!! */
+		chip->mtd.name = of_get_property(child, "label", NULL);
+		chip->nor.erase = aspeed_smc_erase;
+		chip->nor.read = aspeed_smc_read_user;
+		chip->nor.write = aspeed_smc_write_user;
+		chip->nor.read_reg = aspeed_smc_read_reg;
+		chip->nor.write_reg = aspeed_smc_write_reg;
+
+		/*
+		 * XXX use of property and controller info width to choose
+		 * SPI_NOR_QUAD , SPI_NOR_DUAL
+		 */
+		err = spi_nor_scan(&chip->nor, NULL, SPI_NOR_NORMAL);
+		if (err)
+			continue;
+
+		chip->ctl_val[smc_write] = chip->ctl_val[smc_base] |
+			spi_control_fill_opcode(chip->nor.program_opcode) |
+			CONTROL_SPI_COMMAND_MODE_WRITE;
+
+		/* XXX intrepret nor flags into controller settings */
+		/* XXX enable fast read here */
+		/* XXX check if resource size big enough for chip */
+
+		memset(&ppdata, 0, sizeof(ppdata));
+		ppdata.of_node = cdev->dev.of_node;
+		err = mtd_device_parse_register(&chip->mtd, NULL, &ppdata, NULL, 0);
+		if (err)
+			continue;
+		controller->chips[n] = chip;
+	}
+
+	/* did we register any children? */
+	for (n = 0; n < info->nce; n++)
+		if (controller->chips[n])
+			break;
+
+	if (n == info->nce)
+		return -ENODEV;
+
+	return 0;
+}
+
+static struct platform_driver aspeed_smc_driver = {
+	.probe = aspeed_smc_probe,
+	.remove = aspeed_smc_remove,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.of_match_table = aspeed_smc_matches,
+	}
+};
+
+module_platform_driver(aspeed_smc_driver);
+
+MODULE_DESCRIPTION("ASPEED Static Memory Controller Driver");
+MODULE_AUTHOR("Milton Miller");
+MODULE_LICENSE("GPL v2");
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH linux 2/3] aspeed: update bmc dts with attached flash
  2016-01-22  3:50 [PATCH linux 0/3] [PATCH v3 0/3] Aspeed spi nor 3 OpenBMC Patches
  2016-01-22  3:50 ` [PATCH linux 1/3] mtd/spi-nor: Add SPI memory controllers for ASPEED AST2400 OpenBMC Patches
@ 2016-01-22  3:50 ` OpenBMC Patches
  2016-01-25 13:18   ` Andrew Jeffery
  2016-01-22  3:50 ` [PATCH linux 3/3] aspeed: update defconfig OpenBMC Patches
  2 siblings, 1 reply; 7+ messages in thread
From: OpenBMC Patches @ 2016-01-22  3:50 UTC (permalink / raw)
  To: openbmc; +Cc: Milton D. Miller II

From: "Milton D. Miller II" <miltonm@us.ibm.com>

Add the attached spi flash chips attached to the static memory controller
and the SPI memory controller.  The partitions and label for the SMC
attached flash are included in a seperate file for import from other
build systems.

Signed-off-by: Milton Miller <miltonm@us.ibm.com>
---
 arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts     | 35 ++++++++++++++++++++++
 arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi | 28 +++++++++++++++++
 arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts      | 35 ++++++++++++++++++++++
 3 files changed, 98 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi

diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts b/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts
index ebf86bb..cba561a 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts
@@ -7,6 +7,41 @@
 	model = "Barrelye BMC";
 	compatible = "rackspace,barreleye-bmc", "aspeed,ast2400";
 	ahb {
+		fmc@1e620000 {
+			reg = < 0x1e620000 0x94
+				0x20000000 0x02000000 >;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "aspeed,fmc";
+			flash@0 {
+				reg = < 0 >;
+				compatible = "jedec,spi-nor" ;
+				/*
+				 * Possibly required props:
+				 * spi-max-frequency = <>
+				 * spi-tx-bus-width = <>
+				 * spi-rx-bus-width  = <>
+				 * m25p,fast-read
+				 * spi-cpol if inverse clock polarity (CPOL)
+				 * spi-cpha if shifted clock phase (CPHA)
+				 */
+#include "aspeed-bmc-opp-flash-layout.dtsi"
+			};
+		};
+		spi@1e630000 {
+			reg = < 0x1e630000 0x18
+				0x30000000 0x02000000 >;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "aspeed,smc";
+			flash {
+				reg = < 0 >;
+				compatible = "jedec,spi-nor" ;
+				label = "pnor";
+				/* spi-max-frequency = <>; */
+				/* m25p,fast-read; */
+			};
+		};
 		apb {
 			i2c: i2c@1e78a040 {
 				i2c0: i2c-bus@40 {
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi b/arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi
new file mode 100644
index 0000000..ca8639b
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi
@@ -0,0 +1,28 @@
+/* This file is the label for the bmc primary flash and its partitions */
+				label = "bmc";
+				#address-cells = < 1 >;
+				#size-cells = < 1 >;
+				u-boot {
+					reg = < 0 0x60000 >;
+					label = "u-boot";
+				};
+				u-boot-env {
+					reg = < 0x60000 0x20000 >;
+					label = "u-boot-env";
+				};
+				kernel  {
+					reg = < 0x80000 0x280000 >;
+					label = "kernel";
+				};
+				initramfs {
+					reg = < 0x300000 0x1c0000 >;
+					label = "initramfs";
+				};
+				rofs  {
+					reg = < 0x4c0000 0x1740000 >;
+					label = "rofs";
+				};
+				rwfs  {
+					reg = < 0x1c00000 0x400000 >;
+					label = "rwfs";
+				};
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts b/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
index 92a7c77..9aacae7 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
@@ -8,6 +8,41 @@
 	compatible = "tyan,palmetto-bmc", "aspeed,ast2400";
 
 	ahb {
+		fmc@1e620000 {
+			reg = < 0x1e620000 0x94
+				0x20000000 0x02000000 >;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "aspeed,fmc";
+			flash@0 {
+				reg = < 0 >;
+				compatible = "jedec,spi-nor" ;
+				/*
+				 * Possibly required props:
+				 * spi-max-frequency = <>
+				 * spi-tx-bus-width = <>
+				 * spi-rx-bus-width  = <>
+				 * m25p,fast-read
+				 * spi-cpol if inverse clock polarity (CPOL)
+				 * spi-cpha if shifted clock phase (CPHA)
+				 */
+#include "aspeed-bmc-opp-flash-layout.dtsi"
+			};
+		};
+		spi@1e630000 {
+			reg = < 0x1e630000 0x18
+				0x30000000 0x02000000 >;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "aspeed,smc";
+			flash {
+				reg = < 0 >;
+				compatible = "jedec,spi-nor" ;
+				label = "pnor";
+				/* spi-max-frequency = <>; */
+				/* m25p,fast-read; */
+			};
+		};
 		apb {
 			i2c: i2c@1e78a040 {
 				i2c0: i2c-bus@40 {
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH linux 3/3] aspeed: update defconfig
  2016-01-22  3:50 [PATCH linux 0/3] [PATCH v3 0/3] Aspeed spi nor 3 OpenBMC Patches
  2016-01-22  3:50 ` [PATCH linux 1/3] mtd/spi-nor: Add SPI memory controllers for ASPEED AST2400 OpenBMC Patches
  2016-01-22  3:50 ` [PATCH linux 2/3] aspeed: update bmc dts with attached flash OpenBMC Patches
@ 2016-01-22  3:50 ` OpenBMC Patches
  2016-01-25 13:19   ` Andrew Jeffery
  2 siblings, 1 reply; 7+ messages in thread
From: OpenBMC Patches @ 2016-01-22  3:50 UTC (permalink / raw)
  To: openbmc; +Cc: Milton D. Miller II

From: "Milton D. Miller II" <miltonm@us.ibm.com>

Turn on the new spi memory controller driver, plus some file systems
that will be used on the new mtd.

Signed-off-by: Milton Miller <miltonm@us.ibm.com>
---
 arch/arm/configs/aspeed_defconfig | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/configs/aspeed_defconfig b/arch/arm/configs/aspeed_defconfig
index a83da91..9727eba 100644
--- a/arch/arm/configs/aspeed_defconfig
+++ b/arch/arm/configs/aspeed_defconfig
@@ -57,6 +57,8 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_PARTITIONED_MASTER=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_NAND=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_ASPEED_FLASH_SPI=y
 CONFIG_MTD_UBI=y
 CONFIG_MTD_UBI_GLUEBI=y
 CONFIG_BLK_DEV_LOOP=y
@@ -170,11 +172,16 @@ CONFIG_PWM=y
 CONFIG_FIRMWARE_MEMMAP=y
 CONFIG_EXT4_FS=y
 CONFIG_FANOTIFY=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_OVERLAY_FS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
 CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_XATTR=y
 CONFIG_JFFS2_SUMMARY=y
 CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
 CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH linux 1/3] mtd/spi-nor: Add SPI memory controllers for ASPEED AST2400
  2016-01-22  3:50 ` [PATCH linux 1/3] mtd/spi-nor: Add SPI memory controllers for ASPEED AST2400 OpenBMC Patches
@ 2016-01-25 12:28   ` Andrew Jeffery
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Jeffery @ 2016-01-25 12:28 UTC (permalink / raw)
  To: OpenBMC Patches, openbmc

Hi Milton,

scripts/checkpatch.pl has a few things to say and I've included the
output in the relevant spots. Probably worth cleaning them up. One of
the more general ones was WRT MAINTAINERS:

    WARNING: added, moved or deleted file(s), does MAINTAINERS need
    updating?

Doesn't seem as if anyone is listed for any bindings doco under mtd/,
but maybe it wouldn't hurt to start? Maintainer also required for
aspeed-smc.c.

Overall the comments address minor issues, nothing really
architectural.

Andrew

On Thu, 2016-01-21 at 21:50 -0600, OpenBMC Patches wrote:
> From: "Milton D. Miller II" <miltonm@us.ibm.com>
> 
> This driver adds mtd support for spi-nor attached to either or
> both of the Static Memory Controller (new registers) or the SPI
> Memory Controller.
> 
> The Static Memory Controller is the boot soruce

WARNING: 'suport' may be misspelled - perhaps 'support'?

>  for the SOC.
> The controller supports upto

'up to'?

>  5 chip selects in any combination of
> NAND, NOR, and SPI.  The memory controller registers were updated
> in the AST2300 and this fmc binding is for the registers in the
> new mode.  This driver currently supports only SPI-NOR attached
> memory, but has some consierations

considerations?

>  to support the others later
> (including choice of the Kconfig symbol).
> 
> There is also a similar register set to suport the Static Memory
> Controller in a legacy address mode.   That mode is not currently
> supported because it is expected that the system will run with the
> fmc binding supporting multiple chip selects.
> 
> The normal aplication

WARNING: 'aplication' may be misspelled - perhaps 'application'?

>  of the SPI Memory Controller is designated
> for use by the host system either for video bios or system bios
> and can be accessed over either an LPC bus and/or a PCIe bus or via
> a SPI passthough.  The SOC can also access this chip for firmware
> updates when not in passthrough mode.  It is expected the passthru
> mode and the alternate chip select will be controlled by a future
> pinmux driver.
> 
> This driver has only been tested with the ast2400 SOC.
> 
> Signed-off-by: Milton Miller <miltonm@us.ibm.com>
> ---
>  .../devicetree/bindings/mtd/aspeed-smc.txt         |  69 +++
>  drivers/mtd/spi-nor/Kconfig                        |   9 +
>  drivers/mtd/spi-nor/Makefile                       |   1 +
>  drivers/mtd/spi-nor/aspeed-smc.c                   | 547 +++++++++++++++++++++
>  4 files changed, 626 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/aspeed-smc.txt
>  create mode 100644 drivers/mtd/spi-nor/aspeed-smc.c
> 
> diff --git a/Documentation/devicetree/bindings/mtd/aspeed-smc.txt b/Documentation/devicetree/bindings/mtd/aspeed-smc.txt
> new file mode 100644
> index 0000000..01e25de
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/aspeed-smc.txt
> @@ -0,0 +1,69 @@
> +* Aspeed Static Memory controller in SPI mode
> +* Aspeed SPI Flash Controller
> +
> +Required properties:
> +  - compatible : Should be "aspeed,fmc" for Static Memory Controller (AST2400, AST2300?), or
> +> 	> 	>  "aspeed,smc" for the SPI flash controller
> +  - reg : the first contains the register location and length,
> +          the second through nth contains the memory mapping address and length
> +> 	>   for the access window for each chips select
> +  - interrupts : Should contain the interrupt for the dma device if fmc
> +  - clocks : The APB clock input to the controller
> +  - #address-cells : must be 1 corresponding to chip select child binding
> +  - #size-cells : must be 0 corresponding to chip select child binding
> +
> +
> +Child node required properties:
> +  - reg : must contain chip select number in first cell of address, must
> +> 	>   be 1 tuple long
> +  - compatible : may contain "vendor,part", must include "jedec,spi-nor"
> +> 	> 	> (see spi-nor.txt binding).
> +
> +Child node optional properties:
> +  - label           - (optional) name to assign to mtd, default os assigned
> +  - spi-max-frequency - (optional) max frequency of spi bus (XXX max if missing)
> +  - spi-cpol        - (optional) Empty property indicating device requires
> +    > 	>  > 	> 	> inverse clock polarity (CPOL) mode (boolean)
> +  - spi-cpha        - (optional) Empty property indicating device requires
> +    > 	> 	> 	> shifted clock phase (CPHA) mode (boolean)
> +  - spi-tx-bus-width - (optional) The bus width(number of data wires) that
> +                        used for MOSI. Defaults to 1 if not present.
> +  - spi-rx-bus-width - (optional) The bus width(number of data wires) that
> +                        used for MOSI. Defaults to 1 if not present.
> +
> +Child node optional properties:
> + - see mtd/partiton.txt for partitioning bindings and mtd naming
> +
> +
> +Example:
> +
> +fmc: fmc@1e620000 {
> +> 	> compatible = "aspeed,fmc";
> +> 	> reg = < 0x1e620000 0x94
> +> 	> 	> 0x20000000 0x02000000
> +> 	> 	> 0x22000000 0x02000000 >;
> +> 	> #address-cells = <1>;
> +> 	> #size-cells = <0>;
> +> 	bmc@0 {
> +> 	> 	> reg = < 0 >;
> +> 	> 	> compatible = "jedec,spi-nor" ;
> +> 	> 	> label = "bmc0";
> +> 	> 	> /* spi-max-frequency = <>; */
> +> 	> 	> /* m25p,fast-read; */
> +> 	> 	> #address-cells = <1>;
> +> 	> 	> #size-cells = <1>;
> +> 	> 	> 	> bootloader {

Unnecessary indent here?

> +				label = "boot";
> +				reg = < 0 0x8000 >

Indentation should use tabs?

> +> 	> 	> 	> }
> +> 	> };
> +> 	alt@1 {
> +> 	> 	> reg = < 1 >;
> +> 	> 	> compatible = "jedec,spi-nor" ;
> +> 	> 	> label = "bmc1";
> +> 	> 	> /* spi-max-frequency = <>; */
> +> 	> 	> status = "fail";
> +> 	> 	> /* m25p,fast-read; */
> +> 	> };
> +};
> +
> diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
> index 89bf4c1..c7554d8 100644
> --- a/drivers/mtd/spi-nor/Kconfig
> +++ b/drivers/mtd/spi-nor/Kconfig
> @@ -40,4 +40,13 @@ config SPI_NXP_SPIFI
>  > 	>   Flash. Enable this option if you have a device with a SPIFI
>  > 	>   controller and want to access the Flash as a mtd device.
>  
> +config ASPEED_FLASH_SPI
> +> 	> tristate "Aspeed flash controllers in SPI mode"
> +> 	> depends on HAS_IOMEM && OF
> +> 	> depends on ARCH_ASPEED || COMPILE_TEST
> +> 	> help
> +> 	>   This enables support for the New Static Memory Controller (FMC)
> +> 	>   in the AST2400 when attached to SPI nor chips, and support for
> +> 	>   the SPI Memory controller (SPI) for the BIOS.
> +
>  endif # MTD_SPI_NOR
> diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
> index e53333e..ec28610 100644
> --- a/drivers/mtd/spi-nor/Makefile
> +++ b/drivers/mtd/spi-nor/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_MTD_SPI_NOR)> 	> += spi-nor.o
>  obj-$(CONFIG_SPI_FSL_QUADSPI)> 	> += fsl-quadspi.o
> +obj-$(CONFIG_ASPEED_FLASH_SPI)> 	> += aspeed-smc.o
>  obj-$(CONFIG_SPI_NXP_SPIFI)> 	> += nxp-spifi.o
> diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
> new file mode 100644
> index 0000000..6909de7
> --- /dev/null
> +++ b/drivers/mtd/spi-nor/aspeed-smc.c
> @@ -0,0 +1,547 @@
> +/*
> + * ASPEED Static Memory Controller driver
> + * Copyright 2016 IBM Corporation
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation.
> + *
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +enum smc_flash_type {
> +> 	> smc_type_nor = 0,> 	> /* controller connected to nor flash */
> +> 	> smc_type_nand = 1,> 	> /* controller connected to nand flash */
> +> 	> smc_type_spi = 2,> 	> /* controller connected to spi flash */
> +};
> +
> +struct aspeed_smc_info {
> +> 	> u8 nce;> 	> 	> 	> /* number of chip enables */
> +> 	> u8 maxwidth;> 	> 	> /* max width of spi bus */
> +> 	> bool hasdma;> 	> 	> /* has dma engine */
> +> 	> bool hastype;> 	> 	> /* type shift for ce 0 in cfg reg */
> +> 	> u8 we0;> 	> 	> 	> /* we shift for ce 0 in cfg reg */
> +> 	> u8 ctl0;> 	> 	> /* offset in regs of ctl for ce 0 */
> +> 	> u8 cfg;> 	> 	> 	> /* offset in regs of cfg */
> +> 	> u8 time;> 	> 	> /* offset in regs of timing */
> +> 	> u8 misc;> 	> 	> /* offset in regs of misc settings */
> +};
> +
> +static struct aspeed_smc_info fmc_info = {
> +> 	> .nce = 5,
> +> 	> .maxwidth = 4,
> +> 	> .hasdma = true,
> +> 	> .hastype = true,
> +> 	> .we0 = 16,
> +> 	> .ctl0 = 0x10,
> +> 	> .cfg = 0x00,
> +> 	> .time = 0x54,
> +> 	> .misc = 0x50,
> +};
> +
> +static struct aspeed_smc_info smc_info = {
> +> 	> .nce = 1,
> +> 	> .maxwidth = 2,
> +> 	> .hasdma = false,
> +> 	> .hastype = false,
> +> 	> .we0 = 0,
> +> 	> .ctl0 = 0x04,
> +> 	> .cfg = 0x00,
> +> 	> .time = 0x14,
> +> 	> .misc = 0x10,
> +};
> +
> +enum smc_ctl_reg_value {
> +> 	> smc_base,> 	> 	> /* base value without mode for other commands */
> +> 	> smc_read,> 	> 	> /* command reg for (maybe fast) reads */
> +> 	> smc_write,> 	> 	> /* command reg for writes with timings */
> +> 	> smc_num_ctl_reg_values> 	> /* last value to get count of commands */
> +};
> +
> +struct aspeed_smc_controller;
> +
> +struct aspeed_smc_chip {
> +> 	> struct aspeed_smc_controller *controller;
> +> 	> __le32 __iomem *ctl;> 	> 	> 	> /* control register */
> +> 	> void __iomem *base;> 	> 	> 	> /* base of chip window */
> +> 	> struct mtd_info mtd;
> +> 	> __le32 ctl_val[smc_num_ctl_reg_values];> 	> /* controls with timing */
> +> 	> enum smc_flash_type type;> 	> 	> /* what type of flash */
> +> 	> struct spi_nor nor;
> +};
> +
> +struct aspeed_smc_controller {
> +> 	> struct mutex mutex;> 	> 	> 	> /* controller access mutex */
> +> 	> const struct aspeed_smc_info *info;> 	> /* type info of controller */
> +> 	> void __iomem *regs;> 	> 	> 	> /* controller registers */
> +> 	> struct aspeed_smc_chip *chips[0];> 	> /* attached chips */
> +};
> +
> +#define CONTROL_SPI_AAF_MODE BIT(31)
> +#define CONTROL_SPI_IO_MODE_MASK GENMAASK(30, 28)

Typo? GENMASK? Doesn't get detected at during compilation - doesn't
look like CONTROL_SPI_IO_MODE_MASK is actually used?

> +#define CONTROL_SPI_IO_DUAL_DATA BIT(29)
> +#define CONTROL_SPI_IO_DUAL_ADDR_DATA (BIT(29) | BIT(28))
> +#define CONTROL_SPI_IO_QUAD_DATA BIT(30)
> +#define CONTROL_SPI_IO_QUAD_ADDR_DATA (BIT(30) | BIT(28))
> +#define CONTROL_SPI_CE_INACTIVE_SHIFT 24
> +#define CONTROL_SPI_CE_INACTIVE_MASK GENMASK(27, CONTROL_SPI_CE_INACTIVE_SHIFT)
> +/* 0 = 16T ... 15 = 1T   T=HCLK */
> +#define CONTROL_SPI_COMMAND_SHIFT 16
> +#define CONTROL_SPI_DUMMY_CYCLE_COMMAND_OUTPUT BIT(15)
> +#define CONTROL_SPI_IO_DUMMY_CYCLES_HI BIT(14)
> +#define CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT (14 - 2)
> +#define CONTROL_SPI_IO_ADDRESS_4B BIT(13) /* FMC, LEGACY */
> +#define CONTROL_SPI_CLK_DIV4 BIT(13) /* BIOS */
> +#define CONTROL_SPI_RW_MERGE BIT(12)
> +#define CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT 6
> +#define CONTROL_SPI_IO_DUMMY_CYCLES_LO GENMASK(7, CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT)

WARNING: line over 80 characters

> +#define CONTROL_SPI_IO_DUMMY_CYCLES_MASK (CONTROL_SPI_IO_DUMMY_CYCLES_HI | \
> +> 	> 	> 	> 	> 	>   CONTROL_SPI_IO_DUMMY_CYCLES_LO)
> +#define CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT 8
> +#define CONTROL_SPI_CLOCK_FREQ_SEL_MASK GENMASK(11, CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT)
> +#define CONTROL_SPI_LSB_FIRST BIT(5)
> +#define CONTROL_SPI_CLOCK_MODE_3 BIT(4)
> +#define CONTROL_SPI_IN_DUAL_DATA BIT(3)
> +#define CONTROL_SPI_CE_STOP_ACTIVE_CONTROL BIT(2)
> +#define CONTROL_SPI_COMMAND_MODE_MASK GENMASK(1, 0)
> +#define CONTROL_SPI_COMMAND_MODE_NORMAL (0)
> +#define CONTROL_SPI_COMMAND_MODE_FREAD (1)
> +#define CONTROL_SPI_COMMAND_MODE_WRITE (2)
> +#define CONTROL_SPI_COMMAND_MODE_USER (3)
> +
> +#define CONTROL_SPI_KEEP_MASK (CONTROL_SPI_AAF_MODE | \
> +> 	> CONTROL_SPI_CE_INACTIVE_MASK | CONTROL_SPI_IO_ADDRESS_4B | \
> +> 	> CONTROL_SPI_IO_DUMMY_CYCLES_MASK | CONTROL_SPI_CLOCK_FREQ_SEL_MASK | \
> +> 	> CONTROL_SPI_LSB_FIRST | CONTROL_SPI_CLOCK_MODE_3)
> +
> +#define CONTROL_SPI_CLK_DIV4 BIT(13) /* BIOS */
> +
> +static u32 spi_control_fill_opcode(u8 opcode)
> +{
> +> 	> return ((u32)(opcode)) << CONTROL_SPI_COMMAND_SHIFT;
> +}
> +
> +#if 0 /* ATTR */
> +static u32 spi_control_to_freq_div(u32 control)
> +{
> +> 	> u32 sel;
> +
> +> 	> sel = control & CONTROL_SPI_CLOCK_FREQ_SEL_MASK;
> +> 	> sel >>= CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT;
> +
> +> 	> /* 16, 14, 12, 10, 8, 6, 4, 2, 15, 13, 11, 9, 7, 5, 3, 1 */
> +> 	> return 16 - (((sel & 7) << 1) + ((sel & 8) >> 1));
> +}
> +
> +static u32 spi_control_to_dummy_bytes(u32 control)
> +{
> +
> +> 	> return ((control & CONTROL_SPI_IO_DUMMY_CYCLES_LO) >>
> +> 	> 	> 	> CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT) |
> +> 	> 	> ((control & CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT) >>
> +> 	> 	> 	> CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT);
> +}
> +
> +static size_t show_ctl_div(u32 control, char *buf)
> +{
> +> 	> return sprintf(buf, "%u\n", spi_control_to_freq_div(control));
> +}
> +
> +static size_t show_ctl_dummy_bytes(u32 control, char *buf)
> +{
> +> 	> return sprintf(buf, "%u\n", spi_control_to_dummy_bytes(control));
> +}
> +#endif /* ATTR */

Seems Jeremy hasn't replied regarding the #if 0 blocks - my preference
is to remove them from the patch and retain the code for when the
functions are integrated, but I'll leave that call to Jeremy since he
raised it.

> +
> +static void aspeed_smc_start_user(struct spi_nor *nor)
> +{
> +> 	> struct aspeed_smc_chip *chip = nor->priv;
> +> 	> u32 ctl = chip->ctl_val[smc_base];
> +
> +> 	> mutex_lock(&chip->controller->mutex);
> +
> +> 	> ctl |= CONTROL_SPI_COMMAND_MODE_USER |
> +> 	> 	> CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
> +> 	> writel(ctl, chip->ctl);
> +
> +> 	> ctl &= ~CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
> +> 	> writel(ctl, chip->ctl);
> +}
> +
> +static void aspeed_smc_stop_user(struct spi_nor *nor)
> +{
> +> 	> struct aspeed_smc_chip *chip = nor->priv;
> +
> +> 	> u32 ctl = chip->ctl_val[smc_read];
> +> 	> u32 ctl2 = ctl | CONTROL_SPI_COMMAND_MODE_USER |
> +> 	> 	> CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
> +
> +> 	> writel(ctl2, chip->ctl);> 	> /* stop user CE control */
> +> 	> writel(ctl, chip->ctl);> 	> 	> /* default to fread or read */
> +
> +> 	> mutex_unlock(&chip->controller->mutex);
> +}
> +
> +#if 0 /* memcpy */
> +static void aspeed_smc_start_write(struct spi_nor *nor)
> +{
> +> 	> struct aspeed_smc_chip *chip = nor->priv;
> +> 	> u32 ctl = chip->ctl_val[smc_write];
> +
> +> 	> mutex_lock(&chip->controller->mutex);
> +
> +> 	> writel(ctl | CONTROL_SPI_CE_STOP_ACTIVE_CONTROL,  chip->ctl);
> +
> +> 	> writel(ctl, chip->ctl);
> +}
> +
> +static void aspeed_smc_stop_write(struct spi_nor *nor)
> +{
> +> 	> aspeed_smc_stop_user(nor);
> +}
> +#endif
> +
> +static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
> +{
> +> 	> struct aspeed_smc_chip *chip = nor->priv;
> +
> +> 	> aspeed_smc_start_user(nor);
> +> 	> writeb(opcode, chip->base);
> +> 	> _memcpy_fromio(buf, chip->base, len);
> +> 	> aspeed_smc_stop_user(nor);
> +
> +> 	> return 0;
> +}
> +
> +static int aspeed_smc_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
> +> 	> 	> 	> 	> int len, int write_enable)
> +{
> +> 	> struct aspeed_smc_chip *chip = nor->priv;
> +
> +> 	> aspeed_smc_start_user(nor);
> +> 	> writeb(opcode, chip->base);
> +> 	> _memcpy_toio(chip->base, buf, len);
> +> 	> aspeed_smc_stop_user(nor);
> +
> +> 	> return 0;
> +}
> +
> +static void aspeed_smc_send_cmd_addr(struct spi_nor *nor, u8 cmd, u32 addr)
> +{
> +> 	> struct aspeed_smc_chip *chip = nor->priv;
> +> 	> __be32 temp;
> +> 	> u32 cmdaddr;
> +
> +> 	> switch (nor->addr_width) {
> +> 	> default:
> +> 	> 	> WARN_ONCE(1, "Unexpected address width %u, defaulting to 3\n",
> +> 	> 	> 	>   nor->addr_width);
> +> 	> 	> /* FALLTHROUGH */
> +> 	> case 3:
> +> 	> 	> cmdaddr = addr & 0xFFFFFF;
> +
> +> 	> 	> cmdaddr |= (u32)cmd << 24;
> +
> +> 	> 	> temp = cpu_to_be32(cmdaddr);
> +> 	> 	> memcpy_toio(chip->base, &temp, 4);
> +> 	> 	> break;
> +> 	> case 4:
> +> 	> 	> temp = cpu_to_be32(addr);
> +> 	> 	> writeb(cmd, chip->base);
> +> 	> 	> memcpy_toio(chip->base, &temp, 4);
> +> 	> 	> break;
> +> 	> }
> +}
> +
> +#if 0 /* memcpy */
> +static int aspeed_smc_read_memcpy(struct spi_nor *nor, loff_t from, size_t len,
> +> 	> 	> 	> 	>   size_t *retlen, u_char *read_buf)
> +{
> +> 	> struct aspeed_smc_chip *chip = nor->priv;
> +
> +> 	> mutex_lock(&chip->controller->mutex);
> +
> +> 	> memcpy_fromio(read_buf, chip->base, len);
> +> 	> *retlen += len;
> +
> +> 	> mutex_unlock(&chip->controller->mutex);
> +
> +> 	> return 0;
> +}
> +
> +static void aspeed_smc_write_memcpy(struct spi_nor *nor, loff_t to, size_t len,
> +> 	> 	> 	> 	>     size_t *retlen, const u_char *write_buf)
> +{
> +> 	> struct aspeed_smc_chip *chip = nor->priv;
> +
> +> 	> aspeed_smc_start_write(nor);
> +> 	> memcpy_toio(chip->base, write_buf, len);
> +> 	> *retlen += len;
> +> 	> aspeed_smc_stop_write(nor);
> +}
> +#endif
> +
> +static int aspeed_smc_read_user(struct spi_nor *nor, loff_t from, size_t len,
> +> 	> 	> 	> 	> size_t *retlen, u_char *read_buf)
> +{
> +> 	> struct aspeed_smc_chip *chip = nor->priv;
> +
> +> 	> aspeed_smc_start_user(nor);
> +> 	> aspeed_smc_send_cmd_addr(nor, nor->read_opcode, from);
> +> 	> memcpy_fromio(read_buf, chip->base, len);
> +> 	> *retlen += len;
> +> 	> aspeed_smc_stop_user(nor);
> +
> +> 	> return 0;
> +}
> +
> +static void aspeed_smc_write_user(struct spi_nor *nor, loff_t to, size_t len,
> +> 	> 	> 	> 	>   size_t *retlen, const u_char *write_buf)
> +{
> +> 	> struct aspeed_smc_chip *chip = nor->priv;
> +
> +> 	> aspeed_smc_start_user(nor);
> +> 	> aspeed_smc_send_cmd_addr(nor, nor->program_opcode, to);
> +> 	> memcpy_toio(chip->base, write_buf, len);
> +> 	> *retlen += len;
> +> 	> aspeed_smc_stop_user(nor);
> +}
> +
> +static int aspeed_smc_erase(struct spi_nor *nor, loff_t offs)
> +{
> +> 	> aspeed_smc_start_user(nor);
> +> 	> aspeed_smc_send_cmd_addr(nor, nor->erase_opcode, offs);
> +> 	> aspeed_smc_stop_user(nor);
> +
> +> 	> return 0;
> +}
> +
> +static int aspeed_smc_remove(struct platform_device *dev)
> +{
> +> 	> struct aspeed_smc_chip *chip;
> +> 	> struct aspeed_smc_controller *controller = platform_get_drvdata(dev);
> +> 	> int n;
> +
> +> 	> for (n = 0; n < controller->info->nce; n++) {
> +> 	> 	> chip = controller->chips[n];
> +> 	> 	> if (chip)
> +> 	> 	> 	> mtd_device_unregister(&chip->mtd);
> +> 	> }
> +
> +> 	> return 0;
> +}
> +
> +const struct of_device_id aspeed_smc_matches[] = {
> +> 	> { .compatible = "aspeed,fmc", .data = &fmc_info },
> +> 	> { .compatible = "aspeed,smc", .data = &smc_info },
> +> 	> { }
> +};
> +MODULE_DEVICE_TABLE(of, aspeed_smc_matches);
> +
> +static struct platform_device *
> +of_platform_device_create_or_find(struct device_node *child,
> +> 	> 	> 	> 	>   struct device *parent)
> +{
> +> 	> struct platform_device *cdev;
> +
> +> 	> cdev = of_platform_device_create(child, NULL, parent);
> +> 	> if (!cdev)
> +> 	> 	> cdev = of_find_device_by_node(child);
> +> 	> return cdev;
> +}
> +
> +static int aspeed_smc_probe(struct platform_device *dev)
> +{
> +> 	> struct aspeed_smc_controller *controller;
> +> 	> const struct of_device_id *match;
> +> 	> const struct aspeed_smc_info *info;
> +> 	> struct resource *r;
> +> 	> void __iomem *regs;
> +> 	> struct device_node *child;
> +> 	> int err = 0;
> +> 	> unsigned int n;
> +
> +> 	> match = of_match_device(aspeed_smc_matches, &dev->dev);
> +> 	> if (!match || !match->data)
> +> 	> 	> return -ENODEV;
> +> 	> info = match->data;
> +> 	> r = platform_get_resource(dev, IORESOURCE_MEM, 0);
> +> 	> regs = devm_ioremap_resource(&dev->dev, r);
> +> 	> if (IS_ERR(regs))
> +> 	> 	> return PTR_ERR(regs);
> +
> +> 	> controller = devm_kzalloc(&dev->dev, sizeof(*controller) +
> +> 	> 	> info->nce * sizeof(controller->chips[0]), GFP_KERNEL);
> +> 	> if (!controller)
> +> 	> 	> return -ENOMEM;
> +> 	> platform_set_drvdata(dev, controller);
> +> 	> controller->regs = regs;
> +> 	> controller->info = info;
> +> 	> mutex_init(&controller->mutex);
> +
> +> 	> /* XXX turn off legacy mode if fmc ? */
> +> 	> /* XXX handshake to enable access to SMC (bios) controller w/ host? */
> +
> +> 	> for_each_available_child_of_node(dev->dev.of_node, child) {
> +> 	> 	> struct mtd_part_parser_data ppdata;
> +> 	> 	> struct platform_device *cdev;
> +> 	> 	> struct aspeed_smc_chip *chip;
> +> 	> 	> u32 reg;
> +
> +> 	> 	> if (!of_device_is_compatible(child, "jedec,spi-nor"))
> +> 	> 	> 	> continue;> 	> /* XXX consider nand, nor children */
> +
> +
> +> 	> 	> /*
> +> 	> 	>  * create a platform device from the of node.
> +> 	> 	>  * if the device already was created (eg from
> +> 	> 	>  * a prior bind/unbind cycle) use it
> +> 	> 	>  *
> +> 	> 	>  * XXX The child name will become the default mtd
> +> 	> 	>  * name in ioctl and /proc/mtd.  Should we default
> +> 	> 	>  * to node->name (without unit)?  The name must be
> +> 	> 	>  * unique among all platform devices.  (Name would
> +> 	> 	>  * replace NULL in create call below).
> +> 	> 	>  * ... Or we can just encourage the label attribute.
> +> 	> 	>  *
> +> 	> 	>  * The only reason to do the child here is to use it in
> +> 	> 	>  * dev_err below for duplicate chip id.  We could use
> +> 	> 	>  * the controller dev.
> +> 	> 	>  */
> +> 	> 	> cdev = of_platform_device_create_or_find(child, &dev->dev);
> +> 	> 	> if (!cdev)
> +> 	> 	> 	> continue;
> +
> +> 	> 	> err = of_property_read_u32(child, "reg", &n);
> +> 	> 	> if (err == -EINVAL && info->nce == 1)
> +> 	> 	> 	> n = 0;
> +> 	> 	> else if (err || n >= info->nce)
> +> 	> 	> 	> continue;
> +> 	> 	> if (controller->chips[n]) {
> +> 	> 	> 	> dev_err(&cdev->dev,
> +> 	> 	> 	> 	> "chip-id %u already in use in use by %s\n",
> +> 	> 	> 	> 	> n, dev_name(controller->chips[n]->nor.dev));
> +> 	> 	> 	> continue;
> +> 	> 	> }
> +> 	> 	> chip = devm_kzalloc(&dev->dev, sizeof(*chip), GFP_KERNEL);
> +> 	> 	> if (!chip)
> +> 	> 	> 	> continue;
> +
> +> 	> 	> r = platform_get_resource(dev, IORESOURCE_MEM, n + 1);
> +> 	> 	> chip->base = devm_ioremap_resource(&dev->dev, r);
> +
> +> 	> 	> if (!chip->base)
> +> 	> 	> 	> continue;
> +> 	> 	> chip->controller = controller;
> +> 	> 	> chip->ctl = controller->regs + info->ctl0 + n * 4;
> +
> +> 	> 	> /* dt said its spi.  Shoud set in controller if has_type */

WARNING: 'Shoud' may be misspelled - perhaps 'Should'?

> +		chip->type = smc_type_spi;
> +
> +> 	> 	> /*
> +> 	> 	>  * Always turn on write enable bit in config register to
> +> 	> 	>  * allow opcodes to be sent in user mode.
> +> 	> 	>  */
> +> 	> 	> mutex_lock(&controller->mutex);
> +> 	> 	> reg = readl(controller->regs + info->cfg);
> +> 	> 	> dev_dbg(&dev->dev, "flash config was %08x\n", reg);
> +> 	> 	> reg |= 1 << (info->we0 + n); /* WEn */
> +> 	> 	> writel(reg, controller->regs + info->cfg);
> +> 	> 	> mutex_unlock(&controller->mutex);
> +
> +> 	> 	> /* XXX check resource within fmc CEx Segment Address Register */
> +> 	> 	> /* XXX -- see dt vs jedec id vs bootloader */
> +> 	> 	> /* XXX check / program clock phase/polarity,  only 0 or 3 */
> +
> +> 	> 	> /*
> +> 	> 	>  * Read the existing control register to get basic values.
> +> 	> 	>  *
> +> 	> 	>  * XXX probably need more sanitation.
> +> 	> 	>  * XXX do we trust the bootloader or the device tree?
> +> 	> 	>  * spi-nor.c trusts jtag id over passed ids.
> +> 	> 	>  */
> +> 	> 	> reg = readl(chip->ctl);
> +> 	> 	> chip->ctl_val[smc_base] = reg & CONTROL_SPI_KEEP_MASK;
> +
> +> 	> 	> if ((reg & CONTROL_SPI_COMMAND_MODE_MASK) ==
> +> 	> 	>     CONTROL_SPI_COMMAND_MODE_NORMAL)
> +> 	> 	> 	> chip->ctl_val[smc_read] = reg;
> +#if 0 /* should we inherit fast read (fread) from boot ?  or id tables?*/
> +> 	> 	> else if ((reg & CONTROL_SPI_COMMAND_MODE_MASK) ==
> +> 	> 	> 	>  CONTROL_SPI_COMMAND_MODE_FREAD)
> +> 	> 	> 	> chip->ctl_val[smc_read] = reg;
> +#endif
> +> 	> 	> else
> +> 	> 	> 	> chip->ctl_val[smc_read] = chip->ctl_val[smc_base] |
> +> 	> 	> 	> 	> CONTROL_SPI_COMMAND_MODE_NORMAL;
> +
> +> 	> 	> chip->nor.dev = &cdev->dev;
> +> 	> 	> chip->nor.priv = chip;
> +> 	> 	> chip->nor.mtd = &chip->mtd;
> +> 	> 	> chip->mtd.priv = &chip->nor; /* should be in spi_nor_scan()!! */
> +> 	> 	> chip->mtd.name = of_get_property(child, "label", NULL);
> +> 	> 	> chip->nor.erase = aspeed_smc_erase;
> +> 	> 	> chip->nor.read = aspeed_smc_read_user;
> +> 	> 	> chip->nor.write = aspeed_smc_write_user;
> +> 	> 	> chip->nor.read_reg = aspeed_smc_read_reg;
> +> 	> 	> chip->nor.write_reg = aspeed_smc_write_reg;
> +
> +> 	> 	> /*
> +> 	> 	>  * XXX use of property and controller info width to choose
> +> 	> 	>  * SPI_NOR_QUAD , SPI_NOR_DUAL
> +> 	> 	>  */
> +> 	> 	> err = spi_nor_scan(&chip->nor, NULL, SPI_NOR_NORMAL);
> +> 	> 	> if (err)
> +> 	> 	> 	> continue;
> +
> +> 	> 	> chip->ctl_val[smc_write] = chip->ctl_val[smc_base] |
> +> 	> 	> 	> spi_control_fill_opcode(chip->nor.program_opcode) |
> +> 	> 	> 	> CONTROL_SPI_COMMAND_MODE_WRITE;
> +
> +> 	> 	> /* XXX intrepret nor flags into controller settings */
> +> 	> 	> /* XXX enable fast read here */
> +> 	> 	> /* XXX check if resource size big enough for chip */
> +
> +> 	> 	> memset(&ppdata, 0, sizeof(ppdata));
> +> 	> 	> ppdata.of_node = cdev->dev.of_node;
> +> 	> 	> err = mtd_device_parse_register(&chip->mtd, NULL, &ppdata, NULL, 0);

WARNING: line over 80 characters

> +		if (err)
> +> 	> 	> 	> continue;
> +> 	> 	> controller->chips[n] = chip;
> +> 	> }
> +
> +> 	> /* did we register any children? */
> +> 	> for (n = 0; n < info->nce; n++)
> +> 	> 	> if (controller->chips[n])
> +> 	> 	> 	> break;
> +
> +> 	> if (n == info->nce)
> +> 	> 	> return -ENODEV;
> +
> +> 	> return 0;
> +}
> +
> +static struct platform_driver aspeed_smc_driver = {
> +> 	> .probe = aspeed_smc_probe,
> +> 	> .remove = aspeed_smc_remove,
> +> 	> .driver = {
> +> 	> 	> .name = KBUILD_MODNAME,
> +> 	> 	> .of_match_table = aspeed_smc_matches,
> +> 	> }
> +};
> +
> +module_platform_driver(aspeed_smc_driver);
> +
> +MODULE_DESCRIPTION("ASPEED Static Memory Controller Driver");
> +MODULE_AUTHOR("Milton Miller");
> +MODULE_LICENSE("GPL v2");

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH linux 2/3] aspeed: update bmc dts with attached flash
  2016-01-22  3:50 ` [PATCH linux 2/3] aspeed: update bmc dts with attached flash OpenBMC Patches
@ 2016-01-25 13:18   ` Andrew Jeffery
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Jeffery @ 2016-01-25 13:18 UTC (permalink / raw)
  To: OpenBMC Patches, openbmc

On Thu, 2016-01-21 at 21:50 -0600, OpenBMC Patches wrote:
> From: "Milton D. Miller II" <miltonm@us.ibm.com>
> 
> Add the attached spi flash chips attached to the static memory controller
> and the SPI memory controller.  The partitions and label for the SMC
> attached flash are included in a seperate file for import from other
> build systems.
> 
> Signed-off-by: Milton Miller <miltonm@us.ibm.com>
> ---
>  arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts     | 35 ++++++++++++++++++++++
>  arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi | 28 +++++++++++++++++
>  arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts      | 35 ++++++++++++++++++++++
>  3 files changed, 98 insertions(+)
>  create mode 100644 arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> 
> diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts b/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts
> index ebf86bb..cba561a 100644
> --- a/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts
> +++ b/arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts
> @@ -7,6 +7,41 @@
>  > 	> model = "Barrelye BMC";
>  > 	> compatible = "rackspace,barreleye-bmc", "aspeed,ast2400";
>  > 	> ahb {
> +> 	> 	fmc@1e620000 {
> +> 	> 	> 	> reg = < 0x1e620000 0x94
> +> 	> 	> 	> 	> 0x20000000 0x02000000 >;
> +> 	> 	> 	> #address-cells = <1>;
> +> 	> 	> 	> #size-cells = <0>;
> +> 	> 	> 	> compatible = "aspeed,fmc";
> +> 	> 	> 	flash@0 {
> +> 	> 	> 	> 	> reg = < 0 >;
> +> 	> 	> 	> 	> compatible = "jedec,spi-nor" ;
> +> 	> 	> 	> 	> /*
> +> 	> 	> 	> 	>  * Possibly required props:
> +> 	> 	> 	> 	>  * spi-max-frequency = <>
> +> 	> 	> 	> 	>  * spi-tx-bus-width = <>
> +> 	> 	> 	> 	>  * spi-rx-bus-width  = <>
> +> 	> 	> 	> 	>  * m25p,fast-read
> +> 	> 	> 	> 	>  * spi-cpol if inverse clock polarity (CPOL)
> +> 	> 	> 	> 	>  * spi-cpha if shifted clock phase (CPHA)
> +> 	> 	> 	> 	>  */
> +#include "aspeed-bmc-opp-flash-layout.dtsi"

This feels a little surprising, but from my limited knowledge of DT I
don't know any better way.

> +			};
> +> 	> 	> };
> +> 	> 	spi@1e630000 {
> +> 	> 	> 	> reg = < 0x1e630000 0x18
> +> 	> 	> 	> 	> 0x30000000 0x02000000 >;
> +> 	> 	> 	> #address-cells = <1>;
> +> 	> 	> 	> #size-cells = <0>;
> +> 	> 	> 	> compatible = "aspeed,smc";
> +> 	> 	> 	> flash {
> +> 	> 	> 	> 	> reg = < 0 >;
> +> 	> 	> 	> 	> compatible = "jedec,spi-nor" ;
> +> 	> 	> 	> 	> label = "pnor";
> +> 	> 	> 	> 	> /* spi-max-frequency = <>; */
> +> 	> 	> 	> 	> /* m25p,fast-read; */
> +> 	> 	> 	> };
> +> 	> 	> };
>  > 	> 	> apb {
>  > 	> 	> 	> i2c: i2c@1e78a040 {
>  > 	> 	> 	> 	> i2c0: i2c-bus@40 {
> diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi b/arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi
> new file mode 100644
> index 0000000..ca8639b
> --- /dev/null
> +++ b/arch/arm/boot/dts/aspeed-bmc-opp-flash-layout.dtsi
> @@ -0,0 +1,28 @@
> +/* This file is the label for the bmc primary flash and its partitions */
> +> 	> 	> 	> 	> label = "bmc";
> +> 	> 	> 	> 	> #address-cells = < 1 >;
> +> 	> 	> 	> 	> #size-cells = < 1 >;
> +> 	> 	> 	> 	> u-boot {
> +> 	> 	> 	> 	> 	> reg = < 0 0x60000 >;
> +> 	> 	> 	> 	> 	> label = "u-boot";
> +> 	> 	> 	> 	> };
> +> 	> 	> 	> 	> u-boot-env {
> +> 	> 	> 	> 	> 	> reg = < 0x60000 0x20000 >;
> +> 	> 	> 	> 	> 	> label = "u-boot-env";
> +> 	> 	> 	> 	> };
> +> 	> 	> 	> 	> kernel  {
> +> 	> 	> 	> 	> 	> reg = < 0x80000 0x280000 >;
> +> 	> 	> 	> 	> 	> label = "kernel";
> +> 	> 	> 	> 	> };
> +> 	> 	> 	> 	> initramfs {
> +> 	> 	> 	> 	> 	> reg = < 0x300000 0x1c0000 >;
> +> 	> 	> 	> 	> 	> label = "initramfs";
> +> 	> 	> 	> 	> };
> +> 	> 	> 	> 	> rofs  {
> +> 	> 	> 	> 	> 	> reg = < 0x4c0000 0x1740000 >;
> +> 	> 	> 	> 	> 	> label = "rofs";
> +> 	> 	> 	> 	> };
> +> 	> 	> 	> 	> rwfs  {
> +> 	> 	> 	> 	> 	> reg = < 0x1c00000 0x400000 >;
> +> 	> 	> 	> 	> 	> label = "rwfs";
> +> 	> 	> 	> 	> };
> diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts b/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
> index 92a7c77..9aacae7 100644
> --- a/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
> +++ b/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
> @@ -8,6 +8,41 @@
>  > 	> compatible = "tyan,palmetto-bmc", "aspeed,ast2400";
>  
>  > 	> ahb {
> +> 	> 	fmc@1e620000 {
> +> 	> 	> 	> reg = < 0x1e620000 0x94
> +> 	> 	> 	> 	> 0x20000000 0x02000000 >;
> +> 	> 	> 	> #address-cells = <1>;
> +> 	> 	> 	> #size-cells = <0>;
> +> 	> 	> 	> compatible = "aspeed,fmc";
> +> 	> 	> 	flash@0 {
> +> 	> 	> 	> 	> reg = < 0 >;
> +> 	> 	> 	> 	> compatible = "jedec,spi-nor" ;
> +> 	> 	> 	> 	> /*
> +> 	> 	> 	> 	>  * Possibly required props:
> +> 	> 	> 	> 	>  * spi-max-frequency = <>
> +> 	> 	> 	> 	>  * spi-tx-bus-width = <>
> +> 	> 	> 	> 	>  * spi-rx-bus-width  = <>
> +> 	> 	> 	> 	>  * m25p,fast-read
> +> 	> 	> 	> 	>  * spi-cpol if inverse clock polarity (CPOL)
> +> 	> 	> 	> 	>  * spi-cpha if shifted clock phase (CPHA)
> +> 	> 	> 	> 	>  */
> +#include "aspeed-bmc-opp-flash-layout.dtsi"
> +> 	> 	> 	> };
> +> 	> 	> };
> +> 	> 	spi@1e630000 {
> +> 	> 	> 	> reg = < 0x1e630000 0x18
> +> 	> 	> 	> 	> 0x30000000 0x02000000 >;
> +> 	> 	> 	> #address-cells = <1>;
> +> 	> 	> 	> #size-cells = <0>;
> +> 	> 	> 	> compatible = "aspeed,smc";
> +> 	> 	> 	> flash {
> +> 	> 	> 	> 	> reg = < 0 >;
> +> 	> 	> 	> 	> compatible = "jedec,spi-nor" ;
> +> 	> 	> 	> 	> label = "pnor";
> +> 	> 	> 	> 	> /* spi-max-frequency = <>; */
> +> 	> 	> 	> 	> /* m25p,fast-read; */
> +> 	> 	> 	> };
> +> 	> 	> };
>  > 	> 	> apb {
>  > 	> 	> 	> i2c: i2c@1e78a040 {
>  > 	> 	> 	> 	> i2c0: i2c-bus@40 {

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH linux 3/3] aspeed: update defconfig
  2016-01-22  3:50 ` [PATCH linux 3/3] aspeed: update defconfig OpenBMC Patches
@ 2016-01-25 13:19   ` Andrew Jeffery
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Jeffery @ 2016-01-25 13:19 UTC (permalink / raw)
  To: OpenBMC Patches, openbmc

On Thu, 2016-01-21 at 21:50 -0600, OpenBMC Patches wrote:
> From: "Milton D. Miller II" <miltonm@us.ibm.com>
> 
> Turn on the new spi memory controller driver, plus some file systems
> that will be used on the new mtd.
> 
> Signed-off-by: Milton Miller <miltonm@us.ibm.com>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  arch/arm/configs/aspeed_defconfig | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/arm/configs/aspeed_defconfig
> b/arch/arm/configs/aspeed_defconfig
> index a83da91..9727eba 100644
> --- a/arch/arm/configs/aspeed_defconfig
> +++ b/arch/arm/configs/aspeed_defconfig
> @@ -57,6 +57,8 @@ CONFIG_MTD_BLOCK=y
>  CONFIG_MTD_PARTITIONED_MASTER=y
>  CONFIG_MTD_DATAFLASH=y
>  CONFIG_MTD_NAND=y
> +CONFIG_MTD_SPI_NOR=y
> +CONFIG_ASPEED_FLASH_SPI=y
>  CONFIG_MTD_UBI=y
>  CONFIG_MTD_UBI_GLUEBI=y
>  CONFIG_BLK_DEV_LOOP=y
> @@ -170,11 +172,16 @@ CONFIG_PWM=y
>  CONFIG_FIRMWARE_MEMMAP=y
>  CONFIG_EXT4_FS=y
>  CONFIG_FANOTIFY=y
> +CONFIG_AUTOFS4_FS=y
> +CONFIG_OVERLAY_FS=y
>  CONFIG_TMPFS=y
>  CONFIG_TMPFS_POSIX_ACL=y
> +CONFIG_TMPFS_XATTR=y
>  CONFIG_JFFS2_FS=y
> +CONFIG_JFFS2_XATTR=y
>  CONFIG_JFFS2_SUMMARY=y
>  CONFIG_SQUASHFS=y
> +CONFIG_SQUASHFS_XZ=y
>  CONFIG_NFS_FS=y
>  CONFIG_ROOT_NFS=y
>  CONFIG_NLS_CODEPAGE_437=y

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-01-25 13:20 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-22  3:50 [PATCH linux 0/3] [PATCH v3 0/3] Aspeed spi nor 3 OpenBMC Patches
2016-01-22  3:50 ` [PATCH linux 1/3] mtd/spi-nor: Add SPI memory controllers for ASPEED AST2400 OpenBMC Patches
2016-01-25 12:28   ` Andrew Jeffery
2016-01-22  3:50 ` [PATCH linux 2/3] aspeed: update bmc dts with attached flash OpenBMC Patches
2016-01-25 13:18   ` Andrew Jeffery
2016-01-22  3:50 ` [PATCH linux 3/3] aspeed: update defconfig OpenBMC Patches
2016-01-25 13:19   ` Andrew Jeffery

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.