From patchwork Mon May 25 10:07:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: haikun wang X-Patchwork-Id: 6473201 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 36228C0020 for ; Mon, 25 May 2015 10:26:42 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 13D9D203F4 for ; Mon, 25 May 2015 10:26:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B6F52203F1 for ; Mon, 25 May 2015 10:26:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751203AbbEYK0d (ORCPT ); Mon, 25 May 2015 06:26:33 -0400 Received: from mail-by2on0145.outbound.protection.outlook.com ([207.46.100.145]:39808 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750859AbbEYK0b (ORCPT ); Mon, 25 May 2015 06:26:31 -0400 Received: from CO2PR03CA0016.namprd03.prod.outlook.com (10.141.194.143) by DM2PR0301MB0623.namprd03.prod.outlook.com (10.160.95.27) with Microsoft SMTP Server (TLS) id 15.1.166.22; Mon, 25 May 2015 10:11:49 +0000 Received: from BY2FFO11FD054.protection.gbl (2a01:111:f400:7c0c::119) by CO2PR03CA0016.outlook.office365.com (2a01:111:e400:1414::15) with Microsoft SMTP Server (TLS) id 15.1.172.22 via Frontend Transport; Mon, 25 May 2015 10:11:48 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none; Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Received: from tx30smr01.am.freescale.net (192.88.168.50) by BY2FFO11FD054.mail.protection.outlook.com (10.1.15.191) with Microsoft SMTP Server (TLS) id 15.1.172.14 via Frontend Transport; Mon, 25 May 2015 10:11:48 +0000 Received: from titan.ap.freescale.net ([10.192.208.233]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id t4PABjgd017885; Mon, 25 May 2015 03:11:46 -0700 From: Haikun Wang To: , CC: Haikun Wang Subject: [PATCH v3] spi: spi-fsl-dspi: Enable TCF interrupt mode support Date: Mon, 25 May 2015 18:07:49 +0800 Message-ID: <1432548469-12714-1-git-send-email-haikun.wang@freescale.com> X-Mailer: git-send-email 2.1.0.27.g96db324 X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD054; 1:zoK00GTcpVSPKNKP4hkSPZF5kPWzJ1CVkeWgdhHrCiUIa3mwU+q5VBsGIAeM9fvx42uYLBzSNhCE8PHmHRe/AC0r/EZ2VlguUrQ6OHPvbJPKmRXW6Ys6aRR063qWRyuzP+IdXxCaf3GjsXZSAVSCeXlVk2wwan+ztroMxKUm7uJsneZ92A8gz5vLevDwKg3iBFidREhs8cWjllov81BkQ8MHfx0HCKiGz9wm4X0DvxMOOiug09LMu06wanclF13S1NM2A+5RB7rtwUTPxd2RbOMA0J6BW70OjmKagmwTSpkGwF+F6hPvBczUVdqWp17qt8ygzgCowMZ2L6eQygOXBQ== X-Forefront-Antispam-Report: CIP:192.88.168.50; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(339900001)(189002)(199003)(4001540100001)(19580395003)(36756003)(229853001)(5001770100001)(5001830100001)(5001860100001)(62966003)(189998001)(19580405001)(81156007)(50226001)(106466001)(68736005)(97736004)(50466002)(77096005)(5001960100002)(105606002)(107886002)(230783001)(6806004)(77156002)(33646002)(47776003)(87936001)(86362001)(92566002)(64706001)(85426001)(48376002)(50986999)(46102003)(104016003)(5001920100001)(4001430100001); DIR:OUT; SFP:1102; SCL:1; SRVR:DM2PR0301MB0623; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Exchange-Diagnostics: 1; DM2PR0301MB0623; 2:sMY42hL1MfSPrd5p/kT73EV5nxYFZyqmUR/piTf+NUMn+KmoYCNAV0SBYzv6Y7E9; 2:jYeeutKg3PqzlKybHrEga63EjCisZ1w1CS0Ox+CoXbaxvN9ztIHGbqOYbnK9cA8gv3ShVO0vzt0bQIUqsdKPKfEk61hFwVjfRy0YAPV5Q4DZUvkWrxf2fu1J3lu8oyNYVrzfcOApJNbmmNSkd2WMhOPMfZeJ2BR1Tjo6ncYx9FLdY3xdrrKKrtG7TIv4C2qu/RsGQue3wrKGtcS0UDKLXOTGtCGKNS3Ymehdo59eMMg=; 6:Lv36AzWVBWRpa1yzZiWsdKysEMPgDOXZFK4b938MFzFIjf9Gsk9Vd8qif+agCdHNKpWlSWBPwq7mK2ZUCTx/pdwicYBu37dtSzaq+g7dNWMc1uGSY0QqCHfO8pFx2jk+y43ZLoioRGGXsj2SjfZwpUuDlAl3YpBzJF/AsjU7EyhbsSeTirNRXuNN7lGkXc2ERKjnLjRuumR3mcE8AKXLiyHRWWT3M9qOBUx8dxgFCGezy2L6b8Dq6Bz7zTzm2MLJZnvXAVvKSAzoDcohw2jJdMFZQKCsm+LyfR9fLkrxqGDMr2leJBJY1vlpRUpUnebhK2l1V4I9E8SFn+WETHFjkA== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DM2PR0301MB0623; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(5005006)(520002)(3002001); SRVR:DM2PR0301MB0623; BCL:0; PCL:0; RULEID:; SRVR:DM2PR0301MB0623; X-Microsoft-Exchange-Diagnostics: 1; DM2PR0301MB0623; 3:E5YqjW40kwJV+r1PUaOulQ7kJprcjuBV3Yw5gFJ9J619TsdVIpn+FGWLcRhT6Q9NUAOnYP2+dpwuUvLIwWWykdg7pv0Qr4R4kMAJZCBdyq21GDNCiXavlz4mbFoCjxZr9p6QvK8/Tp/E0fIG/MeveOVme3o5ymC9D8nwCWCl/7G7vKbyWq07MPXbbTLUdtHU04gSqi6Pj5MKAeIySmWmrjDEPWErZsVzxz7K2xMHauFnYwtkpc8YZtGIWgqhO+NJMPTgTlt9f+OgdldHbhew2L7rY22qXc2wOsb6Cd0tfpUlhuqYXQzjgJRfG6RbszNS X-Forefront-PRVS: 058707456E X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; DM2PR0301MB0623; 9:VTyQ21HnBf3cZ8a/tmSKeC9kMhfVsBEmxt7aMs+K?= =?us-ascii?Q?LZ3RbM9zyFyGEYjkmTRgjFrfyKVfwXKVIjz8iQ36I2CBw61vlD9+34ccwFy0?= =?us-ascii?Q?Asc9Oc4mNUQeStTtaOPjOS1kznwRjq8njg4/5G69JNRtlA1LBBxZ9prETI2J?= =?us-ascii?Q?gq/Gr/O0VsT2fyLploiiAk2Z/zj2Zlc5pFv9ej55qWuBUgrfC4iAopj8LjxH?= =?us-ascii?Q?9zmS1rWi5sbAJh9YHYaac7Yog7N4fumP8dkvv+nCZF5a7vHFpAbhFAJTDwGL?= =?us-ascii?Q?IIXzAGK4f0DcYKjw2BZLHXpUObp3JJoFKrW2BNfXYt6LCZ/GCCED+RDsJ9z/?= =?us-ascii?Q?XmPcB+fvQyTUT2F9rHBaqqzO6+dgMaQlMxhbp/Qwx1uA6gNu5qK5/irML8fm?= =?us-ascii?Q?6YE22bw5zqtNpV1LmctKSDSMculukYsRtNL8GQ1pwtx7xh5BG4GPC6HlLmcX?= =?us-ascii?Q?4Z3PzRVyLjbklyhcwWMM+AbdVwRFfARxyd8kh+mTvepbLHS/qU/zPkagaO2Q?= =?us-ascii?Q?mRHB6NJu4XN6X6qsCqg0XEyFdszDd89RPDHvPvth4cvbp7Tu1MTG/JvpA+px?= =?us-ascii?Q?nVRHNmKYCm0B325rFggtEKeSacLuh7o1FYNltKHh8nB0T6NfSNUEVoLgVWfi?= =?us-ascii?Q?7nviL/V0ren5Z/ClMHM0XHwR8TmNbh7LNgmZ89DAt6V3y4MarRQPT/wUxPvZ?= =?us-ascii?Q?RG1G/Rx+co29dq6Mt9ASueCUIOgwLR6lGlh7CtzTAyoCqcNPxi5gSSDh1QzK?= =?us-ascii?Q?BDf5gU6lSgsNwbnhZ9wtpwmu6C/Amj6qomM0HMsfjOeivGVfIEaprwV4A/lF?= =?us-ascii?Q?Kc271Wmc463s/9A+6RffTEr69nTeMnZ34Asn2iedWl4aMRfCsJoVtrLy5guI?= =?us-ascii?Q?9i3dVcTS82+1oecu22ZzIVzN6D14sTywaSHBZrcdJjVXex+AQBJXLNb7eRi9?= =?us-ascii?Q?lxKf8mDWsvR0W6iOR0G8UA5ACq3LoLoiGqdsq1PDjxW49ZIJjckvTxTMMzfs?= =?us-ascii?Q?9tdpMz6mOVgjSdrV2JbGvQoHJQozRd13qZfP1f8pfkKY33PB5jhAlGS/JTgd?= =?us-ascii?Q?U5LpVBMW7eciY3PB7IlSpxeRWyO7ArtfD4OOirajzrdPmX1Cjg=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1; DM2PR0301MB0623; 3:wWBLf82pY3aR3DlTie8B4F6hN2QLrwA77rYFKWkqbnly1Gr/CNL0WfIAjeX9hQykxf5LXta3OeuhzitXTX5ipr5uJb7pRH28bv98Tu+a7J7x1U0/9ALiXz0tgjC5qX7p4Us6dK2xucSltjwt/OBimQ==; 10:PU4ZhfA/y2ZPwoV7LW5o239X/S/o9d4jGA+Z6Ocy0ZSx4FI92mfd69hiawsbI0VuzkvROjISWddp6+tgavrfaD62Q3Jq5sUj3THKWaqfZ/Y=; 6:3FH8CsAphGm3vXo2qwQdH7Q0e00D+u8Zcz0dExC5YHuGCfeHpcul4agArLcDqiXX X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 May 2015 10:11:48.3412 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM2PR0301MB0623 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=ham 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 DSPI module has two optional interrupts when complete data transfer. One is EOQ interrupt, the other one is TCF interrupt. EOQ indicates a queue of data frame has been transmitted. TCF indicates a frame has been transmitted. This patch enable support TCF mode. Driver binds a correct interrupt mode to every compatible string. User should use the correct compatible string in the dts node. Signed-off-by: Haikun Wang --- Changes in v3: - Using different compatible strings instead of a individual property to select the interrupt mode Changes in v2: - Remove global variable g_actual_length - Add "dspi->dataflags &= ~TRAN_STATE_WORD_ODD_NUM" if dataflags has TRAN_STATE_WORD_ODD_NUM in IRQ handler - Move single byte chacking inside while loop in function dspi_eoq_write Changes in v1: None drivers/spi/spi-fsl-dspi.c | 214 +++++++++++++++++++++++++++++---------------- 1 file changed, 139 insertions(+), 75 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 5fe54cd..ce2062a 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -67,9 +67,11 @@ #define SPI_SR 0x2c #define SPI_SR_EOQF 0x10000000 +#define SPI_SR_TCFQF 0x80000000 #define SPI_RSER 0x30 #define SPI_RSER_EOQFE 0x10000000 +#define SPI_RSER_TCFQE 0x80000000 #define SPI_PUSHR 0x34 #define SPI_PUSHR_CONT (1 << 31) @@ -108,6 +110,27 @@ struct chip_data { u16 void_write_data; }; +enum dspi_trans_mode { + DSPI_EOQ_MODE = 0, + DSPI_TCFQ_MODE, +}; + +struct fsl_dspi_devtype_data { + enum dspi_trans_mode trans_mode; +}; + +static const struct fsl_dspi_devtype_data vf610_data = { + .trans_mode = DSPI_EOQ_MODE, +}; + +static const struct fsl_dspi_devtype_data ls1021a_v1_data = { + .trans_mode = DSPI_TCFQ_MODE, +}; + +static const struct fsl_dspi_devtype_data ls2085a_data = { + .trans_mode = DSPI_TCFQ_MODE, +}; + struct fsl_dspi { struct spi_master *master; struct platform_device *pdev; @@ -128,6 +151,7 @@ struct fsl_dspi { u8 cs; u16 void_write_data; u32 cs_change; + struct fsl_dspi_devtype_data *devtype_data; wait_queue_head_t waitq; u32 waitflags; @@ -213,63 +237,61 @@ static void ns_delay_scale(char *psc, char *sc, int delay_ns, } } -static int dspi_transfer_write(struct fsl_dspi *dspi) +static u32 dspi_data_to_pushr(struct fsl_dspi *dspi, int tx_word) { - int tx_count = 0; - int tx_word; u16 d16; - u8 d8; - u32 dspi_pushr = 0; - int first = 1; - tx_word = is_double_byte_mode(dspi); + if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) + d16 = tx_word ? *(u16 *)dspi->tx : *(u8 *)dspi->tx; + else + d16 = dspi->void_write_data; - /* If we are in word mode, but only have a single byte to transfer - * then switch to byte mode temporarily. Will switch back at the - * end of the transfer. - */ - if (tx_word && (dspi->len == 1)) { - dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; - regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), - SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8)); - tx_word = 0; - } + dspi->tx += tx_word + 1; + dspi->len -= tx_word + 1; - while (dspi->len && (tx_count < DSPI_FIFO_SIZE)) { - if (tx_word) { - if (dspi->len == 1) - break; + return SPI_PUSHR_TXDATA(d16) | + SPI_PUSHR_PCS(dspi->cs) | + SPI_PUSHR_CTAS(dspi->cs) | + SPI_PUSHR_CONT; +} - if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) { - d16 = *(u16 *)dspi->tx; - dspi->tx += 2; - } else { - d16 = dspi->void_write_data; - } +static void dspi_data_from_popr(struct fsl_dspi *dspi, int rx_word) +{ + u16 d; + unsigned int val; - dspi_pushr = SPI_PUSHR_TXDATA(d16) | - SPI_PUSHR_PCS(dspi->cs) | - SPI_PUSHR_CTAS(dspi->cs) | - SPI_PUSHR_CONT; + regmap_read(dspi->regmap, SPI_POPR, &val); + d = SPI_POPR_RXDATA(val); - dspi->len -= 2; - } else { - if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) { + if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) + rx_word ? (*(u16 *)dspi->rx = d) : (*(u8 *)dspi->rx = d); - d8 = *(u8 *)dspi->tx; - dspi->tx++; - } else { - d8 = (u8)dspi->void_write_data; - } + dspi->rx += rx_word + 1; +} - dspi_pushr = SPI_PUSHR_TXDATA(d8) | - SPI_PUSHR_PCS(dspi->cs) | - SPI_PUSHR_CTAS(dspi->cs) | - SPI_PUSHR_CONT; +static int dspi_eoq_write(struct fsl_dspi *dspi) +{ + int tx_count = 0; + int tx_word; + u32 dspi_pushr = 0; + int first = 1; - dspi->len--; + tx_word = is_double_byte_mode(dspi); + + while (dspi->len && (tx_count < DSPI_FIFO_SIZE)) { + /* If we are in word mode, only have a single byte to transfer + * switch to byte mode temporarily. Will switch back at the + * end of the transfer. + */ + if (tx_word && (dspi->len == 1)) { + dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; + regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), + SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8)); + tx_word = 0; } + dspi_pushr = dspi_data_to_pushr(dspi, tx_word); + if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) { /* last transfer in the transfer */ dspi_pushr |= SPI_PUSHR_EOQ; @@ -291,40 +313,55 @@ static int dspi_transfer_write(struct fsl_dspi *dspi) return tx_count * (tx_word + 1); } -static int dspi_transfer_read(struct fsl_dspi *dspi) +static int dspi_eoq_read(struct fsl_dspi *dspi) { int rx_count = 0; int rx_word = is_double_byte_mode(dspi); - u16 d; while ((dspi->rx < dspi->rx_end) && (rx_count < DSPI_FIFO_SIZE)) { - if (rx_word) { - unsigned int val; + if (rx_word && (dspi->rx_end - dspi->rx) == 1) + rx_word = 0; - if ((dspi->rx_end - dspi->rx) == 1) - break; + dspi_data_from_popr(dspi, rx_word); + rx_count++; + } - regmap_read(dspi->regmap, SPI_POPR, &val); - d = SPI_POPR_RXDATA(val); + return rx_count; +} - if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) - *(u16 *)dspi->rx = d; - dspi->rx += 2; +static int dspi_tcfq_write(struct fsl_dspi *dspi) +{ + int tx_word; + u32 dspi_pushr = 0; - } else { - unsigned int val; + tx_word = is_double_byte_mode(dspi); - regmap_read(dspi->regmap, SPI_POPR, &val); - d = SPI_POPR_RXDATA(val); - if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) - *(u8 *)dspi->rx = d; - dspi->rx++; - } - rx_count++; + if (tx_word && (dspi->len == 1)) { + dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; + regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), + SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8)); + tx_word = 0; } - return rx_count; + dspi_pushr = dspi_data_to_pushr(dspi, tx_word); + + if ((dspi->cs_change) && (!dspi->len)) + dspi_pushr &= ~SPI_PUSHR_CONT; + + regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr); + + return tx_word + 1; +} + +static void dspi_tcfq_read(struct fsl_dspi *dspi) +{ + int rx_word = is_double_byte_mode(dspi); + + if (rx_word && (dspi->rx_end - dspi->rx) == 1) + rx_word = 0; + + dspi_data_from_popr(dspi, rx_word); } static int dspi_transfer_one_message(struct spi_master *master, @@ -334,6 +371,7 @@ static int dspi_transfer_one_message(struct spi_master *master, struct spi_device *spi = message->spi; struct spi_transfer *transfer; int status = 0; + message->actual_length = 0; list_for_each_entry(transfer, &message->transfers, transfer_list) { @@ -370,8 +408,13 @@ static int dspi_transfer_one_message(struct spi_master *master, regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val); - regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE); - message->actual_length += dspi_transfer_write(dspi); + if (dspi->devtype_data->trans_mode == DSPI_EOQ_MODE) { + regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE); + message->actual_length += dspi_eoq_write(dspi); + } else if (dspi->devtype_data->trans_mode == DSPI_TCFQ_MODE) { + regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE); + message->actual_length += dspi_tcfq_write(dspi); + } if (wait_event_interruptible(dspi->waitq, dspi->waitflags)) dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n"); @@ -460,27 +503,39 @@ static void dspi_cleanup(struct spi_device *spi) static irqreturn_t dspi_interrupt(int irq, void *dev_id) { struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; - struct spi_message *msg = dspi->cur_msg; - regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF); - dspi_transfer_read(dspi); + if (dspi->devtype_data->trans_mode == DSPI_EOQ_MODE) { + regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF); + dspi_eoq_read(dspi); + } else if (dspi->devtype_data->trans_mode == DSPI_TCFQ_MODE) { + regmap_write(dspi->regmap, SPI_SR, SPI_SR_TCFQF); + dspi_tcfq_read(dspi); + } if (!dspi->len) { - if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) + if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) { regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16)); + dspi->dataflags &= ~TRAN_STATE_WORD_ODD_NUM; + } dspi->waitflags = 1; wake_up_interruptible(&dspi->waitq); - } else - msg->actual_length += dspi_transfer_write(dspi); - + } else { + if (dspi->devtype_data->trans_mode == DSPI_EOQ_MODE) + msg->actual_length += dspi_eoq_write(dspi); + else if (dspi->devtype_data->trans_mode == DSPI_TCFQ_MODE) + msg->actual_length += dspi_tcfq_write(dspi); + } return IRQ_HANDLED; } static const struct of_device_id fsl_dspi_dt_ids[] = { - { .compatible = "fsl,vf610-dspi", .data = NULL, }, + { .compatible = "fsl,vf610-dspi", .data = (void *)&vf610_data, }, + { .compatible = "fsl,ls1021a-v1.0-dspi", + .data = (void *)&ls1021a_v1_data, }, + { .compatible = "fsl,ls2085a-dspi", .data = (void *)&ls2085a_data, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_dspi_dt_ids); @@ -526,6 +581,8 @@ static int dspi_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; int ret = 0, cs_num, bus_num; + const struct of_device_id *of_id = + of_match_device(fsl_dspi_dt_ids, &pdev->dev); master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); if (!master) @@ -559,6 +616,13 @@ static int dspi_probe(struct platform_device *pdev) } master->bus_num = bus_num; + dspi->devtype_data = (struct fsl_dspi_devtype_data *)of_id->data; + if (!dspi->devtype_data) { + dev_err(&pdev->dev, "can't get devtype_data\n"); + ret = -EFAULT; + goto out_master_put; + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) {