Lines Matching +full:bcm6328 +full:- +full:hsspi
4 * Copyright 2000-2010 Broadcom Corporation
5 * Copyright 2012-2013 Jonas Gorski <jonas.gorski@gmail.com>
17 #include <linux/dma-mapping.h>
23 #include <linux/spi/spi-mem.h>
24 #include <linux/mtd/spi-nor.h>
124 if (bs->xfer_mode == HSSPI_XFER_MODE_AUTO) \
125 dev_dbg(&bs->pdev->dev, fmt, ##__VA_ARGS__); \
126 else if (bs->xfer_mode == HSSPI_XFER_MODE_PREPEND) \
127 dev_err(&bs->pdev->dev, fmt, ##__VA_ARGS__); \
154 return sprintf(buf, "%d\n", bs->wait_mode); in wait_mode_show()
165 return -EINVAL; in wait_mode_store()
169 return -EINVAL; in wait_mode_store()
172 mutex_lock(&bs->msg_mutex); in wait_mode_store()
173 bs->wait_mode = val; in wait_mode_store()
176 __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG); in wait_mode_store()
177 mutex_unlock(&bs->msg_mutex); in wait_mode_store()
190 return sprintf(buf, "%d\n", bs->xfer_mode); in xfer_mode_show()
201 return -EINVAL; in xfer_mode_store()
205 return -EINVAL; in xfer_mode_store()
208 mutex_lock(&bs->msg_mutex); in xfer_mode_store()
209 bs->xfer_mode = val; in xfer_mode_store()
210 mutex_unlock(&bs->msg_mutex); in xfer_mode_store()
232 return HSSPI_BUFFER_LEN - HSSPI_OPCODE_LEN; in bcm63xx_hsspi_max_message_size()
241 if (bs->wait_mode == HSSPI_WAIT_MODE_INTR) { in bcm63xx_hsspi_wait_cmd()
242 if (wait_for_completion_timeout(&bs->done, HZ) == 0) in bcm63xx_hsspi_wait_cmd()
249 reg = __raw_readl(bs->regs + HSSPI_PINGPONG_STATUS_REG(0)); in bcm63xx_hsspi_wait_cmd()
260 dev_err(&bs->pdev->dev, "transfer timed out!\n"); in bcm63xx_hsspi_wait_cmd()
282 bs->prepend_cnt = 0; in bcm63xx_prepare_prepend_transfer()
283 list_for_each_entry(t, &msg->transfers, transfer_list) { in bcm63xx_prepare_prepend_transfer()
284 if ((spi_delay_to_ns(&t->delay, t) > 0) || t->cs_change) { in bcm63xx_prepare_prepend_transfer()
291 if (t->tx_buf && !t->rx_buf) { in bcm63xx_prepare_prepend_transfer()
293 if (bs->prepend_cnt + t->len > in bcm63xx_prepare_prepend_transfer()
294 (HSSPI_BUFFER_LEN - HSSPI_OPCODE_LEN)) { in bcm63xx_prepare_prepend_transfer()
300 if (t->tx_nbits > SPI_NBITS_SINGLE && in bcm63xx_prepare_prepend_transfer()
301 !list_is_last(&t->transfer_list, &msg->transfers)) { in bcm63xx_prepare_prepend_transfer()
303 "multi-bit prepend buf not supported!\n"); in bcm63xx_prepare_prepend_transfer()
307 if (t->tx_nbits == SPI_NBITS_SINGLE) { in bcm63xx_prepare_prepend_transfer()
308 memcpy(bs->prepend_buf + bs->prepend_cnt, t->tx_buf, t->len); in bcm63xx_prepare_prepend_transfer()
309 bs->prepend_cnt += t->len; in bcm63xx_prepare_prepend_transfer()
312 if (!list_is_last(&t->transfer_list, &msg->transfers)) { in bcm63xx_prepare_prepend_transfer()
319 if (list_is_last(&t->transfer_list, &msg->transfers)) { in bcm63xx_prepare_prepend_transfer()
322 if (tx_only && t->tx_nbits == SPI_NBITS_SINGLE) { in bcm63xx_prepare_prepend_transfer()
327 t_prepend->len = bs->prepend_cnt; in bcm63xx_prepare_prepend_transfer()
328 t_prepend->tx_buf = bs->prepend_buf; in bcm63xx_prepare_prepend_transfer()
329 bs->prepend_cnt = 0; in bcm63xx_prepare_prepend_transfer()
336 if (bs->prepend_cnt > HSSPI_MAX_PREPEND_LEN) { in bcm63xx_prepare_prepend_transfer()
351 struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller); in bcm63xx_hsspi_do_prepend_txrx()
354 const u8 *tx = t->tx_buf; in bcm63xx_hsspi_do_prepend_txrx()
355 u8 *rx = t->rx_buf; in bcm63xx_hsspi_do_prepend_txrx()
362 if (t->len + bs->prepend_cnt > (HSSPI_BUFFER_LEN - HSSPI_OPCODE_LEN)) { in bcm63xx_hsspi_do_prepend_txrx()
363 dev_warn(&bs->pdev->dev, in bcm63xx_hsspi_do_prepend_txrx()
365 t->len, bs->prepend_cnt); in bcm63xx_hsspi_do_prepend_txrx()
366 return -EINVAL; in bcm63xx_hsspi_do_prepend_txrx()
369 bcm63xx_hsspi_set_clk(bs, spi, t->speed_hz); in bcm63xx_hsspi_do_prepend_txrx()
378 if ((opcode == HSSPI_OP_READ && t->rx_nbits == SPI_NBITS_DUAL) || in bcm63xx_hsspi_do_prepend_txrx()
379 (opcode == HSSPI_OP_WRITE && t->tx_nbits == SPI_NBITS_DUAL)) { in bcm63xx_hsspi_do_prepend_txrx()
382 if (t->rx_nbits == SPI_NBITS_DUAL) { in bcm63xx_hsspi_do_prepend_txrx()
384 reg |= bs->prepend_cnt << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT; in bcm63xx_hsspi_do_prepend_txrx()
386 if (t->tx_nbits == SPI_NBITS_DUAL) { in bcm63xx_hsspi_do_prepend_txrx()
388 reg |= bs->prepend_cnt << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT; in bcm63xx_hsspi_do_prepend_txrx()
392 reg |= bs->prepend_cnt << MODE_CTRL_PREPENDBYTE_CNT_SHIFT; in bcm63xx_hsspi_do_prepend_txrx()
394 bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select)); in bcm63xx_hsspi_do_prepend_txrx()
396 reinit_completion(&bs->done); in bcm63xx_hsspi_do_prepend_txrx()
397 if (bs->prepend_cnt) in bcm63xx_hsspi_do_prepend_txrx()
398 memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, bs->prepend_buf, in bcm63xx_hsspi_do_prepend_txrx()
399 bs->prepend_cnt); in bcm63xx_hsspi_do_prepend_txrx()
401 memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN + bs->prepend_cnt, tx, in bcm63xx_hsspi_do_prepend_txrx()
402 t->len); in bcm63xx_hsspi_do_prepend_txrx()
404 *(__be16 *)(&val) = cpu_to_be16(opcode | t->len); in bcm63xx_hsspi_do_prepend_txrx()
405 __raw_writew(val, bs->fifo); in bcm63xx_hsspi_do_prepend_txrx()
407 if (bs->wait_mode == HSSPI_WAIT_MODE_INTR) in bcm63xx_hsspi_do_prepend_txrx()
408 __raw_writel(HSSPI_PINGx_CMD_DONE(0), bs->regs + HSSPI_INT_MASK_REG); in bcm63xx_hsspi_do_prepend_txrx()
414 __raw_writel(reg, bs->regs + HSSPI_PINGPONG_COMMAND_REG(0)); in bcm63xx_hsspi_do_prepend_txrx()
417 return -ETIMEDOUT; in bcm63xx_hsspi_do_prepend_txrx()
420 memcpy_fromio(rx, bs->fifo, t->len); in bcm63xx_hsspi_do_prepend_txrx()
430 mutex_lock(&bs->bus_mutex); in bcm63xx_hsspi_set_cs()
431 reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcm63xx_hsspi_set_cs()
434 if (active == !(bs->cs_polarity & BIT(cs))) in bcm63xx_hsspi_set_cs()
437 __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcm63xx_hsspi_set_cs()
438 mutex_unlock(&bs->bus_mutex); in bcm63xx_hsspi_set_cs()
447 reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz)); in bcm63xx_hsspi_set_clk()
449 bs->regs + HSSPI_PROFILE_CLK_CTRL_REG(profile)); in bcm63xx_hsspi_set_clk()
451 reg = __raw_readl(bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile)); in bcm63xx_hsspi_set_clk()
456 __raw_writel(reg, bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile)); in bcm63xx_hsspi_set_clk()
458 mutex_lock(&bs->bus_mutex); in bcm63xx_hsspi_set_clk()
460 reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcm63xx_hsspi_set_clk()
462 if (spi->mode & SPI_CPOL) in bcm63xx_hsspi_set_clk()
464 __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcm63xx_hsspi_set_clk()
465 mutex_unlock(&bs->bus_mutex); in bcm63xx_hsspi_set_clk()
470 struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller); in bcm63xx_hsspi_do_txrx()
473 int pending = t->len; in bcm63xx_hsspi_do_txrx()
475 const u8 *tx = t->tx_buf; in bcm63xx_hsspi_do_txrx()
476 u8 *rx = t->rx_buf; in bcm63xx_hsspi_do_txrx()
479 bcm63xx_hsspi_set_clk(bs, spi, t->speed_hz); in bcm63xx_hsspi_do_txrx()
480 if (!t->cs_off) in bcm63xx_hsspi_do_txrx()
491 step_size -= HSSPI_OPCODE_LEN; in bcm63xx_hsspi_do_txrx()
493 if ((opcode == HSSPI_OP_READ && t->rx_nbits == SPI_NBITS_DUAL) || in bcm63xx_hsspi_do_txrx()
494 (opcode == HSSPI_OP_WRITE && t->tx_nbits == SPI_NBITS_DUAL)) { in bcm63xx_hsspi_do_txrx()
497 if (t->rx_nbits == SPI_NBITS_DUAL) in bcm63xx_hsspi_do_txrx()
499 if (t->tx_nbits == SPI_NBITS_DUAL) in bcm63xx_hsspi_do_txrx()
504 bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select)); in bcm63xx_hsspi_do_txrx()
509 reinit_completion(&bs->done); in bcm63xx_hsspi_do_txrx()
511 memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, tx, curr_step); in bcm63xx_hsspi_do_txrx()
516 __raw_writew(val, bs->fifo); in bcm63xx_hsspi_do_txrx()
519 if (bs->wait_mode == HSSPI_WAIT_MODE_INTR) in bcm63xx_hsspi_do_txrx()
521 bs->regs + HSSPI_INT_MASK_REG); in bcm63xx_hsspi_do_txrx()
526 __raw_writel(reg, bs->regs + HSSPI_PINGPONG_COMMAND_REG(0)); in bcm63xx_hsspi_do_txrx()
529 return -ETIMEDOUT; in bcm63xx_hsspi_do_txrx()
532 memcpy_fromio(rx, bs->fifo, curr_step); in bcm63xx_hsspi_do_txrx()
536 pending -= curr_step; in bcm63xx_hsspi_do_txrx()
544 struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller); in bcm63xx_hsspi_setup()
547 reg = __raw_readl(bs->regs + in bcm63xx_hsspi_setup()
550 if (spi->mode & SPI_CPHA) in bcm63xx_hsspi_setup()
554 __raw_writel(reg, bs->regs + in bcm63xx_hsspi_setup()
557 mutex_lock(&bs->bus_mutex); in bcm63xx_hsspi_setup()
558 reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcm63xx_hsspi_setup()
561 if ((reg & GLOBAL_CTRL_CS_POLARITY_MASK) == bs->cs_polarity) { in bcm63xx_hsspi_setup()
562 if (spi->mode & SPI_CS_HIGH) in bcm63xx_hsspi_setup()
566 __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcm63xx_hsspi_setup()
569 if (spi->mode & SPI_CS_HIGH) in bcm63xx_hsspi_setup()
570 bs->cs_polarity |= BIT(spi_get_chipselect(spi, 0)); in bcm63xx_hsspi_setup()
572 bs->cs_polarity &= ~BIT(spi_get_chipselect(spi, 0)); in bcm63xx_hsspi_setup()
574 mutex_unlock(&bs->bus_mutex); in bcm63xx_hsspi_setup()
582 struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller); in bcm63xx_hsspi_do_dummy_cs_txrx()
583 int status = -EINVAL; in bcm63xx_hsspi_do_dummy_cs_txrx()
606 list_for_each_entry(t, &msg->transfers, transfer_list) { in bcm63xx_hsspi_do_dummy_cs_txrx()
613 if (bs->xfer_mode == HSSPI_XFER_MODE_AUTO) { in bcm63xx_hsspi_do_dummy_cs_txrx()
614 if (t->speed_hz > HSSPI_MAX_SYNC_CLOCK) { in bcm63xx_hsspi_do_dummy_cs_txrx()
615 t->speed_hz = HSSPI_MAX_SYNC_CLOCK; in bcm63xx_hsspi_do_dummy_cs_txrx()
616 dev_warn_once(&bs->pdev->dev, in bcm63xx_hsspi_do_dummy_cs_txrx()
618 t->speed_hz); in bcm63xx_hsspi_do_dummy_cs_txrx()
626 msg->actual_length += t->len; in bcm63xx_hsspi_do_dummy_cs_txrx()
631 if (t->cs_change) { in bcm63xx_hsspi_do_dummy_cs_txrx()
632 if (list_is_last(&t->transfer_list, &msg->transfers)) { in bcm63xx_hsspi_do_dummy_cs_txrx()
635 if (!t->cs_off) in bcm63xx_hsspi_do_dummy_cs_txrx()
640 if (!list_next_entry(t, transfer_list)->cs_off) in bcm63xx_hsspi_do_dummy_cs_txrx()
643 } else if (!list_is_last(&t->transfer_list, &msg->transfers) && in bcm63xx_hsspi_do_dummy_cs_txrx()
644 t->cs_off != list_next_entry(t, transfer_list)->cs_off) { in bcm63xx_hsspi_do_dummy_cs_txrx()
645 bcm63xx_hsspi_set_cs(bs, spi_get_chipselect(spi, 0), t->cs_off); in bcm63xx_hsspi_do_dummy_cs_txrx()
660 struct spi_device *spi = msg->spi; in bcm63xx_hsspi_transfer_one()
661 int status = -EINVAL; in bcm63xx_hsspi_transfer_one()
665 mutex_lock(&bs->msg_mutex); in bcm63xx_hsspi_transfer_one()
667 if (bs->xfer_mode != HSSPI_XFER_MODE_DUMMYCS) in bcm63xx_hsspi_transfer_one()
672 msg->actual_length = (t_prepend.len + bs->prepend_cnt); in bcm63xx_hsspi_transfer_one()
674 if (bs->xfer_mode == HSSPI_XFER_MODE_PREPEND) { in bcm63xx_hsspi_transfer_one()
675 dev_err(&bs->pdev->dev, in bcm63xx_hsspi_transfer_one()
677 status = -EINVAL; in bcm63xx_hsspi_transfer_one()
682 mutex_unlock(&bs->msg_mutex); in bcm63xx_hsspi_transfer_one()
683 msg->status = status; in bcm63xx_hsspi_transfer_one()
696 if ((op->cmd.opcode == SPINOR_OP_READ_1_2_2) || in bcm63xx_hsspi_mem_supports_op()
697 (op->cmd.opcode == SPINOR_OP_READ_1_2_2_4B) || in bcm63xx_hsspi_mem_supports_op()
698 (op->cmd.opcode == SPINOR_OP_READ_1_2_2_DTR) || in bcm63xx_hsspi_mem_supports_op()
699 (op->cmd.opcode == SPINOR_OP_READ_1_2_2_DTR_4B)) in bcm63xx_hsspi_mem_supports_op()
713 if (__raw_readl(bs->regs + HSSPI_INT_STATUS_MASKED_REG) == 0) in bcm63xx_hsspi_interrupt()
716 __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG); in bcm63xx_hsspi_interrupt()
717 __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); in bcm63xx_hsspi_interrupt()
719 complete(&bs->done); in bcm63xx_hsspi_interrupt()
729 struct device *dev = &pdev->dev; in bcm63xx_hsspi_probe()
743 clk = devm_clk_get(dev, "hsspi"); in bcm63xx_hsspi_probe()
777 ret = -EINVAL; in bcm63xx_hsspi_probe()
782 host = spi_alloc_host(&pdev->dev, sizeof(*bs)); in bcm63xx_hsspi_probe()
784 ret = -ENOMEM; in bcm63xx_hsspi_probe()
789 bs->pdev = pdev; in bcm63xx_hsspi_probe()
790 bs->clk = clk; in bcm63xx_hsspi_probe()
791 bs->pll_clk = pll_clk; in bcm63xx_hsspi_probe()
792 bs->regs = regs; in bcm63xx_hsspi_probe()
793 bs->speed_hz = rate; in bcm63xx_hsspi_probe()
794 bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0)); in bcm63xx_hsspi_probe()
795 bs->wait_mode = HSSPI_WAIT_MODE_POLLING; in bcm63xx_hsspi_probe()
796 bs->prepend_buf = devm_kzalloc(dev, HSSPI_BUFFER_LEN, GFP_KERNEL); in bcm63xx_hsspi_probe()
797 if (!bs->prepend_buf) { in bcm63xx_hsspi_probe()
798 ret = -ENOMEM; in bcm63xx_hsspi_probe()
802 mutex_init(&bs->bus_mutex); in bcm63xx_hsspi_probe()
803 mutex_init(&bs->msg_mutex); in bcm63xx_hsspi_probe()
804 init_completion(&bs->done); in bcm63xx_hsspi_probe()
806 host->mem_ops = &bcm63xx_hsspi_mem_ops; in bcm63xx_hsspi_probe()
807 host->dev.of_node = dev->of_node; in bcm63xx_hsspi_probe()
808 if (!dev->of_node) in bcm63xx_hsspi_probe()
809 host->bus_num = HSSPI_BUS_NUM; in bcm63xx_hsspi_probe()
811 of_property_read_u32(dev->of_node, "num-cs", &num_cs); in bcm63xx_hsspi_probe()
817 host->num_chipselect = num_cs; in bcm63xx_hsspi_probe()
818 host->setup = bcm63xx_hsspi_setup; in bcm63xx_hsspi_probe()
819 host->transfer_one_message = bcm63xx_hsspi_transfer_one; in bcm63xx_hsspi_probe()
820 host->max_transfer_size = bcm63xx_hsspi_max_message_size; in bcm63xx_hsspi_probe()
821 host->max_message_size = bcm63xx_hsspi_max_message_size; in bcm63xx_hsspi_probe()
823 host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | in bcm63xx_hsspi_probe()
825 host->bits_per_word_mask = SPI_BPW_MASK(8); in bcm63xx_hsspi_probe()
826 host->auto_runtime_pm = true; in bcm63xx_hsspi_probe()
831 __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); in bcm63xx_hsspi_probe()
834 __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG); in bcm63xx_hsspi_probe()
837 reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcm63xx_hsspi_probe()
838 bs->cs_polarity = reg & GLOBAL_CTRL_CS_POLARITY_MASK; in bcm63xx_hsspi_probe()
840 bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcm63xx_hsspi_probe()
844 pdev->name, bs); in bcm63xx_hsspi_probe()
850 pm_runtime_enable(&pdev->dev); in bcm63xx_hsspi_probe()
852 ret = sysfs_create_group(&pdev->dev.kobj, &bcm63xx_hsspi_group); in bcm63xx_hsspi_probe()
854 dev_err(&pdev->dev, "couldn't register sysfs group\n"); in bcm63xx_hsspi_probe()
868 sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group); in bcm63xx_hsspi_probe()
870 pm_runtime_disable(&pdev->dev); in bcm63xx_hsspi_probe()
887 __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); in bcm63xx_hsspi_remove()
888 clk_disable_unprepare(bs->pll_clk); in bcm63xx_hsspi_remove()
889 clk_disable_unprepare(bs->clk); in bcm63xx_hsspi_remove()
890 sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group); in bcm63xx_hsspi_remove()
900 clk_disable_unprepare(bs->pll_clk); in bcm63xx_hsspi_suspend()
901 clk_disable_unprepare(bs->clk); in bcm63xx_hsspi_suspend()
912 ret = clk_prepare_enable(bs->clk); in bcm63xx_hsspi_resume()
916 if (bs->pll_clk) { in bcm63xx_hsspi_resume()
917 ret = clk_prepare_enable(bs->pll_clk); in bcm63xx_hsspi_resume()
919 clk_disable_unprepare(bs->clk); in bcm63xx_hsspi_resume()
934 { .compatible = "brcm,bcm6328-hsspi", },
935 { .compatible = "brcm,bcmbca-hsspi-v1.0", },
942 .name = "bcm63xx-hsspi",