From patchwork Wed Oct 14 03:23:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leilk Liu X-Patchwork-Id: 7390051 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7DA36BEEA4 for ; Wed, 14 Oct 2015 03:24:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7CEA520832 for ; Wed, 14 Oct 2015 03:24:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6C70320833 for ; Wed, 14 Oct 2015 03:24:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752553AbbJNDYU (ORCPT ); Tue, 13 Oct 2015 23:24:20 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:32930 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1752506AbbJNDYQ (ORCPT ); Tue, 13 Oct 2015 23:24:16 -0400 X-Listener-Flag: 11101 Received: from mtkhts07.mediatek.inc [(172.21.101.69)] by mailgw02.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 84188577; Wed, 14 Oct 2015 11:24:14 +0800 Received: from localhost.localdomain (10.17.3.153) by mtkhts07.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 14.3.181.6; Wed, 14 Oct 2015 11:24:13 +0800 From: Leilk Liu To: Mark Brown CC: Mark Rutland , Matthias Brugger , Sascha Hauer , , , , , , Leilk Liu Subject: [PATCH 4/5] spi: mediatek: mt8173 spi multiple devices support Date: Wed, 14 Oct 2015 11:23:34 +0800 Message-ID: <1444793015-30359-5-git-send-email-leilk.liu@mediatek.com> X-Mailer: git-send-email 1.8.1.1.dirty In-Reply-To: <1444793015-30359-1-git-send-email-leilk.liu@mediatek.com> References: <1444793015-30359-1-git-send-email-leilk.liu@mediatek.com> MIME-Version: 1.0 X-MTK: N Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP mt8173 IC spi HW has 4 gpio group, it's possible to support max <= 4 slave devices, even mtk spi HW is not congruent to spi core. 1. When a device do a spi_message transfer, spi HW should know which pad-group this device is on, and then writes pad-select register. 2. Mtk pad-select register just selects which MISO pin HW will receive data. For example, pad-select=1(select spi1 pins), HW just receives data from spi1 MISO, but it still send waveform to all 4 group cs/clk/mosi. If cs pin in other groups is still spi mode, after spi1 is selected(by active cs pin), devices on other group will also be selected. Signed-off-by: Leilk Liu --- drivers/spi/spi-mt65xx.c | 65 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 13 deletions(-) mode change 100755 => 100644 drivers/spi/spi-mt65xx.c diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c old mode 100755 new mode 100644 index 406695a..563954a --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -84,7 +85,8 @@ struct mtk_spi_compatible { struct mtk_spi { void __iomem *base; u32 state; - u32 pad_sel; + int pad_num; + u32 *pad_sel; struct clk *parent_clk, *sel_clk, *spi_clk; struct spi_transfer *cur_transfer; u32 xfer_len; @@ -188,7 +190,8 @@ static int mtk_spi_prepare_message(struct spi_master *master, /* pad select */ if (mdata->dev_comp->need_pad_sel) - writel(mdata->pad_sel, mdata->base + SPI_PAD_SEL_REG); + writel(mdata->pad_sel[spi->chip_select], + mdata->base + SPI_PAD_SEL_REG); return 0; } @@ -407,6 +410,9 @@ static int mtk_spi_setup(struct spi_device *spi) if (!spi->controller_data) spi->controller_data = (void *)&mtk_default_chip_info; + if (mdata->dev_comp->need_pad_sel) + gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); + return 0; } @@ -481,7 +487,7 @@ static int mtk_spi_probe(struct platform_device *pdev) struct mtk_spi *mdata; const struct of_device_id *of_id; struct resource *res; - int irq, ret; + int i, irq, ret; master = spi_alloc_master(&pdev->dev, sizeof(*mdata)); if (!master) { @@ -512,21 +518,34 @@ static int mtk_spi_probe(struct platform_device *pdev) master->flags = SPI_MASTER_MUST_TX; if (mdata->dev_comp->need_pad_sel) { - ret = of_property_read_u32(pdev->dev.of_node, - "mediatek,pad-select", - &mdata->pad_sel); - if (ret) { - dev_err(&pdev->dev, "failed to read pad select: %d\n", - ret); + mdata->pad_num = of_property_count_u32_elems( + pdev->dev.of_node, + "mediatek,pad-select"); + if (mdata->pad_num < 0) { + dev_err(&pdev->dev, + "No 'mediatek,pad-select' property\n"); + ret = -EINVAL; goto err_put_master; } - if (mdata->pad_sel > MT8173_SPI_MAX_PAD_SEL) { - dev_err(&pdev->dev, "wrong pad-select: %u\n", - mdata->pad_sel); - ret = -EINVAL; + mdata->pad_sel = devm_kmalloc_array(&pdev->dev, mdata->pad_num, + sizeof(u32), GFP_KERNEL); + if (!mdata->pad_sel) { + ret = -ENOMEM; goto err_put_master; } + + for (i = 0; i < mdata->pad_num; i++) { + of_property_read_u32_index(pdev->dev.of_node, + "mediatek,pad-select", + i, &mdata->pad_sel[i]); + if (mdata->pad_sel[i] > MT8173_SPI_MAX_PAD_SEL) { + dev_err(&pdev->dev, "wrong pad-sel[%d]: %u\n", + i, mdata->pad_sel[i]); + ret = -EINVAL; + goto err_put_master; + } + } } platform_set_drvdata(pdev, master); @@ -604,6 +623,26 @@ static int mtk_spi_probe(struct platform_device *pdev) goto err_put_master; } + if (mdata->dev_comp->need_pad_sel) { + if (mdata->pad_num != master->num_chipselect) { + dev_err(&pdev->dev, + "pad_num does not match num_chipselect(%d != %d)\n", + mdata->pad_num, master->num_chipselect); + ret = -EINVAL; + goto err_put_master; + } + + for (i = 0; i < master->num_chipselect; i++) { + ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i], + dev_name(&pdev->dev)); + if (ret) { + dev_err(&pdev->dev, + "can't get CS GPIO %i\n", i); + goto err_put_master; + } + } + } + return 0; err_disable_clk: