Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 02/13] clk: davinci - add PSC clock driver
From: Karicheri, Muralidharan @ 2012-10-10 14:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50756DFD.4070203@ti.com>

>> -----Original Message-----
>> From: Nori, Sekhar
>> Sent: Wednesday, October 10, 2012 8:46 AM
>> To: Nori, Sekhar
>> Cc: Karicheri, Muralidharan; Hilman, Kevin; davinci-linux-open-
>> source at linux.davincidsp.com; mturquette at linaro.org; linux-c6x-dev at linux-c6x.org;
>> arnd at arndb.de; linus.walleij at linaro.org; linux-kernel at vger.kernel.org;
>> rob.herring at calxeda.com; linux-keystone at list.ti.com - Linux developers for Keystone
>> family of devices (May contain non-TIers); viresh.linux at gmail.com;
>> linux at arm.linux.org.uk; akpm at linux-foundation.org; shawn.guo at linaro.org; linux-arm-
>> kernel at lists.infradead.org
>> Subject: Re: [PATCH 02/13] clk: davinci - add PSC clock driver
>> 
>> On 10/10/2012 6:05 PM, Sekhar Nori wrote:
>> 
>> >> +struct clk *clk_register_davinci_psc(struct device *dev, const char *name,
>> >> +			const char *parent_name,
>> >> +			struct clk_davinci_psc_data *psc_data,
>> >> +			spinlock_t *lock)
>> >
>> > Why do you need the lock to be provided from outside of this file? You
>> > can initialize a lock for serializing writes to PSC registers within
>> > this file, no?
>> 
>> Looking again, it seems like the common clock framework defines an "enable_lock" in
>> drivers/clk/clk.c to serialize the clock enable/disable calls. Unless I am missing something,
>> this lock seems unnecessary.
>> 

I think you are right. For enable() api, enable_lock is sufficient and I will remove this.

>> Thanks,
>> Sekhar

^ permalink raw reply

* [PATCH] ARM: OMAP2+: gpmc: Fix kernel BUG for DT boot mode
From: Matt Porter @ 2012-10-10 14:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349773040-8204-1-git-send-email-hvaibhav@ti.com>

On Tue, Oct 09, 2012 at 02:27:20PM +0530, Vaibhav Hiremath wrote:
> With recent changes in omap gpmc driver code, in case of DT
> boot mode, where bootloader does not configure gpmc cs space
> will result into kernel BUG() inside gpmc_mem_init() function,
> as gpmc cs0 gpmc_config7[0].csvalid bit is set to '1' and
> gpmc_config7[0].baseaddress is set to '0' on reset.
> 
> This use-case is applicable for any board/EVM which doesn't have
> any peripheral connected to gpmc cs0, for example BeagleXM and
> BeagleBone, so DT boot mode fails.
> 
> This patch adds of_have_populated_dt() check before creating
> device, so that for DT boot mode, gpmc probe will not be called
> which is expected behavior, as gpmc is not supported yet from DT.
> 
> Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
> Cc: Afzal Mohammed <afzal@ti.com>
> Cc: Tony Lindgren <tony@atomide.com>
> Cc Paul Walmsley <paul@pwsan.com>
> ---
> This should go in for rc1, as this breaks AM33xx boot.

Fixes BeagleBone on mainline.

Tested-by: Matt Porter <mporter@ti.com>

-Matt

^ permalink raw reply

* [PATCH v2 3/5] ARM: use generic unaligned.h
From: Nicolas Pitre @ 2012-10-10 13:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50757837.8050200@gmail.com>

On Wed, 10 Oct 2012, Rob Herring wrote:

> On 10/08/2012 11:01 PM, Nicolas Pitre wrote:
> > On Mon, 8 Oct 2012, Rob Herring wrote:
> > 
> >> On 10/08/2012 06:28 PM, Shawn Guo wrote:
> >>> On Mon, Oct 08, 2012 at 03:34:57PM -0500, Rob Herring wrote:
> >>>> On 10/08/2012 11:43 AM, Shawn Guo wrote:
> >>>>> This patch has been merged into mainline as commit below.
> >>>>>
> >>>>>  d25c881 ARM: 7493/1: use generic unaligned.h
> >>>>>
> >>>>> It introduces a regression for me.  Check out the commit on mainline,
> >>>>> build a v7 only kernel (imx5/6) with imx_v6_v7_defconfig, the kernel
> >>>>> halts in decompressor.  But v6/v7 kernel (imx3/5/6) works fine.  The
> >>>>> kernel built on the parent commit below works all fine.
> >>>>
> >>>> It actually fails in the decompressor or that's the last output you get?
> >>>
> >>> I think it fails in the decompressor, because what I see is 
> >>>
> >>> Uncompressing Linux...
> >>>
> >>> not
> >>>
> >>> Uncompressing Linux... done, booting the kernel.
> >>>
> >>>> I compared the decompressor disassembly of both cases and get the same
> >>>> number of ldrb/strb instructions, so I don't think it is directly
> >>>> related to alignment.
> >>>>
> >>>> I tried the XY decompressor as that is one difference, but that works
> >>>> fine for me on highbank.
> >>>>
> >>>> Does it work with an empty uncompress.h functions? That should be the
> >>>> only difference in our decompressor code.
> >>>
> >>> No, empty putc() in uncompress.h does not help.
> >>>
> >>> New finding is that it only fails with LZO decompressor while the other
> >>> 3 Gzip, LZMA and XZ all work good.  We happen to have LZO as the default
> >>> one in imx_v6_v7_defconfig.
> >>
> >> I must have had an old config with XZ. LZO fails because of this:
> >>  
> >> lib/decompress_unlzo.c: version = get_unaligned_be16(parse);
> >> lib/decompress_unlzo.c: if (get_unaligned_be32(parse) & HEADER_HAS_FILTER)
> >> lib/decompress_unlzo.c:         dst_len = get_unaligned_be32(in_buf);
> >> lib/decompress_unlzo.c:         src_len = get_unaligned_be32(in_buf);
> >>
> >> This was what I was afraid of. The decompressor runs with the sysctrl
> >> register A bit in whatever state the bootloader left it in. In the case
> >> of u-boot it is set, and the maintainers are pretty set on not allowing
> >> unaligned accesses if you've seen the recent discussion.
> > 
> > This is not an u-Boot issue.  The kernel code expects misaligned 
> > accesses to be handled by the hardware on ARMv6+ now.  So it better 
> > enforce proper A bit state itself.
> > 
> >> This should fix things.
> >>
> >> Rob
> >>
> >> 8<---------------------------------------------------------------------
> >>
> >> diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
> >> index bc67cbf..1f87d22 100644
> >> --- a/arch/arm/boot/compressed/head.S
> >> +++ b/arch/arm/boot/compressed/head.S
> >> @@ -654,6 +654,7 @@ __armv7_mmu_cache_on:
> >>  #endif
> >>                 mrc     p15, 0, r0, c1, c0, 0   @ read control reg
> >>                 bic     r0, r0, #1 << 28        @ clear SCTLR.TRE
> >> +               bic     r0, r0, #1 << 1         @ clear SCTLR.A
> >>                 orr     r0, r0, #0x5000         @ I-cache enable, RR cache replacement
> >>                 orr     r0, r0, #0x003c         @ write buffer
> >>  #ifdef CONFIG_MMU
> >>
> > 
> > That's OK for ARMv7, but in the ARMv6 case we use __armv4_mmu_cache_on.  
> > So this patch is incomplete.
> 
> It is still optional on v6 and the compiler will not emit unaligned
> accesses for v6 (which is why it worked when v6 platforms were enabled).

Hmmm, right. However if you look at commit 8428e84d42, the A bit is 
cleared whenever we compile for ARMv6 or higher.  Of course, the 
decompressor doesn't have to deal with unknown user space binaries and 
in that case we might trust that the compiler will never emit known to 
be unaligned loads.

In that case...

Acked-by: Nicolas Pitre <nico@linaro.org>

> That does raise a bigger question. If we're doing combined v6 and v7
> builds, do we want this to require unaligned accesses are enabled and if
> so, can we force that on in the compiler?

When we compile ARMv6 and ARMv7 targets together, the compiler is told 
to compile for ARMv6.  We know that unaligned accesses will be done 
usingLDRB/STRB in that case.


Nicolas

^ permalink raw reply

* [PATCH] i2c: at91: add dma support
From: ludovic.desroches at atmel.com @ 2012-10-10 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

From: Ludovic Desroches <ludovic.desroches@atmel.com>

Add dma support for Atmel TWI which is available on sam9x5 and later.

When using dma for reception, you have to read only n-2 bytes. The last
two bytes are read manually. Don't doing this should cause to send the
STOP command too late and then to get extra data in the receive
register.

Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
---
 drivers/i2c/busses/i2c-at91.c | 326 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 314 insertions(+), 12 deletions(-)

diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index aa59a25..33219f8 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -19,6 +19,8 @@
 
 #include <linux/clk.h>
 #include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
@@ -30,6 +32,8 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
+#include <mach/at_hdmac.h>
+
 #define TWI_CLK_HZ		100000			/* max 400 Kbits/s */
 #define AT91_I2C_TIMEOUT	msecs_to_jiffies(100)	/* transfer timeout */
 
@@ -65,9 +69,21 @@
 #define	AT91_TWI_THR		0x0034	/* Transmit Holding Register */
 
 struct at91_twi_pdata {
-	unsigned	clk_max_div;
-	unsigned	clk_offset;
-	bool		has_unre_flag;
+	unsigned		clk_max_div;
+	unsigned		clk_offset;
+	bool			has_unre_flag;
+	bool			has_dma_support;
+	struct at_dma_slave	dma_slave;
+};
+
+struct at91_twi_dma {
+	struct dma_chan			*chan_rx;
+	struct dma_chan			*chan_tx;
+	struct scatterlist		sg;
+	struct dma_async_tx_descriptor	*data_desc;
+	enum dma_data_direction		direction;
+	bool				buf_mapped;
+	bool				xfer_in_progress;
 };
 
 struct at91_twi_dev {
@@ -79,10 +95,13 @@ struct at91_twi_dev {
 	size_t			buf_len;
 	struct i2c_msg		*msg;
 	int			irq;
+	unsigned		imr;
 	unsigned		transfer_status;
 	struct i2c_adapter	adapter;
 	unsigned		twi_cwgr_reg;
 	struct at91_twi_pdata	*pdata;
+	bool			use_dma;
+	struct at91_twi_dma	dma;
 };
 
 static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
@@ -98,7 +117,18 @@ static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val)
 static void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
 {
 	at91_twi_write(dev, AT91_TWI_IDR,
-		       AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
+			AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
+}
+
+static void at91_twi_irq_save(struct at91_twi_dev *dev)
+{
+	dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7;
+	at91_disable_twi_interrupts(dev);
+}
+
+static void at91_twi_irq_restore(struct at91_twi_dev *dev)
+{
+	at91_twi_write(dev, AT91_TWI_IER, dev->imr);
 }
 
 static void at91_init_twi_bus(struct at91_twi_dev *dev)
@@ -137,6 +167,30 @@ static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
 	dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
 }
 
+static void at91_twi_dma_cleanup(struct at91_twi_dev *dev)
+{
+	struct at91_twi_dma *dma = &dev->dma;
+
+	at91_twi_irq_save(dev);
+
+	if (dma->xfer_in_progress) {
+		if (dma->direction == DMA_FROM_DEVICE)
+			dma->chan_rx->device->device_control(dma->chan_rx,
+				DMA_TERMINATE_ALL, 0);
+		else
+			dma->chan_tx->device->device_control(dma->chan_tx,
+				DMA_TERMINATE_ALL, 0);
+		dma->xfer_in_progress = false;
+	}
+	if (dma->buf_mapped) {
+		dma_unmap_single(dev->dev, sg_dma_address(&dma->sg),
+				 dev->buf_len, dma->direction);
+		dma->buf_mapped = false;
+	}
+
+	at91_twi_irq_restore(dev);
+}
+
 static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
 {
 	if (dev->buf_len <= 0)
@@ -153,6 +207,65 @@ static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
 	++dev->buf;
 }
 
+static void at91_twi_write_data_dma_callback(void *data)
+{
+	struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
+
+	dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
+			 dev->buf_len, DMA_TO_DEVICE);
+
+	at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
+}
+
+static void at91_twi_write_data_dma(struct at91_twi_dev *dev)
+{
+	dma_addr_t dma_addr;
+	dma_cookie_t cookie;
+	struct dma_async_tx_descriptor *txdesc;
+	struct at91_twi_dma *dma = &dev->dma;
+	struct dma_chan *chan_tx = dma->chan_tx;
+
+	if (dev->buf_len <= 0)
+		return;
+
+	dma->direction = DMA_TO_DEVICE;
+
+	at91_twi_irq_save(dev);
+	dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len,
+				  DMA_TO_DEVICE);
+	if (dma_mapping_error(dev->dev, dma_addr)) {
+		dev_err(dev->dev, "dma map failed\n");
+		return;
+	}
+	dma->buf_mapped = true;
+	at91_twi_irq_restore(dev);
+	sg_dma_len(&dma->sg) = dev->buf_len;
+	sg_dma_address(&dma->sg) = dma_addr;
+
+	txdesc = chan_tx->device->device_prep_slave_sg(chan_tx, &dma->sg,
+		1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, NULL);
+	if (!txdesc) {
+		dev_err(dev->dev, "dma prep slave sg failed\n");
+		goto error;
+	}
+
+	txdesc->callback = at91_twi_write_data_dma_callback;
+	txdesc->callback_param = dev;
+
+	dma->xfer_in_progress = true;
+	cookie = txdesc->tx_submit(txdesc);
+	if (dma_submit_error(cookie)) {
+		dev_err(dev->dev, "dma submit error\n");
+		goto error;
+	}
+	dma->chan_tx->device->device_issue_pending(chan_tx);
+
+	return;
+
+error:
+	at91_twi_dma_cleanup(dev);
+}
+
 static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
 {
 	if (dev->buf_len <= 0)
@@ -178,6 +291,66 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
 	++dev->buf;
 }
 
