* [PATCH 00/10] mtd: st_spi_fsm: Add new device @ 2013-11-14 14:22 Lee Jones 2013-11-14 14:22 ` [PATCH 01/10] mtd: st_spi_fsm: Allocate resources and register with MTD framework Lee Jones ` (9 more replies) 0 siblings, 10 replies; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel First stab at getting this thing Mainlined. It doesn't do a great deal yet, but we are able to initialise the device and dynamically set it up correctly based on an extracted JEDEC ID. arch/arm/boot/dts/stih416-b2105.dts | 10 ++ arch/arm/boot/dts/stih416-pinctrl.dtsi | 12 +++ drivers/mtd/devices/Kconfig | 7 ++ drivers/mtd/devices/Makefile | 1 + drivers/mtd/devices/st_spi_fsm.c | 605 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/mtd/devices/st_spi_fsm.h | 187 ++++++++++++++++++++++++++++++++ 6 files changed, 822 insertions(+) ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 01/10] mtd: st_spi_fsm: Allocate resources and register with MTD framework 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones @ 2013-11-14 14:22 ` Lee Jones 2013-11-14 14:22 ` [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines Lee Jones ` (8 subsequent siblings) 9 siblings, 0 replies; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel This is a new driver. It's used to communicate with a special type of optimised Serial Flash Controller called the FSM. The FSM uses a subset of the SPI protocol to communicate with supported NOR-Flash devices. Signed-off-by: Lee Jones <lee.jones@linaro.org> --- drivers/mtd/devices/Kconfig | 7 +++ drivers/mtd/devices/Makefile | 1 + drivers/mtd/devices/st_spi_fsm.c | 119 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 drivers/mtd/devices/st_spi_fsm.c diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 74ab4b7..d977281 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -217,6 +217,13 @@ config MTD_DOCG3 M-Systems and now Sandisk. The support is very experimental, and doesn't give access to any write operations. +config MTD_ST_SPI_FSM + tristate "ST Microelectronics SPI FSM Serial Flash Controller" + help + This provides an MTD device driver for the ST Microelectronics + SPI FSM Serial Flash Controller and support for a subset of + connected Serial Flash devices. + if MTD_DOCG3 config BCH_CONST_M default 14 diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index d83bd73..c68868f 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_OMAP_BCH) += elm.o obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o obj-$(CONFIG_MTD_SST25L) += sst25l.o obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o +obj-$(CONFIG_MTD_ST_SPI_FSM) += st_spi_fsm.o CFLAGS_docg3.o += -I$(src) diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c new file mode 100644 index 0000000..689f059 --- /dev/null +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -0,0 +1,119 @@ +/* + * st_spi_fsm.c Support for ST Serial Flash Controller + * + * Author: Angus Clark <angus.clark@st.com> + * + * Copyright (C) 2010-2013 STicroelectronics Limited + * + * JEDEC probe based on drivers/mtd/devices/m25p80.c + * + * This code 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/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/mtd/mtd.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/of.h> + +#include <asm/io.h> + +#include "st_spi_fsm.h" + +struct stfsm { + struct device *dev; + void __iomem *base; + struct resource *region; + struct mtd_info mtd; + struct mutex lock; +}; + +static int stfsm_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct resource *res; + struct stfsm *fsm; + + if (!np) { + dev_err(&pdev->dev, "No DT found\n"); + return -EINVAL; + } + + fsm = devm_kzalloc(&pdev->dev, sizeof(*fsm), GFP_KERNEL); + if (!fsm) + return -ENOMEM; + + fsm->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Resource not found\n"); + return -ENODEV; + } + + fsm->region = devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), pdev->name); + if (!fsm->region) { + dev_err(&pdev->dev, + "Failed to reserve memory region [0x%08x-0x%08x]\n", + res->start, res->end); + return -EBUSY; + } + + fsm->base = devm_ioremap_nocache(&pdev->dev, + res->start, resource_size(res)); + if (!fsm->base) { + dev_err(&pdev->dev, "Failed to ioremap [0x%08x]\n", res->start); + return -EINVAL; + } + + mutex_init(&fsm->lock); + + platform_set_drvdata(pdev, fsm); + + fsm->mtd.dev.parent = &pdev->dev; + fsm->mtd.type = MTD_NORFLASH; + fsm->mtd.writesize = 4; + fsm->mtd.writebufsize = fsm->mtd.writesize; + fsm->mtd.flags = MTD_CAP_NORFLASH; + + return mtd_device_parse_register(&fsm->mtd, NULL, NULL, NULL, 0); +} + +static int __exit stfsm_remove(struct platform_device *pdev) +{ + struct stfsm *fsm = platform_get_drvdata(pdev); + int err; + + err = mtd_device_unregister(&fsm->mtd); + if (err) + return err; + + return 0; +} + +static struct of_device_id stfsm_match[] = { + { .compatible = "st,spi-fsm", }, + {}, +}; +MODULE_DEVICE_TABLE(of, spi_fsm_match); + +static struct platform_driver stfsm_driver = { + .probe = stfsm_probe, + .remove = stfsm_remove, + .driver = { + .name = "st-spi-fsm", + .owner = THIS_MODULE, + .of_match_table = stfsm_match, + }, +}; +module_platform_driver(stfsm_driver); + +MODULE_AUTHOR("Angus Clark <angus.clark@st.com>"); +MODULE_DESCRIPTION("ST SPI FSM driver"); +MODULE_LICENSE("GPL"); -- 1.8.1.2 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones 2013-11-14 14:22 ` [PATCH 01/10] mtd: st_spi_fsm: Allocate resources and register with MTD framework Lee Jones @ 2013-11-14 14:22 ` Lee Jones 2013-11-18 9:15 ` Linus Walleij 2013-11-14 14:22 ` [PATCH 03/10] mtd: st_spi_fsm: Initialise and configure the FSM for normal working conditions Lee Jones ` (7 subsequent siblings) 9 siblings, 1 reply; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel Here we provide the FSM's register addresses, register bit names/offsets and some commands which will prove useful as we start bulk the FMS's driver out with functionality. Signed-off-by: Lee Jones <lee.jones@linaro.org> --- drivers/mtd/devices/st_spi_fsm.h | 183 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 drivers/mtd/devices/st_spi_fsm.h diff --git a/drivers/mtd/devices/st_spi_fsm.h b/drivers/mtd/devices/st_spi_fsm.h new file mode 100644 index 0000000..11ca33a --- /dev/null +++ b/drivers/mtd/devices/st_spi_fsm.h @@ -0,0 +1,183 @@ +/* + * st_spi_fsm.c Support for ST Serial Flash Controller + * + * Author: Angus Clark <angus.clark@st.com> + * + * Copyright (C) 2010-2013 STicroelectronics Limited + * + * JEDEC probe based on drivers/mtd/devices/m25p80.c + * + * This code 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. + * + */ + +#ifndef ST_SPI_FSM_H +#define ST_SPI_FSM_H + +/* + * FSM SPI Controller Registers + */ +#define SPI_CLOCKDIV 0x0010 +#define SPI_MODESELECT 0x0018 +#define SPI_CONFIGDATA 0x0020 +#define SPI_STA_MODE_CHANGE 0x0028 +#define SPI_FAST_SEQ_TRANSFER_SIZE 0x0100 +#define SPI_FAST_SEQ_ADD1 0x0104 +#define SPI_FAST_SEQ_ADD2 0x0108 +#define SPI_FAST_SEQ_ADD_CFG 0x010c +#define SPI_FAST_SEQ_OPC1 0x0110 +#define SPI_FAST_SEQ_OPC2 0x0114 +#define SPI_FAST_SEQ_OPC3 0x0118 +#define SPI_FAST_SEQ_OPC4 0x011c +#define SPI_FAST_SEQ_OPC5 0x0120 +#define SPI_MODE_BITS 0x0124 +#define SPI_DUMMY_BITS 0x0128 +#define SPI_FAST_SEQ_FLASH_STA_DATA 0x012c +#define SPI_FAST_SEQ_1 0x0130 +#define SPI_FAST_SEQ_2 0x0134 +#define SPI_FAST_SEQ_3 0x0138 +#define SPI_FAST_SEQ_4 0x013c +#define SPI_FAST_SEQ_CFG 0x0140 +#define SPI_FAST_SEQ_STA 0x0144 +#define SPI_QUAD_BOOT_SEQ_INIT_1 0x0148 +#define SPI_QUAD_BOOT_SEQ_INIT_2 0x014c +#define SPI_QUAD_BOOT_READ_SEQ_1 0x0150 +#define SPI_QUAD_BOOT_READ_SEQ_2 0x0154 +#define SPI_PROGRAM_ERASE_TIME 0x0158 +#define SPI_MULT_PAGE_REPEAT_SEQ_1 0x015c +#define SPI_MULT_PAGE_REPEAT_SEQ_2 0x0160 +#define SPI_STATUS_WR_TIME_REG 0x0164 +#define SPI_FAST_SEQ_DATA_REG 0x0300 + +/* + * Register: SPI_MODESELECT + */ +#define SPI_MODESELECT_CONTIG 0x01 +#define SPI_MODESELECT_FASTREAD 0x02 +#define SPI_MODESELECT_DUALIO 0x04 +#define SPI_MODESELECT_FSM 0x08 +#define SPI_MODESELECT_QUADBOOT 0x10 + +/* + * Register: SPI_CONFIGDATA + */ +#define SPI_CFG_DEVICE_ST 0x1 +#define SPI_CFG_DEVICE_ATMEL 0x4 +#define SPI_CFG_MIN_CS_HIGH(x) (((x) & 0xfff) << 4) +#define SPI_CFG_CS_SETUPHOLD(x) (((x) & 0xff) << 16) +#define SPI_CFG_DATA_HOLD(x) (((x) & 0xff) << 24) + +/* + * Register: SPI_FAST_SEQ_TRANSFER_SIZE + */ +#define TRANSFER_SIZE(x) ((x) * 8) + +/* + * Register: SPI_FAST_SEQ_ADD_CFG + */ +#define ADR_CFG_CYCLES_ADD1(x) ((x) << 0) +#define ADR_CFG_PADS_1_ADD1 (0x0 << 6) +#define ADR_CFG_PADS_2_ADD1 (0x1 << 6) +#define ADR_CFG_PADS_4_ADD1 (0x3 << 6) +#define ADR_CFG_CSDEASSERT_ADD1 (1 << 8) +#define ADR_CFG_CYCLES_ADD2(x) ((x) << (0+16)) +#define ADR_CFG_PADS_1_ADD2 (0x0 << (6+16)) +#define ADR_CFG_PADS_2_ADD2 (0x1 << (6+16)) +#define ADR_CFG_PADS_4_ADD2 (0x3 << (6+16)) +#define ADR_CFG_CSDEASSERT_ADD2 (1 << (8+16)) + +/* + * Register: SPI_FAST_SEQ_n + */ +#define SEQ_OPC_OPCODE(x) ((x) << 0) +#define SEQ_OPC_CYCLES(x) ((x) << 8) +#define SEQ_OPC_PADS_1 (0x0 << 14) +#define SEQ_OPC_PADS_2 (0x1 << 14) +#define SEQ_OPC_PADS_4 (0x3 << 14) +#define SEQ_OPC_CSDEASSERT (1 << 16) + +/* + * Register: SPI_FAST_SEQ_CFG + */ +#define SEQ_CFG_STARTSEQ (1 << 0) +#define SEQ_CFG_SWRESET (1 << 5) +#define SEQ_CFG_CSDEASSERT (1 << 6) +#define SEQ_CFG_READNOTWRITE (1 << 7) +#define SEQ_CFG_ERASE (1 << 8) +#define SEQ_CFG_PADS_1 (0x0 << 16) +#define SEQ_CFG_PADS_2 (0x1 << 16) +#define SEQ_CFG_PADS_4 (0x3 << 16) + +/* + * Register: SPI_MODE_BITS + */ +#define MODE_DATA(x) (x & 0xff) +#define MODE_CYCLES(x) ((x & 0x3f) << 16) +#define MODE_PADS_1 (0x0 << 22) +#define MODE_PADS_2 (0x1 << 22) +#define MODE_PADS_4 (0x3 << 22) +#define DUMMY_CSDEASSERT (1 << 24) + +/* + * Register: SPI_DUMMY_BITS + */ +#define DUMMY_CYCLES(x) ((x & 0x3f) << 16) +#define DUMMY_PADS_1 (0x0 << 22) +#define DUMMY_PADS_2 (0x1 << 22) +#define DUMMY_PADS_4 (0x3 << 22) +#define DUMMY_CSDEASSERT (1 << 24) + +/* + * Register: SPI_FAST_SEQ_FLASH_STA_DATA + */ +#define STA_DATA_BYTE1(x) ((x & 0xff) << 0) +#define STA_DATA_BYTE2(x) ((x & 0xff) << 8) +#define STA_PADS_1 (0x0 << 16) +#define STA_PADS_2 (0x1 << 16) +#define STA_PADS_4 (0x3 << 16) +#define STA_CSDEASSERT (0x1 << 20) +#define STA_RDNOTWR (0x1 << 21) + +/* + * FSM SPI Instruction Opcodes + */ +#define STFSM_OPC_CMD 0x1 +#define STFSM_OPC_ADD 0x2 +#define STFSM_OPC_STA 0x3 +#define STFSM_OPC_MODE 0x4 +#define STFSM_OPC_DUMMY 0x5 +#define STFSM_OPC_DATA 0x6 +#define STFSM_OPC_WAIT 0x7 +#define STFSM_OPC_JUMP 0x8 +#define STFSM_OPC_GOTO 0x9 +#define STFSM_OPC_STOP 0xF + +/* + * FSM SPI Instructions (== opcode + operand). + */ +#define STFSM_INSTR(cmd, op) ((cmd) | ((op) << 4)) + +#define STFSM_INST_CMD1 STFSM_INSTR(STFSM_OPC_CMD, 1) +#define STFSM_INST_CMD2 STFSM_INSTR(STFSM_OPC_CMD, 2) +#define STFSM_INST_CMD3 STFSM_INSTR(STFSM_OPC_CMD, 3) +#define STFSM_INST_CMD4 STFSM_INSTR(STFSM_OPC_CMD, 4) +#define STFSM_INST_CMD5 STFSM_INSTR(STFSM_OPC_CMD, 5) +#define STFSM_INST_ADD1 STFSM_INSTR(STFSM_OPC_ADD, 1) +#define STFSM_INST_ADD2 STFSM_INSTR(STFSM_OPC_ADD, 2) + +#define STFSM_INST_DATA_WRITE STFSM_INSTR(STFSM_OPC_DATA, 1) +#define STFSM_INST_DATA_READ STFSM_INSTR(STFSM_OPC_DATA, 2) + +#define STFSM_INST_STA_RD1 STFSM_INSTR(STFSM_OPC_STA, 0x1) +#define STFSM_INST_STA_WR1 STFSM_INSTR(STFSM_OPC_STA, 0x1) +#define STFSM_INST_STA_RD2 STFSM_INSTR(STFSM_OPC_STA, 0x2) +#define STFSM_INST_STA_WR1_2 STFSM_INSTR(STFSM_OPC_STA, 0x3) + +#define STFSM_INST_MODE STFSM_INSTR(STFSM_OPC_MODE, 0) +#define STFSM_INST_DUMMY STFSM_INSTR(STFSM_OPC_DUMMY, 0) +#define STFSM_INST_WAIT STFSM_INSTR(STFSM_OPC_WAIT, 0) +#define STFSM_INST_STOP STFSM_INSTR(STFSM_OPC_STOP, 0) + +#endif /* ST_SPI_FSM_H */ -- 1.8.1.2 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-14 14:22 ` [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines Lee Jones @ 2013-11-18 9:15 ` Linus Walleij 2013-11-18 9:32 ` Lee Jones 0 siblings, 1 reply; 25+ messages in thread From: Linus Walleij @ 2013-11-18 9:15 UTC (permalink / raw) To: linux-arm-kernel On Thu, Nov 14, 2013 at 3:22 PM, Lee Jones <lee.jones@linaro.org> wrote: > Here we provide the FSM's register addresses, register bit names/offsets > and some commands which will prove useful as we start bulk the FMS's > driver out with functionality. > > Signed-off-by: Lee Jones <lee.jones@linaro.org> OK... > +/* > + * FSM SPI Controller Registers > + */ > +#define SPI_CLOCKDIV 0x0010 > +#define SPI_MODESELECT 0x0018 > +#define SPI_CONFIGDATA 0x0020 (...) So what we want to know here is whether this is a general-purpose SPI block, or if it's a special-purpose SPI block that can only be used for accessing flashes. If it's the former that part should be broken out into drivers/spi of course... But the register map seems a bit special-purpose so it could very well be that this is for flash control only. So maybe you can spill some beans from a datasheet here? A clock divider at offset 0x10 already tells us that this is probably a PL022 derivate, just that we don't know how much it has been hacked with... does this thing contain AMBA identifiers at the end of the IO-region, usually at 0x0fe0 thru 0x0fff? Yours, Linus Walleij ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 9:15 ` Linus Walleij @ 2013-11-18 9:32 ` Lee Jones 2013-11-18 13:39 ` Mark Brown 0 siblings, 1 reply; 25+ messages in thread From: Lee Jones @ 2013-11-18 9:32 UTC (permalink / raw) To: linux-arm-kernel On Mon, 18 Nov 2013, Linus Walleij wrote: > On Thu, Nov 14, 2013 at 3:22 PM, Lee Jones <lee.jones@linaro.org> wrote: > > > Here we provide the FSM's register addresses, register bit names/offsets > > and some commands which will prove useful as we start bulk the FMS's > > driver out with functionality. > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org> > > OK... > > > +/* > > + * FSM SPI Controller Registers > > + */ > > +#define SPI_CLOCKDIV 0x0010 > > +#define SPI_MODESELECT 0x0018 > > +#define SPI_CONFIGDATA 0x0020 > (...) > > So what we want to know here is whether this is a general-purpose > SPI block, or if it's a special-purpose SPI block that can only be > used for accessing flashes. > > If it's the former that part should be broken out into drivers/spi > of course... > > But the register map seems a bit special-purpose so it could > very well be that this is for flash control only. So maybe you can > spill some beans from a datasheet here? > > A clock divider at offset 0x10 already tells us that this is probably > a PL022 derivate, just that we don't know how much it has > been hacked with... does this thing contain AMBA identifiers > at the end of the IO-region, usually at 0x0fe0 thru 0x0fff? You've just opened a massive can of worms. Let me try to catch and put them all back as quickly as possible. The FSM Controller is a derivative of an SPI controller, but it's so highly specialised that it can't do anything else but talk to Serial Flash devices. I've actually travelled down the route of separating the SPI Controller parts to drivers/spi. It's possible to do that and perhaps we could then use the generic m25p80 Serial Flash driver as the back-end, but it would be incredibly complicated and would mean we'd need to duplicate almost all of the m25p80 driver into the SPI Controller. The Falcon SPI driver tried to do something similar, but now looks broken due to some incompatible changes in m25p80. We also want to avoid putting ourselves in that position of fragility. There are a list of other reasons why this wouldn't work well. I have asked the original author of this driver (whom I've spent quite a few hours in face-to-face meetings with over the past couple of weeks) to jot them all down so I can reply to these kinds of requests, but I just don't have it yet. Take my word for it for now and I'll get back to you when I can. -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org ? Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 9:32 ` Lee Jones @ 2013-11-18 13:39 ` Mark Brown 2013-11-18 14:24 ` Lee Jones 0 siblings, 1 reply; 25+ messages in thread From: Mark Brown @ 2013-11-18 13:39 UTC (permalink / raw) To: linux-arm-kernel On Mon, Nov 18, 2013 at 09:32:29AM +0000, Lee Jones wrote: > I've actually travelled down the route of separating the SPI > Controller parts to drivers/spi. It's possible to do that and perhaps > we could then use the generic m25p80 Serial Flash driver as the > back-end, but it would be incredibly complicated and would mean we'd > need to duplicate almost all of the m25p80 driver into the SPI > Controller. The Falcon SPI driver tried to do something similar, but > now looks broken due to some incompatible changes in m25p80. We also > want to avoid putting ourselves in that position of fragility. What I've said to people doing similar drivers before is that it seems like there should be an abstraction added in the MTD framework for SPI flash controllers like this is that if there is genunie flash-specific stuff going on then the mp25p80 driver ought to be split so that the code that understands what commands to send to the flash chip is split out from the code that actually sends those commands to the chip. The existing SPI support would then be a function driver for this. This would mean we don't need to support the flash chips multiple times. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131118/d3234a26/attachment.sig> ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 13:39 ` Mark Brown @ 2013-11-18 14:24 ` Lee Jones 2013-11-18 14:45 ` Mark Brown 0 siblings, 1 reply; 25+ messages in thread From: Lee Jones @ 2013-11-18 14:24 UTC (permalink / raw) To: linux-arm-kernel On Mon, 18 Nov 2013, Mark Brown wrote: > On Mon, Nov 18, 2013 at 09:32:29AM +0000, Lee Jones wrote: > > > I've actually travelled down the route of separating the SPI > > Controller parts to drivers/spi. It's possible to do that and perhaps > > we could then use the generic m25p80 Serial Flash driver as the > > back-end, but it would be incredibly complicated and would mean we'd > > need to duplicate almost all of the m25p80 driver into the SPI > > Controller. The Falcon SPI driver tried to do something similar, but > > now looks broken due to some incompatible changes in m25p80. We also > > want to avoid putting ourselves in that position of fragility. > > What I've said to people doing similar drivers before is that it seems > like there should be an abstraction added in the MTD framework for SPI > flash controllers like this is that if there is genunie flash-specific > stuff going on then the mp25p80 driver ought to be split so that the > code that understands what commands to send to the flash chip is split > out from the code that actually sends those commands to the chip. The > existing SPI support would then be a function driver for this. This > would mean we don't need to support the flash chips multiple times. Actually, there isn't much duplication. We reuse a subset of the device table, but even that is extended for our use-case. The majority of the code is setting up the register configs for every given operation we issue on the controller. There are some parts which 'could' be bent in such a way that they could be abstracted, but not much. For example, we have thought about inserting a layer which handles the type of communication that'll be utilised i.e. true SPI, or our bespoke FSM implementation for instance. This would enable us to issue serial_flash_write(), serial_flash_write_then_read(), ... in the m25p80 driver and not care which protocol is used. However, in reality this won't really save a great deal of code - not in our case at least. -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org ? Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 14:24 ` Lee Jones @ 2013-11-18 14:45 ` Mark Brown 2013-11-18 14:56 ` Lee Jones 0 siblings, 1 reply; 25+ messages in thread From: Mark Brown @ 2013-11-18 14:45 UTC (permalink / raw) To: linux-arm-kernel On Mon, Nov 18, 2013 at 02:24:47PM +0000, Lee Jones wrote: > For example, we have thought about inserting a layer which handles the > type of communication that'll be utilised i.e. true SPI, or our > bespoke FSM implementation for instance. This would enable us to issue > serial_flash_write(), serial_flash_write_then_read(), ... in the m25p80 > driver and not care which protocol is used. However, in reality this > won't really save a great deal of code - not in our case at least. Right, that's what I'm suggesting. It's not so much for the code saving as for the data saving, allowing device trees that just say "flash chip X is connected" rather than requiring either the flash chip information in multiple places in the kernel or (worse) have the commands added to the DTs of individual boards using the flash chip. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131118/f8f71139/attachment.sig> ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 14:45 ` Mark Brown @ 2013-11-18 14:56 ` Lee Jones 2013-11-18 15:16 ` Mark Brown 0 siblings, 1 reply; 25+ messages in thread From: Lee Jones @ 2013-11-18 14:56 UTC (permalink / raw) To: linux-arm-kernel On Mon, 18 Nov 2013, Mark Brown wrote: > On Mon, Nov 18, 2013 at 02:24:47PM +0000, Lee Jones wrote: > > > For example, we have thought about inserting a layer which handles the > > type of communication that'll be utilised i.e. true SPI, or our > > bespoke FSM implementation for instance. This would enable us to issue > > serial_flash_write(), serial_flash_write_then_read(), ... in the m25p80 > > driver and not care which protocol is used. However, in reality this > > won't really save a great deal of code - not in our case at least. > > Right, that's what I'm suggesting. It's not so much for the code saving > as for the data saving, allowing device trees that just say "flash chip > X is connected" rather than requiring either the flash chip information > in multiple places in the kernel or (worse) have the commands added to > the DTs of individual boards using the flash chip. I think it's a good idea for people using the m25p80, but still doesn't effect us. All of our chips are dynamically probable. We are moving completely away from saying anything is connected using DT or platform data. The FSM will be registered and will dynamically add devices based on what it can find. We have no plans to use any of the m25p80 functionality, as it's almost completely different. I'm keen on the reuse of frameworks and abstracting common code, but there just isn't any in our case. -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org ? Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 14:56 ` Lee Jones @ 2013-11-18 15:16 ` Mark Brown 2013-11-18 15:31 ` Lee Jones 0 siblings, 1 reply; 25+ messages in thread From: Mark Brown @ 2013-11-18 15:16 UTC (permalink / raw) To: linux-arm-kernel On Mon, Nov 18, 2013 at 02:56:14PM +0000, Lee Jones wrote: > I think it's a good idea for people using the m25p80, but still > doesn't effect us. All of our chips are dynamically probable. We are This doesn't seem realistic, you're assuming that system integrators won't go and use chips you've not heard of and at least in the case of things like quad read my understanding is that the commands aren't standardised so the host just has to know what to write. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131118/e8fe7650/attachment.sig> ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 15:16 ` Mark Brown @ 2013-11-18 15:31 ` Lee Jones 2013-11-18 15:41 ` Mark Brown 0 siblings, 1 reply; 25+ messages in thread From: Lee Jones @ 2013-11-18 15:31 UTC (permalink / raw) To: linux-arm-kernel On Mon, 18 Nov 2013, Mark Brown wrote: > On Mon, Nov 18, 2013 at 02:56:14PM +0000, Lee Jones wrote: > > > I think it's a good idea for people using the m25p80, but still > > doesn't effect us. All of our chips are dynamically probable. We are > > This doesn't seem realistic, you're assuming that system integrators > won't go and use chips you've not heard of and at least in the case of > things like quad read my understanding is that the commands aren't > standardised so the host just has to know what to write. I'm not following? What are you suggesting? After some analysis we have come to the conclusion that using m25p80 is not feasible. It makes more sense for this to be an orthogonal/stand-alone driver. -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org ? Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 15:31 ` Lee Jones @ 2013-11-18 15:41 ` Mark Brown 2013-11-18 16:02 ` Lee Jones 0 siblings, 1 reply; 25+ messages in thread From: Mark Brown @ 2013-11-18 15:41 UTC (permalink / raw) To: linux-arm-kernel On Mon, Nov 18, 2013 at 03:31:10PM +0000, Lee Jones wrote: > On Mon, 18 Nov 2013, Mark Brown wrote: > > This doesn't seem realistic, you're assuming that system integrators > > won't go and use chips you've not heard of and at least in the case of > > things like quad read my understanding is that the commands aren't > > standardised so the host just has to know what to write. > I'm not following? What are you suggesting? Like I say I'm suggesting that the bit of the code that understands the flash chip is separate to the bit of code that knows the mechanics of sending commands and data to the chip. > After some analysis we have come to the conclusion that using m25p80 > is not feasible. It makes more sense for this to be an > orthogonal/stand-alone driver. That seems plausible for the controller side but it seems surprising for the flash chip side. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131118/d4aaa61c/attachment-0001.sig> ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 15:41 ` Mark Brown @ 2013-11-18 16:02 ` Lee Jones 2013-11-18 17:22 ` Mark Brown 0 siblings, 1 reply; 25+ messages in thread From: Lee Jones @ 2013-11-18 16:02 UTC (permalink / raw) To: linux-arm-kernel On Mon, 18 Nov 2013, Mark Brown wrote: > On Mon, Nov 18, 2013 at 03:31:10PM +0000, Lee Jones wrote: > > On Mon, 18 Nov 2013, Mark Brown wrote: > > > > This doesn't seem realistic, you're assuming that system integrators > > > won't go and use chips you've not heard of and at least in the case of > > > things like quad read my understanding is that the commands aren't > > > standardised so the host just has to know what to write. > > > I'm not following? What are you suggesting? > > Like I say I'm suggesting that the bit of the code that understands the > flash chip is separate to the bit of code that knows the mechanics of > sending commands and data to the chip. > > > After some analysis we have come to the conclusion that using m25p80 > > is not feasible. It makes more sense for this to be an > > orthogonal/stand-alone driver. > > That seems plausible for the controller side but it seems surprising for > the flash chip side. The issue is that almost the entire driver is controller side. The only bits that are the same (and not in all cases) are the OPCODEs, but they are one liners (21 lines out of 1153). Most of the controllers which use this stuff could reuse quite a bit of the m25p80 driver as they just write the message containing the OPCODE as the m25p80 driver sets it up, but that's simply not the case with our controller. We would have to pull the OPCODE out and based on which one it is, we'd have to build our own message. Put it this way, if we tried to use the m25p80 our controller driver would most likely be twice as large and twice as complex as it is currently, which is exactly the inverse of what we're trying to achieve here. -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org ? Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 16:02 ` Lee Jones @ 2013-11-18 17:22 ` Mark Brown 2013-11-18 17:32 ` Lee Jones 0 siblings, 1 reply; 25+ messages in thread From: Mark Brown @ 2013-11-18 17:22 UTC (permalink / raw) To: linux-arm-kernel On Mon, Nov 18, 2013 at 04:02:26PM +0000, Lee Jones wrote: > On Mon, 18 Nov 2013, Mark Brown wrote: > > Like I say I'm suggesting that the bit of the code that understands the > > flash chip is separate to the bit of code that knows the mechanics of > > sending commands and data to the chip. > The issue is that almost the entire driver is controller side. The > only bits that are the same (and not in all cases) are the OPCODEs, > but they are one liners (21 lines out of 1153). Most of the > controllers which use this stuff could reuse quite a bit of the m25p80 > driver as they just write the message containing the OPCODE as the > m25p80 driver sets it up, but that's simply not the case with our > controller. We would have to pull the OPCODE out and based on which > one it is, we'd have to build our own message. OK, so then perhaps the abstraction here is simply to export the table with the opcodes from the m25p80 driver so that when someone comes along and adds a new chip they can just add it there and other drivers will get the update too. > Put it this way, if we tried to use the m25p80 our controller driver > would most likely be twice as large and twice as complex as it is > currently, which is exactly the inverse of what we're trying to > achieve here. If we're having to add new flashes to multiple drivers I'd not say we're winning. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131118/36fe5722/attachment.sig> ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 17:22 ` Mark Brown @ 2013-11-18 17:32 ` Lee Jones 2013-11-18 17:59 ` Sourav Poddar 2013-11-18 18:35 ` Mark Brown 0 siblings, 2 replies; 25+ messages in thread From: Lee Jones @ 2013-11-18 17:32 UTC (permalink / raw) To: linux-arm-kernel On Mon, 18 Nov 2013, Mark Brown wrote: > On Mon, Nov 18, 2013 at 04:02:26PM +0000, Lee Jones wrote: > > On Mon, 18 Nov 2013, Mark Brown wrote: > > > > Like I say I'm suggesting that the bit of the code that understands the > > > flash chip is separate to the bit of code that knows the mechanics of > > > sending commands and data to the chip. > > > The issue is that almost the entire driver is controller side. The > > only bits that are the same (and not in all cases) are the OPCODEs, > > but they are one liners (21 lines out of 1153). Most of the > > controllers which use this stuff could reuse quite a bit of the m25p80 > > driver as they just write the message containing the OPCODE as the > > m25p80 driver sets it up, but that's simply not the case with our > > controller. We would have to pull the OPCODE out and based on which > > one it is, we'd have to build our own message. > > OK, so then perhaps the abstraction here is simply to export the table > with the opcodes from the m25p80 driver so that when someone comes along > and adds a new chip they can just add it there and other drivers will > get the update too. We could do that, although I'd have to insist on extending the current framework to add a configuration call-back, as it's the neatest way to configure chip specific attributes. I can get a patch out tomorrow if the MTD guys agree. Where are they by the way? I haven't seen hide nor hair of them since sending out the patch set. > > Put it this way, if we tried to use the m25p80 our controller driver > > would most likely be twice as large and twice as complex as it is > > currently, which is exactly the inverse of what we're trying to > > achieve here. > > If we're having to add new flashes to multiple drivers I'd not say we're > winning. I agree. -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org ? Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 17:32 ` Lee Jones @ 2013-11-18 17:59 ` Sourav Poddar 2013-11-18 18:35 ` Mark Brown 1 sibling, 0 replies; 25+ messages in thread From: Sourav Poddar @ 2013-11-18 17:59 UTC (permalink / raw) To: linux-arm-kernel On Monday 18 November 2013 11:02 PM, Lee Jones wrote: > On Mon, 18 Nov 2013, Mark Brown wrote: > >> On Mon, Nov 18, 2013 at 04:02:26PM +0000, Lee Jones wrote: >>> On Mon, 18 Nov 2013, Mark Brown wrote: >>>> Like I say I'm suggesting that the bit of the code that understands the >>>> flash chip is separate to the bit of code that knows the mechanics of >>>> sending commands and data to the chip. >>> The issue is that almost the entire driver is controller side. The >>> only bits that are the same (and not in all cases) are the OPCODEs, >>> but they are one liners (21 lines out of 1153). Most of the >>> controllers which use this stuff could reuse quite a bit of the m25p80 >>> driver as they just write the message containing the OPCODE as the >>> m25p80 driver sets it up, but that's simply not the case with our >>> controller. We would have to pull the OPCODE out and based on which >>> one it is, we'd have to build our own message. >> OK, so then perhaps the abstraction here is simply to export the table >> with the opcodes from the m25p80 driver so that when someone comes along >> and adds a new chip they can just add it there and other drivers will >> get the update too. > We could do that, although I'd have to insist on extending the current > framework to add a configuration call-back, as it's the neatest way to > configure chip specific attributes. > This looks like the problem which some other controllers(from ti, freescale) are facing. I will just summarise the problem with the ti qspi flash controller which I am working on. There is a set of registers which need to be filled with flash specific commands. One way to deal it with to provide a device tree bindings for all the requirements(which is really cumbersome.). Similarly, for freescale there is a LUT registers which has such flash requirements. So, surely we need a way out from m25p80 driver to handle such cases. drivers/mtd/devices/m25p80.c int pass_flash_info () { u8 info[6]; info[0] = DUMMY WR; info[1] = RD_OPCODE; info[2] - DUMMY BITS; ...... ....... spi_write(flash, info, 6) } Then, somehow parse this information to set up the required info. This is just a rough idea, and can be implemented in a better way. > I can get a patch out tomorrow if the MTD guys agree. Where are they > by the way? I haven't seen hide nor hair of them since sending out the > patch set. > >>> Put it this way, if we tried to use the m25p80 our controller driver >>> would most likely be twice as large and twice as complex as it is >>> currently, which is exactly the inverse of what we're trying to >>> achieve here. >> If we're having to add new flashes to multiple drivers I'd not say we're >> winning. > I agree. > ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines 2013-11-18 17:32 ` Lee Jones 2013-11-18 17:59 ` Sourav Poddar @ 2013-11-18 18:35 ` Mark Brown 1 sibling, 0 replies; 25+ messages in thread From: Mark Brown @ 2013-11-18 18:35 UTC (permalink / raw) To: linux-arm-kernel On Mon, Nov 18, 2013 at 05:32:01PM +0000, Lee Jones wrote: > I can get a patch out tomorrow if the MTD guys agree. Where are they > by the way? I haven't seen hide nor hair of them since sending out the > patch set. They tend to do big batches of things intermittently AFAICT. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131118/4f0e1779/attachment-0001.sig> ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 03/10] mtd: st_spi_fsm: Initialise and configure the FSM for normal working conditions 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones 2013-11-14 14:22 ` [PATCH 01/10] mtd: st_spi_fsm: Allocate resources and register with MTD framework Lee Jones 2013-11-14 14:22 ` [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines Lee Jones @ 2013-11-14 14:22 ` Lee Jones 2013-11-14 14:22 ` [PATCH 04/10] mtd: st_spi_fsm: Supply framework for device requests Lee Jones ` (6 subsequent siblings) 9 siblings, 0 replies; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel This patch uses default values to initialise a connected flash chip. This includes; a device soft reset, setting of a safe working frequency, a switch into Fast Sequencing Mode, configuring of timing data and a purge of the FIFO. Signed-off-by: Lee Jones <lee.jones@linaro.org> --- drivers/mtd/devices/st_spi_fsm.c | 123 +++++++++++++++++++++++++++++++++++++++ drivers/mtd/devices/st_spi_fsm.h | 4 ++ 2 files changed, 127 insertions(+) diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 689f059..f560343 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -25,19 +25,136 @@ #include "st_spi_fsm.h" +#define STFSM_DEFAULT_EMI_FREQ 100000000UL /* 100 MHz */ +#define STFSM_DEFAULT_WR_TIME STFSM_DEFAULT_EMI_FREQ * (15/1000) /* 15ms */ + +#define FLASH_SAFE_FREQ 10000000UL /* 10 MHz */ + struct stfsm { struct device *dev; void __iomem *base; struct resource *region; struct mtd_info mtd; struct mutex lock; + + uint32_t fifo_dir_delay; }; +static inline uint32_t stfsm_fifo_available(struct stfsm *fsm) +{ + return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f; +} + +static void stfsm_clear_fifo(struct stfsm *fsm) +{ + uint32_t avail; + + for (;;) { + avail = stfsm_fifo_available(fsm); + if (!avail) + break; + + while (avail) { + readl(fsm->base + SPI_FAST_SEQ_DATA_REG); + avail--; + } + } +} + +static int stfsm_set_mode(struct stfsm *fsm, uint32_t mode) +{ + int ret, timeout = 10; + + /* Wait for controller to accept mode change */ + while(--timeout) { + ret = readl(fsm->base + SPI_STA_MODE_CHANGE); + if (ret & 0x1) + break; + udelay(1); + } + + if (!timeout) + return -EBUSY; + + writel(mode, fsm->base + SPI_MODESELECT); + + return 0; +} + +static void stfsm_set_freq(struct stfsm *fsm, uint32_t spi_freq) +{ + uint32_t emi_freq; + uint32_t clk_div; + + /* TODO: Make this dynamic */ + emi_freq = STFSM_DEFAULT_EMI_FREQ; + + /* + * Calculate clk_div - values between 2 and 128 + * Multiple of 2, rounded up + */ + clk_div = 2*((emi_freq + (2*spi_freq - 1))/(2*spi_freq)); + if (clk_div < 2) + clk_div = 2; + else if (clk_div > 128) + clk_div = 128; + + /* + * Determine a suitable delay for the IP to complete a change of + * direction of the FIFO. The required delay is related to the clock + * divider used. The following heuristics are based on empirical tests, + * using a 100MHz EMI clock. + */ + if (clk_div <= 4) + fsm->fifo_dir_delay = 0; + else if (clk_div <= 10) + fsm->fifo_dir_delay = 1; + else + fsm->fifo_dir_delay = (clk_div + 9) / 10; + + dev_dbg(fsm->dev, "emi_clk = %uHZ, spi_freq = %uHZ, clk_div = %u\n", + emi_freq, spi_freq, clk_div); + + writel(clk_div, fsm->base + SPI_CLOCKDIV); +} + +static int stfsm_init(struct stfsm *fsm) +{ + int ret; + + /* Perform a soft reset of the FSM controller */ + writel(SEQ_CFG_SWRESET, fsm->base + SPI_FAST_SEQ_CFG); + udelay(1); + writel(0, fsm->base + SPI_FAST_SEQ_CFG); + + /* Set clock to 'safe' frequency initially */ + stfsm_set_freq(fsm, FLASH_SAFE_FREQ); + + /* Switch to FSM */ + ret = stfsm_set_mode(fsm, SPI_MODESELECT_FSM); + if (ret) + return ret; + + /* Set timing parameters */ + writel(SPI_CFG_DEVICE_ST | + SPI_CFG_DEFAULT_MIN_CS_HIGH | + SPI_CFG_DEFAULT_CS_SETUPHOLD | + SPI_CFG_DEFAULT_DATA_HOLD, + fsm->base + SPI_CONFIGDATA); + writel(STFSM_DEFAULT_WR_TIME, fsm->base + SPI_STATUS_WR_TIME_REG); + + /* Clear FIFO, just in case */ + stfsm_clear_fifo(fsm); + + return 0; +} + static int stfsm_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct resource *res; struct stfsm *fsm; + int ret; if (!np) { dev_err(&pdev->dev, "No DT found\n"); @@ -74,6 +191,12 @@ static int stfsm_probe(struct platform_device *pdev) mutex_init(&fsm->lock); + ret = stfsm_init(fsm); + if (ret) { + dev_err(&pdev->dev, "Failed to initialise FSM Controller\n"); + return ret; + } + platform_set_drvdata(pdev, fsm); fsm->mtd.dev.parent = &pdev->dev; diff --git a/drivers/mtd/devices/st_spi_fsm.h b/drivers/mtd/devices/st_spi_fsm.h index 11ca33a..7a8f1eb 100644 --- a/drivers/mtd/devices/st_spi_fsm.h +++ b/drivers/mtd/devices/st_spi_fsm.h @@ -69,6 +69,10 @@ #define SPI_CFG_CS_SETUPHOLD(x) (((x) & 0xff) << 16) #define SPI_CFG_DATA_HOLD(x) (((x) & 0xff) << 24) +#define SPI_CFG_DEFAULT_MIN_CS_HIGH SPI_CFG_MIN_CS_HIGH(0x0AA) +#define SPI_CFG_DEFAULT_CS_SETUPHOLD SPI_CFG_CS_SETUPHOLD(0xA0) +#define SPI_CFG_DEFAULT_DATA_HOLD SPI_CFG_DATA_HOLD(0x00) + /* * Register: SPI_FAST_SEQ_TRANSFER_SIZE */ -- 1.8.1.2 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 04/10] mtd: st_spi_fsm: Supply framework for device requests 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones ` (2 preceding siblings ...) 2013-11-14 14:22 ` [PATCH 03/10] mtd: st_spi_fsm: Initialise and configure the FSM for normal working conditions Lee Jones @ 2013-11-14 14:22 ` Lee Jones 2013-11-14 14:22 ` [PATCH 05/10] mtd: st_spi_fsm: Supply a method to read from the FSM's FIFO Lee Jones ` (5 subsequent siblings) 9 siblings, 0 replies; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel The FSM hardware works by setting a predetermined sequence of register writes. Rather than open coding them inside each functional block we're going to define them in a series of formatted 'sequence structures'. This patch provides the framework which shall be used for every action. Signed-off-by: Lee Jones <lee.jones@linaro.org> --- drivers/mtd/devices/st_spi_fsm.c | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index f560343..02619ee 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -40,11 +40,60 @@ struct stfsm { uint32_t fifo_dir_delay; }; +struct stfsm_seq { + uint32_t data_size; + uint32_t addr1; + uint32_t addr2; + uint32_t addr_cfg; + uint32_t seq_opc[5]; + uint32_t mode; + uint32_t dummy; + uint32_t status; + uint8_t seq[16]; + uint32_t seq_cfg; +} __attribute__((__packed__, aligned(4))); +#define STFSM_SEQ_SIZE sizeof(struct stfsm_seq) + +static inline int stfsm_is_idle(struct stfsm *fsm) +{ + return readl(fsm->base + SPI_FAST_SEQ_STA) & 0x10; +} + static inline uint32_t stfsm_fifo_available(struct stfsm *fsm) { return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f; } +static inline void stfsm_load_seq(struct stfsm *fsm, + const struct stfsm_seq *seq) +{ + void __iomem *dst = fsm->base + SPI_FAST_SEQ_TRANSFER_SIZE; + const uint32_t *src = (const uint32_t *)seq; + int words = STFSM_SEQ_SIZE / sizeof(uint32_t); + + BUG_ON(!stfsm_is_idle(fsm)); + + while (words--) { + writel(*src, dst); + src++; + dst += 4; + } +} + +static void stfsm_wait_seq(struct stfsm *fsm) +{ + unsigned long timeo = jiffies + HZ; + + while (time_before(jiffies, timeo)) { + if (stfsm_is_idle(fsm)) + return; + + cond_resched(); + } + + dev_err(fsm->dev, "timeout on sequence completion\n"); +} + static void stfsm_clear_fifo(struct stfsm *fsm) { uint32_t avail; -- 1.8.1.2 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 05/10] mtd: st_spi_fsm: Supply a method to read from the FSM's FIFO 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones ` (3 preceding siblings ...) 2013-11-14 14:22 ` [PATCH 04/10] mtd: st_spi_fsm: Supply framework for device requests Lee Jones @ 2013-11-14 14:22 ` Lee Jones 2013-11-14 14:22 ` [PATCH 06/10] mtd: st_spi_fsm: Supply defines for the possible flash command opcodes Lee Jones ` (4 subsequent siblings) 9 siblings, 0 replies; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel When invoked the driver will attempt to read any available data from the FSM's data register. Any data collected from this FIFO would have originated from the flash chip. Signed-off-by: Lee Jones <lee.jones@linaro.org> --- drivers/mtd/devices/st_spi_fsm.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 02619ee..a1c2857 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -94,6 +94,32 @@ static void stfsm_wait_seq(struct stfsm *fsm) dev_err(fsm->dev, "timeout on sequence completion\n"); } +static void stfsm_read_fifo(struct stfsm *fsm, uint32_t *buf, + const uint32_t size) +{ + uint32_t remaining = size >> 2; + uint32_t avail; + uint32_t words; + + dev_dbg(fsm->dev, "Reading %d bytes from FIFO\n", size); + + BUG_ON((((uint32_t)buf) & 0x3) || (size & 0x3)); + + while (remaining) { + for (;;) { + avail = stfsm_fifo_available(fsm); + if (avail) + break; + udelay(1); + } + words = min(avail, remaining); + remaining -= words; + + readsl(fsm->base + SPI_FAST_SEQ_DATA_REG, buf, words); + buf += words; + } +} + static void stfsm_clear_fifo(struct stfsm *fsm) { uint32_t avail; -- 1.8.1.2 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 06/10] mtd: st_spi_fsm: Supply defines for the possible flash command opcodes 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones ` (4 preceding siblings ...) 2013-11-14 14:22 ` [PATCH 05/10] mtd: st_spi_fsm: Supply a method to read from the FSM's FIFO Lee Jones @ 2013-11-14 14:22 ` Lee Jones 2013-11-14 14:22 ` [PATCH 07/10] mtd: st_spi_fsm: Add support for JEDEC ID extraction Lee Jones ` (3 subsequent siblings) 9 siblings, 0 replies; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel Flash chip commands are issued using a set of predefined opcodes. These are mostly the same for all flash devices, but do differ on occasion. This patch supplies the majority of the key ones which will be used in this driver. Signed-off-by: Lee Jones <lee.jones@linaro.org> --- drivers/mtd/devices/st_spi_fsm.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index a1c2857..6691eaf 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -30,6 +30,44 @@ #define FLASH_SAFE_FREQ 10000000UL /* 10 MHz */ +/* Flash Commands */ +#define FLASH_CMD_WREN 0x06 +#define FLASH_CMD_WRDI 0x04 +#define FLASH_CMD_RDID 0x9f +#define FLASH_CMD_RDSR 0x05 +#define FLASH_CMD_RDSR2 0x35 +#define FLASH_CMD_WRSR 0x01 +#define FLASH_CMD_SE_4K 0x20 +#define FLASH_CMD_SE_32K 0x52 +#define FLASH_CMD_SE 0xd8 +#define FLASH_CMD_CHIPERASE 0xc7 +#define FLASH_CMD_WRVCR 0x81 +#define FLASH_CMD_RDVCR 0x85 + +#define FLASH_CMD_READ 0x03 /* READ */ +#define FLASH_CMD_READ_FAST 0x0b /* FAST READ */ +#define FLASH_CMD_READ_1_1_2 0x3b /* DUAL OUTPUT READ */ +#define FLASH_CMD_READ_1_2_2 0xbb /* DUAL I/O READ */ +#define FLASH_CMD_READ_1_1_4 0x6b /* QUAD OUTPUT READ */ +#define FLASH_CMD_READ_1_4_4 0xeb /* QUAD I/O READ */ + +#define FLASH_CMD_WRITE 0x02 /* PAGE PROGRAM */ +#define FLASH_CMD_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */ +#define FLASH_CMD_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */ +#define FLASH_CMD_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */ +#define FLASH_CMD_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */ + +#define FLASH_CMD_EN4B_ADDR 0xb7 /* Enter 4-byte address mode */ +#define FLASH_CMD_EX4B_ADDR 0xe9 /* Exit 4-byte address mode */ + +/* READ commands with 32-bit addressing (N25Q256 and S25FLxxxS) */ +#define FLASH_CMD_READ4 0x13 +#define FLASH_CMD_READ4_FAST 0x0c +#define FLASH_CMD_READ4_1_1_2 0x3c +#define FLASH_CMD_READ4_1_2_2 0xbc +#define FLASH_CMD_READ4_1_1_4 0x6c +#define FLASH_CMD_READ4_1_4_4 0xec + struct stfsm { struct device *dev; void __iomem *base; -- 1.8.1.2 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 07/10] mtd: st_spi_fsm: Add support for JEDEC ID extraction 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones ` (5 preceding siblings ...) 2013-11-14 14:22 ` [PATCH 06/10] mtd: st_spi_fsm: Supply defines for the possible flash command opcodes Lee Jones @ 2013-11-14 14:22 ` Lee Jones 2013-11-14 14:22 ` [PATCH 08/10] mtd: st_spi_fsm: Provide device look-up table Lee Jones ` (2 subsequent siblings) 9 siblings, 0 replies; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel Once we start supporting devices it will be handy go detect them dynamically. This will be done using the chip's unique JEDEC ID. This patch allows us to extract a device's JEDEC ID using the a predefined FSM register write sequence. Signed-off-by: Lee Jones <lee.jones@linaro.org> --- drivers/mtd/devices/st_spi_fsm.c | 63 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 6691eaf..2899e0f 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -92,6 +92,22 @@ struct stfsm_seq { } __attribute__((__packed__, aligned(4))); #define STFSM_SEQ_SIZE sizeof(struct stfsm_seq) +static struct stfsm_seq stfsm_seq_read_jedec = { + .data_size = TRANSFER_SIZE(8), + .seq_opc[0] = (SEQ_OPC_PADS_1 | + SEQ_OPC_CYCLES(8) | + SEQ_OPC_OPCODE(FLASH_CMD_RDID)), + .seq = { + STFSM_INST_CMD1, + STFSM_INST_DATA_READ, + STFSM_INST_STOP, + }, + .seq_cfg = (SEQ_CFG_PADS_1 | + SEQ_CFG_READNOTWRITE | + SEQ_CFG_CSDEASSERT | + SEQ_CFG_STARTSEQ), +}; + static inline int stfsm_is_idle(struct stfsm *fsm) { return readl(fsm->base + SPI_FAST_SEQ_STA) & 0x10; @@ -158,6 +174,50 @@ static void stfsm_read_fifo(struct stfsm *fsm, uint32_t *buf, } } +static int stfsm_read_jedec(struct stfsm *fsm, uint8_t *const jedec) +{ + const struct stfsm_seq *seq = &stfsm_seq_read_jedec; + uint32_t tmp[2]; + + stfsm_load_seq(fsm, seq); + + stfsm_read_fifo(fsm, tmp, 8); + + memcpy(jedec, tmp, 5); + + stfsm_wait_seq(fsm); + + return 0; +} + +static struct flash_info * stfsm_jedec_probe(struct stfsm *fsm) +{ + u16 ext_jedec; + u32 jedec; + u8 id[5]; + int ret; + + /* + * JEDEC also defines an optional "extended device information" + * string for after vendor-specific data, after the three bytes + * we use here. Supporting some chips might require using it. + */ + + ret = stfsm_read_jedec(fsm, id); + if (ret) { + dev_info(fsm->dev, "Error reading JEDEC ID\n"); + return NULL; + } + + jedec = id[0] << 16 | id[1] << 8 | id[2]; + ext_jedec = id[3] << 8 | id[4]; + + dev_dbg(fsm->dev, "JEDEC = 0x%08x [%02x %02x %02x %02x %02x]\n", + jedec, id[0], id[1], id[2], id[3], id[4]); + + return NULL; +} + static void stfsm_clear_fifo(struct stfsm *fsm) { uint32_t avail; @@ -310,6 +370,9 @@ static int stfsm_probe(struct platform_device *pdev) return ret; } + /* Detect SPI FLASH device */ + stfsm_jedec_probe(fsm); + platform_set_drvdata(pdev, fsm); fsm->mtd.dev.parent = &pdev->dev; -- 1.8.1.2 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 08/10] mtd: st_spi_fsm: Provide device look-up table 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones ` (6 preceding siblings ...) 2013-11-14 14:22 ` [PATCH 07/10] mtd: st_spi_fsm: Add support for JEDEC ID extraction Lee Jones @ 2013-11-14 14:22 ` Lee Jones 2013-11-14 14:22 ` [PATCH 09/10] mtd: st_spi_fsm: Dynamically setup flash device based on JEDEC ID Lee Jones 2013-11-14 14:22 ` [PATCH 10/10] ARM: STi: Add support for the FSM Serial Flash Controller Lee Jones 9 siblings, 0 replies; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel Supply a lookup table of all the devices we intend to support. This table is used to store device information such as; a human readable device name, their JEDEC ID (plus the extended version), sector size and amount, a bit store of a device's capabilities, its maximum running frequency and possible use of a per-device configuration call-back. Signed-off-by: Lee Jones <lee.jones@linaro.org> --- drivers/mtd/devices/st_spi_fsm.c | 165 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 2899e0f..230024c 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -68,6 +68,33 @@ #define FLASH_CMD_READ4_1_1_4 0x6c #define FLASH_CMD_READ4_1_4_4 0xec +/* Capabilities */ +#define FLASH_CAPS_SINGLE 0x000000ff +#define FLASH_CAPS_READ_WRITE 0x00000001 +#define FLASH_CAPS_READ_FAST 0x00000002 +#define FLASH_CAPS_SE_4K 0x00000004 +#define FLASH_CAPS_SE_32K 0x00000008 +#define FLASH_CAPS_CE 0x00000010 +#define FLASH_CAPS_32BITADDR 0x00000020 +#define FLASH_CAPS_RESET 0x00000040 +#define FLASH_CAPS_DYB_LOCKING 0x00000080 + +#define FLASH_CAPS_DUAL 0x0000ff00 +#define FLASH_CAPS_READ_1_1_2 0x00000100 +#define FLASH_CAPS_READ_1_2_2 0x00000200 +#define FLASH_CAPS_READ_2_2_2 0x00000400 +#define FLASH_CAPS_WRITE_1_1_2 0x00001000 +#define FLASH_CAPS_WRITE_1_2_2 0x00002000 +#define FLASH_CAPS_WRITE_2_2_2 0x00004000 + +#define FLASH_CAPS_QUAD 0x00ff0000 +#define FLASH_CAPS_READ_1_1_4 0x00010000 +#define FLASH_CAPS_READ_1_4_4 0x00020000 +#define FLASH_CAPS_READ_4_4_4 0x00040000 +#define FLASH_CAPS_WRITE_1_1_4 0x00100000 +#define FLASH_CAPS_WRITE_1_4_4 0x00200000 +#define FLASH_CAPS_WRITE_4_4_4 0x00400000 + struct stfsm { struct device *dev; void __iomem *base; @@ -92,6 +119,31 @@ struct stfsm_seq { } __attribute__((__packed__, aligned(4))); #define STFSM_SEQ_SIZE sizeof(struct stfsm_seq) +/* SPI Flash Device Table */ +struct flash_info { + char *name; + /* + * JEDEC id zero means "no ID" (most older chips); otherwise it has + * a high byte of zero plus three data bytes: the manufacturer id, + * then a two byte device id. + */ + u32 jedec_id; + u16 ext_id; + /* + * The size listed here is what works with FLASH_CMD_SE, which isn't + * necessarily called a "sector" by the vendor. + */ + unsigned sector_size; + u16 n_sectors; + u32 capabilities; + /* + * Note, where FAST_READ is supported, freq_max specifies the + * FAST_READ frequency, not the READ frequency. + */ + u32 max_freq; + int (*config)(struct stfsm *, struct flash_info *); +}; + static struct stfsm_seq stfsm_seq_read_jedec = { .data_size = TRANSFER_SIZE(8), .seq_opc[0] = (SEQ_OPC_PADS_1 | @@ -108,6 +160,119 @@ static struct stfsm_seq stfsm_seq_read_jedec = { SEQ_CFG_STARTSEQ), }; +static struct flash_info __initdata flash_types[] = { + + /* + * ST Microelectronics/Numonyx -- + * (newer production versions may have feature updates + * (eg faster operating frequency) + */ +#define M25P_CAPS (FLASH_CAPS_READ_WRITE | FLASH_CAPS_READ_FAST) + { "m25p40", 0x202013, 0, 64 * 1024, 8, M25P_CAPS, 25, NULL }, + { "m25p80", 0x202014, 0, 64 * 1024, 16, M25P_CAPS, 25, NULL }, + { "m25p16", 0x202015, 0, 64 * 1024, 32, M25P_CAPS, 25, NULL }, + { "m25p32", 0x202016, 0, 64 * 1024, 64, M25P_CAPS, 50, NULL }, + { "m25p64", 0x202017, 0, 64 * 1024, 128, M25P_CAPS, 50, NULL }, + { "m25p128", 0x202018, 0, 256 * 1024, 64, M25P_CAPS, 50, NULL }, + +#define M25PX_CAPS (FLASH_CAPS_READ_WRITE | \ + FLASH_CAPS_READ_FAST | \ + FLASH_CAPS_READ_1_1_2 | \ + FLASH_CAPS_WRITE_1_1_2) + { "m25px32", 0x207116, 0, 64 * 1024, 64, M25PX_CAPS, 75, NULL }, + { "m25px64", 0x207117, 0, 64 * 1024, 128, M25PX_CAPS, 75, NULL }, + +#define MX25_CAPS (FLASH_CAPS_READ_WRITE | \ + FLASH_CAPS_READ_FAST | \ + FLASH_CAPS_READ_1_1_2 | \ + FLASH_CAPS_READ_1_2_2 | \ + FLASH_CAPS_READ_1_1_4 | \ + FLASH_CAPS_READ_1_4_4 | \ + FLASH_CAPS_WRITE_1_4_4 | \ + FLASH_CAPS_SE_4K | \ + FLASH_CAPS_SE_32K) + { "mx25l25635e", 0xc22019, 0, 64*1024, 512, + (MX25_CAPS | FLASH_CAPS_32BITADDR | FLASH_CAPS_RESET), 70, NULL }, + +#define N25Q_CAPS (FLASH_CAPS_READ_WRITE | \ + FLASH_CAPS_READ_FAST | \ + FLASH_CAPS_READ_1_1_2 | \ + FLASH_CAPS_READ_1_2_2 | \ + FLASH_CAPS_READ_1_1_4 | \ + FLASH_CAPS_READ_1_4_4 | \ + FLASH_CAPS_WRITE_1_1_2 | \ + FLASH_CAPS_WRITE_1_2_2 | \ + FLASH_CAPS_WRITE_1_1_4 | \ + FLASH_CAPS_WRITE_1_4_4) + { "n25q128", 0x20ba18, 0, 64 * 1024, 256, N25Q_CAPS, 108, NULL }, + { "n25q256", 0x20ba19, 0, 64 * 1024, 512, + N25Q_CAPS | FLASH_CAPS_32BITADDR, 108, NULL }, + + /* + * Spansion S25FLxxxP + * - 256KiB and 64KiB sector variants (identified by ext. JEDEC) + */ +#define S25FLXXXP_CAPS (FLASH_CAPS_READ_WRITE | \ + FLASH_CAPS_READ_1_1_2 | \ + FLASH_CAPS_READ_1_2_2 | \ + FLASH_CAPS_READ_1_1_4 | \ + FLASH_CAPS_READ_1_4_4 | \ + FLASH_CAPS_WRITE_1_1_4 | \ + FLASH_CAPS_READ_FAST) + { "s25fl129p0", 0x012018, 0x4d00, 256 * 1024, 64, S25FLXXXP_CAPS, 80, + NULL }, + { "s25fl129p1", 0x012018, 0x4d01, 64 * 1024, 256, S25FLXXXP_CAPS, 80, + NULL }, + + /* + * Spansion S25FLxxxS + * - 256KiB and 64KiB sector variants (identified by ext. JEDEC) + * - RESET# signal supported by die but not bristled out on all + * package types. The package type is a function of board design, + * so this information is captured in the board's capabilities. + * - Supports 'DYB' sector protection. Depending on variant, sectors + * may default to locked state on power-on. + */ +#define S25FLXXXS_CAPS (S25FLXXXP_CAPS | \ + FLASH_CAPS_RESET | \ + FLASH_CAPS_DYB_LOCKING) + { "s25fl128s0", 0x012018, 0x0300, 256 * 1024, 64, S25FLXXXS_CAPS, 80, + NULL }, + { "s25fl128s1", 0x012018, 0x0301, 64 * 1024, 256, S25FLXXXS_CAPS, 80, + NULL }, + { "s25fl256s0", 0x010219, 0x4d00, 256 * 1024, 128, + S25FLXXXS_CAPS | FLASH_CAPS_32BITADDR, 80, NULL }, + { "s25fl256s1", 0x010219, 0x4d01, 64 * 1024, 512, + S25FLXXXS_CAPS | FLASH_CAPS_32BITADDR, 80, NULL }, + + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ +#define W25X_CAPS (FLASH_CAPS_READ_WRITE | \ + FLASH_CAPS_READ_FAST | \ + FLASH_CAPS_READ_1_1_2 | \ + FLASH_CAPS_WRITE_1_1_2) + { "w25x40", 0xef3013, 0, 64 * 1024, 8, W25X_CAPS, 75, NULL }, + { "w25x80", 0xef3014, 0, 64 * 1024, 16, W25X_CAPS, 75, NULL }, + { "w25x16", 0xef3015, 0, 64 * 1024, 32, W25X_CAPS, 75, NULL }, + { "w25x32", 0xef3016, 0, 64 * 1024, 64, W25X_CAPS, 75, NULL }, + { "w25x64", 0xef3017, 0, 64 * 1024, 128, W25X_CAPS, 75, NULL }, + + /* Winbond -- w25q "blocks" are 64K, "sectors" are 4KiB */ +#define W25Q_CAPS (FLASH_CAPS_READ_WRITE | \ + FLASH_CAPS_READ_FAST | \ + FLASH_CAPS_READ_1_1_2 | \ + FLASH_CAPS_READ_1_2_2 | \ + FLASH_CAPS_READ_1_1_4 | \ + FLASH_CAPS_READ_1_4_4 | \ + FLASH_CAPS_WRITE_1_1_4) + { "w25q80", 0xef4014, 0, 64 * 1024, 16, W25Q_CAPS, 80, NULL }, + { "w25q16", 0xef4015, 0, 64 * 1024, 32, W25Q_CAPS, 80, NULL }, + { "w25q32", 0xef4016, 0, 64 * 1024, 64, W25Q_CAPS, 80, NULL }, + { "w25q64", 0xef4017, 0, 64 * 1024, 128, W25Q_CAPS, 80, NULL }, + + /* Sentinel */ + { NULL, 0x000000, 0, 0, 0, 0, 0, NULL }, +}; + static inline int stfsm_is_idle(struct stfsm *fsm) { return readl(fsm->base + SPI_FAST_SEQ_STA) & 0x10; -- 1.8.1.2 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 09/10] mtd: st_spi_fsm: Dynamically setup flash device based on JEDEC ID 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones ` (7 preceding siblings ...) 2013-11-14 14:22 ` [PATCH 08/10] mtd: st_spi_fsm: Provide device look-up table Lee Jones @ 2013-11-14 14:22 ` Lee Jones 2013-11-14 14:22 ` [PATCH 10/10] ARM: STi: Add support for the FSM Serial Flash Controller Lee Jones 9 siblings, 0 replies; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel Using previously added infrastructure we can now extract a device's JEDEC ID, compare it to a list of known and supported devices and make assumptions based on known characteristics of a given chip. Signed-off-by: Lee Jones <lee.jones@linaro.org> --- drivers/mtd/devices/st_spi_fsm.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c index 230024c..42dd4d9 100644 --- a/drivers/mtd/devices/st_spi_fsm.c +++ b/drivers/mtd/devices/st_spi_fsm.c @@ -357,6 +357,7 @@ static int stfsm_read_jedec(struct stfsm *fsm, uint8_t *const jedec) static struct flash_info * stfsm_jedec_probe(struct stfsm *fsm) { + struct flash_info *info; u16 ext_jedec; u32 jedec; u8 id[5]; @@ -380,6 +381,15 @@ static struct flash_info * stfsm_jedec_probe(struct stfsm *fsm) dev_dbg(fsm->dev, "JEDEC = 0x%08x [%02x %02x %02x %02x %02x]\n", jedec, id[0], id[1], id[2], id[3], id[4]); + for (info = flash_types; info->name; info++) { + if (info->jedec_id == jedec) { + if (info->ext_id && info->ext_id != ext_jedec) + continue; + return info; + } + } + dev_err(fsm->dev, "Unrecognized JEDEC id %06x\n", jedec); + return NULL; } @@ -490,6 +500,7 @@ static int stfsm_init(struct stfsm *fsm) static int stfsm_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + struct flash_info *info; struct resource *res; struct stfsm *fsm; int ret; @@ -536,7 +547,9 @@ static int stfsm_probe(struct platform_device *pdev) } /* Detect SPI FLASH device */ - stfsm_jedec_probe(fsm); + info = stfsm_jedec_probe(fsm); + if (!info) + return -ENODEV; platform_set_drvdata(pdev, fsm); @@ -545,6 +558,15 @@ static int stfsm_probe(struct platform_device *pdev) fsm->mtd.writesize = 4; fsm->mtd.writebufsize = fsm->mtd.writesize; fsm->mtd.flags = MTD_CAP_NORFLASH; + fsm->mtd.size = info->sector_size * info->n_sectors; + fsm->mtd.erasesize = info->sector_size; + + dev_err(&pdev->dev, + "Found serial flash device: %s\n" + " size = %llx (%lldMiB) erasesize = 0x%08x (%uKiB)\n", + info->name, + (long long)fsm->mtd.size, (long long)(fsm->mtd.size >> 20), + fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10)); return mtd_device_parse_register(&fsm->mtd, NULL, NULL, NULL, 0); } -- 1.8.1.2 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 10/10] ARM: STi: Add support for the FSM Serial Flash Controller 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones ` (8 preceding siblings ...) 2013-11-14 14:22 ` [PATCH 09/10] mtd: st_spi_fsm: Dynamically setup flash device based on JEDEC ID Lee Jones @ 2013-11-14 14:22 ` Lee Jones 9 siblings, 0 replies; 25+ messages in thread From: Lee Jones @ 2013-11-14 14:22 UTC (permalink / raw) To: linux-arm-kernel Here we add the necessary device nodes required for successful device probing and Pinctrl setup for the FSM. Cc: Srinivas Kandagatla <srinivas.kandagatla@st.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> --- arch/arm/boot/dts/stih416-b2105.dts | 10 ++++++++++ arch/arm/boot/dts/stih416-pinctrl.dtsi | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/arch/arm/boot/dts/stih416-b2105.dts b/arch/arm/boot/dts/stih416-b2105.dts index f14eec3..29b09ab 100644 --- a/arch/arm/boot/dts/stih416-b2105.dts +++ b/arch/arm/boot/dts/stih416-b2105.dts @@ -32,6 +32,16 @@ status = "okay"; }; + /* FSM */ + spifsm: spifsm at fe902000{ + compatible = "st,spi-fsm", "simple-bus"; + reg = <0xfe902000 0x1000>; + reg-names = "spi-fsm"; + pinctrl-0 = <&pinctrl_fsm>; + + status = "okay"; + }; + leds { compatible = "gpio-leds"; fp_led { diff --git a/arch/arm/boot/dts/stih416-pinctrl.dtsi b/arch/arm/boot/dts/stih416-pinctrl.dtsi index eb426a1..3106ea2 100644 --- a/arch/arm/boot/dts/stih416-pinctrl.dtsi +++ b/arch/arm/boot/dts/stih416-pinctrl.dtsi @@ -235,6 +235,18 @@ }; }; + fsm { + pinctrl_fsm: fsm { + st,pins { + spi-fsm-clk = <&PIO12 2 OUT ALT1>; + spi-fsm-cs = <&PIO12 3 OUT ALT1>; + spi-fsm-mosi = <&PIO12 4 OUT ALT1>; + spi-fsm-miso = <&PIO12 5 IN ALT1>; + spi-fsm-hol = <&PIO12 6 OUT ALT1>; + spi-fsm-wp = <&PIO12 7 OUT ALT1>; + }; + }; + }; }; pin-controller-rear { -- 1.8.1.2 ^ permalink raw reply related [flat|nested] 25+ messages in thread
end of thread, other threads:[~2013-11-18 18:35 UTC | newest] Thread overview: 25+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-11-14 14:22 [PATCH 00/10] mtd: st_spi_fsm: Add new device Lee Jones 2013-11-14 14:22 ` [PATCH 01/10] mtd: st_spi_fsm: Allocate resources and register with MTD framework Lee Jones 2013-11-14 14:22 ` [PATCH 02/10] mtd: st_spi_fsm: Supply all register address and bit logic defines Lee Jones 2013-11-18 9:15 ` Linus Walleij 2013-11-18 9:32 ` Lee Jones 2013-11-18 13:39 ` Mark Brown 2013-11-18 14:24 ` Lee Jones 2013-11-18 14:45 ` Mark Brown 2013-11-18 14:56 ` Lee Jones 2013-11-18 15:16 ` Mark Brown 2013-11-18 15:31 ` Lee Jones 2013-11-18 15:41 ` Mark Brown 2013-11-18 16:02 ` Lee Jones 2013-11-18 17:22 ` Mark Brown 2013-11-18 17:32 ` Lee Jones 2013-11-18 17:59 ` Sourav Poddar 2013-11-18 18:35 ` Mark Brown 2013-11-14 14:22 ` [PATCH 03/10] mtd: st_spi_fsm: Initialise and configure the FSM for normal working conditions Lee Jones 2013-11-14 14:22 ` [PATCH 04/10] mtd: st_spi_fsm: Supply framework for device requests Lee Jones 2013-11-14 14:22 ` [PATCH 05/10] mtd: st_spi_fsm: Supply a method to read from the FSM's FIFO Lee Jones 2013-11-14 14:22 ` [PATCH 06/10] mtd: st_spi_fsm: Supply defines for the possible flash command opcodes Lee Jones 2013-11-14 14:22 ` [PATCH 07/10] mtd: st_spi_fsm: Add support for JEDEC ID extraction Lee Jones 2013-11-14 14:22 ` [PATCH 08/10] mtd: st_spi_fsm: Provide device look-up table Lee Jones 2013-11-14 14:22 ` [PATCH 09/10] mtd: st_spi_fsm: Dynamically setup flash device based on JEDEC ID Lee Jones 2013-11-14 14:22 ` [PATCH 10/10] ARM: STi: Add support for the FSM Serial Flash Controller Lee Jones
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).