Loading Documentation/devicetree/bindings/spi/sh-msiof.txt +2 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ Optional properties: specifiers, one for transmission, and one for reception. - dma-names : Must contain a list of two DMA names, "tx" and "rx". - spi-slave : Empty property indicating the SPI controller is used in slave mode. - renesas,dtdl : delay sync signal (setup) in transmit mode. Must contain one of the following values: 0 (no bit delay) Loading drivers/spi/spi-orion.c +9 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/of_device.h> #include <linux/clk.h> #include <linux/sizes.h> #include <linux/gpio.h> #include <asm/unaligned.h> #define DRIVER_NAME "orion_spi" Loading Loading @@ -320,12 +321,18 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) static void orion_spi_set_cs(struct spi_device *spi, bool enable) { struct orion_spi *orion_spi; int cs; if (gpio_is_valid(spi->cs_gpio)) cs = 0; else cs = spi->chip_select; orion_spi = spi_master_get_devdata(spi->master); orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK); orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS(spi->chip_select)); ORION_SPI_CS(cs)); /* Chip select logic is inverted from spi_set_cs */ if (!enable) Loading Loading @@ -606,6 +613,7 @@ static int orion_spi_probe(struct platform_device *pdev) master->setup = orion_spi_setup; master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->auto_runtime_pm = true; master->flags = SPI_MASTER_GPIO_SS; platform_set_drvdata(pdev, master); Loading drivers/spi/spi-pxa2xx.c +22 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,18 @@ static const struct lpss_config lpss_platforms[] = { .cs_sel_shift = 8, .cs_sel_mask = 3 << 8, }, { /* LPSS_CNL_SSP */ .offset = 0x200, .reg_general = -1, .reg_ssp = 0x20, .reg_cs_ctrl = 0x24, .reg_capabilities = 0xfc, .rx_threshold = 1, .tx_threshold_lo = 32, .tx_threshold_hi = 56, .cs_sel_shift = 8, .cs_sel_mask = 3 << 8, }, }; static inline const struct lpss_config Loading @@ -167,6 +179,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data) case LPSS_BSW_SSP: case LPSS_SPT_SSP: case LPSS_BXT_SSP: case LPSS_CNL_SSP: return true; default: return false; Loading Loading @@ -1275,6 +1288,7 @@ static int setup(struct spi_device *spi) case LPSS_BSW_SSP: case LPSS_SPT_SSP: case LPSS_BXT_SSP: case LPSS_CNL_SSP: config = lpss_get_config(drv_data); tx_thres = config->tx_threshold_lo; tx_hi_thres = config->tx_threshold_hi; Loading Loading @@ -1470,6 +1484,14 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac6), LPSS_BXT_SSP }, /* CNL-LP */ { PCI_VDEVICE(INTEL, 0x9daa), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x9dab), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x9dfb), LPSS_CNL_SSP }, /* CNL-H */ { PCI_VDEVICE(INTEL, 0xa32a), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0xa32b), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0xa37b), LPSS_CNL_SSP }, { }, }; Loading drivers/spi/spi-rockchip.c +41 −38 Original line number Diff line number Diff line Loading @@ -25,6 +25,11 @@ #define DRIVER_NAME "rockchip-spi" #define ROCKCHIP_SPI_CLR_BITS(reg, bits) \ writel_relaxed(readl_relaxed(reg) & ~(bits), reg) #define ROCKCHIP_SPI_SET_BITS(reg, bits) \ writel_relaxed(readl_relaxed(reg) | (bits), reg) /* SPI register offsets */ #define ROCKCHIP_SPI_CTRLR0 0x0000 #define ROCKCHIP_SPI_CTRLR1 0x0004 Loading Loading @@ -149,6 +154,8 @@ */ #define ROCKCHIP_SPI_MAX_TRANLEN 0xffff #define ROCKCHIP_SPI_MAX_CS_NUM 2 enum rockchip_ssi_type { SSI_MOTO_SPI = 0, SSI_TI_SSP, Loading Loading @@ -193,6 +200,8 @@ struct rockchip_spi { /* protect state */ spinlock_t lock; bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM]; u32 use_dma; struct sg_table tx_sg; struct sg_table rx_sg; Loading Loading @@ -264,37 +273,29 @@ static inline u32 rx_max(struct rockchip_spi *rs) static void rockchip_spi_set_cs(struct spi_device *spi, bool enable) { u32 ser; struct spi_master *master = spi->master; struct rockchip_spi *rs = spi_master_get_devdata(master); bool cs_asserted = !enable; pm_runtime_get_sync(rs->dev); /* Return immediately for no-op */ if (cs_asserted == rs->cs_asserted[spi->chip_select]) return; ser = readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & SER_MASK; if (cs_asserted) { /* Keep things powered as long as CS is asserted */ pm_runtime_get_sync(rs->dev); /* * drivers/spi/spi.c: * static void spi_set_cs(struct spi_device *spi, bool enable) * { * if (spi->mode & SPI_CS_HIGH) * enable = !enable; * * if (spi->cs_gpio >= 0) * gpio_set_value(spi->cs_gpio, !enable); * else if (spi->master->set_cs) * spi->master->set_cs(spi, !enable); * } * * Note: enable(rockchip_spi_set_cs) = !enable(spi_set_cs) */ if (!enable) ser |= 1 << spi->chip_select; else ser &= ~(1 << spi->chip_select); ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER, BIT(spi->chip_select)); } else { ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER, BIT(spi->chip_select)); writel_relaxed(ser, rs->regs + ROCKCHIP_SPI_SER); /* Drop reference from when we first asserted CS */ pm_runtime_put(rs->dev); } pm_runtime_put_sync(rs->dev); rs->cs_asserted[spi->chip_select] = cs_asserted; } static int rockchip_spi_prepare_message(struct spi_master *master, Loading Loading @@ -684,33 +685,33 @@ static int rockchip_spi_probe(struct platform_device *pdev) rs->regs = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(rs->regs)) { ret = PTR_ERR(rs->regs); goto err_ioremap_resource; goto err_put_master; } rs->apb_pclk = devm_clk_get(&pdev->dev, "apb_pclk"); if (IS_ERR(rs->apb_pclk)) { dev_err(&pdev->dev, "Failed to get apb_pclk\n"); ret = PTR_ERR(rs->apb_pclk); goto err_ioremap_resource; goto err_put_master; } rs->spiclk = devm_clk_get(&pdev->dev, "spiclk"); if (IS_ERR(rs->spiclk)) { dev_err(&pdev->dev, "Failed to get spi_pclk\n"); ret = PTR_ERR(rs->spiclk); goto err_ioremap_resource; goto err_put_master; } ret = clk_prepare_enable(rs->apb_pclk); if (ret) { dev_err(&pdev->dev, "Failed to enable apb_pclk\n"); goto err_ioremap_resource; goto err_put_master; } ret = clk_prepare_enable(rs->spiclk); if (ret) { dev_err(&pdev->dev, "Failed to enable spi_clk\n"); goto err_spiclk_enable; goto err_disable_apbclk; } spi_enable_chip(rs, 0); Loading @@ -728,7 +729,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) if (!rs->fifo_len) { dev_err(&pdev->dev, "Failed to get fifo length\n"); ret = -EINVAL; goto err_get_fifo_len; goto err_disable_spiclk; } spin_lock_init(&rs->lock); Loading @@ -739,7 +740,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) master->auto_runtime_pm = true; master->bus_num = pdev->id; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; master->num_chipselect = 2; master->num_chipselect = ROCKCHIP_SPI_MAX_CS_NUM; master->dev.of_node = pdev->dev.of_node; master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8); Loading @@ -749,13 +750,14 @@ static int rockchip_spi_probe(struct platform_device *pdev) master->transfer_one = rockchip_spi_transfer_one; master->max_transfer_size = rockchip_spi_max_transfer_size; master->handle_err = rockchip_spi_handle_err; master->flags = SPI_MASTER_GPIO_SS; rs->dma_tx.ch = dma_request_chan(rs->dev, "tx"); if (IS_ERR(rs->dma_tx.ch)) { /* Check tx to see if we need defer probing driver */ if (PTR_ERR(rs->dma_tx.ch) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto err_get_fifo_len; goto err_disable_pm_runtime; } dev_warn(rs->dev, "Failed to request TX DMA channel\n"); rs->dma_tx.ch = NULL; Loading Loading @@ -786,23 +788,24 @@ static int rockchip_spi_probe(struct platform_device *pdev) ret = devm_spi_register_master(&pdev->dev, master); if (ret) { dev_err(&pdev->dev, "Failed to register master\n"); goto err_register_master; goto err_free_dma_rx; } return 0; err_register_master: pm_runtime_disable(&pdev->dev); err_free_dma_rx: if (rs->dma_rx.ch) dma_release_channel(rs->dma_rx.ch); err_free_dma_tx: if (rs->dma_tx.ch) dma_release_channel(rs->dma_tx.ch); err_get_fifo_len: err_disable_pm_runtime: pm_runtime_disable(&pdev->dev); err_disable_spiclk: clk_disable_unprepare(rs->spiclk); err_spiclk_enable: err_disable_apbclk: clk_disable_unprepare(rs->apb_pclk); err_ioremap_resource: err_put_master: spi_master_put(master); return ret; Loading drivers/spi/spi-sh-msiof.c +78 −33 Original line number Diff line number Diff line Loading @@ -2,7 +2,8 @@ * SuperH MSIOF SPI Master Interface * * Copyright (c) 2009 Magnus Damm * Copyright (C) 2014 Glider bvba * Copyright (C) 2014 Renesas Electronics Corporation * Copyright (C) 2014-2017 Glider bvba * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as Loading Loading @@ -33,7 +34,6 @@ #include <asm/unaligned.h> struct sh_msiof_chipdata { u16 tx_fifo_size; u16 rx_fifo_size; Loading @@ -53,6 +53,7 @@ struct sh_msiof_spi_priv { void *rx_dma_page; dma_addr_t tx_dma_addr; dma_addr_t rx_dma_addr; bool slave_aborted; }; #define TMDR1 0x00 /* Transmit Mode Register 1 */ Loading Loading @@ -337,6 +338,9 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, tmp |= !cs_high << MDR1_SYNCAC_SHIFT; tmp |= lsb_first << MDR1_BITLSB_SHIFT; tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p); if (spi_controller_is_slave(p->master)) sh_msiof_write(p, TMDR1, tmp | TMDR1_PCON); else sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON); if (p->master->flags & SPI_MASTER_MUST_TX) { /* These bits are reserved if RX needs TX */ Loading Loading @@ -564,9 +568,11 @@ static int sh_msiof_prepare_message(struct spi_master *master, static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) { int ret; bool slave = spi_controller_is_slave(p->master); int ret = 0; /* setup clock and rx/tx signals */ if (!slave) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE); if (rx_buf && !ret) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_RXE); Loading @@ -574,7 +580,7 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TXE); /* start by setting frame bit */ if (!ret) if (!ret && !slave) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE); return ret; Loading @@ -582,20 +588,49 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf) { int ret; bool slave = spi_controller_is_slave(p->master); int ret = 0; /* shut down frame, rx/tx and clock signals */ if (!slave) ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0); if (!ret) ret = sh_msiof_modify_ctr_wait(p, CTR_TXE, 0); if (rx_buf && !ret) ret = sh_msiof_modify_ctr_wait(p, CTR_RXE, 0); if (!ret) if (!ret && !slave) ret = sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0); return ret; } static int sh_msiof_slave_abort(struct spi_master *master) { struct sh_msiof_spi_priv *p = spi_master_get_devdata(master); p->slave_aborted = true; complete(&p->done); return 0; } static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p) { if (spi_controller_is_slave(p->master)) { if (wait_for_completion_interruptible(&p->done) || p->slave_aborted) { dev_dbg(&p->pdev->dev, "interrupted\n"); return -EINTR; } } else { if (!wait_for_completion_timeout(&p->done, HZ)) { dev_err(&p->pdev->dev, "timeout\n"); return -ETIMEDOUT; } } return 0; } static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int), Loading Loading @@ -628,6 +663,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, tx_fifo(p, tx_buf, words, fifo_shift); reinit_completion(&p->done); p->slave_aborted = false; ret = sh_msiof_spi_start(p, rx_buf); if (ret) { Loading @@ -636,11 +672,9 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, } /* wait for tx fifo to be emptied / rx fifo to be filled */ if (!wait_for_completion_timeout(&p->done, HZ)) { dev_err(&p->pdev->dev, "PIO timeout\n"); ret = -ETIMEDOUT; ret = sh_msiof_wait_for_completion(p); if (ret) goto stop_reset; } /* read rx fifo */ if (rx_buf) Loading Loading @@ -732,6 +766,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, sh_msiof_write(p, IER, ier_bits); reinit_completion(&p->done); p->slave_aborted = false; /* Now start DMA */ if (rx) Loading @@ -746,11 +781,9 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, } /* wait for tx fifo to be emptied / rx fifo to be filled */ if (!wait_for_completion_timeout(&p->done, HZ)) { dev_err(&p->pdev->dev, "DMA timeout\n"); ret = -ETIMEDOUT; ret = sh_msiof_wait_for_completion(p); if (ret) goto stop_reset; } /* clear status bits */ sh_msiof_reset_str(p); Loading Loading @@ -843,6 +876,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, int ret; /* setup clocks (clock already enabled in chipselect()) */ if (!spi_controller_is_slave(p->master)) sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz); while (master->dma_tx && len > 15) { Loading Loading @@ -998,7 +1032,11 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) if (!info) return NULL; info->mode = of_property_read_bool(np, "spi-slave") ? MSIOF_SPI_SLAVE : MSIOF_SPI_MASTER; /* Parse the MSIOF properties */ if (info->mode == MSIOF_SPI_MASTER) of_property_read_u32(np, "num-cs", &num_cs); of_property_read_u32(np, "renesas,tx-fifo-size", &info->tx_fifo_override); Loading Loading @@ -1159,34 +1197,40 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) struct spi_master *master; const struct sh_msiof_chipdata *chipdata; const struct of_device_id *of_id; struct sh_msiof_spi_info *info; struct sh_msiof_spi_priv *p; int i; int ret; master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); if (master == NULL) return -ENOMEM; p = spi_master_get_devdata(master); platform_set_drvdata(pdev, p); p->master = master; of_id = of_match_device(sh_msiof_match, &pdev->dev); if (of_id) { chipdata = of_id->data; p->info = sh_msiof_spi_parse_dt(&pdev->dev); info = sh_msiof_spi_parse_dt(&pdev->dev); } else { chipdata = (const void *)pdev->id_entry->driver_data; p->info = dev_get_platdata(&pdev->dev); info = dev_get_platdata(&pdev->dev); } if (!p->info) { if (!info) { dev_err(&pdev->dev, "failed to obtain device info\n"); ret = -ENXIO; goto err1; return -ENXIO; } if (info->mode == MSIOF_SPI_SLAVE) master = spi_alloc_slave(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); else master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); if (master == NULL) return -ENOMEM; p = spi_master_get_devdata(master); platform_set_drvdata(pdev, p); p->master = master; p->info = info; init_completion(&p->done); p->clk = devm_clk_get(&pdev->dev, NULL); Loading Loading @@ -1237,6 +1281,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) master->num_chipselect = p->info->num_chipselect; master->setup = sh_msiof_spi_setup; master->prepare_message = sh_msiof_prepare_message; master->slave_abort = sh_msiof_slave_abort; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); master->auto_runtime_pm = true; master->transfer_one = sh_msiof_transfer_one; Loading Loading
Documentation/devicetree/bindings/spi/sh-msiof.txt +2 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ Optional properties: specifiers, one for transmission, and one for reception. - dma-names : Must contain a list of two DMA names, "tx" and "rx". - spi-slave : Empty property indicating the SPI controller is used in slave mode. - renesas,dtdl : delay sync signal (setup) in transmit mode. Must contain one of the following values: 0 (no bit delay) Loading
drivers/spi/spi-orion.c +9 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/of_device.h> #include <linux/clk.h> #include <linux/sizes.h> #include <linux/gpio.h> #include <asm/unaligned.h> #define DRIVER_NAME "orion_spi" Loading Loading @@ -320,12 +321,18 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) static void orion_spi_set_cs(struct spi_device *spi, bool enable) { struct orion_spi *orion_spi; int cs; if (gpio_is_valid(spi->cs_gpio)) cs = 0; else cs = spi->chip_select; orion_spi = spi_master_get_devdata(spi->master); orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK); orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS(spi->chip_select)); ORION_SPI_CS(cs)); /* Chip select logic is inverted from spi_set_cs */ if (!enable) Loading Loading @@ -606,6 +613,7 @@ static int orion_spi_probe(struct platform_device *pdev) master->setup = orion_spi_setup; master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->auto_runtime_pm = true; master->flags = SPI_MASTER_GPIO_SS; platform_set_drvdata(pdev, master); Loading
drivers/spi/spi-pxa2xx.c +22 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,18 @@ static const struct lpss_config lpss_platforms[] = { .cs_sel_shift = 8, .cs_sel_mask = 3 << 8, }, { /* LPSS_CNL_SSP */ .offset = 0x200, .reg_general = -1, .reg_ssp = 0x20, .reg_cs_ctrl = 0x24, .reg_capabilities = 0xfc, .rx_threshold = 1, .tx_threshold_lo = 32, .tx_threshold_hi = 56, .cs_sel_shift = 8, .cs_sel_mask = 3 << 8, }, }; static inline const struct lpss_config Loading @@ -167,6 +179,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data) case LPSS_BSW_SSP: case LPSS_SPT_SSP: case LPSS_BXT_SSP: case LPSS_CNL_SSP: return true; default: return false; Loading Loading @@ -1275,6 +1288,7 @@ static int setup(struct spi_device *spi) case LPSS_BSW_SSP: case LPSS_SPT_SSP: case LPSS_BXT_SSP: case LPSS_CNL_SSP: config = lpss_get_config(drv_data); tx_thres = config->tx_threshold_lo; tx_hi_thres = config->tx_threshold_hi; Loading Loading @@ -1470,6 +1484,14 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac6), LPSS_BXT_SSP }, /* CNL-LP */ { PCI_VDEVICE(INTEL, 0x9daa), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x9dab), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x9dfb), LPSS_CNL_SSP }, /* CNL-H */ { PCI_VDEVICE(INTEL, 0xa32a), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0xa32b), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0xa37b), LPSS_CNL_SSP }, { }, }; Loading
drivers/spi/spi-rockchip.c +41 −38 Original line number Diff line number Diff line Loading @@ -25,6 +25,11 @@ #define DRIVER_NAME "rockchip-spi" #define ROCKCHIP_SPI_CLR_BITS(reg, bits) \ writel_relaxed(readl_relaxed(reg) & ~(bits), reg) #define ROCKCHIP_SPI_SET_BITS(reg, bits) \ writel_relaxed(readl_relaxed(reg) | (bits), reg) /* SPI register offsets */ #define ROCKCHIP_SPI_CTRLR0 0x0000 #define ROCKCHIP_SPI_CTRLR1 0x0004 Loading Loading @@ -149,6 +154,8 @@ */ #define ROCKCHIP_SPI_MAX_TRANLEN 0xffff #define ROCKCHIP_SPI_MAX_CS_NUM 2 enum rockchip_ssi_type { SSI_MOTO_SPI = 0, SSI_TI_SSP, Loading Loading @@ -193,6 +200,8 @@ struct rockchip_spi { /* protect state */ spinlock_t lock; bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM]; u32 use_dma; struct sg_table tx_sg; struct sg_table rx_sg; Loading Loading @@ -264,37 +273,29 @@ static inline u32 rx_max(struct rockchip_spi *rs) static void rockchip_spi_set_cs(struct spi_device *spi, bool enable) { u32 ser; struct spi_master *master = spi->master; struct rockchip_spi *rs = spi_master_get_devdata(master); bool cs_asserted = !enable; pm_runtime_get_sync(rs->dev); /* Return immediately for no-op */ if (cs_asserted == rs->cs_asserted[spi->chip_select]) return; ser = readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & SER_MASK; if (cs_asserted) { /* Keep things powered as long as CS is asserted */ pm_runtime_get_sync(rs->dev); /* * drivers/spi/spi.c: * static void spi_set_cs(struct spi_device *spi, bool enable) * { * if (spi->mode & SPI_CS_HIGH) * enable = !enable; * * if (spi->cs_gpio >= 0) * gpio_set_value(spi->cs_gpio, !enable); * else if (spi->master->set_cs) * spi->master->set_cs(spi, !enable); * } * * Note: enable(rockchip_spi_set_cs) = !enable(spi_set_cs) */ if (!enable) ser |= 1 << spi->chip_select; else ser &= ~(1 << spi->chip_select); ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER, BIT(spi->chip_select)); } else { ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER, BIT(spi->chip_select)); writel_relaxed(ser, rs->regs + ROCKCHIP_SPI_SER); /* Drop reference from when we first asserted CS */ pm_runtime_put(rs->dev); } pm_runtime_put_sync(rs->dev); rs->cs_asserted[spi->chip_select] = cs_asserted; } static int rockchip_spi_prepare_message(struct spi_master *master, Loading Loading @@ -684,33 +685,33 @@ static int rockchip_spi_probe(struct platform_device *pdev) rs->regs = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(rs->regs)) { ret = PTR_ERR(rs->regs); goto err_ioremap_resource; goto err_put_master; } rs->apb_pclk = devm_clk_get(&pdev->dev, "apb_pclk"); if (IS_ERR(rs->apb_pclk)) { dev_err(&pdev->dev, "Failed to get apb_pclk\n"); ret = PTR_ERR(rs->apb_pclk); goto err_ioremap_resource; goto err_put_master; } rs->spiclk = devm_clk_get(&pdev->dev, "spiclk"); if (IS_ERR(rs->spiclk)) { dev_err(&pdev->dev, "Failed to get spi_pclk\n"); ret = PTR_ERR(rs->spiclk); goto err_ioremap_resource; goto err_put_master; } ret = clk_prepare_enable(rs->apb_pclk); if (ret) { dev_err(&pdev->dev, "Failed to enable apb_pclk\n"); goto err_ioremap_resource; goto err_put_master; } ret = clk_prepare_enable(rs->spiclk); if (ret) { dev_err(&pdev->dev, "Failed to enable spi_clk\n"); goto err_spiclk_enable; goto err_disable_apbclk; } spi_enable_chip(rs, 0); Loading @@ -728,7 +729,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) if (!rs->fifo_len) { dev_err(&pdev->dev, "Failed to get fifo length\n"); ret = -EINVAL; goto err_get_fifo_len; goto err_disable_spiclk; } spin_lock_init(&rs->lock); Loading @@ -739,7 +740,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) master->auto_runtime_pm = true; master->bus_num = pdev->id; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; master->num_chipselect = 2; master->num_chipselect = ROCKCHIP_SPI_MAX_CS_NUM; master->dev.of_node = pdev->dev.of_node; master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8); Loading @@ -749,13 +750,14 @@ static int rockchip_spi_probe(struct platform_device *pdev) master->transfer_one = rockchip_spi_transfer_one; master->max_transfer_size = rockchip_spi_max_transfer_size; master->handle_err = rockchip_spi_handle_err; master->flags = SPI_MASTER_GPIO_SS; rs->dma_tx.ch = dma_request_chan(rs->dev, "tx"); if (IS_ERR(rs->dma_tx.ch)) { /* Check tx to see if we need defer probing driver */ if (PTR_ERR(rs->dma_tx.ch) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto err_get_fifo_len; goto err_disable_pm_runtime; } dev_warn(rs->dev, "Failed to request TX DMA channel\n"); rs->dma_tx.ch = NULL; Loading Loading @@ -786,23 +788,24 @@ static int rockchip_spi_probe(struct platform_device *pdev) ret = devm_spi_register_master(&pdev->dev, master); if (ret) { dev_err(&pdev->dev, "Failed to register master\n"); goto err_register_master; goto err_free_dma_rx; } return 0; err_register_master: pm_runtime_disable(&pdev->dev); err_free_dma_rx: if (rs->dma_rx.ch) dma_release_channel(rs->dma_rx.ch); err_free_dma_tx: if (rs->dma_tx.ch) dma_release_channel(rs->dma_tx.ch); err_get_fifo_len: err_disable_pm_runtime: pm_runtime_disable(&pdev->dev); err_disable_spiclk: clk_disable_unprepare(rs->spiclk); err_spiclk_enable: err_disable_apbclk: clk_disable_unprepare(rs->apb_pclk); err_ioremap_resource: err_put_master: spi_master_put(master); return ret; Loading
drivers/spi/spi-sh-msiof.c +78 −33 Original line number Diff line number Diff line Loading @@ -2,7 +2,8 @@ * SuperH MSIOF SPI Master Interface * * Copyright (c) 2009 Magnus Damm * Copyright (C) 2014 Glider bvba * Copyright (C) 2014 Renesas Electronics Corporation * Copyright (C) 2014-2017 Glider bvba * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as Loading Loading @@ -33,7 +34,6 @@ #include <asm/unaligned.h> struct sh_msiof_chipdata { u16 tx_fifo_size; u16 rx_fifo_size; Loading @@ -53,6 +53,7 @@ struct sh_msiof_spi_priv { void *rx_dma_page; dma_addr_t tx_dma_addr; dma_addr_t rx_dma_addr; bool slave_aborted; }; #define TMDR1 0x00 /* Transmit Mode Register 1 */ Loading Loading @@ -337,6 +338,9 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, tmp |= !cs_high << MDR1_SYNCAC_SHIFT; tmp |= lsb_first << MDR1_BITLSB_SHIFT; tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p); if (spi_controller_is_slave(p->master)) sh_msiof_write(p, TMDR1, tmp | TMDR1_PCON); else sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON); if (p->master->flags & SPI_MASTER_MUST_TX) { /* These bits are reserved if RX needs TX */ Loading Loading @@ -564,9 +568,11 @@ static int sh_msiof_prepare_message(struct spi_master *master, static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) { int ret; bool slave = spi_controller_is_slave(p->master); int ret = 0; /* setup clock and rx/tx signals */ if (!slave) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE); if (rx_buf && !ret) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_RXE); Loading @@ -574,7 +580,7 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TXE); /* start by setting frame bit */ if (!ret) if (!ret && !slave) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE); return ret; Loading @@ -582,20 +588,49 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf) { int ret; bool slave = spi_controller_is_slave(p->master); int ret = 0; /* shut down frame, rx/tx and clock signals */ if (!slave) ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0); if (!ret) ret = sh_msiof_modify_ctr_wait(p, CTR_TXE, 0); if (rx_buf && !ret) ret = sh_msiof_modify_ctr_wait(p, CTR_RXE, 0); if (!ret) if (!ret && !slave) ret = sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0); return ret; } static int sh_msiof_slave_abort(struct spi_master *master) { struct sh_msiof_spi_priv *p = spi_master_get_devdata(master); p->slave_aborted = true; complete(&p->done); return 0; } static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p) { if (spi_controller_is_slave(p->master)) { if (wait_for_completion_interruptible(&p->done) || p->slave_aborted) { dev_dbg(&p->pdev->dev, "interrupted\n"); return -EINTR; } } else { if (!wait_for_completion_timeout(&p->done, HZ)) { dev_err(&p->pdev->dev, "timeout\n"); return -ETIMEDOUT; } } return 0; } static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int), Loading Loading @@ -628,6 +663,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, tx_fifo(p, tx_buf, words, fifo_shift); reinit_completion(&p->done); p->slave_aborted = false; ret = sh_msiof_spi_start(p, rx_buf); if (ret) { Loading @@ -636,11 +672,9 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, } /* wait for tx fifo to be emptied / rx fifo to be filled */ if (!wait_for_completion_timeout(&p->done, HZ)) { dev_err(&p->pdev->dev, "PIO timeout\n"); ret = -ETIMEDOUT; ret = sh_msiof_wait_for_completion(p); if (ret) goto stop_reset; } /* read rx fifo */ if (rx_buf) Loading Loading @@ -732,6 +766,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, sh_msiof_write(p, IER, ier_bits); reinit_completion(&p->done); p->slave_aborted = false; /* Now start DMA */ if (rx) Loading @@ -746,11 +781,9 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, } /* wait for tx fifo to be emptied / rx fifo to be filled */ if (!wait_for_completion_timeout(&p->done, HZ)) { dev_err(&p->pdev->dev, "DMA timeout\n"); ret = -ETIMEDOUT; ret = sh_msiof_wait_for_completion(p); if (ret) goto stop_reset; } /* clear status bits */ sh_msiof_reset_str(p); Loading Loading @@ -843,6 +876,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, int ret; /* setup clocks (clock already enabled in chipselect()) */ if (!spi_controller_is_slave(p->master)) sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz); while (master->dma_tx && len > 15) { Loading Loading @@ -998,7 +1032,11 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) if (!info) return NULL; info->mode = of_property_read_bool(np, "spi-slave") ? MSIOF_SPI_SLAVE : MSIOF_SPI_MASTER; /* Parse the MSIOF properties */ if (info->mode == MSIOF_SPI_MASTER) of_property_read_u32(np, "num-cs", &num_cs); of_property_read_u32(np, "renesas,tx-fifo-size", &info->tx_fifo_override); Loading Loading @@ -1159,34 +1197,40 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) struct spi_master *master; const struct sh_msiof_chipdata *chipdata; const struct of_device_id *of_id; struct sh_msiof_spi_info *info; struct sh_msiof_spi_priv *p; int i; int ret; master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); if (master == NULL) return -ENOMEM; p = spi_master_get_devdata(master); platform_set_drvdata(pdev, p); p->master = master; of_id = of_match_device(sh_msiof_match, &pdev->dev); if (of_id) { chipdata = of_id->data; p->info = sh_msiof_spi_parse_dt(&pdev->dev); info = sh_msiof_spi_parse_dt(&pdev->dev); } else { chipdata = (const void *)pdev->id_entry->driver_data; p->info = dev_get_platdata(&pdev->dev); info = dev_get_platdata(&pdev->dev); } if (!p->info) { if (!info) { dev_err(&pdev->dev, "failed to obtain device info\n"); ret = -ENXIO; goto err1; return -ENXIO; } if (info->mode == MSIOF_SPI_SLAVE) master = spi_alloc_slave(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); else master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); if (master == NULL) return -ENOMEM; p = spi_master_get_devdata(master); platform_set_drvdata(pdev, p); p->master = master; p->info = info; init_completion(&p->done); p->clk = devm_clk_get(&pdev->dev, NULL); Loading Loading @@ -1237,6 +1281,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) master->num_chipselect = p->info->num_chipselect; master->setup = sh_msiof_spi_setup; master->prepare_message = sh_msiof_prepare_message; master->slave_abort = sh_msiof_slave_abort; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); master->auto_runtime_pm = true; master->transfer_one = sh_msiof_transfer_one; Loading