+static void at91_twi_read_data_dma_callback(void *data)
+{
+	struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
+
+	dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
+			 dev->buf_len, DMA_FROM_DEVICE);
+
+	/* The last two bytes have to be read without using dma */
+	dev->buf += dev->buf_len - 2;
+	dev->buf_len = 2;
+	at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY);
+}
+
+static void at91_twi_read_data_dma(struct at91_twi_dev *dev)
+{
+	dma_addr_t dma_addr;
+	dma_cookie_t cookie;
+	struct dma_async_tx_descriptor *rxdesc;
+	struct at91_twi_dma *dma = &dev->dma;
+	struct dma_chan *chan_rx = dma->chan_rx;
+
+	dma->direction = DMA_FROM_DEVICE;
+
+	/* Keep in mind that we won't use dma to read the last two bytes */
+	at91_twi_irq_save(dev);
+	dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len - 2,
+				  DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev->dev, dma_addr)) {
+		dev_err(dev->dev, "dma map failed\n");
+		return;
+	}
+	dma->buf_mapped = true;
+	at91_twi_irq_restore(dev);
+	dma->sg.dma_address = dma_addr;
+	sg_dma_len(&dma->sg) = dev->buf_len - 2;
+
+	rxdesc = chan_rx->device->device_prep_slave_sg(chan_rx, &dma->sg,
+		1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK, NULL);
+	if (!rxdesc) {
+		dev_err(dev->dev, "dma prep slave sg failed\n");
+		goto error;
+	}
+
+	rxdesc->callback = at91_twi_read_data_dma_callback;
+	rxdesc->callback_param = dev;
+
+	dma->xfer_in_progress = true;
+	cookie = rxdesc->tx_submit(rxdesc);
+	if (dma_submit_error(cookie)) {
+		dev_err(dev->dev, "dma submit error\n");
+		goto error;
+	}
+	dma->chan_rx->device->device_issue_pending(dma->chan_rx);
+
+	return;
+
+error:
+	at91_twi_dma_cleanup(dev);
+}
+
 static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
 {
 	struct at91_twi_dev *dev = dev_id;
@@ -224,12 +397,36 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 		if (dev->buf_len <= 1 && !(dev->msg->flags & I2C_M_RECV_LEN))
 			start_flags |= AT91_TWI_STOP;
 		at91_twi_write(dev, AT91_TWI_CR, start_flags);
-		at91_twi_write(dev, AT91_TWI_IER,
+		/*
+		 * When using dma, the last byte has to be read manually in
+		 * order to not send the stop command too late and then
+		 * to receive extra data. In practice, there are some issues
+		 * if you use the dma to read n-1 bytes because of latency.
+		 * Reading n-2 bytes with dma and the two last ones manually
+		 * seems to be the best solution.
+		 */
+		if (dev->use_dma && (dev->buf_len > 2)) {
+			at91_twi_read_data_dma(dev);
+			/*
+			 * It is important to enable TXCOMP irq here because
+			 * doing it only when transferring the last two bytes
+			 * will mask NACK errors since TXCOMP is set when a
+			 * NACK occurs.
+			 */
+			at91_twi_write(dev, AT91_TWI_IER,
+			       AT91_TWI_TXCOMP);
+		} else
+			at91_twi_write(dev, AT91_TWI_IER,
 			       AT91_TWI_TXCOMP | AT91_TWI_RXRDY);
 	} else {
-		at91_twi_write_next_byte(dev);
-		at91_twi_write(dev, AT91_TWI_IER,
-			       AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
+		if (dev->use_dma) {
+			at91_twi_write_data_dma(dev);
+			at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
+		} else {
+			at91_twi_write_next_byte(dev);
+			at91_twi_write(dev, AT91_TWI_IER,
+				AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
+		}
 	}
 
 	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
@@ -237,23 +434,31 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 	if (ret == 0) {
 		dev_err(dev->dev, "controller timed out\n");
 		at91_init_twi_bus(dev);
-		return -ETIMEDOUT;
+		ret = -ETIMEDOUT;
+		goto error;
 	}
 	if (dev->transfer_status & AT91_TWI_NACK) {
 		dev_dbg(dev->dev, "received nack\n");
-		return -EREMOTEIO;
+		ret = -EREMOTEIO;
+		goto error;
 	}
 	if (dev->transfer_status & AT91_TWI_OVRE) {
 		dev_err(dev->dev, "overrun while reading\n");
-		return -EIO;
+		ret = -EIO;
+		goto error;
 	}
 	if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) {
 		dev_err(dev->dev, "underrun while writing\n");
-		return -EIO;
+		ret = -EIO;
+		goto error;
 	}
 	dev_dbg(dev->dev, "transfer complete\n");
 
 	return 0;
+
+error:
+	at91_twi_dma_cleanup(dev);
+	return ret;
 }
 
 static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
@@ -324,36 +529,42 @@ static struct at91_twi_pdata at91rm9200_config = {
 	.clk_max_div = 5,
 	.clk_offset = 3,
 	.has_unre_flag = true,
+	.has_dma_support = false,
 };
 
 static struct at91_twi_pdata at91sam9261_config = {
 	.clk_max_div = 5,
 	.clk_offset = 4,
 	.has_unre_flag = false,
+	.has_dma_support = false,
 };
 
 static struct at91_twi_pdata at91sam9260_config = {
 	.clk_max_div = 7,
 	.clk_offset = 4,
 	.has_unre_flag = false,
+	.has_dma_support = false,
 };
 
 static struct at91_twi_pdata at91sam9g20_config = {
 	.clk_max_div = 7,
 	.clk_offset = 4,
 	.has_unre_flag = false,
+	.has_dma_support = false,
 };
 
 static struct at91_twi_pdata at91sam9g10_config = {
 	.clk_max_div = 7,
 	.clk_offset = 4,
 	.has_unre_flag = false,
+	.has_dma_support = false,
 };
 
 static struct at91_twi_pdata at91sam9x5_config = {
 	.clk_max_div = 7,
 	.clk_offset = 4,
 	.has_unre_flag = false,
+	.has_dma_support = true,
 };
 
 static const struct platform_device_id at91_twi_devtypes[] = {
@@ -400,6 +611,90 @@ MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
 #define atmel_twi_dt_ids NULL
 #endif
 
+static bool __devinit filter(struct dma_chan *chan, void *slave)
+{
+	struct at_dma_slave *sl = slave;
+
+	if (sl->dma_dev == chan->device->dev) {
+		chan->private = sl;
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static int __devinit at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
+{
+	int ret = 0;
+	struct at_dma_slave *sdata;
+	struct dma_slave_config slave_config;
+	struct at91_twi_dma *dma = &dev->dma;
+
+	sdata = &dev->pdata->dma_slave;
+
+	memset(&slave_config, 0, sizeof(slave_config));
+	slave_config.src_addr = (dma_addr_t)phy_addr + AT91_TWI_RHR;
+	slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	slave_config.src_maxburst = 1;
+	slave_config.dst_addr = (dma_addr_t)phy_addr + AT91_TWI_THR;
+	slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	slave_config.dst_maxburst = 1;
+	slave_config.device_fc = false;
+
+	if (sdata && sdata->dma_dev) {
+		dma_cap_mask_t mask;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+		dma->chan_tx = dma_request_channel(mask, filter, sdata);
+		if (!dma->chan_tx) {
+			dev_err(dev->dev, "no DMA channel available for tx\n");
+			ret = -EBUSY;
+			goto error;
+		}
+		dma->chan_rx = dma_request_channel(mask, filter, sdata);
+		if (!dma->chan_rx) {
+			dev_err(dev->dev, "no DMA channel available for rx\n");
+			ret = -EBUSY;
+			goto error;
+		}
+	} else {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	slave_config.direction = DMA_TO_DEVICE;
+	if (dmaengine_slave_config(dma->chan_tx, &slave_config)) {
+		dev_err(dev->dev, "failed to configure tx channel\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	slave_config.direction = DMA_FROM_DEVICE;
+	if (dmaengine_slave_config(dma->chan_rx, &slave_config)) {
+		dev_err(dev->dev, "failed to configure rx channel\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	sg_init_table(&dma->sg, 1);
+	dma->buf_mapped = false;
+	dma->xfer_in_progress = false;
+
+	dev_info(dev->dev, "using %s (tx) and %s (rx) for DMA transfers\n",
+		 dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
+
+	return ret;
+
+error:
+	dev_info(dev->dev, "can't use DMA\n");
+	if (dma->chan_rx)
+		dma_release_channel(dma->chan_rx);
+	if (dma->chan_tx)
+		dma_release_channel(dma->chan_tx);
+	return ret;
+}
+
 static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
 					struct platform_device *pdev)
 {
@@ -418,6 +713,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
 	struct at91_twi_dev *dev;
 	struct resource *mem;
 	int rc;
+	u32 phy_addr;
 
 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
 	if (!dev)
@@ -428,6 +724,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem)
 		return -ENODEV;
+	phy_addr = mem->start;
 
 	dev->pdata = at91_twi_get_driver_data(pdev);
 	if (!dev->pdata)
@@ -457,6 +754,11 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
 	}
 	clk_prepare_enable(dev->clk);
 
+	if (dev->pdata->has_dma_support) {
+		if (at91_twi_configure_dma(dev, phy_addr) == 0)
+			dev->use_dma = true;
+	}
+
 	at91_calc_twi_clock(dev, TWI_CLK_HZ);
 	at91_init_twi_bus(dev);
 
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH v2 3/5] ARM: use generic unaligned.h
From: Rob Herring @ 2012-10-10 13:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.02.1210082354210.16518@xanadu.home>

On 10/08/2012 11:01 PM, Nicolas Pitre wrote:
> On Mon, 8 Oct 2012, Rob Herring wrote:
> 
>> On 10/08/2012 06:28 PM, Shawn Guo wrote:
>>> On Mon, Oct 08, 2012 at 03:34:57PM -0500, Rob Herring wrote:
>>>> On 10/08/2012 11:43 AM, Shawn Guo wrote:
>>>>> This patch has been merged into mainline as commit below.
>>>>>
>>>>>  d25c881 ARM: 7493/1: use generic unaligned.h
>>>>>
>>>>> It introduces a regression for me.  Check out the commit on mainline,
>>>>> build a v7 only kernel (imx5/6) with imx_v6_v7_defconfig, the kernel
>>>>> halts in decompressor.  But v6/v7 kernel (imx3/5/6) works fine.  The
>>>>> kernel built on the parent commit below works all fine.
>>>>
>>>> It actually fails in the decompressor or that's the last output you get?
>>>
>>> I think it fails in the decompressor, because what I see is 
>>>
>>> Uncompressing Linux...
>>>
>>> not
>>>
>>> Uncompressing Linux... done, booting the kernel.
>>>
>>>> I compared the decompressor disassembly of both cases and get the same
>>>> number of ldrb/strb instructions, so I don't think it is directly
>>>> related to alignment.
>>>>
>>>> I tried the XY decompressor as that is one difference, but that works
>>>> fine for me on highbank.
>>>>
>>>> Does it work with an empty uncompress.h functions? That should be the
>>>> only difference in our decompressor code.
>>>
>>> No, empty putc() in uncompress.h does not help.
>>>
>>> New finding is that it only fails with LZO decompressor while the other
>>> 3 Gzip, LZMA and XZ all work good.  We happen to have LZO as the default
>>> one in imx_v6_v7_defconfig.
>>
>> I must have had an old config with XZ. LZO fails because of this:
>>  
>> lib/decompress_unlzo.c: version = get_unaligned_be16(parse);
>> lib/decompress_unlzo.c: if (get_unaligned_be32(parse) & HEADER_HAS_FILTER)
>> lib/decompress_unlzo.c:         dst_len = get_unaligned_be32(in_buf);
>> lib/decompress_unlzo.c:         src_len = get_unaligned_be32(in_buf);
>>
>> This was what I was afraid of. The decompressor runs with the sysctrl
>> register A bit in whatever state the bootloader left it in. In the case
>> of u-boot it is set, and the maintainers are pretty set on not allowing
>> unaligned accesses if you've seen the recent discussion.
> 
> This is not an u-Boot issue.  The kernel code expects misaligned 
> accesses to be handled by the hardware on ARMv6+ now.  So it better 
> enforce proper A bit state itself.
> 
>> This should fix things.
>>
>> Rob
>>
>> 8<---------------------------------------------------------------------
>>
>> diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
>> index bc67cbf..1f87d22 100644
>> --- a/arch/arm/boot/compressed/head.S
>> +++ b/arch/arm/boot/compressed/head.S
>> @@ -654,6 +654,7 @@ __armv7_mmu_cache_on:
>>  #endif
>>                 mrc     p15, 0, r0, c1, c0, 0   @ read control reg
>>                 bic     r0, r0, #1 << 28        @ clear SCTLR.TRE
>> +               bic     r0, r0, #1 << 1         @ clear SCTLR.A
>>                 orr     r0, r0, #0x5000         @ I-cache enable, RR cache replacement
>>                 orr     r0, r0, #0x003c         @ write buffer
>>  #ifdef CONFIG_MMU
>>
> 
> That's OK for ARMv7, but in the ARMv6 case we use __armv4_mmu_cache_on.  
> So this patch is incomplete.

It is still optional on v6 and the compiler will not emit unaligned
accesses for v6 (which is why it worked when v6 platforms were enabled).
That does raise a bigger question. If we're doing combined v6 and v7
builds, do we want this to require unaligned accesses are enabled and if
so, can we force that on in the compiler?

Rob

^ permalink raw reply

* [PATCH 02/13] clk: davinci - add PSC clock driver
From: Sekhar Nori @ 2012-10-10 12:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50756B96.1070008@ti.com>

On 10/10/2012 6:05 PM, Sekhar Nori wrote:

>> +struct clk *clk_register_davinci_psc(struct device *dev, const char *name,
>> +			const char *parent_name,
>> +			struct clk_davinci_psc_data *psc_data,
>> +			spinlock_t *lock)
> 
> Why do you need the lock to be provided from outside of this file? You
> can initialize a lock for serializing writes to PSC registers within
> this file, no?

Looking again, it seems like the common clock framework defines an
"enable_lock" in drivers/clk/clk.c to serialize the clock enable/disable
calls. Unless I am missing something, this lock seems unnecessary.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH 5/5] pinctrl/nomadik: merge old pincfg header
From: Linus Walleij @ 2012-10-10 12:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: Linus Walleij <linus.walleij@linaro.org>

This merges the old <plat/pincfg.h> header into
<linux/platform_data/pinctrl-nomadik.h> and rids us of
yet one more <plat/*> include.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-nomadik/board-nhk8815.c         |   1 -
 arch/arm/mach-nomadik/i2c-8815nhk.c           |   1 -
 arch/arm/mach-ux500/board-mop500-audio.c      |   1 -
 arch/arm/mach-ux500/board-mop500-pins.c       |   1 -
 arch/arm/plat-nomadik/include/plat/pincfg.h   | 173 --------------------------
 drivers/pinctrl/pinctrl-nomadik.c             |   4 +-
 include/linux/platform_data/pinctrl-nomadik.h | 158 +++++++++++++++++++++++
 7 files changed, 159 insertions(+), 180 deletions(-)
 delete mode 100644 arch/arm/plat-nomadik/include/plat/pincfg.h

diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index 3a41ad0..22ef8a1 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -34,7 +34,6 @@
 #include <asm/mach/time.h>
 
 #include <plat/mtu.h>
-#include <plat/pincfg.h>
 
 #include <linux/platform_data/mtd-nomadik-nand.h>
 #include <mach/fsmc.h>
diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c
index f81496f..0c2f662 100644
--- a/arch/arm/mach-nomadik/i2c-8815nhk.c
+++ b/arch/arm/mach-nomadik/i2c-8815nhk.c
@@ -5,7 +5,6 @@
 #include <linux/i2c-gpio.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/pinctrl-nomadik.h>
-#include <plat/pincfg.h>
 
 /*
  * There are two busses in the 8815NHK.
diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c
index ea828cc..33631c9 100644
--- a/arch/arm/mach-ux500/board-mop500-audio.c
+++ b/arch/arm/mach-ux500/board-mop500-audio.c
@@ -9,7 +9,6 @@
 #include <linux/gpio.h>
 #include <linux/platform_data/pinctrl-nomadik.h>
 
-#include <plat/pincfg.h>
 #include <plat/ste_dma40.h>
 
 #include <mach/devices.h>
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index 05f2bb5..c34d4ef 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -12,7 +12,6 @@
 #include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/mach-types.h>
-#include <plat/pincfg.h>
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h
deleted file mode 100644
index 3b8ec60..0000000
--- a/arch/arm/plat-nomadik/include/plat/pincfg.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License terms: GNU General Public License, version 2
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- *
- * Based on arch/arm/mach-pxa/include/mach/mfp.h:
- *   Copyright (C) 2007 Marvell International Ltd.
- *   eric miao <eric.miao@marvell.com>
- */
-
-#ifndef __PLAT_PINCFG_H
-#define __PLAT_PINCFG_H
-
-/*
- * pin configurations are represented by 32-bit integers:
- *
- *	bit  0.. 8 - Pin Number (512 Pins Maximum)
- *	bit  9..10 - Alternate Function Selection
- *	bit 11..12 - Pull up/down state
- *	bit     13 - Sleep mode behaviour
- *	bit     14 - Direction
- *	bit     15 - Value (if output)
- *	bit 16..18 - SLPM pull up/down state
- *	bit 19..20 - SLPM direction
- *	bit 21..22 - SLPM Value (if output)
- *	bit 23..25 - PDIS value (if input)
- *	bit	26 - Gpio mode
- *	bit	27 - Sleep mode
- *
- * to facilitate the definition, the following macros are provided
- *
- * PIN_CFG_DEFAULT - default config (0):
- *		     pull up/down = disabled
- *		     sleep mode = input/wakeup
- *		     direction = input
- *		     value = low
- *		     SLPM direction = same as normal
- *		     SLPM pull = same as normal
- *		     SLPM value = same as normal
- *
- * PIN_CFG	   - default config with alternate function
- */
-
-typedef unsigned long pin_cfg_t;
-
-#define PIN_NUM_MASK		0x1ff
-#define PIN_NUM(x)		((x) & PIN_NUM_MASK)
-
-#define PIN_ALT_SHIFT		9
-#define PIN_ALT_MASK		(0x3 << PIN_ALT_SHIFT)
-#define PIN_ALT(x)		(((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT)
-#define PIN_GPIO		(NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT)
-#define PIN_ALT_A		(NMK_GPIO_ALT_A << PIN_ALT_SHIFT)
-#define PIN_ALT_B		(NMK_GPIO_ALT_B << PIN_ALT_SHIFT)
-#define PIN_ALT_C		(NMK_GPIO_ALT_C << PIN_ALT_SHIFT)
-
-#define PIN_PULL_SHIFT		11
-#define PIN_PULL_MASK		(0x3 << PIN_PULL_SHIFT)
-#define PIN_PULL(x)		(((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT)
-#define PIN_PULL_NONE		(NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT)
-#define PIN_PULL_UP		(NMK_GPIO_PULL_UP << PIN_PULL_SHIFT)
-#define PIN_PULL_DOWN		(NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT)
-
-#define PIN_SLPM_SHIFT		13
-#define PIN_SLPM_MASK		(0x1 << PIN_SLPM_SHIFT)
-#define PIN_SLPM(x)		(((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
-#define PIN_SLPM_MAKE_INPUT	(NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
-#define PIN_SLPM_NOCHANGE	(NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
-/* These two replace the above in DB8500v2+ */
-#define PIN_SLPM_WAKEUP_ENABLE	(NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
-#define PIN_SLPM_WAKEUP_DISABLE	(NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
-#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE
-
-#define PIN_SLPM_GPIO  PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */
-#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */
-
-#define PIN_DIR_SHIFT		14
-#define PIN_DIR_MASK		(0x1 << PIN_DIR_SHIFT)
-#define PIN_DIR(x)		(((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
-#define PIN_DIR_INPUT		(0 << PIN_DIR_SHIFT)
-#define PIN_DIR_OUTPUT		(1 << PIN_DIR_SHIFT)
-
-#define PIN_VAL_SHIFT		15
-#define PIN_VAL_MASK		(0x1 << PIN_VAL_SHIFT)
-#define PIN_VAL(x)		(((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
-#define PIN_VAL_LOW		(0 << PIN_VAL_SHIFT)
-#define PIN_VAL_HIGH		(1 << PIN_VAL_SHIFT)
-
-#define PIN_SLPM_PULL_SHIFT	16
-#define PIN_SLPM_PULL_MASK	(0x7 << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL(x)	\
-	(((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_NONE	\
-	((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_UP	\
-	((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_DOWN	\
-	((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
-
-#define PIN_SLPM_DIR_SHIFT	19
-#define PIN_SLPM_DIR_MASK	(0x3 << PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR(x)		\
-	(((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR_INPUT	((1 + 0) << PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR_OUTPUT	((1 + 1) << PIN_SLPM_DIR_SHIFT)
-
-#define PIN_SLPM_VAL_SHIFT	21
-#define PIN_SLPM_VAL_MASK	(0x3 << PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL(x)		\
-	(((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL_LOW	((1 + 0) << PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL_HIGH	((1 + 1) << PIN_SLPM_VAL_SHIFT)
-
-#define PIN_SLPM_PDIS_SHIFT		23
-#define PIN_SLPM_PDIS_MASK		(0x3 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS(x)	\
-	(((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_NO_CHANGE		(0 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_DISABLED		(1 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_ENABLED		(2 << PIN_SLPM_PDIS_SHIFT)
-
-#define PIN_LOWEMI_SHIFT	25
-#define PIN_LOWEMI_MASK		(0x1 << PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI(x)		(((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI_DISABLED	(0 << PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI_ENABLED	(1 << PIN_LOWEMI_SHIFT)
-
-#define PIN_GPIOMODE_SHIFT	26
-#define PIN_GPIOMODE_MASK	(0x1 << PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE(x)		(((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE_DISABLED	(0 << PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE_ENABLED	(1 << PIN_GPIOMODE_SHIFT)
-
-#define PIN_SLEEPMODE_SHIFT	27
-#define PIN_SLEEPMODE_MASK	(0x1 << PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE(x)	(((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE_DISABLED	(0 << PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE_ENABLED	(1 << PIN_SLEEPMODE_SHIFT)
-
-
-/* Shortcuts.  Use these instead of separate DIR, PULL, and VAL.  */
-#define PIN_INPUT_PULLDOWN	(PIN_DIR_INPUT | PIN_PULL_DOWN)
-#define PIN_INPUT_PULLUP	(PIN_DIR_INPUT | PIN_PULL_UP)
-#define PIN_INPUT_NOPULL	(PIN_DIR_INPUT | PIN_PULL_NONE)
-#define PIN_OUTPUT_LOW		(PIN_DIR_OUTPUT | PIN_VAL_LOW)
-#define PIN_OUTPUT_HIGH		(PIN_DIR_OUTPUT | PIN_VAL_HIGH)
-
-#define PIN_SLPM_INPUT_PULLDOWN	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
-#define PIN_SLPM_INPUT_PULLUP	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
-#define PIN_SLPM_INPUT_NOPULL	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
-#define PIN_SLPM_OUTPUT_LOW	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
-#define PIN_SLPM_OUTPUT_HIGH	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
-
-#define PIN_CFG_DEFAULT		(0)
-
-#define PIN_CFG(num, alt)		\
-	(PIN_CFG_DEFAULT |\
-	 (PIN_NUM(num) | PIN_##alt))
-
-#define PIN_CFG_INPUT(num, alt, pull)		\
-	(PIN_CFG_DEFAULT |\
-	 (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
-
-#define PIN_CFG_OUTPUT(num, alt, val)		\
-	(PIN_CFG_DEFAULT |\
-	 (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
-
-extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
-extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
-extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
-
-#endif
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 63cdfc1..2bf6049 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -35,8 +35,6 @@
 
 #include <asm/mach/irq.h>
 
-#include <plat/pincfg.h>
-
 #include "pinctrl-nomadik.h"
 
 /*
@@ -521,7 +519,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
  * and its sleep mode based on the specified configuration.  The @cfg is
  * usually one of the SoC specific macros defined in mach/<soc>-pins.h.  These
  * are constructed using, and can be further enhanced with, the macros in
- * plat/pincfg.h.
+ * <linux/platform_data/pinctrl-nomadik.h>
  *
  * If a pin's mode is set to GPIO, it is configured as an input to avoid
  * side-effects.  The gpio can be manipulated later using standard GPIO API
diff --git a/include/linux/platform_data/pinctrl-nomadik.h b/include/linux/platform_data/pinctrl-nomadik.h
index a749994..f73b2f0 100644
--- a/include/linux/platform_data/pinctrl-nomadik.h
+++ b/include/linux/platform_data/pinctrl-nomadik.h
@@ -14,6 +14,160 @@
 #define __PLAT_NOMADIK_GPIO
 
 /*
+ * pin configurations are represented by 32-bit integers:
+ *
+ *	bit  0.. 8 - Pin Number (512 Pins Maximum)
+ *	bit  9..10 - Alternate Function Selection
+ *	bit 11..12 - Pull up/down state
+ *	bit     13 - Sleep mode behaviour
+ *	bit     14 - Direction
+ *	bit     15 - Value (if output)
+ *	bit 16..18 - SLPM pull up/down state
+ *	bit 19..20 - SLPM direction
+ *	bit 21..22 - SLPM Value (if output)
+ *	bit 23..25 - PDIS value (if input)
+ *	bit	26 - Gpio mode
+ *	bit	27 - Sleep mode
+ *
+ * to facilitate the definition, the following macros are provided
+ *
+ * PIN_CFG_DEFAULT - default config (0):
+ *		     pull up/down = disabled
+ *		     sleep mode = input/wakeup
+ *		     direction = input
+ *		     value = low
+ *		     SLPM direction = same as normal
+ *		     SLPM pull = same as normal
+ *		     SLPM value = same as normal
+ *
+ * PIN_CFG	   - default config with alternate function
+ */
+
+typedef unsigned long pin_cfg_t;
+
+#define PIN_NUM_MASK		0x1ff
+#define PIN_NUM(x)		((x) & PIN_NUM_MASK)
+
+#define PIN_ALT_SHIFT		9
+#define PIN_ALT_MASK		(0x3 << PIN_ALT_SHIFT)
+#define PIN_ALT(x)		(((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT)
+#define PIN_GPIO		(NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT)
+#define PIN_ALT_A		(NMK_GPIO_ALT_A << PIN_ALT_SHIFT)
+#define PIN_ALT_B		(NMK_GPIO_ALT_B << PIN_ALT_SHIFT)
+#define PIN_ALT_C		(NMK_GPIO_ALT_C << PIN_ALT_SHIFT)
+
+#define PIN_PULL_SHIFT		11
+#define PIN_PULL_MASK		(0x3 << PIN_PULL_SHIFT)
+#define PIN_PULL(x)		(((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT)
+#define PIN_PULL_NONE		(NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT)
+#define PIN_PULL_UP		(NMK_GPIO_PULL_UP << PIN_PULL_SHIFT)
+#define PIN_PULL_DOWN		(NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT)
+
+#define PIN_SLPM_SHIFT		13
+#define PIN_SLPM_MASK		(0x1 << PIN_SLPM_SHIFT)
+#define PIN_SLPM(x)		(((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
+#define PIN_SLPM_MAKE_INPUT	(NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
+#define PIN_SLPM_NOCHANGE	(NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
+/* These two replace the above in DB8500v2+ */
+#define PIN_SLPM_WAKEUP_ENABLE	(NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_WAKEUP_DISABLE	(NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE
+
+#define PIN_SLPM_GPIO  PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */
+#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */
+
+#define PIN_DIR_SHIFT		14
+#define PIN_DIR_MASK		(0x1 << PIN_DIR_SHIFT)
+#define PIN_DIR(x)		(((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
+#define PIN_DIR_INPUT		(0 << PIN_DIR_SHIFT)
+#define PIN_DIR_OUTPUT		(1 << PIN_DIR_SHIFT)
+
+#define PIN_VAL_SHIFT		15
+#define PIN_VAL_MASK		(0x1 << PIN_VAL_SHIFT)
+#define PIN_VAL(x)		(((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
+#define PIN_VAL_LOW		(0 << PIN_VAL_SHIFT)
+#define PIN_VAL_HIGH		(1 << PIN_VAL_SHIFT)
+
+#define PIN_SLPM_PULL_SHIFT	16
+#define PIN_SLPM_PULL_MASK	(0x7 << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL(x)	\
+	(((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_NONE	\
+	((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_UP	\
+	((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_DOWN	\
+	((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
+
+#define PIN_SLPM_DIR_SHIFT	19
+#define PIN_SLPM_DIR_MASK	(0x3 << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR(x)		\
+	(((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_INPUT	((1 + 0) << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_OUTPUT	((1 + 1) << PIN_SLPM_DIR_SHIFT)
+
+#define PIN_SLPM_VAL_SHIFT	21
+#define PIN_SLPM_VAL_MASK	(0x3 << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL(x)		\
+	(((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_LOW	((1 + 0) << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_HIGH	((1 + 1) << PIN_SLPM_VAL_SHIFT)
+
+#define PIN_SLPM_PDIS_SHIFT		23
+#define PIN_SLPM_PDIS_MASK		(0x3 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS(x)	\
+	(((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_NO_CHANGE		(0 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_DISABLED		(1 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_ENABLED		(2 << PIN_SLPM_PDIS_SHIFT)
+
+#define PIN_LOWEMI_SHIFT	25
+#define PIN_LOWEMI_MASK		(0x1 << PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI(x)		(((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI_DISABLED	(0 << PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI_ENABLED	(1 << PIN_LOWEMI_SHIFT)
+
+#define PIN_GPIOMODE_SHIFT	26
+#define PIN_GPIOMODE_MASK	(0x1 << PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE(x)		(((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE_DISABLED	(0 << PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE_ENABLED	(1 << PIN_GPIOMODE_SHIFT)
+
+#define PIN_SLEEPMODE_SHIFT	27
+#define PIN_SLEEPMODE_MASK	(0x1 << PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE(x)	(((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE_DISABLED	(0 << PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE_ENABLED	(1 << PIN_SLEEPMODE_SHIFT)
+
+
+/* Shortcuts.  Use these instead of separate DIR, PULL, and VAL.  */
+#define PIN_INPUT_PULLDOWN	(PIN_DIR_INPUT | PIN_PULL_DOWN)
+#define PIN_INPUT_PULLUP	(PIN_DIR_INPUT | PIN_PULL_UP)
+#define PIN_INPUT_NOPULL	(PIN_DIR_INPUT | PIN_PULL_NONE)
+#define PIN_OUTPUT_LOW		(PIN_DIR_OUTPUT | PIN_VAL_LOW)
+#define PIN_OUTPUT_HIGH		(PIN_DIR_OUTPUT | PIN_VAL_HIGH)
+
+#define PIN_SLPM_INPUT_PULLDOWN	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
+#define PIN_SLPM_INPUT_PULLUP	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
+#define PIN_SLPM_INPUT_NOPULL	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
+#define PIN_SLPM_OUTPUT_LOW	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
+#define PIN_SLPM_OUTPUT_HIGH	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
+
+#define PIN_CFG_DEFAULT		(0)
+
+#define PIN_CFG(num, alt)		\
+	(PIN_CFG_DEFAULT |\
+	 (PIN_NUM(num) | PIN_##alt))
+
+#define PIN_CFG_INPUT(num, alt, pull)		\
+	(PIN_CFG_DEFAULT |\
+	 (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
+
+#define PIN_CFG_OUTPUT(num, alt, val)		\
+	(PIN_CFG_DEFAULT |\
+	 (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
+
+/*
  * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
  * the "gpio" namespace for generic and cross-machine functions
  */
@@ -72,6 +226,10 @@ enum nmk_gpio_slpm {
 	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
 };
 
+/* Older deprecated pin config API that should go away soon */
+extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
+extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
+extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
 extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
 extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
 #ifdef CONFIG_PINCTRL_NOMADIK
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH 4/5] pinctrl/nomadik: move the platform data header
From: Linus Walleij @ 2012-10-10 12:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: Linus Walleij <linus.walleij@linaro.org>

This moves the platform data header for the Nomadik pin controller
to <linux/platform_data/pinctrl-nomadik.h>.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-nomadik/board-nhk8815.c             |   2 +-
 arch/arm/mach-nomadik/cpu-8815.c                  |   2 +-
 arch/arm/mach-nomadik/i2c-8815nhk.c               |   2 +-
 arch/arm/mach-ux500/board-mop500-audio.c          |   2 +-
 arch/arm/mach-ux500/board-mop500-pins.c           |   2 +-
 arch/arm/mach-ux500/board-mop500.c                |   2 +-
 arch/arm/mach-ux500/cpu-db8500.c                  |   4 +-
 arch/arm/mach-ux500/devices-common.c              |   3 +-
 arch/arm/plat-nomadik/include/plat/gpio-nomadik.h | 108 ----------------------
 drivers/pinctrl/pinctrl-nomadik.c                 |   2 +-
 drivers/pinctrl/pinctrl-nomadik.h                 |   2 +-
 include/linux/platform_data/pinctrl-nomadik.h     | 108 ++++++++++++++++++++++
 12 files changed, 119 insertions(+), 120 deletions(-)
 delete mode 100644 arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
 create mode 100644 include/linux/platform_data/pinctrl-nomadik.h

diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index bfa1eab..3a41ad0 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -24,6 +24,7 @@
 #include <linux/i2c.h>
 #include <linux/io.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 #include <asm/hardware/vic.h>
 #include <asm/sizes.h>
 #include <asm/mach-types.h>
@@ -32,7 +33,6 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
 
-#include <plat/gpio-nomadik.h>
 #include <plat/mtu.h>
 #include <plat/pincfg.h>
 
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c
index b617eae..1273931 100644
--- a/arch/arm/mach-nomadik/cpu-8815.c
+++ b/arch/arm/mach-nomadik/cpu-8815.c
@@ -26,8 +26,8 @@
 #include <linux/irq.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/clk-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
-#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach/map.h>
diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c
index 6d14454..f81496f 100644
--- a/arch/arm/mach-nomadik/i2c-8815nhk.c
+++ b/arch/arm/mach-nomadik/i2c-8815nhk.c
@@ -4,7 +4,7 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c-gpio.h>
 #include <linux/platform_device.h>
-#include <plat/gpio-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 #include <plat/pincfg.h>
 
 /*
diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c
index 070629a..ea828cc 100644
--- a/arch/arm/mach-ux500/board-mop500-audio.c
+++ b/arch/arm/mach-ux500/board-mop500-audio.c
@@ -7,8 +7,8 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
-#include <plat/gpio-nomadik.h>
 #include <plat/pincfg.h>
 #include <plat/ste_dma40.h>
 
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index a267c6d..05f2bb5 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -9,10 +9,10 @@
 #include <linux/bug.h>
 #include <linux/string.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/mach-types.h>
 #include <plat/pincfg.h>
-#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 416d436..0a3dd60 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -37,13 +37,13 @@
 #include <linux/of_platform.h>
 #include <linux/leds.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 
 #include <plat/ste_dma40.h>
-#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index bcdfe6b..87a8f9f 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -17,14 +17,14 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mfd/abx500/ab8500.h>
+#include <linux/platform_data/usb-musb-ux500.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/pmu.h>
 #include <asm/mach/map.h>
-#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
-#include <linux/platform_data/usb-musb-ux500.h>
 #include <mach/db8500-regs.h>
 
 #include "devices-db8500.h"
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
index dfdd4a5..692a77a 100644
--- a/arch/arm/mach-ux500/devices-common.c
+++ b/arch/arm/mach-ux500/devices-common.c
@@ -11,8 +11,7 @@
 #include <linux/irq.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
-
-#include <plat/gpio-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
deleted file mode 100644
index a749994..0000000
--- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Structures and registers for GPIO access in the Nomadik SoC
- *
- * Copyright (C) 2008 STMicroelectronics
- *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
- * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __PLAT_NOMADIK_GPIO
-#define __PLAT_NOMADIK_GPIO
-
-/*
- * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
- * the "gpio" namespace for generic and cross-machine functions
- */
-
-#define GPIO_BLOCK_SHIFT 5
-#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
-
-/* Register in the logic block */
-#define NMK_GPIO_DAT	0x00
-#define NMK_GPIO_DATS	0x04
-#define NMK_GPIO_DATC	0x08
-#define NMK_GPIO_PDIS	0x0c
-#define NMK_GPIO_DIR	0x10
-#define NMK_GPIO_DIRS	0x14
-#define NMK_GPIO_DIRC	0x18
-#define NMK_GPIO_SLPC	0x1c
-#define NMK_GPIO_AFSLA	0x20
-#define NMK_GPIO_AFSLB	0x24
-#define NMK_GPIO_LOWEMI	0x28
-
-#define NMK_GPIO_RIMSC	0x40
-#define NMK_GPIO_FIMSC	0x44
-#define NMK_GPIO_IS	0x48
-#define NMK_GPIO_IC	0x4c
-#define NMK_GPIO_RWIMSC	0x50
-#define NMK_GPIO_FWIMSC	0x54
-#define NMK_GPIO_WKS	0x58
-/* These appear in DB8540 and later ASICs */
-#define NMK_GPIO_EDGELEVEL 0x5C
-#define NMK_GPIO_LEVEL	0x60
-
-/* Alternate functions: function C is set in hw by setting both A and B */
-#define NMK_GPIO_ALT_GPIO	0
-#define NMK_GPIO_ALT_A	1
-#define NMK_GPIO_ALT_B	2
-#define NMK_GPIO_ALT_C	(NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
-
-#define NMK_GPIO_ALT_CX_SHIFT 2
-#define NMK_GPIO_ALT_C1	((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C2	((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C3	((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C4	((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-
-/* Pull up/down values */
-enum nmk_gpio_pull {
-	NMK_GPIO_PULL_NONE,
-	NMK_GPIO_PULL_UP,
-	NMK_GPIO_PULL_DOWN,
-};
-
-/* Sleep mode */
-enum nmk_gpio_slpm {
-	NMK_GPIO_SLPM_INPUT,
-	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
-	NMK_GPIO_SLPM_NOCHANGE,
-	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
-};
-
-extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
-extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
-#ifdef CONFIG_PINCTRL_NOMADIK
-extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
-#else
-static inline int nmk_gpio_set_mode(int gpio, int gpio_mode)
-{
-	return -ENODEV;
-}
-#endif
-extern int nmk_gpio_get_mode(int gpio);
-
-extern void nmk_gpio_wakeups_suspend(void);
-extern void nmk_gpio_wakeups_resume(void);
-
-extern void nmk_gpio_clocks_enable(void);
-extern void nmk_gpio_clocks_disable(void);
-
-extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
-
-/*
- * Platform data to register a block: only the initial gpio/irq number.
- */
-struct nmk_gpio_platform_data {
-	char *name;
-	int first_gpio;
-	int first_irq;
-	int num_gpio;
-	u32 (*get_secondary_status)(unsigned int bank);
-	void (*set_ioforce)(bool enable);
-	bool supports_sleepmode;
-};
-
-#endif /* __PLAT_NOMADIK_GPIO */
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index e4d3778..63cdfc1 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -31,11 +31,11 @@
 /* Since we request GPIOs from ourself */
 #include <linux/pinctrl/consumer.h>
 #include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/mach/irq.h>
 
 #include <plat/pincfg.h>
-#include <plat/gpio-nomadik.h>
 
 #include "pinctrl-nomadik.h"
 
diff --git a/drivers/pinctrl/pinctrl-nomadik.h b/drivers/pinctrl/pinctrl-nomadik.h
index eef316e..bcd4191 100644
--- a/drivers/pinctrl/pinctrl-nomadik.h
+++ b/drivers/pinctrl/pinctrl-nomadik.h
@@ -1,7 +1,7 @@
 #ifndef PINCTRL_PINCTRL_NOMADIK_H
 #define PINCTRL_PINCTRL_NOMADIK_H
 
-#include <plat/gpio-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 /* Package definitions */
 #define PINCTRL_NMK_STN8815	0
diff --git a/include/linux/platform_data/pinctrl-nomadik.h b/include/linux/platform_data/pinctrl-nomadik.h
new file mode 100644
index 0000000..a749994
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-nomadik.h
@@ -0,0 +1,108 @@
+/*
+ * Structures and registers for GPIO access in the Nomadik SoC
+ *
+ * Copyright (C) 2008 STMicroelectronics
+ *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_NOMADIK_GPIO
+#define __PLAT_NOMADIK_GPIO
+
+/*
+ * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
+ * the "gpio" namespace for generic and cross-machine functions
+ */
+
+#define GPIO_BLOCK_SHIFT 5
+#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
+
+/* Register in the logic block */
+#define NMK_GPIO_DAT	0x00
+#define NMK_GPIO_DATS	0x04
+#define NMK_GPIO_DATC	0x08
+#define NMK_GPIO_PDIS	0x0c
+#define NMK_GPIO_DIR	0x10
+#define NMK_GPIO_DIRS	0x14
+#define NMK_GPIO_DIRC	0x18
+#define NMK_GPIO_SLPC	0x1c
+#define NMK_GPIO_AFSLA	0x20
+#define NMK_GPIO_AFSLB	0x24
+#define NMK_GPIO_LOWEMI	0x28
+
+#define NMK_GPIO_RIMSC	0x40
+#define NMK_GPIO_FIMSC	0x44
+#define NMK_GPIO_IS	0x48
+#define NMK_GPIO_IC	0x4c
+#define NMK_GPIO_RWIMSC	0x50
+#define NMK_GPIO_FWIMSC	0x54
+#define NMK_GPIO_WKS	0x58
+/* These appear in DB8540 and later ASICs */
+#define NMK_GPIO_EDGELEVEL 0x5C
+#define NMK_GPIO_LEVEL	0x60
+
+/* Alternate functions: function C is set in hw by setting both A and B */
+#define NMK_GPIO_ALT_GPIO	0
+#define NMK_GPIO_ALT_A	1
+#define NMK_GPIO_ALT_B	2
+#define NMK_GPIO_ALT_C	(NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
+
+#define NMK_GPIO_ALT_CX_SHIFT 2
+#define NMK_GPIO_ALT_C1	((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C2	((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C3	((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C4	((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+
+/* Pull up/down values */
+enum nmk_gpio_pull {
+	NMK_GPIO_PULL_NONE,
+	NMK_GPIO_PULL_UP,
+	NMK_GPIO_PULL_DOWN,
+};
+
+/* Sleep mode */
+enum nmk_gpio_slpm {
+	NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_NOCHANGE,
+	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
+};
+
+extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
+extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
+#ifdef CONFIG_PINCTRL_NOMADIK
+extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
+#else
+static inline int nmk_gpio_set_mode(int gpio, int gpio_mode)
+{
+	return -ENODEV;
+}
+#endif
+extern int nmk_gpio_get_mode(int gpio);
+
+extern void nmk_gpio_wakeups_suspend(void);
+extern void nmk_gpio_wakeups_resume(void);
+
+extern void nmk_gpio_clocks_enable(void);
+extern void nmk_gpio_clocks_disable(void);
+
+extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
+
+/*
+ * Platform data to register a block: only the initial gpio/irq number.
+ */
+struct nmk_gpio_platform_data {
+	char *name;
+	int first_gpio;
+	int first_irq;
+	int num_gpio;
+	u32 (*get_secondary_status)(unsigned int bank);
+	void (*set_ioforce)(bool enable);
+	bool supports_sleepmode;
+};
+
+#endif /* __PLAT_NOMADIK_GPIO */
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH 3/5] pinctrl/nomadik: allow to support several ranges per GPIO bank
From: Linus Walleij @ 2012-10-10 12:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: Patrice Chotard <patrice.chotard@stericsson.com>

With DB8500 the number of GPIO chips = number GPIO bank =
number of GPIO ranges.

With DB8540, a new GPIO range configuration is used, some GPIO
banks can have several GPIO ranges.

For example, DB8540 GPIO bank0 (GPIO0 to GPIO32) have 2 GPIO
ranges:
    - GPIO0 to GPIO17  : routed
    - GPIO18 to GPIO21 : hole
    - GPIO22 to GPIO28 : routed
    - GPIO29 to GPIO32 : hole

Previously, during nmk_pinctrl_probe(), all GPIO ranges were
parsed, as GPIO ranges are larger than the number of GPIO chips,
a warning occurs. This commit allows each bank to have several
GPIO ranges.

Signed-off-by: Patrice Chotard <patrice.chotard@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/pinctrl/pinctrl-nomadik.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 334cd2f..e4d3778 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -1837,11 +1837,11 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
 	 * need this to proceed.
 	 */
 	for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
-		if (!nmk_gpio_chips[i]) {
+		if (!nmk_gpio_chips[npct->soc->gpio_ranges[i].id]) {
 			dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
 			return -EPROBE_DEFER;
 		}
-		npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[i]->chip;
+		npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[npct->soc->gpio_ranges[i].id]->chip;
 	}
 
 	nmk_pinctrl_desc.pins = npct->soc->pins;
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH 2/5] ARM: plat-nomadik: move NMK_GPIO_PER_CHIP into gpio-nomadik.h
From: Linus Walleij @ 2012-10-10 12:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: Patrice Chotard <patrice.chotard@stericsson.com>

Move NMK_GPIO_PER_CHIP to gpio-nomadik.h and define it with a
shift operator.

Signed-off-by: Patrice Chotard <patrice.chotard@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/plat-nomadik/include/plat/gpio-nomadik.h | 3 +++
 drivers/pinctrl/pinctrl-nomadik.c                 | 2 --
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
index cf81111..a749994 100644
--- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
+++ b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
@@ -18,6 +18,9 @@
  * the "gpio" namespace for generic and cross-machine functions
  */
 
+#define GPIO_BLOCK_SHIFT 5
+#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
+
 /* Register in the logic block */
 #define NMK_GPIO_DAT	0x00
 #define NMK_GPIO_DATS	0x04
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index fec9c30..334cd2f 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -47,8 +47,6 @@
  * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
  */
 
-#define NMK_GPIO_PER_CHIP	32
-
 struct nmk_gpio_chip {
 	struct gpio_chip chip;
 	struct irq_domain *domain;
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH 1/5] ARM: plat-nomadik: Introduce new DB8540 GPIO registers
From: Linus Walleij @ 2012-10-10 12:37 UTC (permalink / raw)
  To: linux-arm-kernel

From: Maxime Coquelin <maxime.coquelin@stericsson.com>

DB8540's GPIO controller introduce level detection
support for both interrupts and wakeups.

Signed-off-by: Maxime Coquelin <maxime.coquelin@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/plat-nomadik/include/plat/gpio-nomadik.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
index c08a54d..cf81111 100644
--- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
+++ b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
@@ -38,6 +38,9 @@
 #define NMK_GPIO_RWIMSC	0x50
 #define NMK_GPIO_FWIMSC	0x54
 #define NMK_GPIO_WKS	0x58
+/* These appear in DB8540 and later ASICs */
+#define NMK_GPIO_EDGELEVEL 0x5C
+#define NMK_GPIO_LEVEL	0x60
 
 /* Alternate functions: function C is set in hw by setting both A and B */
 #define NMK_GPIO_ALT_GPIO	0
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH v2 7/8] video: mark nuc900fb_map_video_memory as __devinit
From: Florian Tobias Schandinat @ 2012-10-10 12:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349813638-4617-8-git-send-email-arnd@arndb.de>

On 10/09/2012 08:13 PM, Arnd Bergmann wrote:
> nuc900fb_map_video_memory is called by an devinit function
> that may be called at run-time, but the function itself is
> marked __init and will be discarded after boot.
> 
> To avoid calling into a function that may have been overwritten,
> mark nuc900fb_map_video_memory itself as __devinit.
> 
> Without this patch, building nuc950_defconfig results in:
> 
> WARNING: drivers/video/built-in.o(.devinit.text+0x26c): Section mismatch in reference from the function nuc900fb_probe() to the function .init.text:nuc900fb_map_video_memory()
> The function __devinit nuc900fb_probe() references
> a function __init nuc900fb_map_video_memory().
> If nuc900fb_map_video_memory is only used by nuc900fb_probe then
> annotate nuc900fb_map_video_memory with a matching annotation.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Cc: Wan ZongShun <mcuos.com@gmail.com>
> Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
> Cc: linux-fbdev at vger.kernel.org

Applied.


Thanks,

Florian Tobias Schandinat

> ---
>  drivers/video/nuc900fb.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
> index e10f551..b31b12b 100644
> --- a/drivers/video/nuc900fb.c
> +++ b/drivers/video/nuc900fb.c
> @@ -387,7 +387,7 @@ static int nuc900fb_init_registers(struct fb_info *info)
>   *    The buffer should be a non-cached, non-buffered, memory region
>   *    to allow palette and pixel writes without flushing the cache.
>   */
> -static int __init nuc900fb_map_video_memory(struct fb_info *info)
> +static int __devinit nuc900fb_map_video_memory(struct fb_info *info)
>  {
>  	struct nuc900fb_info *fbi = info->par;
>  	dma_addr_t map_dma;

^ permalink raw reply

* [PATCH v2] USB: usb-skeleton.c: fix compilation error and restore kref_put on fail in skel_open
From: Oliver Neukum @ 2012-10-10 12:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349865174-21649-1-git-send-email-const@MakeLinux.com>

On Wednesday 10 October 2012 12:32:54 Constantine Shulyupin wrote:
> From: Constantine Shulyupin <const@MakeLinux.com>
> 
> Function skel_open increments usage count for the device with kref_get and the usage count should be decremented on the function failure.
> 
> Some last changes in function skel_open and finally commit
> 52a7499 Revert "USB: usb-skeleton.c: fix open/disconnect race"
> introduced a bug in function skel_open, which this patch fixes.
> 
> --
> Changelog:
> -- Fixed accordinly feedback of Oliver Neukum oneukum at suse.de: also need to drop the lock.

Well, touching file->private_data is not nice. It is correct, but
really dirty. The skeleton driver should be nice. Could you introduce
a second label for goto at the right place?

	Regards
		Oliver

^ permalink raw reply

* [PATCH 02/13] clk: davinci - add PSC clock driver
From: Sekhar Nori @ 2012-10-10 12:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1348682889-9509-3-git-send-email-m-karicheri2@ti.com>

On 9/26/2012 11:37 PM, Murali Karicheri wrote:
> This is the driver for the Power Sleep Controller (PSC) hardware
> found on DM SoCs as well Keystone SoCs (c6x). This driver borrowed
> code from arch/arm/mach-davinci/psc.c and implemented the driver
> as per common clock provider API. The PSC module is responsible for
> enabling/disabling the Power Domain and Clock domain for different IPs
> present in the SoC. The driver is configured through the platform
> data structure struct clk_davinci_psc_data.
> 
> Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
> 
> diff --git a/drivers/clk/davinci/clk-davinci-psc.c b/drivers/clk/davinci/clk-davinci-psc.c
> new file mode 100644
> index 0000000..b7aa332
> --- /dev/null
> +++ b/drivers/clk/davinci/clk-davinci-psc.c
> @@ -0,0 +1,197 @@
> +/*
> + * PSC clk driver for DaVinci devices
> + *
> + * Copyright (C) 2006-2012 Texas Instruments.
> + * Copyright (C) 2008-2009 Deep Root Systems, LLC
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/platform_data/clk-davinci-psc.h>

Sort these alphabetically.

> +
> +/* PSC register offsets */
> +#define EPCPR		0x070
> +#define PTCMD		0x120
> +#define PTSTAT		0x128
> +#define PDSTAT		0x200
> +#define PDCTL		0x300
> +#define MDSTAT		0x800
> +#define MDCTL		0xA00
> +
> +/* PSC module states */
> +#define PSC_STATE_SWRSTDISABLE	0
> +#define PSC_STATE_SYNCRST	1
> +#define PSC_STATE_DISABLE	2
> +#define PSC_STATE_ENABLE	3
> +
> +#define MDSTAT_STATE_MASK	0x3f
> +#define PDSTAT_STATE_MASK	0x1f
> +#define MDCTL_FORCE		BIT(31)
> +#define PDCTL_NEXT		BIT(0)
> +#define PDCTL_EPCGOOD		BIT(8)
> +
> +/* PSC flags */
> +#define PSC_SWRSTDISABLE	BIT(0) /* Disable state is SwRstDisable */
> +#define PSC_FORCE		BIT(1) /* Force module state transtition */
> +#define PSC_HAS_EXT_POWER_CNTL	BIT(2) /* PSC has external power control
> +					* available (for DM6446 SoC) */

Can you try and keep the comment above on a single line?

> +/**
> + * struct clk_psc - DaVinci PSC clock
> + * @hw: clk_hw for the psc
> + * @psc_data: PSC driver specific data
> + * @lock: Spinlock used by the driver
> + */
> +struct clk_psc {
> +	struct clk_hw hw;
> +	struct clk_davinci_psc_data *psc_data;
> +	spinlock_t *lock;
> +};
> +
> +#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw)
> +
> +/* Enable or disable a PSC domain */
> +static void clk_psc_config(void __iomem *base, unsigned int domain,
> +		unsigned int id, bool enable, u32 flags)
> +{
> +	u32 epcpr, ptcmd, ptstat, pdstat, pdctl, mdstat, mdctl;
> +	u32 next_state = PSC_STATE_ENABLE;
> +	void __iomem *psc_base = base;
> +
> +	if (!enable) {
> +		if (flags & PSC_SWRSTDISABLE)
> +			next_state = PSC_STATE_SWRSTDISABLE;
> +		else
> +			next_state = PSC_STATE_DISABLE;
> +	}
> +
> +	mdctl = __raw_readl(psc_base + MDCTL + 4 * id);

Please convert all __raw_ variants to simple readl/writel() calls.

> +	mdctl &= ~MDSTAT_STATE_MASK;
> +	mdctl |= next_state;
> +	if (flags & PSC_FORCE)
> +		mdctl |= MDCTL_FORCE;
> +	__raw_writel(mdctl, psc_base + MDCTL + 4 * id);
> +
> +	pdstat = __raw_readl(psc_base + PDSTAT + 4 * domain);
> +	if ((pdstat & PDSTAT_STATE_MASK) == 0) {
> +		pdctl = __raw_readl(psc_base + PDCTL + 4 * domain);
> +		pdctl |= PDCTL_NEXT;
> +		__raw_writel(pdctl, psc_base + PDCTL + 4 * domain);
> +
> +		ptcmd = 1 << domain;
> +		__raw_writel(ptcmd, psc_base + PTCMD);
> +
> +		if (flags & PSC_HAS_EXT_POWER_CNTL) {
> +			do {
> +				epcpr = __raw_readl(psc_base + EPCPR);
> +			} while ((((epcpr >> domain) & 1) == 0));
> +		}
> +
> +		pdctl = __raw_readl(psc_base + PDCTL + 4 * domain);
> +		pdctl |= 0x100;
> +		__raw_writel(pdctl, psc_base + PDCTL + 4 * domain);
> +
> +		pdctl = __raw_readl(psc_base + PDCTL + 4 * domain);
> +		pdctl |= PDCTL_EPCGOOD;
> +		__raw_writel(pdctl, psc_base + PDCTL + 4 * domain);
> +	} else {
> +		ptcmd = 1 << domain;
> +		__raw_writel(ptcmd, psc_base + PTCMD);
> +	}
> +
> +	do {
> +		ptstat = __raw_readl(psc_base + PTSTAT);
> +	} while (!(((ptstat >> domain) & 1) == 0));
> +
> +	do {
> +		mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
> +	} while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
> +}
> +
> +static int clk_psc_is_enabled(struct clk_hw *hw)
> +{
> +	struct clk_psc *psc = to_clk_psc(hw);
> +	struct clk_davinci_psc_data *psc_data = psc->psc_data;
> +	u32 mdstat;
> +
> +	mdstat = __raw_readl(psc_data->base + MDSTAT + 4 * psc_data->lpsc);
> +	/* if clocked, state can be "Enable" or "SyncReset" */
> +	return (mdstat & BIT(12)) ? 1 : 0;

Can you include a blank line before the return. Also, since the API
seems to expect a 0 or 1, you can simply do:

	return !!(mdstat & BIT(12);

> +}
> +
> +static int clk_psc_enable(struct clk_hw *hw)
> +{
> +	struct clk_psc *psc = to_clk_psc(hw);
> +	struct clk_davinci_psc_data *psc_data = psc->psc_data;
> +	unsigned long flags = 0;

No need to initialize flags here.

> +
> +	if (psc->lock)
> +		spin_lock_irqsave(psc->lock, flags);

Is locking really optional here?

> +
> +	clk_psc_config(psc_data->base, psc_data->domain, psc_data->lpsc,
> +			1, psc_data->psc_flags);
> +
> +	if (psc->lock)
> +		spin_unlock_irqrestore(psc->lock, flags);
> +
> +	return 0;
> +}
> +
> +static void clk_psc_disable(struct clk_hw *hw)
> +{
> +	struct clk_psc *psc = to_clk_psc(hw);
> +	struct clk_davinci_psc_data *psc_data = psc->psc_data;
> +	unsigned long flags = 0;
> +
> +	if (psc->lock)
> +		spin_lock_irqsave(psc->lock, flags);
> +
> +	clk_psc_config(psc_data->base, psc_data->domain, psc_data->lpsc,
> +			0, psc_data->psc_flags);
> +
> +	if (psc->lock)
> +		spin_unlock_irqrestore(psc->lock, flags);
> +}
> +
> +static const struct clk_ops clk_psc_ops = {
> +	.enable = clk_psc_enable,
> +	.disable = clk_psc_disable,
> +	.is_enabled = clk_psc_is_enabled,
> +};
> +
> +struct clk *clk_register_davinci_psc(struct device *dev, const char *name,
> +			const char *parent_name,
> +			struct clk_davinci_psc_data *psc_data,
> +			spinlock_t *lock)

Why do you need the lock to be provided from outside of this file? You
can initialize a lock for serializing writes to PSC registers within
this file, no?

> +{
> +	struct clk_init_data init;
> +	struct clk_psc *psc;
> +	struct clk *clk;
> +
> +	psc = kzalloc(sizeof(*psc), GFP_KERNEL);
> +	if (!psc)
> +		return ERR_PTR(-ENOMEM);
> +
> +	init.name = name;
> +	init.ops = &clk_psc_ops;
> +	init.flags = psc_data->flags;
> +	init.parent_names = (parent_name ? &parent_name : NULL);
> +	init.num_parents = (parent_name ? 1 : 0);
> +
> +	psc->psc_data = psc_data;
> +	psc->lock = lock;
> +	psc->hw.init = &init;
> +
> +	clk = clk_register(NULL, &psc->hw);
> +	if (IS_ERR(clk))
> +		kfree(psc);
> +
> +	return clk;
> +}

I guess, an unregister API will be useful here as well.

> diff --git a/include/linux/platform_data/clk-davinci-psc.h b/include/linux/platform_data/clk-davinci-psc.h
> new file mode 100644
> index 0000000..b805f72
> --- /dev/null
> +++ b/include/linux/platform_data/clk-davinci-psc.h
> @@ -0,0 +1,53 @@
> +/*
> + *  DaVinci Power & Sleep Controller (PSC) clk driver platform data
> + *
> + *  Copyright (C) 2006-2012 Texas Instruments.
> + *
> + *  This program is free software; you can redistribute  it and/or modify it
> + *  under  the terms of  the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the  License, or (at your
> + *  option) any later version.
> + *
> + *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
> + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
> + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
> + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
> + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
> + *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
> + *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
> + *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Is this taken from GPL text? There should be no need to have this here.

> + *
> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.

This is not needed as well. ;-)

Thanks,
Sekhar

^ permalink raw reply

* [PATCH v6] Enable USB peripheral mode on dm365 EVM
From: Constantine Shulyupin @ 2012-10-10 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

From: Constantine Shulyupin <const@MakeLinux.com>

Sets USB PHY clock source to 24 MHz clock and call USB configuration from board initialization.

Tested with OTG configuration, usb gadget g_zero on DM365 EVM connected to PC.

References:

Definition of USB_PHY_CTRL and PHYCLKFREQ:
- http://www.makelinux.com/lib/ti/DM36x_ARM/doc-141

Original patch by miguel.aguilar at ridgerun.com three years ago:
- http://www.mail-archive.com/davinci-linux-open-source at linux.davincidsp.com/msg14741.html

Signed-off-by: Constantine Shulyupin <const@MakeLinux.com>
---

Note:

Changelog

Changes since v5 http://www.spinics.net/lists/kernel/msg1413120.html
accordingy feedback of nsekhar at ti.com http://www.spinics.net/lists/kernel/msg1414914.html
- phy configuration moved to drivers/usb/musb/davinci.c
- USB_OTG configuration is submitted in separated patch: http://www.spinics.net/lists/kernel/msg1414964.html
- Setting current limit to 1000 mA. Any way the current is limited to 510 mA in davinci_setup_usb.

Changes since v4 http://www.spinics.net/lists/kernel/msg1412995.html
- removed fix of dev_info in musb_init_controller

Changes since v3 http://www.spinics.net/lists/kernel/msg1412544.html:
- removed optional altering of pr_info

Changes since v1  http://marc.info/?l=linux-kernel&m=130894150803661&w=2:
- removed optional code and reordered
- removed alternation of GPIO33, which is multiplexed with DRVVBUS, because is not need for peripheral USB

This patch is based on code from projects Arago, Angstom and RidgeRun.

---
 arch/arm/mach-davinci/board-dm365-evm.c |    2 ++
 drivers/usb/musb/davinci.c              |    3 +++
 drivers/usb/musb/davinci.h              |    1 +
 3 files changed, 6 insertions(+)

diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 688a9c5..ba5ffc1 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -38,6 +38,7 @@
 #include <mach/mmc.h>
 #include <mach/nand.h>
 #include <mach/keyscan.h>
+#include <mach/usb.h>
 
 #include <media/tvp514x.h>
 
@@ -610,6 +611,7 @@ static __init void dm365_evm_init(void)
 
 	dm365_init_spi0(BIT(0), dm365_evm_spi_info,
 			ARRAY_SIZE(dm365_evm_spi_info));
+	davinci_setup_usb(1000, 8);
 }
 
 MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 472c8b4..af09ebf 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -428,6 +428,9 @@ static int davinci_musb_init(struct musb *musb)
 		__raw_writel(deepsleep, DM355_DEEPSLEEP);
 	}
 
+	if (machine_is_davinci_dm365_evm())
+		writel(readl(USB_PHY_CTRL) | USBPHY_CLKFREQ_24MHZ, USB_PHY_CTRL);
+
 	/* reset the controller */
 	musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
 
diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h
index 371baa0..e737d97 100644
--- a/drivers/usb/musb/davinci.h
+++ b/drivers/usb/musb/davinci.h
@@ -16,6 +16,7 @@
 
 /* Integrated highspeed/otg PHY */
 #define USBPHY_CTL_PADDR	0x01c40034
+#define USBPHY_CLKFREQ_24MHZ	BIT(13)
 #define USBPHY_DATAPOL		BIT(11)	/* (dm355) switch D+/D- */
 #define USBPHY_PHYCLKGD		BIT(8)
 #define USBPHY_SESNDEN		BIT(7)	/* v(sess_end) comparator */
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 3/3] ARM: dts: EMIF and LPDDR2 device tree data for OMAP5 boards
From: Lokesh Vutla @ 2012-10-10 12:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349870716-25511-1-git-send-email-lokeshvutla@ti.com>

Device tree data for the EMIF sdram controllers in OMAP5
and LPDDR2 memory devices attached to OMAP5 boards.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
 arch/arm/boot/dts/lpddr2_data.dtsi |   64 +++++++++++++++++++++++++++++++++++-
 arch/arm/boot/dts/omap5-evm.dts    |   11 +++++++
 arch/arm/boot/dts/omap5.dtsi       |   18 ++++++++++
 3 files changed, 92 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/lpddr2_data.dtsi b/arch/arm/boot/dts/lpddr2_data.dtsi
index f97f70f..8e8c1bc 100644
--- a/arch/arm/boot/dts/lpddr2_data.dtsi
+++ b/arch/arm/boot/dts/lpddr2_data.dtsi
@@ -3,7 +3,7 @@
  */
 
 / {
-	elpida_ECB240ABACN: lpddr2 {
+	elpida_ECB240ABACN: lpddr2 at 0 {
 		compatible	= "Elpida,ECB240ABACN","jedec,lpddr2-s4";
 		density		= <2048>;
 		io-width	= <32>;
@@ -64,4 +64,66 @@
 			tDQSCK-max-derated = <6000>;
 		};
 	};
+
+	samsung_K3PE0E000B: lpddr2 at 1 {
+		compatible	= "Samsung,K3PE0E000B","jedec,lpddr2-s4";
+		density		= <4096>;
+		io-width	= <32>;
+
+		tRPab-min-tck	= <3>;
+		tRCD-min-tck	= <3>;
+		tWR-min-tck	= <3>;
+		tRASmin-min-tck	= <3>;
+		tRRD-min-tck	= <2>;
+		tWTR-min-tck	= <2>;
+		tXP-min-tck	= <2>;
+		tRTP-min-tck	= <2>;
+		tCKE-min-tck	= <3>;
+		tCKESR-min-tck	= <3>;
+		tFAW-min-tck	= <8>;
+
+		timings_samsung_K3PE0E000B_533mhz: lpddr2-timings at 0 {
+			compatible	= "jedec,lpddr2-timings";
+			min-freq	= <10000000>;
+			max-freq	= <533333333>;
+			tRPab		= <21000>;
+			tRCD		= <18000>;
+			tWR		= <15000>;
+			tRAS-min	= <42000>;
+			tRRD		= <10000>;
+			tWTR		= <7500>;
+			tXP		= <7500>;
+			tRTP		= <7500>;
+			tCKESR		= <15000>;
+			tDQSCK-max	= <5500>;
+			tFAW		= <50000>;
+			tZQCS		= <90000>;
+			tZQCL		= <360000>;
+			tZQinit		= <1000000>;
+			tRAS-max-ns	= <70000>;
+			tDQSCK-max-derated = <5620>;
+		};
+
+		timings_samsung_K3PE0E000B_266mhz: lpddr2-timings at 1 {
+			compatible	= "jedec,lpddr2-timings";
+			min-freq	= <10000000>;
+			max-freq	= <266666666>;
+			tRPab		= <21000>;
+			tRCD		= <18000>;
+			tWR		= <15000>;
+			tRAS-min	= <42000>;
+			tRRD		= <10000>;
+			tWTR		= <7500>;
+			tXP		= <7500>;
+			tRTP		= <7500>;
+			tCKESR		= <15000>;
+			tDQSCK-max	= <5500>;
+			tFAW		= <50000>;
+			tZQCS		= <90000>;
+			tZQCL		= <360000>;
+			tZQinit		= <1000000>;
+			tRAS-max-ns	= <70000>;
+			tDQSCK-max-derated = <6000>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/omap5-evm.dts b/arch/arm/boot/dts/omap5-evm.dts
index 6f87e1a..8a952f8 100644
--- a/arch/arm/boot/dts/omap5-evm.dts
+++ b/arch/arm/boot/dts/omap5-evm.dts
@@ -8,6 +8,7 @@
 /dts-v1/;
 
 /include/ "omap5.dtsi"
+/include/ "lpddr2_data.dtsi"
 
 / {
 	model = "TI OMAP5 EVM board";
@@ -82,3 +83,13 @@
 			0x020700d9>;	/* SEARCH */
 	linux,input-no-autorepeat;
 };
+
+&emif1 {
+	cs1-used;
+	device-handle = <&samsung_K3PE0E000B>;
+};
+
+&emif2 {
+	cs1-used;
+	device-handle = <&samsung_K3PE0E000B>;
+};
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 5db33f4..40b41c2 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -319,5 +319,23 @@
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp3";
 		};
+
+		emif1: emif at 0x4c000000 {
+			compatible	= "ti,emif-4d5";
+			ti,hwmods	= "emif1";
+			phy-type	= <2>;
+			hw-caps-read-idle-ctrl;
+			hw-caps-ll-interface;
+			hw-caps-temp-alert;
+		};
+
+		emif2: emif at 0x4d000000 {
+			compatible	= "ti,emif-4d5";
+			ti,hwmods	= "emif2";
+			phy-type	= <2>;
+			hw-caps-read-idle-ctrl;
+			hw-caps-ll-interface;
+			hw-caps-temp-alert;
+		};
 	};
 };
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 2/3] ARM: dts: Correcting size of memory defined for omap5
From: Lokesh Vutla @ 2012-10-10 12:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349870716-25511-1-git-send-email-lokeshvutla@ti.com>

Memory present for omap5 is 2GB. But in dt file
it is specified as 1GB. Correcting the same
in this patch

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
 arch/arm/boot/dts/omap5-evm.dts |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/omap5-evm.dts b/arch/arm/boot/dts/omap5-evm.dts
index 9c41a3f..6f87e1a 100644
--- a/arch/arm/boot/dts/omap5-evm.dts
+++ b/arch/arm/boot/dts/omap5-evm.dts
@@ -15,7 +15,7 @@
 
 	memory {
 		device_type = "memory";
-		reg = <0x80000000 0x40000000>; /* 1 GB */
+		reg = <0x80000000 0x80000000>; /* 2 GB */
 	};
 
 	vmmcsd_fixed: fixedregulator-mmcsd {
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 1/3] ARM: dts: Renaming elpida_ecb240abacn.dtsi as lpddr2_data.dtsi
From: Lokesh Vutla @ 2012-10-10 12:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349870716-25511-1-git-send-email-lokeshvutla@ti.com>

Renaming elpida_ecb240abacn.dtsi file generic, so that the
same file can be reused for other parts from different vendors.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
 arch/arm/boot/dts/{elpida_ecb240abacn.dtsi => lpddr2_data.dtsi} |    0
 arch/arm/boot/dts/omap4-panda.dts                               |    2 +-
 arch/arm/boot/dts/omap4-sdp.dts                                 |    2 +-
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename arch/arm/boot/dts/{elpida_ecb240abacn.dtsi => lpddr2_data.dtsi} (100%)

diff --git a/arch/arm/boot/dts/elpida_ecb240abacn.dtsi b/arch/arm/boot/dts/lpddr2_data.dtsi
similarity index 100%
rename from arch/arm/boot/dts/elpida_ecb240abacn.dtsi
rename to arch/arm/boot/dts/lpddr2_data.dtsi
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts
index 20b966e..09d3a32 100644
--- a/arch/arm/boot/dts/omap4-panda.dts
+++ b/arch/arm/boot/dts/omap4-panda.dts
@@ -8,7 +8,7 @@
 /dts-v1/;
 
 /include/ "omap4.dtsi"
-/include/ "elpida_ecb240abacn.dtsi"
+/include/ "lpddr2_data.dtsi"
 
 / {
 	model = "TI OMAP4 PandaBoard";
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index 94a23b3..dd749fc 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -8,7 +8,7 @@
 /dts-v1/;
 
 /include/ "omap4.dtsi"
-/include/ "elpida_ecb240abacn.dtsi"
+/include/ "lpddr2_data.dtsi"
 
 / {
 	model = "TI OMAP4 SDP board";
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 0/3] ARM: dts: EMIF and LPDDR2 device tree data for OMAP5 boards
From: Lokesh Vutla @ 2012-10-10 12:05 UTC (permalink / raw)
  To: linux-arm-kernel

Patch 1:
	Renaming elpida_ecb240abacn.dtsi as lpddr2_data.dtsi
Patch 2:
	Correcting size of memory defined for omap5
Patch 3:
	EMIF and LPDDR2 device tree data for OMAP5 boards

Testing:
- Boot tested on omap5-sevm board
- Built emif as a module

Lokesh Vutla (3):
  ARM: dts: Renaming elpida_ecb240abacn.dts as lpddr2_data.dtsi
  ARM: dts: Correcting size of memory defined for omap5
  ARM: dts: EMIF and LPDDR2 device tree data for OMAP5 boards

 arch/arm/boot/dts/elpida_ecb240abacn.dtsi |   67 ---------------
 arch/arm/boot/dts/lpddr2_data.dtsi        |  129 +++++++++++++++++++++++++++++
 arch/arm/boot/dts/omap4-panda.dts         |    2 +-
 arch/arm/boot/dts/omap4-sdp.dts           |    2 +-
 arch/arm/boot/dts/omap5-evm.dts           |   13 ++-
 arch/arm/boot/dts/omap5.dtsi              |   18 ++++
 6 files changed, 161 insertions(+), 70 deletions(-)
 delete mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi
 create mode 100644 arch/arm/boot/dts/lpddr2_data.dtsi

-- 
1.7.10.4

^ permalink raw reply

* [PATCH 01/13] clk: davinci - add Main PLL clock driver
From: Sekhar Nori @ 2012-10-10 12:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1348682889-9509-2-git-send-email-m-karicheri2@ti.com>

Hi Murali,

On 9/26/2012 11:37 PM, Murali Karicheri wrote:
> This is the driver for the main PLL clock hardware found on DM SoCs.
> This driver borrowed code from arch/arm/mach-davinci/clock.c and
> implemented the driver as per common clock provider API. The main PLL
> hardware typically has a multiplier, a pre-divider and a post-divider.
> Some of the SoCs has the divider fixed meaning they can not be
> configured through a register. HAS_PREDIV and HAS_POSTDIV flags are used
> to tell the driver if a hardware has these dividers present or not.
> Driver is configured through the structure clk_davinci_pll_data
> that has the platform data for the driver.
> 
> Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>

Are you using git-format-patch to generate the patches? It should have
added a diffstat here by default which is very useful in quickly
understanding what the patch is touching.
> 
> diff --git a/drivers/clk/davinci/clk-davinci-pll.c b/drivers/clk/davinci/clk-davinci-pll.c
> new file mode 100644
> index 0000000..13e1690
> --- /dev/null
> +++ b/drivers/clk/davinci/clk-davinci-pll.c
> @@ -0,0 +1,128 @@
> +/*
> + * PLL clk driver DaVinci devices
> + *
> + * Copyright (C) 2006-2012 Texas Instruments.
> + * Copyright (C) 2008-2009 Deep Root Systems, LLC
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + * TODO - Add set_parent_rate()
> + */
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/platform_data/clk-davinci-pll.h>

It will be nice to keep these sorted in alphabetical order. You got it
almost right, except the last one. Keeping it sorted keeps out duplicates.

> +
> +#include <mach/cputype.h>

Hmm, why is this needed? mach/ includes in driver files make it tough to
use this on other architectures/machines. You have plan to use this on
driver on keystone and c6x as well, right? It will also break
multi-platform ARM build.

> +
> +#define PLLM		0x110
> +#define PLLM_PLLM_MASK  0xff
> +#define PREDIV          0x114
> +#define POSTDIV         0x128
> +#define PLLDIV_EN       BIT(15)

Can you use tabs for indentation?

> +
> +/**
> + * struct clk_davinci_pll - DaVinci Main pll clock

no capitalization on 'M' needed, I think.

> + * @hw: clk_hw for the pll
> + * @pll_data: PLL driver specific data
> + */
> +struct clk_davinci_pll {
> +	struct clk_hw hw;
> +	struct clk_davinci_pll_data *pll_data;
> +};
> +
> +#define to_clk_pll(_hw) container_of(_hw, struct clk_davinci_pll, hw)
> +
> +static unsigned long clk_pllclk_recalc(struct clk_hw *hw,
> +					unsigned long parent_rate)
> +{
> +	struct clk_davinci_pll *pll = to_clk_pll(hw);
> +	struct clk_davinci_pll_data *pll_data = pll->pll_data;
> +	u32 mult = 1, prediv = 1, postdiv = 1;

No need to initialize mult here since you are doing it right away below.

> +	unsigned long rate = parent_rate;
> +
> +	/* If there is a device specific recalc defined invoke it. Otherwise
> +	 * fallback to default one
> +	 */

This is not following the multi-line comment style defined in
Documentation/CodingStyle.

> +	mult = __raw_readl(pll_data->pllm);

Do not use __raw_ variants since they are not safe on ARMv7. Use
readl/writel instead.

> +	if (pll_data->pllm_multiplier)
> +		mult =  pll_data->pllm_multiplier *
> +				(mult & pll_data->pllm_mask);
> +	else
> +		mult = (mult & pll_data->pllm_mask) + 1;
> +
> +	if (pll_data->flags & CLK_DAVINCI_PLL_HAS_PREDIV) {
> +		/* pre-divider is fixed, take prediv value from pll_data  */
> +		if (pll_data->fixed_prediv)
> +			prediv = pll_data->fixed_prediv;

Since else is multi-line, if needs braces as well.

> +		else {
> +			prediv = __raw_readl(pll_data->prediv);
> +			if (prediv & PLLDIV_EN)
> +				prediv = (prediv & pll_data->prediv_mask) + 1;
> +			else
> +				prediv = 1;
> +		}
> +	}
> +
> +	if (pll_data->flags & CLK_DAVINCI_PLL_HAS_POSTDIV) {
> +		postdiv = __raw_readl(pll_data->postdiv);
> +		if (postdiv & PLLDIV_EN)
> +			postdiv = (postdiv & pll_data->postdiv_mask) + 1;
> +		else
> +			postdiv = 1;
> +	}
> +
> +	rate /= prediv;
> +	rate *= mult;
> +	rate /= postdiv;
> +
> +	pr_debug("PLL%d: input = %lu MHz [ ",
> +		 pll_data->num, parent_rate / 1000000);
> +	if (prediv > 1)
> +		pr_debug("/ %d ", prediv);
> +	if (mult > 1)
> +		pr_debug("* %d ", mult);
> +	if (postdiv > 1)
> +		pr_debug("/ %d ", postdiv);
> +	pr_debug("] --> %lu MHz output.\n", rate / 1000000);
> +	return rate;

Have a blank like before the return, its easier to read that way.

> +}
> +
> +static const struct clk_ops clk_pll_ops = {
> +	.recalc_rate = clk_pllclk_recalc,
> +};
> +
> +struct clk *clk_register_davinci_pll(struct device *dev, const char *name,
> +			const char *parent_name,
> +			struct clk_davinci_pll_data *pll_data)
> +{
> +	struct clk_init_data init;
> +	struct clk_davinci_pll *pll;
> +	struct clk *clk;
> +
> +	if (!pll_data)
> +		return ERR_PTR(-ENODEV);
> +
> +	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
> +	if (!pll)
> +		return ERR_PTR(-ENOMEM);
> +	init.name = name;
> +	init.ops = &clk_pll_ops;
> +	init.flags = pll_data->flags;
> +	init.parent_names = (parent_name ? &parent_name : NULL);
> +	init.num_parents = (parent_name ? 1 : 0);
> +
> +	pll->pll_data	= pll_data;
> +	pll->hw.init = &init;
> +
> +	clk = clk_register(NULL, &pll->hw);
> +	if (IS_ERR(clk))
> +		kfree(pll);
> +
> +	return clk;
> +}

I guess there is an an "unregister" required as well which will free the
pll memory allocated above and unregister the clock? Not sure if you
would ever unregister a PLL, but providing this will probably help symmetry.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH] Add McSPI devices found in AM33xx SoC to dtsi
From: Hebbar, Gururaja @ 2012-10-10 12:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3608180472966131184@unknownmsgid>

On Tue, Oct 09, 2012 at 19:54:28, Phil Pokorny wrote:
> On Oct 9, 2012, at 3:36 AM, "Philip, Avinash" <avinashphilip@ti.com>
> wrote:
> 
> > On Tue, Oct 09, 2012 at 10:40:58, Phil Pokorny wrote:
> >> We're using the BeagleBone for a project and we need the SPI devices
> >> available and configured with all available chip selects.
> >>
> >> Please accept the following patch to add these to the base .dtsi file
> >> so they can then be enabled in the beaglebone specific .dts with
> >> minimal fuss.
> >
> > Patch for adding MCSPI in am33xx.dtsi already been sent by me.
> > https://lkml.org/lkml/2012/9/18/32
> 
> Thank you for responding.
> 
> Was that accepted?  It didn't seem to be in the Linux-omap git tree I
> cloned. I need to check the Torvalds mainline kernel.
> 
> I believe the number of chip selects on spi1 is incorrect. There is
> only one (1) CS shown in the hardware documentation for AM33xx.

Which Hardware document are you referring to? TRM shows 2 chip
selects for McSPI1

> 
> Is OMAP4-McSPI the best match for the hardware?  The mcspi driver
> appears to differ only in the register offset used.  A hard coded zero
> value for omap2 and a named constant for omap4. The hardware manual
> for the AM33xx shows the register map starting at zero.
> 
> Thank you,
> Phil P.
> >
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


Regards, 
Gururaja

^ permalink raw reply

* [PATCH 8/8] cpufreq: db8500: Use armss clk to update frequency
From: Ulf Hansson @ 2012-10-10 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349869349-8070-1-git-send-email-ulf.hansson@stericsson.com>

From: Ulf Hansson <ulf.hansson@linaro.org>

Using the armss clk to update the frequency makes the driver no more
directly dependant on the prmcu API.

Cc: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/cpufreq/db8500-cpufreq.c |   24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c
index dea9a49..4f154bc 100644
--- a/drivers/cpufreq/db8500-cpufreq.c
+++ b/drivers/cpufreq/db8500-cpufreq.c
@@ -14,10 +14,11 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/clk.h>
 #include <mach/id.h>
 
 static struct cpufreq_frequency_table *freq_table;
+static struct clk *armss_clk;
 
 static struct freq_attr *db8500_cpufreq_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
@@ -58,9 +59,9 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
 	for_each_cpu(freqs.cpu, policy->cpus)
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	/* request the PRCM unit for opp change */
-	if (prcmu_set_arm_opp(freq_table[idx].index)) {
-		pr_err("db8500-cpufreq:  Failed to set OPP level\n");
+	/* update armss clk frequency */
+	if (clk_set_rate(armss_clk, freq_table[idx].frequency * 1000)) {
+		pr_err("db8500-cpufreq: Failed to update armss clk\n");
 		return -EINVAL;
 	}
 
@@ -74,16 +75,16 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
 static unsigned int db8500_cpufreq_getspeed(unsigned int cpu)
 {
 	int i = 0;
-	/* request the prcm to get the current ARM opp */
-	int opp = prcmu_get_arm_opp();
+	unsigned long freq = clk_get_rate(armss_clk) / 1000;
 
 	while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
-		if (opp == freq_table[i].index)
+		if (freq <= freq_table[i].frequency)
 			return freq_table[i].frequency;
 		i++;
 	}
 
-	/* We could not find a corresponding opp frequency. */
+	/* We could not find a corresponding frequency. */
+	pr_err("db8500-cpufreq: Failed to find cpufreq speed\n");
 	return 0;
 }
 
@@ -92,6 +93,12 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 	int i = 0;
 	int res;
 
+	armss_clk = clk_get(NULL, "armss");
+	if (IS_ERR(armss_clk)) {
+		pr_err("db8500-cpufreq : Failed to get armss clk\n");
+		return PTR_ERR(armss_clk);
+	}
+
 	pr_info("db8500-cpufreq : Available frequencies:\n");
 	while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
 		pr_info("  %d Mhz\n", freq_table[i].frequency/1000);
@@ -104,6 +111,7 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 		cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
 	else {
 		pr_err("db8500-cpufreq : Failed to read policy table\n");
+		clk_put(armss_clk);
 		return res;
 	}
 
-- 
1.7.10

^ permalink raw reply related

* [PATCH 7/8] clk: ux500: Add armss clk and fixup smp_twd clk for u8500
From: Ulf Hansson @ 2012-10-10 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349869349-8070-1-git-send-email-ulf.hansson@stericsson.com>

From: Ulf Hansson <ulf.hansson@linaro.org>

The new armss clk is a prcmu_scalable_rate clk which represents
the ARMSS clk. This then makes it possible to convert the smp_twd
clk to a fixed factor clock type, using a fixed divider of 2 and
with the armss clk as parent.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/clk/ux500/u8500_clk.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
index ca4a25e..b1bd1c46 100644
--- a/drivers/clk/ux500/u8500_clk.c
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -205,16 +205,18 @@ void u8500_clk_init(void)
 	clk_register_clkdev(clk, "dsilp2", "dsilink.2");
 	clk_register_clkdev(clk, "dsilp2", "mcde");
 
-	clk = clk_reg_prcmu_rate("smp_twd", NULL, PRCMU_ARMSS,
-				CLK_IS_ROOT|CLK_GET_RATE_NOCACHE|
-				CLK_IGNORE_UNUSED);
+	clk = clk_reg_prcmu_scalable_rate("armss", NULL,
+				PRCMU_ARMSS, 0, CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+	clk_register_clkdev(clk, "armss", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "smp_twd", "armss",
+				CLK_IGNORE_UNUSED, 1, 2);
 	clk_register_clkdev(clk, NULL, "smp_twd");
 
 	/*
 	 * FIXME: Add special handled PRCMU clocks here:
-	 * 1. clk_arm, use PRCMU_ARMCLK.
-	 * 2. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
-	 * 3. ab9540_clkout1yuv, see clkout0yuv
+	 * 1. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
+	 * 2. ab9540_clkout1yuv, see clkout0yuv
 	 */
 
 	/* PRCC P-clocks */
-- 
1.7.10

^ permalink raw reply related

* [PATCH 6/8] clk: ux500: Support for prcmu_scalable_rate clock
From: Ulf Hansson @ 2012-10-10 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349869349-8070-1-git-send-email-ulf.hansson@stericsson.com>

From: Ulf Hansson <ulf.hansson@linaro.org>

The prcmu_scalable_rate clock can change rate but is not gateable.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/clk/ux500/clk-prcmu.c |   17 +++++++++++++++++
 drivers/clk/ux500/clk.h       |    6 ++++++
 2 files changed, 23 insertions(+)

diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index 930cdfe..2e5ef7a 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -153,6 +153,13 @@ static struct clk_ops clk_prcmu_gate_ops = {
 	.recalc_rate = clk_prcmu_recalc_rate,
 };
 
+static struct clk_ops clk_prcmu_scalable_rate_ops = {
+	.is_enabled = clk_prcmu_is_enabled,
+	.recalc_rate = clk_prcmu_recalc_rate,
+	.round_rate = clk_prcmu_round_rate,
+	.set_rate = clk_prcmu_set_rate,
+};
+
 static struct clk_ops clk_prcmu_rate_ops = {
 	.is_enabled = clk_prcmu_is_enabled,
 	.recalc_rate = clk_prcmu_recalc_rate,
@@ -233,6 +240,16 @@ struct clk *clk_reg_prcmu_gate(const char *name,
 			&clk_prcmu_gate_ops);
 }
 
+struct clk *clk_reg_prcmu_scalable_rate(const char *name,
+					const char *parent_name,
+					u8 cg_sel,
+					unsigned long rate,
+					unsigned long flags)
+{
+	return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
+			&clk_prcmu_scalable_rate_ops);
+}
+
 struct clk *clk_reg_prcmu_rate(const char *name,
 			       const char *parent_name,
 			       u8 cg_sel,
diff --git a/drivers/clk/ux500/clk.h b/drivers/clk/ux500/clk.h
index 836d7d1..a9e2961 100644
--- a/drivers/clk/ux500/clk.h
+++ b/drivers/clk/ux500/clk.h
@@ -35,6 +35,12 @@ struct clk *clk_reg_prcmu_gate(const char *name,
 			       u8 cg_sel,
 			       unsigned long flags);
 
+struct clk *clk_reg_prcmu_scalable_rate(const char *name,
+					const char *parent_name,
+					u8 cg_sel,
+					unsigned long rate,
+					unsigned long flags);
+
 struct clk *clk_reg_prcmu_rate(const char *name,
 			       const char *parent_name,
 			       u8 cg_sel,
-- 
1.7.10

^ permalink raw reply related

* [PATCH 5/8] mfd: db8500: Connect ARMSS clk to ARM OPP
From: Ulf Hansson @ 2012-10-10 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349869349-8070-1-git-send-email-ulf.hansson@stericsson.com>

From: Ulf Hansson <ulf.hansson@linaro.org>

ARMSS clk directly maps it's frequency towards the cpufreq table.
To be able to update the ARMSS clk rate, a new set_rate function for
the ARMSS clk is added, which also will trigger a corresponding ARM
OPP request. Additionally an ARMSS clk round_rate function is added
to fetch valid cpufreq frequencies.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/mfd/db8500-prcmu.c |   78 +++++++++++++++++++++++++++++++-------------
 1 file changed, 56 insertions(+), 22 deletions(-)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 53c24c4..e91a6e6 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -421,9 +421,6 @@ static struct {
 
 static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
 
-/* Functions definition */
-static void compute_armss_rate(void);
-
 /* Spinlocks */
 static DEFINE_SPINLOCK(prcmu_lock);
 static DEFINE_SPINLOCK(clkout_lock);
@@ -1020,7 +1017,6 @@ int db8500_prcmu_set_arm_opp(u8 opp)
 		(mb1_transfer.ack.arm_opp != opp))
 		r = -EIO;
 
-	compute_armss_rate();
 	mutex_unlock(&mb1_transfer.lock);
 
 	return r;
@@ -1670,13 +1666,8 @@ static unsigned long clock_rate(u8 clock)
 	else
 		return 0;
 }
-static unsigned long latest_armss_rate;
-static unsigned long armss_rate(void)
-{
-	return latest_armss_rate;
-}
 
-static void compute_armss_rate(void)
+static unsigned long armss_rate(void)
 {
 	u32 r;
 	unsigned long rate;
@@ -1701,7 +1692,7 @@ static void compute_armss_rate(void)
 		rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV);
 	}
 
-	latest_armss_rate = rate;
+	return rate;
 }
 
 static unsigned long dsiclk_rate(u8 n)
@@ -1821,6 +1812,35 @@ static long round_clock_rate(u8 clock, unsigned long rate)
 	return rounded_rate;
 }
 
+/* CPU FREQ table, may be changed due to if MAX_OPP is supported. */
+static struct cpufreq_frequency_table db8500_cpufreq_table[] = {
+	{ .frequency = 200000, .index = ARM_EXTCLK,},
+	{ .frequency = 400000, .index = ARM_50_OPP,},
+	{ .frequency = 800000, .index = ARM_100_OPP,},
+	{ .frequency = CPUFREQ_TABLE_END,}, /* To be used for MAX_OPP. */
+	{ .frequency = CPUFREQ_TABLE_END,},
+};
+
+static long round_armss_rate(unsigned long rate)
+{
+	long freq = 0;
+	int i = 0;
+
+	/* cpufreq table frequencies is in KHz. */
+	rate = rate / 1000;
+
+	/* Find the corresponding arm opp from the cpufreq table. */
+	while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) {
+		freq = db8500_cpufreq_table[i].frequency;
+		if (freq == rate)
+			break;
+		i++;
+	}
+
+	/* Return the last valid value, even if a match was not found. */
+	return freq * 1000;
+}
+
 #define MIN_PLL_VCO_RATE 600000000ULL
 #define MAX_PLL_VCO_RATE 1680640000ULL
 
@@ -1892,6 +1912,8 @@ long prcmu_round_clock_rate(u8 clock, unsigned long rate)
 {
 	if (clock < PRCMU_NUM_REG_CLOCKS)
 		return round_clock_rate(clock, rate);
+	else if (clock == PRCMU_ARMSS)
+		return round_armss_rate(rate);
 	else if (clock == PRCMU_PLLDSI)
 		return round_plldsi_rate(rate);
 	else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
@@ -1951,6 +1973,27 @@ static void set_clock_rate(u8 clock, unsigned long rate)
 	spin_unlock_irqrestore(&clk_mgt_lock, flags);
 }
 
+static int set_armss_rate(unsigned long rate)
+{
+	int i = 0;
+
+	/* cpufreq table frequencies is in KHz. */
+	rate = rate / 1000;
+
+	/* Find the corresponding arm opp from the cpufreq table. */
+	while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) {
+		if (db8500_cpufreq_table[i].frequency == rate)
+			break;
+		i++;
+	}
+
+	if (db8500_cpufreq_table[i].frequency != rate)
+		return -EINVAL;
+
+	/* Set the new arm opp. */
+	return db8500_prcmu_set_arm_opp(db8500_cpufreq_table[i].index);
+}
+
 static int set_plldsi_rate(unsigned long rate)
 {
 	unsigned long src_rate;
@@ -2031,6 +2074,8 @@ int prcmu_set_clock_rate(u8 clock, unsigned long rate)
 {
 	if (clock < PRCMU_NUM_REG_CLOCKS)
 		set_clock_rate(clock, rate);
+	else if (clock == PRCMU_ARMSS)
+		return set_armss_rate(rate);
 	else if (clock == PRCMU_PLLDSI)
 		return set_plldsi_rate(rate);
 	else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
@@ -2755,8 +2800,6 @@ void __init db8500_prcmu_early_init(void)
 	init_completion(&mb5_transfer.work);
 
 	INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
-
-	compute_armss_rate();
 }
 
 static void __init init_prcm_registers(void)
@@ -3003,15 +3046,6 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
 	},
 };
 
-/* CPU FREQ table, may be changed due to if MAX_OPP is supported. */
-static struct cpufreq_frequency_table db8500_cpufreq_table[] = {
-	{ .frequency = 200000, .index = ARM_EXTCLK,},
-	{ .frequency = 400000, .index = ARM_50_OPP,},
-	{ .frequency = 800000, .index = ARM_100_OPP,},
-	{ .frequency = CPUFREQ_TABLE_END,}, /* To be used for MAX_OPP. */
-	{ .frequency = CPUFREQ_TABLE_END,},
-};
-
 static struct resource ab8500_resources[] = {
 	[0] = {
 		.start	= IRQ_DB8500_AB8500,
-- 
1.7.10

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox