From patchwork Wed Apr 28 22:30:25 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hartley Sweeten X-Patchwork-Id: 95820 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o3SMVUQr026143 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 28 Apr 2010 22:32:06 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-2.v29.ch3.sourceforge.com) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1O7Fmv-0005ae-D5; Wed, 28 Apr 2010 22:31:25 +0000 Received: from sfi-mx-3.v28.ch3.sourceforge.com ([172.29.28.123] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1O7Fmu-0005aZ-8v for spi-devel-general@lists.sourceforge.net; Wed, 28 Apr 2010 22:31:24 +0000 X-ACL-Warn: Received: from p01c11o147.mxlogic.net ([208.65.144.70]) by sfi-mx-3.v28.ch3.sourceforge.com with esmtps (TLSv1:AES256-SHA:256) (Exim 4.69) id 1O7Fms-00085C-P8 for spi-devel-general@lists.sourceforge.net; Wed, 28 Apr 2010 22:31:24 +0000 Received: from unknown [216.166.12.99] (EHLO p01c11o147.mxlogic.net) by p01c11o147.mxlogic.net(mxl_mta-6.5.0-2) with ESMTP id a37b8db4.4a01f940.29960.00-420.66993.p01c11o147.mxlogic.net (envelope-from ); Wed, 28 Apr 2010 16:31:22 -0600 (MDT) X-MXL-Hash: 4bd8b73a67872285-4236617a8e74f4f93ea398b80a88a4d0dff114e5 Received: from unknown [216.166.12.99] by p01c11o147.mxlogic.net(mxl_mta-6.5.0-2) with SMTP id b27b8db4.0.29858.00-016.66902.p01c11o147.mxlogic.net (envelope-from ); Wed, 28 Apr 2010 16:31:11 -0600 (MDT) X-MXL-Hash: 4bd8b72f591e8a76-06ae957a9a7cd3dc0e514b303a025231e0ee5f37 Received: from AUSP01VMBX24.collaborationhost.net ([10.2.12.2]) by AUSP01MHUB08.collaborationhost.net ([10.2.8.243]) with mapi; Wed, 28 Apr 2010 17:30:28 -0500 From: H Hartley Sweeten To: Mika Westerberg , "spi-devel-general@lists.sourceforge.net" Date: Wed, 28 Apr 2010 17:30:25 -0500 Thread-Topic: [PATCH v5 0/2] spi: driver for Cirrus EP93xx SPI controller Thread-Index: Acrm+3q8+1JYqYBXQKCfUWvtWxqyRAAIf9Ow Message-ID: <0D753D10438DA54287A00B0270842697636DB622A3@AUSP01VMBX24.collaborationhost.net> References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US MIME-Version: 1.0 X-Spam: [F=0.2000000000; CM=0.500; S=0.200(2010042201)] X-MAIL-FROM: X-SOURCE-IP: [216.166.12.99] X-AnalysisOut: [v=1.0 c=1 a=hxFyygaa3EoA:10 a=VphdPIyG4kEA:10 a=8nJEP1OIZ-] X-AnalysisOut: [IA:10 a=MfCJKx98tC58LqYwCYfhJw==:17 a=drOt6m5kAAAA:8 a=i00] X-AnalysisOut: [gxMtYAAAA:8 a=sIO_mHK_b7FAxCerguoA:9 a=jKFNtec40fSW1XMCn4U] X-AnalysisOut: [A:7 a=XjsdQIoITShTrd57q9e2wKA6w14A:4 a=wPNLvfGTeEIA:10 a=6] X-AnalysisOut: [EvNOKEwbLYA:10 a=x1WnkoZAwusA:10 a=eYh6yvJUMmxvgFki:21 a=x] X-AnalysisOut: [eapu6fh-bhqv3xP:21] X-Spam-Score: 0.0 (/) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 AWL AWL: From: address is in the auto white-list X-Headers-End: 1O7Fms-00085C-P8 Cc: "martinwguy@gmail.com" , "ryan@bluewatersys.com" , "linux-arm-kernel@lists.infradead.org" Subject: Re: [spi-devel-general] [PATCH v5 0/2] spi: driver for Cirrus EP93xx SPI controller X-BeenThere: spi-devel-general@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Linux SPI core/device drivers discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: spi-devel-general-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 28 Apr 2010 22:32:20 +0000 (UTC) --- arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h.orig 2010-04-28 14:36:14.000000000 -0700 +++ arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h 2010-04-28 15:27:39.000000000 -0700 @@ -7,25 +7,20 @@ struct spi_device; * struct ep93xx_spi_info - EP93xx specific SPI descriptor * @num_chipselect: number of chip selects on this board, must be * at least one - * @cs_control: chip select control function. Can be %NULL if not needed. - * - * This structure is passed from board support files to EP93xx SPI controller - * driver. It provides callback hook to control chip select lines that are - * allocated in board support files during the board initialization. */ struct ep93xx_spi_info { int num_chipselect; - /* - * cs_control() - control board chipselect GPIO lines - * @spi: SPI device whose chipselect is controlled - * @value: value to set the chip select line to - * - * This function is used to control board specific chip select lines. - * @value is either %0 or %1. - * - * This function is called from thread context and can sleep if - * necessary. - */ +}; + +/** + * struct ep93xx_spi_chip_ops - operation callbacks for SPI slave device + * @setup: setup the chip select mechanism + * @cleanup: cleanup the chip select mechanism + * @cs_control: control the device chip select + */ +struct ep93xx_spi_chip_ops { + int (*setup)(struct spi_device *spi); + void (*cleanup)(struct spi_device *spi); void (*cs_control)(struct spi_device *spi, int value); }; --- drivers/spi/ep93xx_spi.c.orig 2010-04-28 13:06:07.000000000 -0700 +++ drivers/spi/ep93xx_spi.c 2010-04-28 15:24:47.000000000 -0700 @@ -84,7 +84,6 @@ * @rx: current byte in transfer to receive * @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one * frame decreases this level and sending one frame increases it. - * @cs_control: chip select control function * * This structure holds EP93xx SPI controller specific information. When * @running is %true, driver accepts transfer requests from protocol drivers. @@ -113,7 +112,6 @@ struct ep93xx_spi { size_t tx; size_t rx; size_t fifo_level; - void (*cs_control)(struct spi_device *, int); }; /** @@ -123,6 +121,7 @@ struct ep93xx_spi { * @div_cpsr: cpsr (pre-scaler) divider * @div_scr: scr divider * @dss: bits per word (4 - 16 bits) + * @ops: private chip operations * * This structure is used to store hardware register specific settings for each * SPI device. Settings are written to hardware by function @@ -134,6 +133,7 @@ struct ep93xx_spi_chip { u8 div_cpsr; u8 div_scr; u8 dss; + struct ep93xx_spi_chip_ops *ops; }; /* converts bits per word to CR0.DSS value */ @@ -283,7 +283,6 @@ static int ep93xx_spi_calc_divisors(cons /** * ep93xx_spi_cs_control() - controls chipselect for given device - * @espi: ep93xx SPI controller struct * @spi: SPI device to select/deselect * @control: select (%true) / deselect (%false) * @@ -291,14 +290,13 @@ static int ep93xx_spi_calc_divisors(cons * * Note that this function is called from a thread context and can sleep. */ -static inline void ep93xx_spi_cs_control(const struct ep93xx_spi *espi, - struct spi_device *spi, - bool control) +static void ep93xx_spi_cs_control(struct spi_device *spi, bool control) { + struct ep93xx_spi_chip *chip = spi_get_ctldata(spi); int value = (spi->mode & SPI_CS_HIGH) ? control : !control; - if (espi->cs_control) - espi->cs_control(spi, value); + if (chip->ops && chip->ops->cs_control) + chip->ops->cs_control(spi, value); } /** @@ -323,12 +321,25 @@ static int ep93xx_spi_setup(struct spi_d chip = spi_get_ctldata(spi); if (!chip) { + dev_dbg(&espi->pdev->dev, "initial setup for %s\n", + spi->modalias); + chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; - spi_set_ctldata(spi, chip); chip->spi = spi; + chip->ops = spi->controller_data; + + if (chip->ops && chip->ops->setup) { + ret = chip->ops->setup(spi); + if (ret) { + kfree(chip); + return ret; + } + } + + spi_set_ctldata(spi, chip); } if (spi->max_speed_hz != chip->rate) { @@ -345,7 +356,7 @@ static int ep93xx_spi_setup(struct spi_d chip->dss = bits_per_word_to_dss(spi->bits_per_word); - ep93xx_spi_cs_control(espi, spi, false); + ep93xx_spi_cs_control(spi, false); return 0; } @@ -414,6 +425,8 @@ static void ep93xx_spi_cleanup(struct sp chip = spi_get_ctldata(spi); if (chip) { + if (chip->ops && chip->ops->cleanup) + chip->ops->cleanup(spi); spi_set_ctldata(spi, NULL); kfree(chip); } @@ -610,9 +623,9 @@ static void ep93xx_spi_process_transfer( * chipselect briefly, we let the scheduler to handle * any "delay" here. */ - ep93xx_spi_cs_control(espi, msg->spi, false); + ep93xx_spi_cs_control(msg->spi, false); cond_resched(); - ep93xx_spi_cs_control(espi, msg->spi, true); + ep93xx_spi_cs_control(msg->spi, true); } } @@ -674,7 +687,7 @@ static void ep93xx_spi_process_message(s * the chipselect. */ ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi)); - ep93xx_spi_cs_control(espi, msg->spi, true); + ep93xx_spi_cs_control(msg->spi, true); list_for_each_entry(t, &msg->transfers, transfer_list) { ep93xx_spi_process_transfer(espi, msg, t); @@ -686,7 +699,7 @@ static void ep93xx_spi_process_message(s * Now the whole message is transferred (or failed for some reason). We * deselect the device and disable the SPI controller. */ - ep93xx_spi_cs_control(espi, msg->spi, false); + ep93xx_spi_cs_control(msg->spi, false); ep93xx_spi_disable(espi); } @@ -811,7 +824,6 @@ static int __init ep93xx_spi_probe(struc platform_set_drvdata(pdev, master); espi = spi_master_get_devdata(master); - espi->cs_control = info->cs_control; espi->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(espi->clk)) { @@ -860,7 +872,7 @@ static int __init ep93xx_spi_probe(struc } error = request_irq(espi->irq, ep93xx_spi_interrupt, 0, - "ep93xx-spi", espi); + "ep93xx-spi", espi); if (error) { dev_err(&pdev->dev, "failed to request irq\n"); goto fail_unmap_regs; @@ -878,7 +890,7 @@ static int __init ep93xx_spi_probe(struc /* make sure that the hardware is disabled */ ep93xx_spi_write_u8(espi, SSPCR1, 0); - error = spi_register_master(master); + error = spi_register_master(master); if (error) { dev_err(&pdev->dev, "failed to register SPI master\n"); goto fail_free_queue;