Message ID | 1440053705-3836-1-git-send-email-vndao@altera.com |
---|---|
State | Under Review, archived |
Headers | show |
On Thursday, August 20, 2015 at 08:55:05 AM, vndao@altera.com wrote: > From: VIET NGA DAO <vndao@altera.com> > > Altera Quad SPI Controller is a soft IP which enables access to > Altera EPCS and EPCQ flash chips. This patch adds driver > for these devices. > > Signed-off-by: VIET NGA DAO <vndao@altera.com> > > --- > v5: > - Remove Micron support > - Add multiple flashes probe failure handle > > v4: > - Add more flash devices support ( EPCQL and Micron) > - Remove redundant messages > - Change EPCQ_OPCODE_ID to NON_EPCS_OPCODE_ID > - Replace get_flash_name to altera_quadspi_scan > - Remove clk related parts > - Remove altera_quadspi_plat > - Change device tree reg name and remove opcode-id > > v3: > - Change altera_epcq driver name to altera_quadspi for more generic name > - Implement flash name searching in altera_quadspi.c instead of spi-nor > - Edit the altra quadspi info table in spi-nor > - Remove wait_til_ready in all read,write, erase, lock, unlock functions > - Merge .h and .c into 1 file > > v2: > - Change to spi_nor structure > - Add lock and unlock functions for spi_nor > - Simplify the altera_epcq_lock function > - Replace reg by compatible in device tree > --- > .../devicetree/bindings/mtd/altera-quadspi.txt | 45 ++ > drivers/mtd/spi-nor/Kconfig | 8 + > drivers/mtd/spi-nor/Makefile | 1 + > drivers/mtd/spi-nor/altera-quadspi.c | 557 > ++++++++++++++++++++ drivers/mtd/spi-nor/spi-nor.c | > 18 + > 5 files changed, 629 insertions(+), 0 deletions(-) > create mode 100644 > Documentation/devicetree/bindings/mtd/altera-quadspi.txt create mode > 100644 drivers/mtd/spi-nor/altera-quadspi.c > > diff --git a/Documentation/devicetree/bindings/mtd/altera-quadspi.txt > b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt new file mode > 100644 > index 0000000..e1bcf18 > --- /dev/null > +++ b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt > @@ -0,0 +1,45 @@ > +* MTD Altera QUADSPI driver > + > +Required properties: > +- compatible: Should be "altr,quadspi-1.0" > +- reg: Address and length of the register set for the device. It contains > + the information of registers in the same order as described by reg-names > +- reg-names: Should contain the reg names > + "avl_csr": Should contain the register configuration base address > + "avl_mem": Should contain the data base address > +- #address-cells: Must be <1>. > +- #size-cells: Must be <0>. > +- flash device tree subnode, there must be a node with the following > fields: + - compatible: Should contain the flash name: > + 1. EPCS: epcs16, epcs64, epcs128 > + 2. EPCQ: epcq16, epcq32, epcq64, epcq128, epcq256, epcq512, epcq1024 > + 3. EPCQ-L: epcql256, epcql512, epcql1024 > + - #address-cells: please refer to /mtd/partition.txt > + - #size-cells: please refer to /mtd/partition.txt > + For partitions inside each flash, please refer to /mtd/partition.txt > + > +Example: > + > + quadspi_controller_0: quadspi@0x180014a0 { > + compatible = "altr,quadspi-1.0"; > + reg = <0x180014a0 0x00000020>, > + <0x14000000 0x04000000>; > + reg-names = "avl_csr", "avl_mem"; > + #address-cells = <1>; > + #size-cells = <0>; > + flash0: epcq256@0 { > + compatible = "altr,epcq256"; > + #address-cells = <1>; > + #size-cells = <1>; > + partition@0 { > + /* 16 MB for raw data. */ > + label = "EPCQ Flash 0 raw data"; > + reg = <0x0 0x1000000>; > + }; > + partition@1000000 { > + /* 16 MB for jffs2 data. */ > + label = "EPCQ Flash 0 JFFS 2"; > + reg = <0x1000000 0x1000000>; > + }; IIRC, encoding partitions into OF is deprecated (and it shouldn't be part of the example anyway, so please remove this bit). > + }; > + }; //end quadspi@0x180014a0 (quadspi_controller_0) Remove this incorrect comment. [...] > +static struct flash_device flash_devices[] = { > + FLASH_ID("epcs16", EPCS_OPCODE_ID, 0x14), > + FLASH_ID("epcs64", EPCS_OPCODE_ID, 0x16), > + FLASH_ID("epcs128", EPCS_OPCODE_ID, 0x18), > + > + FLASH_ID("epcq16", NON_EPCS_OPCODE_ID, 0x15), > + FLASH_ID("epcq32", NON_EPCS_OPCODE_ID, 0x16), > + FLASH_ID("epcq64", NON_EPCS_OPCODE_ID, 0x17), > + FLASH_ID("epcq128", NON_EPCS_OPCODE_ID, 0x18), > + FLASH_ID("epcq256", NON_EPCS_OPCODE_ID, 0x19), > + FLASH_ID("epcq512", NON_EPCS_OPCODE_ID, 0x20), > + FLASH_ID("epcq1024", NON_EPCS_OPCODE_ID, 0x21), > + > + FLASH_ID("epcql256", NON_EPCS_OPCODE_ID, 0x19), > + FLASH_ID("epcql512", NON_EPCS_OPCODE_ID, 0x20), > + FLASH_ID("epcql1024", NON_EPCS_OPCODE_ID, 0x21), > + > +}; I think it'd be better to wait until the IP block is fixed and can issue READID correctly. > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c > index 14a5d23..2ab7279 100644 > --- a/drivers/mtd/spi-nor/spi-nor.c > +++ b/drivers/mtd/spi-nor/spi-nor.c > @@ -687,6 +687,24 @@ static const struct spi_device_id spi_nor_ids[] = { > { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | > SPI_NOR_NO_FR) }, { "cat25c17", CAT25_INFO( 256, 8, 32, 2, > SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25128", CAT25_INFO(2048, 8, 64, > 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, + > + /* Altera EPCQ/EPCS Flashes are non-JEDEC */ Are they really ? Last time I checked on CV SoC, I was able to read their JEDEC ID just fine ; though it's true I used that EPCS core. > + { "epcs16", INFO(0, 0, 0x10000, 32, 0) }, > + { "epcs64", INFO(0, 0, 0x10000, 128, 0) }, > + { "epcs128", INFO(0, 0, 0x40000, 256, 0) }, > + > + { "epcq16", INFO(0, 0, 0x10000, 32, 0) }, > + { "epcq32", INFO(0, 0, 0x10000, 64, 0) }, > + { "epcq64", INFO(0, 0, 0x10000, 128, 0) }, > + { "epcq128", INFO(0, 0, 0x10000, 256, 0) }, > + { "epcq256", INFO(0, 0, 0x10000, 512, 0) }, > + { "epcq512", INFO(0, 0, 0x10000, 1024, 0) }, > + { "epcq1024", INFO(0, 0, 0x10000, 2048, 0) }, > + > + { "epcql256", INFO(0, 0, 0x10000, 512, 0) }, > + { "epcql512", INFO(0, 0, 0x10000, 1024, 0) }, > + { "epcql1024", INFO(0, 0, 0x10000, 2048, 0) }, > + > { }, > }; -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Aug 20, 2015 at 4:03 PM, Marek Vasut <marex@denx.de> wrote: > On Thursday, August 20, 2015 at 08:55:05 AM, vndao@altera.com wrote: >> From: VIET NGA DAO <vndao@altera.com> >> >> Altera Quad SPI Controller is a soft IP which enables access to >> Altera EPCS and EPCQ flash chips. This patch adds driver >> for these devices. >> >> Signed-off-by: VIET NGA DAO <vndao@altera.com> >> >> --- >> v5: >> - Remove Micron support >> - Add multiple flashes probe failure handle >> >> v4: >> - Add more flash devices support ( EPCQL and Micron) >> - Remove redundant messages >> - Change EPCQ_OPCODE_ID to NON_EPCS_OPCODE_ID >> - Replace get_flash_name to altera_quadspi_scan >> - Remove clk related parts >> - Remove altera_quadspi_plat >> - Change device tree reg name and remove opcode-id >> >> v3: >> - Change altera_epcq driver name to altera_quadspi for more generic name >> - Implement flash name searching in altera_quadspi.c instead of spi-nor >> - Edit the altra quadspi info table in spi-nor >> - Remove wait_til_ready in all read,write, erase, lock, unlock functions >> - Merge .h and .c into 1 file >> >> v2: >> - Change to spi_nor structure >> - Add lock and unlock functions for spi_nor >> - Simplify the altera_epcq_lock function >> - Replace reg by compatible in device tree >> --- >> .../devicetree/bindings/mtd/altera-quadspi.txt | 45 ++ >> drivers/mtd/spi-nor/Kconfig | 8 + >> drivers/mtd/spi-nor/Makefile | 1 + >> drivers/mtd/spi-nor/altera-quadspi.c | 557 >> ++++++++++++++++++++ drivers/mtd/spi-nor/spi-nor.c | >> 18 + >> 5 files changed, 629 insertions(+), 0 deletions(-) >> create mode 100644 >> Documentation/devicetree/bindings/mtd/altera-quadspi.txt create mode >> 100644 drivers/mtd/spi-nor/altera-quadspi.c >> >> diff --git a/Documentation/devicetree/bindings/mtd/altera-quadspi.txt >> b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt new file mode >> 100644 >> index 0000000..e1bcf18 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt >> @@ -0,0 +1,45 @@ >> +* MTD Altera QUADSPI driver >> + >> +Required properties: >> +- compatible: Should be "altr,quadspi-1.0" >> +- reg: Address and length of the register set for the device. It contains >> + the information of registers in the same order as described by reg-names >> +- reg-names: Should contain the reg names >> + "avl_csr": Should contain the register configuration base address >> + "avl_mem": Should contain the data base address >> +- #address-cells: Must be <1>. >> +- #size-cells: Must be <0>. >> +- flash device tree subnode, there must be a node with the following >> fields: + - compatible: Should contain the flash name: >> + 1. EPCS: epcs16, epcs64, epcs128 >> + 2. EPCQ: epcq16, epcq32, epcq64, epcq128, epcq256, epcq512, epcq1024 >> + 3. EPCQ-L: epcql256, epcql512, epcql1024 >> + - #address-cells: please refer to /mtd/partition.txt >> + - #size-cells: please refer to /mtd/partition.txt >> + For partitions inside each flash, please refer to /mtd/partition.txt >> + >> +Example: >> + >> + quadspi_controller_0: quadspi@0x180014a0 { >> + compatible = "altr,quadspi-1.0"; >> + reg = <0x180014a0 0x00000020>, >> + <0x14000000 0x04000000>; >> + reg-names = "avl_csr", "avl_mem"; >> + #address-cells = <1>; >> + #size-cells = <0>; >> + flash0: epcq256@0 { >> + compatible = "altr,epcq256"; >> + #address-cells = <1>; >> + #size-cells = <1>; >> + partition@0 { >> + /* 16 MB for raw data. */ >> + label = "EPCQ Flash 0 raw data"; >> + reg = <0x0 0x1000000>; >> + }; >> + partition@1000000 { >> + /* 16 MB for jffs2 data. */ >> + label = "EPCQ Flash 0 JFFS 2"; >> + reg = <0x1000000 0x1000000>; >> + }; > > IIRC, encoding partitions into OF is deprecated (and it shouldn't be > part of the example anyway, so please remove this bit). > >> + }; >> + }; //end quadspi@0x180014a0 (quadspi_controller_0) > > Remove this incorrect comment. > > > [...] > Do you mean the partition part below should not be in example? partition@0 { /* 16 MB for raw data. */ label = "EPCQ Flash 0 raw data"; reg = <0x0 0x1000000>; }; partition@1000000 { /* 16 MB for jffs2 data. */ label = "EPCQ Flash 0 JFFS 2"; reg = <0x1000000 0x1000000>; }; >> +static struct flash_device flash_devices[] = { >> + FLASH_ID("epcs16", EPCS_OPCODE_ID, 0x14), >> + FLASH_ID("epcs64", EPCS_OPCODE_ID, 0x16), >> + FLASH_ID("epcs128", EPCS_OPCODE_ID, 0x18), >> + >> + FLASH_ID("epcq16", NON_EPCS_OPCODE_ID, 0x15), >> + FLASH_ID("epcq32", NON_EPCS_OPCODE_ID, 0x16), >> + FLASH_ID("epcq64", NON_EPCS_OPCODE_ID, 0x17), >> + FLASH_ID("epcq128", NON_EPCS_OPCODE_ID, 0x18), >> + FLASH_ID("epcq256", NON_EPCS_OPCODE_ID, 0x19), >> + FLASH_ID("epcq512", NON_EPCS_OPCODE_ID, 0x20), >> + FLASH_ID("epcq1024", NON_EPCS_OPCODE_ID, 0x21), >> + >> + FLASH_ID("epcql256", NON_EPCS_OPCODE_ID, 0x19), >> + FLASH_ID("epcql512", NON_EPCS_OPCODE_ID, 0x20), >> + FLASH_ID("epcql1024", NON_EPCS_OPCODE_ID, 0x21), >> + >> +}; > > I think it'd be better to wait until the IP block is fixed and can > issue READID correctly. > The hardware IP fix will take time while there are lot of customer are waiting for this driver. That is why we decided to upstream the driver. If the hardware fix, there might not need to have any changes in driver to support or if yes, it will be just minor. >> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c >> index 14a5d23..2ab7279 100644 >> --- a/drivers/mtd/spi-nor/spi-nor.c >> +++ b/drivers/mtd/spi-nor/spi-nor.c >> @@ -687,6 +687,24 @@ static const struct spi_device_id spi_nor_ids[] = { >> { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | >> SPI_NOR_NO_FR) }, { "cat25c17", CAT25_INFO( 256, 8, 32, 2, >> SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25128", CAT25_INFO(2048, 8, 64, >> 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, + >> + /* Altera EPCQ/EPCS Flashes are non-JEDEC */ > > Are they really ? Last time I checked on CV SoC, I was able to read their > JEDEC ID just fine ; though it's true I used that EPCS core. > >> + { "epcs16", INFO(0, 0, 0x10000, 32, 0) }, >> + { "epcs64", INFO(0, 0, 0x10000, 128, 0) }, >> + { "epcs128", INFO(0, 0, 0x40000, 256, 0) }, >> + >> + { "epcq16", INFO(0, 0, 0x10000, 32, 0) }, >> + { "epcq32", INFO(0, 0, 0x10000, 64, 0) }, >> + { "epcq64", INFO(0, 0, 0x10000, 128, 0) }, >> + { "epcq128", INFO(0, 0, 0x10000, 256, 0) }, >> + { "epcq256", INFO(0, 0, 0x10000, 512, 0) }, >> + { "epcq512", INFO(0, 0, 0x10000, 1024, 0) }, >> + { "epcq1024", INFO(0, 0, 0x10000, 2048, 0) }, >> + >> + { "epcql256", INFO(0, 0, 0x10000, 512, 0) }, >> + { "epcql512", INFO(0, 0, 0x10000, 1024, 0) }, >> + { "epcql1024", INFO(0, 0, 0x10000, 2048, 0) }, >> + >> { }, >> };
Sorry for missing to reply the last question On Thu, Aug 20, 2015 at 4:13 PM, Nga Chi <ngachi86@gmail.com> wrote: > On Thu, Aug 20, 2015 at 4:03 PM, Marek Vasut <marex@denx.de> wrote: >> On Thursday, August 20, 2015 at 08:55:05 AM, vndao@altera.com wrote: >>> From: VIET NGA DAO <vndao@altera.com> >>> >>> Altera Quad SPI Controller is a soft IP which enables access to >>> Altera EPCS and EPCQ flash chips. This patch adds driver >>> for these devices. >>> >>> Signed-off-by: VIET NGA DAO <vndao@altera.com> >>> >>> --- >>> v5: >>> - Remove Micron support >>> - Add multiple flashes probe failure handle >>> >>> v4: >>> - Add more flash devices support ( EPCQL and Micron) >>> - Remove redundant messages >>> - Change EPCQ_OPCODE_ID to NON_EPCS_OPCODE_ID >>> - Replace get_flash_name to altera_quadspi_scan >>> - Remove clk related parts >>> - Remove altera_quadspi_plat >>> - Change device tree reg name and remove opcode-id >>> >>> v3: >>> - Change altera_epcq driver name to altera_quadspi for more generic name >>> - Implement flash name searching in altera_quadspi.c instead of spi-nor >>> - Edit the altra quadspi info table in spi-nor >>> - Remove wait_til_ready in all read,write, erase, lock, unlock functions >>> - Merge .h and .c into 1 file >>> >>> v2: >>> - Change to spi_nor structure >>> - Add lock and unlock functions for spi_nor >>> - Simplify the altera_epcq_lock function >>> - Replace reg by compatible in device tree >>> --- >>> .../devicetree/bindings/mtd/altera-quadspi.txt | 45 ++ >>> drivers/mtd/spi-nor/Kconfig | 8 + >>> drivers/mtd/spi-nor/Makefile | 1 + >>> drivers/mtd/spi-nor/altera-quadspi.c | 557 >>> ++++++++++++++++++++ drivers/mtd/spi-nor/spi-nor.c | >>> 18 + >>> 5 files changed, 629 insertions(+), 0 deletions(-) >>> create mode 100644 >>> Documentation/devicetree/bindings/mtd/altera-quadspi.txt create mode >>> 100644 drivers/mtd/spi-nor/altera-quadspi.c >>> >>> diff --git a/Documentation/devicetree/bindings/mtd/altera-quadspi.txt >>> b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt new file mode >>> 100644 >>> index 0000000..e1bcf18 >>> --- /dev/null >>> +++ b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt >>> @@ -0,0 +1,45 @@ >>> +* MTD Altera QUADSPI driver >>> + >>> +Required properties: >>> +- compatible: Should be "altr,quadspi-1.0" >>> +- reg: Address and length of the register set for the device. It contains >>> + the information of registers in the same order as described by reg-names >>> +- reg-names: Should contain the reg names >>> + "avl_csr": Should contain the register configuration base address >>> + "avl_mem": Should contain the data base address >>> +- #address-cells: Must be <1>. >>> +- #size-cells: Must be <0>. >>> +- flash device tree subnode, there must be a node with the following >>> fields: + - compatible: Should contain the flash name: >>> + 1. EPCS: epcs16, epcs64, epcs128 >>> + 2. EPCQ: epcq16, epcq32, epcq64, epcq128, epcq256, epcq512, epcq1024 >>> + 3. EPCQ-L: epcql256, epcql512, epcql1024 >>> + - #address-cells: please refer to /mtd/partition.txt >>> + - #size-cells: please refer to /mtd/partition.txt >>> + For partitions inside each flash, please refer to /mtd/partition.txt >>> + >>> +Example: >>> + >>> + quadspi_controller_0: quadspi@0x180014a0 { >>> + compatible = "altr,quadspi-1.0"; >>> + reg = <0x180014a0 0x00000020>, >>> + <0x14000000 0x04000000>; >>> + reg-names = "avl_csr", "avl_mem"; >>> + #address-cells = <1>; >>> + #size-cells = <0>; >>> + flash0: epcq256@0 { >>> + compatible = "altr,epcq256"; >>> + #address-cells = <1>; >>> + #size-cells = <1>; >>> + partition@0 { >>> + /* 16 MB for raw data. */ >>> + label = "EPCQ Flash 0 raw data"; >>> + reg = <0x0 0x1000000>; >>> + }; >>> + partition@1000000 { >>> + /* 16 MB for jffs2 data. */ >>> + label = "EPCQ Flash 0 JFFS 2"; >>> + reg = <0x1000000 0x1000000>; >>> + }; >> >> IIRC, encoding partitions into OF is deprecated (and it shouldn't be >> part of the example anyway, so please remove this bit). >> >>> + }; >>> + }; //end quadspi@0x180014a0 (quadspi_controller_0) >> >> Remove this incorrect comment. >> >> >> [...] >> > >Do you mean the partition part below should not be in example? > partition@0 { > /* 16 MB for raw data. */ > label = "EPCQ Flash 0 raw data"; > reg = <0x0 0x1000000>; > }; > partition@1000000 { > /* 16 MB for jffs2 data. */ > label = "EPCQ Flash 0 JFFS 2"; > reg = <0x1000000 0x1000000>; > }; > >>> +static struct flash_device flash_devices[] = { >>> + FLASH_ID("epcs16", EPCS_OPCODE_ID, 0x14), >>> + FLASH_ID("epcs64", EPCS_OPCODE_ID, 0x16), >>> + FLASH_ID("epcs128", EPCS_OPCODE_ID, 0x18), >>> + >>> + FLASH_ID("epcq16", NON_EPCS_OPCODE_ID, 0x15), >>> + FLASH_ID("epcq32", NON_EPCS_OPCODE_ID, 0x16), >>> + FLASH_ID("epcq64", NON_EPCS_OPCODE_ID, 0x17), >>> + FLASH_ID("epcq128", NON_EPCS_OPCODE_ID, 0x18), >>> + FLASH_ID("epcq256", NON_EPCS_OPCODE_ID, 0x19), >>> + FLASH_ID("epcq512", NON_EPCS_OPCODE_ID, 0x20), >>> + FLASH_ID("epcq1024", NON_EPCS_OPCODE_ID, 0x21), >>> + >>> + FLASH_ID("epcql256", NON_EPCS_OPCODE_ID, 0x19), >>> + FLASH_ID("epcql512", NON_EPCS_OPCODE_ID, 0x20), >>> + FLASH_ID("epcql1024", NON_EPCS_OPCODE_ID, 0x21), >>> + >>> +}; >> >> I think it'd be better to wait until the IP block is fixed and can >> issue READID correctly. >> > > The hardware IP fix will take time while there are lot of customer are > waiting for this driver. That is why we decided to upstream the > driver. If the hardware fix, there might not need to have any changes > in driver to support or if yes, it will be just minor. > >>> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c >>> index 14a5d23..2ab7279 100644 >>> --- a/drivers/mtd/spi-nor/spi-nor.c >>> +++ b/drivers/mtd/spi-nor/spi-nor.c >>> @@ -687,6 +687,24 @@ static const struct spi_device_id spi_nor_ids[] = { >>> { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | >>> SPI_NOR_NO_FR) }, { "cat25c17", CAT25_INFO( 256, 8, 32, 2, >>> SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25128", CAT25_INFO(2048, 8, 64, >>> 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, + >>> + /* Altera EPCQ/EPCS Flashes are non-JEDEC */ >> >> Are they really ? Last time I checked on CV SoC, I was able to read their >> JEDEC ID just fine ; though it's true I used that EPCS core. >> Altera EPCS flash is non-jedec device. And this new controller is not EPCS controller. If you look at the documentation i sent in another email, they are not the same. >>> + { "epcs16", INFO(0, 0, 0x10000, 32, 0) }, >>> + { "epcs64", INFO(0, 0, 0x10000, 128, 0) }, >>> + { "epcs128", INFO(0, 0, 0x40000, 256, 0) }, >>> + >>> + { "epcq16", INFO(0, 0, 0x10000, 32, 0) }, >>> + { "epcq32", INFO(0, 0, 0x10000, 64, 0) }, >>> + { "epcq64", INFO(0, 0, 0x10000, 128, 0) }, >>> + { "epcq128", INFO(0, 0, 0x10000, 256, 0) }, >>> + { "epcq256", INFO(0, 0, 0x10000, 512, 0) }, >>> + { "epcq512", INFO(0, 0, 0x10000, 1024, 0) }, >>> + { "epcq1024", INFO(0, 0, 0x10000, 2048, 0) }, >>> + >>> + { "epcql256", INFO(0, 0, 0x10000, 512, 0) }, >>> + { "epcql512", INFO(0, 0, 0x10000, 1024, 0) }, >>> + { "epcql1024", INFO(0, 0, 0x10000, 2048, 0) }, >>> + >>> { }, >>> }; > > > > -- > Nga -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thursday, August 20, 2015 at 10:13:30 AM, Nga Chi wrote: > On Thu, Aug 20, 2015 at 4:03 PM, Marek Vasut <marex@denx.de> wrote: > > On Thursday, August 20, 2015 at 08:55:05 AM, vndao@altera.com wrote: > >> From: VIET NGA DAO <vndao@altera.com> > >> > >> Altera Quad SPI Controller is a soft IP which enables access to > >> Altera EPCS and EPCQ flash chips. This patch adds driver > >> for these devices. > >> > >> Signed-off-by: VIET NGA DAO <vndao@altera.com> > >> > >> --- > >> v5: > >> - Remove Micron support > >> - Add multiple flashes probe failure handle > >> > >> v4: > >> - Add more flash devices support ( EPCQL and Micron) > >> - Remove redundant messages > >> - Change EPCQ_OPCODE_ID to NON_EPCS_OPCODE_ID > >> - Replace get_flash_name to altera_quadspi_scan > >> - Remove clk related parts > >> - Remove altera_quadspi_plat > >> - Change device tree reg name and remove opcode-id > >> > >> v3: > >> - Change altera_epcq driver name to altera_quadspi for more generic name > >> - Implement flash name searching in altera_quadspi.c instead of spi-nor > >> - Edit the altra quadspi info table in spi-nor > >> - Remove wait_til_ready in all read,write, erase, lock, unlock functions > >> - Merge .h and .c into 1 file > >> > >> v2: > >> - Change to spi_nor structure > >> - Add lock and unlock functions for spi_nor > >> - Simplify the altera_epcq_lock function > >> - Replace reg by compatible in device tree > >> --- > >> > >> .../devicetree/bindings/mtd/altera-quadspi.txt | 45 ++ > >> drivers/mtd/spi-nor/Kconfig | 8 + > >> drivers/mtd/spi-nor/Makefile | 1 + > >> drivers/mtd/spi-nor/altera-quadspi.c | 557 > >> > >> ++++++++++++++++++++ drivers/mtd/spi-nor/spi-nor.c > >> | > >> > >> 18 + > >> 5 files changed, 629 insertions(+), 0 deletions(-) > >> create mode 100644 > >> > >> Documentation/devicetree/bindings/mtd/altera-quadspi.txt create mode > >> 100644 drivers/mtd/spi-nor/altera-quadspi.c > >> > >> diff --git a/Documentation/devicetree/bindings/mtd/altera-quadspi.txt > >> b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt new file mode > >> 100644 > >> index 0000000..e1bcf18 > >> --- /dev/null > >> +++ b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt > >> @@ -0,0 +1,45 @@ > >> +* MTD Altera QUADSPI driver > >> + > >> +Required properties: > >> +- compatible: Should be "altr,quadspi-1.0" > >> +- reg: Address and length of the register set for the device. It > >> contains + the information of registers in the same order as described > >> by reg-names +- reg-names: Should contain the reg names > >> + "avl_csr": Should contain the register configuration base address > >> + "avl_mem": Should contain the data base address > >> +- #address-cells: Must be <1>. > >> +- #size-cells: Must be <0>. > >> +- flash device tree subnode, there must be a node with the following > >> fields: + - compatible: Should contain the flash name: > >> + 1. EPCS: epcs16, epcs64, epcs128 > >> + 2. EPCQ: epcq16, epcq32, epcq64, epcq128, epcq256, epcq512, > >> epcq1024 + 3. EPCQ-L: epcql256, epcql512, epcql1024 > >> + - #address-cells: please refer to /mtd/partition.txt > >> + - #size-cells: please refer to /mtd/partition.txt > >> + For partitions inside each flash, please refer to > >> /mtd/partition.txt + > >> +Example: > >> + > >> + quadspi_controller_0: quadspi@0x180014a0 { > >> + compatible = "altr,quadspi-1.0"; > >> + reg = <0x180014a0 0x00000020>, > >> + <0x14000000 0x04000000>; > >> + reg-names = "avl_csr", "avl_mem"; > >> + #address-cells = <1>; > >> + #size-cells = <0>; > >> + flash0: epcq256@0 { > >> + compatible = "altr,epcq256"; > >> + #address-cells = <1>; > >> + #size-cells = <1>; > >> + partition@0 { > >> + /* 16 MB for raw data. */ > >> + label = "EPCQ Flash 0 raw > >> data"; + reg = <0x0 > >> 0x1000000>; + }; > >> + partition@1000000 { > >> + /* 16 MB for jffs2 data. > >> */ + label = "EPCQ Flash 0 > >> JFFS 2"; + reg = <0x1000000 > >> 0x1000000>; + }; > > > > IIRC, encoding partitions into OF is deprecated (and it shouldn't be > > part of the example anyway, so please remove this bit). > > > >> + }; > >> + }; //end quadspi@0x180014a0 (quadspi_controller_0) > > > > Remove this incorrect comment. > > > > > > [...] > > Do you mean the partition part below should not be in example? > partition@0 { > /* 16 MB for raw data. */ > label = "EPCQ Flash 0 raw > data"; reg = <0x0 0x1000000>; }; > partition@1000000 { > /* 16 MB for jffs2 data. */ > label = "EPCQ Flash 0 JFFS 2"; > reg = <0x1000000 0x1000000>; > }; Yes, it's not really relevant. > >> +static struct flash_device flash_devices[] = { > >> + FLASH_ID("epcs16", EPCS_OPCODE_ID, 0x14), > >> + FLASH_ID("epcs64", EPCS_OPCODE_ID, 0x16), > >> + FLASH_ID("epcs128", EPCS_OPCODE_ID, 0x18), > >> + > >> + FLASH_ID("epcq16", NON_EPCS_OPCODE_ID, 0x15), > >> + FLASH_ID("epcq32", NON_EPCS_OPCODE_ID, 0x16), > >> + FLASH_ID("epcq64", NON_EPCS_OPCODE_ID, 0x17), > >> + FLASH_ID("epcq128", NON_EPCS_OPCODE_ID, 0x18), > >> + FLASH_ID("epcq256", NON_EPCS_OPCODE_ID, 0x19), > >> + FLASH_ID("epcq512", NON_EPCS_OPCODE_ID, 0x20), > >> + FLASH_ID("epcq1024", NON_EPCS_OPCODE_ID, 0x21), > >> + > >> + FLASH_ID("epcql256", NON_EPCS_OPCODE_ID, 0x19), > >> + FLASH_ID("epcql512", NON_EPCS_OPCODE_ID, 0x20), > >> + FLASH_ID("epcql1024", NON_EPCS_OPCODE_ID, 0x21), > >> + > >> +}; > > > > I think it'd be better to wait until the IP block is fixed and can > > issue READID correctly. > > The hardware IP fix will take time while there are lot of customer are > waiting for this driver. Does that justify pushing serious crap into mainline Linux in any way ? > That is why we decided to upstream the > driver. If the hardware fix, there might not need to have any changes > in driver to support or if yes, it will be just minor. If the hardware can do proper READID opcode, this entire nonsense table will go away and a proper integration into the SPI NOR framework will take place. You might consider submitting this driver for staging, but I definitely am not a big fan of that. > >> diff --git a/drivers/mtd/spi-nor/spi-nor.c > >> b/drivers/mtd/spi-nor/spi-nor.c index 14a5d23..2ab7279 100644 > >> --- a/drivers/mtd/spi-nor/spi-nor.c > >> +++ b/drivers/mtd/spi-nor/spi-nor.c > >> @@ -687,6 +687,24 @@ static const struct spi_device_id spi_nor_ids[] = { > >> > >> { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | > >> > >> SPI_NOR_NO_FR) }, { "cat25c17", CAT25_INFO( 256, 8, 32, 2, > >> SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25128", CAT25_INFO(2048, 8, > >> 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, + > >> + /* Altera EPCQ/EPCS Flashes are non-JEDEC */ > > > > Are they really ? Last time I checked on CV SoC, I was able to read their > > JEDEC ID just fine ; though it's true I used that EPCS core. > > > >> + { "epcs16", INFO(0, 0, 0x10000, 32, 0) }, > >> + { "epcs64", INFO(0, 0, 0x10000, 128, 0) }, > >> + { "epcs128", INFO(0, 0, 0x40000, 256, 0) }, > >> + > >> + { "epcq16", INFO(0, 0, 0x10000, 32, 0) }, > >> + { "epcq32", INFO(0, 0, 0x10000, 64, 0) }, > >> + { "epcq64", INFO(0, 0, 0x10000, 128, 0) }, > >> + { "epcq128", INFO(0, 0, 0x10000, 256, 0) }, > >> + { "epcq256", INFO(0, 0, 0x10000, 512, 0) }, > >> + { "epcq512", INFO(0, 0, 0x10000, 1024, 0) }, > >> + { "epcq1024", INFO(0, 0, 0x10000, 2048, 0) }, > >> + > >> + { "epcql256", INFO(0, 0, 0x10000, 512, 0) }, > >> + { "epcql512", INFO(0, 0, 0x10000, 1024, 0) }, > >> + { "epcql1024", INFO(0, 0, 0x10000, 2048, 0) }, > >> + > >> > >> { }, > >> > >> }; -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thursday, August 20, 2015 at 10:17:57 AM, Viet Nga Dao wrote: > Sorry for missing to reply the last question Hi! > >>> diff --git a/drivers/mtd/spi-nor/spi-nor.c > >>> b/drivers/mtd/spi-nor/spi-nor.c index 14a5d23..2ab7279 100644 > >>> --- a/drivers/mtd/spi-nor/spi-nor.c > >>> +++ b/drivers/mtd/spi-nor/spi-nor.c > >>> @@ -687,6 +687,24 @@ static const struct spi_device_id spi_nor_ids[] = > >>> { > >>> > >>> { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | > >>> > >>> SPI_NOR_NO_FR) }, { "cat25c17", CAT25_INFO( 256, 8, 32, 2, > >>> SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25128", CAT25_INFO(2048, 8, > >>> 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, + > >>> + /* Altera EPCQ/EPCS Flashes are non-JEDEC */ > >> > >> Are they really ? Last time I checked on CV SoC, I was able to read > >> their JEDEC ID just fine ; though it's true I used that EPCS core. > > Altera EPCS flash is non-jedec device. And this new controller is not > EPCS controller. If you look at the documentation i sent in another > email, they are not the same. https://www.altera.com/content/dam/altera- www/global/en_US/pdfs/literature/hb/cfg/cfg_cf52012.pdf page 15 ; seems like opcode 0x9f is supported. All the other opcodes seems compatible too. What is the problem ? Best regards, Marek Vasut -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Aug 20, 2015 at 4:52 PM, Marek Vasut <marex@denx.de> wrote: > On Thursday, August 20, 2015 at 10:13:30 AM, Nga Chi wrote: >> On Thu, Aug 20, 2015 at 4:03 PM, Marek Vasut <marex@denx.de> wrote: >> > On Thursday, August 20, 2015 at 08:55:05 AM, vndao@altera.com wrote: >> >> From: VIET NGA DAO <vndao@altera.com> >> >> >> >> Altera Quad SPI Controller is a soft IP which enables access to >> >> Altera EPCS and EPCQ flash chips. This patch adds driver >> >> for these devices. >> >> >> >> Signed-off-by: VIET NGA DAO <vndao@altera.com> >> >> >> >> --- >> >> v5: >> >> - Remove Micron support >> >> - Add multiple flashes probe failure handle >> >> >> >> v4: >> >> - Add more flash devices support ( EPCQL and Micron) >> >> - Remove redundant messages >> >> - Change EPCQ_OPCODE_ID to NON_EPCS_OPCODE_ID >> >> - Replace get_flash_name to altera_quadspi_scan >> >> - Remove clk related parts >> >> - Remove altera_quadspi_plat >> >> - Change device tree reg name and remove opcode-id >> >> >> >> v3: >> >> - Change altera_epcq driver name to altera_quadspi for more generic name >> >> - Implement flash name searching in altera_quadspi.c instead of spi-nor >> >> - Edit the altra quadspi info table in spi-nor >> >> - Remove wait_til_ready in all read,write, erase, lock, unlock functions >> >> - Merge .h and .c into 1 file >> >> >> >> v2: >> >> - Change to spi_nor structure >> >> - Add lock and unlock functions for spi_nor >> >> - Simplify the altera_epcq_lock function >> >> - Replace reg by compatible in device tree >> >> --- >> >> >> >> .../devicetree/bindings/mtd/altera-quadspi.txt | 45 ++ >> >> drivers/mtd/spi-nor/Kconfig | 8 + >> >> drivers/mtd/spi-nor/Makefile | 1 + >> >> drivers/mtd/spi-nor/altera-quadspi.c | 557 >> >> >> >> ++++++++++++++++++++ drivers/mtd/spi-nor/spi-nor.c >> >> | >> >> >> >> 18 + >> >> 5 files changed, 629 insertions(+), 0 deletions(-) >> >> create mode 100644 >> >> >> >> Documentation/devicetree/bindings/mtd/altera-quadspi.txt create mode >> >> 100644 drivers/mtd/spi-nor/altera-quadspi.c >> >> >> >> diff --git a/Documentation/devicetree/bindings/mtd/altera-quadspi.txt >> >> b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt new file mode >> >> 100644 >> >> index 0000000..e1bcf18 >> >> --- /dev/null >> >> +++ b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt >> >> @@ -0,0 +1,45 @@ >> >> +* MTD Altera QUADSPI driver >> >> + >> >> +Required properties: >> >> +- compatible: Should be "altr,quadspi-1.0" >> >> +- reg: Address and length of the register set for the device. It >> >> contains + the information of registers in the same order as described >> >> by reg-names +- reg-names: Should contain the reg names >> >> + "avl_csr": Should contain the register configuration base address >> >> + "avl_mem": Should contain the data base address >> >> +- #address-cells: Must be <1>. >> >> +- #size-cells: Must be <0>. >> >> +- flash device tree subnode, there must be a node with the following >> >> fields: + - compatible: Should contain the flash name: >> >> + 1. EPCS: epcs16, epcs64, epcs128 >> >> + 2. EPCQ: epcq16, epcq32, epcq64, epcq128, epcq256, epcq512, >> >> epcq1024 + 3. EPCQ-L: epcql256, epcql512, epcql1024 >> >> + - #address-cells: please refer to /mtd/partition.txt >> >> + - #size-cells: please refer to /mtd/partition.txt >> >> + For partitions inside each flash, please refer to >> >> /mtd/partition.txt + >> >> +Example: >> >> + >> >> + quadspi_controller_0: quadspi@0x180014a0 { >> >> + compatible = "altr,quadspi-1.0"; >> >> + reg = <0x180014a0 0x00000020>, >> >> + <0x14000000 0x04000000>; >> >> + reg-names = "avl_csr", "avl_mem"; >> >> + #address-cells = <1>; >> >> + #size-cells = <0>; >> >> + flash0: epcq256@0 { >> >> + compatible = "altr,epcq256"; >> >> + #address-cells = <1>; >> >> + #size-cells = <1>; >> >> + partition@0 { >> >> + /* 16 MB for raw data. */ >> >> + label = "EPCQ Flash 0 raw >> >> data"; + reg = <0x0 >> >> 0x1000000>; + }; >> >> + partition@1000000 { >> >> + /* 16 MB for jffs2 data. >> >> */ + label = "EPCQ Flash 0 >> >> JFFS 2"; + reg = <0x1000000 >> >> 0x1000000>; + }; >> > >> > IIRC, encoding partitions into OF is deprecated (and it shouldn't be >> > part of the example anyway, so please remove this bit). >> > >> >> + }; >> >> + }; //end quadspi@0x180014a0 (quadspi_controller_0) >> > >> > Remove this incorrect comment. >> > >> > >> > [...] >> >> Do you mean the partition part below should not be in example? >> partition@0 { >> /* 16 MB for raw data. */ >> label = "EPCQ Flash 0 raw >> data"; reg = <0x0 0x1000000>; }; >> partition@1000000 { >> /* 16 MB for jffs2 data. */ >> label = "EPCQ Flash 0 JFFS 2"; >> reg = <0x1000000 0x1000000>; >> }; > > Yes, it's not really relevant. > OK >> >> +static struct flash_device flash_devices[] = { >> >> + FLASH_ID("epcs16", EPCS_OPCODE_ID, 0x14), >> >> + FLASH_ID("epcs64", EPCS_OPCODE_ID, 0x16), >> >> + FLASH_ID("epcs128", EPCS_OPCODE_ID, 0x18), >> >> + >> >> + FLASH_ID("epcq16", NON_EPCS_OPCODE_ID, 0x15), >> >> + FLASH_ID("epcq32", NON_EPCS_OPCODE_ID, 0x16), >> >> + FLASH_ID("epcq64", NON_EPCS_OPCODE_ID, 0x17), >> >> + FLASH_ID("epcq128", NON_EPCS_OPCODE_ID, 0x18), >> >> + FLASH_ID("epcq256", NON_EPCS_OPCODE_ID, 0x19), >> >> + FLASH_ID("epcq512", NON_EPCS_OPCODE_ID, 0x20), >> >> + FLASH_ID("epcq1024", NON_EPCS_OPCODE_ID, 0x21), >> >> + >> >> + FLASH_ID("epcql256", NON_EPCS_OPCODE_ID, 0x19), >> >> + FLASH_ID("epcql512", NON_EPCS_OPCODE_ID, 0x20), >> >> + FLASH_ID("epcql1024", NON_EPCS_OPCODE_ID, 0x21), >> >> + >> >> +}; >> > >> > I think it'd be better to wait until the IP block is fixed and can >> > issue READID correctly. >> >> The hardware IP fix will take time while there are lot of customer are >> waiting for this driver. > > Does that justify pushing serious crap into mainline Linux in any way ? > >> That is why we decided to upstream the >> driver. If the hardware fix, there might not need to have any changes >> in driver to support or if yes, it will be just minor. > > If the hardware can do proper READID opcode, this entire nonsense table > will go away and a proper integration into the SPI NOR framework will > take place. > > You might consider submitting this driver for staging, but I definitely > am not a big fan of that. > You might misunderstand the hardware problem i mention here. This soft IP controller is able to provide the ID for our Altera EPCS/EPCQ flash chips, which are non JEDEC chips. As from EPCQ device data sheet (https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cfg/cfg_cf52012.pdf), the device ID is 8 bit data. The remaining problem here is that this controller is able to support Micron chips but it currently has limitation in providing only 8 bit ID, which is not full JEDEC ID for Micron chips. Hence, we are asking hardware engineer to find out the solution so that the driver does not need to do any dirty hacking. And so, this table should still be here even hardware fix will take place or not. >> >> diff --git a/drivers/mtd/spi-nor/spi-nor.c >> >> b/drivers/mtd/spi-nor/spi-nor.c index 14a5d23..2ab7279 100644 >> >> --- a/drivers/mtd/spi-nor/spi-nor.c >> >> +++ b/drivers/mtd/spi-nor/spi-nor.c >> >> @@ -687,6 +687,24 @@ static const struct spi_device_id spi_nor_ids[] = { >> >> >> >> { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | >> >> >> >> SPI_NOR_NO_FR) }, { "cat25c17", CAT25_INFO( 256, 8, 32, 2, >> >> SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25128", CAT25_INFO(2048, 8, >> >> 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, + >> >> + /* Altera EPCQ/EPCS Flashes are non-JEDEC */ >> > >> > Are they really ? Last time I checked on CV SoC, I was able to read their >> > JEDEC ID just fine ; though it's true I used that EPCS core. >> > >> >> + { "epcs16", INFO(0, 0, 0x10000, 32, 0) }, >> >> + { "epcs64", INFO(0, 0, 0x10000, 128, 0) }, >> >> + { "epcs128", INFO(0, 0, 0x40000, 256, 0) }, >> >> + >> >> + { "epcq16", INFO(0, 0, 0x10000, 32, 0) }, >> >> + { "epcq32", INFO(0, 0, 0x10000, 64, 0) }, >> >> + { "epcq64", INFO(0, 0, 0x10000, 128, 0) }, >> >> + { "epcq128", INFO(0, 0, 0x10000, 256, 0) }, >> >> + { "epcq256", INFO(0, 0, 0x10000, 512, 0) }, >> >> + { "epcq512", INFO(0, 0, 0x10000, 1024, 0) }, >> >> + { "epcq1024", INFO(0, 0, 0x10000, 2048, 0) }, >> >> + >> >> + { "epcql256", INFO(0, 0, 0x10000, 512, 0) }, >> >> + { "epcql512", INFO(0, 0, 0x10000, 1024, 0) }, >> >> + { "epcql1024", INFO(0, 0, 0x10000, 2048, 0) }, >> >> + >> >> >> >> { }, >> >> >> >> }; -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thursday, August 20, 2015 at 11:18:14 AM, Viet Nga Dao wrote: Hi, [...] > >> That is why we decided to upstream the > >> driver. If the hardware fix, there might not need to have any changes > >> in driver to support or if yes, it will be just minor. > > > > If the hardware can do proper READID opcode, this entire nonsense table > > will go away and a proper integration into the SPI NOR framework will > > take place. > > > > You might consider submitting this driver for staging, but I definitely > > am not a big fan of that. > > You might misunderstand the hardware problem i mention here. This soft > IP controller is able to provide the ID for our Altera EPCS/EPCQ flash > chips, which are non JEDEC chips. As from EPCQ device data sheet > (https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature > /hb/cfg/cfg_cf52012.pdf), the device ID is 8 bit data. So what exactly is the output of READID instruction followed by 6 Byte read on an EPCQ chip? > The remaining > problem here is that this controller is able to support Micron chips but > it currently has > limitation in providing only 8 bit ID, which is not full JEDEC ID for > Micron chips. OK > Hence, we are asking hardware engineer to find out the > solution so that the driver does not need to do any dirty hacking. And > so, this table should still be here even hardware fix will take place > or not. [...] Best regards, Marek Vasut -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hello Marek, On Thursday 20 August 2015 10:03:38, Marek Vasut wrote: > > +Example: > > + > > + quadspi_controller_0: quadspi@0x180014a0 { > > + compatible = "altr,quadspi-1.0"; > > + reg = <0x180014a0 0x00000020>, > > + <0x14000000 0x04000000>; > > + reg-names = "avl_csr", "avl_mem"; > > + #address-cells = <1>; > > + #size-cells = <0>; > > + flash0: epcq256@0 { > > + compatible = "altr,epcq256"; > > + #address-cells = <1>; > > + #size-cells = <1>; > > + partition@0 { > > + /* 16 MB for raw data. */ > > + label = "EPCQ Flash 0 raw data"; > > + reg = <0x0 0x1000000>; > > + }; > > + partition@1000000 { > > + /* 16 MB for jffs2 data. */ > > + label = "EPCQ Flash 0 JFFS 2"; > > + reg = <0x1000000 0x1000000>; > > + }; > > IIRC, encoding partitions into OF is deprecated (and it shouldn't be > part of the example anyway, so please remove this bit). Do you mean specifying partitions in OF is deprecated in general? Is there any link for that? What would be an alternative to it? Best regards, Alexander
On Thu, Aug 20, 2015 at 12:06:36PM +0200, Alexander Stein wrote: > On Thursday 20 August 2015 10:03:38, Marek Vasut wrote: > > > +Example: > > > + > > > + quadspi_controller_0: quadspi@0x180014a0 { > > > + compatible = "altr,quadspi-1.0"; > > > + reg = <0x180014a0 0x00000020>, > > > + <0x14000000 0x04000000>; > > > + reg-names = "avl_csr", "avl_mem"; > > > + #address-cells = <1>; > > > + #size-cells = <0>; > > > + flash0: epcq256@0 { > > > + compatible = "altr,epcq256"; > > > + #address-cells = <1>; > > > + #size-cells = <1>; > > > + partition@0 { > > > + /* 16 MB for raw data. */ > > > + label = "EPCQ Flash 0 raw data"; > > > + reg = <0x0 0x1000000>; > > > + }; > > > + partition@1000000 { > > > + /* 16 MB for jffs2 data. */ > > > + label = "EPCQ Flash 0 JFFS 2"; > > > + reg = <0x1000000 0x1000000>; > > > + }; > > > > IIRC, encoding partitions into OF is deprecated (and it shouldn't be > > part of the example anyway, so please remove this bit). > > Do you mean specifying partitions in OF is deprecated in general? Is there any link for that? > What would be an alternative to it? This is the first I've heard of such a deprecation. I would argue that it's still probably one of the best ways to specify partitions. It's not exactly perfect (partitions aren't really "hardware", so may not belong in the "hardware description"), but IMO it's better than cmdlineparts, for instance. I also don't really know of any good-enough, generically useful on-flash partition formats, especially ones that can handle the complexities of NAND. Brian -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Aug 20, 2015 at 05:18:14PM +0800, Viet Nga Dao wrote: > You might misunderstand the hardware problem i mention here. This soft > IP controller is able to provide the ID for our Altera EPCS/EPCQ flash > chips, which are non JEDEC chips. As from EPCQ device data sheet > (https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cfg/cfg_cf52012.pdf), > the device ID is 8 bit data. 8 bits of data is vastly insufficient for uniquely identifying a flash. This is not extendible and is not really a candidate for inclusion in mainline, unless it's somehow guaranteed that these flash can only be used with your controller (and I'm not sure how you would do that). Otherwise, you need to augment every flash with more out-of-band device-tree information. > The remaining problem here is that this > controller is able to support Micron chips but it currently has > limitation in providing only 8 bit ID, which is not full JEDEC ID for > Micron chips. You're just proving my point. I will not support "READ ID" detection that is based on only 8 bits of ID. > Hence, we are asking hardware engineer to find out the > solution so that the driver does not need to do any dirty hacking. OK, then I wish your hardware team great speed. > And > so, this table should still be here even hardware fix will take place > or not. I'm not sure how you come to this conclusion. BTW, to reiterate one other question that I feel wasn't adequately answered: what does the full ID string look like for these EPCS/EPCQ flash chips? Not the ID as seen by your limited controller, but the ID that can be reported by the flash chip. Is it really only an 8-bit number? Or does it have a longer string that your controller just can't read? Brian -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Aug 20, 2015 at 11:42:18AM +0200, Marek Vasut wrote: > On Thursday, August 20, 2015 at 11:18:14 AM, Viet Nga Dao wrote: > > You might misunderstand the hardware problem i mention here. This soft > > IP controller is able to provide the ID for our Altera EPCS/EPCQ flash > > chips, which are non JEDEC chips. As from EPCQ device data sheet > > (https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature > > /hb/cfg/cfg_cf52012.pdf), the device ID is 8 bit data. > > So what exactly is the output of READID instruction followed by 6 Byte read > on an EPCQ chip? +1 to this question -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thursday, August 20, 2015 at 10:19:25 PM, Brian Norris wrote: > On Thu, Aug 20, 2015 at 12:06:36PM +0200, Alexander Stein wrote: > > On Thursday 20 August 2015 10:03:38, Marek Vasut wrote: > > > > +Example: > > > > + > > > > + quadspi_controller_0: quadspi@0x180014a0 { > > > > + compatible = "altr,quadspi-1.0"; > > > > + reg = <0x180014a0 0x00000020>, > > > > + <0x14000000 0x04000000>; > > > > + reg-names = "avl_csr", "avl_mem"; > > > > + #address-cells = <1>; > > > > + #size-cells = <0>; > > > > + flash0: epcq256@0 { > > > > + compatible = "altr,epcq256"; > > > > + #address-cells = <1>; > > > > + #size-cells = <1>; > > > > + partition@0 { > > > > + /* 16 MB for raw data. */ > > > > + label = "EPCQ Flash 0 raw data"; > > > > + reg = <0x0 0x1000000>; > > > > + }; > > > > + partition@1000000 { > > > > + /* 16 MB for jffs2 data. */ > > > > + label = "EPCQ Flash 0 JFFS 2"; > > > > + reg = <0x1000000 0x1000000>; > > > > + }; > > > > > > IIRC, encoding partitions into OF is deprecated (and it shouldn't be > > > part of the example anyway, so please remove this bit). > > > > Do you mean specifying partitions in OF is deprecated in general? Is > > there any link for that? What would be an alternative to it? > > This is the first I've heard of such a deprecation. I would argue that > it's still probably one of the best ways to specify partitions. It's not > exactly perfect (partitions aren't really "hardware", so may not belong > in the "hardware description") Which is the reasoning why I heard it was deprecated, but it seems my knowledge is not correct. I apologize for the misinformation, sorry. > , but IMO it's better than cmdlineparts, > for instance. I also don't really know of any good-enough, generically > useful on-flash partition formats, especially ones that can handle the > complexities of NAND. Right. Best regards, Marek Vasut -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, Aug 21, 2015 at 4:37 AM, Brian Norris <computersforpeace@gmail.com> wrote: > On Thu, Aug 20, 2015 at 05:18:14PM +0800, Viet Nga Dao wrote: >> You might misunderstand the hardware problem i mention here. This soft >> IP controller is able to provide the ID for our Altera EPCS/EPCQ flash >> chips, which are non JEDEC chips. As from EPCQ device data sheet >> (https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cfg/cfg_cf52012.pdf), >> the device ID is 8 bit data. > > 8 bits of data is vastly insufficient for uniquely identifying a flash. > This is not extendible and is not really a candidate for inclusion in > mainline, unless it's somehow guaranteed that these flash can only be > used with your controller (and I'm not sure how you would do that). > Otherwise, you need to augment every flash with more out-of-band > device-tree information. > >> The remaining problem here is that this >> controller is able to support Micron chips but it currently has >> limitation in providing only 8 bit ID, which is not full JEDEC ID for >> Micron chips. > > You're just proving my point. I will not support "READ ID" detection > that is based on only 8 bits of ID. > >> Hence, we are asking hardware engineer to find out the >> solution so that the driver does not need to do any dirty hacking. > > OK, then I wish your hardware team great speed. > >> And >> so, this table should still be here even hardware fix will take place >> or not. > > I'm not sure how you come to this conclusion. > I have this conclusion is because Altera EPCQ/EPCS flashes are non JEDEC. Thus on the spi_device_id table, the ID in the INFO struct must be filled up with zeros in order to matches the current framework. However, since i still persist to have the device id check in my driver, as suggested by Rash, I should implement it locally in my driver. And this table is the look up table for the device ID of supported flashes. Or maybe you can give me any other better idea? > BTW, to reiterate one other question that I feel wasn't adequately > answered: what does the full ID string look like for these EPCS/EPCQ > flash chips? Not the ID as seen by your limited controller, but the ID > that can be reported by the flash chip. Is it really only an 8-bit > number? Or does it have a longer string that your controller just can't > read? > Yes, As you can refer to page 32 of EPCQ flash datasheet (https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cfg/cfg_cf52012.pdf), "This operation reads the 8-bit device identification of the EPCQ device from the DATA1 output pin". Table 29 lists the EPCQ device identifications Nga -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Aug 20, 2015 at 2:55 PM, <vndao@altera.com> wrote: > From: VIET NGA DAO <vndao@altera.com> > > Altera Quad SPI Controller is a soft IP which enables access to > Altera EPCS and EPCQ flash chips. This patch adds driver > for these devices. > > Signed-off-by: VIET NGA DAO <vndao@altera.com> > > --- > v5: > - Remove Micron support > - Add multiple flashes probe failure handle > > v4: > - Add more flash devices support ( EPCQL and Micron) > - Remove redundant messages > - Change EPCQ_OPCODE_ID to NON_EPCS_OPCODE_ID > - Replace get_flash_name to altera_quadspi_scan > - Remove clk related parts > - Remove altera_quadspi_plat > - Change device tree reg name and remove opcode-id > > v3: > - Change altera_epcq driver name to altera_quadspi for more generic name > - Implement flash name searching in altera_quadspi.c instead of spi-nor > - Edit the altra quadspi info table in spi-nor > - Remove wait_til_ready in all read,write, erase, lock, unlock functions > - Merge .h and .c into 1 file > > v2: > - Change to spi_nor structure > - Add lock and unlock functions for spi_nor > - Simplify the altera_epcq_lock function > - Replace reg by compatible in device tree > --- Hi, i decided to wait for the hardware fixed and tested before submitting new patch. Thanks for all for your reviews and comments. Viet Nga -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/Documentation/devicetree/bindings/mtd/altera-quadspi.txt b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt new file mode 100644 index 0000000..e1bcf18 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/altera-quadspi.txt @@ -0,0 +1,45 @@ +* MTD Altera QUADSPI driver + +Required properties: +- compatible: Should be "altr,quadspi-1.0" +- reg: Address and length of the register set for the device. It contains + the information of registers in the same order as described by reg-names +- reg-names: Should contain the reg names + "avl_csr": Should contain the register configuration base address + "avl_mem": Should contain the data base address +- #address-cells: Must be <1>. +- #size-cells: Must be <0>. +- flash device tree subnode, there must be a node with the following fields: + - compatible: Should contain the flash name: + 1. EPCS: epcs16, epcs64, epcs128 + 2. EPCQ: epcq16, epcq32, epcq64, epcq128, epcq256, epcq512, epcq1024 + 3. EPCQ-L: epcql256, epcql512, epcql1024 + - #address-cells: please refer to /mtd/partition.txt + - #size-cells: please refer to /mtd/partition.txt + For partitions inside each flash, please refer to /mtd/partition.txt + +Example: + + quadspi_controller_0: quadspi@0x180014a0 { + compatible = "altr,quadspi-1.0"; + reg = <0x180014a0 0x00000020>, + <0x14000000 0x04000000>; + reg-names = "avl_csr", "avl_mem"; + #address-cells = <1>; + #size-cells = <0>; + flash0: epcq256@0 { + compatible = "altr,epcq256"; + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + /* 16 MB for raw data. */ + label = "EPCQ Flash 0 raw data"; + reg = <0x0 0x1000000>; + }; + partition@1000000 { + /* 16 MB for jffs2 data. */ + label = "EPCQ Flash 0 JFFS 2"; + reg = <0x1000000 0x1000000>; + }; + }; + }; //end quadspi@0x180014a0 (quadspi_controller_0) diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index 64a4f0e..5aa1197 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -28,4 +28,12 @@ config SPI_FSL_QUADSPI This enables support for the Quad SPI controller in master mode. We only connect the NOR to this controller now. +config SPI_ALTERA_QUADSPI + tristate "Altera Generic Quad SPI Controller" + depends on OF + help + This enables access to Altera EPCQ/EPCS flash chips, + used for data storage. See the driver source for the current list, + or to add other chips. + endif # MTD_SPI_NOR diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile index 6a7ce14..4e700df 100644 --- a/drivers/mtd/spi-nor/Makefile +++ b/drivers/mtd/spi-nor/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o +obj-$(CONFIG_SPI_ALTERA_QUADSPI) += altera-quadspi.o diff --git a/drivers/mtd/spi-nor/altera-quadspi.c b/drivers/mtd/spi-nor/altera-quadspi.c new file mode 100644 index 0000000..71285a4 --- /dev/null +++ b/drivers/mtd/spi-nor/altera-quadspi.c @@ -0,0 +1,557 @@ +/* + * Copyright (C) 2014 Altera Corporation. All rights reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/log2.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/mtd/spi-nor.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/sched.h> + +#define ALTERA_QUADSPI_RESOURCE_NAME "altera_quadspi" + +/* max possible slots for serial flash chip in the QUADSPI controller */ +#define MAX_NUM_FLASH_CHIP 3 + +#define EPCS_OPCODE_ID 1 +#define NON_EPCS_OPCODE_ID 2 + +#define WRITE_CHECK 1 +#define ERASE_CHECK 0 + +/* Define max times to check status register before we give up. */ +#define QUADSPI_MAX_TIME_OUT (40 * HZ) + +/* defines for status register */ +#define QUADSPI_SR_REG 0x0 +#define QUADSPI_SR_WIP_MASK 0x00000001 +#define QUADSPI_SR_WIP 0x1 +#define QUADSPI_SR_WEL 0x2 +#define QUADSPI_SR_BP0 0x4 +#define QUADSPI_SR_BP1 0x8 +#define QUADSPI_SR_BP2 0x10 +#define QUADSPI_SR_BP3 0x40 +#define QUADSPI_SR_TB 0x20 +#define QUADSPI_SR_MASK 0x0000000F + +/* defines for device id register */ +#define QUADSPI_SID_REG 0x4 +#define QUADSPI_RDID_REG 0x8 +#define QUADSPI_ID_MASK 0x000000FF + +/* + * QUADSPI_MEM_OP register offset + * + * The QUADSPI_MEM_OP register is used to do memory protect and erase operations + * + */ +#define QUADSPI_MEM_OP_REG 0xC + +#define QUADSPI_MEM_OP_CMD_MASK 0x00000003 +#define QUADSPI_MEM_OP_BULK_ERASE_CMD 0x00000001 +#define QUADSPI_MEM_OP_SECTOR_ERASE_CMD 0x00000002 +#define QUADSPI_MEM_OP_SECTOR_PROTECT_CMD 0x00000003 +#define QUADSPI_MEM_OP_SECTOR_VALUE_MASK 0x0003FF00 +#define QUADSPI_MEM_OP_SECTOR_PROTECT_VALUE_MASK 0x00001F00 +#define QUADSPI_MEM_OP_SECTOR_PROTECT_SHIFT 8 +/* + * QUADSPI_ISR register offset + * + * The QUADSPI_ISR register is used to determine whether an invalid write or + * erase operation trigerred an interrupt + * + */ +#define QUADSPI_ISR_REG 0x10 + +#define QUADSPI_ISR_ILLEGAL_ERASE_MASK 0x00000001 +#define QUADSPI_ISR_ILLEGAL_WRITE_MASK 0x00000002 + +/* + * QUADSPI_IMR register offset + * + * The QUADSPI_IMR register is used to mask the invalid erase or the invalid + * write interrupts. + * + */ +#define QUADSPI_IMR_REG 0x14 +#define QUADSPI_IMR_ILLEGAL_ERASE_MASK 0x00000001 + +#define QUADSPI_IMR_ILLEGAL_WRITE_MASK 0x00000002 + +#define QUADSPI_CHIP_SELECT_REG 0x18 +#define QUADSPI_CHIP_SELECT_MASK 0x00000007 +#define QUADSPI_CHIP_SELECT_0 0x00000001 +#define QUADSPI_CHIP_SELECT_1 0x00000002 +#define QUADSPI_CHIP_SELECT_2 0x00000004 + +struct altera_quadspi { + u32 opcode_id; + void __iomem *csr_base; + void __iomem *data_base; + u32 num_flashes; + struct device *dev; + struct altera_quadspi_flash *flash[MAX_NUM_FLASH_CHIP]; + struct device_node *np[MAX_NUM_FLASH_CHIP]; +}; + +struct altera_quadspi_flash { + struct mtd_info mtd; + struct spi_nor nor; + struct altera_quadspi *q; +}; + +struct flash_device { + char *name; + u32 opcode_id; + u32 device_id; +}; + +#define FLASH_ID(_n, _opcode_id, _id) \ +{ \ + .name = (_n), \ + .opcode_id = (_opcode_id), \ + .device_id = (_id), \ +} + +static struct flash_device flash_devices[] = { + FLASH_ID("epcs16", EPCS_OPCODE_ID, 0x14), + FLASH_ID("epcs64", EPCS_OPCODE_ID, 0x16), + FLASH_ID("epcs128", EPCS_OPCODE_ID, 0x18), + + FLASH_ID("epcq16", NON_EPCS_OPCODE_ID, 0x15), + FLASH_ID("epcq32", NON_EPCS_OPCODE_ID, 0x16), + FLASH_ID("epcq64", NON_EPCS_OPCODE_ID, 0x17), + FLASH_ID("epcq128", NON_EPCS_OPCODE_ID, 0x18), + FLASH_ID("epcq256", NON_EPCS_OPCODE_ID, 0x19), + FLASH_ID("epcq512", NON_EPCS_OPCODE_ID, 0x20), + FLASH_ID("epcq1024", NON_EPCS_OPCODE_ID, 0x21), + + FLASH_ID("epcql256", NON_EPCS_OPCODE_ID, 0x19), + FLASH_ID("epcql512", NON_EPCS_OPCODE_ID, 0x20), + FLASH_ID("epcql1024", NON_EPCS_OPCODE_ID, 0x21), + +}; + +static int altera_quadspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *val, + int len, int wr_en) +{ + return 0; +} + +static int altera_quadspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *val, + int len) +{ + struct altera_quadspi_flash *flash = nor->priv; + struct altera_quadspi *q = flash->q; + u32 data = 0; + + memset(val, 0, len); + + switch (opcode) { + case SPINOR_OP_RDSR: + data = readl(q->csr_base + QUADSPI_SR_REG); + *val = (u8)data & QUADSPI_SR_MASK; + break; + case SPINOR_OP_RDID: + if (q->opcode_id == EPCS_OPCODE_ID) + data = readl(q->csr_base + QUADSPI_SID_REG); + else + data = readl(q->csr_base + QUADSPI_RDID_REG); + + *val = (u8)data & QUADSPI_ID_MASK; /* device id */ + break; + default: + *val = 0; + break; + } + return 0; +} + +static int altera_quadspi_write_erase_check(struct spi_nor *nor, + bool write_erase) +{ + struct altera_quadspi_flash *flash = nor->priv; + struct altera_quadspi *q = flash->q; + u32 val; + u32 mask; + + if (write_erase) + mask = QUADSPI_ISR_ILLEGAL_WRITE_MASK; + else + mask = QUADSPI_ISR_ILLEGAL_ERASE_MASK; + + val = readl(q->csr_base + QUADSPI_ISR_REG); + if (val & mask) { + dev_err(nor->dev, + "write/erase failed, sector might be protected\n"); + /* clear this status for next use */ + writel(val, q->csr_base + QUADSPI_ISR_REG); + return -EIO; + } + return 0; +} + +static int altera_quadspi_addr_to_sector(struct mtd_info *mtd, uint64_t offset) +{ + if (mtd->erasesize_shift) + return offset >> mtd->erasesize_shift; + do_div(offset, mtd->erasesize); + return offset; +} + +static int altera_quadspi_erase(struct spi_nor *nor, loff_t offset) +{ + struct altera_quadspi_flash *flash = nor->priv; + struct altera_quadspi *q = flash->q; + struct mtd_info *mtd = &flash->mtd; + u32 val; + int sector_value; + + sector_value = altera_quadspi_addr_to_sector(mtd, offset); + /* sanity check that block_offset is a valid sector number */ + if (sector_value < 0) + return -EINVAL; + + /* sector value should occupy bits 17:8 */ + val = (sector_value << 8) & QUADSPI_MEM_OP_SECTOR_VALUE_MASK; + + /* sector erase commands occupies lower 2 bits */ + val |= QUADSPI_MEM_OP_SECTOR_ERASE_CMD; + + /* write sector erase command to QUADSPI_MEM_OP register */ + writel(val, q->csr_base + QUADSPI_MEM_OP_REG); + + return altera_quadspi_write_erase_check(nor, ERASE_CHECK); +} + +static int altera_quadspi_read(struct spi_nor *nor, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct altera_quadspi_flash *flash = nor->priv; + struct altera_quadspi *q = flash->q; + + memcpy_fromio(buf, q->data_base + from, len); + *retlen = len; + + return 0; +} + +static void altera_quadspi_write(struct spi_nor *nor, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct altera_quadspi_flash *flash = nor->priv; + struct altera_quadspi *q = flash->q; + + memcpy_toio(q->data_base + to, buf, len); + *retlen += len; + + /* check whether write triggered a illegal write interrupt */ + altera_quadspi_write_erase_check(nor, WRITE_CHECK); +} + +static int altera_quadspi_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) +{ + struct altera_quadspi_flash *flash = nor->priv; + struct altera_quadspi *q = flash->q; + struct mtd_info *mtd = &flash->mtd; + uint32_t offset = ofs; + u32 sector_start, sector_end; + uint64_t num_sectors; + u32 mem_op; + u32 sr_bp; + u32 sr_tb; + + sector_start = offset; + sector_end = altera_quadspi_addr_to_sector(mtd, offset + len); + num_sectors = mtd->size; + do_div(num_sectors, mtd->erasesize); + + dev_dbg(nor->dev, "%s: sector start is %u,sector end is %u\n", + __func__, sector_start, sector_end); + + if (sector_start >= num_sectors / 2) { + sr_bp = fls(num_sectors - 1 - sector_start) + 1; + sr_tb = 0; + } else if ((sector_end < num_sectors / 2) && + (q->opcode_id != EPCS_OPCODE_ID)) { + sr_bp = fls(sector_end) + 1; + sr_tb = 1; + } else { + sr_bp = 16; + sr_tb = 0; + } + + mem_op = (sr_tb << 12) | (sr_bp << 8); + mem_op &= QUADSPI_MEM_OP_SECTOR_PROTECT_VALUE_MASK; + mem_op |= QUADSPI_MEM_OP_SECTOR_PROTECT_CMD; + writel(mem_op, q->csr_base + QUADSPI_MEM_OP_REG); + + return 0; +} + +static int altera_quadspi_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) +{ + struct altera_quadspi_flash *flash = nor->priv; + struct altera_quadspi *q = flash->q; + u32 mem_op; + + dev_dbg(nor->dev, "Unlock all protected area\n"); + mem_op = QUADSPI_MEM_OP_SECTOR_PROTECT_CMD; + writel(mem_op, q->csr_base + QUADSPI_MEM_OP_REG); + + return 0; +} + +static void altera_quadspi_chip_select(struct altera_quadspi *q, u32 bank) +{ + u32 val = 0; + + switch (bank) { + case 0: + val = QUADSPI_CHIP_SELECT_0; + break; + case 1: + val = QUADSPI_CHIP_SELECT_1; + break; + case 2: + val = QUADSPI_CHIP_SELECT_2; + break; + default: + dev_err(q->dev, "invalid bank\n"); + return; + } + writel(val, q->csr_base + QUADSPI_CHIP_SELECT_REG); +} + +static int altera_quadspi_probe_config_dt(struct platform_device *pdev, + struct device_node *np, + struct altera_quadspi *q) +{ + struct device_node *pp; + struct resource *quadspi_res; + int i = 0; + + quadspi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "avl_csr"); + q->csr_base = devm_ioremap_resource(&pdev->dev, quadspi_res); + if (IS_ERR(q->csr_base)) { + dev_err(&pdev->dev, "%s: ERROR: failed to map csr base\n", + __func__); + return PTR_ERR(q->csr_base); + } + + quadspi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "avl_mem"); + q->data_base = devm_ioremap_resource(&pdev->dev, quadspi_res); + if (IS_ERR(q->data_base)) { + dev_err(&pdev->dev, "%s: ERROR: failed to map data base\n", + __func__); + return PTR_ERR(q->data_base); + } + + /* Fill structs for each subnode (flash device) */ + for_each_available_child_of_node(np, pp) { + /* Read bank id from DT */ + q->np[i] = pp; + i++; + } + q->num_flashes = i; + return 0; +} + +static int altera_quadspi_scan(struct spi_nor *nor, const char *name) +{ + struct altera_quadspi_flash *flash = nor->priv; + struct altera_quadspi *q = flash->q; + int index; + int ret; + u8 id = 0; + + ret = nor->read_reg(nor, SPINOR_OP_RDID, &id, 1); + if (ret) + return ret; + + for (index = 0; index < ARRAY_SIZE(flash_devices); index++) { + if (flash_devices[index].device_id == id && + strcmp(name, flash_devices[index].name) == 0) { + q->opcode_id = flash_devices[index].opcode_id; + return 0; + } + } + + /* Memory chip is not listed and not supported */ + return -EINVAL; +} + +static int altera_quadspi_setup_banks(struct platform_device *pdev, + u32 bank, struct device_node *np) +{ + struct altera_quadspi *q = platform_get_drvdata(pdev); + struct mtd_part_parser_data ppdata = {}; + struct altera_quadspi_flash *flash; + struct spi_nor *nor; + int ret = 0; + char modalias[40]; + + if (bank > q->num_flashes - 1) + return -EINVAL; + + altera_quadspi_chip_select(q, bank); + + flash = devm_kzalloc(q->dev, sizeof(*flash), GFP_KERNEL); + if (!flash) + return -ENOMEM; + + q->flash[bank] = flash; + nor = &flash->nor; + nor->mtd = &flash->mtd; + nor->dev = &pdev->dev; + nor->priv = flash; + flash->mtd.priv = nor; + flash->q = q; + + /* spi nor framework*/ + nor->read_reg = altera_quadspi_read_reg; + nor->write_reg = altera_quadspi_write_reg; + nor->read = altera_quadspi_read; + nor->write = altera_quadspi_write; + nor->erase = altera_quadspi_erase; + nor->flash_lock = altera_quadspi_lock; + nor->flash_unlock = altera_quadspi_unlock; + + /* scanning flash and checking dev id */ + if (of_modalias_node(np, modalias, sizeof(modalias)) < 0) + return -EINVAL; + + ret = altera_quadspi_scan(nor, modalias); + if (ret) { + dev_err(nor->dev, "flash not found\n"); + return ret; + } + + ret = spi_nor_scan(nor, modalias, SPI_NOR_QUAD); + if (ret) + return ret; + + ppdata.of_node = np; + + return mtd_device_parse_register(&flash->mtd, NULL, &ppdata, NULL, 0); +} + +static int altera_quadspi_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct altera_quadspi *q; + int ret = 0; + int i; + int count; + + if (!np) { + dev_err(dev, "no device found\n"); + return -ENODEV; + } + + q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL); + if (!q) + return -ENOMEM; + + ret = altera_quadspi_probe_config_dt(pdev, np, q); + if (ret) { + dev_err(dev, "probe device tree failed\n"); + return -ENODEV; + } + + q->dev = dev; + + /* check number of flashes */ + if (q->num_flashes > MAX_NUM_FLASH_CHIP) { + dev_err(dev, "exceeding max number of flashes\n"); + q->num_flashes = MAX_NUM_FLASH_CHIP; + } + + platform_set_drvdata(pdev, q); + + /* count is number of successful setup chips */ + count = q->num_flashes; + /* loop for each serial flash which is connected to quadspi */ + for (i = 0; i < q->num_flashes; i++) { + ret = altera_quadspi_setup_banks(pdev, i, q->np[i]); + if (ret) { + dev_err(dev, "bank %d setup failed\n", i); + count--; + } + } + return (count > 0) ? 0 : -ENODEV; +} + +static int altera_quadspi_remove(struct platform_device *pdev) +{ + struct altera_quadspi *q = platform_get_drvdata(pdev); + struct altera_quadspi_flash *flash; + int i; + int ret = 0; + + /* clean up for all nor flash */ + for (i = 0; i < q->num_flashes; i++) { + flash = q->flash[i]; + if (!flash) + continue; + + /* clean up mtd stuff */ + ret = mtd_device_unregister(&flash->mtd); + if (ret) { + dev_err(&pdev->dev, "error removing mtd\n"); + return ret; + } + } + + return 0; +} + +static const struct of_device_id altera_quadspi_id_table[] = { + { .compatible = "altr,quadspi-1.0" }, + {} +}; +MODULE_DEVICE_TABLE(of, altera_quadspi_id_table); + +static struct platform_driver altera_quadspi_driver = { + .driver = { + .name = ALTERA_QUADSPI_RESOURCE_NAME, + .of_match_table = altera_quadspi_id_table, + }, + .probe = altera_quadspi_probe, + .remove = altera_quadspi_remove, +}; +module_platform_driver(altera_quadspi_driver); + +MODULE_AUTHOR("Viet Nga Dao <vndao@altera.com>"); +MODULE_DESCRIPTION("Altera QuadSPI Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 14a5d23..2ab7279 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -687,6 +687,24 @@ static const struct spi_device_id spi_nor_ids[] = { { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, + + /* Altera EPCQ/EPCS Flashes are non-JEDEC */ + { "epcs16", INFO(0, 0, 0x10000, 32, 0) }, + { "epcs64", INFO(0, 0, 0x10000, 128, 0) }, + { "epcs128", INFO(0, 0, 0x40000, 256, 0) }, + + { "epcq16", INFO(0, 0, 0x10000, 32, 0) }, + { "epcq32", INFO(0, 0, 0x10000, 64, 0) }, + { "epcq64", INFO(0, 0, 0x10000, 128, 0) }, + { "epcq128", INFO(0, 0, 0x10000, 256, 0) }, + { "epcq256", INFO(0, 0, 0x10000, 512, 0) }, + { "epcq512", INFO(0, 0, 0x10000, 1024, 0) }, + { "epcq1024", INFO(0, 0, 0x10000, 2048, 0) }, + + { "epcql256", INFO(0, 0, 0x10000, 512, 0) }, + { "epcql512", INFO(0, 0, 0x10000, 1024, 0) }, + { "epcql1024", INFO(0, 0, 0x10000, 2048, 0) }, + { }, };