From f06e1588fbd18a03ad0ed0c1b3f82ab4e9d9a6c9 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Thu, 13 Oct 2016 15:53:17 +0530 Subject: ARM: dts: am437x-idk: Fix QSPI compatible string Unlike Linux kernel, U-Boot depends on "spi-flash" compatible to probe m25p80 spi-nor devices. Hence, add "spi-flash" compatible string to m25p80 node. Without this patch, flash device DT data is not parsed and QSPI operates in unsupported mode leading to data corruption. Signed-off-by: Vignesh R Reviewed-by: Jagan Teki diff --git a/arch/arm/dts/am437x-idk-evm.dts b/arch/arm/dts/am437x-idk-evm.dts index 478f0a6..e454647 100644 --- a/arch/arm/dts/am437x-idk-evm.dts +++ b/arch/arm/dts/am437x-idk-evm.dts @@ -341,7 +341,7 @@ spi-max-frequency = <48000000>; m25p80@0 { - compatible = "mx66l51235l"; + compatible = "mx66l51235l", "spi-flash"; spi-max-frequency = <48000000>; reg = <0>; spi-cpol; -- cgit v0.10.2 From 1b7c28f5147144d7902d048ca90be58987899c25 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 29 Nov 2016 20:00:13 -0700 Subject: spi: Add error checking for invalid bus widths At present an invalid bus width prints a message but does not return an error. This is the opposite of the correct behaviour. Adjust it to avoid code bloat in the common case, and avoid hard-to-debug failure in the uncommon case. Signed-off-by: Simon Glass Reviewed-by: Jagan Teki diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index f59a701..1ab5b75 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -418,7 +418,7 @@ int spi_slave_ofdata_to_platdata(const void *blob, int node, mode |= SPI_TX_QUAD; break; default: - error("spi-tx-bus-width %d not supported\n", value); + warn_non_spl("spi-tx-bus-width %d not supported\n", value); break; } @@ -433,7 +433,7 @@ int spi_slave_ofdata_to_platdata(const void *blob, int node, mode |= SPI_RX_QUAD; break; default: - error("spi-rx-bus-width %d not supported\n", value); + warn_non_spl("spi-rx-bus-width %d not supported\n", value); break; } -- cgit v0.10.2 From cc80a897e4fafbd9e9b6920eb866f0600a5cd5ee Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 29 Nov 2016 12:58:26 +0000 Subject: spi: cadence_qspi: Fix clearing of pol/pha bits Or'ing together bit positions is clearly wrong. Signed-off-by: Phil Edworthy Acked-by: Marek Vasut Reviewed-by: Jagan Teki diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index e285d3c..2403e71 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -311,8 +311,8 @@ void cadence_qspi_apb_set_clk_mode(void *reg_base, cadence_qspi_apb_controller_disable(reg_base); reg = readl(reg_base + CQSPI_REG_CONFIG); - reg &= ~(1 << - (CQSPI_REG_CONFIG_CLK_POL_LSB | CQSPI_REG_CONFIG_CLK_PHA_LSB)); + reg &= ~(1 << CQSPI_REG_CONFIG_CLK_POL_LSB); + reg &= ~(1 << CQSPI_REG_CONFIG_CLK_PHA_LSB); reg |= ((clk_pol & 0x1) << CQSPI_REG_CONFIG_CLK_POL_LSB); reg |= ((clk_pha & 0x1) << CQSPI_REG_CONFIG_CLK_PHA_LSB); -- cgit v0.10.2 From 32068c42a7230ad1ef756ed7a201cc3b3c580076 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 29 Nov 2016 12:58:27 +0000 Subject: spi: cadence_qspi: Fix baud rate calculation With the existing code, when the requested SPI clock rate is near to the lowest that can be achieved by the hardware (max divider of the ref clock is 32), the generated clock rate is wrong. For example, with a 50MHz ref clock, when asked for anything less than a 1.5MHz SPI clock, the code sets up the divider to generate 25MHz. This change fixes the calculation. Signed-off-by: Phil Edworthy Reviewed-by: Jagan Teki diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 2403e71..b5c664f 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -273,22 +273,12 @@ void cadence_qspi_apb_config_baudrate_div(void *reg_base, reg = readl(reg_base + CQSPI_REG_CONFIG); reg &= ~(CQSPI_REG_CONFIG_BAUD_MASK << CQSPI_REG_CONFIG_BAUD_LSB); - div = ref_clk_hz / sclk_hz; - - if (div > 32) - div = 32; - - /* Check if even number. */ - if ((div & 1)) { - div = (div / 2); - } else { - if (ref_clk_hz % sclk_hz) - /* ensure generated SCLK doesn't exceed user - specified sclk_hz */ - div = (div / 2); - else - div = (div / 2) - 1; - } + /* + * The baud_div field in the config reg is 4 bits, and the ref clock is + * divided by 2 * (baud_div + 1). Round up the divider to ensure the + * SPI clock rate is less than or equal to the requested clock rate. + */ + div = DIV_ROUND_UP(ref_clk_hz, sclk_hz * 2) - 1; debug("%s: ref_clk %dHz sclk %dHz Div 0x%x\n", __func__, ref_clk_hz, sclk_hz, div); -- cgit v0.10.2 From 0ceb4d9e9a64dcc662ea52150feebed37deda716 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 29 Nov 2016 12:58:28 +0000 Subject: spi: cadence_qspi: Better debug information on the SPI clock rate Show what the output clock rate actually is. Signed-off-by: Phil Edworthy Acked-by: Marek Vasut Reviewed-by: Jagan Teki diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index b5c664f..0a2963d 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -280,13 +280,13 @@ void cadence_qspi_apb_config_baudrate_div(void *reg_base, */ div = DIV_ROUND_UP(ref_clk_hz, sclk_hz * 2) - 1; - debug("%s: ref_clk %dHz sclk %dHz Div 0x%x\n", __func__, - ref_clk_hz, sclk_hz, div); - /* ensure the baud rate doesn't exceed the max value */ if (div > CQSPI_REG_CONFIG_BAUD_MASK) div = CQSPI_REG_CONFIG_BAUD_MASK; + debug("%s: ref_clk %dHz sclk %dHz Div 0x%x, actual %dHz\n", __func__, + ref_clk_hz, sclk_hz, div, ref_clk_hz / (2 * (div + 1))); + reg |= (div << CQSPI_REG_CONFIG_BAUD_LSB); writel(reg, reg_base + CQSPI_REG_CONFIG); -- cgit v0.10.2 From db37cc9c3954d5e33b218e5635e7e08ff902e3f6 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 29 Nov 2016 12:58:29 +0000 Subject: spi: cadence_qspi: Use #define for bits instead of bit shifts Most of the code already uses #defines for the bit value, rather than the shift required to get the value. This changes the remaining code over. Whislt at it, fix the names of the "Rd Data Capture" register defs. Signed-off-by: Phil Edworthy Acked-by: Marek Vasut Reviewed-by: Jagan Teki diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 0a2963d..b41f36b 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -57,9 +57,9 @@ * Controller's configuration and status register (offset from QSPI_BASE) ****************************************************************************/ #define CQSPI_REG_CONFIG 0x00 -#define CQSPI_REG_CONFIG_CLK_POL_LSB 1 -#define CQSPI_REG_CONFIG_CLK_PHA_LSB 2 #define CQSPI_REG_CONFIG_ENABLE_MASK BIT(0) +#define CQSPI_REG_CONFIG_CLK_POL BIT(1) +#define CQSPI_REG_CONFIG_CLK_PHA BIT(2) #define CQSPI_REG_CONFIG_DIRECT_MASK BIT(7) #define CQSPI_REG_CONFIG_DECODE_MASK BIT(9) #define CQSPI_REG_CONFIG_XIP_IMM_MASK BIT(18) @@ -94,10 +94,10 @@ #define CQSPI_REG_DELAY_TSD2D_MASK 0xFF #define CQSPI_REG_DELAY_TSHSL_MASK 0xFF -#define CQSPI_READLCAPTURE 0x10 -#define CQSPI_READLCAPTURE_BYPASS_LSB 0 -#define CQSPI_READLCAPTURE_DELAY_LSB 1 -#define CQSPI_READLCAPTURE_DELAY_MASK 0xF +#define CQSPI_REG_RD_DATA_CAPTURE 0x10 +#define CQSPI_REG_RD_DATA_CAPTURE_BYPASS BIT(0) +#define CQSPI_REG_RD_DATA_CAPTURE_DELAY_LSB 1 +#define CQSPI_REG_RD_DATA_CAPTURE_DELAY_MASK 0xF #define CQSPI_REG_SIZE 0x14 #define CQSPI_REG_SIZE_ADDRESS_LSB 0 @@ -244,20 +244,20 @@ void cadence_qspi_apb_readdata_capture(void *reg_base, unsigned int reg; cadence_qspi_apb_controller_disable(reg_base); - reg = readl(reg_base + CQSPI_READLCAPTURE); + reg = readl(reg_base + CQSPI_REG_RD_DATA_CAPTURE); if (bypass) - reg |= (1 << CQSPI_READLCAPTURE_BYPASS_LSB); + reg |= CQSPI_REG_RD_DATA_CAPTURE_BYPASS; else - reg &= ~(1 << CQSPI_READLCAPTURE_BYPASS_LSB); + reg &= ~CQSPI_REG_RD_DATA_CAPTURE_BYPASS; - reg &= ~(CQSPI_READLCAPTURE_DELAY_MASK - << CQSPI_READLCAPTURE_DELAY_LSB); + reg &= ~(CQSPI_REG_RD_DATA_CAPTURE_DELAY_MASK + << CQSPI_REG_RD_DATA_CAPTURE_DELAY_LSB); - reg |= ((delay & CQSPI_READLCAPTURE_DELAY_MASK) - << CQSPI_READLCAPTURE_DELAY_LSB); + reg |= (delay & CQSPI_REG_RD_DATA_CAPTURE_DELAY_MASK) + << CQSPI_REG_RD_DATA_CAPTURE_DELAY_LSB; - writel(reg, reg_base + CQSPI_READLCAPTURE); + writel(reg, reg_base + CQSPI_REG_RD_DATA_CAPTURE); cadence_qspi_apb_controller_enable(reg_base); return; @@ -301,11 +301,12 @@ void cadence_qspi_apb_set_clk_mode(void *reg_base, cadence_qspi_apb_controller_disable(reg_base); reg = readl(reg_base + CQSPI_REG_CONFIG); - reg &= ~(1 << CQSPI_REG_CONFIG_CLK_POL_LSB); - reg &= ~(1 << CQSPI_REG_CONFIG_CLK_PHA_LSB); + reg &= ~(CQSPI_REG_CONFIG_CLK_POL | CQSPI_REG_CONFIG_CLK_PHA); - reg |= ((clk_pol & 0x1) << CQSPI_REG_CONFIG_CLK_POL_LSB); - reg |= ((clk_pha & 0x1) << CQSPI_REG_CONFIG_CLK_PHA_LSB); + if (clk_pol) + reg |= CQSPI_REG_CONFIG_CLK_POL; + if (clk_pha) + reg |= CQSPI_REG_CONFIG_CLK_PHA; writel(reg, reg_base + CQSPI_REG_CONFIG); -- cgit v0.10.2 From 7e76c4b08a30c0a90813ae56cd876555bef8d9f6 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 29 Nov 2016 12:58:30 +0000 Subject: spi: cadence_qspi: Clean up the #define names A lot of the #defines are for single bits in a register, where the name has _MASK on the end. Since this can be used for both a mask and the value, remove _MASK from them. Whilst doing so, also remove the unnecessary brackets around the constants. Signed-off-by: Phil Edworthy Acked-by: Marek Vasut Reviewed-by: Jagan Teki diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index b41f36b..634a857 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -32,37 +32,37 @@ #include #include "cadence_qspi.h" -#define CQSPI_REG_POLL_US (1) /* 1us */ -#define CQSPI_REG_RETRY (10000) -#define CQSPI_POLL_IDLE_RETRY (3) +#define CQSPI_REG_POLL_US 1 /* 1us */ +#define CQSPI_REG_RETRY 10000 +#define CQSPI_POLL_IDLE_RETRY 3 -#define CQSPI_FIFO_WIDTH (4) +#define CQSPI_FIFO_WIDTH 4 -#define CQSPI_REG_SRAM_THRESHOLD_WORDS (50) +#define CQSPI_REG_SRAM_THRESHOLD_WORDS 50 /* Transfer mode */ -#define CQSPI_INST_TYPE_SINGLE (0) -#define CQSPI_INST_TYPE_DUAL (1) -#define CQSPI_INST_TYPE_QUAD (2) +#define CQSPI_INST_TYPE_SINGLE 0 +#define CQSPI_INST_TYPE_DUAL 1 +#define CQSPI_INST_TYPE_QUAD 2 -#define CQSPI_STIG_DATA_LEN_MAX (8) - -#define CQSPI_DUMMY_CLKS_PER_BYTE (8) -#define CQSPI_DUMMY_BYTES_MAX (4) +#define CQSPI_STIG_DATA_LEN_MAX 8 +#define CQSPI_DUMMY_CLKS_PER_BYTE 8 +#define CQSPI_DUMMY_BYTES_MAX 4 #define CQSPI_REG_SRAM_FILL_THRESHOLD \ ((CQSPI_REG_SRAM_SIZE_WORD / 2) * CQSPI_FIFO_WIDTH) + /**************************************************************************** * Controller's configuration and status register (offset from QSPI_BASE) ****************************************************************************/ #define CQSPI_REG_CONFIG 0x00 -#define CQSPI_REG_CONFIG_ENABLE_MASK BIT(0) +#define CQSPI_REG_CONFIG_ENABLE BIT(0) #define CQSPI_REG_CONFIG_CLK_POL BIT(1) #define CQSPI_REG_CONFIG_CLK_PHA BIT(2) -#define CQSPI_REG_CONFIG_DIRECT_MASK BIT(7) -#define CQSPI_REG_CONFIG_DECODE_MASK BIT(9) -#define CQSPI_REG_CONFIG_XIP_IMM_MASK BIT(18) +#define CQSPI_REG_CONFIG_DIRECT BIT(7) +#define CQSPI_REG_CONFIG_DECODE BIT(9) +#define CQSPI_REG_CONFIG_XIP_IMM BIT(18) #define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10 #define CQSPI_REG_CONFIG_BAUD_LSB 19 #define CQSPI_REG_CONFIG_IDLE_LSB 31 @@ -123,18 +123,18 @@ #define CQSPI_REG_IRQMASK 0x44 #define CQSPI_REG_INDIRECTRD 0x60 -#define CQSPI_REG_INDIRECTRD_START_MASK BIT(0) -#define CQSPI_REG_INDIRECTRD_CANCEL_MASK BIT(1) -#define CQSPI_REG_INDIRECTRD_INPROGRESS_MASK BIT(2) -#define CQSPI_REG_INDIRECTRD_DONE_MASK BIT(5) +#define CQSPI_REG_INDIRECTRD_START BIT(0) +#define CQSPI_REG_INDIRECTRD_CANCEL BIT(1) +#define CQSPI_REG_INDIRECTRD_INPROGRESS BIT(2) +#define CQSPI_REG_INDIRECTRD_DONE BIT(5) #define CQSPI_REG_INDIRECTRDWATERMARK 0x64 #define CQSPI_REG_INDIRECTRDSTARTADDR 0x68 #define CQSPI_REG_INDIRECTRDBYTES 0x6C #define CQSPI_REG_CMDCTRL 0x90 -#define CQSPI_REG_CMDCTRL_EXECUTE_MASK BIT(0) -#define CQSPI_REG_CMDCTRL_INPROGRESS_MASK BIT(1) +#define CQSPI_REG_CMDCTRL_EXECUTE BIT(0) +#define CQSPI_REG_CMDCTRL_INPROGRESS BIT(1) #define CQSPI_REG_CMDCTRL_DUMMY_LSB 7 #define CQSPI_REG_CMDCTRL_WR_BYTES_LSB 12 #define CQSPI_REG_CMDCTRL_WR_EN_LSB 15 @@ -150,10 +150,10 @@ #define CQSPI_REG_CMDCTRL_OPCODE_MASK 0xFF #define CQSPI_REG_INDIRECTWR 0x70 -#define CQSPI_REG_INDIRECTWR_START_MASK BIT(0) -#define CQSPI_REG_INDIRECTWR_CANCEL_MASK BIT(1) -#define CQSPI_REG_INDIRECTWR_INPROGRESS_MASK BIT(2) -#define CQSPI_REG_INDIRECTWR_DONE_MASK BIT(5) +#define CQSPI_REG_INDIRECTWR_START BIT(0) +#define CQSPI_REG_INDIRECTWR_CANCEL BIT(1) +#define CQSPI_REG_INDIRECTWR_INPROGRESS BIT(2) +#define CQSPI_REG_INDIRECTWR_DONE BIT(5) #define CQSPI_REG_INDIRECTWRWATERMARK 0x74 #define CQSPI_REG_INDIRECTWRSTARTADDR 0x78 @@ -197,7 +197,7 @@ void cadence_qspi_apb_controller_enable(void *reg_base) { unsigned int reg; reg = readl(reg_base + CQSPI_REG_CONFIG); - reg |= CQSPI_REG_CONFIG_ENABLE_MASK; + reg |= CQSPI_REG_CONFIG_ENABLE; writel(reg, reg_base + CQSPI_REG_CONFIG); return; } @@ -206,7 +206,7 @@ void cadence_qspi_apb_controller_disable(void *reg_base) { unsigned int reg; reg = readl(reg_base + CQSPI_REG_CONFIG); - reg &= ~CQSPI_REG_CONFIG_ENABLE_MASK; + reg &= ~CQSPI_REG_CONFIG_ENABLE; writel(reg, reg_base + CQSPI_REG_CONFIG); return; } @@ -327,9 +327,9 @@ void cadence_qspi_apb_chipselect(void *reg_base, reg = readl(reg_base + CQSPI_REG_CONFIG); /* docoder */ if (decoder_enable) { - reg |= CQSPI_REG_CONFIG_DECODE_MASK; + reg |= CQSPI_REG_CONFIG_DECODE; } else { - reg &= ~CQSPI_REG_CONFIG_DECODE_MASK; + reg &= ~CQSPI_REG_CONFIG_DECODE; /* Convert CS if without decoder. * CS0 to 4b'1110 * CS1 to 4b'1101 @@ -423,12 +423,12 @@ static int cadence_qspi_apb_exec_flash_cmd(void *reg_base, /* Write the CMDCTRL without start execution. */ writel(reg, reg_base + CQSPI_REG_CMDCTRL); /* Start execute */ - reg |= CQSPI_REG_CMDCTRL_EXECUTE_MASK; + reg |= CQSPI_REG_CMDCTRL_EXECUTE; writel(reg, reg_base + CQSPI_REG_CMDCTRL); while (retry--) { reg = readl(reg_base + CQSPI_REG_CMDCTRL); - if ((reg & CQSPI_REG_CMDCTRL_INPROGRESS_MASK) == 0) + if ((reg & CQSPI_REG_CMDCTRL_INPROGRESS) == 0) break; udelay(1); } @@ -646,7 +646,7 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, writel(n_rx, plat->regbase + CQSPI_REG_INDIRECTRDBYTES); /* Start the indirect read transfer */ - writel(CQSPI_REG_INDIRECTRD_START_MASK, + writel(CQSPI_REG_INDIRECTRD_START, plat->regbase + CQSPI_REG_INDIRECTRD); while (remaining > 0) { @@ -675,21 +675,21 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, /* Check indirect done status */ ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTRD, - CQSPI_REG_INDIRECTRD_DONE_MASK, 1, 10, 0); + CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0); if (ret) { printf("Indirect read completion error (%i)\n", ret); goto failrd; } /* Clear indirect completion status */ - writel(CQSPI_REG_INDIRECTRD_DONE_MASK, + writel(CQSPI_REG_INDIRECTRD_DONE, plat->regbase + CQSPI_REG_INDIRECTRD); return 0; failrd: /* Cancel the indirect read */ - writel(CQSPI_REG_INDIRECTRD_CANCEL_MASK, + writel(CQSPI_REG_INDIRECTRD_CANCEL, plat->regbase + CQSPI_REG_INDIRECTRD); return ret; } @@ -737,7 +737,7 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, writel(n_tx, plat->regbase + CQSPI_REG_INDIRECTWRBYTES); /* Start the indirect write transfer */ - writel(CQSPI_REG_INDIRECTWR_START_MASK, + writel(CQSPI_REG_INDIRECTWR_START, plat->regbase + CQSPI_REG_INDIRECTWR); while (remaining > 0) { @@ -762,20 +762,20 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, /* Check indirect done status */ ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTWR, - CQSPI_REG_INDIRECTWR_DONE_MASK, 1, 10, 0); + CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0); if (ret) { printf("Indirect write completion error (%i)\n", ret); goto failwr; } /* Clear indirect completion status */ - writel(CQSPI_REG_INDIRECTWR_DONE_MASK, + writel(CQSPI_REG_INDIRECTWR_DONE, plat->regbase + CQSPI_REG_INDIRECTWR); return 0; failwr: /* Cancel the indirect write */ - writel(CQSPI_REG_INDIRECTWR_CANCEL_MASK, + writel(CQSPI_REG_INDIRECTWR_CANCEL, plat->regbase + CQSPI_REG_INDIRECTWR); return ret; } @@ -786,9 +786,9 @@ void cadence_qspi_apb_enter_xip(void *reg_base, char xip_dummy) /* enter XiP mode immediately and enable direct mode */ reg = readl(reg_base + CQSPI_REG_CONFIG); - reg |= CQSPI_REG_CONFIG_ENABLE_MASK; - reg |= CQSPI_REG_CONFIG_DIRECT_MASK; - reg |= CQSPI_REG_CONFIG_XIP_IMM_MASK; + reg |= CQSPI_REG_CONFIG_ENABLE; + reg |= CQSPI_REG_CONFIG_DIRECT; + reg |= CQSPI_REG_CONFIG_XIP_IMM; writel(reg, reg_base + CQSPI_REG_CONFIG); /* keep the XiP mode */ -- cgit v0.10.2 From 7d403f284c814d6df9f1d116e691d6468c75282a Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 29 Nov 2016 12:58:31 +0000 Subject: spi: cadence_qspi: Use spi mode at the point it is needed Instead of extracting mode settings and passing them as separate args to another function, just pass the SPI mode as an arg. Signed-off-by: Phil Edworthy Reviewed-by: Jagan Teki diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 1051afb..55192d6 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -170,14 +170,12 @@ static int cadence_spi_probe(struct udevice *bus) static int cadence_spi_set_mode(struct udevice *bus, uint mode) { struct cadence_spi_priv *priv = dev_get_priv(bus); - unsigned int clk_pol = (mode & SPI_CPOL) ? 1 : 0; - unsigned int clk_pha = (mode & SPI_CPHA) ? 1 : 0; /* Disable QSPI */ cadence_qspi_apb_controller_disable(priv->regbase); /* Set SPI mode */ - cadence_qspi_apb_set_clk_mode(priv->regbase, clk_pol, clk_pha); + cadence_qspi_apb_set_clk_mode(priv->regbase, mode); /* Enable QSPI */ cadence_qspi_apb_controller_enable(priv->regbase); diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index a849f7b..d1927a4 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -63,8 +63,7 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, void cadence_qspi_apb_chipselect(void *reg_base, unsigned int chip_select, unsigned int decoder_enable); -void cadence_qspi_apb_set_clk_mode(void *reg_base_addr, - unsigned int clk_pol, unsigned int clk_pha); +void cadence_qspi_apb_set_clk_mode(void *reg_base, uint mode); void cadence_qspi_apb_config_baudrate_div(void *reg_base, unsigned int ref_clk_hz, unsigned int sclk_hz); void cadence_qspi_apb_delay(void *reg_base, diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 634a857..e81d678 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -294,8 +294,7 @@ void cadence_qspi_apb_config_baudrate_div(void *reg_base, return; } -void cadence_qspi_apb_set_clk_mode(void *reg_base, - unsigned int clk_pol, unsigned int clk_pha) +void cadence_qspi_apb_set_clk_mode(void *reg_base, uint mode) { unsigned int reg; @@ -303,9 +302,9 @@ void cadence_qspi_apb_set_clk_mode(void *reg_base, reg = readl(reg_base + CQSPI_REG_CONFIG); reg &= ~(CQSPI_REG_CONFIG_CLK_POL | CQSPI_REG_CONFIG_CLK_PHA); - if (clk_pol) + if (mode & SPI_CPOL) reg |= CQSPI_REG_CONFIG_CLK_POL; - if (clk_pha) + if (mode & SPI_CPHA) reg |= CQSPI_REG_CONFIG_CLK_PHA; writel(reg, reg_base + CQSPI_REG_CONFIG); -- cgit v0.10.2 From 3c5695321929d3c3d1936cb8a7773566af0886b5 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 29 Nov 2016 12:58:32 +0000 Subject: spi: cadence_qspi: Remove returns from end of void functions Signed-off-by: Phil Edworthy Acked-by: Marek Vasut Reviewed-by: Jagan Teki diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index e81d678..39e31f6 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -199,7 +199,6 @@ void cadence_qspi_apb_controller_enable(void *reg_base) reg = readl(reg_base + CQSPI_REG_CONFIG); reg |= CQSPI_REG_CONFIG_ENABLE; writel(reg, reg_base + CQSPI_REG_CONFIG); - return; } void cadence_qspi_apb_controller_disable(void *reg_base) @@ -208,7 +207,6 @@ void cadence_qspi_apb_controller_disable(void *reg_base) reg = readl(reg_base + CQSPI_REG_CONFIG); reg &= ~CQSPI_REG_CONFIG_ENABLE; writel(reg, reg_base + CQSPI_REG_CONFIG); - return; } /* Return 1 if idle, otherwise return 0 (busy). */ @@ -260,7 +258,6 @@ void cadence_qspi_apb_readdata_capture(void *reg_base, writel(reg, reg_base + CQSPI_REG_RD_DATA_CAPTURE); cadence_qspi_apb_controller_enable(reg_base); - return; } void cadence_qspi_apb_config_baudrate_div(void *reg_base, @@ -291,7 +288,6 @@ void cadence_qspi_apb_config_baudrate_div(void *reg_base, writel(reg, reg_base + CQSPI_REG_CONFIG); cadence_qspi_apb_controller_enable(reg_base); - return; } void cadence_qspi_apb_set_clk_mode(void *reg_base, uint mode) @@ -310,7 +306,6 @@ void cadence_qspi_apb_set_clk_mode(void *reg_base, uint mode) writel(reg, reg_base + CQSPI_REG_CONFIG); cadence_qspi_apb_controller_enable(reg_base); - return; } void cadence_qspi_apb_chipselect(void *reg_base, @@ -345,7 +340,6 @@ void cadence_qspi_apb_chipselect(void *reg_base, writel(reg, reg_base + CQSPI_REG_CONFIG); cadence_qspi_apb_controller_enable(reg_base); - return; } void cadence_qspi_apb_delay(void *reg_base, @@ -383,7 +377,6 @@ void cadence_qspi_apb_delay(void *reg_base, writel(reg, reg_base + CQSPI_REG_DELAY); cadence_qspi_apb_controller_enable(reg_base); - return; } void cadence_qspi_apb_controller_init(struct cadence_spi_platdata *plat) @@ -411,7 +404,6 @@ void cadence_qspi_apb_controller_init(struct cadence_spi_platdata *plat) writel(0, plat->regbase + CQSPI_REG_IRQMASK); cadence_qspi_apb_controller_enable(plat->regbase); - return; } static int cadence_qspi_apb_exec_flash_cmd(void *reg_base, -- cgit v0.10.2 From 22e63ff3a23d189187d96dbcec50e94233027b3a Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 29 Nov 2016 12:58:33 +0000 Subject: spi: cadence_qspi: Fix CS timings The Cadence QSPI controller has specified overheads for the various CS times that are in addition to those programmed in to the Device Delay register. The overheads are different for the delays. In addition, the existing code does not handle the case when the delay is less than a SCLK period. This change accurately calculates the additional delays in Ref clocks. Signed-off-by: Phil Edworthy Reviewed-by: Jagan Teki diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 39e31f6..df6a91f 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -169,9 +169,6 @@ ((readl(base + CQSPI_REG_CONFIG) >> \ CQSPI_REG_CONFIG_IDLE_LSB) & 0x1) -#define CQSPI_CAL_DELAY(tdelay_ns, tref_ns, tsclk_ns) \ - ((((tdelay_ns) - (tsclk_ns)) / (tref_ns))) - #define CQSPI_GET_RD_SRAM_LEVEL(reg_base) \ (((readl(reg_base + CQSPI_REG_SDRAMLEVEL)) >> \ CQSPI_REG_SDRAMLEVEL_RD_LSB) & CQSPI_REG_SDRAMLEVEL_RD_MASK) @@ -355,16 +352,20 @@ void cadence_qspi_apb_delay(void *reg_base, cadence_qspi_apb_controller_disable(reg_base); /* Convert to ns. */ - ref_clk_ns = (1000000000) / ref_clk; + ref_clk_ns = DIV_ROUND_UP(1000000000, ref_clk); /* Convert to ns. */ - sclk_ns = (1000000000) / sclk_hz; - - /* Plus 1 to round up 1 clock cycle. */ - tshsl = CQSPI_CAL_DELAY(tshsl_ns, ref_clk_ns, sclk_ns) + 1; - tchsh = CQSPI_CAL_DELAY(tchsh_ns, ref_clk_ns, sclk_ns) + 1; - tslch = CQSPI_CAL_DELAY(tslch_ns, ref_clk_ns, sclk_ns) + 1; - tsd2d = CQSPI_CAL_DELAY(tsd2d_ns, ref_clk_ns, sclk_ns) + 1; + sclk_ns = DIV_ROUND_UP(1000000000, sclk_hz); + + /* The controller adds additional delay to that programmed in the reg */ + if (tshsl_ns >= sclk_ns + ref_clk_ns) + tshsl_ns -= sclk_ns + ref_clk_ns; + if (tchsh_ns >= sclk_ns + 3 * ref_clk_ns) + tchsh_ns -= sclk_ns + 3 * ref_clk_ns; + tshsl = DIV_ROUND_UP(tshsl_ns, ref_clk_ns); + tchsh = DIV_ROUND_UP(tchsh_ns, ref_clk_ns); + tslch = DIV_ROUND_UP(tslch_ns, ref_clk_ns); + tsd2d = DIV_ROUND_UP(tsd2d_ns, ref_clk_ns); reg = ((tshsl & CQSPI_REG_DELAY_TSHSL_MASK) << CQSPI_REG_DELAY_TSHSL_LSB); -- cgit v0.10.2 From 6d72810c6640e13b4c1e25f6c26ac8c304d5b54e Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Tue, 29 Nov 2016 12:58:34 +0000 Subject: spi: cadence_qspi: Move DT prop code to match layout Move the code to read the "sram-size" property into the other code that reads properties from the node, rather than the SF subnode. Signed-off-by: Phil Edworthy Reviewed-by: Jagan Teki diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 55192d6..f16f90d 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -296,6 +296,7 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus) plat->regbase = (void *)data[0]; plat->ahbbase = (void *)data[2]; + plat->sram_size = fdtdec_get_int(blob, node, "sram-size", 128); /* All other paramters are embedded in the child node */ subnode = fdt_first_subnode(blob, node); @@ -315,7 +316,6 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus) plat->tsd2d_ns = fdtdec_get_int(blob, subnode, "tsd2d-ns", 255); plat->tchsh_ns = fdtdec_get_int(blob, subnode, "tchsh-ns", 20); plat->tslch_ns = fdtdec_get_int(blob, subnode, "tslch-ns", 20); - plat->sram_size = fdtdec_get_int(blob, node, "sram-size", 128); debug("%s: regbase=%p ahbbase=%p max-frequency=%d page-size=%d\n", __func__, plat->regbase, plat->ahbbase, plat->max_hz, -- cgit v0.10.2 From 304decdd31d54ae274f785fb086f3f6ae30a8711 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Mon, 5 Dec 2016 19:09:10 +0100 Subject: mtd: spi: don't return -1 when scan succeed In spi_flash_scan, 'ret' is initialled to -1, but 'ret' is not always used to store a return value, in that case, even when the function succeed, an error (-1) will be returned. Lets just return 0 if we hit the end of the function. Signed-off-by: Fabien Parent Reviewed-by: Jagan Teki diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 94c0b00..41fc0a6 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -1000,7 +1000,7 @@ int spi_flash_scan(struct spi_flash *flash) { struct spi_slave *spi = flash->spi; const struct spi_flash_info *info = NULL; - int ret = -1; + int ret; info = spi_flash_read_id(flash); if (IS_ERR_OR_NULL(info)) @@ -1166,5 +1166,5 @@ int spi_flash_scan(struct spi_flash *flash) } #endif - return ret; + return 0; } -- cgit v0.10.2 From db9225ba2686d6b7e249d00e1803bd07f71d6070 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Fri, 9 Dec 2016 15:03:39 +0000 Subject: sf: Do not force the DT memory map size to exactly match the device As long as the memory mapped size specifeid in the DT is the same or bigger than the device size, it will work. So do not force the sizes to be identical. Signed-off-by: Phil Edworthy Reviewed-by: Jagan Teki diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 41fc0a6..b902540 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -985,7 +985,7 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) return 0; } - if (flash->size != size) { + if (flash->size > size) { debug("%s: Memory map must cover entire device\n", __func__); return -1; } -- cgit v0.10.2 From 9bcb0188708594f7f2d86ddff3ec1fc8c1364e0d Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Thu, 15 Dec 2016 17:45:39 +0100 Subject: Revert "sf: Fix quad bit set for micron devices" This reverts commit c56ae7519f141523ba1248b22b5b5169b21772fe. Once the 'Quad Enable' bit is cleared in their Enhanced Volatile Configuration Register (EVCR), Micron memories expect ALL commands to use the SPI 4-4-4 protocol. Commands using SPI 1-y-z protocols are no longer accepted. Within the reverted commit, the write_evcr() function is implemented using the spi_flash_write_common(), which is a shortcut for the [ spi_flash_cmd_write_enable(), spi_flash_cmd_write(), spi_flash_cmd_wait_ready() ] sequence. Since the internal state of the Micron memory has been changed when the spi_flash_cmd_write() function completes, the later call of the spi_flash_cmd_wait_ready() function fails. Indeed the SPI controller driver is not aware of the SPI protocol switch. Further patches will fix the support of Micron QSPI memories. Signed-off-by: Cyrille Pitchen [Rebase on master, use JEDEC_MFR(info) in place of idcode0] Signed-off-by: Jagan Teki diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 2463686..839cdbe 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -49,7 +49,6 @@ enum spi_nor_option_flags { #define CMD_WRITE_DISABLE 0x04 #define CMD_WRITE_ENABLE 0x06 #define CMD_QUAD_PAGE_PROGRAM 0x32 -#define CMD_WRITE_EVCR 0x61 /* Read commands */ #define CMD_READ_ARRAY_SLOW 0x03 @@ -63,7 +62,6 @@ enum spi_nor_option_flags { #define CMD_READ_STATUS1 0x35 #define CMD_READ_CONFIG 0x35 #define CMD_FLAG_STATUS 0x70 -#define CMD_READ_EVCR 0x65 /* Bank addr access commands */ #ifdef CONFIG_SPI_FLASH_BAR @@ -78,7 +76,6 @@ enum spi_nor_option_flags { #define STATUS_QEB_WINSPAN BIT(1) #define STATUS_QEB_MXIC BIT(6) #define STATUS_PEC BIT(7) -#define STATUS_QEB_MICRON BIT(7) #define SR_BP0 BIT(2) /* Block protect 0 */ #define SR_BP1 BIT(3) /* Block protect 1 */ #define SR_BP2 BIT(4) /* Block protect 2 */ diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index b902540..2e378dc 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -112,37 +112,6 @@ static int write_cr(struct spi_flash *flash, u8 wc) } #endif -#ifdef CONFIG_SPI_FLASH_STMICRO -static int read_evcr(struct spi_flash *flash, u8 *evcr) -{ - int ret; - const u8 cmd = CMD_READ_EVCR; - - ret = spi_flash_read_common(flash, &cmd, 1, evcr, 1); - if (ret < 0) { - debug("SF: error reading EVCR\n"); - return ret; - } - - return 0; -} - -static int write_evcr(struct spi_flash *flash, u8 evcr) -{ - u8 cmd; - int ret; - - cmd = CMD_WRITE_EVCR; - ret = spi_flash_write_common(flash, &cmd, 1, &evcr, 1); - if (ret < 0) { - debug("SF: error while writing EVCR register\n"); - return ret; - } - - return 0; -} -#endif - #ifdef CONFIG_SPI_FLASH_BAR static int write_bar(struct spi_flash *flash, u32 offset) { @@ -894,34 +863,6 @@ static int spansion_quad_enable(struct spi_flash *flash) } #endif -#ifdef CONFIG_SPI_FLASH_STMICRO -static int micron_quad_enable(struct spi_flash *flash) -{ - u8 qeb_status; - int ret; - - ret = read_evcr(flash, &qeb_status); - if (ret < 0) - return ret; - - if (!(qeb_status & STATUS_QEB_MICRON)) - return 0; - - ret = write_evcr(flash, qeb_status & ~STATUS_QEB_MICRON); - if (ret < 0) - return ret; - - /* read EVCR and check it */ - ret = read_evcr(flash, &qeb_status); - if (!(ret >= 0 && !(qeb_status & STATUS_QEB_MICRON))) { - printf("SF: Micron EVCR Quad bit not clear\n"); - return -EINVAL; - } - - return ret; -} -#endif - static const struct spi_flash_info *spi_flash_read_id(struct spi_flash *flash) { int tmp; @@ -962,7 +903,8 @@ static int set_quad_mode(struct spi_flash *flash, #endif #ifdef CONFIG_SPI_FLASH_STMICRO case SPI_FLASH_CFI_MFR_STMICRO: - return micron_quad_enable(flash); + debug("SF: QEB is volatile for %02x flash\n", JEDEC_MFR(info)); + return 0; #endif default: printf("SF: Need set QEB func for %02x flash\n", -- cgit v0.10.2