Loading Documentation/devicetree/bindings/spi/samsung,spi.yaml +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ properties: compatible: oneOf: - enum: - google,gs101-spi - samsung,s3c2443-spi # for S3C2443, S3C2416 and S3C2450 - samsung,s3c6410-spi - samsung,s5pv210-spi # for S5PV210 and S5PC110 Loading drivers/spi/spi-s3c64xx.c +70 −15 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ #include <linux/platform_data/spi-s3c64xx.h> #define MAX_SPI_PORTS 12 #define MAX_SPI_PORTS 16 #define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1) #define AUTOSUSPEND_TIMEOUT 2000 Loading Loading @@ -142,6 +142,7 @@ struct s3c64xx_spi_dma_data { * prescaler unit. * @clk_ioclk: True if clock is present on this device * @has_loopback: True if loopback mode can be supported * @use_32bit_io: True if the SoC allows only 32-bit register accesses. * * The Samsung s3c64xx SPI controller are used on various Samsung SoC's but * differ in some aspects such as the size of the fifo and spi bus clock Loading @@ -158,6 +159,7 @@ struct s3c64xx_spi_port_config { bool clk_from_cmu; bool clk_ioclk; bool has_loopback; bool use_32bit_io; }; /** Loading Loading @@ -414,6 +416,56 @@ static bool s3c64xx_spi_can_dma(struct spi_controller *host, } static void s3c64xx_iowrite8_32_rep(volatile void __iomem *addr, const void *buffer, unsigned int count) { if (count) { const u8 *buf = buffer; do { __raw_writel(*buf++, addr); } while (--count); } } static void s3c64xx_iowrite16_32_rep(volatile void __iomem *addr, const void *buffer, unsigned int count) { if (count) { const u16 *buf = buffer; do { __raw_writel(*buf++, addr); } while (--count); } } static void s3c64xx_iowrite_rep(const struct s3c64xx_spi_driver_data *sdd, struct spi_transfer *xfer) { void __iomem *addr = sdd->regs + S3C64XX_SPI_TX_DATA; const void *buf = xfer->tx_buf; unsigned int len = xfer->len; switch (sdd->cur_bpw) { case 32: iowrite32_rep(addr, buf, len / 4); break; case 16: if (sdd->port_conf->use_32bit_io) s3c64xx_iowrite16_32_rep(addr, buf, len / 2); else iowrite16_rep(addr, buf, len / 2); break; default: if (sdd->port_conf->use_32bit_io) s3c64xx_iowrite8_32_rep(addr, buf, len); else iowrite8_rep(addr, buf, len); break; } } static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd, struct spi_transfer *xfer, int dma_mode) { Loading Loading @@ -447,20 +499,7 @@ static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd, modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; ret = prepare_dma(&sdd->tx_dma, &xfer->tx_sg); } else { switch (sdd->cur_bpw) { case 32: iowrite32_rep(regs + S3C64XX_SPI_TX_DATA, xfer->tx_buf, xfer->len / 4); break; case 16: iowrite16_rep(regs + S3C64XX_SPI_TX_DATA, xfer->tx_buf, xfer->len / 2); break; default: iowrite8_rep(regs + S3C64XX_SPI_TX_DATA, xfer->tx_buf, xfer->len); break; } s3c64xx_iowrite_rep(sdd, xfer); } } Loading Loading @@ -1495,6 +1534,19 @@ static const struct s3c64xx_spi_port_config fsd_spi_port_config = { .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; static const struct s3c64xx_spi_port_config gs101_spi_port_config = { .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, .rx_lvl_offset = 15, .tx_st_done = 25, .clk_div = 4, .high_speed = true, .clk_from_cmu = true, .has_loopback = true, .use_32bit_io = true, .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; static const struct platform_device_id s3c64xx_spi_driver_ids[] = { { .name = "s3c2443-spi", Loading @@ -1507,6 +1559,9 @@ static const struct platform_device_id s3c64xx_spi_driver_ids[] = { }; static const struct of_device_id s3c64xx_spi_dt_match[] = { { .compatible = "google,gs101-spi", .data = &gs101_spi_port_config, }, { .compatible = "samsung,s3c2443-spi", .data = (void *)&s3c2443_spi_port_config, }, Loading Loading
Documentation/devicetree/bindings/spi/samsung,spi.yaml +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ properties: compatible: oneOf: - enum: - google,gs101-spi - samsung,s3c2443-spi # for S3C2443, S3C2416 and S3C2450 - samsung,s3c6410-spi - samsung,s5pv210-spi # for S5PV210 and S5PC110 Loading
drivers/spi/spi-s3c64xx.c +70 −15 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ #include <linux/platform_data/spi-s3c64xx.h> #define MAX_SPI_PORTS 12 #define MAX_SPI_PORTS 16 #define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1) #define AUTOSUSPEND_TIMEOUT 2000 Loading Loading @@ -142,6 +142,7 @@ struct s3c64xx_spi_dma_data { * prescaler unit. * @clk_ioclk: True if clock is present on this device * @has_loopback: True if loopback mode can be supported * @use_32bit_io: True if the SoC allows only 32-bit register accesses. * * The Samsung s3c64xx SPI controller are used on various Samsung SoC's but * differ in some aspects such as the size of the fifo and spi bus clock Loading @@ -158,6 +159,7 @@ struct s3c64xx_spi_port_config { bool clk_from_cmu; bool clk_ioclk; bool has_loopback; bool use_32bit_io; }; /** Loading Loading @@ -414,6 +416,56 @@ static bool s3c64xx_spi_can_dma(struct spi_controller *host, } static void s3c64xx_iowrite8_32_rep(volatile void __iomem *addr, const void *buffer, unsigned int count) { if (count) { const u8 *buf = buffer; do { __raw_writel(*buf++, addr); } while (--count); } } static void s3c64xx_iowrite16_32_rep(volatile void __iomem *addr, const void *buffer, unsigned int count) { if (count) { const u16 *buf = buffer; do { __raw_writel(*buf++, addr); } while (--count); } } static void s3c64xx_iowrite_rep(const struct s3c64xx_spi_driver_data *sdd, struct spi_transfer *xfer) { void __iomem *addr = sdd->regs + S3C64XX_SPI_TX_DATA; const void *buf = xfer->tx_buf; unsigned int len = xfer->len; switch (sdd->cur_bpw) { case 32: iowrite32_rep(addr, buf, len / 4); break; case 16: if (sdd->port_conf->use_32bit_io) s3c64xx_iowrite16_32_rep(addr, buf, len / 2); else iowrite16_rep(addr, buf, len / 2); break; default: if (sdd->port_conf->use_32bit_io) s3c64xx_iowrite8_32_rep(addr, buf, len); else iowrite8_rep(addr, buf, len); break; } } static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd, struct spi_transfer *xfer, int dma_mode) { Loading Loading @@ -447,20 +499,7 @@ static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd, modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; ret = prepare_dma(&sdd->tx_dma, &xfer->tx_sg); } else { switch (sdd->cur_bpw) { case 32: iowrite32_rep(regs + S3C64XX_SPI_TX_DATA, xfer->tx_buf, xfer->len / 4); break; case 16: iowrite16_rep(regs + S3C64XX_SPI_TX_DATA, xfer->tx_buf, xfer->len / 2); break; default: iowrite8_rep(regs + S3C64XX_SPI_TX_DATA, xfer->tx_buf, xfer->len); break; } s3c64xx_iowrite_rep(sdd, xfer); } } Loading Loading @@ -1495,6 +1534,19 @@ static const struct s3c64xx_spi_port_config fsd_spi_port_config = { .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; static const struct s3c64xx_spi_port_config gs101_spi_port_config = { .fifo_lvl_mask = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, .rx_lvl_offset = 15, .tx_st_done = 25, .clk_div = 4, .high_speed = true, .clk_from_cmu = true, .has_loopback = true, .use_32bit_io = true, .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; static const struct platform_device_id s3c64xx_spi_driver_ids[] = { { .name = "s3c2443-spi", Loading @@ -1507,6 +1559,9 @@ static const struct platform_device_id s3c64xx_spi_driver_ids[] = { }; static const struct of_device_id s3c64xx_spi_dt_match[] = { { .compatible = "google,gs101-spi", .data = &gs101_spi_port_config, }, { .compatible = "samsung,s3c2443-spi", .data = (void *)&s3c2443_spi_port_config, }, Loading