Loading drivers/spi/spi-armada-3700.c +48 −97 Original line number Diff line number Diff line Loading @@ -99,11 +99,6 @@ /* A3700_SPI_IF_TIME_REG */ #define A3700_SPI_CLK_CAPT_EDGE BIT(7) /* Flags and macros for struct a3700_spi */ #define A3700_INSTR_CNT 1 #define A3700_ADDR_CNT 3 #define A3700_DUMMY_CNT 1 struct a3700_spi { struct spi_master *master; void __iomem *base; Loading @@ -117,9 +112,6 @@ struct a3700_spi { u8 byte_len; u32 wait_mask; struct completion done; u32 addr_cnt; u32 instr_cnt; size_t hdr_cnt; }; static u32 spireg_read(struct a3700_spi *a3700_spi, u32 offset) Loading Loading @@ -161,7 +153,7 @@ static void a3700_spi_deactivate_cs(struct a3700_spi *a3700_spi, } static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, unsigned int pin_mode) unsigned int pin_mode, bool receiving) { u32 val; Loading @@ -177,6 +169,9 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, break; case SPI_NBITS_QUAD: val |= A3700_SPI_DATA_PIN1; /* RX during address reception uses 4-pin */ if (receiving) val |= A3700_SPI_ADDR_PIN; break; default: dev_err(&a3700_spi->master->dev, "wrong pin mode %u", pin_mode); Loading Loading @@ -392,7 +387,8 @@ static bool a3700_spi_wait_completion(struct spi_device *spi) spireg_write(a3700_spi, A3700_SPI_INT_MASK_REG, 0); return true; /* Timeout was reached */ return false; } static bool a3700_spi_transfer_wait(struct spi_device *spi, Loading Loading @@ -446,53 +442,35 @@ static void a3700_spi_set_cs(struct spi_device *spi, bool enable) static void a3700_spi_header_set(struct a3700_spi *a3700_spi) { u32 instr_cnt = 0, addr_cnt = 0, dummy_cnt = 0; unsigned int addr_cnt; u32 val = 0; /* Clear the header registers */ spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_RMODE_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, 0); /* Set header counters */ if (a3700_spi->tx_buf) { if (a3700_spi->buf_len <= a3700_spi->instr_cnt) { instr_cnt = a3700_spi->buf_len; } else if (a3700_spi->buf_len <= (a3700_spi->instr_cnt + a3700_spi->addr_cnt)) { instr_cnt = a3700_spi->instr_cnt; addr_cnt = a3700_spi->buf_len - instr_cnt; } else if (a3700_spi->buf_len <= a3700_spi->hdr_cnt) { instr_cnt = a3700_spi->instr_cnt; addr_cnt = a3700_spi->addr_cnt; /* Need to handle the normal write case with 1 byte * data /* * when tx data is not 4 bytes aligned, there will be unexpected * bytes out of SPI output register, since it always shifts out * as whole 4 bytes. This might cause incorrect transaction with * some devices. To avoid that, use SPI header count feature to * transfer up to 3 bytes of data first, and then make the rest * of data 4-byte aligned. */ if (!a3700_spi->tx_buf[instr_cnt + addr_cnt]) dummy_cnt = a3700_spi->buf_len - instr_cnt - addr_cnt; } val |= ((instr_cnt & A3700_SPI_INSTR_CNT_MASK) << A3700_SPI_INSTR_CNT_BIT); val |= ((addr_cnt & A3700_SPI_ADDR_CNT_MASK) << A3700_SPI_ADDR_CNT_BIT); val |= ((dummy_cnt & A3700_SPI_DUMMY_CNT_MASK) << A3700_SPI_DUMMY_CNT_BIT); } addr_cnt = a3700_spi->buf_len % 4; if (addr_cnt) { val = (addr_cnt & A3700_SPI_ADDR_CNT_MASK) << A3700_SPI_ADDR_CNT_BIT; spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, val); /* Update the buffer length to be transferred */ a3700_spi->buf_len -= (instr_cnt + addr_cnt + dummy_cnt); a3700_spi->buf_len -= addr_cnt; /* Set Instruction */ val = 0; while (instr_cnt--) { val = (val << 8) | a3700_spi->tx_buf[0]; a3700_spi->tx_buf++; } spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, val); /* Set Address */ /* transfer 1~3 bytes through address count */ val = 0; while (addr_cnt--) { val = (val << 8) | a3700_spi->tx_buf[0]; Loading @@ -500,6 +478,8 @@ static void a3700_spi_header_set(struct a3700_spi *a3700_spi) } spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, val); } } } static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi) { Loading @@ -512,35 +492,12 @@ static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi) static int a3700_spi_fifo_write(struct a3700_spi *a3700_spi) { u32 val; int i = 0; while (!a3700_is_wfifo_full(a3700_spi) && a3700_spi->buf_len) { val = 0; if (a3700_spi->buf_len >= 4) { val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf); spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); a3700_spi->buf_len -= 4; a3700_spi->tx_buf += 4; } else { /* * If the remained buffer length is less than 4-bytes, * we should pad the write buffer with all ones. So that * it avoids overwrite the unexpected bytes following * the last one. */ val = GENMASK(31, 0); while (a3700_spi->buf_len) { val &= ~(0xff << (8 * i)); val |= *a3700_spi->tx_buf++ << (8 * i); i++; a3700_spi->buf_len--; spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); } break; } } return 0; Loading Loading @@ -645,15 +602,18 @@ static int a3700_spi_transfer_one(struct spi_master *master, a3700_spi->rx_buf = xfer->rx_buf; a3700_spi->buf_len = xfer->len; /* SPI transfer headers */ a3700_spi_header_set(a3700_spi); if (xfer->tx_buf) nbits = xfer->tx_nbits; else if (xfer->rx_buf) nbits = xfer->rx_nbits; a3700_spi_pin_mode_set(a3700_spi, nbits); a3700_spi_pin_mode_set(a3700_spi, nbits, xfer->rx_buf ? true : false); /* Flush the FIFOs */ a3700_spi_fifo_flush(a3700_spi); /* Transfer first bytes of data when buffer is not 4-byte aligned */ a3700_spi_header_set(a3700_spi); if (xfer->rx_buf) { /* Set read data length */ Loading Loading @@ -733,17 +693,12 @@ static int a3700_spi_transfer_one(struct spi_master *master, dev_err(&spi->dev, "wait wfifo empty timed out\n"); return -ETIMEDOUT; } } else { /* * If the instruction in SPI_INSTR does not require data * to be written to the SPI device, wait until SPI_RDY * is 1 for the SPI interface to be in idle. */ } if (!a3700_spi_transfer_wait(spi, A3700_SPI_XFER_RDY)) { dev_err(&spi->dev, "wait xfer ready timed out\n"); return -ETIMEDOUT; } } val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG); val |= A3700_SPI_XFER_STOP; Loading Loading @@ -834,10 +789,6 @@ static int a3700_spi_probe(struct platform_device *pdev) memset(spi, 0, sizeof(struct a3700_spi)); spi->master = master; spi->instr_cnt = A3700_INSTR_CNT; spi->addr_cnt = A3700_ADDR_CNT; spi->hdr_cnt = A3700_INSTR_CNT + A3700_ADDR_CNT + A3700_DUMMY_CNT; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi->base = devm_ioremap_resource(dev, res); Loading drivers/spi/spi-bcm-qspi.c +5 −4 Original line number Diff line number Diff line Loading @@ -1250,7 +1250,7 @@ int bcm_qspi_probe(struct platform_device *pdev, goto qspi_probe_err; } } else { goto qspi_probe_err; goto qspi_resource_err; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi"); Loading @@ -1272,7 +1272,7 @@ int bcm_qspi_probe(struct platform_device *pdev, qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res); if (IS_ERR(qspi->base[CHIP_SELECT])) { ret = PTR_ERR(qspi->base[CHIP_SELECT]); goto qspi_probe_err; goto qspi_resource_err; } } Loading @@ -1280,7 +1280,7 @@ int bcm_qspi_probe(struct platform_device *pdev, GFP_KERNEL); if (!qspi->dev_ids) { ret = -ENOMEM; goto qspi_probe_err; goto qspi_resource_err; } for (val = 0; val < num_irqs; val++) { Loading Loading @@ -1369,8 +1369,9 @@ int bcm_qspi_probe(struct platform_device *pdev, bcm_qspi_hw_uninit(qspi); clk_disable_unprepare(qspi->clk); qspi_probe_err: spi_master_put(master); kfree(qspi->dev_ids); qspi_resource_err: spi_master_put(master); return ret; } /* probe function to be called by SoC specific platform driver probe */ Loading drivers/spi/spi-stm32.c +2 −2 Original line number Diff line number Diff line Loading @@ -263,8 +263,8 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz) * no need to check it there. * However, we need to ensure the following calculations. */ if ((div < SPI_MBR_DIV_MIN) && (div > SPI_MBR_DIV_MAX)) if (div < SPI_MBR_DIV_MIN || div > SPI_MBR_DIV_MAX) return -EINVAL; /* Determine the first power of 2 greater than or equal to div */ Loading drivers/spi/spi.c +9 −4 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ #define CREATE_TRACE_POINTS #include <trace/events/spi.h> #define SPI_DYN_FIRST_BUS_NUM 0 static DEFINE_IDR(spi_master_idr); Loading Loading @@ -2086,7 +2085,7 @@ int spi_register_controller(struct spi_controller *ctlr) struct device *dev = ctlr->dev.parent; struct boardinfo *bi; int status = -ENODEV; int id; int id, first_dynamic; if (!dev) return -ENODEV; Loading Loading @@ -2116,9 +2115,15 @@ int spi_register_controller(struct spi_controller *ctlr) } } if (ctlr->bus_num < 0) { first_dynamic = of_alias_get_highest_id("spi"); if (first_dynamic < 0) first_dynamic = 0; else first_dynamic++; mutex_lock(&board_lock); id = idr_alloc(&spi_master_idr, ctlr, SPI_DYN_FIRST_BUS_NUM, 0, GFP_KERNEL); id = idr_alloc(&spi_master_idr, ctlr, first_dynamic, 0, GFP_KERNEL); mutex_unlock(&board_lock); if (WARN(id < 0, "couldn't get idr")) return id; Loading include/uapi/linux/spi/spidev.h +1 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #define SPIDEV_H #include <linux/types.h> #include <linux/ioctl.h> /* User space versions of kernel symbols for SPI clocking modes, * matching <linux/spi/spi.h> Loading Loading
drivers/spi/spi-armada-3700.c +48 −97 Original line number Diff line number Diff line Loading @@ -99,11 +99,6 @@ /* A3700_SPI_IF_TIME_REG */ #define A3700_SPI_CLK_CAPT_EDGE BIT(7) /* Flags and macros for struct a3700_spi */ #define A3700_INSTR_CNT 1 #define A3700_ADDR_CNT 3 #define A3700_DUMMY_CNT 1 struct a3700_spi { struct spi_master *master; void __iomem *base; Loading @@ -117,9 +112,6 @@ struct a3700_spi { u8 byte_len; u32 wait_mask; struct completion done; u32 addr_cnt; u32 instr_cnt; size_t hdr_cnt; }; static u32 spireg_read(struct a3700_spi *a3700_spi, u32 offset) Loading Loading @@ -161,7 +153,7 @@ static void a3700_spi_deactivate_cs(struct a3700_spi *a3700_spi, } static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, unsigned int pin_mode) unsigned int pin_mode, bool receiving) { u32 val; Loading @@ -177,6 +169,9 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, break; case SPI_NBITS_QUAD: val |= A3700_SPI_DATA_PIN1; /* RX during address reception uses 4-pin */ if (receiving) val |= A3700_SPI_ADDR_PIN; break; default: dev_err(&a3700_spi->master->dev, "wrong pin mode %u", pin_mode); Loading Loading @@ -392,7 +387,8 @@ static bool a3700_spi_wait_completion(struct spi_device *spi) spireg_write(a3700_spi, A3700_SPI_INT_MASK_REG, 0); return true; /* Timeout was reached */ return false; } static bool a3700_spi_transfer_wait(struct spi_device *spi, Loading Loading @@ -446,53 +442,35 @@ static void a3700_spi_set_cs(struct spi_device *spi, bool enable) static void a3700_spi_header_set(struct a3700_spi *a3700_spi) { u32 instr_cnt = 0, addr_cnt = 0, dummy_cnt = 0; unsigned int addr_cnt; u32 val = 0; /* Clear the header registers */ spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_RMODE_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, 0); /* Set header counters */ if (a3700_spi->tx_buf) { if (a3700_spi->buf_len <= a3700_spi->instr_cnt) { instr_cnt = a3700_spi->buf_len; } else if (a3700_spi->buf_len <= (a3700_spi->instr_cnt + a3700_spi->addr_cnt)) { instr_cnt = a3700_spi->instr_cnt; addr_cnt = a3700_spi->buf_len - instr_cnt; } else if (a3700_spi->buf_len <= a3700_spi->hdr_cnt) { instr_cnt = a3700_spi->instr_cnt; addr_cnt = a3700_spi->addr_cnt; /* Need to handle the normal write case with 1 byte * data /* * when tx data is not 4 bytes aligned, there will be unexpected * bytes out of SPI output register, since it always shifts out * as whole 4 bytes. This might cause incorrect transaction with * some devices. To avoid that, use SPI header count feature to * transfer up to 3 bytes of data first, and then make the rest * of data 4-byte aligned. */ if (!a3700_spi->tx_buf[instr_cnt + addr_cnt]) dummy_cnt = a3700_spi->buf_len - instr_cnt - addr_cnt; } val |= ((instr_cnt & A3700_SPI_INSTR_CNT_MASK) << A3700_SPI_INSTR_CNT_BIT); val |= ((addr_cnt & A3700_SPI_ADDR_CNT_MASK) << A3700_SPI_ADDR_CNT_BIT); val |= ((dummy_cnt & A3700_SPI_DUMMY_CNT_MASK) << A3700_SPI_DUMMY_CNT_BIT); } addr_cnt = a3700_spi->buf_len % 4; if (addr_cnt) { val = (addr_cnt & A3700_SPI_ADDR_CNT_MASK) << A3700_SPI_ADDR_CNT_BIT; spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, val); /* Update the buffer length to be transferred */ a3700_spi->buf_len -= (instr_cnt + addr_cnt + dummy_cnt); a3700_spi->buf_len -= addr_cnt; /* Set Instruction */ val = 0; while (instr_cnt--) { val = (val << 8) | a3700_spi->tx_buf[0]; a3700_spi->tx_buf++; } spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, val); /* Set Address */ /* transfer 1~3 bytes through address count */ val = 0; while (addr_cnt--) { val = (val << 8) | a3700_spi->tx_buf[0]; Loading @@ -500,6 +478,8 @@ static void a3700_spi_header_set(struct a3700_spi *a3700_spi) } spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, val); } } } static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi) { Loading @@ -512,35 +492,12 @@ static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi) static int a3700_spi_fifo_write(struct a3700_spi *a3700_spi) { u32 val; int i = 0; while (!a3700_is_wfifo_full(a3700_spi) && a3700_spi->buf_len) { val = 0; if (a3700_spi->buf_len >= 4) { val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf); spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); a3700_spi->buf_len -= 4; a3700_spi->tx_buf += 4; } else { /* * If the remained buffer length is less than 4-bytes, * we should pad the write buffer with all ones. So that * it avoids overwrite the unexpected bytes following * the last one. */ val = GENMASK(31, 0); while (a3700_spi->buf_len) { val &= ~(0xff << (8 * i)); val |= *a3700_spi->tx_buf++ << (8 * i); i++; a3700_spi->buf_len--; spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); } break; } } return 0; Loading Loading @@ -645,15 +602,18 @@ static int a3700_spi_transfer_one(struct spi_master *master, a3700_spi->rx_buf = xfer->rx_buf; a3700_spi->buf_len = xfer->len; /* SPI transfer headers */ a3700_spi_header_set(a3700_spi); if (xfer->tx_buf) nbits = xfer->tx_nbits; else if (xfer->rx_buf) nbits = xfer->rx_nbits; a3700_spi_pin_mode_set(a3700_spi, nbits); a3700_spi_pin_mode_set(a3700_spi, nbits, xfer->rx_buf ? true : false); /* Flush the FIFOs */ a3700_spi_fifo_flush(a3700_spi); /* Transfer first bytes of data when buffer is not 4-byte aligned */ a3700_spi_header_set(a3700_spi); if (xfer->rx_buf) { /* Set read data length */ Loading Loading @@ -733,17 +693,12 @@ static int a3700_spi_transfer_one(struct spi_master *master, dev_err(&spi->dev, "wait wfifo empty timed out\n"); return -ETIMEDOUT; } } else { /* * If the instruction in SPI_INSTR does not require data * to be written to the SPI device, wait until SPI_RDY * is 1 for the SPI interface to be in idle. */ } if (!a3700_spi_transfer_wait(spi, A3700_SPI_XFER_RDY)) { dev_err(&spi->dev, "wait xfer ready timed out\n"); return -ETIMEDOUT; } } val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG); val |= A3700_SPI_XFER_STOP; Loading Loading @@ -834,10 +789,6 @@ static int a3700_spi_probe(struct platform_device *pdev) memset(spi, 0, sizeof(struct a3700_spi)); spi->master = master; spi->instr_cnt = A3700_INSTR_CNT; spi->addr_cnt = A3700_ADDR_CNT; spi->hdr_cnt = A3700_INSTR_CNT + A3700_ADDR_CNT + A3700_DUMMY_CNT; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi->base = devm_ioremap_resource(dev, res); Loading
drivers/spi/spi-bcm-qspi.c +5 −4 Original line number Diff line number Diff line Loading @@ -1250,7 +1250,7 @@ int bcm_qspi_probe(struct platform_device *pdev, goto qspi_probe_err; } } else { goto qspi_probe_err; goto qspi_resource_err; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi"); Loading @@ -1272,7 +1272,7 @@ int bcm_qspi_probe(struct platform_device *pdev, qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res); if (IS_ERR(qspi->base[CHIP_SELECT])) { ret = PTR_ERR(qspi->base[CHIP_SELECT]); goto qspi_probe_err; goto qspi_resource_err; } } Loading @@ -1280,7 +1280,7 @@ int bcm_qspi_probe(struct platform_device *pdev, GFP_KERNEL); if (!qspi->dev_ids) { ret = -ENOMEM; goto qspi_probe_err; goto qspi_resource_err; } for (val = 0; val < num_irqs; val++) { Loading Loading @@ -1369,8 +1369,9 @@ int bcm_qspi_probe(struct platform_device *pdev, bcm_qspi_hw_uninit(qspi); clk_disable_unprepare(qspi->clk); qspi_probe_err: spi_master_put(master); kfree(qspi->dev_ids); qspi_resource_err: spi_master_put(master); return ret; } /* probe function to be called by SoC specific platform driver probe */ Loading
drivers/spi/spi-stm32.c +2 −2 Original line number Diff line number Diff line Loading @@ -263,8 +263,8 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz) * no need to check it there. * However, we need to ensure the following calculations. */ if ((div < SPI_MBR_DIV_MIN) && (div > SPI_MBR_DIV_MAX)) if (div < SPI_MBR_DIV_MIN || div > SPI_MBR_DIV_MAX) return -EINVAL; /* Determine the first power of 2 greater than or equal to div */ Loading
drivers/spi/spi.c +9 −4 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ #define CREATE_TRACE_POINTS #include <trace/events/spi.h> #define SPI_DYN_FIRST_BUS_NUM 0 static DEFINE_IDR(spi_master_idr); Loading Loading @@ -2086,7 +2085,7 @@ int spi_register_controller(struct spi_controller *ctlr) struct device *dev = ctlr->dev.parent; struct boardinfo *bi; int status = -ENODEV; int id; int id, first_dynamic; if (!dev) return -ENODEV; Loading Loading @@ -2116,9 +2115,15 @@ int spi_register_controller(struct spi_controller *ctlr) } } if (ctlr->bus_num < 0) { first_dynamic = of_alias_get_highest_id("spi"); if (first_dynamic < 0) first_dynamic = 0; else first_dynamic++; mutex_lock(&board_lock); id = idr_alloc(&spi_master_idr, ctlr, SPI_DYN_FIRST_BUS_NUM, 0, GFP_KERNEL); id = idr_alloc(&spi_master_idr, ctlr, first_dynamic, 0, GFP_KERNEL); mutex_unlock(&board_lock); if (WARN(id < 0, "couldn't get idr")) return id; Loading
include/uapi/linux/spi/spidev.h +1 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #define SPIDEV_H #include <linux/types.h> #include <linux/ioctl.h> /* User space versions of kernel symbols for SPI clocking modes, * matching <linux/spi/spi.h> Loading