diff options
| -rw-r--r-- | drivers/spi/spi-mt65xx.c | 65 |
1 files changed, 52 insertions, 13 deletions
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 406695a42e19..563954a61424 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
| 23 | #include <linux/of_gpio.h> | ||
| 23 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| 24 | #include <linux/platform_data/spi-mt65xx.h> | 25 | #include <linux/platform_data/spi-mt65xx.h> |
| 25 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
| @@ -84,7 +85,8 @@ struct mtk_spi_compatible { | |||
| 84 | struct mtk_spi { | 85 | struct mtk_spi { |
| 85 | void __iomem *base; | 86 | void __iomem *base; |
| 86 | u32 state; | 87 | u32 state; |
| 87 | u32 pad_sel; | 88 | int pad_num; |
| 89 | u32 *pad_sel; | ||
| 88 | struct clk *parent_clk, *sel_clk, *spi_clk; | 90 | struct clk *parent_clk, *sel_clk, *spi_clk; |
| 89 | struct spi_transfer *cur_transfer; | 91 | struct spi_transfer *cur_transfer; |
| 90 | u32 xfer_len; | 92 | u32 xfer_len; |
| @@ -188,7 +190,8 @@ static int mtk_spi_prepare_message(struct spi_master *master, | |||
| 188 | 190 | ||
| 189 | /* pad select */ | 191 | /* pad select */ |
| 190 | if (mdata->dev_comp->need_pad_sel) | 192 | if (mdata->dev_comp->need_pad_sel) |
| 191 | writel(mdata->pad_sel, mdata->base + SPI_PAD_SEL_REG); | 193 | writel(mdata->pad_sel[spi->chip_select], |
| 194 | mdata->base + SPI_PAD_SEL_REG); | ||
| 192 | 195 | ||
| 193 | return 0; | 196 | return 0; |
| 194 | } | 197 | } |
| @@ -407,6 +410,9 @@ static int mtk_spi_setup(struct spi_device *spi) | |||
| 407 | if (!spi->controller_data) | 410 | if (!spi->controller_data) |
| 408 | spi->controller_data = (void *)&mtk_default_chip_info; | 411 | spi->controller_data = (void *)&mtk_default_chip_info; |
| 409 | 412 | ||
| 413 | if (mdata->dev_comp->need_pad_sel) | ||
| 414 | gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); | ||
| 415 | |||
| 410 | return 0; | 416 | return 0; |
| 411 | } | 417 | } |
| 412 | 418 | ||
| @@ -481,7 +487,7 @@ static int mtk_spi_probe(struct platform_device *pdev) | |||
| 481 | struct mtk_spi *mdata; | 487 | struct mtk_spi *mdata; |
| 482 | const struct of_device_id *of_id; | 488 | const struct of_device_id *of_id; |
| 483 | struct resource *res; | 489 | struct resource *res; |
| 484 | int irq, ret; | 490 | int i, irq, ret; |
| 485 | 491 | ||
| 486 | master = spi_alloc_master(&pdev->dev, sizeof(*mdata)); | 492 | master = spi_alloc_master(&pdev->dev, sizeof(*mdata)); |
| 487 | if (!master) { | 493 | if (!master) { |
| @@ -512,21 +518,34 @@ static int mtk_spi_probe(struct platform_device *pdev) | |||
| 512 | master->flags = SPI_MASTER_MUST_TX; | 518 | master->flags = SPI_MASTER_MUST_TX; |
| 513 | 519 | ||
| 514 | if (mdata->dev_comp->need_pad_sel) { | 520 | if (mdata->dev_comp->need_pad_sel) { |
| 515 | ret = of_property_read_u32(pdev->dev.of_node, | 521 | mdata->pad_num = of_property_count_u32_elems( |
| 516 | "mediatek,pad-select", | 522 | pdev->dev.of_node, |
| 517 | &mdata->pad_sel); | 523 | "mediatek,pad-select"); |
| 518 | if (ret) { | 524 | if (mdata->pad_num < 0) { |
| 519 | dev_err(&pdev->dev, "failed to read pad select: %d\n", | 525 | dev_err(&pdev->dev, |
| 520 | ret); | 526 | "No 'mediatek,pad-select' property\n"); |
| 527 | ret = -EINVAL; | ||
| 521 | goto err_put_master; | 528 | goto err_put_master; |
| 522 | } | 529 | } |
| 523 | 530 | ||
| 524 | if (mdata->pad_sel > MT8173_SPI_MAX_PAD_SEL) { | 531 | mdata->pad_sel = devm_kmalloc_array(&pdev->dev, mdata->pad_num, |
| 525 | dev_err(&pdev->dev, "wrong pad-select: %u\n", | 532 | sizeof(u32), GFP_KERNEL); |
| 526 | mdata->pad_sel); | 533 | if (!mdata->pad_sel) { |
| 527 | ret = -EINVAL; | 534 | ret = -ENOMEM; |
| 528 | goto err_put_master; | 535 | goto err_put_master; |
| 529 | } | 536 | } |
| 537 | |||
| 538 | for (i = 0; i < mdata->pad_num; i++) { | ||
| 539 | of_property_read_u32_index(pdev->dev.of_node, | ||
| 540 | "mediatek,pad-select", | ||
| 541 | i, &mdata->pad_sel[i]); | ||
| 542 | if (mdata->pad_sel[i] > MT8173_SPI_MAX_PAD_SEL) { | ||
| 543 | dev_err(&pdev->dev, "wrong pad-sel[%d]: %u\n", | ||
| 544 | i, mdata->pad_sel[i]); | ||
| 545 | ret = -EINVAL; | ||
| 546 | goto err_put_master; | ||
| 547 | } | ||
| 548 | } | ||
| 530 | } | 549 | } |
| 531 | 550 | ||
| 532 | platform_set_drvdata(pdev, master); | 551 | platform_set_drvdata(pdev, master); |
| @@ -604,6 +623,26 @@ static int mtk_spi_probe(struct platform_device *pdev) | |||
| 604 | goto err_put_master; | 623 | goto err_put_master; |
| 605 | } | 624 | } |
| 606 | 625 | ||
| 626 | if (mdata->dev_comp->need_pad_sel) { | ||
| 627 | if (mdata->pad_num != master->num_chipselect) { | ||
| 628 | dev_err(&pdev->dev, | ||
| 629 | "pad_num does not match num_chipselect(%d != %d)\n", | ||
| 630 | mdata->pad_num, master->num_chipselect); | ||
| 631 | ret = -EINVAL; | ||
| 632 | goto err_put_master; | ||
| 633 | } | ||
| 634 | |||
| 635 | for (i = 0; i < master->num_chipselect; i++) { | ||
| 636 | ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i], | ||
| 637 | dev_name(&pdev->dev)); | ||
| 638 | if (ret) { | ||
| 639 | dev_err(&pdev->dev, | ||
| 640 | "can't get CS GPIO %i\n", i); | ||
| 641 | goto err_put_master; | ||
| 642 | } | ||
| 643 | } | ||
| 644 | } | ||
| 645 | |||
| 607 | return 0; | 646 | return 0; |
| 608 | 647 | ||
| 609 | err_disable_clk: | 648 | err_disable_clk: |
