diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-07 16:32:41 +0900 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-07 16:32:41 +0900 |
commit | 43df169fe6887691f87935cdfae227f022cd7c1c (patch) | |
tree | b1488627678a141695a36a9db04f6af06e1e288a | |
parent | afe8135a605144e3795e2f0d4b18a2e341ed5c23 (diff) | |
download | ltsi-kernel-43df169fe6887691f87935cdfae227f022cd7c1c.tar.gz |
add kzm9g patches
206 files changed, 26038 insertions, 0 deletions
diff --git a/patches.kzm9g/0001-net-remove-mm.h-inclusion-from-netdevice.h.patch b/patches.kzm9g/0001-net-remove-mm.h-inclusion-from-netdevice.h.patch new file mode 100644 index 00000000000000..87178759729ae8 --- /dev/null +++ b/patches.kzm9g/0001-net-remove-mm.h-inclusion-from-netdevice.h.patch @@ -0,0 +1,167 @@ +From 49d759919c99a3cb5391a446f5541f606c65e3c1 Mon Sep 17 00:00:00 2001 +From: Alexey Dobriyan <adobriyan@gmail.com> +Date: Thu, 16 Jun 2011 11:01:34 +0000 +Subject: net: remove mm.h inclusion from netdevice.h + +Remove linux/mm.h inclusion from netdevice.h -- it's unused (I've checked manually). + +To prevent mm.h inclusion via other channels also extract "enum dma_data_direction" +definition into separate header. This tiny piece is what gluing netdevice.h with mm.h +via "netdevice.h => dmaengine.h => dma-mapping.h => scatterlist.h => mm.h". +Removal of mm.h from scatterlist.h was tried and was found not feasible +on most archs, so the link was cutoff earlier. + +Hope people are OK with tiny include file. + +Note, that mm_types.h is still dragged in, but it is a separate story. + +Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit b7f080cfe223b3b7424872639d153695615a9255) + +Conflicts: + + arch/arm/mach-davinci/board-mityomapl138.c + arch/arm/mach-davinci/dm646x.c + arch/arm/mach-davinci/pm.c + arch/arm/mach-imx/dma-v1.c + arch/arm/mach-imx/mach-mx31_3ds.c + arch/arm/mach-iop13xx/setup.c + arch/arm/mach-mxs/devices/platform-auart.c + arch/arm/mach-mxs/devices/platform-dma.c + arch/arm/mach-mxs/devices/platform-fec.c + arch/arm/plat-mxc/devices/platform-fec.c + arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c + arch/arm/plat-mxc/devices/platform-imx-fb.c + arch/arm/plat-mxc/devices/platform-ipu-core.c + arch/arm/plat-mxc/devices/platform-mxc-ehci.c + arch/arm/plat-mxc/devices/platform-mxc-mmc.c + arch/arm/plat-nomadik/include/plat/ste_dma40.h + arch/x86/kernel/tboot.c + crypto/async_tx/raid6test.c + drivers/dma/coh901318.c + drivers/dma/dmatest.c + drivers/dma/ipu/ipu_idmac.c + drivers/dma/ste_dma40.c + drivers/media/dvb/mantis/mantis_ca.c + drivers/media/dvb/mantis/mantis_evm.c + drivers/media/dvb/mantis/mantis_hif.c + drivers/media/dvb/mantis/mantis_ioc.c + drivers/media/dvb/mantis/mantis_pcmcia.c + drivers/media/dvb/mantis/mantis_uart.c + drivers/media/dvb/mantis/mantis_vp1034.c + drivers/mmc/host/tmio_mmc_dma.c + drivers/mtd/nand/atmel_nand.c + drivers/net/arm/ks8695net.c + drivers/net/bnx2x/bnx2x.h + drivers/net/can/janz-ican3.c + drivers/net/can/softing/softing_fw.c + drivers/net/can/softing/softing_main.c + drivers/net/ethoc.c + drivers/net/fec_mpc52xx.c + drivers/net/greth.c + drivers/net/irda/pxaficp_ir.c + drivers/net/ks8851_mll.c + drivers/net/sgiseeq.c + drivers/net/stmmac/dwmac1000_core.c + drivers/net/stmmac/dwmac1000_dma.c + drivers/net/stmmac/dwmac100_core.c + drivers/net/stmmac/dwmac100_dma.c + drivers/net/stmmac/stmmac_ethtool.c + drivers/net/stmmac/stmmac_mdio.c + drivers/net/usb/cdc-phonet.c + drivers/net/vxge/vxge-config.h + drivers/net/wireless/ath/ath5k/base.c + drivers/net/wireless/ath/ath9k/beacon.c + drivers/net/wireless/ath/ath9k/init.c + drivers/net/wireless/ath/ath9k/recv.c + drivers/net/wireless/ath/ath9k/xmit.c + drivers/staging/pohmelfs/crypto.c + drivers/tty/serial/ifx6x60.c + drivers/usb/gadget/f_phonet.c + include/crypto/if_alg.h + include/linux/netdevice.h + net/sched/sch_netem.c + security/apparmor/lib.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/dmaengine.c | 1 + + include/linux/dma-direction.h | 13 +++++++++++++ + include/linux/dma-mapping.h | 10 +--------- + include/linux/dmaengine.h | 4 +++- + 4 files changed, 18 insertions(+), 10 deletions(-) + create mode 100644 include/linux/dma-direction.h + +diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c +index 8bcb15f..48694c3 100644 +--- a/drivers/dma/dmaengine.c ++++ b/drivers/dma/dmaengine.c +@@ -45,6 +45,7 @@ + * See Documentation/dmaengine.txt for more details + */ + ++#include <linux/dma-mapping.h> + #include <linux/init.h> + #include <linux/module.h> + #include <linux/mm.h> +diff --git a/include/linux/dma-direction.h b/include/linux/dma-direction.h +new file mode 100644 +index 0000000..95b6a82 +--- /dev/null ++++ b/include/linux/dma-direction.h +@@ -0,0 +1,13 @@ ++#ifndef _LINUX_DMA_DIRECTION_H ++#define _LINUX_DMA_DIRECTION_H ++/* ++ * These definitions mirror those in pci.h, so they can be used ++ * interchangeably with their PCI_ counterparts. ++ */ ++enum dma_data_direction { ++ DMA_BIDIRECTIONAL = 0, ++ DMA_TO_DEVICE = 1, ++ DMA_FROM_DEVICE = 2, ++ DMA_NONE = 3, ++}; ++#endif +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index ba8319a..1a167c4 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -4,17 +4,9 @@ + #include <linux/device.h> + #include <linux/err.h> + #include <linux/dma-attrs.h> ++#include <linux/dma-direction.h> + #include <linux/scatterlist.h> + +-/* These definitions mirror those in pci.h, so they can be used +- * interchangeably with their PCI_ counterparts */ +-enum dma_data_direction { +- DMA_BIDIRECTIONAL = 0, +- DMA_TO_DEVICE = 1, +- DMA_FROM_DEVICE = 2, +- DMA_NONE = 3, +-}; +- + struct dma_map_ops { + void* (*alloc_coherent)(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp); +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index eee7add..8fbf40e 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -23,7 +23,9 @@ + + #include <linux/device.h> + #include <linux/uio.h> +-#include <linux/dma-mapping.h> ++#include <linux/dma-direction.h> ++ ++struct scatterlist; + + /** + * typedef dma_cookie_t - an opaque DMA cookie +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0002-Include-linux-dma-mapping.h-in-linux-dmaengine.h.patch b/patches.kzm9g/0002-Include-linux-dma-mapping.h-in-linux-dmaengine.h.patch new file mode 100644 index 00000000000000..049d91e5123c18 --- /dev/null +++ b/patches.kzm9g/0002-Include-linux-dma-mapping.h-in-linux-dmaengine.h.patch @@ -0,0 +1,35 @@ +From 0056ad033559371f0ce04d68fffc30c92fb551e8 Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Fri, 17 Feb 2012 16:16:28 +0900 +Subject: Include linux/dma-mapping.h in linux/dmaengine.h + +This reverses the effect of b7f080cfe223b3b7424872639d153695615a9255 (net: +remove mm.h inclusion from netdevice.h) while leaving almost all of the +code changes in place, in particular the creation of linux/dma-diretion.h +which is a dependency of subsequent patches that will be backported. + +The motivation for this it to unbreak multiple drivers. +This patch cam be reverted if backports to all relevant drivers +are made. + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/dmaengine.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 8fbf40e..8bf1032 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -23,7 +23,7 @@ + + #include <linux/device.h> + #include <linux/uio.h> +-#include <linux/dma-direction.h> ++#include <linux/dma-mapping.h> + + struct scatterlist; + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0003-dmaengine-failure-to-get-a-specific-DMA-channel-is-n.patch b/patches.kzm9g/0003-dmaengine-failure-to-get-a-specific-DMA-channel-is-n.patch new file mode 100644 index 00000000000000..a57dbe97cab20a --- /dev/null +++ b/patches.kzm9g/0003-dmaengine-failure-to-get-a-specific-DMA-channel-is-n.patch @@ -0,0 +1,53 @@ +From d607a7087661613a9c1e4a45ae548570061bc6b8 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Mon, 20 Jun 2011 17:02:47 +0200 +Subject: dmaengine: failure to get a specific DMA channel is not critical + +There exist systems with multiple DMA controllers with different +capabilities. For example, on some sh-mobile / rmobile systems there are +DMA controllers, whose channels can be configured to be used with +SD- and MMC-host controllers, serial ports etc. Besides there are also +DMA controllers, that can only be used for one special function, e.g., +for USB. In such cases the DMA client filter function can just choose +to specify to the DMA driver, which channel it needs. Then the +.device_alloc_chan_resources() method of the DMA driver will check, +whether it can provide that dunction. If not, it will fail and the loop +in __dma_request_channel() will continue to the next DMA device, until +it finds a suitable one. This works fine with just one minor glitch: +the kernel logs error messages like + +dmaengine: failed to get <channel name>: (-<error code>) + +after each such non-critical failure. This patch lowers priority of +this message to the debug level. + +Reported-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Vinod Koul <vinod.koul@intel.com> +(cherry picked from commit a03a202e95fdaa3ff52ccfc2594ec531e5917816) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/dmaengine.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c +index 48694c3..26374b2 100644 +--- a/drivers/dma/dmaengine.c ++++ b/drivers/dma/dmaengine.c +@@ -510,8 +510,8 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v + dma_chan_name(chan)); + list_del_rcu(&device->global_node); + } else if (err) +- pr_err("dmaengine: failed to get %s: (%d)\n", +- dma_chan_name(chan), err); ++ pr_debug("dmaengine: failed to get %s: (%d)\n", ++ dma_chan_name(chan), err); + else + break; + if (--device->privatecnt == 0) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0004-Improve-slave-cyclic-DMA-engine-documentation.patch b/patches.kzm9g/0004-Improve-slave-cyclic-DMA-engine-documentation.patch new file mode 100644 index 00000000000000..66ba26c33f5787 --- /dev/null +++ b/patches.kzm9g/0004-Improve-slave-cyclic-DMA-engine-documentation.patch @@ -0,0 +1,279 @@ +From 8c0defafbf160e399767547d7b08b19fba273026 Mon Sep 17 00:00:00 2001 +From: Russell King - ARM Linux <linux@arm.linux.org.uk> +Date: Tue, 26 Jul 2011 14:25:10 +0100 +Subject: Improve slave/cyclic DMA engine documentation + +Improve the documentation for the slave and cyclic DMA engine support +reformatting it for easier reading, adding further APIs, splitting it +into five steps, and including references to the documentation in +dmaengine.h. + +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +[Fixed the index title to reflect new changes] +Signed-off-by: Vinod Koul <vinod.koul@intel.com> +(cherry picked from commit 5a42fb93e6a33224774786691027ef2d9795c245) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + Documentation/dmaengine.txt | 234 +++++++++++++++++++++++++++++++------------- + 1 file changed, 164 insertions(+), 70 deletions(-) + +diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt +index 5a0cb1e..94b7e0f 100644 +--- a/Documentation/dmaengine.txt ++++ b/Documentation/dmaengine.txt +@@ -10,87 +10,181 @@ NOTE: For DMA Engine usage in async_tx please see: + Below is a guide to device driver writers on how to use the Slave-DMA API of the + DMA Engine. This is applicable only for slave DMA usage only. + +-The slave DMA usage consists of following steps ++The slave DMA usage consists of following steps: + 1. Allocate a DMA slave channel + 2. Set slave and controller specific parameters + 3. Get a descriptor for transaction +-4. Submit the transaction and wait for callback notification ++4. Submit the transaction ++5. Issue pending requests and wait for callback notification + + 1. Allocate a DMA slave channel +-Channel allocation is slightly different in the slave DMA context, client +-drivers typically need a channel from a particular DMA controller only and even +-in some cases a specific channel is desired. To request a channel +-dma_request_channel() API is used. +- +-Interface: +-struct dma_chan *dma_request_channel(dma_cap_mask_t mask, +- dma_filter_fn filter_fn, +- void *filter_param); +-where dma_filter_fn is defined as: +-typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); +- +-When the optional 'filter_fn' parameter is set to NULL dma_request_channel +-simply returns the first channel that satisfies the capability mask. Otherwise, +-when the mask parameter is insufficient for specifying the necessary channel, +-the filter_fn routine can be used to disposition the available channels in the +-system. The filter_fn routine is called once for each free channel in the +-system. Upon seeing a suitable channel filter_fn returns DMA_ACK which flags +-that channel to be the return value from dma_request_channel. A channel +-allocated via this interface is exclusive to the caller, until +-dma_release_channel() is called. ++ ++ Channel allocation is slightly different in the slave DMA context, ++ client drivers typically need a channel from a particular DMA ++ controller only and even in some cases a specific channel is desired. ++ To request a channel dma_request_channel() API is used. ++ ++ Interface: ++ struct dma_chan *dma_request_channel(dma_cap_mask_t mask, ++ dma_filter_fn filter_fn, ++ void *filter_param); ++ where dma_filter_fn is defined as: ++ typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); ++ ++ The 'filter_fn' parameter is optional, but highly recommended for ++ slave and cyclic channels as they typically need to obtain a specific ++ DMA channel. ++ ++ When the optional 'filter_fn' parameter is NULL, dma_request_channel() ++ simply returns the first channel that satisfies the capability mask. ++ ++ Otherwise, the 'filter_fn' routine will be called once for each free ++ channel which has a capability in 'mask'. 'filter_fn' is expected to ++ return 'true' when the desired DMA channel is found. ++ ++ A channel allocated via this interface is exclusive to the caller, ++ until dma_release_channel() is called. + + 2. Set slave and controller specific parameters +-Next step is always to pass some specific information to the DMA driver. Most of +-the generic information which a slave DMA can use is in struct dma_slave_config. +-It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA +-burst lengths etc. If some DMA controllers have more parameters to be sent then +-they should try to embed struct dma_slave_config in their controller specific +-structure. That gives flexibility to client to pass more parameters, if +-required. +- +-Interface: +-int dmaengine_slave_config(struct dma_chan *chan, +- struct dma_slave_config *config) ++ ++ Next step is always to pass some specific information to the DMA ++ driver. Most of the generic information which a slave DMA can use ++ is in struct dma_slave_config. This allows the clients to specify ++ DMA direction, DMA addresses, bus widths, DMA burst lengths etc ++ for the peripheral. ++ ++ If some DMA controllers have more parameters to be sent then they ++ should try to embed struct dma_slave_config in their controller ++ specific structure. That gives flexibility to client to pass more ++ parameters, if required. ++ ++ Interface: ++ int dmaengine_slave_config(struct dma_chan *chan, ++ struct dma_slave_config *config) ++ ++ Please see the dma_slave_config structure definition in dmaengine.h ++ for a detailed explaination of the struct members. Please note ++ that the 'direction' member will be going away as it duplicates the ++ direction given in the prepare call. + + 3. Get a descriptor for transaction +-For slave usage the various modes of slave transfers supported by the +-DMA-engine are: +-slave_sg - DMA a list of scatter gather buffers from/to a peripheral +-dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the ++ ++ For slave usage the various modes of slave transfers supported by the ++ DMA-engine are: ++ ++ slave_sg - DMA a list of scatter gather buffers from/to a peripheral ++ dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the + operation is explicitly stopped. +-The non NULL return of this transfer API represents a "descriptor" for the given +-transaction. +- +-Interface: +-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)( +- struct dma_chan *chan, +- struct scatterlist *dst_sg, unsigned int dst_nents, +- struct scatterlist *src_sg, unsigned int src_nents, ++ ++ A non-NULL return of this transfer API represents a "descriptor" for ++ the given transaction. ++ ++ Interface: ++ struct dma_async_tx_descriptor *(*chan->device->device_prep_slave_sg)( ++ struct dma_chan *chan, struct scatterlist *sgl, ++ unsigned int sg_len, enum dma_data_direction direction, + unsigned long flags); +-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( ++ ++ struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_data_direction direction); + +-4. Submit the transaction and wait for callback notification +-To schedule the transaction to be scheduled by dma device, the "descriptor" +-returned in above (3) needs to be submitted. +-To tell the dma driver that a transaction is ready to be serviced, the +-descriptor->submit() callback needs to be invoked. This chains the descriptor to +-the pending queue. +-The transactions in the pending queue can be activated by calling the +-issue_pending API. If channel is idle then the first transaction in queue is +-started and subsequent ones queued up. +-On completion of the DMA operation the next in queue is submitted and a tasklet +-triggered. The tasklet would then call the client driver completion callback +-routine for notification, if set. +-Interface: +-void dma_async_issue_pending(struct dma_chan *chan); +- +-============================================================================== +- +-Additional usage notes for dma driver writers +-1/ Although DMA engine specifies that completion callback routines cannot submit +-any new operations, but typically for slave DMA subsequent transaction may not +-be available for submit prior to callback routine being called. This requirement +-is not a requirement for DMA-slave devices. But they should take care to drop +-the spin-lock they might be holding before calling the callback routine ++ The peripheral driver is expected to have mapped the scatterlist for ++ the DMA operation prior to calling device_prep_slave_sg, and must ++ keep the scatterlist mapped until the DMA operation has completed. ++ The scatterlist must be mapped using the DMA struct device. So, ++ normal setup should look like this: ++ ++ nr_sg = dma_map_sg(chan->device->dev, sgl, sg_len); ++ if (nr_sg == 0) ++ /* error */ ++ ++ desc = chan->device->device_prep_slave_sg(chan, sgl, nr_sg, ++ direction, flags); ++ ++ Once a descriptor has been obtained, the callback information can be ++ added and the descriptor must then be submitted. Some DMA engine ++ drivers may hold a spinlock between a successful preparation and ++ submission so it is important that these two operations are closely ++ paired. ++ ++ Note: ++ Although the async_tx API specifies that completion callback ++ routines cannot submit any new operations, this is not the ++ case for slave/cyclic DMA. ++ ++ For slave DMA, the subsequent transaction may not be available ++ for submission prior to callback function being invoked, so ++ slave DMA callbacks are permitted to prepare and submit a new ++ transaction. ++ ++ For cyclic DMA, a callback function may wish to terminate the ++ DMA via dmaengine_terminate_all(). ++ ++ Therefore, it is important that DMA engine drivers drop any ++ locks before calling the callback function which may cause a ++ deadlock. ++ ++ Note that callbacks will always be invoked from the DMA ++ engines tasklet, never from interrupt context. ++ ++4. Submit the transaction ++ ++ Once the descriptor has been prepared and the callback information ++ added, it must be placed on the DMA engine drivers pending queue. ++ ++ Interface: ++ dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) ++ ++ This returns a cookie can be used to check the progress of DMA engine ++ activity via other DMA engine calls not covered in this document. ++ ++ dmaengine_submit() will not start the DMA operation, it merely adds ++ it to the pending queue. For this, see step 5, dma_async_issue_pending. ++ ++5. Issue pending DMA requests and wait for callback notification ++ ++ The transactions in the pending queue can be activated by calling the ++ issue_pending API. If channel is idle then the first transaction in ++ queue is started and subsequent ones queued up. ++ ++ On completion of each DMA operation, the next in queue is started and ++ a tasklet triggered. The tasklet will then call the client driver ++ completion callback routine for notification, if set. ++ ++ Interface: ++ void dma_async_issue_pending(struct dma_chan *chan); ++ ++Further APIs: ++ ++1. int dmaengine_terminate_all(struct dma_chan *chan) ++ ++ This causes all activity for the DMA channel to be stopped, and may ++ discard data in the DMA FIFO which hasn't been fully transferred. ++ No callback functions will be called for any incomplete transfers. ++ ++2. int dmaengine_pause(struct dma_chan *chan) ++ ++ This pauses activity on the DMA channel without data loss. ++ ++3. int dmaengine_resume(struct dma_chan *chan) ++ ++ Resume a previously paused DMA channel. It is invalid to resume a ++ channel which is not currently paused. ++ ++4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, ++ dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) ++ ++ This can be used to check the status of the channel. Please see ++ the documentation in include/linux/dmaengine.h for a more complete ++ description of this API. ++ ++ This can be used in conjunction with dma_async_is_complete() and ++ the cookie returned from 'descriptor->submit()' to check for ++ completion of a specific DMA transaction. ++ ++ Note: ++ Not all DMA engine drivers can return reliable information for ++ a running DMA channel. It is recommended that DMA engine users ++ pause or stop (via dmaengine_terminate_all) the channel before ++ using this API. +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0005-dmaengine-use-DEFINE_IDR-for-static-initialization.patch b/patches.kzm9g/0005-dmaengine-use-DEFINE_IDR-for-static-initialization.patch new file mode 100644 index 00000000000000..d954e2422daa19 --- /dev/null +++ b/patches.kzm9g/0005-dmaengine-use-DEFINE_IDR-for-static-initialization.patch @@ -0,0 +1,47 @@ +From b30e6b9e041ba92ec2ce074eff1e7094e047f036 Mon Sep 17 00:00:00 2001 +From: Axel Lin <axel.lin@gmail.com> +Date: Wed, 20 Jul 2011 11:32:28 +0800 +Subject: dmaengine: use DEFINE_IDR for static initialization + +We could use DEFINE_IDR for statically allocated idr +that allow us to save a few lines of code. + +And also remove unneeded mutex_init() for dma_list_mutex, as +dma_list_mutex is initialized automatically by DEFINE_MUTEX(). + +Signed-off-by: Axel Lin <axel.lin@gmail.com> +Signed-off-by: Dan Williams <dan.j.williams@intel.com> +(cherry picked from commit 21ef4b8b7a7d59a995bf44382de38c95587767d4) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/dmaengine.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c +index 26374b2..b48967b 100644 +--- a/drivers/dma/dmaengine.c ++++ b/drivers/dma/dmaengine.c +@@ -62,9 +62,9 @@ + #include <linux/slab.h> + + static DEFINE_MUTEX(dma_list_mutex); ++static DEFINE_IDR(dma_idr); + static LIST_HEAD(dma_device_list); + static long dmaengine_ref_count; +-static struct idr dma_idr; + + /* --- sysfs implementation --- */ + +@@ -1050,8 +1050,6 @@ EXPORT_SYMBOL_GPL(dma_run_dependencies); + + static int __init dma_bus_init(void) + { +- idr_init(&dma_idr); +- mutex_init(&dma_list_mutex); + return class_register(&dma_devclass); + } + arch_initcall(dma_bus_init); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0006-dmaengine-add-helper-function-for-slave_single.patch b/patches.kzm9g/0006-dmaengine-add-helper-function-for-slave_single.patch new file mode 100644 index 00000000000000..f16c73a718e7dc --- /dev/null +++ b/patches.kzm9g/0006-dmaengine-add-helper-function-for-slave_single.patch @@ -0,0 +1,51 @@ +From 1259f8b41cee5c445fd905087ec351f3e3f6524d Mon Sep 17 00:00:00 2001 +From: Vinod Koul <vinod.koul@intel.com> +Date: Mon, 25 Jul 2011 19:57:52 +0530 +Subject: dmaengine: add helper function for slave_single + +For clients which require a single slave transfer and dont want to be bothered +about the scatterlist api, this helper gives simple API for this transfer and +creates single scatterlist for DMA API + +Idea from Russell King + +Signed-off-by: Vinod Koul <vinod.koul@intel.com> +(cherry picked from commit 90b44f8ffdf6c66d190ee71b330009bf7f11a208) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/dmaengine.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 8bf1032..2ae9e01 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -24,6 +24,7 @@ + #include <linux/device.h> + #include <linux/uio.h> + #include <linux/dma-mapping.h> ++#include <linux/scatterlist.h> + + struct scatterlist; + +@@ -519,6 +520,16 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, + (unsigned long)config); + } + ++static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( ++ struct dma_chan *chan, void *buf, size_t len, ++ enum dma_data_direction dir, unsigned long flags) ++{ ++ struct scatterlist sg; ++ sg_init_one(&sg, buf, len); ++ ++ return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags); ++} ++ + static inline int dmaengine_terminate_all(struct dma_chan *chan) + { + return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0007-dmaengine-remove-struct-scatterlist-for-header.patch b/patches.kzm9g/0007-dmaengine-remove-struct-scatterlist-for-header.patch new file mode 100644 index 00000000000000..90fd360233b3bf --- /dev/null +++ b/patches.kzm9g/0007-dmaengine-remove-struct-scatterlist-for-header.patch @@ -0,0 +1,37 @@ +From d8000e0bf432de5c7bb8454e660c6d6d75f7df0c Mon Sep 17 00:00:00 2001 +From: Vinod Koul <vinod.koul@intel.com> +Date: Tue, 9 Aug 2011 10:08:10 +0530 +Subject: dmaengine: remove struct scatterlist for header + +Commit 90b44f8 introduces dmaengine_prep_slave_single API which adds +scatterlist.h in dmaengine.h, so defining struct scatterlist is not required + +Signed-off-by: Vinod Koul <vinod.koul@intel.com> +Acked-by: Dan Williams <dan.j.williams@intel.com> +(cherry picked from commit a16e470caa173d323ef68dcac98c899b95fa4f84) + +Conflicts: + + include/linux/dmaengine.h + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/dmaengine.h | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 2ae9e01..0d079a4 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -26,8 +26,6 @@ + #include <linux/dma-mapping.h> + #include <linux/scatterlist.h> + +-struct scatterlist; +- + /** + * typedef dma_cookie_t - an opaque DMA cookie + * +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0008-dmaengine-add-new-enum-dma_transfer_direction.patch b/patches.kzm9g/0008-dmaengine-add-new-enum-dma_transfer_direction.patch new file mode 100644 index 00000000000000..24bd2ec0feaa0f --- /dev/null +++ b/patches.kzm9g/0008-dmaengine-add-new-enum-dma_transfer_direction.patch @@ -0,0 +1,83 @@ +From f506f696ecb0ca3f9f34ea0bffbece7ed2c79342 Mon Sep 17 00:00:00 2001 +From: Vinod Koul <vinod.koul@linux.intel.com> +Date: Thu, 13 Oct 2011 15:15:27 +0530 +Subject: dmaengine: add new enum dma_transfer_direction + +This new enum removes usage of dma_data_direction for dma direction. The new +enum cleans tells the DMA direction and mode +This further paves way for merging the dmaengine _prep operations and also for +interleaved dma + +Suggested-by: Jassi Brar <jaswinder.singh@linaro.org> +Reviewed-by: Barry Song <Baohua.Song@csr.com> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 49920bc66984a512f4bcc7735a61642cd0e4d6f2) + +Conflicts: + + include/linux/dmaengine.h + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/dmaengine.h | 21 +++++++++++++++++---- + 1 file changed, 17 insertions(+), 4 deletions(-) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 0d079a4..7a51acb 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -75,6 +75,19 @@ enum dma_transaction_type { + /* last transaction type for creation of the capabilities mask */ + #define DMA_TX_TYPE_END (DMA_CYCLIC + 1) + ++/** ++ * enum dma_transfer_direction - dma transfer mode and direction indicator ++ * @DMA_MEM_TO_MEM: Async/Memcpy mode ++ * @DMA_MEM_TO_DEV: Slave mode & From Memory to Device ++ * @DMA_DEV_TO_MEM: Slave mode & From Device to Memory ++ * @DMA_DEV_TO_DEV: Slave mode & From Device to Device ++ */ ++enum dma_transfer_direction { ++ DMA_MEM_TO_MEM, ++ DMA_MEM_TO_DEV, ++ DMA_DEV_TO_MEM, ++ DMA_DEV_TO_DEV, ++}; + + /** + * enum dma_ctrl_flags - DMA flags to augment operation preparation, +@@ -267,7 +280,7 @@ enum dma_slave_buswidth { + * struct, if applicable. + */ + struct dma_slave_config { +- enum dma_data_direction direction; ++ enum dma_transfer_direction direction; + dma_addr_t src_addr; + dma_addr_t dst_addr; + enum dma_slave_buswidth src_addr_width; +@@ -490,11 +503,11 @@ struct dma_device { + + struct dma_async_tx_descriptor *(*device_prep_slave_sg)( + struct dma_chan *chan, struct scatterlist *sgl, +- unsigned int sg_len, enum dma_data_direction direction, ++ unsigned int sg_len, enum dma_transfer_direction direction, + unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, +- size_t period_len, enum dma_data_direction direction); ++ size_t period_len, enum dma_transfer_direction direction); + int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg); + +@@ -520,7 +533,7 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, + + static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( + struct dma_chan *chan, void *buf, size_t len, +- enum dma_data_direction dir, unsigned long flags) ++ enum dma_transfer_direction dir, unsigned long flags) + { + struct scatterlist sg; + sg_init_one(&sg, buf, len); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0009-linux-dmaengine.h-fix-implicit-use-of-bitmap.h-and-a.patch b/patches.kzm9g/0009-linux-dmaengine.h-fix-implicit-use-of-bitmap.h-and-a.patch new file mode 100644 index 00000000000000..7845d6bbf189ba --- /dev/null +++ b/patches.kzm9g/0009-linux-dmaengine.h-fix-implicit-use-of-bitmap.h-and-a.patch @@ -0,0 +1,45 @@ +From 7f472b5f26b7ca5024aa78e636ecce48c03c3dc2 Mon Sep 17 00:00:00 2001 +From: Paul Gortmaker <paul.gortmaker@windriver.com> +Date: Fri, 29 Jul 2011 16:55:11 +1000 +Subject: linux/dmaengine.h: fix implicit use of bitmap.h and asm/page.h + +The implicit presence of module.h and all its sub-includes was +masking these implicit header usages: + +include/linux/dmaengine.h:684: warning: 'struct page' declared inside parameter list +include/linux/dmaengine.h:684: warning: its scope is only this definition or declaration, which is probably not what you want +include/linux/dmaengine.h:687: warning: 'struct page' declared inside parameter list +include/linux/dmaengine.h:736:2: error: implicit declaration of function 'bitmap_zero' + +With input from Stephen Rothwell <sfr@canb.auug.org.au> + +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +(cherry picked from commit a8efa9d6bf00fbe9597dd3352dc062a998bf9b15) + +Conflicts: + + include/linux/dmaengine.h + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/dmaengine.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 7a51acb..79d6881 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -25,6 +25,10 @@ + #include <linux/uio.h> + #include <linux/dma-mapping.h> + #include <linux/scatterlist.h> ++#include <linux/bitmap.h> ++#include <asm/page.h> ++ ++struct scatterlist; + + /** + * typedef dma_cookie_t - an opaque DMA cookie +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0010-DMAEngine-Define-interleaved-transfer-request-api.patch b/patches.kzm9g/0010-DMAEngine-Define-interleaved-transfer-request-api.patch new file mode 100644 index 00000000000000..53cc2f6ec6fba3 --- /dev/null +++ b/patches.kzm9g/0010-DMAEngine-Define-interleaved-transfer-request-api.patch @@ -0,0 +1,192 @@ +From c6e7f820f97455f1f4320f3a9a925ee9e3a9c0c1 Mon Sep 17 00:00:00 2001 +From: Jassi Brar <jaswinder.singh@linaro.org> +Date: Thu, 13 Oct 2011 12:33:30 +0530 +Subject: DMAEngine: Define interleaved transfer request api + +Define a new api that could be used for doing fancy data transfers +like interleaved to contiguous copy and vice-versa. +Traditional SG_list based transfers tend to be very inefficient in +such cases as where the interleave and chunk are only a few bytes, +which call for a very condensed api to convey pattern of the transfer. +This api supports all 4 variants of scatter-gather and contiguous transfer. + +Of course, neither can this api help transfers that don't lend to DMA by +nature, i.e, scattered tiny read/writes with no periodic pattern. + +Also since now we support SLAVE channels that might not provide +device_prep_slave_sg callback but device_prep_interleaved_dma, +remove the BUG_ON check. + +Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org> +Acked-by: Barry Song <Baohua.Song@csr.com> +[renamed dmaxfer_template to dma_interleaved_template + did fixup after the enum dma_transfer_merge] +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit b14dab792dee3245b628e046d80a7fad5573fea6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + Documentation/dmaengine.txt | 8 +++++ + drivers/dma/dmaengine.c | 4 +-- + include/linux/dmaengine.h | 78 +++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 85 insertions(+), 5 deletions(-) + +diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt +index 94b7e0f..bbe6cb3 100644 +--- a/Documentation/dmaengine.txt ++++ b/Documentation/dmaengine.txt +@@ -75,6 +75,10 @@ The slave DMA usage consists of following steps: + slave_sg - DMA a list of scatter gather buffers from/to a peripheral + dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the + operation is explicitly stopped. ++ interleaved_dma - This is common to Slave as well as M2M clients. For slave ++ address of devices' fifo could be already known to the driver. ++ Various types of operations could be expressed by setting ++ appropriate values to the 'dma_interleaved_template' members. + + A non-NULL return of this transfer API represents a "descriptor" for + the given transaction. +@@ -89,6 +93,10 @@ The slave DMA usage consists of following steps: + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_data_direction direction); + ++ struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( ++ struct dma_chan *chan, struct dma_interleaved_template *xt, ++ unsigned long flags); ++ + The peripheral driver is expected to have mapped the scatterlist for + the DMA operation prior to calling device_prep_slave_sg, and must + keep the scatterlist mapped until the DMA operation has completed. +diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c +index b48967b..a6c6051 100644 +--- a/drivers/dma/dmaengine.c ++++ b/drivers/dma/dmaengine.c +@@ -693,12 +693,12 @@ int dma_async_device_register(struct dma_device *device) + !device->device_prep_dma_interrupt); + BUG_ON(dma_has_cap(DMA_SG, device->cap_mask) && + !device->device_prep_dma_sg); +- BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && +- !device->device_prep_slave_sg); + BUG_ON(dma_has_cap(DMA_CYCLIC, device->cap_mask) && + !device->device_prep_dma_cyclic); + BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && + !device->device_control); ++ BUG_ON(dma_has_cap(DMA_INTERLEAVE, device->cap_mask) && ++ !device->device_prep_interleaved_dma); + + BUG_ON(!device->device_alloc_chan_resources); + BUG_ON(!device->device_free_chan_resources); +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 79d6881..3489430 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -74,10 +74,10 @@ enum dma_transaction_type { + DMA_ASYNC_TX, + DMA_SLAVE, + DMA_CYCLIC, +-}; +- ++ DMA_INTERLEAVE, + /* last transaction type for creation of the capabilities mask */ +-#define DMA_TX_TYPE_END (DMA_CYCLIC + 1) ++ DMA_TX_TYPE_END, ++}; + + /** + * enum dma_transfer_direction - dma transfer mode and direction indicator +@@ -94,6 +94,74 @@ enum dma_transfer_direction { + }; + + /** ++ * Interleaved Transfer Request ++ * ---------------------------- ++ * A chunk is collection of contiguous bytes to be transfered. ++ * The gap(in bytes) between two chunks is called inter-chunk-gap(ICG). ++ * ICGs may or maynot change between chunks. ++ * A FRAME is the smallest series of contiguous {chunk,icg} pairs, ++ * that when repeated an integral number of times, specifies the transfer. ++ * A transfer template is specification of a Frame, the number of times ++ * it is to be repeated and other per-transfer attributes. ++ * ++ * Practically, a client driver would have ready a template for each ++ * type of transfer it is going to need during its lifetime and ++ * set only 'src_start' and 'dst_start' before submitting the requests. ++ * ++ * ++ * | Frame-1 | Frame-2 | ~ | Frame-'numf' | ++ * |====....==.===...=...|====....==.===...=...| ~ |====....==.===...=...| ++ * ++ * == Chunk size ++ * ... ICG ++ */ ++ ++/** ++ * struct data_chunk - Element of scatter-gather list that makes a frame. ++ * @size: Number of bytes to read from source. ++ * size_dst := fn(op, size_src), so doesn't mean much for destination. ++ * @icg: Number of bytes to jump after last src/dst address of this ++ * chunk and before first src/dst address for next chunk. ++ * Ignored for dst(assumed 0), if dst_inc is true and dst_sgl is false. ++ * Ignored for src(assumed 0), if src_inc is true and src_sgl is false. ++ */ ++struct data_chunk { ++ size_t size; ++ size_t icg; ++}; ++ ++/** ++ * struct dma_interleaved_template - Template to convey DMAC the transfer pattern ++ * and attributes. ++ * @src_start: Bus address of source for the first chunk. ++ * @dst_start: Bus address of destination for the first chunk. ++ * @dir: Specifies the type of Source and Destination. ++ * @src_inc: If the source address increments after reading from it. ++ * @dst_inc: If the destination address increments after writing to it. ++ * @src_sgl: If the 'icg' of sgl[] applies to Source (scattered read). ++ * Otherwise, source is read contiguously (icg ignored). ++ * Ignored if src_inc is false. ++ * @dst_sgl: If the 'icg' of sgl[] applies to Destination (scattered write). ++ * Otherwise, destination is filled contiguously (icg ignored). ++ * Ignored if dst_inc is false. ++ * @numf: Number of frames in this template. ++ * @frame_size: Number of chunks in a frame i.e, size of sgl[]. ++ * @sgl: Array of {chunk,icg} pairs that make up a frame. ++ */ ++struct dma_interleaved_template { ++ dma_addr_t src_start; ++ dma_addr_t dst_start; ++ enum dma_transfer_direction dir; ++ bool src_inc; ++ bool dst_inc; ++ bool src_sgl; ++ bool dst_sgl; ++ size_t numf; ++ size_t frame_size; ++ struct data_chunk sgl[0]; ++}; ++ ++/** + * enum dma_ctrl_flags - DMA flags to augment operation preparation, + * control completion, and communicate status. + * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of +@@ -448,6 +516,7 @@ struct dma_tx_state { + * @device_prep_dma_cyclic: prepare a cyclic dma operation suitable for audio. + * The function takes a buffer of size buf_len. The callback function will + * be called after period_len bytes have been transferred. ++ * @device_prep_interleaved_dma: Transfer expression in a generic way. + * @device_control: manipulate all pending operations on a channel, returns + * zero or error code + * @device_tx_status: poll for transaction completion, the optional +@@ -512,6 +581,9 @@ struct dma_device { + struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction); ++ struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( ++ struct dma_chan *chan, struct dma_interleaved_template *xt, ++ unsigned long flags); + int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg); + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0011-dmaengine-add-DMA_TRANS_NONE-to-dma_transfer_directi.patch b/patches.kzm9g/0011-dmaengine-add-DMA_TRANS_NONE-to-dma_transfer_directi.patch new file mode 100644 index 00000000000000..b3bc13296a62a5 --- /dev/null +++ b/patches.kzm9g/0011-dmaengine-add-DMA_TRANS_NONE-to-dma_transfer_directi.patch @@ -0,0 +1,60 @@ +From d063219e6c8f9f5ec4f6b03c874f0e77d4ffc686 Mon Sep 17 00:00:00 2001 +From: Shawn Guo <shawn.guo@linaro.org> +Date: Tue, 13 Dec 2011 23:48:03 +0800 +Subject: dmaengine: add DMA_TRANS_NONE to dma_transfer_direction +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Before dma_transfer_direction was introduced to replace +dma_data_direction, some dmaengine device uses DMA_NONE of +dma_data_direction for some talk with its client drivers. +The mxs-dma and its clients mxs-mmc and gpmi-nand are such case. + +This patch adds DMA_TRANS_NONE to dma_transfer_direction and +migrate the DMA_NONE use in mxs-dma to it. + +It also fixes the compile warning below. + +CC drivers/dma/mxs-dma.o +drivers/dma/mxs-dma.c: In function ‘mxs_dma_prep_slave_sg’: +drivers/dma/mxs-dma.c:420:16: warning: comparison between ‘enum dma_transfer_direction’ and ‘enum dma_data_direction’ + +Signed-off-by: Shawn Guo <shawn.guo@linaro.org> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 62268ce9170c5466332c046ff6ddafcb67751502) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/mxs-dma.c | 2 +- + include/linux/dmaengine.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c +index 88aad4f..428903d 100644 +--- a/drivers/dma/mxs-dma.c ++++ b/drivers/dma/mxs-dma.c +@@ -412,7 +412,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( + idx = 0; + } + +- if (direction == DMA_NONE) { ++ if (direction == DMA_TRANS_NONE) { + ccw = &mxs_chan->ccw[idx++]; + pio = (u32 *) sgl; + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 3489430..18e71fd 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -91,6 +91,7 @@ enum dma_transfer_direction { + DMA_MEM_TO_DEV, + DMA_DEV_TO_MEM, + DMA_DEV_TO_DEV, ++ DMA_TRANS_NONE, + }; + + /** +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0012-dmaengine-Add-flow-controller-information-to-dma_sla.patch b/patches.kzm9g/0012-dmaengine-Add-flow-controller-information-to-dma_sla.patch new file mode 100644 index 00000000000000..11538f96799a0c --- /dev/null +++ b/patches.kzm9g/0012-dmaengine-Add-flow-controller-information-to-dma_sla.patch @@ -0,0 +1,59 @@ +From f7b36b70b02e3a82938758b9975c41dbe6aa331d Mon Sep 17 00:00:00 2001 +From: Viresh Kumar <viresh.kumar@st.com> +Date: Wed, 1 Feb 2012 16:12:18 +0530 +Subject: dmaengine: Add flow controller information to dma_slave_config + +Flow controller is programmable for few controllers and there are few +intelligent peripherals like, Synopsys JPEG controller, that needs to be a flow +controller of DMA transfers on dest side. + +For this, currently two drivers, pl08x and dw_dmac, support flow controller to +be passed from platform to these drivers. + +Perhaps, this should be a part of struct dma_slave_config. This patch adds +another field device_fc to this structure. User drivers must pass this as true +if they want to be flow controller of certain transfers. + +Signed-off-by: Viresh Kumar <viresh.kumar@st.com> +Acked-by: Linus Walleij <linus.walleij@linaro.org> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit dcc043dc0c60046cf6b75ca04a462314cf64e2ba) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/dmaengine.h | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 18e71fd..b8b4a84 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -26,6 +26,7 @@ + #include <linux/dma-mapping.h> + #include <linux/scatterlist.h> + #include <linux/bitmap.h> ++#include <linux/types.h> + #include <asm/page.h> + + struct scatterlist; +@@ -334,6 +335,9 @@ enum dma_slave_buswidth { + * may or may not be applicable on memory sources. + * @dst_maxburst: same as src_maxburst but for destination target + * mutatis mutandis. ++ * @device_fc: Flow Controller Settings. Only valid for slave channels. Fill ++ * with 'true' if peripheral should be flow controller. Direction will be ++ * selected at Runtime. + * + * This struct is passed in as configuration data to a DMA engine + * in order to set up a certain channel for DMA transport at runtime. +@@ -360,6 +364,7 @@ struct dma_slave_config { + enum dma_slave_buswidth dst_addr_width; + u32 src_maxburst; + u32 dst_maxburst; ++ bool device_fc; + }; + + static inline const char *dma_chan_name(struct dma_chan *chan) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0013-dma-dmaengine-Distinguish-between-dmaengine-failed-t.patch b/patches.kzm9g/0013-dma-dmaengine-Distinguish-between-dmaengine-failed-t.patch new file mode 100644 index 00000000000000..25327e73ecd196 --- /dev/null +++ b/patches.kzm9g/0013-dma-dmaengine-Distinguish-between-dmaengine-failed-t.patch @@ -0,0 +1,49 @@ +From 081cbf58313406bddf98861bb72e9d97a9343e83 Mon Sep 17 00:00:00 2001 +From: Fabio Estevam <festevam@gmail.com> +Date: Tue, 21 Feb 2012 12:51:59 -0200 +Subject: dma: dmaengine: Distinguish between 'dmaengine: failed to get' + messages + +The message "dmaengine: failed to get" can come from two possible locations within dmaengine.c. + +In order to distinguish between them, replace "dmaengine" with __func__ string so that the +source function of the error message can be easily identified. + +Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit d8b53489d4c80490a70327fce6657816e33fafb3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/dmaengine.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c +index a6c6051..767bcc3 100644 +--- a/drivers/dma/dmaengine.c ++++ b/drivers/dma/dmaengine.c +@@ -510,8 +510,8 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v + dma_chan_name(chan)); + list_del_rcu(&device->global_node); + } else if (err) +- pr_debug("dmaengine: failed to get %s: (%d)\n", +- dma_chan_name(chan), err); ++ pr_debug("%s: failed to get %s: (%d)\n", ++ __func__, dma_chan_name(chan), err); + else + break; + if (--device->privatecnt == 0) +@@ -564,8 +564,8 @@ void dmaengine_get(void) + list_del_rcu(&device->global_node); + break; + } else if (err) +- pr_err("dmaengine: failed to get %s: (%d)\n", +- dma_chan_name(chan), err); ++ pr_err("%s: failed to get %s: (%d)\n", ++ __func__, dma_chan_name(chan), err); + } + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0014-dmaengine-add-private-header-file.patch b/patches.kzm9g/0014-dmaengine-add-private-header-file.patch new file mode 100644 index 00000000000000..805892068e3e12 --- /dev/null +++ b/patches.kzm9g/0014-dmaengine-add-private-header-file.patch @@ -0,0 +1,87 @@ +From 49799aa5029a873211dda26d311c29fac21e9d58 Mon Sep 17 00:00:00 2001 +From: Russell King - ARM Linux <linux@arm.linux.org.uk> +Date: Tue, 6 Mar 2012 22:34:26 +0000 +Subject: dmaengine: add private header file + +Add a local private header file to contain definitions and declarations +which should only be used by DMA engine drivers. + +We also fix linux/dmaengine.h to use LINUX_DMAENGINE_H to guard against +multiple inclusion. + +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +Tested-by: Linus Walleij <linus.walleij@linaro.org> +Reviewed-by: Linus Walleij <linus.walleij@linaro.org> +Acked-by: Jassi Brar <jassisinghbrar@gmail.com> +[imx-sdma.c & mxs-dma.c] +Tested-by: Shawn Guo <shawn.guo@linaro.org> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit d2ebfb335b0426deb1a4fb14e4e926d81ecd8235) + +Conflicts: + + drivers/dma/amba-pl08x.c + drivers/dma/at_hdmac.c + drivers/dma/coh901318.c + drivers/dma/dw_dmac.c + drivers/dma/ep93xx_dma.c + drivers/dma/fsldma.c + drivers/dma/imx-dma.c + drivers/dma/imx-sdma.c + drivers/dma/intel_mid_dma.c + drivers/dma/ioat/dma.c + drivers/dma/ioat/dma_v2.c + drivers/dma/iop-adma.c + drivers/dma/ipu/ipu_idmac.c + drivers/dma/mpc512x_dma.c + drivers/dma/mv_xor.c + drivers/dma/mxs-dma.c + drivers/dma/pch_dma.c + drivers/dma/pl330.c + drivers/dma/ppc4xx/adma.c + drivers/dma/shdma.c + drivers/dma/ste_dma40.c + drivers/dma/timb_dma.c + drivers/dma/txx9dmac.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/dmaengine.h | 10 ++++++++++ + include/linux/dmaengine.h | 4 ++-- + 2 files changed, 12 insertions(+), 2 deletions(-) + create mode 100644 drivers/dma/dmaengine.h + +diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h +new file mode 100644 +index 0000000..968570d +--- /dev/null ++++ b/drivers/dma/dmaengine.h +@@ -0,0 +1,10 @@ ++/* ++ * The contents of this file are private to DMA engine drivers, and is not ++ * part of the API to be used by DMA engine users. ++ */ ++#ifndef DMAENGINE_H ++#define DMAENGINE_H ++ ++#include <linux/dmaengine.h> ++ ++#endif +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index b8b4a84..56628b2 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -18,8 +18,8 @@ + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +-#ifndef DMAENGINE_H +-#define DMAENGINE_H ++#ifndef LINUX_DMAENGINE_H ++#define LINUX_DMAENGINE_H + + #include <linux/device.h> + #include <linux/uio.h> +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0015-dmaengine-dma_slave-introduce-inline-wrappers.patch b/patches.kzm9g/0015-dmaengine-dma_slave-introduce-inline-wrappers.patch new file mode 100644 index 00000000000000..9acba60907eb7b --- /dev/null +++ b/patches.kzm9g/0015-dmaengine-dma_slave-introduce-inline-wrappers.patch @@ -0,0 +1,79 @@ +From 5a5c8a21c23c048134232d2daf8dc275c26c244d Mon Sep 17 00:00:00 2001 +From: Alexandre Bounine <alexandre.bounine@idt.com> +Date: Thu, 8 Mar 2012 16:11:18 -0500 +Subject: dmaengine/dma_slave: introduce inline wrappers + +Add inline wrappers for device_prep_slave_sg() and device_prep_dma_cyclic() +interfaces to hide new parameter from current users of affected interfaces. +Convert current users to use new wrappers instead of direct calls. +Suggested by Russell King [https://lkml.org/lkml/2012/2/3/269]. + +Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 16052827d98fbc13c31ebad560af4bd53e2b4dd5) + +Conflicts: + + arch/arm/plat-samsung/dma-ops.c + arch/arm/plat-nomadik/include/plat/ste_dma40.h + drivers/media/video/mx3_camera.c + drivers/media/video/timblogiw.c + drivers/mmc/host/atmel-mci.c + drivers/mmc/host/mmci.c + drivers/mmc/host/mxcmmc.c + drivers/mmc/host/mxs-mmc.c + drivers/mmc/host/sh_mmcif.c + drivers/mmc/host/tmio_mmc_dma.c + drivers/mtd/nand/gpmi-nand/gpmi-lib.c + drivers/usb/musb/ux500_dma.c + drivers/net/ethernet/micrel/ks8842.c + drivers/spi/spi-dw-mid.c + drivers/spi/spi-ep93xx.c + drivers/spi/spi-pl022.c + drivers/spi/spi-topcliff-pch.c + drivers/tty/serial/amba-pl011.c + drivers/tty/serial/pch_uart.c + drivers/tty/serial/sh-sci.c + drivers/usb/renesas_usbhs/fifo.c + drivers/video/mx3fb.c + sound/soc/ep93xx/ep93xx-pcm.c + sound/soc/imx/imx-pcm-dma-mx2.c + sound/soc/mxs/mxs-pcm.c + sound/soc/sh/siu_pcm.c + sound/soc/txx9/txx9aclc.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/dmaengine.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 56628b2..ee123d2 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -623,6 +623,22 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( + return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags); + } + ++static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg( ++ struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, ++ enum dma_transfer_direction dir, unsigned long flags) ++{ ++ return chan->device->device_prep_slave_sg(chan, sgl, sg_len, ++ dir, flags); ++} ++ ++static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( ++ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, ++ size_t period_len, enum dma_transfer_direction dir) ++{ ++ return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, ++ period_len, dir); ++} ++ + static inline int dmaengine_terminate_all(struct dma_chan *chan) + { + return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0016-ARM-Add-init_consistent_dma_size.patch b/patches.kzm9g/0016-ARM-Add-init_consistent_dma_size.patch new file mode 100644 index 00000000000000..2679fb0230eaa4 --- /dev/null +++ b/patches.kzm9g/0016-ARM-Add-init_consistent_dma_size.patch @@ -0,0 +1,195 @@ +From 2690e41103fa44c11e9e435bb58121de3cf16350 Mon Sep 17 00:00:00 2001 +From: Jon Medhurst <tixy@yxit.co.uk> +Date: Tue, 2 Aug 2011 17:28:27 +0100 +Subject: ARM: Add init_consistent_dma_size() + +This function can be called during boot to increase the size of the consistent +DMA region above it's default value of 2MB. It must be called before the memory +allocator is initialised, i.e. before any core_initcall. + +Signed-off-by: Jon Medhurst <tixy@yxit.co.uk> +Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org> +(cherry picked from commit 99d1717dd7fecf2b10195b0d864323b952b4eba0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/include/asm/dma-mapping.h | 7 ++++++ + arch/arm/include/asm/memory.h | 9 ------- + arch/arm/mm/dma-mapping.c | 49 +++++++++++++++++++++++++++++--------- + arch/arm/mm/init.c | 9 ------- + 4 files changed, 45 insertions(+), 29 deletions(-) + +diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h +index 4fff837..5f974f2 100644 +--- a/arch/arm/include/asm/dma-mapping.h ++++ b/arch/arm/include/asm/dma-mapping.h +@@ -236,6 +236,13 @@ extern void *dma_alloc_writecombine(struct device *, size_t, dma_addr_t *, + int dma_mmap_writecombine(struct device *, struct vm_area_struct *, + void *, dma_addr_t, size_t); + ++/* ++ * This can be called during boot to increase the size of the consistent ++ * DMA region above it's default value of 2MB. It must be called before the ++ * memory allocator is initialised, i.e. before any core_initcall. ++ */ ++extern void __init init_consistent_dma_size(unsigned long size); ++ + + #ifdef CONFIG_DMABOUNCE + /* +diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h +index af44a8f..0b0aaa4 100644 +--- a/arch/arm/include/asm/memory.h ++++ b/arch/arm/include/asm/memory.h +@@ -77,16 +77,7 @@ + */ + #define IOREMAP_MAX_ORDER 24 + +-/* +- * Size of DMA-consistent memory region. Must be multiple of 2M, +- * between 2MB and 14MB inclusive. +- */ +-#ifndef CONSISTENT_DMA_SIZE +-#define CONSISTENT_DMA_SIZE SZ_2M +-#endif +- + #define CONSISTENT_END (0xffe00000UL) +-#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE) + + #else /* CONFIG_MMU */ + +diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c +index f96d2c7..c6e2c9f 100644 +--- a/arch/arm/mm/dma-mapping.c ++++ b/arch/arm/mm/dma-mapping.c +@@ -18,12 +18,14 @@ + #include <linux/device.h> + #include <linux/dma-mapping.h> + #include <linux/highmem.h> ++#include <linux/slab.h> + + #include <asm/memory.h> + #include <asm/highmem.h> + #include <asm/cacheflush.h> + #include <asm/tlbflush.h> + #include <asm/sizes.h> ++#include <asm/mach/arch.h> + + static u64 get_coherent_dma_mask(struct device *dev) + { +@@ -115,26 +117,41 @@ static void __dma_free_buffer(struct page *page, size_t size) + } + + #ifdef CONFIG_MMU +-/* Sanity check size */ +-#if (CONSISTENT_DMA_SIZE % SZ_2M) +-#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB" +-#endif + +-#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT) +-#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT) +-#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT) ++ ++#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - consistent_base) >> PAGE_SHIFT) ++#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PGDIR_SHIFT) + + /* + * These are the page tables (2MB each) covering uncached, DMA consistent allocations + */ +-static pte_t *consistent_pte[NUM_CONSISTENT_PTES]; ++static pte_t **consistent_pte; ++ ++#ifdef CONSISTENT_DMA_SIZE ++#define DEFAULT_CONSISTENT_DMA_SIZE CONSISTENT_DMA_SIZE ++#else ++#define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M ++#endif ++ ++unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE; ++ ++void __init init_consistent_dma_size(unsigned long size) ++{ ++ unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M); ++ ++ BUG_ON(consistent_pte); /* Check we're called before DMA region init */ ++ BUG_ON(base < VMALLOC_END); ++ ++ /* Grow region to accommodate specified size */ ++ if (base < consistent_base) ++ consistent_base = base; ++} + + #include "vmregion.h" + + static struct arm_vmregion_head consistent_head = { + .vm_lock = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock), + .vm_list = LIST_HEAD_INIT(consistent_head.vm_list), +- .vm_start = CONSISTENT_BASE, + .vm_end = CONSISTENT_END, + }; + +@@ -153,7 +170,17 @@ static int __init consistent_init(void) + pmd_t *pmd; + pte_t *pte; + int i = 0; +- u32 base = CONSISTENT_BASE; ++ unsigned long base = consistent_base; ++ unsigned long num_ptes = (CONSISTENT_END - base) >> PGDIR_SHIFT; ++ ++ consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL); ++ if (!consistent_pte) { ++ pr_err("%s: no memory\n", __func__); ++ return -ENOMEM; ++ } ++ ++ pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END); ++ consistent_head.vm_start = base; + + do { + pgd = pgd_offset(&init_mm, base); +@@ -196,7 +223,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot) + size_t align; + int bit; + +- if (!consistent_pte[0]) { ++ if (!consistent_pte) { + printk(KERN_ERR "%s: not initialised\n", __func__); + dump_stack(); + return NULL; +diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c +index e038b49..db04a3e5 100644 +--- a/arch/arm/mm/init.c ++++ b/arch/arm/mm/init.c +@@ -638,9 +638,6 @@ void __init mem_init(void) + " ITCM : 0x%08lx - 0x%08lx (%4ld kB)\n" + #endif + " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n" +-#ifdef CONFIG_MMU +- " DMA : 0x%08lx - 0x%08lx (%4ld MB)\n" +-#endif + " vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n" + " lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n" + #ifdef CONFIG_HIGHMEM +@@ -659,9 +656,6 @@ void __init mem_init(void) + MLK(ITCM_OFFSET, (unsigned long) itcm_end), + #endif + MLK(FIXADDR_START, FIXADDR_TOP), +-#ifdef CONFIG_MMU +- MLM(CONSISTENT_BASE, CONSISTENT_END), +-#endif + MLM(VMALLOC_START, VMALLOC_END), + MLM(PAGE_OFFSET, (unsigned long)high_memory), + #ifdef CONFIG_HIGHMEM +@@ -684,9 +678,6 @@ void __init mem_init(void) + * be detected at build time already. + */ + #ifdef CONFIG_MMU +- BUILD_BUG_ON(VMALLOC_END > CONSISTENT_BASE); +- BUG_ON(VMALLOC_END > CONSISTENT_BASE); +- + BUILD_BUG_ON(TASK_SIZE > MODULES_VADDR); + BUG_ON(TASK_SIZE > MODULES_VADDR); + #endif +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0017-mmc-add-a-card-hotplug-handler-context.patch b/patches.kzm9g/0017-mmc-add-a-card-hotplug-handler-context.patch new file mode 100644 index 00000000000000..6b31c7b051fa93 --- /dev/null +++ b/patches.kzm9g/0017-mmc-add-a-card-hotplug-handler-context.patch @@ -0,0 +1,55 @@ +From 6ce12292dadb9a6064862a23cbda3ba144de06ff Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Sun, 25 Dec 2011 20:40:03 -0500 +Subject: mmc: add a card hotplug handler context + +SD/MMC controllers provide different card insertion and removal detection +methods. On some of them the controller itself issues an interrupt, on +others polling is used, on yet others auxiliary means are used for this +purpose, e.g., a GPIO IRQ. Further, on some systems one of those methods +can be chosen at driver probing time and configured in software. E.g., on +some systems the SD/MMC controller card hot-plug detection pin can be +configured either as a respective controller functions, or an IRQ-capable +GPIO. To support such flexible configurations a card hot-plug context +is added by this patch. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit b67e198073b2d2f16572f5fa77553fec14775f69) + +Conflicts: + + include/linux/mmc/host.h + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/mmc/host.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h +index 1ee4424..786bd1f 100644 +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -144,6 +144,11 @@ struct mmc_host_ops { + struct mmc_card; + struct device; + ++struct mmc_hotplug { ++ unsigned int irq; ++ void *handler_priv; ++}; ++ + struct mmc_host { + struct device *parent; + struct device class_dev; +@@ -261,6 +266,7 @@ struct mmc_host { + int claim_cnt; /* "claim" nesting count */ + + struct delayed_work detect; ++ struct mmc_hotplug hotplug; + + const struct mmc_bus_ops *bus_ops; /* current bus driver */ + unsigned int bus_refs; /* reference counter */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0018-mmc-add-a-generic-GPIO-card-detect-helper.patch b/patches.kzm9g/0018-mmc-add-a-generic-GPIO-card-detect-helper.patch new file mode 100644 index 00000000000000..e5901c4a52bbd5 --- /dev/null +++ b/patches.kzm9g/0018-mmc-add-a-generic-GPIO-card-detect-helper.patch @@ -0,0 +1,144 @@ +From e9d1edae3f34367442cab71753a0d1e55cbc439b Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Sun, 25 Dec 2011 21:36:02 +0100 +Subject: mmc: add a generic GPIO card-detect helper + +This patch adds a primitive helper to support card hotplug detection on +platforms, where a GPIO, capable of producing interrupts, is used for +detection of card-insertion and -removal events. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 349ab52446772a359bc7e7699cae3880d48fa5c9) + +Conflicts: + + drivers/mmc/core/Makefile + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/core/Makefile | 1 + + drivers/mmc/core/cd-gpio.c | 74 +++++++++++++++++++++++++++++++++++++++++++++ + include/linux/mmc/cd-gpio.h | 19 ++++++++++++ + 3 files changed, 94 insertions(+) + create mode 100644 drivers/mmc/core/cd-gpio.c + create mode 100644 include/linux/mmc/cd-gpio.h + +diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile +index 6395019..274b67c 100644 +--- a/drivers/mmc/core/Makefile ++++ b/drivers/mmc/core/Makefile +@@ -9,4 +9,5 @@ mmc_core-y := core.o bus.o host.o \ + sdio_cis.o sdio_io.o sdio_irq.o \ + quirks.o + ++mmc_core-$(CONFIG_GPIOLIB) += cd-gpio.o + mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o +diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c +new file mode 100644 +index 0000000..082202a +--- /dev/null ++++ b/drivers/mmc/core/cd-gpio.c +@@ -0,0 +1,74 @@ ++/* ++ * Generic GPIO card-detect helper ++ * ++ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de> ++ * ++ * 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. ++ */ ++ ++#include <linux/err.h> ++#include <linux/gpio.h> ++#include <linux/interrupt.h> ++#include <linux/jiffies.h> ++#include <linux/mmc/host.h> ++#include <linux/module.h> ++#include <linux/slab.h> ++ ++struct mmc_cd_gpio { ++ unsigned int gpio; ++ char label[0]; ++}; ++ ++static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id) ++{ ++ /* Schedule a card detection after a debounce timeout */ ++ mmc_detect_change(dev_id, msecs_to_jiffies(100)); ++ return IRQ_HANDLED; ++} ++ ++int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio, ++ unsigned int irq, unsigned long flags) ++{ ++ size_t len = strlen(dev_name(host->parent)) + 4; ++ struct mmc_cd_gpio *cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL); ++ int ret; ++ ++ if (!cd) ++ return -ENOMEM; ++ ++ snprintf(cd->label, len, "%s cd", dev_name(host->parent)); ++ ++ ret = gpio_request_one(gpio, GPIOF_DIR_IN, cd->label); ++ if (ret < 0) ++ goto egpioreq; ++ ++ ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt, ++ flags, cd->label, host); ++ if (ret < 0) ++ goto eirqreq; ++ ++ cd->gpio = gpio; ++ host->hotplug.irq = irq; ++ host->hotplug.handler_priv = cd; ++ ++ return 0; ++ ++eirqreq: ++ gpio_free(gpio); ++egpioreq: ++ kfree(cd); ++ return ret; ++} ++EXPORT_SYMBOL(mmc_cd_gpio_request); ++ ++void mmc_cd_gpio_free(struct mmc_host *host) ++{ ++ struct mmc_cd_gpio *cd = host->hotplug.handler_priv; ++ ++ free_irq(host->hotplug.irq, host); ++ gpio_free(cd->gpio); ++ kfree(cd); ++} ++EXPORT_SYMBOL(mmc_cd_gpio_free); +diff --git a/include/linux/mmc/cd-gpio.h b/include/linux/mmc/cd-gpio.h +new file mode 100644 +index 0000000..a8e4697 +--- /dev/null ++++ b/include/linux/mmc/cd-gpio.h +@@ -0,0 +1,19 @@ ++/* ++ * Generic GPIO card-detect helper header ++ * ++ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de> ++ * ++ * 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 MMC_CD_GPIO_H ++#define MMC_CD_GPIO_H ++ ++struct mmc_host; ++int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio, ++ unsigned int irq, unsigned long flags); ++void mmc_cd_gpio_free(struct mmc_host *host); ++ ++#endif +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0019-mmc-simplify-mmc_cd_gpio_request-by-removing-two-par.patch b/patches.kzm9g/0019-mmc-simplify-mmc_cd_gpio_request-by-removing-two-par.patch new file mode 100644 index 00000000000000..8c85d61ce13f2c --- /dev/null +++ b/patches.kzm9g/0019-mmc-simplify-mmc_cd_gpio_request-by-removing-two-par.patch @@ -0,0 +1,71 @@ +From 6859f92c44996d7337c5d3a1dbfbbb43af00a3c4 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 9 Feb 2012 22:57:07 +0100 +Subject: mmc: simplify mmc_cd_gpio_request() by removing two parameters + +Calculate the IRQ number, using gpio_to_irq() and use fixed flags: trigger +on both edges. This makes two out of four arguments of the +mmc_cd_gpio_request() function redundant. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit c9b0546a59293cabf54c85e1218da595af3274ff) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/core/cd-gpio.c | 13 +++++++++---- + include/linux/mmc/cd-gpio.h | 3 +-- + 2 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c +index 082202a..29de31e 100644 +--- a/drivers/mmc/core/cd-gpio.c ++++ b/drivers/mmc/core/cd-gpio.c +@@ -28,13 +28,17 @@ static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id) + return IRQ_HANDLED; + } + +-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio, +- unsigned int irq, unsigned long flags) ++int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio) + { + size_t len = strlen(dev_name(host->parent)) + 4; +- struct mmc_cd_gpio *cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL); ++ struct mmc_cd_gpio *cd; ++ int irq = gpio_to_irq(gpio); + int ret; + ++ if (irq < 0) ++ return irq; ++ ++ cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL); + if (!cd) + return -ENOMEM; + +@@ -45,7 +49,8 @@ int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio, + goto egpioreq; + + ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt, +- flags, cd->label, host); ++ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, ++ cd->label, host); + if (ret < 0) + goto eirqreq; + +diff --git a/include/linux/mmc/cd-gpio.h b/include/linux/mmc/cd-gpio.h +index a8e4697..cefaba0 100644 +--- a/include/linux/mmc/cd-gpio.h ++++ b/include/linux/mmc/cd-gpio.h +@@ -12,8 +12,7 @@ + #define MMC_CD_GPIO_H + + struct mmc_host; +-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio, +- unsigned int irq, unsigned long flags); ++int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio); + void mmc_cd_gpio_free(struct mmc_host *host); + + #endif +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0020-mmc-Standardize-header-file-inclusion-checks.patch b/patches.kzm9g/0020-mmc-Standardize-header-file-inclusion-checks.patch new file mode 100644 index 00000000000000..560a4ac361d4b7 --- /dev/null +++ b/patches.kzm9g/0020-mmc-Standardize-header-file-inclusion-checks.patch @@ -0,0 +1,65 @@ +From 062b1cec7113d11cddbead31195d74707b9c5bb8 Mon Sep 17 00:00:00 2001 +From: "Robert P. J. Day" <rpjday@crashcourse.ca> +Date: Fri, 27 May 2011 16:04:03 -0400 +Subject: mmc: Standardize header file inclusion checks. + +Standardize the checks for multiple MMC header file inclusion, +including adding comments to terminating #endif's, and fixing +one incorrect comment. + +Signed-off-by: Robert P. J. Day <rpjday@crashcourse.ca> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 100e918610b7487fa18db97b3879cd8d1fdd5974) + +Cherry-picked changes for: + include/linux/mmc/sh_mobile_sdhi.h + include/linux/mmc/tmio.h + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/mmc/sh_mobile_sdhi.h | 6 +++--- + include/linux/mmc/tmio.h | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h +index faf32b6..bd50b36 100644 +--- a/include/linux/mmc/sh_mobile_sdhi.h ++++ b/include/linux/mmc/sh_mobile_sdhi.h +@@ -1,5 +1,5 @@ +-#ifndef __SH_MOBILE_SDHI_H__ +-#define __SH_MOBILE_SDHI_H__ ++#ifndef LINUX_MMC_SH_MOBILE_SDHI_H ++#define LINUX_MMC_SH_MOBILE_SDHI_H + + #include <linux/types.h> + +@@ -17,4 +17,4 @@ struct sh_mobile_sdhi_info { + int (*get_cd)(struct platform_device *pdev); + }; + +-#endif /* __SH_MOBILE_SDHI_H__ */ ++#endif /* LINUX_MMC_SH_MOBILE_SDHI_H */ +diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h +index 19490b9..551490f 100644 +--- a/include/linux/mmc/tmio.h ++++ b/include/linux/mmc/tmio.h +@@ -12,8 +12,8 @@ + * + * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3 + */ +-#ifndef _LINUX_MMC_TMIO_H_ +-#define _LINUX_MMC_TMIO_H_ ++#ifndef LINUX_MMC_TMIO_H ++#define LINUX_MMC_TMIO_H + + #define CTL_SD_CMD 0x00 + #define CTL_ARG_REG 0x04 +@@ -60,4 +60,4 @@ + + #define TMIO_BBS 512 /* Boot block size */ + +-#endif /* _LINUX_MMC_TMIO_H_ */ ++#endif /* LINUX_MMC_TMIO_H */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0021-mmc-tmio-name-0xd8-as-CTL_DMA_ENABLE.patch b/patches.kzm9g/0021-mmc-tmio-name-0xd8-as-CTL_DMA_ENABLE.patch new file mode 100644 index 00000000000000..f218a6469806da --- /dev/null +++ b/patches.kzm9g/0021-mmc-tmio-name-0xd8-as-CTL_DMA_ENABLE.patch @@ -0,0 +1,48 @@ +From 92448997a8190180d93ffc4e48be91a99fca2c41 Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Tue, 21 Jun 2011 08:00:08 +0900 +Subject: mmc: tmio: name 0xd8 as CTL_DMA_ENABLE + +This reflects at least the current usage of this register +and I think it improves the readability of the code ever so slightly. + +Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Magnus Damm <magnus.damm@gmail.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 95c7348d948dc4832434ddfaeba804ac14732f02) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_dma.c | 2 +- + include/linux/mmc/tmio.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c +index 25f1ad6..9c4da66 100644 +--- a/drivers/mmc/host/tmio_mmc_dma.c ++++ b/drivers/mmc/host/tmio_mmc_dma.c +@@ -26,7 +26,7 @@ static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) + { + #if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE) + /* Switch DMA mode on or off - SuperH specific? */ +- writew(enable ? 2 : 0, host->ctl + (0xd8 << host->bus_shift)); ++ writew(enable ? 2 : 0, host->ctl + (CTL_DMA_ENABLE << host->bus_shift)); + #endif + } + +diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h +index 551490f..3ae3776 100644 +--- a/include/linux/mmc/tmio.h ++++ b/include/linux/mmc/tmio.h +@@ -30,6 +30,7 @@ + #define CTL_TRANSACTION_CTL 0x34 + #define CTL_SDIO_STATUS 0x36 + #define CTL_SDIO_IRQ_MASK 0x38 ++#define CTL_DMA_ENABLE 0xd8 + #define CTL_RESET_SD 0xe0 + #define CTL_SDIO_REGS 0x100 + #define CTL_CLK_AND_WAIT_CTL 0x138 +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0022-mmc-tmio-Share-register-access-functions.patch b/patches.kzm9g/0022-mmc-tmio-Share-register-access-functions.patch new file mode 100644 index 00000000000000..05bfa4654dee85 --- /dev/null +++ b/patches.kzm9g/0022-mmc-tmio-Share-register-access-functions.patch @@ -0,0 +1,130 @@ +From 92d89dd2b2076ea2d981596de7753ce0ded0fb17 Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Tue, 21 Jun 2011 08:00:09 +0900 +Subject: mmc: tmio: Share register access functions + +Move register access functions into a shared header. +Use sd_ctrl_write16 in tmio_mmc_dma.c:tmio_mmc_enable_dma(). + +Other than avoiding (trivial) open-coding, the motivation for +this is to allow platform-hooks in access functions to +be applied across all applicable accesses. + +Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Magnus Damm <magnus.damm@gmail.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit a11862d3389d4304211eed0758f510d5e573f93c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 35 +++++++++++++++++++++++++++++++++++ + drivers/mmc/host/tmio_mmc_dma.c | 2 +- + drivers/mmc/host/tmio_mmc_pio.c | 34 ---------------------------------- + 3 files changed, 36 insertions(+), 35 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index 8260bc2..0c22df0 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -134,4 +134,39 @@ int tmio_mmc_host_resume(struct device *dev); + int tmio_mmc_host_runtime_suspend(struct device *dev); + int tmio_mmc_host_runtime_resume(struct device *dev); + ++static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) ++{ ++ return readw(host->ctl + (addr << host->bus_shift)); ++} ++ ++static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, ++ u16 *buf, int count) ++{ ++ readsw(host->ctl + (addr << host->bus_shift), buf, count); ++} ++ ++static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) ++{ ++ return readw(host->ctl + (addr << host->bus_shift)) | ++ readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16; ++} ++ ++static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) ++{ ++ writew(val, host->ctl + (addr << host->bus_shift)); ++} ++ ++static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, ++ u16 *buf, int count) ++{ ++ writesw(host->ctl + (addr << host->bus_shift), buf, count); ++} ++ ++static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) ++{ ++ writew(val, host->ctl + (addr << host->bus_shift)); ++ writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); ++} ++ ++ + #endif +diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c +index 9c4da66..f24a029 100644 +--- a/drivers/mmc/host/tmio_mmc_dma.c ++++ b/drivers/mmc/host/tmio_mmc_dma.c +@@ -26,7 +26,7 @@ static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) + { + #if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE) + /* Switch DMA mode on or off - SuperH specific? */ +- writew(enable ? 2 : 0, host->ctl + (CTL_DMA_ENABLE << host->bus_shift)); ++ sd_ctrl_write16(host, enable ? 2 : 0, CTL_DMA_ENABLE); + #endif + } + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 0b09e82..4d17807 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -46,40 +46,6 @@ + + #include "tmio_mmc.h" + +-static u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) +-{ +- return readw(host->ctl + (addr << host->bus_shift)); +-} +- +-static void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, +- u16 *buf, int count) +-{ +- readsw(host->ctl + (addr << host->bus_shift), buf, count); +-} +- +-static u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) +-{ +- return readw(host->ctl + (addr << host->bus_shift)) | +- readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16; +-} +- +-static void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) +-{ +- writew(val, host->ctl + (addr << host->bus_shift)); +-} +- +-static void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, +- u16 *buf, int count) +-{ +- writesw(host->ctl + (addr << host->bus_shift), buf, count); +-} +- +-static void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) +-{ +- writew(val, host->ctl + (addr << host->bus_shift)); +- writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); +-} +- + void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i) + { + u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) & ~(i & TMIO_MASK_IRQ); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0023-mmc-sdhi-Add-write16_hook.patch b/patches.kzm9g/0023-mmc-sdhi-Add-write16_hook.patch new file mode 100644 index 00000000000000..ae80b0eede9db1 --- /dev/null +++ b/patches.kzm9g/0023-mmc-sdhi-Add-write16_hook.patch @@ -0,0 +1,149 @@ +From 337f49667f11fbdb1bcd1ca51816c812de84123f Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Tue, 21 Jun 2011 08:00:10 +0900 +Subject: mmc: sdhi: Add write16_hook + +Some controllers require waiting for the bus to become idle +before writing to some registers. I have implemented this +by adding a hook to sd_ctrl_write16() and implementing +a hook for SDHI which waits for the bus to become idle. + +Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Magnus Damm <magnus.damm@gmail.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 973ed3af1a570612771ed10dec6506c757767668) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 36 ++++++++++++++++++++++++++++++++++++ + drivers/mmc/host/tmio_mmc.h | 5 +++++ + include/linux/mfd/tmio.h | 8 ++++++++ + include/linux/mmc/tmio.h | 1 + + 4 files changed, 50 insertions(+) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index ce500f0..774f643 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -26,6 +26,7 @@ + #include <linux/mmc/sh_mobile_sdhi.h> + #include <linux/mfd/tmio.h> + #include <linux/sh_dma.h> ++#include <linux/delay.h> + + #include "tmio_mmc.h" + +@@ -55,6 +56,39 @@ static int sh_mobile_sdhi_get_cd(struct platform_device *pdev) + return -ENOSYS; + } + ++static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) ++{ ++ int timeout = 1000; ++ ++ while (--timeout && !(sd_ctrl_read16(host, CTL_STATUS2) & (1 << 13))) ++ udelay(1); ++ ++ if (!timeout) { ++ dev_warn(host->pdata->dev, "timeout waiting for SD bus idle\n"); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) ++{ ++ switch (addr) ++ { ++ case CTL_SD_CMD: ++ case CTL_STOP_INTERNAL_ACTION: ++ case CTL_XFER_BLK_COUNT: ++ case CTL_SD_CARD_CLK_CTL: ++ case CTL_SD_XFER_LEN: ++ case CTL_SD_MEM_CARD_OPT: ++ case CTL_TRANSACTION_CTL: ++ case CTL_DMA_ENABLE: ++ return sh_mobile_sdhi_wait_idle(host); ++ } ++ ++ return 0; ++} ++ + static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + { + struct sh_mobile_sdhi *priv; +@@ -86,6 +120,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + mmc_data->hclk = clk_get_rate(priv->clk); + mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; + mmc_data->get_cd = sh_mobile_sdhi_get_cd; ++ if (mmc_data->flags & TMIO_MMC_HAS_IDLE_WAIT) ++ mmc_data->write16_hook = sh_mobile_sdhi_write16_hook; + mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; + if (p) { + mmc_data->flags = p->tmio_flags; +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index 0c22df0..211ef6e 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -153,6 +153,11 @@ static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) + + static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) + { ++ /* If there is a hook and it returns non-zero then there ++ * is an error and the write should be skipped ++ */ ++ if (host->pdata->write16_hook && host->pdata->write16_hook(host, addr)) ++ return; + writew(val, host->ctl + (addr << host->bus_shift)); + } + +diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h +index 5a90266..0dc9804 100644 +--- a/include/linux/mfd/tmio.h ++++ b/include/linux/mfd/tmio.h +@@ -68,6 +68,11 @@ + * controller and report the event to the driver. + */ + #define TMIO_MMC_HAS_COLD_CD (1 << 3) ++/* ++ * Some controllers require waiting for the SD bus to become ++ * idle before writing to some registers. ++ */ ++#define TMIO_MMC_HAS_IDLE_WAIT (1 << 4) + + int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base); + int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base); +@@ -80,6 +85,8 @@ struct tmio_mmc_dma { + int alignment_shift; + }; + ++struct tmio_mmc_host; ++ + /* + * data for the MMC controller + */ +@@ -94,6 +101,7 @@ struct tmio_mmc_data { + void (*set_pwr)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); + int (*get_cd)(struct platform_device *host); ++ int (*write16_hook)(struct tmio_mmc_host *host, int addr); + }; + + static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata) +diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h +index 3ae3776..a1c1f32 100644 +--- a/include/linux/mmc/tmio.h ++++ b/include/linux/mmc/tmio.h +@@ -21,6 +21,7 @@ + #define CTL_XFER_BLK_COUNT 0xa + #define CTL_RESPONSE 0x0c + #define CTL_STATUS 0x1c ++#define CTL_STATUS2 0x1e + #define CTL_IRQ_MASK 0x20 + #define CTL_SD_CARD_CLK_CTL 0x24 + #define CTL_SD_XFER_LEN 0x26 +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0024-mmc-tmio-Fix-race-condition-resulting-in-spurious-in.patch b/patches.kzm9g/0024-mmc-tmio-Fix-race-condition-resulting-in-spurious-in.patch new file mode 100644 index 00000000000000..3a2ce6eed2ab07 --- /dev/null +++ b/patches.kzm9g/0024-mmc-tmio-Fix-race-condition-resulting-in-spurious-in.patch @@ -0,0 +1,132 @@ +From 95c27915c3f1955092a6cc2e5900a58aa2dfc7c0 Mon Sep 17 00:00:00 2001 +From: Paul Parsons <lost.distance@yahoo.com> +Date: Sun, 15 May 2011 13:24:41 +0000 +Subject: mmc: tmio: Fix race condition resulting in spurious interrupts + +There is a race condition in the tmio_mmc_irq() interrupt handler, +caused by the presence of a while loop, which results in warnings of +spurious interrupts. This was found on an HP iPAQ hx4700 whose HTC +ASIC3 reportedly incorporates the Toshiba TC6380AF controller. + +Towards the end of a multiple read (CMD18) operation the handler clears +the final RXRDY status bit in the first loop iteration, sees the DATAEND +status bit at the bottom of the loop, and so clears the DATAEND status +bit in the second loop iteration. However the DATAEND interrupt is still +queued in the system somewhere and can't be delivered until the handler +has returned. This second interrupt is then reported as spurious in the +next call to the handler. Likewise for single read (CMD17) operations. +And something similar occurs for multiple write (CMD25) and single write +(CMD24) operations, where CMDRESPEND and TXRQ status bits are cleared in +a single call. + +In these cases the interrupt handler clears two separate interrupts when +it should only clear the one interrupt for which it was invoked. The fix +is to remove the while loop. + +Signed-off-by: Paul Parsons <lost.distance@yahoo.com> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit e312eb1e66e4357000e4e7438849d5a5fd738219) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 76 +++++++++++++++++------------------------ + 1 file changed, 32 insertions(+), 44 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 4d17807..f7dd3b1 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -569,58 +569,46 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) + pr_debug_status(status); + pr_debug_status(ireg); + +- if (!ireg) { +- tmio_mmc_disable_mmc_irqs(host, status & ~irq_mask); +- +- pr_warning("tmio_mmc: Spurious irq, disabling! " +- "0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg); +- pr_debug_status(status); +- ++ /* Card insert / remove attempts */ ++ if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) { ++ tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT | ++ TMIO_STAT_CARD_REMOVE); ++ mmc_detect_change(host->mmc, msecs_to_jiffies(100)); + goto out; + } + +- while (ireg) { +- /* Card insert / remove attempts */ +- if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) { +- tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT | +- TMIO_STAT_CARD_REMOVE); +- mmc_detect_change(host->mmc, msecs_to_jiffies(100)); +- } +- +- /* CRC and other errors */ +-/* if (ireg & TMIO_STAT_ERR_IRQ) +- * handled |= tmio_error_irq(host, irq, stat); ++ /* CRC and other errors */ ++/* if (ireg & TMIO_STAT_ERR_IRQ) ++ * handled |= tmio_error_irq(host, irq, stat); + */ + +- /* Command completion */ +- if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) { +- tmio_mmc_ack_mmc_irqs(host, +- TMIO_STAT_CMDRESPEND | +- TMIO_STAT_CMDTIMEOUT); +- tmio_mmc_cmd_irq(host, status); +- } +- +- /* Data transfer */ +- if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) { +- tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ); +- tmio_mmc_pio_irq(host); +- } +- +- /* Data transfer completion */ +- if (ireg & TMIO_STAT_DATAEND) { +- tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND); +- tmio_mmc_data_irq(host); +- } ++ /* Command completion */ ++ if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) { ++ tmio_mmc_ack_mmc_irqs(host, ++ TMIO_STAT_CMDRESPEND | ++ TMIO_STAT_CMDTIMEOUT); ++ tmio_mmc_cmd_irq(host, status); ++ goto out; ++ } + +- /* Check status - keep going until we've handled it all */ +- status = sd_ctrl_read32(host, CTL_STATUS); +- irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK); +- ireg = status & TMIO_MASK_IRQ & ~irq_mask; ++ /* Data transfer */ ++ if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) { ++ tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ); ++ tmio_mmc_pio_irq(host); ++ goto out; ++ } + +- pr_debug("Status at end of loop: %08x\n", status); +- pr_debug_status(status); ++ /* Data transfer completion */ ++ if (ireg & TMIO_STAT_DATAEND) { ++ tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND); ++ tmio_mmc_data_irq(host); ++ goto out; + } +- pr_debug("MMC IRQ end\n"); ++ ++ pr_warning("tmio_mmc: Spurious irq, disabling! " ++ "0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg); ++ pr_debug_status(status); ++ tmio_mmc_disable_mmc_irqs(host, status & ~irq_mask); + + out: + return IRQ_HANDLED; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0025-mmc-tmio-fix-recursive-spinlock-don-t-schedule-with-.patch b/patches.kzm9g/0025-mmc-tmio-fix-recursive-spinlock-don-t-schedule-with-.patch new file mode 100644 index 00000000000000..30f595ec588b1b --- /dev/null +++ b/patches.kzm9g/0025-mmc-tmio-fix-recursive-spinlock-don-t-schedule-with-.patch @@ -0,0 +1,167 @@ +From ea988b80417af51f72b175c2ec36c82b41b08b5d Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 14 Jul 2011 12:12:38 +0200 +Subject: mmc: tmio: fix recursive spinlock, don't schedule with interrupts + disabled + +Calling mmc_request_done() under a spinlock with interrupts disabled +leads to a recursive spin-lock on request retry path and to +scheduling in atomic context. This patch fixes both these problems +by moving mmc_request_done() to the scheduler workqueue. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit b9269fdd4f61aa4d185c982b0f84a3e7b7ccb4d2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 6 +++++- + drivers/mmc/host/tmio_mmc_pio.c | 35 +++++++++++++++++++++++++++++------ + 2 files changed, 34 insertions(+), 7 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index 211ef6e..f0d7c43 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -18,6 +18,7 @@ + + #include <linux/highmem.h> + #include <linux/mmc/tmio.h> ++#include <linux/mutex.h> + #include <linux/pagemap.h> + #include <linux/spinlock.h> + +@@ -73,8 +74,11 @@ struct tmio_mmc_host { + + /* Track lost interrupts */ + struct delayed_work delayed_reset_work; +- spinlock_t lock; ++ struct work_struct done; ++ ++ spinlock_t lock; /* protect host private data */ + unsigned long last_req_ts; ++ struct mutex ios_lock; /* protect set_ios() context */ + }; + + int tmio_mmc_host_probe(struct tmio_mmc_host **host, +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index f7dd3b1..a2f76ad 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -250,10 +250,16 @@ static void tmio_mmc_reset_work(struct work_struct *work) + /* called with host->lock held, interrupts disabled */ + static void tmio_mmc_finish_request(struct tmio_mmc_host *host) + { +- struct mmc_request *mrq = host->mrq; ++ struct mmc_request *mrq; ++ unsigned long flags; + +- if (!mrq) ++ spin_lock_irqsave(&host->lock, flags); ++ ++ mrq = host->mrq; ++ if (IS_ERR_OR_NULL(mrq)) { ++ spin_unlock_irqrestore(&host->lock, flags); + return; ++ } + + host->cmd = NULL; + host->data = NULL; +@@ -262,11 +268,18 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) + cancel_delayed_work(&host->delayed_reset_work); + + host->mrq = NULL; ++ spin_unlock_irqrestore(&host->lock, flags); + +- /* FIXME: mmc_request_done() can schedule! */ + mmc_request_done(host->mmc, mrq); + } + ++static void tmio_mmc_done_work(struct work_struct *work) ++{ ++ struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host, ++ done); ++ tmio_mmc_finish_request(host); ++} ++ + /* These are the bitmasks the tmio chip requires to implement the MMC response + * types. Note that R1 and R6 are the same in this scheme. */ + #define APP_CMD 0x0040 +@@ -433,7 +446,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host) + BUG(); + } + +- tmio_mmc_finish_request(host); ++ schedule_work(&host->done); + } + + static void tmio_mmc_data_irq(struct tmio_mmc_host *host) +@@ -523,7 +536,7 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, + tasklet_schedule(&host->dma_issue); + } + } else { +- tmio_mmc_finish_request(host); ++ schedule_work(&host->done); + } + + out: +@@ -573,7 +586,8 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) + if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) { + tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT | + TMIO_STAT_CARD_REMOVE); +- mmc_detect_change(host->mmc, msecs_to_jiffies(100)); ++ if (!work_pending(&host->mmc->detect.work)) ++ mmc_detect_change(host->mmc, msecs_to_jiffies(100)); + goto out; + } + +@@ -703,6 +717,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + struct tmio_mmc_data *pdata = host->pdata; + unsigned long flags; + ++ mutex_lock(&host->ios_lock); ++ + spin_lock_irqsave(&host->lock, flags); + if (host->mrq) { + if (IS_ERR(host->mrq)) { +@@ -718,6 +734,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + host->mrq->cmd->opcode, host->last_req_ts, jiffies); + } + spin_unlock_irqrestore(&host->lock, flags); ++ ++ mutex_unlock(&host->ios_lock); + return; + } + +@@ -771,6 +789,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + current->comm, task_pid_nr(current), + ios->clock, ios->power_mode); + host->mrq = NULL; ++ ++ mutex_unlock(&host->ios_lock); + } + + static int tmio_mmc_get_ro(struct mmc_host *mmc) +@@ -867,9 +887,11 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + tmio_mmc_enable_sdio_irq(mmc, 0); + + spin_lock_init(&_host->lock); ++ mutex_init(&_host->ios_lock); + + /* Init delayed work for request timeouts */ + INIT_DELAYED_WORK(&_host->delayed_reset_work, tmio_mmc_reset_work); ++ INIT_WORK(&_host->done, tmio_mmc_done_work); + + /* See if we also get DMA */ + tmio_mmc_request_dma(_host, pdata); +@@ -917,6 +939,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) + pm_runtime_get_sync(&pdev->dev); + + mmc_remove_host(host->mmc); ++ cancel_work_sync(&host->done); + cancel_delayed_work_sync(&host->delayed_reset_work); + tmio_mmc_release_dma(host); + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0026-mmc-tmio-maximize-power-saving.patch b/patches.kzm9g/0026-mmc-tmio-maximize-power-saving.patch new file mode 100644 index 00000000000000..5e9aaa562be870 --- /dev/null +++ b/patches.kzm9g/0026-mmc-tmio-maximize-power-saving.patch @@ -0,0 +1,172 @@ +From b3250d284d1eafa128d1955c4142697d9227e9e6 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 14 Jul 2011 12:16:59 +0200 +Subject: mmc: tmio: maximize power saving + +This patch uses runtime PM to allow the system to power down the MMC +controller, when the MMC closk is switched off. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 71d111cd34ee119c93d056ad9e84dc0e82367f82) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 2 ++ + drivers/mmc/host/tmio_mmc_pio.c | 64 ++++++++++++++++++++++++----------------- + 2 files changed, 39 insertions(+), 27 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index f0d7c43..ba0d8e6 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -53,6 +53,8 @@ struct tmio_mmc_host { + void (*set_clk_div)(struct platform_device *host, int state); + + int pm_error; ++ /* recognise system-wide suspend in runtime PM methods */ ++ bool pm_global; + + /* pio related stuff */ + struct scatterlist *sg_ptr; +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index a2f76ad..221ffb7 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -546,6 +546,7 @@ out: + irqreturn_t tmio_mmc_irq(int irq, void *devid) + { + struct tmio_mmc_host *host = devid; ++ struct mmc_host *mmc = host->mmc; + struct tmio_mmc_data *pdata = host->pdata; + unsigned int ireg, irq_mask, status; + unsigned int sdio_ireg, sdio_irq_mask, sdio_status; +@@ -567,13 +568,13 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) + if (sdio_ireg && !host->sdio_irq_enabled) { + pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n", + sdio_status, sdio_irq_mask, sdio_ireg); +- tmio_mmc_enable_sdio_irq(host->mmc, 0); ++ tmio_mmc_enable_sdio_irq(mmc, 0); + goto out; + } + +- if (host->mmc->caps & MMC_CAP_SDIO_IRQ && ++ if (mmc->caps & MMC_CAP_SDIO_IRQ && + sdio_ireg & TMIO_SDIO_STAT_IOIRQ) +- mmc_signal_sdio_irq(host->mmc); ++ mmc_signal_sdio_irq(mmc); + + if (sdio_ireg) + goto out; +@@ -586,7 +587,9 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) + if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) { + tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT | + TMIO_STAT_CARD_REMOVE); +- if (!work_pending(&host->mmc->detect.work)) ++ if ((((ireg & TMIO_STAT_CARD_REMOVE) && mmc->card) || ++ ((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) && ++ !work_pending(&mmc->detect.work)) + mmc_detect_change(host->mmc, msecs_to_jiffies(100)); + goto out; + } +@@ -743,33 +746,30 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + + spin_unlock_irqrestore(&host->lock, flags); + +- if (ios->clock) +- tmio_mmc_set_clock(host, ios->clock); +- +- /* Power sequence - OFF -> UP -> ON */ +- if (ios->power_mode == MMC_POWER_UP) { +- if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && !pdata->power) { ++ /* ++ * pdata->power == false only if COLD_CD is available, otherwise only ++ * in short time intervals during probing or resuming ++ */ ++ if (ios->power_mode == MMC_POWER_ON && ios->clock) { ++ if (!pdata->power) { + pm_runtime_get_sync(&host->pdev->dev); + pdata->power = true; + } ++ tmio_mmc_set_clock(host, ios->clock); + /* power up SD bus */ + if (host->set_pwr) + host->set_pwr(host->pdev, 1); +- } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) { +- /* power down SD bus */ +- if (ios->power_mode == MMC_POWER_OFF) { +- if (host->set_pwr) +- host->set_pwr(host->pdev, 0); +- if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && +- pdata->power) { +- pdata->power = false; +- pm_runtime_put(&host->pdev->dev); +- } +- } +- tmio_mmc_clk_stop(host); +- } else { + /* start bus clock */ + tmio_mmc_clk_start(host); ++ } else if (ios->power_mode != MMC_POWER_UP) { ++ if (host->set_pwr) ++ host->set_pwr(host->pdev, 0); ++ if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && ++ pdata->power) { ++ pdata->power = false; ++ pm_runtime_put(&host->pdev->dev); ++ } ++ tmio_mmc_clk_stop(host); + } + + switch (ios->bus_width) { +@@ -897,8 +897,10 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + tmio_mmc_request_dma(_host, pdata); + + /* We have to keep the device powered for its card detection to work */ +- if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD)) ++ if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD)) { ++ pdata->power = true; + pm_runtime_get_noresume(&pdev->dev); ++ } + + mmc_add_host(mmc); + +@@ -975,11 +977,16 @@ int tmio_mmc_host_resume(struct device *dev) + /* The MMC core will perform the complete set up */ + host->pdata->power = false; + ++ host->pm_global = true; + if (!host->pm_error) + pm_runtime_get_sync(dev); + +- tmio_mmc_reset(mmc_priv(mmc)); +- tmio_mmc_request_dma(host, host->pdata); ++ if (host->pm_global) { ++ /* Runtime PM resume callback didn't run */ ++ tmio_mmc_reset(host); ++ tmio_mmc_request_dma(host, host->pdata); ++ host->pm_global = false; ++ } + + return mmc_resume_host(mmc); + } +@@ -1000,12 +1007,15 @@ int tmio_mmc_host_runtime_resume(struct device *dev) + struct tmio_mmc_data *pdata = host->pdata; + + tmio_mmc_reset(host); ++ tmio_mmc_request_dma(host, host->pdata); + + if (pdata->power) { + /* Only entered after a card-insert interrupt */ +- tmio_mmc_set_ios(mmc, &mmc->ios); ++ if (!mmc->card) ++ tmio_mmc_set_ios(mmc, &mmc->ios); + mmc_detect_change(mmc, msecs_to_jiffies(100)); + } ++ host->pm_global = false; + + return 0; + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0027-mmc-tmio-fix-a-recently-introduced-bug-in-DMA-code.patch b/patches.kzm9g/0027-mmc-tmio-fix-a-recently-introduced-bug-in-DMA-code.patch new file mode 100644 index 00000000000000..283da7f0c71e0e --- /dev/null +++ b/patches.kzm9g/0027-mmc-tmio-fix-a-recently-introduced-bug-in-DMA-code.patch @@ -0,0 +1,34 @@ +From c87079bc67dfd1e0aac3f5acf682085f6b65d266 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 14 Jul 2011 18:39:06 +0200 +Subject: mmc: tmio: fix a recently introduced bug in DMA code + +A recent commit "mmc: tmio: Share register access functions" has swapped +arguments of a macro and broken DMA with TMIO MMC. This patch fixes the +arguments back. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 332bdb506f800d177f6657247347a253dd5b5be8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_dma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c +index f24a029..7e86662 100644 +--- a/drivers/mmc/host/tmio_mmc_dma.c ++++ b/drivers/mmc/host/tmio_mmc_dma.c +@@ -26,7 +26,7 @@ static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) + { + #if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE) + /* Switch DMA mode on or off - SuperH specific? */ +- sd_ctrl_write16(host, enable ? 2 : 0, CTL_DMA_ENABLE); ++ sd_ctrl_write16(host, CTL_DMA_ENABLE, enable ? 2 : 0); + #endif + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0028-mmc-tmio-fix-a-deadlock.patch b/patches.kzm9g/0028-mmc-tmio-fix-a-deadlock.patch new file mode 100644 index 00000000000000..2b82b73c9d48c4 --- /dev/null +++ b/patches.kzm9g/0028-mmc-tmio-fix-a-deadlock.patch @@ -0,0 +1,85 @@ +From 3d74cc1d62a8973298e5f559517f1f9cc362cfe4 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 14 Jul 2011 18:39:10 +0200 +Subject: mmc: tmio: fix a deadlock + +Currently the tmio-mmc driver contains a recursive runtime PM method +invocation, which leads to a deadlock on a mutex. Avoid it by taking +care not to request DMA too early. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 162f43e31c5a376ec16336e5d0ac973373d54c89) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 5 +++++ + drivers/mmc/host/tmio_mmc_dma.c | 5 ++++- + drivers/mmc/host/tmio_mmc_pio.c | 4 ++-- + 3 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index ba0d8e6..087d880 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -109,6 +109,7 @@ static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg, + + #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE) + void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data); ++void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable); + void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); + void tmio_mmc_release_dma(struct tmio_mmc_host *host); + #else +@@ -117,6 +118,10 @@ static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host, + { + } + ++static inline void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) ++{ ++} ++ + static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host, + struct tmio_mmc_data *pdata) + { +diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c +index 7e86662..2aa616d 100644 +--- a/drivers/mmc/host/tmio_mmc_dma.c ++++ b/drivers/mmc/host/tmio_mmc_dma.c +@@ -22,8 +22,11 @@ + + #define TMIO_MMC_MIN_DMA_LEN 8 + +-static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) ++void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) + { ++ if (!host->chan_tx || !host->chan_rx) ++ return; ++ + #if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE) + /* Switch DMA mode on or off - SuperH specific? */ + sd_ctrl_write16(host, CTL_DMA_ENABLE, enable ? 2 : 0); +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 221ffb7..1f16357 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -984,7 +984,7 @@ int tmio_mmc_host_resume(struct device *dev) + if (host->pm_global) { + /* Runtime PM resume callback didn't run */ + tmio_mmc_reset(host); +- tmio_mmc_request_dma(host, host->pdata); ++ tmio_mmc_enable_dma(host, true); + host->pm_global = false; + } + +@@ -1007,7 +1007,7 @@ int tmio_mmc_host_runtime_resume(struct device *dev) + struct tmio_mmc_data *pdata = host->pdata; + + tmio_mmc_reset(host); +- tmio_mmc_request_dma(host, host->pdata); ++ tmio_mmc_enable_dma(host, true); + + if (pdata->power) { + /* Only entered after a card-insert interrupt */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0029-net-remove-mm.h-inclusion-from-netdevice.h.patch b/patches.kzm9g/0029-net-remove-mm.h-inclusion-from-netdevice.h.patch new file mode 100644 index 00000000000000..66dc4806ea641d --- /dev/null +++ b/patches.kzm9g/0029-net-remove-mm.h-inclusion-from-netdevice.h.patch @@ -0,0 +1,109 @@ +From f079e5f73032b58caef775a101a141f45fed0915 Mon Sep 17 00:00:00 2001 +From: Alexey Dobriyan <adobriyan@gmail.com> +Date: Thu, 16 Jun 2011 11:01:34 +0000 +Subject: net: remove mm.h inclusion from netdevice.h + +Remove linux/mm.h inclusion from netdevice.h -- it's unused (I've checked manually). + +To prevent mm.h inclusion via other channels also extract "enum dma_data_direction" +definition into separate header. This tiny piece is what gluing netdevice.h with mm.h +via "netdevice.h => dmaengine.h => dma-mapping.h => scatterlist.h => mm.h". +Removal of mm.h from scatterlist.h was tried and was found not feasible +on most archs, so the link was cutoff earlier. + +Hope people are OK with tiny include file. + +Note, that mm_types.h is still dragged in, but it is a separate story. + +Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit b7f080cfe223b3b7424872639d153695615a9255) + +Conflicts: + + arch/arm/mach-davinci/board-mityomapl138.c + arch/arm/mach-davinci/dm646x.c + arch/arm/mach-davinci/pm.c + arch/arm/mach-imx/dma-v1.c + arch/arm/mach-imx/mach-mx31_3ds.c + arch/arm/mach-iop13xx/setup.c + arch/arm/mach-mxs/devices/platform-auart.c + arch/arm/mach-mxs/devices/platform-dma.c + arch/arm/mach-mxs/devices/platform-fec.c + arch/arm/plat-mxc/devices/platform-fec.c + arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c + arch/arm/plat-mxc/devices/platform-imx-fb.c + arch/arm/plat-mxc/devices/platform-ipu-core.c + arch/arm/plat-mxc/devices/platform-mxc-ehci.c + arch/arm/plat-mxc/devices/platform-mxc-mmc.c + arch/arm/plat-nomadik/include/plat/ste_dma40.h + arch/x86/kernel/tboot.c + crypto/async_tx/raid6test.c + drivers/dma/coh901318.c + drivers/dma/dmaengine.c + drivers/dma/dmatest.c + drivers/dma/ipu/ipu_idmac.c + drivers/dma/ste_dma40.c + drivers/media/dvb/mantis/mantis_ca.c + drivers/media/dvb/mantis/mantis_evm.c + drivers/media/dvb/mantis/mantis_hif.c + drivers/media/dvb/mantis/mantis_ioc.c + drivers/media/dvb/mantis/mantis_pcmcia.c + drivers/media/dvb/mantis/mantis_uart.c + drivers/media/dvb/mantis/mantis_vp1034.c + drivers/mtd/nand/atmel_nand.c + drivers/net/arm/ks8695net.c + drivers/net/bnx2x/bnx2x.h + drivers/net/can/janz-ican3.c + drivers/net/can/softing/softing_fw.c + drivers/net/can/softing/softing_main.c + drivers/net/ethoc.c + drivers/net/fec_mpc52xx.c + drivers/net/greth.c + drivers/net/irda/pxaficp_ir.c + drivers/net/ks8851_mll.c + drivers/net/sgiseeq.c + drivers/net/stmmac/dwmac1000_core.c + drivers/net/stmmac/dwmac1000_dma.c + drivers/net/stmmac/dwmac100_core.c + drivers/net/stmmac/dwmac100_dma.c + drivers/net/stmmac/stmmac_ethtool.c + drivers/net/stmmac/stmmac_mdio.c + drivers/net/usb/cdc-phonet.c + drivers/net/vxge/vxge-config.h + drivers/net/wireless/ath/ath5k/base.c + drivers/net/wireless/ath/ath9k/beacon.c + drivers/net/wireless/ath/ath9k/init.c + drivers/net/wireless/ath/ath9k/recv.c + drivers/net/wireless/ath/ath9k/xmit.c + drivers/staging/pohmelfs/crypto.c + drivers/tty/serial/ifx6x60.c + drivers/usb/gadget/f_phonet.c + include/crypto/if_alg.h + include/linux/dma-direction.h + include/linux/dma-mapping.h + include/linux/dmaengine.h + include/linux/netdevice.h + net/sched/sch_netem.c + security/apparmor/lib.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_dma.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c +index 2aa616d..86f259c 100644 +--- a/drivers/mmc/host/tmio_mmc_dma.c ++++ b/drivers/mmc/host/tmio_mmc_dma.c +@@ -11,6 +11,7 @@ + */ + + #include <linux/device.h> ++#include <linux/dma-mapping.h> + #include <linux/dmaengine.h> + #include <linux/mfd/tmio.h> + #include <linux/mmc/host.h> +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0030-MMC-TMIO-Fix-build-issue-related-to-struct-scatterli.patch b/patches.kzm9g/0030-MMC-TMIO-Fix-build-issue-related-to-struct-scatterli.patch new file mode 100644 index 00000000000000..8d59531622e57f --- /dev/null +++ b/patches.kzm9g/0030-MMC-TMIO-Fix-build-issue-related-to-struct-scatterli.patch @@ -0,0 +1,32 @@ +From 5f95cc2e38f83f6ce91e1312e078cbcc5ee839b1 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" <rjw@sisk.pl> +Date: Tue, 26 Jul 2011 20:50:23 +0200 +Subject: MMC / TMIO: Fix build issue related to struct scatterlist + +Fix build issue caused by undefined struct scatterlist in +drivers/mmc/host/tmio_mmc.c. + +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +(cherry picked from commit 6c0cbef6662aa685c6a47a18039b9d4f1d5abcb1) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index 087d880..eeaf643 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -21,6 +21,7 @@ + #include <linux/mutex.h> + #include <linux/pagemap.h> + #include <linux/spinlock.h> ++#include <linux/scatterlist.h> + + /* Definitions for values the CTRL_SDIO_STATUS register can take. */ + #define TMIO_SDIO_STAT_IOIRQ 0x0001 +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0031-mmc-tmio-eliminate-unused-variable-mmc-warning.patch b/patches.kzm9g/0031-mmc-tmio-eliminate-unused-variable-mmc-warning.patch new file mode 100644 index 00000000000000..554251e6533874 --- /dev/null +++ b/patches.kzm9g/0031-mmc-tmio-eliminate-unused-variable-mmc-warning.patch @@ -0,0 +1,45 @@ +From 37284ff5509343e2d777637a23487da3335c2f31 Mon Sep 17 00:00:00 2001 +From: Axel Lin <axel.lin@gmail.com> +Date: Wed, 3 Aug 2011 14:48:58 +0800 +Subject: mmc: tmio: eliminate unused variable 'mmc' warning + +Fix below compile warning: + CC drivers/mmc/host/tmio_mmc.o +drivers/mmc/host/tmio_mmc.c: In function 'tmio_mmc_suspend': +drivers/mmc/host/tmio_mmc.c:30: warning: unused variable 'mmc' +drivers/mmc/host/tmio_mmc.c: In function 'tmio_mmc_resume': +drivers/mmc/host/tmio_mmc.c:45: warning: unused variable 'mmc' + +Signed-off-by: Axel Lin <axel.lin@gmail.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 4906baf080623b4971bdeeac0a9fec5b8885d3ac) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c +index 8d185de..44a9668 100644 +--- a/drivers/mmc/host/tmio_mmc.c ++++ b/drivers/mmc/host/tmio_mmc.c +@@ -27,7 +27,6 @@ + static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) + { + const struct mfd_cell *cell = mfd_get_cell(dev); +- struct mmc_host *mmc = platform_get_drvdata(dev); + int ret; + + ret = tmio_mmc_host_suspend(&dev->dev); +@@ -42,7 +41,6 @@ static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) + static int tmio_mmc_resume(struct platform_device *dev) + { + const struct mfd_cell *cell = mfd_get_cell(dev); +- struct mmc_host *mmc = platform_get_drvdata(dev); + int ret = 0; + + /* Tell the MFD core we are ready to be enabled */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0032-mmc-sdhi-initialise-mmc_data-flags-before-use.patch b/patches.kzm9g/0032-mmc-sdhi-initialise-mmc_data-flags-before-use.patch new file mode 100644 index 00000000000000..c88dadd8462f77 --- /dev/null +++ b/patches.kzm9g/0032-mmc-sdhi-initialise-mmc_data-flags-before-use.patch @@ -0,0 +1,39 @@ +From bf87a92d768043390903be036df2292b6775bdb5 Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Fri, 19 Aug 2011 10:07:07 +0900 +Subject: mmc: sdhi: initialise mmc_data->flags before use + +This corrects a logic error that I introduced in +"mmc: sdhi: Add write16_hook" + +Reported-by: Magnus Damm <magnus.damm@gmail.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit b91df1593e361109f1fe665ce17c5e87ca60582b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 774f643..0c4a672 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -120,11 +120,11 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + mmc_data->hclk = clk_get_rate(priv->clk); + mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; + mmc_data->get_cd = sh_mobile_sdhi_get_cd; +- if (mmc_data->flags & TMIO_MMC_HAS_IDLE_WAIT) +- mmc_data->write16_hook = sh_mobile_sdhi_write16_hook; + mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; + if (p) { + mmc_data->flags = p->tmio_flags; ++ if (mmc_data->flags & TMIO_MMC_HAS_IDLE_WAIT) ++ mmc_data->write16_hook = sh_mobile_sdhi_write16_hook; + mmc_data->ocr_mask = p->tmio_ocr_mask; + mmc_data->capabilities |= p->tmio_caps; + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0033-mmc-tmio-Cache-interrupt-masks.patch b/patches.kzm9g/0033-mmc-tmio-Cache-interrupt-masks.patch new file mode 100644 index 00000000000000..7f23958328ab13 --- /dev/null +++ b/patches.kzm9g/0033-mmc-tmio-Cache-interrupt-masks.patch @@ -0,0 +1,131 @@ +From 841db3ade6dadb8573cbe50fa35238f7d0bbe637 Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Thu, 25 Aug 2011 10:27:25 +0900 +Subject: mmc: tmio: Cache interrupt masks + +This avoids the need to look up the masks each time an interrupt is handled. +As suggested by Guennadi. + +Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Magnus Damm <magnus.damm@gmail.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 54680fe7f6ad0fb0c52e330484e2cf1609587862) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 4 ++++ + drivers/mmc/host/tmio_mmc_pio.c | 34 ++++++++++++++++++---------------- + 2 files changed, 22 insertions(+), 16 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index eeaf643..1cf8db5 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -79,6 +79,10 @@ struct tmio_mmc_host { + struct delayed_work delayed_reset_work; + struct work_struct done; + ++ /* Cache IRQ mask */ ++ u32 sdcard_irq_mask; ++ u32 sdio_irq_mask; ++ + spinlock_t lock; /* protect host private data */ + unsigned long last_req_ts; + struct mutex ios_lock; /* protect set_ios() context */ +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 1f16357..f0c7830 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -48,14 +48,14 @@ + + void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i) + { +- u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) & ~(i & TMIO_MASK_IRQ); +- sd_ctrl_write32(host, CTL_IRQ_MASK, mask); ++ host->sdcard_irq_mask &= ~(i & TMIO_MASK_IRQ); ++ sd_ctrl_write32(host, CTL_IRQ_MASK, host->sdcard_irq_mask); + } + + void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i) + { +- u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) | (i & TMIO_MASK_IRQ); +- sd_ctrl_write32(host, CTL_IRQ_MASK, mask); ++ host->sdcard_irq_mask |= (i & TMIO_MASK_IRQ); ++ sd_ctrl_write32(host, CTL_IRQ_MASK, host->sdcard_irq_mask); + } + + static void tmio_mmc_ack_mmc_irqs(struct tmio_mmc_host *host, u32 i) +@@ -127,11 +127,13 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + + if (enable) { + host->sdio_irq_enabled = 1; ++ host->sdio_irq_mask = TMIO_SDIO_MASK_ALL & ++ ~TMIO_SDIO_STAT_IOIRQ; + sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); +- sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, +- (TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ)); ++ sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); + } else { +- sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL); ++ host->sdio_irq_mask = TMIO_SDIO_MASK_ALL; ++ sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); + sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000); + host->sdio_irq_enabled = 0; + } +@@ -548,26 +550,25 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) + struct tmio_mmc_host *host = devid; + struct mmc_host *mmc = host->mmc; + struct tmio_mmc_data *pdata = host->pdata; +- unsigned int ireg, irq_mask, status; +- unsigned int sdio_ireg, sdio_irq_mask, sdio_status; ++ unsigned int ireg, status; ++ unsigned int sdio_ireg, sdio_status; + + pr_debug("MMC IRQ begin\n"); + + status = sd_ctrl_read32(host, CTL_STATUS); +- irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK); +- ireg = status & TMIO_MASK_IRQ & ~irq_mask; ++ ireg = status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask; + + sdio_ireg = 0; + if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) { + sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS); +- sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK); +- sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ~sdio_irq_mask; ++ sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ++ ~host->sdio_irq_mask; + + sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL); + + if (sdio_ireg && !host->sdio_irq_enabled) { + pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n", +- sdio_status, sdio_irq_mask, sdio_ireg); ++ sdio_status, host->sdio_irq_mask, sdio_ireg); + tmio_mmc_enable_sdio_irq(mmc, 0); + goto out; + } +@@ -623,9 +624,9 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) + } + + pr_warning("tmio_mmc: Spurious irq, disabling! " +- "0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg); ++ "0x%08x 0x%08x 0x%08x\n", status, host->sdcard_irq_mask, ireg); + pr_debug_status(status); +- tmio_mmc_disable_mmc_irqs(host, status & ~irq_mask); ++ tmio_mmc_disable_mmc_irqs(host, status & ~host->sdcard_irq_mask); + + out: + return IRQ_HANDLED; +@@ -882,6 +883,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + tmio_mmc_clk_stop(_host); + tmio_mmc_reset(_host); + ++ _host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK); + tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); + if (pdata->flags & TMIO_MMC_SDIO_IRQ) + tmio_mmc_enable_sdio_irq(mmc, 0); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0034-mmc-tmio-Provide-separate-interrupt-handlers.patch b/patches.kzm9g/0034-mmc-tmio-Provide-separate-interrupt-handlers.patch new file mode 100644 index 00000000000000..a36ee79a77255d --- /dev/null +++ b/patches.kzm9g/0034-mmc-tmio-Provide-separate-interrupt-handlers.patch @@ -0,0 +1,215 @@ +From 82db957f7a037e60d56f38437d5d0e8517cfd3f9 Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Thu, 25 Aug 2011 10:27:26 +0900 +Subject: mmc: tmio: Provide separate interrupt handlers + +Provide separate interrupt handlers which may be used by platforms where +SDHI has three interrupt sources. + +This patch also removes the commented-out handling of CRC and other errors. + +Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Magnus Damm <magnus.damm@gmail.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 7729c7a232a95360fa17ffe8beb1adb621bc0ba0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 3 + + drivers/mmc/host/tmio_mmc_pio.c | 131 +++++++++++++++++++++++++--------------- + 2 files changed, 86 insertions(+), 48 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index 1cf8db5..3020f98 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -97,6 +97,9 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host); + void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i); + void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i); + irqreturn_t tmio_mmc_irq(int irq, void *devid); ++irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid); ++irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid); ++irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid); + + static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, + unsigned long *flags) +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index f0c7830..6275e3d 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -545,44 +545,20 @@ out: + spin_unlock(&host->lock); + } + +-irqreturn_t tmio_mmc_irq(int irq, void *devid) ++static void tmio_mmc_card_irq_status(struct tmio_mmc_host *host, ++ int *ireg, int *status) + { +- struct tmio_mmc_host *host = devid; +- struct mmc_host *mmc = host->mmc; +- struct tmio_mmc_data *pdata = host->pdata; +- unsigned int ireg, status; +- unsigned int sdio_ireg, sdio_status; +- +- pr_debug("MMC IRQ begin\n"); +- +- status = sd_ctrl_read32(host, CTL_STATUS); +- ireg = status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask; ++ *status = sd_ctrl_read32(host, CTL_STATUS); ++ *ireg = *status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask; + +- sdio_ireg = 0; +- if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) { +- sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS); +- sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & +- ~host->sdio_irq_mask; +- +- sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL); +- +- if (sdio_ireg && !host->sdio_irq_enabled) { +- pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n", +- sdio_status, host->sdio_irq_mask, sdio_ireg); +- tmio_mmc_enable_sdio_irq(mmc, 0); +- goto out; +- } +- +- if (mmc->caps & MMC_CAP_SDIO_IRQ && +- sdio_ireg & TMIO_SDIO_STAT_IOIRQ) +- mmc_signal_sdio_irq(mmc); +- +- if (sdio_ireg) +- goto out; +- } ++ pr_debug_status(*status); ++ pr_debug_status(*ireg); ++} + +- pr_debug_status(status); +- pr_debug_status(ireg); ++static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host, ++ int ireg, int status) ++{ ++ struct mmc_host *mmc = host->mmc; + + /* Card insert / remove attempts */ + if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) { +@@ -592,43 +568,102 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) + ((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) && + !work_pending(&mmc->detect.work)) + mmc_detect_change(host->mmc, msecs_to_jiffies(100)); +- goto out; ++ return true; + } + +- /* CRC and other errors */ +-/* if (ireg & TMIO_STAT_ERR_IRQ) +- * handled |= tmio_error_irq(host, irq, stat); +- */ ++ return false; ++} ++ ++irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid) ++{ ++ unsigned int ireg, status; ++ struct tmio_mmc_host *host = devid; + ++ tmio_mmc_card_irq_status(host, &ireg, &status); ++ __tmio_mmc_card_detect_irq(host, ireg, status); ++ ++ return IRQ_HANDLED; ++} ++EXPORT_SYMBOL(tmio_mmc_card_detect_irq); ++ ++static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host, ++ int ireg, int status) ++{ + /* Command completion */ + if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) { + tmio_mmc_ack_mmc_irqs(host, + TMIO_STAT_CMDRESPEND | + TMIO_STAT_CMDTIMEOUT); + tmio_mmc_cmd_irq(host, status); +- goto out; ++ return true; + } + + /* Data transfer */ + if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) { + tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ); + tmio_mmc_pio_irq(host); +- goto out; ++ return true; + } + + /* Data transfer completion */ + if (ireg & TMIO_STAT_DATAEND) { + tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND); + tmio_mmc_data_irq(host); +- goto out; ++ return true; + } + +- pr_warning("tmio_mmc: Spurious irq, disabling! " +- "0x%08x 0x%08x 0x%08x\n", status, host->sdcard_irq_mask, ireg); +- pr_debug_status(status); +- tmio_mmc_disable_mmc_irqs(host, status & ~host->sdcard_irq_mask); ++ return false; ++} ++ ++irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid) ++{ ++ unsigned int ireg, status; ++ struct tmio_mmc_host *host = devid; ++ ++ tmio_mmc_card_irq_status(host, &ireg, &status); ++ __tmio_mmc_sdcard_irq(host, ireg, status); ++ ++ return IRQ_HANDLED; ++} ++EXPORT_SYMBOL(tmio_mmc_sdcard_irq); ++ ++irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid) ++{ ++ struct tmio_mmc_host *host = devid; ++ struct mmc_host *mmc = host->mmc; ++ struct tmio_mmc_data *pdata = host->pdata; ++ unsigned int ireg, status; ++ ++ if (!(pdata->flags & TMIO_MMC_SDIO_IRQ)) ++ return IRQ_HANDLED; ++ ++ status = sd_ctrl_read16(host, CTL_SDIO_STATUS); ++ ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask; ++ ++ sd_ctrl_write16(host, CTL_SDIO_STATUS, status & ~TMIO_SDIO_MASK_ALL); ++ ++ if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ) ++ mmc_signal_sdio_irq(mmc); ++ ++ return IRQ_HANDLED; ++} ++EXPORT_SYMBOL(tmio_mmc_sdio_irq); ++ ++irqreturn_t tmio_mmc_irq(int irq, void *devid) ++{ ++ struct tmio_mmc_host *host = devid; ++ unsigned int ireg, status; ++ ++ pr_debug("MMC IRQ begin\n"); ++ ++ tmio_mmc_card_irq_status(host, &ireg, &status); ++ if (__tmio_mmc_card_detect_irq(host, ireg, status)) ++ return IRQ_HANDLED; ++ if (__tmio_mmc_sdcard_irq(host, ireg, status)) ++ return IRQ_HANDLED; ++ ++ tmio_mmc_sdio_irq(irq, devid); + +-out: + return IRQ_HANDLED; + } + EXPORT_SYMBOL(tmio_mmc_irq); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0035-mmc-sdhi-Allow-named-IRQs-to-use-specific-handlers.patch b/patches.kzm9g/0035-mmc-sdhi-Allow-named-IRQs-to-use-specific-handlers.patch new file mode 100644 index 00000000000000..44d188ce33d7ea --- /dev/null +++ b/patches.kzm9g/0035-mmc-sdhi-Allow-named-IRQs-to-use-specific-handlers.patch @@ -0,0 +1,180 @@ +From 0f69bae0394ca010c38bb88a66b8a9a480f5f3ea Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Fri, 26 Aug 2011 10:42:39 +0200 +Subject: mmc: sdhi: Allow named IRQs to use specific handlers + +Allow named IRQs to use corresponding specific handlers. If named IRQs are +used, at least an "sdcard" IRQ has to be specified by the platform. If +names are not used, an arbitrary number of IRQs can be provided by the +platform, in which case the generic ISR will be used for each of them. + +Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Magnus Damm <magnus.damm@gmail.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +[g.liakhovetski@gmx.de: style and typo corrections, platform data check] +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit d5098cb63b3f13da2a2b230b3566ac7b5dfa4f28) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 98 ++++++++++++++++++++++++++++---------- + include/linux/mmc/sh_mobile_sdhi.h | 4 ++ + 2 files changed, 77 insertions(+), 25 deletions(-) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 0c4a672..75bffc4 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -96,7 +96,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; + struct tmio_mmc_host *host; + char clk_name[8]; +- int i, irq, ret; ++ int irq, ret, i = 0; ++ bool multiplexed_isr = true; + + priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL); + if (priv == NULL) { +@@ -153,27 +154,60 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + if (ret < 0) + goto eprobe; + +- for (i = 0; i < 3; i++) { +- irq = platform_get_irq(pdev, i); +- if (irq < 0) { +- if (i) { +- continue; +- } else { +- ret = irq; +- goto eirq; +- } +- } +- ret = request_irq(irq, tmio_mmc_irq, 0, ++ /* ++ * Allow one or more specific (named) ISRs or ++ * one or more multiplexed (un-named) ISRs. ++ */ ++ ++ irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT); ++ if (irq >= 0) { ++ multiplexed_isr = false; ++ ret = request_irq(irq, tmio_mmc_card_detect_irq, 0, ++ dev_name(&pdev->dev), host); ++ if (ret) ++ goto eirq_card_detect; ++ } ++ ++ irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO); ++ if (irq >= 0) { ++ multiplexed_isr = false; ++ ret = request_irq(irq, tmio_mmc_sdio_irq, 0, ++ dev_name(&pdev->dev), host); ++ if (ret) ++ goto eirq_sdio; ++ } ++ ++ irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDCARD); ++ if (irq >= 0) { ++ multiplexed_isr = false; ++ ret = request_irq(irq, tmio_mmc_sdcard_irq, 0, + dev_name(&pdev->dev), host); +- if (ret) { +- while (i--) { +- irq = platform_get_irq(pdev, i); +- if (irq >= 0) +- free_irq(irq, host); +- } +- goto eirq; ++ if (ret) ++ goto eirq_sdcard; ++ } else if (!multiplexed_isr) { ++ dev_err(&pdev->dev, ++ "Principal SD-card IRQ is missing among named interrupts\n"); ++ ret = irq; ++ goto eirq_sdcard; ++ } ++ ++ if (multiplexed_isr) { ++ while (1) { ++ irq = platform_get_irq(pdev, i); ++ if (irq < 0) ++ break; ++ i++; ++ ret = request_irq(irq, tmio_mmc_irq, 0, ++ dev_name(&pdev->dev), host); ++ if (ret) ++ goto eirq_multiplexed; + } ++ ++ /* There must be at least one IRQ source */ ++ if (!i) ++ goto eirq_multiplexed; + } ++ + dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n", + mmc_hostname(host->mmc), (unsigned long) + (platform_get_resource(pdev,IORESOURCE_MEM, 0)->start), +@@ -181,7 +215,20 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + + return ret; + +-eirq: ++eirq_multiplexed: ++ while (i--) { ++ irq = platform_get_irq(pdev, i); ++ free_irq(irq, host); ++ } ++eirq_sdcard: ++ irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO); ++ if (irq >= 0) ++ free_irq(irq, host); ++eirq_sdio: ++ irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT); ++ if (irq >= 0) ++ free_irq(irq, host); ++eirq_card_detect: + tmio_mmc_host_remove(host); + eprobe: + clk_disable(priv->clk); +@@ -197,16 +244,17 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) + struct tmio_mmc_host *host = mmc_priv(mmc); + struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); + struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; +- int i, irq; ++ int i = 0, irq; + + p->pdata = NULL; + + tmio_mmc_host_remove(host); + +- for (i = 0; i < 3; i++) { +- irq = platform_get_irq(pdev, i); +- if (irq >= 0) +- free_irq(irq, host); ++ while (1) { ++ irq = platform_get_irq(pdev, i++); ++ if (irq < 0) ++ break; ++ free_irq(irq, host); + } + + clk_disable(priv->clk); +diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h +index bd50b36..71b8054 100644 +--- a/include/linux/mmc/sh_mobile_sdhi.h ++++ b/include/linux/mmc/sh_mobile_sdhi.h +@@ -6,6 +6,10 @@ + struct platform_device; + struct tmio_mmc_data; + ++#define SH_MOBILE_SDHI_IRQ_CARD_DETECT "card_detect" ++#define SH_MOBILE_SDHI_IRQ_SDCARD "sdcard" ++#define SH_MOBILE_SDHI_IRQ_SDIO "sdio" ++ + struct sh_mobile_sdhi_info { + int dma_slave_tx; + int dma_slave_rx; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0036-mmc-irq-Remove-IRQF_DISABLED.patch b/patches.kzm9g/0036-mmc-irq-Remove-IRQF_DISABLED.patch new file mode 100644 index 00000000000000..be5d23aac991d4 --- /dev/null +++ b/patches.kzm9g/0036-mmc-irq-Remove-IRQF_DISABLED.patch @@ -0,0 +1,46 @@ +From 659def1c9d9094e00aef310907f2859663a850c8 Mon Sep 17 00:00:00 2001 +From: Yong Zhang <yong.zhang0@gmail.com> +Date: Thu, 22 Sep 2011 16:59:04 +0800 +Subject: mmc: irq: Remove IRQF_DISABLED + +Since commit [e58aa3d2: genirq: Run irq handlers with interrupts +disabled], we run all interrupt handlers with interrupts disabled +and we even check and yell when an interrupt handler returns with +interrupts enabled (see commit [b738a50a: genirq: Warn when handler +enables interrupts]). + +So now this flag is a NOOP and can be removed. + +Signed-off-by: Yong Zhang <yong.zhang0@gmail.com> +Acked-by: Kishore Kadiyala <kishore.kadiyala@ti.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit d9618e9f1a057efdfc52514d6cd7af56e9bddc17) + +Conflicts: + + drivers/mmc/host/omap_hsmmc.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c +index 44a9668..a4ea102 100644 +--- a/drivers/mmc/host/tmio_mmc.c ++++ b/drivers/mmc/host/tmio_mmc.c +@@ -88,8 +88,8 @@ static int __devinit tmio_mmc_probe(struct platform_device *pdev) + if (ret) + goto cell_disable; + +- ret = request_irq(irq, tmio_mmc_irq, IRQF_DISABLED | +- IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), host); ++ ret = request_irq(irq, tmio_mmc_irq, IRQF_TRIGGER_FALLING, ++ dev_name(&pdev->dev), host); + if (ret) + goto host_remove; + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0037-mmc-Add-module.h-to-drivers-mmc-users-assuming-impli.patch b/patches.kzm9g/0037-mmc-Add-module.h-to-drivers-mmc-users-assuming-impli.patch new file mode 100644 index 00000000000000..b3cae7b2e76dd6 --- /dev/null +++ b/patches.kzm9g/0037-mmc-Add-module.h-to-drivers-mmc-users-assuming-impli.patch @@ -0,0 +1,36 @@ +From b19f896d27c56c6fdf613e245c7cd8963cac5c05 Mon Sep 17 00:00:00 2001 +From: Paul Gortmaker <paul.gortmaker@windriver.com> +Date: Sun, 3 Jul 2011 15:15:51 -0400 +Subject: mmc: Add module.h to drivers/mmc users assuming implicit presence. + +We are cleaning up the implicit presence of module.h; these guys are +some of the people who just assume it will be there. Call it out +explitly for those that really need it. + +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 88b47679746b81534002bcba42da97ab82b5d12a) + +Cherry picked changes for: + drivers/mmc/host/sh_mobile_sdhi.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 75bffc4..41ae646 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -21,6 +21,7 @@ + #include <linux/kernel.h> + #include <linux/clk.h> + #include <linux/slab.h> ++#include <linux/module.h> + #include <linux/platform_device.h> + #include <linux/mmc/host.h> + #include <linux/mmc/sh_mobile_sdhi.h> +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0038-mmc-replace-printk-with-appropriate-display-macro.patch b/patches.kzm9g/0038-mmc-replace-printk-with-appropriate-display-macro.patch new file mode 100644 index 00000000000000..d31b0098cfaeeb --- /dev/null +++ b/patches.kzm9g/0038-mmc-replace-printk-with-appropriate-display-macro.patch @@ -0,0 +1,36 @@ +From f1b038d466d3385553728a07eb252ea400847af6 Mon Sep 17 00:00:00 2001 +From: Girish K S <girish.shivananjappa@linaro.org> +Date: Tue, 11 Oct 2011 11:44:09 +0530 +Subject: mmc: replace printk with appropriate display macro + +All the files using printk function for displaying kernel messages +in the mmc driver have been replaced with corresponding macro. + +Signed-off-by: Girish K S <girish.shivananjappa@linaro.org> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993) + +Cherry-picked changes for: + drivers/mmc/host/tmio_mmc_pio.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 6275e3d..d85a60c 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -92,7 +92,7 @@ static int tmio_mmc_next_sg(struct tmio_mmc_host *host) + static void pr_debug_status(u32 status) + { + int i = 0; +- printk(KERN_DEBUG "status: %08x = ", status); ++ pr_debug("status: %08x = ", status); + STATUS_TO_TEXT(CARD_REMOVE, status, i); + STATUS_TO_TEXT(CARD_INSERT, status, i); + STATUS_TO_TEXT(SIGSTATE, status, i); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0039-mmc-tmio-fix-clock-gating-on-platforms-with-a-.set_p.patch b/patches.kzm9g/0039-mmc-tmio-fix-clock-gating-on-platforms-with-a-.set_p.patch new file mode 100644 index 00000000000000..e0f1bf06d3a7e8 --- /dev/null +++ b/patches.kzm9g/0039-mmc-tmio-fix-clock-gating-on-platforms-with-a-.set_p.patch @@ -0,0 +1,33 @@ +From 998c2d6fab4e0ed0eb6f8bc58f9fdeb2f9ee9620 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 16 Nov 2011 10:11:45 +0100 +Subject: mmc: tmio: fix clock gating on platforms with a .set_pwr() method + +Do not power down the card in .set_ios(), unless MMC_POWER_OFF is +requested. This fixes the SDHI functionality on ecovec. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit f6b8b52c68f6109db4be02b55660258ff503fc3b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index d85a60c..4208b39 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -798,7 +798,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + /* start bus clock */ + tmio_mmc_clk_start(host); + } else if (ios->power_mode != MMC_POWER_UP) { +- if (host->set_pwr) ++ if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) + host->set_pwr(host->pdev, 0); + if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && + pdata->power) { +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0040-mmc-convert-drivers-mmc-host-to-use-module_platform_.patch b/patches.kzm9g/0040-mmc-convert-drivers-mmc-host-to-use-module_platform_.patch new file mode 100644 index 00000000000000..51127b5b8c05e1 --- /dev/null +++ b/patches.kzm9g/0040-mmc-convert-drivers-mmc-host-to-use-module_platform_.patch @@ -0,0 +1,103 @@ +From 9fd478fb4b61077bb435702bcb65e79de681e1c6 Mon Sep 17 00:00:00 2001 +From: Axel Lin <axel.lin@gmail.com> +Date: Sat, 26 Nov 2011 12:55:43 +0800 +Subject: mmc: convert drivers/mmc/host/* to use module_platform_driver() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch converts the drivers in drivers/mmc/host/* to use the +module_platform_driver() macro which makes the code smaller and a bit +simpler. + +Signed-off-by: Axel Lin <axel.lin@gmail.com> +Acked-by: "Michał Mirosław" <mirq-linux@rere.qmqm.pl> +Acked-by: David Brown <davidb@codeaurora.org> +Acked-by: Viresh Kumar <viresh.kumar@st.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Sascha Hauer <s.hauer@pengutronix.de> +Acked-by: Wolfram Sang <w.sang@pengutronix.de> +Acked-by: Anton Vorontsov <cbouatmailru@gmail.com> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry-picked from commit d1f81a64a4250bdd776978be06ae2b8e13ec7471) + +Conflicts: + + drivers/mmc/host/bfin_sdh.c + drivers/mmc/host/cb710-mmc.c + drivers/mmc/host/jz4740_mmc.c + drivers/mmc/host/msm_sdcc.c + drivers/mmc/host/mxcmmc.c + drivers/mmc/host/mxs-mmc.c + drivers/mmc/host/pxamci.c + drivers/mmc/host/s3cmci.c + drivers/mmc/host/sdhci-cns3xxx.c + drivers/mmc/host/sdhci-dove.c + drivers/mmc/host/sdhci-esdhc-imx.c + drivers/mmc/host/sdhci-of-esdhc.c + drivers/mmc/host/sdhci-of-hlwd.c + drivers/mmc/host/sdhci-pxav2.c + drivers/mmc/host/sdhci-pxav3.c + drivers/mmc/host/sdhci-s3c.c + drivers/mmc/host/sdhci-spear.c + drivers/mmc/host/sdhci-tegra.c + drivers/mmc/host/sh_mmcif.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 13 +------------ + drivers/mmc/host/tmio_mmc.c | 14 +------------- + 2 files changed, 2 insertions(+), 25 deletions(-) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 41ae646..58da3c4 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -282,18 +282,7 @@ static struct platform_driver sh_mobile_sdhi_driver = { + .remove = __devexit_p(sh_mobile_sdhi_remove), + }; + +-static int __init sh_mobile_sdhi_init(void) +-{ +- return platform_driver_register(&sh_mobile_sdhi_driver); +-} +- +-static void __exit sh_mobile_sdhi_exit(void) +-{ +- platform_driver_unregister(&sh_mobile_sdhi_driver); +-} +- +-module_init(sh_mobile_sdhi_init); +-module_exit(sh_mobile_sdhi_exit); ++module_platform_driver(sh_mobile_sdhi_driver); + + MODULE_DESCRIPTION("SuperH Mobile SDHI driver"); + MODULE_AUTHOR("Magnus Damm"); +diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c +index a4ea102..113ce6c 100644 +--- a/drivers/mmc/host/tmio_mmc.c ++++ b/drivers/mmc/host/tmio_mmc.c +@@ -138,19 +138,7 @@ static struct platform_driver tmio_mmc_driver = { + .resume = tmio_mmc_resume, + }; + +- +-static int __init tmio_mmc_init(void) +-{ +- return platform_driver_register(&tmio_mmc_driver); +-} +- +-static void __exit tmio_mmc_exit(void) +-{ +- platform_driver_unregister(&tmio_mmc_driver); +-} +- +-module_init(tmio_mmc_init); +-module_exit(tmio_mmc_exit); ++module_platform_driver(tmio_mmc_driver); + + MODULE_DESCRIPTION("Toshiba TMIO SD/MMC driver"); + MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0041-mmc-remove-the-second-argument-of-k-un-map_atomic.patch b/patches.kzm9g/0041-mmc-remove-the-second-argument-of-k-un-map_atomic.patch new file mode 100644 index 00000000000000..9ac5f48f863ccc --- /dev/null +++ b/patches.kzm9g/0041-mmc-remove-the-second-argument-of-k-un-map_atomic.patch @@ -0,0 +1,46 @@ +From 5a1454200daaf7e2ed0ec2ad17e960240af1f9ee Mon Sep 17 00:00:00 2001 +From: Cong Wang <amwang@redhat.com> +Date: Sun, 27 Nov 2011 13:27:00 +0800 +Subject: mmc: remove the second argument of k[un]map_atomic() + +Signed-off-by: Cong Wang <amwang@redhat.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 482fce997e143a8d5429406fe066d31aa76ef70a) + +Conflicts: + + drivers/mmc/host/at91_mci.c + drivers/mmc/host/msm_sdcc.c + drivers/mmc/host/sdhci.c + drivers/mmc/host/tifm_sd.c + drivers/mmc/host/tmio_mmc.h + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index 3020f98..a95e6d9 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -105,13 +105,13 @@ static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, + unsigned long *flags) + { + local_irq_save(*flags); +- return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; ++ return kmap_atomic(sg_page(sg)) + sg->offset; + } + + static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg, + unsigned long *flags, void *virt) + { +- kunmap_atomic(virt - sg->offset, KM_BIO_SRC_IRQ); ++ kunmap_atomic(virt - sg->offset); + local_irq_restore(*flags); + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0042-mmc-tmio_mmc-Hotplug-code-regrouping.patch b/patches.kzm9g/0042-mmc-tmio_mmc-Hotplug-code-regrouping.patch new file mode 100644 index 00000000000000..9c567795f38f3a --- /dev/null +++ b/patches.kzm9g/0042-mmc-tmio_mmc-Hotplug-code-regrouping.patch @@ -0,0 +1,84 @@ +From 4ca7e51f2818d592650cabed935acd9f094ca26a Mon Sep 17 00:00:00 2001 +From: Bastian Hecht <hechtb@googlemail.com> +Date: Fri, 23 Dec 2011 23:03:13 +0100 +Subject: mmc: tmio_mmc: Hotplug code regrouping + +This patch regroups the code slightly, adds documentation and allows +the rtpm counter of MMC_CAP_NEEDS_POLL devices to reach 0 again. + +Signed-off-by: Bastian Hecht <hechtb@gmail.com> +[g.liakhovetski@gmx.de: restore pm_runtime_get_noresume()] +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit cbb18b309d3d6b6661f931279697eac77b6591c9) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 30 +++++++++++++++++++++--------- + 1 file changed, 21 insertions(+), 9 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 4208b39..abad01b 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -800,8 +800,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + } else if (ios->power_mode != MMC_POWER_UP) { + if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) + host->set_pwr(host->pdev, 0); +- if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && +- pdata->power) { ++ if (pdata->power) { + pdata->power = false; + pm_runtime_put(&host->pdev->dev); + } +@@ -915,6 +914,23 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + if (ret < 0) + goto pm_disable; + ++ /* ++ * There are 4 different scenarios for the card detection: ++ * 1) an external gpio irq handles the cd (best for power savings) ++ * 2) internal sdhi irq handles the cd ++ * 3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL ++ * 4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE ++ * ++ * While we increment the rtpm counter for all scenarios when the mmc ++ * core activates us by calling an appropriate set_ios(), we must ++ * additionally ensure that in case 2) the tmio mmc hardware stays ++ * powered on during runtime for the card detection to work. ++ */ ++ if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD ++ || mmc->caps & MMC_CAP_NEEDS_POLL ++ || mmc->caps & MMC_CAP_NONREMOVABLE)) ++ pm_runtime_get_noresume(&pdev->dev); ++ + tmio_mmc_clk_stop(_host); + tmio_mmc_reset(_host); + +@@ -933,12 +949,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + /* See if we also get DMA */ + tmio_mmc_request_dma(_host, pdata); + +- /* We have to keep the device powered for its card detection to work */ +- if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD)) { +- pdata->power = true; +- pm_runtime_get_noresume(&pdev->dev); +- } +- + mmc_add_host(mmc); + + /* Unmask the IRQs we want to know about */ +@@ -974,7 +984,9 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) + * the controller, the runtime PM is suspended and pdata->power == false, + * so, our .runtime_resume() will not try to detect a card in the slot. + */ +- if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD) ++ if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD ++ || host->mmc->caps & MMC_CAP_NEEDS_POLL ++ || host->mmc->caps & MMC_CAP_NONREMOVABLE) + pm_runtime_get_sync(&pdev->dev); + + mmc_remove_host(host->mmc); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0043-mmc-host-move-to-dma_transfer_direction.patch b/patches.kzm9g/0043-mmc-host-move-to-dma_transfer_direction.patch new file mode 100644 index 00000000000000..e0e100e94f4d61 --- /dev/null +++ b/patches.kzm9g/0043-mmc-host-move-to-dma_transfer_direction.patch @@ -0,0 +1,54 @@ +From aa9a805a43f06d6cf99be9a4ef28701aa8ec1314 Mon Sep 17 00:00:00 2001 +From: Vinod Koul <vinod.koul@linux.intel.com> +Date: Fri, 14 Oct 2011 10:45:11 +0530 +Subject: mmc-host: move to dma_transfer_direction + +fixup usage of dma direction by introducing dma_transfer_direction, +this patch moves mmc drivers to use new enum + +Cc: Nicolas Ferre <nicolas.ferre@atmel.com> +Cc: Chris Ball <cjb@laptop.org> +Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 05f5799cbe5c9e2c03f604b3de5783cf4d726227) + +Conflicts: + + drivers/mmc/host/atmel-mci.c + drivers/mmc/host/mmci.c + drivers/mmc/host/mxcmmc.c + drivers/mmc/host/mxs-mmc.c + drivers/mmc/host/sh_mmcif.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_dma.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c +index 86f259c..7a6e6cc 100644 +--- a/drivers/mmc/host/tmio_mmc_dma.c ++++ b/drivers/mmc/host/tmio_mmc_dma.c +@@ -77,7 +77,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) + ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE); + if (ret > 0) + desc = chan->device->device_prep_slave_sg(chan, sg, ret, +- DMA_FROM_DEVICE, DMA_CTRL_ACK); ++ DMA_DEV_TO_MEM, DMA_CTRL_ACK); + + if (desc) { + cookie = dmaengine_submit(desc); +@@ -158,7 +158,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) + ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE); + if (ret > 0) + desc = chan->device->device_prep_slave_sg(chan, sg, ret, +- DMA_TO_DEVICE, DMA_CTRL_ACK); ++ DMA_MEM_TO_DEV, DMA_CTRL_ACK); + + if (desc) { + cookie = dmaengine_submit(desc); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0044-mmc-tmio_mmc-fix-card-eject-during-IO-with-DMA.patch b/patches.kzm9g/0044-mmc-tmio_mmc-fix-card-eject-during-IO-with-DMA.patch new file mode 100644 index 00000000000000..5f23faae47bc97 --- /dev/null +++ b/patches.kzm9g/0044-mmc-tmio_mmc-fix-card-eject-during-IO-with-DMA.patch @@ -0,0 +1,111 @@ +From 471b39df4319e8f35fe4ab3d91c859c391385bdd Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Fri, 6 Jan 2012 13:06:51 +0100 +Subject: mmc: tmio_mmc: fix card eject during IO with DMA + +When DMA is in use and the card is ejected during IO, DMA transfers have to +be terminated, otherwise the dmaengine driver fails to operate properly, +when the card is re-inserted. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit e3de2be7368d2983bd7f7ddb6e9cf5ea32363128) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 7 ++++++- + drivers/mmc/host/tmio_mmc_dma.c | 12 ++++++++++++ + drivers/mmc/host/tmio_mmc_pio.c | 6 +++++- + 3 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index a95e6d9..f96c536 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -20,8 +20,8 @@ + #include <linux/mmc/tmio.h> + #include <linux/mutex.h> + #include <linux/pagemap.h> +-#include <linux/spinlock.h> + #include <linux/scatterlist.h> ++#include <linux/spinlock.h> + + /* Definitions for values the CTRL_SDIO_STATUS register can take. */ + #define TMIO_SDIO_STAT_IOIRQ 0x0001 +@@ -120,6 +120,7 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data); + void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable); + void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); + void tmio_mmc_release_dma(struct tmio_mmc_host *host); ++void tmio_mmc_abort_dma(struct tmio_mmc_host *host); + #else + static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host, + struct mmc_data *data) +@@ -140,6 +141,10 @@ static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host, + static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host) + { + } ++ ++static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host) ++{ ++} + #endif + + #ifdef CONFIG_PM +diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c +index 7a6e6cc..8253ec1 100644 +--- a/drivers/mmc/host/tmio_mmc_dma.c ++++ b/drivers/mmc/host/tmio_mmc_dma.c +@@ -34,6 +34,18 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) + #endif + } + ++void tmio_mmc_abort_dma(struct tmio_mmc_host *host) ++{ ++ tmio_mmc_enable_dma(host, false); ++ ++ if (host->chan_rx) ++ dmaengine_terminate_all(host->chan_rx); ++ if (host->chan_tx) ++ dmaengine_terminate_all(host->chan_tx); ++ ++ tmio_mmc_enable_dma(host, true); ++} ++ + static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) + { + struct scatterlist *sg = host->sg_ptr, *sg_tmp; +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index abad01b..5f9ad74 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -41,8 +41,8 @@ + #include <linux/platform_device.h> + #include <linux/pm_runtime.h> + #include <linux/scatterlist.h> +-#include <linux/workqueue.h> + #include <linux/spinlock.h> ++#include <linux/workqueue.h> + + #include "tmio_mmc.h" + +@@ -246,6 +246,7 @@ static void tmio_mmc_reset_work(struct work_struct *work) + /* Ready for new calls */ + host->mrq = NULL; + ++ tmio_mmc_abort_dma(host); + mmc_request_done(host->mmc, mrq); + } + +@@ -272,6 +273,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) + host->mrq = NULL; + spin_unlock_irqrestore(&host->lock, flags); + ++ if (mrq->cmd->error || (mrq->data && mrq->data->error)) ++ tmio_mmc_abort_dma(host); ++ + mmc_request_done(host->mmc, mrq); + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0045-mmc-tmio_mmc-do-not-enable-card-hotplug-interrupts-i.patch b/patches.kzm9g/0045-mmc-tmio_mmc-do-not-enable-card-hotplug-interrupts-i.patch new file mode 100644 index 00000000000000..fbf34ec4499e10 --- /dev/null +++ b/patches.kzm9g/0045-mmc-tmio_mmc-do-not-enable-card-hotplug-interrupts-i.patch @@ -0,0 +1,53 @@ +From aa83922dbd8c0d4e16cbc28fae2d59a6d709ed07 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 22 Feb 2012 13:16:09 +0100 +Subject: mmc: tmio_mmc: do not enable card hotplug interrupts, if unused + +If TMIO MMC is used in polling mode, or the card is non-removable, or +card-detection is performed, using an external interrupt, there is no +need to enable controller native card hotplug interrupts. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit e23cd53c799694d0dc1d6a66370201ad9c181bae) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 5f9ad74..f013347 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -303,6 +303,7 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command + { + struct mmc_data *data = host->data; + int c = cmd->opcode; ++ u32 irq_mask = TMIO_MASK_CMD; + + /* Command 12 is handled by hardware */ + if (cmd->opcode == 12 && !cmd->arg) { +@@ -338,7 +339,9 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command + c |= TRANSFER_READ; + } + +- tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_CMD); ++ if (!host->native_hotplug) ++ irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); ++ tmio_mmc_enable_mmc_irqs(host, irq_mask); + + /* Fire off the command */ + sd_ctrl_write32(host, CTL_ARG_REG, cmd->arg); +@@ -960,6 +963,8 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + irq_mask |= TMIO_MASK_READOP; + if (!_host->chan_tx) + irq_mask |= TMIO_MASK_WRITEOP; ++ if (!_host->native_hotplug) ++ irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); + + tmio_mmc_enable_mmc_irqs(_host, irq_mask); + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0046-mmc-tmio-calculate-the-native-hotplug-condition-only.patch b/patches.kzm9g/0046-mmc-tmio-calculate-the-native-hotplug-condition-only.patch new file mode 100644 index 00000000000000..f2e1b51a51d4d0 --- /dev/null +++ b/patches.kzm9g/0046-mmc-tmio-calculate-the-native-hotplug-condition-only.patch @@ -0,0 +1,71 @@ +From ca17c6399644d13094702101c3a3960445a465dd Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 9 Feb 2012 22:57:08 +0100 +Subject: mmc: tmio: calculate the native hotplug condition only once + +The condition, whether we have to use the native TMIO card hotplug +detection interrupt, is rather complex, it is better to only calculate it +once and store in the private data. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 2b1ac5c2caccbfd43bd616321cbbe21eb33c7879) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 1 + + drivers/mmc/host/tmio_mmc_pio.c | 12 ++++++------ + 2 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index f96c536..8531d8d 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -86,6 +86,7 @@ struct tmio_mmc_host { + spinlock_t lock; /* protect host private data */ + unsigned long last_req_ts; + struct mutex ios_lock; /* protect set_ios() context */ ++ bool native_hotplug; + }; + + int tmio_mmc_host_probe(struct tmio_mmc_host **host, +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index f013347..0a111f4 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -915,6 +915,10 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + else + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + ++ _host->native_hotplug = !(pdata->flags & TMIO_MMC_HAS_COLD_CD || ++ mmc->caps & MMC_CAP_NEEDS_POLL || ++ mmc->caps & MMC_CAP_NONREMOVABLE); ++ + pdata->power = false; + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_resume(&pdev->dev); +@@ -933,9 +937,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + * additionally ensure that in case 2) the tmio mmc hardware stays + * powered on during runtime for the card detection to work. + */ +- if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD +- || mmc->caps & MMC_CAP_NEEDS_POLL +- || mmc->caps & MMC_CAP_NONREMOVABLE)) ++ if (_host->native_hotplug) + pm_runtime_get_noresume(&pdev->dev); + + tmio_mmc_clk_stop(_host); +@@ -993,9 +995,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) + * the controller, the runtime PM is suspended and pdata->power == false, + * so, our .runtime_resume() will not try to detect a card in the slot. + */ +- if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD +- || host->mmc->caps & MMC_CAP_NEEDS_POLL +- || host->mmc->caps & MMC_CAP_NONREMOVABLE) ++ if (!host->native_hotplug) + pm_runtime_get_sync(&pdev->dev); + + mmc_remove_host(host->mmc); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0047-mmc-tmio_mmc-support-the-generic-MMC-GPIO-card-hotpl.patch b/patches.kzm9g/0047-mmc-tmio_mmc-support-the-generic-MMC-GPIO-card-hotpl.patch new file mode 100644 index 00000000000000..5d839b0bb05098 --- /dev/null +++ b/patches.kzm9g/0047-mmc-tmio_mmc-support-the-generic-MMC-GPIO-card-hotpl.patch @@ -0,0 +1,255 @@ +From 8605d396d99e7c52ec9a8b5f67835735ce9fa7c2 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 9 Feb 2012 22:57:09 +0100 +Subject: mmc: tmio_mmc: support the generic MMC GPIO card hotplug helper + +If the platform specifies the TMIO_MMC_HAS_COLD_CD flag, use the generic +MMC GPIO card hotplug helper. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit c8be24c2afd3ed2445bbf8f542af35a9787fc0e8) + +Conflicts: + + drivers/mmc/host/tmio_mmc_pio.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 4 --- + drivers/mmc/host/tmio_mmc_pio.c | 67 ++++++++++++++++++----------------------- + include/linux/mfd/tmio.h | 25 +++++++++++---- + 3 files changed, 49 insertions(+), 47 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index 8531d8d..ede2f4e5 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -53,10 +53,6 @@ struct tmio_mmc_host { + void (*set_pwr)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); + +- int pm_error; +- /* recognise system-wide suspend in runtime PM methods */ +- bool pm_global; +- + /* pio related stuff */ + struct scatterlist *sg_ptr; + struct scatterlist *sg_orig; +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 0a111f4..ce5f126 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -34,6 +34,7 @@ + #include <linux/io.h> + #include <linux/irq.h> + #include <linux/mfd/tmio.h> ++#include <linux/mmc/cd-gpio.h> + #include <linux/mmc/host.h> + #include <linux/mmc/tmio.h> + #include <linux/module.h> +@@ -790,8 +791,10 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + spin_unlock_irqrestore(&host->lock, flags); + + /* +- * pdata->power == false only if COLD_CD is available, otherwise only +- * in short time intervals during probing or resuming ++ * pdata->power toggles between false and true in both cases - either ++ * or not the controller can be runtime-suspended during inactivity. ++ * But if the controller has to be kept on, the runtime-pm usage_count ++ * is kept positive, so no suspending actually takes place. + */ + if (ios->power_mode == MMC_POWER_ON && ios->clock) { + if (!pdata->power) { +@@ -915,7 +918,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + else + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + +- _host->native_hotplug = !(pdata->flags & TMIO_MMC_HAS_COLD_CD || ++ _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD || + mmc->caps & MMC_CAP_NEEDS_POLL || + mmc->caps & MMC_CAP_NONREMOVABLE); + +@@ -932,8 +935,9 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + * 3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL + * 4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE + * +- * While we increment the rtpm counter for all scenarios when the mmc +- * core activates us by calling an appropriate set_ios(), we must ++ * While we increment the runtime PM counter for all scenarios when ++ * the mmc core activates us by calling an appropriate set_ios(), we ++ * must additionally ensure that in case 2) the tmio mmc hardware stays + * additionally ensure that in case 2) the tmio mmc hardware stays + * powered on during runtime for the card detection to work. + */ +@@ -970,6 +974,14 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + + tmio_mmc_enable_mmc_irqs(_host, irq_mask); + ++ if (pdata->flags & TMIO_MMC_USE_GPIO_CD) { ++ ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio); ++ if (ret < 0) { ++ tmio_mmc_host_remove(_host); ++ return ret; ++ } ++ } ++ + *host = _host; + + return 0; +@@ -987,14 +999,16 @@ EXPORT_SYMBOL(tmio_mmc_host_probe); + void tmio_mmc_host_remove(struct tmio_mmc_host *host) + { + struct platform_device *pdev = host->pdev; ++ struct tmio_mmc_data *pdata = host->pdata; ++ struct mmc_host *mmc = host->mmc; ++ ++ if (pdata->flags & TMIO_MMC_USE_GPIO_CD) ++ /* ++ * This means we can miss a card-eject, but this is anyway ++ * possible, because of delayed processing of hotplug events. ++ */ ++ mmc_cd_gpio_free(mmc); + +- /* +- * We don't have to manipulate pdata->power here: if there is a card in +- * the slot, the runtime PM is active and our .runtime_resume() will not +- * be run. If there is no card in the slot and the platform can suspend +- * the controller, the runtime PM is suspended and pdata->power == false, +- * so, our .runtime_resume() will not try to detect a card in the slot. +- */ + if (!host->native_hotplug) + pm_runtime_get_sync(&pdev->dev); + +@@ -1007,7 +1021,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) + pm_runtime_disable(&pdev->dev); + + iounmap(host->ctl); +- mmc_free_host(host->mmc); ++ mmc_free_host(mmc); + } + EXPORT_SYMBOL(tmio_mmc_host_remove); + +@@ -1021,8 +1035,6 @@ int tmio_mmc_host_suspend(struct device *dev) + if (!ret) + tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); + +- host->pm_error = pm_runtime_put_sync(dev); +- + return ret; + } + EXPORT_SYMBOL(tmio_mmc_host_suspend); +@@ -1032,20 +1044,10 @@ int tmio_mmc_host_resume(struct device *dev) + struct mmc_host *mmc = dev_get_drvdata(dev); + struct tmio_mmc_host *host = mmc_priv(mmc); + +- /* The MMC core will perform the complete set up */ +- host->pdata->power = false; +- +- host->pm_global = true; +- if (!host->pm_error) +- pm_runtime_get_sync(dev); +- +- if (host->pm_global) { +- /* Runtime PM resume callback didn't run */ +- tmio_mmc_reset(host); +- tmio_mmc_enable_dma(host, true); +- host->pm_global = false; +- } ++ tmio_mmc_reset(host); ++ tmio_mmc_enable_dma(host, true); + ++ /* The MMC core will perform the complete set up */ + return mmc_resume_host(mmc); + } + EXPORT_SYMBOL(tmio_mmc_host_resume); +@@ -1062,19 +1064,10 @@ int tmio_mmc_host_runtime_resume(struct device *dev) + { + struct mmc_host *mmc = dev_get_drvdata(dev); + struct tmio_mmc_host *host = mmc_priv(mmc); +- struct tmio_mmc_data *pdata = host->pdata; + + tmio_mmc_reset(host); + tmio_mmc_enable_dma(host, true); + +- if (pdata->power) { +- /* Only entered after a card-insert interrupt */ +- if (!mmc->card) +- tmio_mmc_set_ios(mmc, &mmc->ios); +- mmc_detect_change(mmc, msecs_to_jiffies(100)); +- } +- host->pm_global = false; +- + return 0; + } + EXPORT_SYMBOL(tmio_mmc_host_runtime_resume); +diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h +index 0dc9804..5a197de 100644 +--- a/include/linux/mfd/tmio.h ++++ b/include/linux/mfd/tmio.h +@@ -1,8 +1,10 @@ + #ifndef MFD_TMIO_H + #define MFD_TMIO_H + ++#include <linux/device.h> + #include <linux/fb.h> + #include <linux/io.h> ++#include <linux/jiffies.h> + #include <linux/platform_device.h> + #include <linux/pm_runtime.h> + +@@ -64,8 +66,8 @@ + #define TMIO_MMC_SDIO_IRQ (1 << 2) + /* + * Some platforms can detect card insertion events with controller powered +- * down, in which case they have to call tmio_mmc_cd_wakeup() to power up the +- * controller and report the event to the driver. ++ * down, using a GPIO IRQ, in which case they have to fill in cd_irq, cd_gpio, ++ * and cd_flags fields of struct tmio_mmc_data. + */ + #define TMIO_MMC_HAS_COLD_CD (1 << 3) + /* +@@ -73,6 +75,12 @@ + * idle before writing to some registers. + */ + #define TMIO_MMC_HAS_IDLE_WAIT (1 << 4) ++/* ++ * A GPIO is used for card hotplug detection. We need an extra flag for this, ++ * because 0 is a valid GPIO number too, and requiring users to specify ++ * cd_gpio < 0 to disable GPIO hotplug would break backwards compatibility. ++ */ ++#define TMIO_MMC_USE_GPIO_CD (1 << 5) + + int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base); + int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base); +@@ -98,18 +106,23 @@ struct tmio_mmc_data { + struct tmio_mmc_dma *dma; + struct device *dev; + bool power; ++ unsigned int cd_gpio; + void (*set_pwr)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); + int (*get_cd)(struct platform_device *host); + int (*write16_hook)(struct tmio_mmc_host *host, int addr); + }; + ++/* ++ * This function is deprecated and will be removed soon. Please, convert your ++ * platform to use drivers/mmc/core/cd-gpio.c ++ */ ++#include <linux/mmc/host.h> + static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata) + { +- if (pdata && !pdata->power) { +- pdata->power = true; +- pm_runtime_get(pdata->dev); +- } ++ if (pdata) ++ mmc_detect_change(dev_get_drvdata(pdata->dev), ++ msecs_to_jiffies(100)); + } + + /* +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0048-mmc-sh_mobile_sdhi-pass-card-hotplug-GPIO-number-to-.patch b/patches.kzm9g/0048-mmc-sh_mobile_sdhi-pass-card-hotplug-GPIO-number-to-.patch new file mode 100644 index 00000000000000..48b733b7c362b7 --- /dev/null +++ b/patches.kzm9g/0048-mmc-sh_mobile_sdhi-pass-card-hotplug-GPIO-number-to-.patch @@ -0,0 +1,55 @@ +From 4c75a4614497dab36aeb8a5a033ae5da1cb18a98 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 9 Feb 2012 22:57:10 +0100 +Subject: mmc: sh_mobile_sdhi: pass card hotplug GPIO number to TMIO MMC + +To use TMIO MMC driver ability to interface to the generic MMC GPIO card +hotplug detection helper, the SDHI driver has to pass the GPIO number +from its own platform data. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 58126c878b4a4f658015e383614bafb6331e46d3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 3 ++- + include/linux/mmc/sh_mobile_sdhi.h | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 58da3c4..cb279b4 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -129,6 +129,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + mmc_data->write16_hook = sh_mobile_sdhi_write16_hook; + mmc_data->ocr_mask = p->tmio_ocr_mask; + mmc_data->capabilities |= p->tmio_caps; ++ mmc_data->cd_gpio = p->cd_gpio; + + if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { + priv->param_tx.slave_id = p->dma_slave_tx; +@@ -211,7 +212,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + + dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n", + mmc_hostname(host->mmc), (unsigned long) +- (platform_get_resource(pdev,IORESOURCE_MEM, 0)->start), ++ (platform_get_resource(pdev, IORESOURCE_MEM, 0)->start), + mmc_data->hclk / 1000000); + + return ret; +diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h +index 71b8054..082a736 100644 +--- a/include/linux/mmc/sh_mobile_sdhi.h ++++ b/include/linux/mmc/sh_mobile_sdhi.h +@@ -16,6 +16,7 @@ struct sh_mobile_sdhi_info { + unsigned long tmio_flags; + unsigned long tmio_caps; + u32 tmio_ocr_mask; /* available MMC voltages */ ++ unsigned int cd_gpio; + struct tmio_mmc_data *pdata; + void (*set_pwr)(struct platform_device *pdev, int state); + int (*get_cd)(struct platform_device *pdev); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0049-mmc-tmio_mmc-power-status-flag-doesn-t-have-to-be-ex.patch b/patches.kzm9g/0049-mmc-tmio_mmc-power-status-flag-doesn-t-have-to-be-ex.patch new file mode 100644 index 00000000000000..c11b9bb76837a2 --- /dev/null +++ b/patches.kzm9g/0049-mmc-tmio_mmc-power-status-flag-doesn-t-have-to-be-ex.patch @@ -0,0 +1,101 @@ +From 9c90215e8425dad06659dcb19f69b7c62d5de92a Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 9 Feb 2012 22:57:13 +0100 +Subject: mmc: tmio_mmc: power status flag doesn't have to be exposed in + platform data + +The controller power status flag does not have to be accessed from the +hot-plug detection code any more, it can now be removed from the platform +data and put in the controller private struct. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit c391e1b9ebfe31514fa95a0cdd30c2cbc9652c89) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 3 +++ + drivers/mmc/host/tmio_mmc_pio.c | 13 ++++++------- + include/linux/mfd/tmio.h | 1 - + 3 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index ede2f4e5..edfcfd7 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -49,6 +49,9 @@ struct tmio_mmc_host { + struct mmc_host *mmc; + unsigned int sdio_irq_enabled; + ++ /* Controller power state */ ++ bool power; ++ + /* Callbacks for clock / power control */ + void (*set_pwr)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index ce5f126..4a2829c 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -761,7 +761,6 @@ fail: + static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct tmio_mmc_host *host = mmc_priv(mmc); +- struct tmio_mmc_data *pdata = host->pdata; + unsigned long flags; + + mutex_lock(&host->ios_lock); +@@ -791,15 +790,15 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + spin_unlock_irqrestore(&host->lock, flags); + + /* +- * pdata->power toggles between false and true in both cases - either ++ * host->power toggles between false and true in both cases - either + * or not the controller can be runtime-suspended during inactivity. + * But if the controller has to be kept on, the runtime-pm usage_count + * is kept positive, so no suspending actually takes place. + */ + if (ios->power_mode == MMC_POWER_ON && ios->clock) { +- if (!pdata->power) { ++ if (!host->power) { + pm_runtime_get_sync(&host->pdev->dev); +- pdata->power = true; ++ host->power = true; + } + tmio_mmc_set_clock(host, ios->clock); + /* power up SD bus */ +@@ -810,8 +809,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + } else if (ios->power_mode != MMC_POWER_UP) { + if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) + host->set_pwr(host->pdev, 0); +- if (pdata->power) { +- pdata->power = false; ++ if (host->power) { ++ host->power = false; + pm_runtime_put(&host->pdev->dev); + } + tmio_mmc_clk_stop(host); +@@ -922,7 +921,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + mmc->caps & MMC_CAP_NEEDS_POLL || + mmc->caps & MMC_CAP_NONREMOVABLE); + +- pdata->power = false; ++ _host->power = false; + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_resume(&pdev->dev); + if (ret < 0) +diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h +index 5a197de..f5171db 100644 +--- a/include/linux/mfd/tmio.h ++++ b/include/linux/mfd/tmio.h +@@ -105,7 +105,6 @@ struct tmio_mmc_data { + u32 ocr_mask; /* available voltages */ + struct tmio_mmc_dma *dma; + struct device *dev; +- bool power; + unsigned int cd_gpio; + void (*set_pwr)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0050-mmc-tmio_mmc-remove-unused-sdio_irq_enabled-flag.patch b/patches.kzm9g/0050-mmc-tmio_mmc-remove-unused-sdio_irq_enabled-flag.patch new file mode 100644 index 00000000000000..0e15dcedde89cd --- /dev/null +++ b/patches.kzm9g/0050-mmc-tmio_mmc-remove-unused-sdio_irq_enabled-flag.patch @@ -0,0 +1,54 @@ +From a863686f8649014af31553e5d294fb6fc34a0406 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 9 Feb 2012 22:57:14 +0100 +Subject: mmc: tmio_mmc: remove unused sdio_irq_enabled flag + +The sdio_irq_enabled member of struct tmio_mmc_host is a left-over from the +previously removed SDIO IRQ workaround. It is no longer needed and can now +be removed too. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 5bd99c375e141b8dd12e18c45617158f98920e57) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc.h | 1 - + drivers/mmc/host/tmio_mmc_pio.c | 2 -- + 2 files changed, 3 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index edfcfd7..d857f5c 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -47,7 +47,6 @@ struct tmio_mmc_host { + struct mmc_request *mrq; + struct mmc_data *data; + struct mmc_host *mmc; +- unsigned int sdio_irq_enabled; + + /* Controller power state */ + bool power; +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 4a2829c..97110ba 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -127,7 +127,6 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + struct tmio_mmc_host *host = mmc_priv(mmc); + + if (enable) { +- host->sdio_irq_enabled = 1; + host->sdio_irq_mask = TMIO_SDIO_MASK_ALL & + ~TMIO_SDIO_STAT_IOIRQ; + sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); +@@ -136,7 +135,6 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + host->sdio_irq_mask = TMIO_SDIO_MASK_ALL; + sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); + sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000); +- host->sdio_irq_enabled = 0; + } + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0051-mmc-sh_mobile_sdhi-do-not-manage-PM-clocks-manually.patch b/patches.kzm9g/0051-mmc-sh_mobile_sdhi-do-not-manage-PM-clocks-manually.patch new file mode 100644 index 00000000000000..3d6c1a941d4438 --- /dev/null +++ b/patches.kzm9g/0051-mmc-sh_mobile_sdhi-do-not-manage-PM-clocks-manually.patch @@ -0,0 +1,52 @@ +From 3305f89b5921cc5a8174d1fa302be7ff8fd7085b Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 9 Feb 2012 22:57:15 +0100 +Subject: mmc: sh_mobile_sdhi: do not manage PM clocks manually + +On sh-mobile platforms the MMC clock frequency for the TMIO MMC unit is +obtained from the same clock, as the one, that runtime power-manages the +controller. The SDHI glue code has to access that clock directly, +bypassing the runtime PM framework, to get its frequency, but it +shouldn't enable or disable it. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 996bc8aebd2cd5b6d4c5d85085f171fa2447f364) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index cb279b4..f91c3aa 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -117,8 +117,6 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + goto eclkget; + } + +- clk_enable(priv->clk); +- + mmc_data->hclk = clk_get_rate(priv->clk); + mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; + mmc_data->get_cd = sh_mobile_sdhi_get_cd; +@@ -233,7 +231,6 @@ eirq_sdio: + eirq_card_detect: + tmio_mmc_host_remove(host); + eprobe: +- clk_disable(priv->clk); + clk_put(priv->clk); + eclkget: + kfree(priv); +@@ -259,7 +256,6 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) + free_irq(irq, host); + } + +- clk_disable(priv->clk); + clk_put(priv->clk); + kfree(priv); + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0052-mmc-tmio-cosmetic-prettify-the-tmio_mmc_set_ios-func.patch b/patches.kzm9g/0052-mmc-tmio-cosmetic-prettify-the-tmio_mmc_set_ios-func.patch new file mode 100644 index 00000000000000..f4c6d66f0d0095 --- /dev/null +++ b/patches.kzm9g/0052-mmc-tmio-cosmetic-prettify-the-tmio_mmc_set_ios-func.patch @@ -0,0 +1,63 @@ +From 62da637655deae3561b0ba9fd230afa6e15cc221 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 9 Feb 2012 22:57:16 +0100 +Subject: mmc: tmio: cosmetic: prettify the tmio_mmc_set_ios() function + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 4932bd64a2bb4e80b79efb20c4736ac3b30ba7fe) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 97110ba..2500163 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -759,6 +759,7 @@ fail: + static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct tmio_mmc_host *host = mmc_priv(mmc); ++ struct device *dev = &host->pdev->dev; + unsigned long flags; + + mutex_lock(&host->ios_lock); +@@ -766,13 +767,13 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + spin_lock_irqsave(&host->lock, flags); + if (host->mrq) { + if (IS_ERR(host->mrq)) { +- dev_dbg(&host->pdev->dev, ++ dev_dbg(dev, + "%s.%d: concurrent .set_ios(), clk %u, mode %u\n", + current->comm, task_pid_nr(current), + ios->clock, ios->power_mode); + host->mrq = ERR_PTR(-EINTR); + } else { +- dev_dbg(&host->pdev->dev, ++ dev_dbg(dev, + "%s.%d: CMD%u active since %lu, now %lu!\n", + current->comm, task_pid_nr(current), + host->mrq->cmd->opcode, host->last_req_ts, jiffies); +@@ -795,7 +796,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + */ + if (ios->power_mode == MMC_POWER_ON && ios->clock) { + if (!host->power) { +- pm_runtime_get_sync(&host->pdev->dev); ++ pm_runtime_get_sync(dev); + host->power = true; + } + tmio_mmc_set_clock(host, ios->clock); +@@ -809,7 +810,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + host->set_pwr(host->pdev, 0); + if (host->power) { + host->power = false; +- pm_runtime_put(&host->pdev->dev); ++ pm_runtime_put(dev); + } + tmio_mmc_clk_stop(host); + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0053-mmc-sh_mobile_sdhi-add-a-callback-for-board-specific.patch b/patches.kzm9g/0053-mmc-sh_mobile_sdhi-add-a-callback-for-board-specific.patch new file mode 100644 index 00000000000000..58860876e860ab --- /dev/null +++ b/patches.kzm9g/0053-mmc-sh_mobile_sdhi-add-a-callback-for-board-specific.patch @@ -0,0 +1,74 @@ +From 0a98733a6514780187f2f435f3057949932d531b Mon Sep 17 00:00:00 2001 +From: Bastian Hecht <hechtb@googlemail.com> +Date: Fri, 16 Mar 2012 12:19:29 -0400 +Subject: mmc: sh_mobile_sdhi: add a callback for board specific init code + +Some boards need a preliminary setup stage to prepare the sdhi +controller. + +Signed-off-by: Bastian Hecht <hechtb@gmail.com> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit e82b4ac94e5c43fad51b975aed058858ceda1f0f) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 13 +++++++++++++ + include/linux/mmc/sh_mobile_sdhi.h | 4 ++++ + 2 files changed, 17 insertions(+) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index f91c3aa..07ff3fe 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -109,6 +109,12 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + mmc_data = &priv->mmc_data; + p->pdata = mmc_data; + ++ if (p->init) { ++ ret = p->init(pdev); ++ if (ret) ++ goto einit; ++ } ++ + snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id); + priv->clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(priv->clk)) { +@@ -233,6 +239,9 @@ eirq_card_detect: + eprobe: + clk_put(priv->clk); + eclkget: ++ if (p->cleanup) ++ p->cleanup(pdev); ++einit: + kfree(priv); + return ret; + } +@@ -257,6 +266,10 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) + } + + clk_put(priv->clk); ++ ++ if (p->cleanup) ++ p->cleanup(pdev); ++ + kfree(priv); + + return 0; +diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h +index 082a736..686b85b 100644 +--- a/include/linux/mmc/sh_mobile_sdhi.h ++++ b/include/linux/mmc/sh_mobile_sdhi.h +@@ -20,6 +20,10 @@ struct sh_mobile_sdhi_info { + struct tmio_mmc_data *pdata; + void (*set_pwr)(struct platform_device *pdev, int state); + int (*get_cd)(struct platform_device *pdev); ++ ++ /* callbacks for board specific setup code */ ++ int (*init)(struct platform_device *pdev); ++ void (*cleanup)(struct platform_device *pdev); + }; + + #endif /* LINUX_MMC_SH_MOBILE_SDHI_H */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0054-mmc-sh_mobile_sdhi-support-modular-mmc-core-with-non.patch b/patches.kzm9g/0054-mmc-sh_mobile_sdhi-support-modular-mmc-core-with-non.patch new file mode 100644 index 00000000000000..bbffae5a0f631f --- /dev/null +++ b/patches.kzm9g/0054-mmc-sh_mobile_sdhi-support-modular-mmc-core-with-non.patch @@ -0,0 +1,85 @@ +From 0107e6bd1c3993bcd3cefb7406bff5976921bced Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Fri, 9 Mar 2012 10:16:00 +0100 +Subject: mmc: sh_mobile_sdhi: support modular mmc-core with non-standard + hotplug + +Currently if a platform wants to implement a non-standard card-detection +method, it would need to call tmio_mmc_cd_wakeup(), which is an inline +function, calling mmc_detect_change(). For this the platform would have +to link mmc_core statically into the kernel, losing the ability to build +it as a module. This patch adds a callback to the sh_mobile_sdhi driver, +which eliminates this dependency. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 7f524217439cc17da74523582c303cced432713e) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 11 ++++++++++- + include/linux/mmc/sh_mobile_sdhi.h | 11 ++++++++++- + 2 files changed, 20 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 07ff3fe..934b68e 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -90,6 +90,15 @@ static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) + return 0; + } + ++static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev) ++{ ++ mmc_detect_change(dev_get_drvdata(&pdev->dev), msecs_to_jiffies(100)); ++} ++ ++static const struct sh_mobile_sdhi_ops sdhi_ops = { ++ .cd_wakeup = sh_mobile_sdhi_cd_wakeup, ++}; ++ + static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + { + struct sh_mobile_sdhi *priv; +@@ -110,7 +119,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + p->pdata = mmc_data; + + if (p->init) { +- ret = p->init(pdev); ++ ret = p->init(pdev, &sdhi_ops); + if (ret) + goto einit; + } +diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h +index 686b85b..e94e620 100644 +--- a/include/linux/mmc/sh_mobile_sdhi.h ++++ b/include/linux/mmc/sh_mobile_sdhi.h +@@ -10,6 +10,14 @@ struct tmio_mmc_data; + #define SH_MOBILE_SDHI_IRQ_SDCARD "sdcard" + #define SH_MOBILE_SDHI_IRQ_SDIO "sdio" + ++/** ++ * struct sh_mobile_sdhi_ops - SDHI driver callbacks ++ * @cd_wakeup: trigger a card-detection run ++ */ ++struct sh_mobile_sdhi_ops { ++ void (*cd_wakeup)(const struct platform_device *pdev); ++}; ++ + struct sh_mobile_sdhi_info { + int dma_slave_tx; + int dma_slave_rx; +@@ -22,7 +30,8 @@ struct sh_mobile_sdhi_info { + int (*get_cd)(struct platform_device *pdev); + + /* callbacks for board specific setup code */ +- int (*init)(struct platform_device *pdev); ++ int (*init)(struct platform_device *pdev, ++ const struct sh_mobile_sdhi_ops *ops); + void (*cleanup)(struct platform_device *pdev); + }; + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0055-mmc-Standardize-header-file-inclusion-checks.patch b/patches.kzm9g/0055-mmc-Standardize-header-file-inclusion-checks.patch new file mode 100644 index 00000000000000..2ba0ecbdc76767 --- /dev/null +++ b/patches.kzm9g/0055-mmc-Standardize-header-file-inclusion-checks.patch @@ -0,0 +1,61 @@ +From 905868b59a760b3df8ce9ae406534a8299e0a0e2 Mon Sep 17 00:00:00 2001 +From: "Robert P. J. Day" <rpjday@crashcourse.ca> +Date: Fri, 27 May 2011 16:04:03 -0400 +Subject: mmc: Standardize header file inclusion checks. + +Standardize the checks for multiple MMC header file inclusion, +including adding comments to terminating #endif's, and fixing +one incorrect comment. + +Signed-off-by: Robert P. J. Day <rpjday@crashcourse.ca> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 100e918610b7487fa18db97b3879cd8d1fdd5974) + +Conflicts: + + include/linux/mmc/boot.h + include/linux/mmc/card.h + include/linux/mmc/core.h + include/linux/mmc/dw_mmc.h + include/linux/mmc/host.h + include/linux/mmc/ioctl.h + include/linux/mmc/mmc.h + include/linux/mmc/pm.h + include/linux/mmc/sd.h + include/linux/mmc/sdhci-spear.h + include/linux/mmc/sdhci.h + include/linux/mmc/sdio.h + include/linux/mmc/sdio_func.h + include/linux/mmc/sdio_ids.h + include/linux/mmc/sh_mobile_sdhi.h + include/linux/mmc/tmio.h + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/mmc/sh_mmcif.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h +index 9eb9b4b..0222cd8 100644 +--- a/include/linux/mmc/sh_mmcif.h ++++ b/include/linux/mmc/sh_mmcif.h +@@ -11,8 +11,8 @@ + * + */ + +-#ifndef __SH_MMCIF_H__ +-#define __SH_MMCIF_H__ ++#ifndef LINUX_MMC_SH_MMCIF_H ++#define LINUX_MMC_SH_MMCIF_H + + #include <linux/io.h> + #include <linux/platform_device.h> +@@ -220,4 +220,4 @@ static inline void sh_mmcif_boot_init(void __iomem *base) + sh_mmcif_boot_cmd(base, 0x03400040, 0x00010000); + } + +-#endif /* __SH_MMCIF_H__ */ ++#endif /* LINUX_MMC_SH_MMCIF_H */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0056-mmc-sh_mmcif-maximize-power-saving.patch b/patches.kzm9g/0056-mmc-sh_mmcif-maximize-power-saving.patch new file mode 100644 index 00000000000000..28e6383a2bf9f9 --- /dev/null +++ b/patches.kzm9g/0056-mmc-sh_mmcif-maximize-power-saving.patch @@ -0,0 +1,82 @@ +From 896e44c328f1ab6c44097333ba1db7ae3a08ff5d Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 26 May 2011 15:33:30 +0200 +Subject: mmc: sh_mmcif: maximize power saving + +This patch uses runtime PM to allow the system to power down the MMC +controller, when the MMC closk is switched off. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit c9b0cef23f8d2a16c97623d25d6e8f8e93a56e4b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 27 ++++++++++++++++++--------- + 1 file changed, 18 insertions(+), 9 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 14f8edb..557886b 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -175,6 +175,7 @@ struct sh_mmcif_host { + enum mmcif_state state; + spinlock_t lock; + bool power; ++ bool card_present; + + /* DMA support */ + struct dma_chan *chan_rx; +@@ -877,23 +878,23 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + spin_unlock_irqrestore(&host->lock, flags); + + if (ios->power_mode == MMC_POWER_UP) { +- if (p->set_pwr) +- p->set_pwr(host->pd, ios->power_mode); +- if (!host->power) { ++ if (!host->card_present) { + /* See if we also get DMA */ + sh_mmcif_request_dma(host, host->pd->dev.platform_data); +- pm_runtime_get_sync(&host->pd->dev); +- host->power = true; ++ host->card_present = true; + } + } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) { + /* clock stop */ + sh_mmcif_clock_control(host, 0); + if (ios->power_mode == MMC_POWER_OFF) { +- if (host->power) { +- pm_runtime_put(&host->pd->dev); ++ if (host->card_present) { + sh_mmcif_release_dma(host); +- host->power = false; ++ host->card_present = false; + } ++ } ++ if (host->power) { ++ pm_runtime_put(&host->pd->dev); ++ host->power = false; + if (p->down_pwr) + p->down_pwr(host->pd); + } +@@ -901,8 +902,16 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + return; + } + +- if (ios->clock) ++ if (ios->clock) { ++ if (!host->power) { ++ if (p->set_pwr) ++ p->set_pwr(host->pd, ios->power_mode); ++ pm_runtime_get_sync(&host->pd->dev); ++ host->power = true; ++ sh_mmcif_sync_reset(host); ++ } + sh_mmcif_clock_control(host, ios->clock); ++ } + + host->bus_width = ios->bus_width; + host->state = STATE_IDLE; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0057-mmc-sh_mmcif-simplify-platform-data.patch b/patches.kzm9g/0057-mmc-sh_mmcif-simplify-platform-data.patch new file mode 100644 index 00000000000000..3197c322c9b371 --- /dev/null +++ b/patches.kzm9g/0057-mmc-sh_mmcif-simplify-platform-data.patch @@ -0,0 +1,89 @@ +From e269a3b04e790e2b0c18d19a64358706363f9ace Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 30 Aug 2011 18:26:39 +0200 +Subject: mmc: sh_mmcif: simplify platform data + +Provide platforms with a simplified way to specify MMCIF DMA slave IDs in +a way, similar to SDHI and other sh_dma clients. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 714c4a6e3a0f730834ec8a8bc83b2a6da33f54dc) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 20 ++++++++++++++++---- + include/linux/mmc/sh_mmcif.h | 4 +++- + 2 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 557886b..bd91c94 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -165,6 +165,8 @@ struct sh_mmcif_host { + struct mmc_host *mmc; + struct mmc_data *data; + struct platform_device *pd; ++ struct sh_dmae_slave dma_slave_tx; ++ struct sh_dmae_slave dma_slave_rx; + struct clk *hclk; + unsigned int clk; + int bus_width; +@@ -323,25 +325,35 @@ static bool sh_mmcif_filter(struct dma_chan *chan, void *arg) + static void sh_mmcif_request_dma(struct sh_mmcif_host *host, + struct sh_mmcif_plat_data *pdata) + { ++ struct sh_dmae_slave *tx, *rx; + host->dma_active = false; + + /* We can only either use DMA for both Tx and Rx or not use it at all */ + if (pdata->dma) { ++ dev_warn(&host->pd->dev, ++ "Update your platform to use embedded DMA slave IDs\n"); ++ tx = &pdata->dma->chan_priv_tx; ++ rx = &pdata->dma->chan_priv_rx; ++ } else { ++ tx = &host->dma_slave_tx; ++ tx->slave_id = pdata->slave_id_tx; ++ rx = &host->dma_slave_rx; ++ rx->slave_id = pdata->slave_id_rx; ++ } ++ if (tx->slave_id > 0 && rx->slave_id > 0) { + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + +- host->chan_tx = dma_request_channel(mask, sh_mmcif_filter, +- &pdata->dma->chan_priv_tx); ++ host->chan_tx = dma_request_channel(mask, sh_mmcif_filter, tx); + dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__, + host->chan_tx); + + if (!host->chan_tx) + return; + +- host->chan_rx = dma_request_channel(mask, sh_mmcif_filter, +- &pdata->dma->chan_priv_rx); ++ host->chan_rx = dma_request_channel(mask, sh_mmcif_filter, rx); + dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__, + host->chan_rx); + +diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h +index 0222cd8..04ff452 100644 +--- a/include/linux/mmc/sh_mmcif.h ++++ b/include/linux/mmc/sh_mmcif.h +@@ -41,7 +41,9 @@ struct sh_mmcif_plat_data { + void (*set_pwr)(struct platform_device *pdev, int state); + void (*down_pwr)(struct platform_device *pdev); + int (*get_cd)(struct platform_device *pdef); +- struct sh_mmcif_dma *dma; ++ struct sh_mmcif_dma *dma; /* Deprecated. Instead */ ++ unsigned int slave_id_tx; /* use embedded slave_id_[tr]x */ ++ unsigned int slave_id_rx; + u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */ + unsigned long caps; + u32 ocr; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0058-mmc-Add-module.h-to-drivers-mmc-users-assuming-impli.patch b/patches.kzm9g/0058-mmc-Add-module.h-to-drivers-mmc-users-assuming-impli.patch new file mode 100644 index 00000000000000..6555f45617df5d --- /dev/null +++ b/patches.kzm9g/0058-mmc-Add-module.h-to-drivers-mmc-users-assuming-impli.patch @@ -0,0 +1,52 @@ +From c53d4419269e916098238ef2bbd15ee2e9381cf0 Mon Sep 17 00:00:00 2001 +From: Paul Gortmaker <paul.gortmaker@windriver.com> +Date: Sun, 3 Jul 2011 15:15:51 -0400 +Subject: mmc: Add module.h to drivers/mmc users assuming implicit presence. + +We are cleaning up the implicit presence of module.h; these guys are +some of the people who just assume it will be there. Call it out +explitly for those that really need it. + +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 88b47679746b81534002bcba42da97ab82b5d12a) + +Conflicts: + + drivers/mmc/card/mmc_test.c + drivers/mmc/host/mmc_spi.c + drivers/mmc/host/mxs-mmc.c + drivers/mmc/host/sdhci-of-esdhc.c + drivers/mmc/host/sdhci-of-hlwd.c + drivers/mmc/host/sdhci-pci.c + drivers/mmc/host/sdhci-pltfm.c + drivers/mmc/host/sdhci-pxav2.c + drivers/mmc/host/sdhci-pxav3.c + drivers/mmc/host/sdhci-spear.c + drivers/mmc/host/sdhci-tegra.c + drivers/mmc/host/sdhci.c + drivers/mmc/host/sdricoh_cs.c + drivers/mmc/host/sh_mobile_sdhi.c + drivers/mmc/host/tifm_sd.c + drivers/mmc/host/via-sdmmc.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index bd91c94..369366c 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -31,6 +31,7 @@ + #include <linux/platform_device.h> + #include <linux/pm_runtime.h> + #include <linux/spinlock.h> ++#include <linux/module.h> + + #define DRIVER_NAME "sh_mmcif" + #define DRIVER_VERSION "2010-04-28" +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0059-mmc-host-move-to-dma_transfer_direction.patch b/patches.kzm9g/0059-mmc-host-move-to-dma_transfer_direction.patch new file mode 100644 index 00000000000000..a9168363038e0e --- /dev/null +++ b/patches.kzm9g/0059-mmc-host-move-to-dma_transfer_direction.patch @@ -0,0 +1,54 @@ +From 36af543e2ebf0c4fd2201cf4aa7bd652c2a78809 Mon Sep 17 00:00:00 2001 +From: Vinod Koul <vinod.koul@linux.intel.com> +Date: Fri, 14 Oct 2011 10:45:11 +0530 +Subject: mmc-host: move to dma_transfer_direction + +fixup usage of dma direction by introducing dma_transfer_direction, +this patch moves mmc drivers to use new enum + +Cc: Nicolas Ferre <nicolas.ferre@atmel.com> +Cc: Chris Ball <cjb@laptop.org> +Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry-picked from commit 05f5799cbe5c9e2c03f604b3de5783cf4d726227) + +Conflicts: + + drivers/mmc/host/atmel-mci.c + drivers/mmc/host/mmci.c + drivers/mmc/host/mxcmmc.c + drivers/mmc/host/mxs-mmc.c + drivers/mmc/host/tmio_mmc_dma.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 369366c..1c0c10b 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -233,7 +233,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) + if (ret > 0) { + host->dma_active = true; + desc = chan->device->device_prep_slave_sg(chan, sg, ret, +- DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + } + + if (desc) { +@@ -281,7 +281,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) + if (ret > 0) { + host->dma_active = true; + desc = chan->device->device_prep_slave_sg(chan, sg, ret, +- DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + } + + if (desc) { +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0060-mmc-sh_mmcif-fix-clock-gating-on-platforms-with-a-.d.patch b/patches.kzm9g/0060-mmc-sh_mmcif-fix-clock-gating-on-platforms-with-a-.d.patch new file mode 100644 index 00000000000000..aaa15101e62b63 --- /dev/null +++ b/patches.kzm9g/0060-mmc-sh_mmcif-fix-clock-gating-on-platforms-with-a-.d.patch @@ -0,0 +1,34 @@ +From 9349a2c3b6de8530004a628228b5b72e646decbd Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 16 Nov 2011 10:10:41 +0100 +Subject: mmc: sh_mmcif: fix clock gating on platforms with a .down_pwr() + method + +Do not power down the card in .set_ios(), unless MMC_POWER_OFF is +requested. This fixes the MMCIF interface functionality on ecovec boards. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit f6bc41fb08cbd6943df358437e0af90c91a3caa3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 1c0c10b..b758b21 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -908,7 +908,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + if (host->power) { + pm_runtime_put(&host->pd->dev); + host->power = false; +- if (p->down_pwr) ++ if (p->down_pwr && ios->power_mode == MMC_POWER_OFF) + p->down_pwr(host->pd); + } + host->state = STATE_IDLE; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0061-mmc-sh_mmcif-simplify-clock-divisor-calculation.patch b/patches.kzm9g/0061-mmc-sh_mmcif-simplify-clock-divisor-calculation.patch new file mode 100644 index 00000000000000..07c17d299f77db --- /dev/null +++ b/patches.kzm9g/0061-mmc-sh_mmcif-simplify-clock-divisor-calculation.patch @@ -0,0 +1,42 @@ +From ac5156aad3d50ae4acfe30f57e74c0677b5cc3a7 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 23 Nov 2011 15:52:30 +0100 +Subject: mmc: sh_mmcif: simplify clock divisor calculation + +Replace ilog2(__rounddown_pow_of_two(x)) with the equivalent but much +simpler fls(x) - 1. + +Reported-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 86df174585de79a460e3515ec413ea1f5a0bcf68) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index b758b21..86edbad 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -16,6 +16,7 @@ + * + */ + ++#include <linux/bitops.h> + #include <linux/clk.h> + #include <linux/completion.h> + #include <linux/delay.h> +@@ -399,7 +400,7 @@ static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk) + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK); + else + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & +- (ilog2(__rounddown_pow_of_two(host->clk / clk)) << 16)); ++ ((fls(host->clk / clk) - 1) << 16)); + + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0062-mmc-convert-drivers-mmc-host-to-use-module_platform_.patch b/patches.kzm9g/0062-mmc-convert-drivers-mmc-host-to-use-module_platform_.patch new file mode 100644 index 00000000000000..3c15bd131c035b --- /dev/null +++ b/patches.kzm9g/0062-mmc-convert-drivers-mmc-host-to-use-module_platform_.patch @@ -0,0 +1,79 @@ +From 44f21f022edbdf0032b9f6d2e197d7e042c14d04 Mon Sep 17 00:00:00 2001 +From: Axel Lin <axel.lin@gmail.com> +Date: Sat, 26 Nov 2011 12:55:43 +0800 +Subject: mmc: convert drivers/mmc/host/* to use module_platform_driver() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch converts the drivers in drivers/mmc/host/* to use the +module_platform_driver() macro which makes the code smaller and a bit +simpler. + +Signed-off-by: Axel Lin <axel.lin@gmail.com> +Acked-by: "Michał Mirosław" <mirq-linux@rere.qmqm.pl> +Acked-by: David Brown <davidb@codeaurora.org> +Acked-by: Viresh Kumar <viresh.kumar@st.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Sascha Hauer <s.hauer@pengutronix.de> +Acked-by: Wolfram Sang <w.sang@pengutronix.de> +Acked-by: Anton Vorontsov <cbouatmailru@gmail.com> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit d1f81a64a4250bdd776978be06ae2b8e13ec7471) + +Conflicts: + + drivers/mmc/host/bfin_sdh.c + drivers/mmc/host/cb710-mmc.c + drivers/mmc/host/jz4740_mmc.c + drivers/mmc/host/msm_sdcc.c + drivers/mmc/host/mxcmmc.c + drivers/mmc/host/mxs-mmc.c + drivers/mmc/host/pxamci.c + drivers/mmc/host/s3cmci.c + drivers/mmc/host/sdhci-cns3xxx.c + drivers/mmc/host/sdhci-dove.c + drivers/mmc/host/sdhci-esdhc-imx.c + drivers/mmc/host/sdhci-of-esdhc.c + drivers/mmc/host/sdhci-of-hlwd.c + drivers/mmc/host/sdhci-pxav2.c + drivers/mmc/host/sdhci-pxav3.c + drivers/mmc/host/sdhci-s3c.c + drivers/mmc/host/sdhci-spear.c + drivers/mmc/host/sdhci-tegra.c + drivers/mmc/host/sh_mobile_sdhi.c + drivers/mmc/host/tmio_mmc.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 14 +------------- + 1 file changed, 1 insertion(+), 13 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 86edbad..fd0fd11 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -1207,19 +1207,7 @@ static struct platform_driver sh_mmcif_driver = { + }, + }; + +-static int __init sh_mmcif_init(void) +-{ +- return platform_driver_register(&sh_mmcif_driver); +-} +- +-static void __exit sh_mmcif_exit(void) +-{ +- platform_driver_unregister(&sh_mmcif_driver); +-} +- +-module_init(sh_mmcif_init); +-module_exit(sh_mmcif_exit); +- ++module_platform_driver(sh_mmcif_driver); + + MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver"); + MODULE_LICENSE("GPL"); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0063-mmc-sh_mmcif-process-error-interrupts-first.patch b/patches.kzm9g/0063-mmc-sh_mmcif-process-error-interrupts-first.patch new file mode 100644 index 00000000000000..67e7f70ae2b098 --- /dev/null +++ b/patches.kzm9g/0063-mmc-sh_mmcif-process-error-interrupts-first.patch @@ -0,0 +1,53 @@ +From 5e6bf4faa8039a5bc1dba4d380a116a7e4d9a7e4 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 14 Dec 2011 19:31:51 +0100 +Subject: mmc: sh_mmcif: process error interrupts first + +If an interrupt is coming with both error and data completion status bits +set, it has to be handled as an error interrupt, for which error interrupts +have to be processed first. The current version of the driver on the +contrary doesn't recognise such interrupts as an error event, which leads +to data corruption and breaks the error recovery. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 8a8284a98c1a58f5aa3eebce7971f81bcdb29d98) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index fd0fd11..e9ba52e 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -961,7 +961,12 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) + + state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); + +- if (state & INT_RBSYE) { ++ if (state & INT_ERR_STS) { ++ /* error interrupts - process first */ ++ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); ++ sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state); ++ err = 1; ++ } else if (state & INT_RBSYE) { + sh_mmcif_writel(host->addr, MMCIF_CE_INT, + ~(INT_RBSYE | INT_CRSPE)); + sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE); +@@ -989,11 +994,6 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) + sh_mmcif_writel(host->addr, MMCIF_CE_INT, + ~(INT_CMD12RBE | INT_CMD12CRE)); + sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); +- } else if (state & INT_ERR_STS) { +- /* err interrupts */ +- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); +- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state); +- err = 1; + } else { + dev_dbg(&host->pd->dev, "Unsupported interrupt: 0x%x\n", state); + sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0064-mmc-sh_mmcif-cosmetic-clean-up.patch b/patches.kzm9g/0064-mmc-sh_mmcif-cosmetic-clean-up.patch new file mode 100644 index 00000000000000..5b4215a8f80813 --- /dev/null +++ b/patches.kzm9g/0064-mmc-sh_mmcif-cosmetic-clean-up.patch @@ -0,0 +1,211 @@ +From 364bbb124f5f7023aa0999c8382c3cfb38629615 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 14 Dec 2011 19:31:52 +0100 +Subject: mmc: sh_mmcif: cosmetic clean up + +This patch doesn't introduce any functional changes, it only simplifies +some code fragments, removes superfluous parameters, fixes typos. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit ee4b88879f23badd54f5557852745fa28a1570f6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 79 +++++++++++++++++++-------------------------- + 1 file changed, 34 insertions(+), 45 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index e9ba52e..1408ded 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -124,6 +124,11 @@ + #define MASK_MRBSYTO (1 << 1) + #define MASK_MRSPTO (1 << 0) + ++#define MASK_START_CMD (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \ ++ MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \ ++ MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \ ++ MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO) ++ + /* CE_HOST_STS1 */ + #define STS1_CMDSEQ (1 << 31) + +@@ -176,8 +181,8 @@ struct sh_mmcif_host { + long timeout; + void __iomem *addr; + struct completion intr_wait; ++ spinlock_t lock; /* protect sh_mmcif_host::state */ + enum mmcif_state state; +- spinlock_t lock; + bool power; + bool card_present; + +@@ -422,7 +427,7 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host) + static int sh_mmcif_error_manage(struct sh_mmcif_host *host) + { + u32 state1, state2; +- int ret, timeout = 10000000; ++ int ret, timeout; + + host->sd_error = false; + +@@ -434,31 +439,30 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host) + if (state1 & STS1_CMDSEQ) { + sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK); + sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, ~CMD_CTRL_BREAK); +- while (1) { +- timeout--; +- if (timeout < 0) { +- dev_err(&host->pd->dev, +- "Forceed end of command sequence timeout err\n"); +- return -EIO; +- } ++ for (timeout = 10000000; timeout; timeout--) { + if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1) +- & STS1_CMDSEQ)) ++ & STS1_CMDSEQ)) + break; + mdelay(1); + } ++ if (!timeout) { ++ dev_err(&host->pd->dev, ++ "Forced end of command sequence timeout err\n"); ++ return -EIO; ++ } + sh_mmcif_sync_reset(host); + dev_dbg(&host->pd->dev, "Forced end of command sequence\n"); + return -EIO; + } + + if (state2 & STS2_CRC_ERR) { +- dev_dbg(&host->pd->dev, ": Happened CRC error\n"); ++ dev_dbg(&host->pd->dev, ": CRC error\n"); + ret = -EIO; + } else if (state2 & STS2_TIMEOUT_ERR) { +- dev_dbg(&host->pd->dev, ": Happened Timeout error\n"); ++ dev_dbg(&host->pd->dev, ": Timeout\n"); + ret = -ETIMEDOUT; + } else { +- dev_dbg(&host->pd->dev, ": Happened End/Index error\n"); ++ dev_dbg(&host->pd->dev, ": End/Index error\n"); + ret = -EIO; + } + return ret; +@@ -681,55 +685,44 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, + static int sh_mmcif_data_trans(struct sh_mmcif_host *host, + struct mmc_request *mrq, u32 opc) + { +- int ret; +- + switch (opc) { + case MMC_READ_MULTIPLE_BLOCK: +- ret = sh_mmcif_multi_read(host, mrq); +- break; ++ return sh_mmcif_multi_read(host, mrq); + case MMC_WRITE_MULTIPLE_BLOCK: +- ret = sh_mmcif_multi_write(host, mrq); +- break; ++ return sh_mmcif_multi_write(host, mrq); + case MMC_WRITE_BLOCK: +- ret = sh_mmcif_single_write(host, mrq); +- break; ++ return sh_mmcif_single_write(host, mrq); + case MMC_READ_SINGLE_BLOCK: + case MMC_SEND_EXT_CSD: +- ret = sh_mmcif_single_read(host, mrq); +- break; ++ return sh_mmcif_single_read(host, mrq); + default: + dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc); +- ret = -EINVAL; +- break; ++ return -EINVAL; + } +- return ret; + } + + static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, +- struct mmc_request *mrq, struct mmc_command *cmd) ++ struct mmc_request *mrq) + { ++ struct mmc_command *cmd = mrq->cmd; + long time; +- int ret = 0, mask = 0; +- u32 opc = cmd->opcode; ++ int ret = 0; ++ u32 mask, opc = cmd->opcode; + + switch (opc) { +- /* respons busy check */ ++ /* response busy check */ + case MMC_SWITCH: + case MMC_STOP_TRANSMISSION: + case MMC_SET_WRITE_PROT: + case MMC_CLR_WRITE_PROT: + case MMC_ERASE: + case MMC_GEN_CMD: +- mask = MASK_MRBSYE; ++ mask = MASK_START_CMD | MASK_MRBSYE; + break; + default: +- mask = MASK_MCRSPE; ++ mask = MASK_START_CMD | MASK_MCRSPE; + break; + } +- mask |= MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | +- MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | +- MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | +- MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO; + + if (host->data) { + sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0); +@@ -797,8 +790,9 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, + } + + static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, +- struct mmc_request *mrq, struct mmc_command *cmd) ++ struct mmc_request *mrq) + { ++ struct mmc_command *cmd = mrq->stop; + long time; + + if (mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) +@@ -867,11 +861,11 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) + sh_mmcif_start_dma_tx(host); + } + } +- sh_mmcif_start_cmd(host, mrq, mrq->cmd); ++ sh_mmcif_start_cmd(host, mrq); + host->data = NULL; + + if (!mrq->cmd->error && mrq->stop) +- sh_mmcif_stop_cmd(host, mrq, mrq->stop); ++ sh_mmcif_stop_cmd(host, mrq); + host->state = STATE_IDLE; + mmc_request_done(mmc, mrq); + } +@@ -948,11 +942,6 @@ static struct mmc_host_ops sh_mmcif_ops = { + .get_cd = sh_mmcif_get_cd, + }; + +-static void sh_mmcif_detect(struct mmc_host *mmc) +-{ +- mmc_detect_change(mmc, 0); +-} +- + static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) + { + struct sh_mmcif_host *host = dev_id; +@@ -1114,7 +1103,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) + goto clean_up3; + } + +- sh_mmcif_detect(host->mmc); ++ mmc_detect_change(host->mmc, 0); + + dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); + dev_dbg(&pdev->dev, "chip ver H'%04x\n", +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0065-mmc-sh_mmcif-process-requests-asynchronously.patch b/patches.kzm9g/0065-mmc-sh_mmcif-process-requests-asynchronously.patch new file mode 100644 index 00000000000000..ac2e137efa91b1 --- /dev/null +++ b/patches.kzm9g/0065-mmc-sh_mmcif-process-requests-asynchronously.patch @@ -0,0 +1,788 @@ +From 24a541a85df9dd327db05d3ebb3058d256ac90a6 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Sun, 25 Dec 2011 21:07:52 +0100 +Subject: mmc: sh_mmcif: process requests asynchronously + +This patch converts the sh_mmcif MMC host driver to process requests +asynchronously instead of waiting in its .request() method for completion. +This is achieved by using threaded IRQs. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit f985da17f4d368896fb30d94531e4ffaa18e68d8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 588 +++++++++++++++++++++++++++++++------------- + 1 file changed, 416 insertions(+), 172 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 1408ded..5d0ade7 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -16,6 +16,32 @@ + * + */ + ++/* ++ * The MMCIF driver is now processing MMC requests asynchronously, according ++ * to the Linux MMC API requirement. ++ * ++ * The MMCIF driver processes MMC requests in up to 3 stages: command, optional ++ * data, and optional stop. To achieve asynchronous processing each of these ++ * stages is split into two halves: a top and a bottom half. The top half ++ * initialises the hardware, installs a timeout handler to handle completion ++ * timeouts, and returns. In case of the command stage this immediately returns ++ * control to the caller, leaving all further processing to run asynchronously. ++ * All further request processing is performed by the bottom halves. ++ * ++ * The bottom half further consists of a "hard" IRQ handler, an IRQ handler ++ * thread, a DMA completion callback, if DMA is used, a timeout work, and ++ * request- and stage-specific handler methods. ++ * ++ * Each bottom half run begins with either a hardware interrupt, a DMA callback ++ * invocation, or a timeout work run. In case of an error or a successful ++ * processing completion, the MMC core is informed and the request processing is ++ * finished. In case processing has to continue, i.e., if data has to be read ++ * from or written to the card, or if a stop command has to be sent, the next ++ * top half is called, which performs the necessary hardware handling and ++ * reschedules the timeout work. This returns the driver state machine into the ++ * bottom half waiting state. ++ */ ++ + #include <linux/bitops.h> + #include <linux/clk.h> + #include <linux/completion.h> +@@ -168,9 +194,22 @@ enum mmcif_state { + STATE_IOS, + }; + ++enum mmcif_wait_for { ++ MMCIF_WAIT_FOR_REQUEST, ++ MMCIF_WAIT_FOR_CMD, ++ MMCIF_WAIT_FOR_MREAD, ++ MMCIF_WAIT_FOR_MWRITE, ++ MMCIF_WAIT_FOR_READ, ++ MMCIF_WAIT_FOR_WRITE, ++ MMCIF_WAIT_FOR_READ_END, ++ MMCIF_WAIT_FOR_WRITE_END, ++ MMCIF_WAIT_FOR_STOP, ++}; ++ + struct sh_mmcif_host { + struct mmc_host *mmc; + struct mmc_data *data; ++ struct mmc_request *mrq; + struct platform_device *pd; + struct sh_dmae_slave dma_slave_tx; + struct sh_dmae_slave dma_slave_rx; +@@ -178,11 +217,17 @@ struct sh_mmcif_host { + unsigned int clk; + int bus_width; + bool sd_error; ++ bool dying; + long timeout; + void __iomem *addr; +- struct completion intr_wait; ++ u32 *pio_ptr; + spinlock_t lock; /* protect sh_mmcif_host::state */ + enum mmcif_state state; ++ enum mmcif_wait_for wait_for; ++ struct delayed_work timeout_work; ++ size_t blocksize; ++ int sg_idx; ++ int sg_blkidx; + bool power; + bool card_present; + +@@ -468,125 +513,183 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host) + return ret; + } + +-static int sh_mmcif_single_read(struct sh_mmcif_host *host, +- struct mmc_request *mrq) ++static bool sh_mmcif_next_block(struct sh_mmcif_host *host, u32 *p) + { +- struct mmc_data *data = mrq->data; +- long time; +- u32 blocksize, i, *p = sg_virt(data->sg); ++ struct mmc_data *data = host->mrq->data; ++ ++ host->sg_blkidx += host->blocksize; ++ ++ /* data->sg->length must be a multiple of host->blocksize? */ ++ BUG_ON(host->sg_blkidx > data->sg->length); ++ ++ if (host->sg_blkidx == data->sg->length) { ++ host->sg_blkidx = 0; ++ if (++host->sg_idx < data->sg_len) ++ host->pio_ptr = sg_virt(++data->sg); ++ } else { ++ host->pio_ptr = p; ++ } ++ ++ if (host->sg_idx == data->sg_len) ++ return false; ++ ++ return true; ++} ++ ++static void sh_mmcif_single_read(struct sh_mmcif_host *host, ++ struct mmc_request *mrq) ++{ ++ host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & ++ BLOCK_SIZE_MASK) + 3; ++ ++ host->wait_for = MMCIF_WAIT_FOR_READ; ++ schedule_delayed_work(&host->timeout_work, host->timeout); + + /* buf read enable */ + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); +- +- blocksize = (BLOCK_SIZE_MASK & +- sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; +- for (i = 0; i < blocksize / 4; i++) ++} ++ ++static bool sh_mmcif_read_block(struct sh_mmcif_host *host) ++{ ++ struct mmc_data *data = host->mrq->data; ++ u32 *p = sg_virt(data->sg); ++ int i; ++ ++ if (host->sd_error) { ++ data->error = sh_mmcif_error_manage(host); ++ return false; ++ } ++ ++ for (i = 0; i < host->blocksize / 4; i++) + *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA); + + /* buffer read end */ + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); ++ host->wait_for = MMCIF_WAIT_FOR_READ_END; + +- return 0; ++ return true; + } + +-static int sh_mmcif_multi_read(struct sh_mmcif_host *host, +- struct mmc_request *mrq) ++static void sh_mmcif_multi_read(struct sh_mmcif_host *host, ++ struct mmc_request *mrq) + { + struct mmc_data *data = mrq->data; +- long time; +- u32 blocksize, i, j, sec, *p; +- +- blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr, +- MMCIF_CE_BLOCK_SET); +- for (j = 0; j < data->sg_len; j++) { +- p = sg_virt(data->sg); +- for (sec = 0; sec < data->sg->length / blocksize; sec++) { +- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); +- /* buf read enable */ +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); +- +- for (i = 0; i < blocksize / 4; i++) +- *p++ = sh_mmcif_readl(host->addr, +- MMCIF_CE_DATA); +- } +- if (j < data->sg_len - 1) +- data->sg++; ++ ++ if (!data->sg_len || !data->sg->length) ++ return; ++ ++ host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & ++ BLOCK_SIZE_MASK; ++ ++ host->wait_for = MMCIF_WAIT_FOR_MREAD; ++ host->sg_idx = 0; ++ host->sg_blkidx = 0; ++ host->pio_ptr = sg_virt(data->sg); ++ schedule_delayed_work(&host->timeout_work, host->timeout); ++ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); ++} ++ ++static bool sh_mmcif_mread_block(struct sh_mmcif_host *host) ++{ ++ struct mmc_data *data = host->mrq->data; ++ u32 *p = host->pio_ptr; ++ int i; ++ ++ if (host->sd_error) { ++ data->error = sh_mmcif_error_manage(host); ++ return false; + } +- return 0; ++ ++ BUG_ON(!data->sg->length); ++ ++ for (i = 0; i < host->blocksize / 4; i++) ++ *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA); ++ ++ if (!sh_mmcif_next_block(host, p)) ++ return false; ++ ++ schedule_delayed_work(&host->timeout_work, host->timeout); ++ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); ++ ++ return true; + } + +-static int sh_mmcif_single_write(struct sh_mmcif_host *host, ++static void sh_mmcif_single_write(struct sh_mmcif_host *host, + struct mmc_request *mrq) + { +- struct mmc_data *data = mrq->data; +- long time; +- u32 blocksize, i, *p = sg_virt(data->sg); ++ host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & ++ BLOCK_SIZE_MASK) + 3; + +- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); ++ host->wait_for = MMCIF_WAIT_FOR_WRITE; ++ schedule_delayed_work(&host->timeout_work, host->timeout); + + /* buf write enable */ +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); +- +- blocksize = (BLOCK_SIZE_MASK & +- sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; +- for (i = 0; i < blocksize / 4; i++) ++ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); ++} ++ ++static bool sh_mmcif_write_block(struct sh_mmcif_host *host) ++{ ++ struct mmc_data *data = host->mrq->data; ++ u32 *p = sg_virt(data->sg); ++ int i; ++ ++ if (host->sd_error) { ++ data->error = sh_mmcif_error_manage(host); ++ return false; ++ } ++ ++ for (i = 0; i < host->blocksize / 4; i++) + sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++); + + /* buffer write end */ + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); ++ host->wait_for = MMCIF_WAIT_FOR_WRITE_END; + +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); +- +- return 0; ++ return true; + } + +-static int sh_mmcif_multi_write(struct sh_mmcif_host *host, +- struct mmc_request *mrq) ++static void sh_mmcif_multi_write(struct sh_mmcif_host *host, ++ struct mmc_request *mrq) + { + struct mmc_data *data = mrq->data; +- long time; +- u32 i, sec, j, blocksize, *p; + +- blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr, +- MMCIF_CE_BLOCK_SET); ++ if (!data->sg_len || !data->sg->length) ++ return; + +- for (j = 0; j < data->sg_len; j++) { +- p = sg_virt(data->sg); +- for (sec = 0; sec < data->sg->length / blocksize; sec++) { +- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); +- /* buf write enable*/ +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); ++ host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & ++ BLOCK_SIZE_MASK; + +- if (time <= 0 || host->sd_error) +- return sh_mmcif_error_manage(host); ++ host->wait_for = MMCIF_WAIT_FOR_MWRITE; ++ host->sg_idx = 0; ++ host->sg_blkidx = 0; ++ host->pio_ptr = sg_virt(data->sg); ++ schedule_delayed_work(&host->timeout_work, host->timeout); ++ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); ++} + +- for (i = 0; i < blocksize / 4; i++) +- sh_mmcif_writel(host->addr, +- MMCIF_CE_DATA, *p++); +- } +- if (j < data->sg_len - 1) +- data->sg++; ++static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host) ++{ ++ struct mmc_data *data = host->mrq->data; ++ u32 *p = host->pio_ptr; ++ int i; ++ ++ if (host->sd_error) { ++ data->error = sh_mmcif_error_manage(host); ++ return false; + } +- return 0; ++ ++ BUG_ON(!data->sg->length); ++ ++ for (i = 0; i < host->blocksize / 4; i++) ++ sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++); ++ ++ if (!sh_mmcif_next_block(host, p)) ++ return false; ++ ++ schedule_delayed_work(&host->timeout_work, host->timeout); ++ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); ++ ++ return true; + } + + static void sh_mmcif_get_response(struct sh_mmcif_host *host, +@@ -683,18 +786,22 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, + } + + static int sh_mmcif_data_trans(struct sh_mmcif_host *host, +- struct mmc_request *mrq, u32 opc) ++ struct mmc_request *mrq, u32 opc) + { + switch (opc) { + case MMC_READ_MULTIPLE_BLOCK: +- return sh_mmcif_multi_read(host, mrq); ++ sh_mmcif_multi_read(host, mrq); ++ return 0; + case MMC_WRITE_MULTIPLE_BLOCK: +- return sh_mmcif_multi_write(host, mrq); ++ sh_mmcif_multi_write(host, mrq); ++ return 0; + case MMC_WRITE_BLOCK: +- return sh_mmcif_single_write(host, mrq); ++ sh_mmcif_single_write(host, mrq); ++ return 0; + case MMC_READ_SINGLE_BLOCK: + case MMC_SEND_EXT_CSD: +- return sh_mmcif_single_read(host, mrq); ++ sh_mmcif_single_read(host, mrq); ++ return 0; + default: + dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc); + return -EINVAL; +@@ -705,9 +812,8 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, + struct mmc_request *mrq) + { + struct mmc_command *cmd = mrq->cmd; +- long time; +- int ret = 0; +- u32 mask, opc = cmd->opcode; ++ u32 opc = cmd->opcode; ++ u32 mask; + + switch (opc) { + /* response busy check */ +@@ -738,62 +844,14 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, + /* set cmd */ + sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); + +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0) { +- cmd->error = sh_mmcif_error_manage(host); +- return; +- } +- if (host->sd_error) { +- switch (cmd->opcode) { +- case MMC_ALL_SEND_CID: +- case MMC_SELECT_CARD: +- case MMC_APP_CMD: +- cmd->error = -ETIMEDOUT; +- break; +- default: +- dev_dbg(&host->pd->dev, "Cmd(d'%d) err\n", +- cmd->opcode); +- cmd->error = sh_mmcif_error_manage(host); +- break; +- } +- host->sd_error = false; +- return; +- } +- if (!(cmd->flags & MMC_RSP_PRESENT)) { +- cmd->error = 0; +- return; +- } +- sh_mmcif_get_response(host, cmd); +- if (host->data) { +- if (!host->dma_active) { +- ret = sh_mmcif_data_trans(host, mrq, cmd->opcode); +- } else { +- long time = +- wait_for_completion_interruptible_timeout(&host->dma_complete, +- host->timeout); +- if (!time) +- ret = -ETIMEDOUT; +- else if (time < 0) +- ret = time; +- sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, +- BUF_ACC_DMAREN | BUF_ACC_DMAWEN); +- host->dma_active = false; +- } +- if (ret < 0) +- mrq->data->bytes_xfered = 0; +- else +- mrq->data->bytes_xfered = +- mrq->data->blocks * mrq->data->blksz; +- } +- cmd->error = ret; ++ host->wait_for = MMCIF_WAIT_FOR_CMD; ++ schedule_delayed_work(&host->timeout_work, host->timeout); + } + + static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, + struct mmc_request *mrq) + { + struct mmc_command *cmd = mrq->stop; +- long time; + + if (mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE); +@@ -805,14 +863,8 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, + return; + } + +- time = wait_for_completion_interruptible_timeout(&host->intr_wait, +- host->timeout); +- if (time <= 0 || host->sd_error) { +- cmd->error = sh_mmcif_error_manage(host); +- return; +- } +- sh_mmcif_get_cmd12response(host, cmd); +- cmd->error = 0; ++ host->wait_for = MMCIF_WAIT_FOR_STOP; ++ schedule_delayed_work(&host->timeout_work, host->timeout); + } + + static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) +@@ -851,23 +903,11 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) + default: + break; + } ++ ++ host->mrq = mrq; + host->data = mrq->data; +- if (mrq->data) { +- if (mrq->data->flags & MMC_DATA_READ) { +- if (host->chan_rx) +- sh_mmcif_start_dma_rx(host); +- } else { +- if (host->chan_tx) +- sh_mmcif_start_dma_tx(host); +- } +- } +- sh_mmcif_start_cmd(host, mrq); +- host->data = NULL; + +- if (!mrq->cmd->error && mrq->stop) +- sh_mmcif_stop_cmd(host, mrq); +- host->state = STATE_IDLE; +- mmc_request_done(mmc, mrq); ++ sh_mmcif_start_cmd(host, mrq); + } + + static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +@@ -942,6 +982,157 @@ static struct mmc_host_ops sh_mmcif_ops = { + .get_cd = sh_mmcif_get_cd, + }; + ++static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) ++{ ++ struct mmc_command *cmd = host->mrq->cmd; ++ long time; ++ ++ if (host->sd_error) { ++ switch (cmd->opcode) { ++ case MMC_ALL_SEND_CID: ++ case MMC_SELECT_CARD: ++ case MMC_APP_CMD: ++ cmd->error = -ETIMEDOUT; ++ host->sd_error = false; ++ break; ++ default: ++ cmd->error = sh_mmcif_error_manage(host); ++ dev_dbg(&host->pd->dev, "Cmd(d'%d) error %d\n", ++ cmd->opcode, cmd->error); ++ break; ++ } ++ return false; ++ } ++ if (!(cmd->flags & MMC_RSP_PRESENT)) { ++ cmd->error = 0; ++ return false; ++ } ++ ++ sh_mmcif_get_response(host, cmd); ++ ++ if (!host->data) ++ return false; ++ ++ if (host->mrq->data->flags & MMC_DATA_READ) { ++ if (host->chan_rx) ++ sh_mmcif_start_dma_rx(host); ++ } else { ++ if (host->chan_tx) ++ sh_mmcif_start_dma_tx(host); ++ } ++ ++ if (!host->dma_active) { ++ host->data->error = sh_mmcif_data_trans(host, host->mrq, cmd->opcode); ++ if (!host->data->error) ++ return true; ++ return false; ++ } ++ ++ /* Running in the IRQ thread, can sleep */ ++ time = wait_for_completion_interruptible_timeout(&host->dma_complete, ++ host->timeout); ++ if (host->sd_error) { ++ dev_err(host->mmc->parent, ++ "Error IRQ while waiting for DMA completion!\n"); ++ /* Woken up by an error IRQ: abort DMA */ ++ if (host->data->flags & MMC_DATA_READ) ++ dmaengine_terminate_all(host->chan_rx); ++ else ++ dmaengine_terminate_all(host->chan_tx); ++ host->data->error = sh_mmcif_error_manage(host); ++ } else if (!time) { ++ host->data->error = -ETIMEDOUT; ++ } else if (time < 0) { ++ host->data->error = time; ++ } ++ sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, ++ BUF_ACC_DMAREN | BUF_ACC_DMAWEN); ++ host->dma_active = false; ++ ++ if (host->data->error) ++ host->data->bytes_xfered = 0; ++ ++ return false; ++} ++ ++static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) ++{ ++ struct sh_mmcif_host *host = dev_id; ++ struct mmc_request *mrq = host->mrq; ++ ++ cancel_delayed_work_sync(&host->timeout_work); ++ ++ /* ++ * All handlers return true, if processing continues, and false, if the ++ * request has to be completed - successfully or not ++ */ ++ switch (host->wait_for) { ++ case MMCIF_WAIT_FOR_REQUEST: ++ /* We're too late, the timeout has already kicked in */ ++ return IRQ_HANDLED; ++ case MMCIF_WAIT_FOR_CMD: ++ if (sh_mmcif_end_cmd(host)) ++ /* Wait for data */ ++ return IRQ_HANDLED; ++ break; ++ case MMCIF_WAIT_FOR_MREAD: ++ if (sh_mmcif_mread_block(host)) ++ /* Wait for more data */ ++ return IRQ_HANDLED; ++ break; ++ case MMCIF_WAIT_FOR_READ: ++ if (sh_mmcif_read_block(host)) ++ /* Wait for data end */ ++ return IRQ_HANDLED; ++ break; ++ case MMCIF_WAIT_FOR_MWRITE: ++ if (sh_mmcif_mwrite_block(host)) ++ /* Wait data to write */ ++ return IRQ_HANDLED; ++ break; ++ case MMCIF_WAIT_FOR_WRITE: ++ if (sh_mmcif_write_block(host)) ++ /* Wait for data end */ ++ return IRQ_HANDLED; ++ break; ++ case MMCIF_WAIT_FOR_STOP: ++ if (host->sd_error) { ++ mrq->stop->error = sh_mmcif_error_manage(host); ++ break; ++ } ++ sh_mmcif_get_cmd12response(host, mrq->stop); ++ mrq->stop->error = 0; ++ break; ++ case MMCIF_WAIT_FOR_READ_END: ++ case MMCIF_WAIT_FOR_WRITE_END: ++ if (host->sd_error) ++ mrq->data->error = sh_mmcif_error_manage(host); ++ break; ++ default: ++ BUG(); ++ } ++ ++ if (host->wait_for != MMCIF_WAIT_FOR_STOP) { ++ host->data = NULL; ++ ++ if (!mrq->cmd->error && mrq->data && !mrq->data->error) ++ mrq->data->bytes_xfered = ++ mrq->data->blocks * mrq->data->blksz; ++ ++ if (mrq->stop && !mrq->cmd->error && (!mrq->data || !mrq->data->error)) { ++ sh_mmcif_stop_cmd(host, mrq); ++ if (!mrq->stop->error) ++ return IRQ_HANDLED; ++ } ++ } ++ ++ host->wait_for = MMCIF_WAIT_FOR_REQUEST; ++ host->state = STATE_IDLE; ++ mmc_request_done(host->mmc, mrq); ++ ++ return IRQ_HANDLED; ++} ++ + static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) + { + struct sh_mmcif_host *host = dev_id; +@@ -993,14 +1184,58 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) + host->sd_error = true; + dev_dbg(&host->pd->dev, "int err state = %08x\n", state); + } +- if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) +- complete(&host->intr_wait); +- else ++ if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { ++ if (!host->dma_active) ++ return IRQ_WAKE_THREAD; ++ else if (host->sd_error) ++ mmcif_dma_complete(host); ++ } else { + dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state); ++ } + + return IRQ_HANDLED; + } + ++static void mmcif_timeout_work(struct work_struct *work) ++{ ++ struct delayed_work *d = container_of(work, struct delayed_work, work); ++ struct sh_mmcif_host *host = container_of(d, struct sh_mmcif_host, timeout_work); ++ struct mmc_request *mrq = host->mrq; ++ ++ if (host->dying) ++ /* Don't run after mmc_remove_host() */ ++ return; ++ ++ /* ++ * Handle races with cancel_delayed_work(), unless ++ * cancel_delayed_work_sync() is used ++ */ ++ switch (host->wait_for) { ++ case MMCIF_WAIT_FOR_CMD: ++ mrq->cmd->error = sh_mmcif_error_manage(host); ++ break; ++ case MMCIF_WAIT_FOR_STOP: ++ mrq->stop->error = sh_mmcif_error_manage(host); ++ break; ++ case MMCIF_WAIT_FOR_MREAD: ++ case MMCIF_WAIT_FOR_MWRITE: ++ case MMCIF_WAIT_FOR_READ: ++ case MMCIF_WAIT_FOR_WRITE: ++ case MMCIF_WAIT_FOR_READ_END: ++ case MMCIF_WAIT_FOR_WRITE_END: ++ host->data->error = sh_mmcif_error_manage(host); ++ break; ++ default: ++ BUG(); ++ } ++ ++ host->state = STATE_IDLE; ++ host->wait_for = MMCIF_WAIT_FOR_REQUEST; ++ host->data = NULL; ++ host->mrq = NULL; ++ mmc_request_done(host->mmc, mrq); ++} ++ + static int __devinit sh_mmcif_probe(struct platform_device *pdev) + { + int ret = 0, irq[2]; +@@ -1054,7 +1289,6 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) + host->clk = clk_get_rate(host->hclk); + host->pd = pdev; + +- init_completion(&host->intr_wait); + spin_lock_init(&host->lock); + + mmc->ops = &sh_mmcif_ops; +@@ -1091,18 +1325,20 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) + + sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); + +- ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host); ++ ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host); + if (ret) { + dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n"); + goto clean_up3; + } +- ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host); ++ ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); + if (ret) { + free_irq(irq[0], host); + dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); + goto clean_up3; + } + ++ INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); ++ + mmc_detect_change(host->mmc, 0); + + dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); +@@ -1129,11 +1365,19 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev) + struct sh_mmcif_host *host = platform_get_drvdata(pdev); + int irq[2]; + ++ host->dying = true; + pm_runtime_get_sync(&pdev->dev); + + mmc_remove_host(host->mmc); + sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); + ++ /* ++ * FIXME: cancel_delayed_work(_sync)() and free_irq() race with the ++ * mmc_remove_host() call above. But swapping order doesn't help either ++ * (a query on the linux-mmc mailing list didn't bring any replies). ++ */ ++ cancel_delayed_work_sync(&host->timeout_work); ++ + if (host->addr) + iounmap(host->addr); + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0066-mmc-sh_mmcif-remove-now-superfluous-sh_mmcif_host-da.patch b/patches.kzm9g/0066-mmc-sh_mmcif-remove-now-superfluous-sh_mmcif_host-da.patch new file mode 100644 index 00000000000000..36257241a0c463 --- /dev/null +++ b/patches.kzm9g/0066-mmc-sh_mmcif-remove-now-superfluous-sh_mmcif_host-da.patch @@ -0,0 +1,319 @@ +From 2f2db71dd4017c3fec347a00c6e8b2a9ac8df42d Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Mon, 26 Dec 2011 12:52:13 -0500 +Subject: mmc: sh_mmcif: remove now superfluous sh_mmcif_host::data member + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 699834045f1ec30156dd51c362a6840e737baaba) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 94 ++++++++++++++++++++++++--------------------- + 1 file changed, 50 insertions(+), 44 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 5d0ade7..f5d8b53 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -208,7 +208,6 @@ enum mmcif_wait_for { + + struct sh_mmcif_host { + struct mmc_host *mmc; +- struct mmc_data *data; + struct mmc_request *mrq; + struct platform_device *pd; + struct sh_dmae_slave dma_slave_tx; +@@ -253,19 +252,21 @@ static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host, + static void mmcif_dma_complete(void *arg) + { + struct sh_mmcif_host *host = arg; ++ struct mmc_data *data = host->mrq->data; ++ + dev_dbg(&host->pd->dev, "Command completed\n"); + +- if (WARN(!host->data, "%s: NULL data in DMA completion!\n", ++ if (WARN(!data, "%s: NULL data in DMA completion!\n", + dev_name(&host->pd->dev))) + return; + +- if (host->data->flags & MMC_DATA_READ) ++ if (data->flags & MMC_DATA_READ) + dma_unmap_sg(host->chan_rx->device->dev, +- host->data->sg, host->data->sg_len, ++ data->sg, data->sg_len, + DMA_FROM_DEVICE); + else + dma_unmap_sg(host->chan_tx->device->dev, +- host->data->sg, host->data->sg_len, ++ data->sg, data->sg_len, + DMA_TO_DEVICE); + + complete(&host->dma_complete); +@@ -273,13 +274,14 @@ static void mmcif_dma_complete(void *arg) + + static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) + { +- struct scatterlist *sg = host->data->sg; ++ struct mmc_data *data = host->mrq->data; ++ struct scatterlist *sg = data->sg; + struct dma_async_tx_descriptor *desc = NULL; + struct dma_chan *chan = host->chan_rx; + dma_cookie_t cookie = -EINVAL; + int ret; + +- ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len, ++ ret = dma_map_sg(chan->device->dev, sg, data->sg_len, + DMA_FROM_DEVICE); + if (ret > 0) { + host->dma_active = true; +@@ -295,7 +297,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) + dma_async_issue_pending(chan); + } + dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n", +- __func__, host->data->sg_len, ret, cookie); ++ __func__, data->sg_len, ret, cookie); + + if (!desc) { + /* DMA failed, fall back to PIO */ +@@ -316,18 +318,19 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) + } + + dev_dbg(&host->pd->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__, +- desc, cookie, host->data->sg_len); ++ desc, cookie, data->sg_len); + } + + static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) + { +- struct scatterlist *sg = host->data->sg; ++ struct mmc_data *data = host->mrq->data; ++ struct scatterlist *sg = data->sg; + struct dma_async_tx_descriptor *desc = NULL; + struct dma_chan *chan = host->chan_tx; + dma_cookie_t cookie = -EINVAL; + int ret; + +- ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len, ++ ret = dma_map_sg(chan->device->dev, sg, data->sg_len, + DMA_TO_DEVICE); + if (ret > 0) { + host->dma_active = true; +@@ -343,7 +346,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) + dma_async_issue_pending(chan); + } + dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n", +- __func__, host->data->sg_len, ret, cookie); ++ __func__, data->sg_len, ret, cookie); + + if (!desc) { + /* DMA failed, fall back to PIO */ +@@ -711,8 +714,11 @@ static void sh_mmcif_get_cmd12response(struct sh_mmcif_host *host, + } + + static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, +- struct mmc_request *mrq, struct mmc_command *cmd, u32 opc) ++ struct mmc_request *mrq) + { ++ struct mmc_data *data = mrq->data; ++ struct mmc_command *cmd = mrq->cmd; ++ u32 opc = cmd->opcode; + u32 tmp = 0; + + /* Response Type check */ +@@ -744,7 +750,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, + break; + } + /* WDAT / DATW */ +- if (host->data) { ++ if (data) { + tmp |= CMD_SET_WDAT; + switch (host->bus_width) { + case MMC_BUS_WIDTH_1: +@@ -768,7 +774,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, + if (opc == MMC_READ_MULTIPLE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) { + tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN; + sh_mmcif_bitset(host, MMCIF_CE_BLOCK_SET, +- mrq->data->blocks << 16); ++ data->blocks << 16); + } + /* RIDXC[1:0] check bits */ + if (opc == MMC_SEND_OP_COND || opc == MMC_ALL_SEND_CID || +@@ -782,7 +788,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, + opc == MMC_SEND_CSD || opc == MMC_SEND_CID) + tmp |= CMD_SET_CRC7C_INTERNAL; + +- return opc = ((opc << 24) | tmp); ++ return (opc << 24) | tmp; + } + + static int sh_mmcif_data_trans(struct sh_mmcif_host *host, +@@ -830,12 +836,12 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, + break; + } + +- if (host->data) { ++ if (mrq->data) { + sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0); + sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, + mrq->data->blksz); + } +- opc = sh_mmcif_set_cmd(host, mrq, cmd, opc); ++ opc = sh_mmcif_set_cmd(host, mrq); + + sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0); + sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask); +@@ -851,15 +857,16 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, + static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, + struct mmc_request *mrq) + { +- struct mmc_command *cmd = mrq->stop; +- +- if (mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) ++ switch (mrq->cmd->opcode) { ++ case MMC_READ_MULTIPLE_BLOCK: + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE); +- else if (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) ++ break; ++ case MMC_WRITE_MULTIPLE_BLOCK: + sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); +- else { ++ break; ++ default: + dev_err(&host->pd->dev, "unsupported stop cmd\n"); +- cmd->error = sh_mmcif_error_manage(host); ++ mrq->stop->error = sh_mmcif_error_manage(host); + return; + } + +@@ -905,7 +912,6 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) + } + + host->mrq = mrq; +- host->data = mrq->data; + + sh_mmcif_start_cmd(host, mrq); + } +@@ -985,6 +991,7 @@ static struct mmc_host_ops sh_mmcif_ops = { + static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) + { + struct mmc_command *cmd = host->mrq->cmd; ++ struct mmc_data *data = host->mrq->data; + long time; + + if (host->sd_error) { +@@ -1010,10 +1017,10 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) + + sh_mmcif_get_response(host, cmd); + +- if (!host->data) ++ if (!data) + return false; + +- if (host->mrq->data->flags & MMC_DATA_READ) { ++ if (data->flags & MMC_DATA_READ) { + if (host->chan_rx) + sh_mmcif_start_dma_rx(host); + } else { +@@ -1022,8 +1029,8 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) + } + + if (!host->dma_active) { +- host->data->error = sh_mmcif_data_trans(host, host->mrq, cmd->opcode); +- if (!host->data->error) ++ data->error = sh_mmcif_data_trans(host, host->mrq, cmd->opcode); ++ if (!data->error) + return true; + return false; + } +@@ -1035,22 +1042,22 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) + dev_err(host->mmc->parent, + "Error IRQ while waiting for DMA completion!\n"); + /* Woken up by an error IRQ: abort DMA */ +- if (host->data->flags & MMC_DATA_READ) ++ if (data->flags & MMC_DATA_READ) + dmaengine_terminate_all(host->chan_rx); + else + dmaengine_terminate_all(host->chan_tx); +- host->data->error = sh_mmcif_error_manage(host); ++ data->error = sh_mmcif_error_manage(host); + } else if (!time) { +- host->data->error = -ETIMEDOUT; ++ data->error = -ETIMEDOUT; + } else if (time < 0) { +- host->data->error = time; ++ data->error = time; + } + sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, + BUF_ACC_DMAREN | BUF_ACC_DMAWEN); + host->dma_active = false; + +- if (host->data->error) +- host->data->bytes_xfered = 0; ++ if (data->error) ++ data->bytes_xfered = 0; + + return false; + } +@@ -1059,6 +1066,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) + { + struct sh_mmcif_host *host = dev_id; + struct mmc_request *mrq = host->mrq; ++ struct mmc_data *data = mrq->data; + + cancel_delayed_work_sync(&host->timeout_work); + +@@ -1106,20 +1114,18 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) + case MMCIF_WAIT_FOR_READ_END: + case MMCIF_WAIT_FOR_WRITE_END: + if (host->sd_error) +- mrq->data->error = sh_mmcif_error_manage(host); ++ data->error = sh_mmcif_error_manage(host); + break; + default: + BUG(); + } + + if (host->wait_for != MMCIF_WAIT_FOR_STOP) { +- host->data = NULL; ++ if (!mrq->cmd->error && data && !data->error) ++ data->bytes_xfered = ++ data->blocks * data->blksz; + +- if (!mrq->cmd->error && mrq->data && !mrq->data->error) +- mrq->data->bytes_xfered = +- mrq->data->blocks * mrq->data->blksz; +- +- if (mrq->stop && !mrq->cmd->error && (!mrq->data || !mrq->data->error)) { ++ if (mrq->stop && !mrq->cmd->error && (!data || !data->error)) { + sh_mmcif_stop_cmd(host, mrq); + if (!mrq->stop->error) + return IRQ_HANDLED; +@@ -1128,6 +1134,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) + + host->wait_for = MMCIF_WAIT_FOR_REQUEST; + host->state = STATE_IDLE; ++ host->mrq = NULL; + mmc_request_done(host->mmc, mrq); + + return IRQ_HANDLED; +@@ -1223,7 +1230,7 @@ static void mmcif_timeout_work(struct work_struct *work) + case MMCIF_WAIT_FOR_WRITE: + case MMCIF_WAIT_FOR_READ_END: + case MMCIF_WAIT_FOR_WRITE_END: +- host->data->error = sh_mmcif_error_manage(host); ++ mrq->data->error = sh_mmcif_error_manage(host); + break; + default: + BUG(); +@@ -1231,7 +1238,6 @@ static void mmcif_timeout_work(struct work_struct *work) + + host->state = STATE_IDLE; + host->wait_for = MMCIF_WAIT_FOR_REQUEST; +- host->data = NULL; + host->mrq = NULL; + mmc_request_done(host->mmc, mrq); + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0067-mmc-sh_mmcif-fix-MMC_GEN_CMD-setting.patch b/patches.kzm9g/0067-mmc-sh_mmcif-fix-MMC_GEN_CMD-setting.patch new file mode 100644 index 00000000000000..c7f20da2927c71 --- /dev/null +++ b/patches.kzm9g/0067-mmc-sh_mmcif-fix-MMC_GEN_CMD-setting.patch @@ -0,0 +1,40 @@ +From 34adc0ba61f82e5f33cb9d17893051afaac12a7a Mon Sep 17 00:00:00 2001 +From: "Shimoda, Yoshihiro" <yoshihiro.shimoda.uh@renesas.com> +Date: Wed, 7 Mar 2012 17:37:10 +0900 +Subject: mmc: sh_mmcif: fix MMC_GEN_CMD setting + +The MMC_GEN_CMD (CMD56) doesn't need to check busy signal. +So, the patch fixes the setting. + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 183f796b5f701f8ab530ab232e4c27aef527bd76) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index f5d8b53..f91ae31 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -745,7 +745,6 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, + case MMC_SET_WRITE_PROT: + case MMC_CLR_WRITE_PROT: + case MMC_ERASE: +- case MMC_GEN_CMD: + tmp |= CMD_SET_RBSY; + break; + } +@@ -828,7 +827,6 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, + case MMC_SET_WRITE_PROT: + case MMC_CLR_WRITE_PROT: + case MMC_ERASE: +- case MMC_GEN_CMD: + mask = MASK_START_CMD | MASK_MRBSYE; + break; + default: +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0068-mmc-sh_mmcif-simplify-bitmask-macros.patch b/patches.kzm9g/0068-mmc-sh_mmcif-simplify-bitmask-macros.patch new file mode 100644 index 00000000000000..ea61e07929d1e0 --- /dev/null +++ b/patches.kzm9g/0068-mmc-sh_mmcif-simplify-bitmask-macros.patch @@ -0,0 +1,51 @@ +From 75e468534fc26dc5eea595dee43f1a6ae0231ddc Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Fri, 16 Mar 2012 12:49:04 +0100 +Subject: mmc: sh_mmcif: simplify bitmask macros + +Purely cosmetic readability improvement, no functional change. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 135111cc5595c6a24dd826d503e2d2bae92da1c4) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/mmc/sh_mmcif.h | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h +index 04ff452..05f0e3d 100644 +--- a/include/linux/mmc/sh_mmcif.h ++++ b/include/linux/mmc/sh_mmcif.h +@@ -77,18 +77,15 @@ struct sh_mmcif_plat_data { + + /* CE_CLK_CTRL */ + #define CLK_ENABLE (1 << 24) /* 1: output mmc clock */ +-#define CLK_CLEAR ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16)) +-#define CLK_SUP_PCLK ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16)) +-#define CLKDIV_4 (1<<16) /* mmc clock frequency. +- * n: bus clock/(2^(n+1)) */ +-#define CLKDIV_256 (7<<16) /* mmc clock frequency. (see above) */ +-#define SRSPTO_256 ((1 << 13) | (0 << 12)) /* resp timeout */ +-#define SRBSYTO_29 ((1 << 11) | (1 << 10) | \ +- (1 << 9) | (1 << 8)) /* resp busy timeout */ +-#define SRWDTO_29 ((1 << 7) | (1 << 6) | \ +- (1 << 5) | (1 << 4)) /* read/write timeout */ +-#define SCCSTO_29 ((1 << 3) | (1 << 2) | \ +- (1 << 1) | (1 << 0)) /* ccs timeout */ ++#define CLK_CLEAR (0xf << 16) ++#define CLK_SUP_PCLK (0xf << 16) ++#define CLKDIV_4 (1 << 16) /* mmc clock frequency. ++ * n: bus clock/(2^(n+1)) */ ++#define CLKDIV_256 (7 << 16) /* mmc clock frequency. (see above) */ ++#define SRSPTO_256 (2 << 12) /* resp timeout */ ++#define SRBSYTO_29 (0xf << 8) /* resp busy timeout */ ++#define SRWDTO_29 (0xf << 4) /* read/write timeout */ ++#define SCCSTO_29 (0xf << 0) /* ccs timeout */ + + /* CE_VERSION */ + #define SOFT_RST_ON (1 << 31) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0069-mmc-sh_mmcif-double-clock-speed.patch b/patches.kzm9g/0069-mmc-sh_mmcif-double-clock-speed.patch new file mode 100644 index 00000000000000..921cf8c2925c74 --- /dev/null +++ b/patches.kzm9g/0069-mmc-sh_mmcif-double-clock-speed.patch @@ -0,0 +1,41 @@ +From 7d7d0268cfe4401bd5a571771542032700670266 Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Wed, 28 Mar 2012 18:01:09 +0900 +Subject: mmc: sh_mmcif: double clock speed + +Correct an off-by one error when calculating the clock divisor in cases +where the host clock is a power of two of the target clock. Previously the +divisor was one greater than the correct value in these cases leading to +the clock being set at half the desired speed. + +Thanks to Guennadi Liakhovetski for working with me on the logic for this +change. + +Tested-by: Cao Minh Hiep <hiepcm@gmail.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit f93882570496aa02ba8a47bfaf81cce43046b978) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index f91ae31..6288046 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -453,7 +453,8 @@ static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk) + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK); + else + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & +- ((fls(host->clk / clk) - 1) << 16)); ++ ((fls(DIV_ROUND_UP(host->clk, ++ clk) - 1) - 1) << 16)); + + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0070-mmc-sh_mmcif-mmc-f_max-should-be-half-of-the-bus-clo.patch b/patches.kzm9g/0070-mmc-sh_mmcif-mmc-f_max-should-be-half-of-the-bus-clo.patch new file mode 100644 index 00000000000000..49db503a2580cb --- /dev/null +++ b/patches.kzm9g/0070-mmc-sh_mmcif-mmc-f_max-should-be-half-of-the-bus-clo.patch @@ -0,0 +1,49 @@ +From f75a73e27d80a451ca2d71defb9a19412eda150b Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Wed, 28 Mar 2012 18:01:10 +0900 +Subject: mmc: sh_mmcif: mmc->f_max should be half of the bus clock + +mmc->f_max should be half of the bus clock. +And now that mmc->f_max is not equal to the bus clock the +latter should be used directly to calculate mmc->f_min. + +Cc: Magnus Damm <magnus.damm@gmail.com> +Tested-by: Cao Minh Hiep <hiepcm@gmail.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 930f152cc9998388031af577843baae572ac8ab6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 6288046..347b330 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -1297,14 +1297,14 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) + spin_lock_init(&host->lock); + + mmc->ops = &sh_mmcif_ops; +- mmc->f_max = host->clk; ++ mmc->f_max = host->clk / 2; + /* close to 400KHz */ +- if (mmc->f_max < 51200000) +- mmc->f_min = mmc->f_max / 128; +- else if (mmc->f_max < 102400000) +- mmc->f_min = mmc->f_max / 256; ++ if (host->clk < 51200000) ++ mmc->f_min = host->clk / 128; ++ else if (host->clk < 102400000) ++ mmc->f_min = host->clk / 256; + else +- mmc->f_min = mmc->f_max / 512; ++ mmc->f_min = host->clk / 512; + if (pd->ocr) + mmc->ocr_avail = pd->ocr; + mmc->caps = MMC_CAP_MMC_HIGHSPEED; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0071-mmc-sh_mmcif-Simplify-calculation-of-mmc-f_min.patch b/patches.kzm9g/0071-mmc-sh_mmcif-Simplify-calculation-of-mmc-f_min.patch new file mode 100644 index 00000000000000..a86157b48157da --- /dev/null +++ b/patches.kzm9g/0071-mmc-sh_mmcif-Simplify-calculation-of-mmc-f_min.patch @@ -0,0 +1,44 @@ +From cf3d0f14aa4b001ace80b5535d6b1d6e84a0d0e2 Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Wed, 28 Mar 2012 18:01:11 +0900 +Subject: mmc: sh_mmcif: Simplify calculation of mmc->f_min + +There is no need to tune mmc->f_min to a value near 400kHz as the MMC core +begins testing frequencies at 400kHz regardless of the value of mmc->f_min. + +As suggested by Guennadi Liakhovetski. + +Cc: Magnus Damm <magnus.damm@gmail.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Tested-by: Cao Minh Hiep <hiepcm@gmail.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit eb91b9118db8c05a5a1257b594b021d32b491254) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 347b330..020c9cc 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -1298,13 +1298,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) + + mmc->ops = &sh_mmcif_ops; + mmc->f_max = host->clk / 2; +- /* close to 400KHz */ +- if (host->clk < 51200000) +- mmc->f_min = host->clk / 128; +- else if (host->clk < 102400000) +- mmc->f_min = host->clk / 256; +- else +- mmc->f_min = host->clk / 512; ++ mmc->f_min = host->clk / 512; + if (pd->ocr) + mmc->ocr_avail = pd->ocr; + mmc->caps = MMC_CAP_MMC_HIGHSPEED; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0072-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch b/patches.kzm9g/0072-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch new file mode 100644 index 00000000000000..27f4312a233f86 --- /dev/null +++ b/patches.kzm9g/0072-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch @@ -0,0 +1,203 @@ +From 30534687e4e814095198494bc946a63c55731d43 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:07:47 -0700 +Subject: ARM: mach-shmobile: clock-r8a7740: add USB clock + +R8A7740 USB needs many clocks for workaround, +and it has confusing name "usb24s" and "usb24". +This "usb24s" will be used by other clocks. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 118 ++++++++++++++++++++++++++++++++- + 1 file changed, 116 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 99c4d74..30535f4 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -47,6 +47,7 @@ + #define PLLC01CR 0xe6150028 + + #define SUBCKCR 0xe6150080 ++#define USBCKCR 0xe615008c + + #define MSTPSR0 0xe6150030 + #define MSTPSR1 0xe6150038 +@@ -181,6 +182,100 @@ static struct clk pllc1_div2_clk = { + .parent = &pllc1_clk, + }; + ++/* USB clock */ ++static struct clk *usb24s_parents[] = { ++ [0] = &system_clk, ++ [1] = &extal2_clk ++}; ++ ++static unsigned long usb24s_recalc(struct clk *clk) ++{ ++ return clk->parent->rate; ++}; ++ ++static int usb24s_enable(struct clk *clk) ++{ ++ __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR); ++ ++ return 0; ++} ++ ++static void usb24s_disable(struct clk *clk) ++{ ++ __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR); ++} ++ ++static int usb24s_set_parent(struct clk *clk, struct clk *parent) ++{ ++ int i, ret; ++ u32 val; ++ ++ if (!clk->parent_table || !clk->parent_num) ++ return -EINVAL; ++ ++ /* Search the parent */ ++ for (i = 0; i < clk->parent_num; i++) ++ if (clk->parent_table[i] == parent) ++ break; ++ ++ if (i == clk->parent_num) ++ return -ENODEV; ++ ++ ret = clk_reparent(clk, parent); ++ if (ret < 0) ++ return ret; ++ ++ val = __raw_readl(USBCKCR); ++ val &= ~(1 << 7); ++ val |= i << 7; ++ __raw_writel(val, USBCKCR); ++ ++ return 0; ++} ++ ++static struct sh_clk_ops usb24s_clk_ops = { ++ .recalc = usb24s_recalc, ++ .enable = usb24s_enable, ++ .disable = usb24s_disable, ++ .set_parent = usb24s_set_parent, ++}; ++ ++static struct clk usb24s_clk = { ++ .ops = &usb24s_clk_ops, ++ .parent_table = usb24s_parents, ++ .parent_num = ARRAY_SIZE(usb24s_parents), ++ .parent = &system_clk, ++}; ++ ++static unsigned long usb24_recalc(struct clk *clk) ++{ ++ return clk->parent->rate / ++ ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2); ++}; ++ ++static int usb24_set_rate(struct clk *clk, unsigned long rate) ++{ ++ u32 val; ++ ++ /* closer to which ? parent->rate or parent->rate/2 */ ++ val = __raw_readl(USBCKCR); ++ val &= ~(1 << 6); ++ val |= (rate > (clk->parent->rate / 4) * 3) << 6; ++ __raw_writel(val, USBCKCR); ++ ++ return 0; ++} ++ ++static struct sh_clk_ops usb24_clk_ops = { ++ .recalc = usb24_recalc, ++ .set_rate = usb24_set_rate, ++}; ++ ++static struct clk usb24_clk = { ++ .ops = &usb24_clk_ops, ++ .parent = &usb24s_clk, ++}; ++ + struct clk *main_clks[] = { + &extalr_clk, + &extal1_clk, +@@ -196,6 +291,8 @@ struct clk *main_clks[] = { + &pllc0_clk, + &pllc1_clk, + &pllc1_div2_clk, ++ &usb24s_clk, ++ &usb24_clk, + }; + + static void div4_kick(struct clk *clk) +@@ -223,7 +320,7 @@ static struct clk_div4_table div4_table = { + + enum { + DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, +- DIV4_HPP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, ++ DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, + DIV4_NR + }; + +@@ -234,6 +331,7 @@ struct clk div4_clks[DIV4_NR] = { + [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), + [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0), + [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0), ++ [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0), + [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0), + [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0), + [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0), +@@ -257,7 +355,9 @@ enum { + MSTP222, + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + +- MSTP329, MSTP323, ++ MSTP329, MSTP323, MSTP320, ++ ++ MSTP416, MSTP407, MSTP406, + + MSTP_NR + }; +@@ -281,6 +381,11 @@ static struct clk mstp_clks[MSTP_NR] = { + + [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ + [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ ++ [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ ++ ++ [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ ++ [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */ ++ [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */ + }; + + static struct clk_lookup lookups[] = { +@@ -299,6 +404,7 @@ static struct clk_lookup lookups[] = { + CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), + CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), + CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), ++ CLKDEV_CON_ID("usb24s", &usb24s_clk), + + /* DIV4 clocks */ + CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), +@@ -335,6 +441,14 @@ static struct clk_lookup lookups[] = { + + CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), + CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), ++ CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), ++ ++ /* ICK */ ++ CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]), ++ CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]), ++ CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), ++ CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), ++ CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), + }; + + void __init r8a7740_clock_init(u8 md_ck) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0073-ALSA-workaround-change-the-timing-of-alsa_sound_last.patch b/patches.kzm9g/0073-ALSA-workaround-change-the-timing-of-alsa_sound_last.patch new file mode 100644 index 00000000000000..e0d98cea4904de --- /dev/null +++ b/patches.kzm9g/0073-ALSA-workaround-change-the-timing-of-alsa_sound_last.patch @@ -0,0 +1,38 @@ +From d7462814e127df262ab184179b807f388fe51c1f Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 19 Apr 2012 00:00:27 -0700 +Subject: ALSA: workaround: change the timing of alsa_sound_last_init() + +Current alsa_sound_last_init() was called as __initcall(). +So, on current ALSA, only devices that had been properly +registered at this point were shown. +So, it will show "No soundcards found" if driver requests +probe deferment. it's often misleading. +This patch delays the timing of alsa_sound_last_init() +as workaround. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Reviwed-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +(cherry picked from commit 590b4775d6b628c7ad215fd0335a0a787032e2dd) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/last.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/last.c b/sound/last.c +index bdd0857..7ffc182 100644 +--- a/sound/last.c ++++ b/sound/last.c +@@ -38,4 +38,4 @@ static int __init alsa_sound_last_init(void) + return 0; + } + +-__initcall(alsa_sound_last_init); ++late_initcall_sync(alsa_sound_last_init); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0074-ASoC-core-Optimise-and-refactor-pcm_new-to-pass-only.patch b/patches.kzm9g/0074-ASoC-core-Optimise-and-refactor-pcm_new-to-pass-only.patch new file mode 100644 index 00000000000000..bd3ba2b7f43230 --- /dev/null +++ b/patches.kzm9g/0074-ASoC-core-Optimise-and-refactor-pcm_new-to-pass-only.patch @@ -0,0 +1,529 @@ +From c41e2859faba7ea13c8bf3bf54a5c25d8297a09c Mon Sep 17 00:00:00 2001 +From: Liam Girdwood <lrg@ti.com> +Date: Tue, 7 Jun 2011 16:08:33 +0100 +Subject: ASoC: core - Optimise and refactor pcm_new() to pass only rtd + +Currently pcm_new() passes in 3 arguments :- card, pcm and DAI. + +Refactor this to only pass in 1 argument (i.e. the rtd) since struct rtd contains +card, pcm and DAI along with other members too that are useful too. + +Signed-off-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 552d1ef6b5a98d7b95959d5b139071e3c90cebf1) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/sound/soc.h | 3 +-- + sound/soc/atmel/atmel-pcm.c | 6 ++++-- + sound/soc/au1x/dbdma2.c | 7 ++++--- + sound/soc/blackfin/bf5xx-ac97-pcm.c | 6 ++++-- + sound/soc/blackfin/bf5xx-i2s-pcm.c | 6 ++++-- + sound/soc/blackfin/bf5xx-tdm-pcm.c | 6 ++++-- + sound/soc/davinci/davinci-pcm.c | 6 ++++-- + sound/soc/ep93xx/ep93xx-pcm.c | 6 ++++-- + sound/soc/fsl/fsl_dma.c | 6 ++++-- + sound/soc/fsl/mpc5200_dma.c | 7 ++++--- + sound/soc/imx/imx-pcm-fiq.c | 8 +++++--- + sound/soc/imx/imx-ssi.c | 7 ++++--- + sound/soc/imx/imx-ssi.h | 3 +-- + sound/soc/jz4740/jz4740-pcm.c | 6 ++++-- + sound/soc/kirkwood/kirkwood-dma.c | 6 ++++-- + sound/soc/mid-x86/sst_platform.c | 5 +++-- + sound/soc/nuc900/nuc900-pcm.c | 7 +++++-- + sound/soc/omap/omap-pcm.c | 6 ++++-- + sound/soc/pxa/pxa2xx-pcm.c | 6 ++++-- + sound/soc/s6000/s6000-pcm.c | 7 ++++--- + sound/soc/samsung/dma.c | 6 ++++-- + sound/soc/sh/dma-sh7760.c | 6 +++--- + sound/soc/sh/fsi.c | 6 +++--- + sound/soc/sh/siu_pcm.c | 5 +++-- + sound/soc/soc-core.c | 3 +-- + sound/soc/tegra/tegra_pcm.c | 6 ++++-- + sound/soc/txx9/txx9aclc.c | 5 +++-- + 27 files changed, 96 insertions(+), 61 deletions(-) + +diff --git a/include/sound/soc.h b/include/sound/soc.h +index 3a4bd3a..e9db08c 100644 +--- a/include/sound/soc.h ++++ b/include/sound/soc.h +@@ -623,8 +623,7 @@ struct snd_soc_platform_driver { + int (*resume)(struct snd_soc_dai *dai); + + /* pcm creation and destruction */ +- int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, +- struct snd_pcm *); ++ int (*pcm_new)(struct snd_soc_pcm_runtime *); + void (*pcm_free)(struct snd_pcm *); + + /* +diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c +index d0e7532..42f699c 100644 +--- a/sound/soc/atmel/atmel-pcm.c ++++ b/sound/soc/atmel/atmel-pcm.c +@@ -364,9 +364,11 @@ static struct snd_pcm_ops atmel_pcm_ops = { + \*--------------------------------------------------------------------------*/ + static u64 atmel_pcm_dmamask = 0xffffffff; + +-static int atmel_pcm_new(struct snd_card *card, +- struct snd_soc_dai *dai, struct snd_pcm *pcm) ++static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + if (!card->dev->dma_mask) +diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c +index 10fdd28..20bb53a 100644 +--- a/sound/soc/au1x/dbdma2.c ++++ b/sound/soc/au1x/dbdma2.c +@@ -319,10 +319,11 @@ static void au1xpsc_pcm_free_dma_buffers(struct snd_pcm *pcm) + snd_pcm_lib_preallocate_free_for_all(pcm); + } + +-static int au1xpsc_pcm_new(struct snd_card *card, +- struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_pcm *pcm = rtd->pcm; ++ + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + card->dev, AU1XPSC_BUFFER_MIN_BYTES, (4096 * 1024) - 1); + +diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c +index 98b44b3..9e59f68 100644 +--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c ++++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c +@@ -418,9 +418,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) + + static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); + +-int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + pr_debug("%s enter\n", __func__); +diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c +index f1fd95b..c42fb73 100644 +--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c ++++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c +@@ -257,9 +257,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) + + static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); + +-int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + pr_debug("%s enter\n", __func__); +diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c +index 07cfc7a..c95cc03 100644 +--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c ++++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c +@@ -283,9 +283,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) + + static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); + +-static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int bf5xx_pcm_tdm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + if (!card->dev->dma_mask) +diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c +index 9d35b8c..29759e1 100644 +--- a/sound/soc/davinci/davinci-pcm.c ++++ b/sound/soc/davinci/davinci-pcm.c +@@ -811,9 +811,11 @@ static void davinci_pcm_free(struct snd_pcm *pcm) + + static u64 davinci_pcm_dmamask = 0xffffffff; + +-static int davinci_pcm_new(struct snd_card *card, +- struct snd_soc_dai *dai, struct snd_pcm *pcm) ++static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret; + + if (!card->dev->dma_mask) +diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c +index a456e49..e27c417 100644 +--- a/sound/soc/ep93xx/ep93xx-pcm.c ++++ b/sound/soc/ep93xx/ep93xx-pcm.c +@@ -266,9 +266,11 @@ static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm) + + static u64 ep93xx_pcm_dmamask = 0xffffffff; + +-static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + if (!card->dev->dma_mask) +diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c +index 6680c0b..5312d1b 100644 +--- a/sound/soc/fsl/fsl_dma.c ++++ b/sound/soc/fsl/fsl_dma.c +@@ -294,9 +294,11 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) + * Regardless of where the memory is actually allocated, since the device can + * technically DMA to any 36-bit address, we do need to set the DMA mask to 36. + */ +-static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + static u64 fsl_dma_dmamask = DMA_BIT_MASK(36); + int ret; + +diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c +index cbaf8b7..61d2ecc 100644 +--- a/sound/soc/fsl/mpc5200_dma.c ++++ b/sound/soc/fsl/mpc5200_dma.c +@@ -299,10 +299,11 @@ static struct snd_pcm_ops psc_dma_ops = { + }; + + static u64 psc_dma_dmamask = 0xffffffff; +-static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int psc_dma_new(struct snd_soc_pcm_runtime *rtd) + { +- struct snd_soc_pcm_runtime *rtd = pcm->private_data; ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); + size_t size = psc_dma_hardware.buffer_bytes_max; + int rc = 0; +diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c +index 413b78d..309c59e 100644 +--- a/sound/soc/imx/imx-pcm-fiq.c ++++ b/sound/soc/imx/imx-pcm-fiq.c +@@ -238,12 +238,14 @@ static struct snd_pcm_ops imx_pcm_ops = { + + static int ssi_irq = 0; + +-static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret; + +- ret = imx_pcm_new(card, dai, pcm); ++ ret = imx_pcm_new(rtd); + if (ret) + return ret; + +diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c +index 3b56254..3a676cd 100644 +--- a/sound/soc/imx/imx-ssi.c ++++ b/sound/soc/imx/imx-ssi.c +@@ -388,10 +388,11 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) + + static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); + +-int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) + { +- ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + if (!card->dev->dma_mask) +diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h +index dc8a875..0a84cec 100644 +--- a/sound/soc/imx/imx-ssi.h ++++ b/sound/soc/imx/imx-ssi.h +@@ -225,8 +225,7 @@ struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev, + struct imx_ssi *ssi); + + int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma); +-int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm); ++int imx_pcm_new(struct snd_soc_pcm_runtime *rtd); + void imx_pcm_free(struct snd_pcm *pcm); + + /* +diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c +index fb1483f..a7c9578 100644 +--- a/sound/soc/jz4740/jz4740-pcm.c ++++ b/sound/soc/jz4740/jz4740-pcm.c +@@ -299,9 +299,11 @@ static void jz4740_pcm_free(struct snd_pcm *pcm) + + static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32); + +-int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + if (!card->dev->dma_mask) +diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c +index e13c6ce..cd33de1 100644 +--- a/sound/soc/kirkwood/kirkwood-dma.c ++++ b/sound/soc/kirkwood/kirkwood-dma.c +@@ -312,9 +312,11 @@ static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm, + return 0; + } + +-static int kirkwood_dma_new(struct snd_card *card, +- struct snd_soc_dai *dai, struct snd_pcm *pcm) ++static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret; + + if (!card->dev->dma_mask) +diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c +index 5a946b4..3e78260 100644 +--- a/sound/soc/mid-x86/sst_platform.c ++++ b/sound/soc/mid-x86/sst_platform.c +@@ -402,9 +402,10 @@ static void sst_pcm_free(struct snd_pcm *pcm) + snd_pcm_lib_preallocate_free_for_all(pcm); + } + +-int sst_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int retval = 0; + + pr_debug("sst_pcm_new called\n"); +diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c +index 8263f56..d589ef1 100644 +--- a/sound/soc/nuc900/nuc900-pcm.c ++++ b/sound/soc/nuc900/nuc900-pcm.c +@@ -315,9 +315,12 @@ static void nuc900_dma_free_dma_buffers(struct snd_pcm *pcm) + } + + static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32); +-static int nuc900_dma_new(struct snd_card *card, +- struct snd_soc_dai *dai, struct snd_pcm *pcm) ++static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; ++ + if (!card->dev->dma_mask) + card->dev->dma_mask = &nuc900_pcm_dmamask; + if (!card->dev->coherent_dma_mask) +diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c +index e6a6b99..b2f5751 100644 +--- a/sound/soc/omap/omap-pcm.c ++++ b/sound/soc/omap/omap-pcm.c +@@ -366,9 +366,11 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm) + } + } + +-static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + if (!card->dev->dma_mask) +diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c +index fab20a5..da28394 100644 +--- a/sound/soc/pxa/pxa2xx-pcm.c ++++ b/sound/soc/pxa/pxa2xx-pcm.c +@@ -85,9 +85,11 @@ static struct snd_pcm_ops pxa2xx_pcm_ops = { + + static u64 pxa2xx_pcm_dmamask = DMA_BIT_MASK(32); + +-static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + if (!card->dev->dma_mask) +diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c +index ab3ccae..80c85fd 100644 +--- a/sound/soc/s6000/s6000-pcm.c ++++ b/sound/soc/s6000/s6000-pcm.c +@@ -443,10 +443,11 @@ static void s6000_pcm_free(struct snd_pcm *pcm) + + static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32); + +-static int s6000_pcm_new(struct snd_card *card, +- struct snd_soc_dai *dai, struct snd_pcm *pcm) ++static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime) + { +- struct snd_soc_pcm_runtime *runtime = pcm->private_data; ++ struct snd_card *card = runtime->card->snd_card; ++ struct snd_soc_dai *dai = runtime->cpu_dai; ++ struct snd_pcm *pcm = runtime->pcm; + struct s6000_pcm_dma_params *params; + int res; + +diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c +index 5cb3b88..9465588 100644 +--- a/sound/soc/samsung/dma.c ++++ b/sound/soc/samsung/dma.c +@@ -425,9 +425,11 @@ static void dma_free_dma_buffers(struct snd_pcm *pcm) + + static u64 dma_mask = DMA_BIT_MASK(32); + +-static int dma_new(struct snd_card *card, +- struct snd_soc_dai *dai, struct snd_pcm *pcm) ++static int dma_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + pr_debug("Entered %s\n", __func__); +diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c +index c326d29..db74005 100644 +--- a/sound/soc/sh/dma-sh7760.c ++++ b/sound/soc/sh/dma-sh7760.c +@@ -327,10 +327,10 @@ static void camelot_pcm_free(struct snd_pcm *pcm) + snd_pcm_lib_preallocate_free_for_all(pcm); + } + +-static int camelot_pcm_new(struct snd_card *card, +- struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_pcm *pcm = rtd->pcm; ++ + /* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel + * in MMAP mode (i.e. aplay -M) + */ +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 4a9da6b..339a1df 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1129,10 +1129,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm) + snd_pcm_lib_preallocate_free_for_all(pcm); + } + +-static int fsi_pcm_new(struct snd_card *card, +- struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_pcm *pcm = rtd->pcm; ++ + /* + * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel + * in MMAP mode (i.e. aplay -M) +diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c +index a423bab..f8f6816 100644 +--- a/sound/soc/sh/siu_pcm.c ++++ b/sound/soc/sh/siu_pcm.c +@@ -527,10 +527,11 @@ static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss) + return bytes_to_frames(ss->runtime, ptr); + } + +-static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int siu_pcm_new(struct snd_soc_pcm_runtime *rtd) + { + /* card->dev == socdev->dev, see snd_soc_new_pcms() */ ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_pcm *pcm = rtd->pcm; + struct siu_info *info = siu_i2s_data; + struct platform_device *pdev = to_platform_device(card->dev); + int ret; +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index e2bfe1d..f2a920a 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -2157,8 +2157,7 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); + + if (platform->driver->pcm_new) { +- ret = platform->driver->pcm_new(rtd->card->snd_card, +- codec_dai, pcm); ++ ret = platform->driver->pcm_new(rtd); + if (ret < 0) { + pr_err("asoc: platform pcm constructor failed\n"); + return ret; +diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c +index 6201710..c7cfd96 100644 +--- a/sound/soc/tegra/tegra_pcm.c ++++ b/sound/soc/tegra/tegra_pcm.c +@@ -327,9 +327,11 @@ static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) + + static u64 tegra_dma_mask = DMA_BIT_MASK(32); + +-static int tegra_pcm_new(struct snd_card *card, +- struct snd_soc_dai *dai, struct snd_pcm *pcm) ++static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_card *card = rtd->card->snd_card; ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + if (!card->dev->dma_mask) +diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c +index f4aa4e0..34aa972 100644 +--- a/sound/soc/txx9/txx9aclc.c ++++ b/sound/soc/txx9/txx9aclc.c +@@ -288,9 +288,10 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm) + snd_pcm_lib_preallocate_free_for_all(pcm); + } + +-static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +- struct snd_pcm *pcm) ++static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd) + { ++ struct snd_soc_dai *dai = rtd->cpu_dai; ++ struct snd_pcm *pcm = rtd->pcm; + struct platform_device *pdev = to_platform_device(dai->platform->dev); + struct txx9aclc_soc_device *dev; + struct resource *r; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0075-ASoC-core-Allow-components-to-probe-remove-in-sequen.patch b/patches.kzm9g/0075-ASoC-core-Allow-components-to-probe-remove-in-sequen.patch new file mode 100644 index 00000000000000..7a32b263c33977 --- /dev/null +++ b/patches.kzm9g/0075-ASoC-core-Allow-components-to-probe-remove-in-sequen.patch @@ -0,0 +1,249 @@ +From 94df9e9b6182759ffe6a44fb699a5bd97bd5ca53 Mon Sep 17 00:00:00 2001 +From: Liam Girdwood <lrg@ti.com> +Date: Tue, 7 Jun 2011 16:08:05 +0100 +Subject: ASoC: core - Allow components to probe/remove in sequence. + +Some ASoC components depend on other ASoC components to provide clocks and +power resources in order to probe() and vice versa for remove(). + +Allow components to be ordered so that components can be probed() and removed() +in sequences that conform to their dependencies. + +Signed-off-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 0168bf0d130de83cd3532b834237c6228a6158dd) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/sound/soc-dai.h | 4 ++++ + include/sound/soc.h | 18 +++++++++++++++ + sound/soc/soc-core.c | 60 ++++++++++++++++++++++++++++++++----------------- + 3 files changed, 61 insertions(+), 21 deletions(-) + +diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h +index 1bafe95..5ad5f3a 100644 +--- a/include/sound/soc-dai.h ++++ b/include/sound/soc-dai.h +@@ -209,6 +209,10 @@ struct snd_soc_dai_driver { + struct snd_soc_pcm_stream capture; + struct snd_soc_pcm_stream playback; + unsigned int symmetric_rates:1; ++ ++ /* probe ordering - for components with runtime dependencies */ ++ int probe_order; ++ int remove_order; + }; + + /* +diff --git a/include/sound/soc.h b/include/sound/soc.h +index e9db08c..447232c 100644 +--- a/include/sound/soc.h ++++ b/include/sound/soc.h +@@ -203,6 +203,16 @@ + SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues) + + /* ++ * Component probe and remove ordering levels for components with runtime ++ * dependencies. ++ */ ++#define SND_SOC_COMP_ORDER_FIRST -2 ++#define SND_SOC_COMP_ORDER_EARLY -1 ++#define SND_SOC_COMP_ORDER_NORMAL 0 ++#define SND_SOC_COMP_ORDER_LATE 1 ++#define SND_SOC_COMP_ORDER_LAST 2 ++ ++/* + * Bias levels + * + * @ON: Bias is fully on for audio playback and capture operations. +@@ -612,6 +622,10 @@ struct snd_soc_codec_driver { + + void (*seq_notifier)(struct snd_soc_dapm_context *, + enum snd_soc_dapm_type, int); ++ ++ /* probe ordering - for components with runtime dependencies */ ++ int probe_order; ++ int remove_order; + }; + + /* SoC platform interface */ +@@ -635,6 +649,10 @@ struct snd_soc_platform_driver { + + /* platform stream ops */ + struct snd_pcm_ops *ops; ++ ++ /* probe ordering - for components with runtime dependencies */ ++ int probe_order; ++ int remove_order; + }; + + struct snd_soc_platform { +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index f2a920a..841b1c9 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -1396,7 +1396,7 @@ static void soc_remove_codec(struct snd_soc_codec *codec) + module_put(codec->dev->driver->owner); + } + +-static void soc_remove_dai_link(struct snd_soc_card *card, int num) ++static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) + { + struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; + struct snd_soc_codec *codec = rtd->codec; +@@ -1413,7 +1413,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) + } + + /* remove the CODEC DAI */ +- if (codec_dai && codec_dai->probed) { ++ if (codec_dai && codec_dai->probed && ++ codec_dai->driver->remove_order == order) { + if (codec_dai->driver->remove) { + err = codec_dai->driver->remove(codec_dai); + if (err < 0) +@@ -1424,7 +1425,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) + } + + /* remove the platform */ +- if (platform && platform->probed) { ++ if (platform && platform->probed && ++ platform->driver->remove_order == order) { + if (platform->driver->remove) { + err = platform->driver->remove(platform); + if (err < 0) +@@ -1436,11 +1438,13 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) + } + + /* remove the CODEC */ +- if (codec && codec->probed) ++ if (codec && codec->probed && ++ codec->driver->remove_order == order) + soc_remove_codec(codec); + + /* remove the cpu_dai */ +- if (cpu_dai && cpu_dai->probed) { ++ if (cpu_dai && cpu_dai->probed && ++ cpu_dai->driver->remove_order == order) { + if (cpu_dai->driver->remove) { + err = cpu_dai->driver->remove(cpu_dai); + if (err < 0) +@@ -1454,11 +1458,13 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) + + static void soc_remove_dai_links(struct snd_soc_card *card) + { +- int i; +- +- for (i = 0; i < card->num_rtd; i++) +- soc_remove_dai_link(card, i); ++ int dai, order; + ++ for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; ++ order++) { ++ for (dai = 0; dai < card->num_rtd; dai++) ++ soc_remove_dai_link(card, dai, order); ++ } + card->num_rtd = 0; + } + +@@ -1599,7 +1605,7 @@ static int soc_post_component_init(struct snd_soc_card *card, + return 0; + } + +-static int soc_probe_dai_link(struct snd_soc_card *card, int num) ++static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) + { + struct snd_soc_dai_link *dai_link = &card->dai_link[num]; + struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; +@@ -1608,7 +1614,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) + struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; + int ret; + +- dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); ++ dev_dbg(card->dev, "probe %s dai link %d late %d\n", ++ card->name, num, order); + + /* config components */ + codec_dai->codec = codec; +@@ -1620,7 +1627,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) + rtd->pmdown_time = pmdown_time; + + /* probe the cpu_dai */ +- if (!cpu_dai->probed) { ++ if (!cpu_dai->probed && ++ cpu_dai->driver->probe_order == order) { + if (!try_module_get(cpu_dai->dev->driver->owner)) + return -ENODEV; + +@@ -1639,14 +1647,16 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) + } + + /* probe the CODEC */ +- if (!codec->probed) { ++ if (!codec->probed && ++ codec->driver->probe_order == order) { + ret = soc_probe_codec(card, codec); + if (ret < 0) + return ret; + } + + /* probe the platform */ +- if (!platform->probed) { ++ if (!platform->probed && ++ platform->driver->probe_order == order) { + if (!try_module_get(platform->dev->driver->owner)) + return -ENODEV; + +@@ -1665,7 +1675,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) + } + + /* probe the CODEC DAI */ +- if (!codec_dai->probed) { ++ if (!codec_dai->probed && codec_dai->driver->probe_order == order) { + if (codec_dai->driver->probe) { + ret = codec_dai->driver->probe(codec_dai); + if (ret < 0) { +@@ -1680,6 +1690,10 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) + list_add(&codec_dai->card_list, &card->dai_dev_list); + } + ++ /* complete DAI probe during last probe */ ++ if (order != SND_SOC_COMP_ORDER_LAST) ++ return 0; ++ + /* DAPM dai link stream work */ + INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); + +@@ -1820,7 +1834,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) + struct snd_soc_codec *codec; + struct snd_soc_codec_conf *codec_conf; + enum snd_soc_compress_type compress_type; +- int ret, i; ++ int ret, i, order; + + mutex_lock(&card->mutex); + +@@ -1898,12 +1912,16 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) + goto card_probe_error; + } + +- for (i = 0; i < card->num_links; i++) { +- ret = soc_probe_dai_link(card, i); +- if (ret < 0) { +- pr_err("asoc: failed to instantiate card %s: %d\n", ++ /* early DAI link probe */ ++ for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; ++ order++) { ++ for (i = 0; i < card->num_links; i++) { ++ ret = soc_probe_dai_link(card, i, order); ++ if (ret < 0) { ++ pr_err("asoc: failed to instantiate card %s: %d\n", + card->name, ret); +- goto probe_dai_err; ++ goto probe_dai_err; ++ } + } + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0076-ASoC-core-Separate-out-PCM-operations-into-new-file.patch b/patches.kzm9g/0076-ASoC-core-Separate-out-PCM-operations-into-new-file.patch new file mode 100644 index 00000000000000..a4e97ef1757301 --- /dev/null +++ b/patches.kzm9g/0076-ASoC-core-Separate-out-PCM-operations-into-new-file.patch @@ -0,0 +1,1333 @@ +From 481aa7d92ac3e22d6bc73a27f56efe7cec947585 Mon Sep 17 00:00:00 2001 +From: Liam Girdwood <lrg@ti.com> +Date: Thu, 9 Jun 2011 14:45:53 +0100 +Subject: ASoC: core - Separate out PCM operations into new file. + +In preparation for Dynamic PCM support (AKA DSP support). + +There will be future patches that add support to allow PCMs to be dynamically +routed to multiple DAIs at startup and also during stream runtime. This patch +moves the ASoC core PCM operaitions into a new file called soc-pcm.c. This will +in simplify the ASoC core features into distinct files. + +Signed-off-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit ddee627cf6bb601aa980104fc17d4f84201380be) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/Makefile | 2 +- + sound/soc/soc-core.c | 612 +----------------------------------------------- + sound/soc/soc-pcm.c | 639 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 641 insertions(+), 612 deletions(-) + create mode 100644 sound/soc/soc-pcm.c + +diff --git a/sound/soc/Makefile b/sound/soc/Makefile +index 1ed61c5..adb5719 100644 +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -1,4 +1,4 @@ +-snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o ++snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o soc-pcm.o + + obj-$(CONFIG_SND_SOC) += snd-soc-core.o + obj-$(CONFIG_SND_SOC) += codecs/ +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index 841b1c9..f5ec7d8 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -45,7 +45,6 @@ + + #define NAME_SIZE 32 + +-static DEFINE_MUTEX(pcm_mutex); + static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); + + #ifdef CONFIG_DEBUG_FS +@@ -59,7 +58,7 @@ static LIST_HEAD(dai_list); + static LIST_HEAD(platform_list); + static LIST_HEAD(codec_list); + +-static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); ++int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); + + /* + * This is a timeout to do a DAPM powerdown after a stream is closed(). +@@ -486,552 +485,6 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) + } + #endif + +-static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- struct snd_soc_dai *codec_dai = rtd->codec_dai; +- int ret; +- +- if (!codec_dai->driver->symmetric_rates && +- !cpu_dai->driver->symmetric_rates && +- !rtd->dai_link->symmetric_rates) +- return 0; +- +- /* This can happen if multiple streams are starting simultaneously - +- * the second can need to get its constraints before the first has +- * picked a rate. Complain and allow the application to carry on. +- */ +- if (!rtd->rate) { +- dev_warn(&rtd->dev, +- "Not enforcing symmetric_rates due to race\n"); +- return 0; +- } +- +- dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate); +- +- ret = snd_pcm_hw_constraint_minmax(substream->runtime, +- SNDRV_PCM_HW_PARAM_RATE, +- rtd->rate, rtd->rate); +- if (ret < 0) { +- dev_err(&rtd->dev, +- "Unable to apply rate symmetry constraint: %d\n", ret); +- return ret; +- } +- +- return 0; +-} +- +-/* +- * Called by ALSA when a PCM substream is opened, the runtime->hw record is +- * then initialized and any private data can be allocated. This also calls +- * startup for the cpu DAI, platform, machine and codec DAI. +- */ +-static int soc_pcm_open(struct snd_pcm_substream *substream) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct snd_soc_platform *platform = rtd->platform; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- struct snd_soc_dai *codec_dai = rtd->codec_dai; +- struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; +- struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; +- int ret = 0; +- +- mutex_lock(&pcm_mutex); +- +- /* startup the audio subsystem */ +- if (cpu_dai->driver->ops->startup) { +- ret = cpu_dai->driver->ops->startup(substream, cpu_dai); +- if (ret < 0) { +- printk(KERN_ERR "asoc: can't open interface %s\n", +- cpu_dai->name); +- goto out; +- } +- } +- +- if (platform->driver->ops && platform->driver->ops->open) { +- ret = platform->driver->ops->open(substream); +- if (ret < 0) { +- printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); +- goto platform_err; +- } +- } +- +- if (codec_dai->driver->ops->startup) { +- ret = codec_dai->driver->ops->startup(substream, codec_dai); +- if (ret < 0) { +- printk(KERN_ERR "asoc: can't open codec %s\n", +- codec_dai->name); +- goto codec_dai_err; +- } +- } +- +- if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { +- ret = rtd->dai_link->ops->startup(substream); +- if (ret < 0) { +- printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name); +- goto machine_err; +- } +- } +- +- /* Check that the codec and cpu DAIs are compatible */ +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- runtime->hw.rate_min = +- max(codec_dai_drv->playback.rate_min, +- cpu_dai_drv->playback.rate_min); +- runtime->hw.rate_max = +- min(codec_dai_drv->playback.rate_max, +- cpu_dai_drv->playback.rate_max); +- runtime->hw.channels_min = +- max(codec_dai_drv->playback.channels_min, +- cpu_dai_drv->playback.channels_min); +- runtime->hw.channels_max = +- min(codec_dai_drv->playback.channels_max, +- cpu_dai_drv->playback.channels_max); +- runtime->hw.formats = +- codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats; +- runtime->hw.rates = +- codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates; +- if (codec_dai_drv->playback.rates +- & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) +- runtime->hw.rates |= cpu_dai_drv->playback.rates; +- if (cpu_dai_drv->playback.rates +- & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) +- runtime->hw.rates |= codec_dai_drv->playback.rates; +- } else { +- runtime->hw.rate_min = +- max(codec_dai_drv->capture.rate_min, +- cpu_dai_drv->capture.rate_min); +- runtime->hw.rate_max = +- min(codec_dai_drv->capture.rate_max, +- cpu_dai_drv->capture.rate_max); +- runtime->hw.channels_min = +- max(codec_dai_drv->capture.channels_min, +- cpu_dai_drv->capture.channels_min); +- runtime->hw.channels_max = +- min(codec_dai_drv->capture.channels_max, +- cpu_dai_drv->capture.channels_max); +- runtime->hw.formats = +- codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats; +- runtime->hw.rates = +- codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates; +- if (codec_dai_drv->capture.rates +- & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) +- runtime->hw.rates |= cpu_dai_drv->capture.rates; +- if (cpu_dai_drv->capture.rates +- & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) +- runtime->hw.rates |= codec_dai_drv->capture.rates; +- } +- +- ret = -EINVAL; +- snd_pcm_limit_hw_rates(runtime); +- if (!runtime->hw.rates) { +- printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", +- codec_dai->name, cpu_dai->name); +- goto config_err; +- } +- if (!runtime->hw.formats) { +- printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", +- codec_dai->name, cpu_dai->name); +- goto config_err; +- } +- if (!runtime->hw.channels_min || !runtime->hw.channels_max || +- runtime->hw.channels_min > runtime->hw.channels_max) { +- printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", +- codec_dai->name, cpu_dai->name); +- goto config_err; +- } +- +- /* Symmetry only applies if we've already got an active stream. */ +- if (cpu_dai->active || codec_dai->active) { +- ret = soc_pcm_apply_symmetry(substream); +- if (ret != 0) +- goto config_err; +- } +- +- pr_debug("asoc: %s <-> %s info:\n", +- codec_dai->name, cpu_dai->name); +- pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); +- pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, +- runtime->hw.channels_max); +- pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, +- runtime->hw.rate_max); +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- cpu_dai->playback_active++; +- codec_dai->playback_active++; +- } else { +- cpu_dai->capture_active++; +- codec_dai->capture_active++; +- } +- cpu_dai->active++; +- codec_dai->active++; +- rtd->codec->active++; +- mutex_unlock(&pcm_mutex); +- return 0; +- +-config_err: +- if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) +- rtd->dai_link->ops->shutdown(substream); +- +-machine_err: +- if (codec_dai->driver->ops->shutdown) +- codec_dai->driver->ops->shutdown(substream, codec_dai); +- +-codec_dai_err: +- if (platform->driver->ops && platform->driver->ops->close) +- platform->driver->ops->close(substream); +- +-platform_err: +- if (cpu_dai->driver->ops->shutdown) +- cpu_dai->driver->ops->shutdown(substream, cpu_dai); +-out: +- mutex_unlock(&pcm_mutex); +- return ret; +-} +- +-/* +- * Power down the audio subsystem pmdown_time msecs after close is called. +- * This is to ensure there are no pops or clicks in between any music tracks +- * due to DAPM power cycling. +- */ +-static void close_delayed_work(struct work_struct *work) +-{ +- struct snd_soc_pcm_runtime *rtd = +- container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); +- struct snd_soc_dai *codec_dai = rtd->codec_dai; +- +- mutex_lock(&pcm_mutex); +- +- pr_debug("pop wq checking: %s status: %s waiting: %s\n", +- codec_dai->driver->playback.stream_name, +- codec_dai->playback_active ? "active" : "inactive", +- codec_dai->pop_wait ? "yes" : "no"); +- +- /* are we waiting on this codec DAI stream */ +- if (codec_dai->pop_wait == 1) { +- codec_dai->pop_wait = 0; +- snd_soc_dapm_stream_event(rtd, +- codec_dai->driver->playback.stream_name, +- SND_SOC_DAPM_STREAM_STOP); +- } +- +- mutex_unlock(&pcm_mutex); +-} +- +-/* +- * Called by ALSA when a PCM substream is closed. Private data can be +- * freed here. The cpu DAI, codec DAI, machine and platform are also +- * shutdown. +- */ +-static int soc_codec_close(struct snd_pcm_substream *substream) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct snd_soc_platform *platform = rtd->platform; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- struct snd_soc_dai *codec_dai = rtd->codec_dai; +- struct snd_soc_codec *codec = rtd->codec; +- +- mutex_lock(&pcm_mutex); +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- cpu_dai->playback_active--; +- codec_dai->playback_active--; +- } else { +- cpu_dai->capture_active--; +- codec_dai->capture_active--; +- } +- +- cpu_dai->active--; +- codec_dai->active--; +- codec->active--; +- +- /* Muting the DAC suppresses artifacts caused during digital +- * shutdown, for example from stopping clocks. +- */ +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- snd_soc_dai_digital_mute(codec_dai, 1); +- +- if (cpu_dai->driver->ops->shutdown) +- cpu_dai->driver->ops->shutdown(substream, cpu_dai); +- +- if (codec_dai->driver->ops->shutdown) +- codec_dai->driver->ops->shutdown(substream, codec_dai); +- +- if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) +- rtd->dai_link->ops->shutdown(substream); +- +- if (platform->driver->ops && platform->driver->ops->close) +- platform->driver->ops->close(substream); +- cpu_dai->runtime = NULL; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- /* start delayed pop wq here for playback streams */ +- codec_dai->pop_wait = 1; +- schedule_delayed_work(&rtd->delayed_work, +- msecs_to_jiffies(rtd->pmdown_time)); +- } else { +- /* capture streams can be powered down now */ +- snd_soc_dapm_stream_event(rtd, +- codec_dai->driver->capture.stream_name, +- SND_SOC_DAPM_STREAM_STOP); +- } +- +- mutex_unlock(&pcm_mutex); +- return 0; +-} +- +-/* +- * Called by ALSA when the PCM substream is prepared, can set format, sample +- * rate, etc. This function is non atomic and can be called multiple times, +- * it can refer to the runtime info. +- */ +-static int soc_pcm_prepare(struct snd_pcm_substream *substream) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct snd_soc_platform *platform = rtd->platform; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- struct snd_soc_dai *codec_dai = rtd->codec_dai; +- int ret = 0; +- +- mutex_lock(&pcm_mutex); +- +- if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { +- ret = rtd->dai_link->ops->prepare(substream); +- if (ret < 0) { +- printk(KERN_ERR "asoc: machine prepare error\n"); +- goto out; +- } +- } +- +- if (platform->driver->ops && platform->driver->ops->prepare) { +- ret = platform->driver->ops->prepare(substream); +- if (ret < 0) { +- printk(KERN_ERR "asoc: platform prepare error\n"); +- goto out; +- } +- } +- +- if (codec_dai->driver->ops->prepare) { +- ret = codec_dai->driver->ops->prepare(substream, codec_dai); +- if (ret < 0) { +- printk(KERN_ERR "asoc: codec DAI prepare error\n"); +- goto out; +- } +- } +- +- if (cpu_dai->driver->ops->prepare) { +- ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); +- if (ret < 0) { +- printk(KERN_ERR "asoc: cpu DAI prepare error\n"); +- goto out; +- } +- } +- +- /* cancel any delayed stream shutdown that is pending */ +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && +- codec_dai->pop_wait) { +- codec_dai->pop_wait = 0; +- cancel_delayed_work(&rtd->delayed_work); +- } +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- snd_soc_dapm_stream_event(rtd, +- codec_dai->driver->playback.stream_name, +- SND_SOC_DAPM_STREAM_START); +- else +- snd_soc_dapm_stream_event(rtd, +- codec_dai->driver->capture.stream_name, +- SND_SOC_DAPM_STREAM_START); +- +- snd_soc_dai_digital_mute(codec_dai, 0); +- +-out: +- mutex_unlock(&pcm_mutex); +- return ret; +-} +- +-/* +- * Called by ALSA when the hardware params are set by application. This +- * function can also be called multiple times and can allocate buffers +- * (using snd_pcm_lib_* ). It's non-atomic. +- */ +-static int soc_pcm_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct snd_soc_platform *platform = rtd->platform; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- struct snd_soc_dai *codec_dai = rtd->codec_dai; +- int ret = 0; +- +- mutex_lock(&pcm_mutex); +- +- if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { +- ret = rtd->dai_link->ops->hw_params(substream, params); +- if (ret < 0) { +- printk(KERN_ERR "asoc: machine hw_params failed\n"); +- goto out; +- } +- } +- +- if (codec_dai->driver->ops->hw_params) { +- ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); +- if (ret < 0) { +- printk(KERN_ERR "asoc: can't set codec %s hw params\n", +- codec_dai->name); +- goto codec_err; +- } +- } +- +- if (cpu_dai->driver->ops->hw_params) { +- ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); +- if (ret < 0) { +- printk(KERN_ERR "asoc: interface %s hw params failed\n", +- cpu_dai->name); +- goto interface_err; +- } +- } +- +- if (platform->driver->ops && platform->driver->ops->hw_params) { +- ret = platform->driver->ops->hw_params(substream, params); +- if (ret < 0) { +- printk(KERN_ERR "asoc: platform %s hw params failed\n", +- platform->name); +- goto platform_err; +- } +- } +- +- rtd->rate = params_rate(params); +- +-out: +- mutex_unlock(&pcm_mutex); +- return ret; +- +-platform_err: +- if (cpu_dai->driver->ops->hw_free) +- cpu_dai->driver->ops->hw_free(substream, cpu_dai); +- +-interface_err: +- if (codec_dai->driver->ops->hw_free) +- codec_dai->driver->ops->hw_free(substream, codec_dai); +- +-codec_err: +- if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) +- rtd->dai_link->ops->hw_free(substream); +- +- mutex_unlock(&pcm_mutex); +- return ret; +-} +- +-/* +- * Frees resources allocated by hw_params, can be called multiple times +- */ +-static int soc_pcm_hw_free(struct snd_pcm_substream *substream) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct snd_soc_platform *platform = rtd->platform; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- struct snd_soc_dai *codec_dai = rtd->codec_dai; +- struct snd_soc_codec *codec = rtd->codec; +- +- mutex_lock(&pcm_mutex); +- +- /* apply codec digital mute */ +- if (!codec->active) +- snd_soc_dai_digital_mute(codec_dai, 1); +- +- /* free any machine hw params */ +- if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) +- rtd->dai_link->ops->hw_free(substream); +- +- /* free any DMA resources */ +- if (platform->driver->ops && platform->driver->ops->hw_free) +- platform->driver->ops->hw_free(substream); +- +- /* now free hw params for the DAIs */ +- if (codec_dai->driver->ops->hw_free) +- codec_dai->driver->ops->hw_free(substream, codec_dai); +- +- if (cpu_dai->driver->ops->hw_free) +- cpu_dai->driver->ops->hw_free(substream, cpu_dai); +- +- mutex_unlock(&pcm_mutex); +- return 0; +-} +- +-static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct snd_soc_platform *platform = rtd->platform; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- struct snd_soc_dai *codec_dai = rtd->codec_dai; +- int ret; +- +- if (codec_dai->driver->ops->trigger) { +- ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); +- if (ret < 0) +- return ret; +- } +- +- if (platform->driver->ops && platform->driver->ops->trigger) { +- ret = platform->driver->ops->trigger(substream, cmd); +- if (ret < 0) +- return ret; +- } +- +- if (cpu_dai->driver->ops->trigger) { +- ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); +- if (ret < 0) +- return ret; +- } +- return 0; +-} +- +-/* +- * soc level wrapper for pointer callback +- * If cpu_dai, codec_dai, platform driver has the delay callback, than +- * the runtime->delay will be updated accordingly. +- */ +-static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct snd_soc_platform *platform = rtd->platform; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- struct snd_soc_dai *codec_dai = rtd->codec_dai; +- struct snd_pcm_runtime *runtime = substream->runtime; +- snd_pcm_uframes_t offset = 0; +- snd_pcm_sframes_t delay = 0; +- +- if (platform->driver->ops && platform->driver->ops->pointer) +- offset = platform->driver->ops->pointer(substream); +- +- if (cpu_dai->driver->ops->delay) +- delay += cpu_dai->driver->ops->delay(substream, cpu_dai); +- +- if (codec_dai->driver->ops->delay) +- delay += codec_dai->driver->ops->delay(substream, codec_dai); +- +- if (platform->driver->delay) +- delay += platform->driver->delay(substream, codec_dai); +- +- runtime->delay = delay; +- +- return offset; +-} +- +-/* ASoC PCM operations */ +-static struct snd_pcm_ops soc_pcm_ops = { +- .open = soc_pcm_open, +- .close = soc_codec_close, +- .hw_params = soc_pcm_hw_params, +- .hw_free = soc_pcm_hw_free, +- .prepare = soc_pcm_prepare, +- .trigger = soc_pcm_trigger, +- .pointer = soc_pcm_pointer, +-}; +- + #ifdef CONFIG_PM_SLEEP + /* powers down audio subsystem for suspend */ + int snd_soc_suspend(struct device *dev) +@@ -1694,9 +1147,6 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) + if (order != SND_SOC_COMP_ORDER_LAST) + return 0; + +- /* DAPM dai link stream work */ +- INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); +- + ret = soc_post_component_init(card, codec, num, 0); + if (ret) + return ret; +@@ -2128,66 +1578,6 @@ static struct platform_driver soc_driver = { + .remove = soc_remove, + }; + +-/* create a new pcm */ +-static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) +-{ +- struct snd_soc_codec *codec = rtd->codec; +- struct snd_soc_platform *platform = rtd->platform; +- struct snd_soc_dai *codec_dai = rtd->codec_dai; +- struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +- struct snd_pcm *pcm; +- char new_name[64]; +- int ret = 0, playback = 0, capture = 0; +- +- /* check client and interface hw capabilities */ +- snprintf(new_name, sizeof(new_name), "%s %s-%d", +- rtd->dai_link->stream_name, codec_dai->name, num); +- +- if (codec_dai->driver->playback.channels_min) +- playback = 1; +- if (codec_dai->driver->capture.channels_min) +- capture = 1; +- +- dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name); +- ret = snd_pcm_new(rtd->card->snd_card, new_name, +- num, playback, capture, &pcm); +- if (ret < 0) { +- printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); +- return ret; +- } +- +- rtd->pcm = pcm; +- pcm->private_data = rtd; +- if (platform->driver->ops) { +- soc_pcm_ops.mmap = platform->driver->ops->mmap; +- soc_pcm_ops.pointer = platform->driver->ops->pointer; +- soc_pcm_ops.ioctl = platform->driver->ops->ioctl; +- soc_pcm_ops.copy = platform->driver->ops->copy; +- soc_pcm_ops.silence = platform->driver->ops->silence; +- soc_pcm_ops.ack = platform->driver->ops->ack; +- soc_pcm_ops.page = platform->driver->ops->page; +- } +- +- if (playback) +- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); +- +- if (capture) +- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); +- +- if (platform->driver->pcm_new) { +- ret = platform->driver->pcm_new(rtd); +- if (ret < 0) { +- pr_err("asoc: platform pcm constructor failed\n"); +- return ret; +- } +- } +- +- pcm->private_free = platform->driver->pcm_free; +- printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, +- cpu_dai->name); +- return ret; +-} +- + /** + * snd_soc_codec_volatile_register: Report if a register is volatile. + * +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +new file mode 100644 +index 0000000..9bebee8 +--- /dev/null ++++ b/sound/soc/soc-pcm.c +@@ -0,0 +1,639 @@ ++/* ++ * soc-pcm.c -- ALSA SoC PCM ++ * ++ * Copyright 2005 Wolfson Microelectronics PLC. ++ * Copyright 2005 Openedhand Ltd. ++ * Copyright (C) 2010 Slimlogic Ltd. ++ * Copyright (C) 2010 Texas Instruments Inc. ++ * ++ * Authors: Liam Girdwood <lrg@ti.com> ++ * Mark Brown <broonie@opensource.wolfsonmicro.com> ++ * ++ * 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/kernel.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/slab.h> ++#include <linux/workqueue.h> ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/soc.h> ++#include <sound/initval.h> ++ ++static DEFINE_MUTEX(pcm_mutex); ++ ++static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ int ret; ++ ++ if (!codec_dai->driver->symmetric_rates && ++ !cpu_dai->driver->symmetric_rates && ++ !rtd->dai_link->symmetric_rates) ++ return 0; ++ ++ /* This can happen if multiple streams are starting simultaneously - ++ * the second can need to get its constraints before the first has ++ * picked a rate. Complain and allow the application to carry on. ++ */ ++ if (!rtd->rate) { ++ dev_warn(&rtd->dev, ++ "Not enforcing symmetric_rates due to race\n"); ++ return 0; ++ } ++ ++ dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate); ++ ++ ret = snd_pcm_hw_constraint_minmax(substream->runtime, ++ SNDRV_PCM_HW_PARAM_RATE, ++ rtd->rate, rtd->rate); ++ if (ret < 0) { ++ dev_err(&rtd->dev, ++ "Unable to apply rate symmetry constraint: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Called by ALSA when a PCM substream is opened, the runtime->hw record is ++ * then initialized and any private data can be allocated. This also calls ++ * startup for the cpu DAI, platform, machine and codec DAI. ++ */ ++static int soc_pcm_open(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ struct snd_soc_platform *platform = rtd->platform; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; ++ struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; ++ int ret = 0; ++ ++ mutex_lock(&pcm_mutex); ++ ++ /* startup the audio subsystem */ ++ if (cpu_dai->driver->ops->startup) { ++ ret = cpu_dai->driver->ops->startup(substream, cpu_dai); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: can't open interface %s\n", ++ cpu_dai->name); ++ goto out; ++ } ++ } ++ ++ if (platform->driver->ops && platform->driver->ops->open) { ++ ret = platform->driver->ops->open(substream); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); ++ goto platform_err; ++ } ++ } ++ ++ if (codec_dai->driver->ops->startup) { ++ ret = codec_dai->driver->ops->startup(substream, codec_dai); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: can't open codec %s\n", ++ codec_dai->name); ++ goto codec_dai_err; ++ } ++ } ++ ++ if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { ++ ret = rtd->dai_link->ops->startup(substream); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name); ++ goto machine_err; ++ } ++ } ++ ++ /* Check that the codec and cpu DAIs are compatible */ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ runtime->hw.rate_min = ++ max(codec_dai_drv->playback.rate_min, ++ cpu_dai_drv->playback.rate_min); ++ runtime->hw.rate_max = ++ min(codec_dai_drv->playback.rate_max, ++ cpu_dai_drv->playback.rate_max); ++ runtime->hw.channels_min = ++ max(codec_dai_drv->playback.channels_min, ++ cpu_dai_drv->playback.channels_min); ++ runtime->hw.channels_max = ++ min(codec_dai_drv->playback.channels_max, ++ cpu_dai_drv->playback.channels_max); ++ runtime->hw.formats = ++ codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats; ++ runtime->hw.rates = ++ codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates; ++ if (codec_dai_drv->playback.rates ++ & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) ++ runtime->hw.rates |= cpu_dai_drv->playback.rates; ++ if (cpu_dai_drv->playback.rates ++ & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) ++ runtime->hw.rates |= codec_dai_drv->playback.rates; ++ } else { ++ runtime->hw.rate_min = ++ max(codec_dai_drv->capture.rate_min, ++ cpu_dai_drv->capture.rate_min); ++ runtime->hw.rate_max = ++ min(codec_dai_drv->capture.rate_max, ++ cpu_dai_drv->capture.rate_max); ++ runtime->hw.channels_min = ++ max(codec_dai_drv->capture.channels_min, ++ cpu_dai_drv->capture.channels_min); ++ runtime->hw.channels_max = ++ min(codec_dai_drv->capture.channels_max, ++ cpu_dai_drv->capture.channels_max); ++ runtime->hw.formats = ++ codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats; ++ runtime->hw.rates = ++ codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates; ++ if (codec_dai_drv->capture.rates ++ & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) ++ runtime->hw.rates |= cpu_dai_drv->capture.rates; ++ if (cpu_dai_drv->capture.rates ++ & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) ++ runtime->hw.rates |= codec_dai_drv->capture.rates; ++ } ++ ++ ret = -EINVAL; ++ snd_pcm_limit_hw_rates(runtime); ++ if (!runtime->hw.rates) { ++ printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", ++ codec_dai->name, cpu_dai->name); ++ goto config_err; ++ } ++ if (!runtime->hw.formats) { ++ printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", ++ codec_dai->name, cpu_dai->name); ++ goto config_err; ++ } ++ if (!runtime->hw.channels_min || !runtime->hw.channels_max || ++ runtime->hw.channels_min > runtime->hw.channels_max) { ++ printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", ++ codec_dai->name, cpu_dai->name); ++ goto config_err; ++ } ++ ++ /* Symmetry only applies if we've already got an active stream. */ ++ if (cpu_dai->active || codec_dai->active) { ++ ret = soc_pcm_apply_symmetry(substream); ++ if (ret != 0) ++ goto config_err; ++ } ++ ++ pr_debug("asoc: %s <-> %s info:\n", ++ codec_dai->name, cpu_dai->name); ++ pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); ++ pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, ++ runtime->hw.channels_max); ++ pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, ++ runtime->hw.rate_max); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ cpu_dai->playback_active++; ++ codec_dai->playback_active++; ++ } else { ++ cpu_dai->capture_active++; ++ codec_dai->capture_active++; ++ } ++ cpu_dai->active++; ++ codec_dai->active++; ++ rtd->codec->active++; ++ mutex_unlock(&pcm_mutex); ++ return 0; ++ ++config_err: ++ if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) ++ rtd->dai_link->ops->shutdown(substream); ++ ++machine_err: ++ if (codec_dai->driver->ops->shutdown) ++ codec_dai->driver->ops->shutdown(substream, codec_dai); ++ ++codec_dai_err: ++ if (platform->driver->ops && platform->driver->ops->close) ++ platform->driver->ops->close(substream); ++ ++platform_err: ++ if (cpu_dai->driver->ops->shutdown) ++ cpu_dai->driver->ops->shutdown(substream, cpu_dai); ++out: ++ mutex_unlock(&pcm_mutex); ++ return ret; ++} ++ ++/* ++ * Power down the audio subsystem pmdown_time msecs after close is called. ++ * This is to ensure there are no pops or clicks in between any music tracks ++ * due to DAPM power cycling. ++ */ ++static void close_delayed_work(struct work_struct *work) ++{ ++ struct snd_soc_pcm_runtime *rtd = ++ container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ ++ mutex_lock(&pcm_mutex); ++ ++ pr_debug("pop wq checking: %s status: %s waiting: %s\n", ++ codec_dai->driver->playback.stream_name, ++ codec_dai->playback_active ? "active" : "inactive", ++ codec_dai->pop_wait ? "yes" : "no"); ++ ++ /* are we waiting on this codec DAI stream */ ++ if (codec_dai->pop_wait == 1) { ++ codec_dai->pop_wait = 0; ++ snd_soc_dapm_stream_event(rtd, ++ codec_dai->driver->playback.stream_name, ++ SND_SOC_DAPM_STREAM_STOP); ++ } ++ ++ mutex_unlock(&pcm_mutex); ++} ++ ++/* ++ * Called by ALSA when a PCM substream is closed. Private data can be ++ * freed here. The cpu DAI, codec DAI, machine and platform are also ++ * shutdown. ++ */ ++static int soc_codec_close(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_platform *platform = rtd->platform; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ mutex_lock(&pcm_mutex); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ cpu_dai->playback_active--; ++ codec_dai->playback_active--; ++ } else { ++ cpu_dai->capture_active--; ++ codec_dai->capture_active--; ++ } ++ ++ cpu_dai->active--; ++ codec_dai->active--; ++ codec->active--; ++ ++ /* Muting the DAC suppresses artifacts caused during digital ++ * shutdown, for example from stopping clocks. ++ */ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ snd_soc_dai_digital_mute(codec_dai, 1); ++ ++ if (cpu_dai->driver->ops->shutdown) ++ cpu_dai->driver->ops->shutdown(substream, cpu_dai); ++ ++ if (codec_dai->driver->ops->shutdown) ++ codec_dai->driver->ops->shutdown(substream, codec_dai); ++ ++ if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) ++ rtd->dai_link->ops->shutdown(substream); ++ ++ if (platform->driver->ops && platform->driver->ops->close) ++ platform->driver->ops->close(substream); ++ cpu_dai->runtime = NULL; ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ /* start delayed pop wq here for playback streams */ ++ codec_dai->pop_wait = 1; ++ schedule_delayed_work(&rtd->delayed_work, ++ msecs_to_jiffies(rtd->pmdown_time)); ++ } else { ++ /* capture streams can be powered down now */ ++ snd_soc_dapm_stream_event(rtd, ++ codec_dai->driver->capture.stream_name, ++ SND_SOC_DAPM_STREAM_STOP); ++ } ++ ++ mutex_unlock(&pcm_mutex); ++ return 0; ++} ++ ++/* ++ * Called by ALSA when the PCM substream is prepared, can set format, sample ++ * rate, etc. This function is non atomic and can be called multiple times, ++ * it can refer to the runtime info. ++ */ ++static int soc_pcm_prepare(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_platform *platform = rtd->platform; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ int ret = 0; ++ ++ mutex_lock(&pcm_mutex); ++ ++ if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { ++ ret = rtd->dai_link->ops->prepare(substream); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: machine prepare error\n"); ++ goto out; ++ } ++ } ++ ++ if (platform->driver->ops && platform->driver->ops->prepare) { ++ ret = platform->driver->ops->prepare(substream); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: platform prepare error\n"); ++ goto out; ++ } ++ } ++ ++ if (codec_dai->driver->ops->prepare) { ++ ret = codec_dai->driver->ops->prepare(substream, codec_dai); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: codec DAI prepare error\n"); ++ goto out; ++ } ++ } ++ ++ if (cpu_dai->driver->ops->prepare) { ++ ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: cpu DAI prepare error\n"); ++ goto out; ++ } ++ } ++ ++ /* cancel any delayed stream shutdown that is pending */ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && ++ codec_dai->pop_wait) { ++ codec_dai->pop_wait = 0; ++ cancel_delayed_work(&rtd->delayed_work); ++ } ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ snd_soc_dapm_stream_event(rtd, ++ codec_dai->driver->playback.stream_name, ++ SND_SOC_DAPM_STREAM_START); ++ else ++ snd_soc_dapm_stream_event(rtd, ++ codec_dai->driver->capture.stream_name, ++ SND_SOC_DAPM_STREAM_START); ++ ++ snd_soc_dai_digital_mute(codec_dai, 0); ++ ++out: ++ mutex_unlock(&pcm_mutex); ++ return ret; ++} ++ ++/* ++ * Called by ALSA when the hardware params are set by application. This ++ * function can also be called multiple times and can allocate buffers ++ * (using snd_pcm_lib_* ). It's non-atomic. ++ */ ++static int soc_pcm_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_platform *platform = rtd->platform; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ int ret = 0; ++ ++ mutex_lock(&pcm_mutex); ++ ++ if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { ++ ret = rtd->dai_link->ops->hw_params(substream, params); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: machine hw_params failed\n"); ++ goto out; ++ } ++ } ++ ++ if (codec_dai->driver->ops->hw_params) { ++ ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: can't set codec %s hw params\n", ++ codec_dai->name); ++ goto codec_err; ++ } ++ } ++ ++ if (cpu_dai->driver->ops->hw_params) { ++ ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: interface %s hw params failed\n", ++ cpu_dai->name); ++ goto interface_err; ++ } ++ } ++ ++ if (platform->driver->ops && platform->driver->ops->hw_params) { ++ ret = platform->driver->ops->hw_params(substream, params); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: platform %s hw params failed\n", ++ platform->name); ++ goto platform_err; ++ } ++ } ++ ++ rtd->rate = params_rate(params); ++ ++out: ++ mutex_unlock(&pcm_mutex); ++ return ret; ++ ++platform_err: ++ if (cpu_dai->driver->ops->hw_free) ++ cpu_dai->driver->ops->hw_free(substream, cpu_dai); ++ ++interface_err: ++ if (codec_dai->driver->ops->hw_free) ++ codec_dai->driver->ops->hw_free(substream, codec_dai); ++ ++codec_err: ++ if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) ++ rtd->dai_link->ops->hw_free(substream); ++ ++ mutex_unlock(&pcm_mutex); ++ return ret; ++} ++ ++/* ++ * Frees resources allocated by hw_params, can be called multiple times ++ */ ++static int soc_pcm_hw_free(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_platform *platform = rtd->platform; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ mutex_lock(&pcm_mutex); ++ ++ /* apply codec digital mute */ ++ if (!codec->active) ++ snd_soc_dai_digital_mute(codec_dai, 1); ++ ++ /* free any machine hw params */ ++ if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) ++ rtd->dai_link->ops->hw_free(substream); ++ ++ /* free any DMA resources */ ++ if (platform->driver->ops && platform->driver->ops->hw_free) ++ platform->driver->ops->hw_free(substream); ++ ++ /* now free hw params for the DAIs */ ++ if (codec_dai->driver->ops->hw_free) ++ codec_dai->driver->ops->hw_free(substream, codec_dai); ++ ++ if (cpu_dai->driver->ops->hw_free) ++ cpu_dai->driver->ops->hw_free(substream, cpu_dai); ++ ++ mutex_unlock(&pcm_mutex); ++ return 0; ++} ++ ++static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_platform *platform = rtd->platform; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ int ret; ++ ++ if (codec_dai->driver->ops->trigger) { ++ ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (platform->driver->ops && platform->driver->ops->trigger) { ++ ret = platform->driver->ops->trigger(substream, cmd); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (cpu_dai->driver->ops->trigger) { ++ ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); ++ if (ret < 0) ++ return ret; ++ } ++ return 0; ++} ++ ++/* ++ * soc level wrapper for pointer callback ++ * If cpu_dai, codec_dai, platform driver has the delay callback, than ++ * the runtime->delay will be updated accordingly. ++ */ ++static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_platform *platform = rtd->platform; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ snd_pcm_uframes_t offset = 0; ++ snd_pcm_sframes_t delay = 0; ++ ++ if (platform->driver->ops && platform->driver->ops->pointer) ++ offset = platform->driver->ops->pointer(substream); ++ ++ if (cpu_dai->driver->ops->delay) ++ delay += cpu_dai->driver->ops->delay(substream, cpu_dai); ++ ++ if (codec_dai->driver->ops->delay) ++ delay += codec_dai->driver->ops->delay(substream, codec_dai); ++ ++ if (platform->driver->delay) ++ delay += platform->driver->delay(substream, codec_dai); ++ ++ runtime->delay = delay; ++ ++ return offset; ++} ++ ++/* ASoC PCM operations */ ++static struct snd_pcm_ops soc_pcm_ops = { ++ .open = soc_pcm_open, ++ .close = soc_codec_close, ++ .hw_params = soc_pcm_hw_params, ++ .hw_free = soc_pcm_hw_free, ++ .prepare = soc_pcm_prepare, ++ .trigger = soc_pcm_trigger, ++ .pointer = soc_pcm_pointer, ++}; ++ ++/* create a new pcm */ ++int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_platform *platform = rtd->platform; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_pcm *pcm; ++ char new_name[64]; ++ int ret = 0, playback = 0, capture = 0; ++ ++ /* check client and interface hw capabilities */ ++ snprintf(new_name, sizeof(new_name), "%s %s-%d", ++ rtd->dai_link->stream_name, codec_dai->name, num); ++ ++ if (codec_dai->driver->playback.channels_min) ++ playback = 1; ++ if (codec_dai->driver->capture.channels_min) ++ capture = 1; ++ ++ dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name); ++ ret = snd_pcm_new(rtd->card->snd_card, new_name, ++ num, playback, capture, &pcm); ++ if (ret < 0) { ++ printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); ++ return ret; ++ } ++ ++ /* DAPM dai link stream work */ ++ INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); ++ ++ rtd->pcm = pcm; ++ pcm->private_data = rtd; ++ if (platform->driver->ops) { ++ soc_pcm_ops.mmap = platform->driver->ops->mmap; ++ soc_pcm_ops.pointer = platform->driver->ops->pointer; ++ soc_pcm_ops.ioctl = platform->driver->ops->ioctl; ++ soc_pcm_ops.copy = platform->driver->ops->copy; ++ soc_pcm_ops.silence = platform->driver->ops->silence; ++ soc_pcm_ops.ack = platform->driver->ops->ack; ++ soc_pcm_ops.page = platform->driver->ops->page; ++ } ++ ++ if (playback) ++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); ++ ++ if (capture) ++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); ++ ++ if (platform->driver->pcm_new) { ++ ret = platform->driver->pcm_new(rtd); ++ if (ret < 0) { ++ pr_err("asoc: platform pcm constructor failed\n"); ++ return ret; ++ } ++ } ++ ++ pcm->private_free = platform->driver->pcm_free; ++ printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, ++ cpu_dai->name); ++ return ret; ++} +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0077-ASoC-core-PCM-mutex-per-rtd.patch b/patches.kzm9g/0077-ASoC-core-PCM-mutex-per-rtd.patch new file mode 100644 index 00000000000000..2f91a0f4b76221 --- /dev/null +++ b/patches.kzm9g/0077-ASoC-core-PCM-mutex-per-rtd.patch @@ -0,0 +1,203 @@ +From 7c74178e9fd0dbf8b3e823a1fea0a0f4ab907afe Mon Sep 17 00:00:00 2001 +From: Liam Girdwood <lrg@ti.com> +Date: Thu, 9 Jun 2011 17:04:39 +0100 +Subject: ASoC: core - PCM mutex per rtd + +In preparation for the new ASoC Dynamic PCM support (AKA DSP support). + +The new ASoC Dynamic PCM core allows DAIs to be dynamically re-routed +at runtime between the PCM device end (or Frontend - FE) and the physical DAI +(Backend - BE) using regular kcontrols (just like a hardware CODEC routes +audio in the analog domain). The Dynamic PCM core therefore must be +able to call PCM operations for both the Frontend and Backend(s) DAIs at +the same time. + +Currently we have a global pcm_mutex that is used to serialise +the ASoC PCM operations. This patch removes the global mutex +and adds a mutex per RTD allowing the PCM operations to be reentrant and +allow control of more than one DAI at at time. e.g. a frontend PCM hw_params() +could configure multiple backend DAI hw_params() with similar or different +hw parameters at the same time. + +Signed-off-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit b8c0dab9bf3373010e857a8d3f1b594c60a348dd) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/sound/soc.h | 8 ++++++++ + sound/soc/soc-core.c | 1 + + sound/soc/soc-pcm.c | 28 ++++++++++++++-------------- + 3 files changed, 23 insertions(+), 14 deletions(-) + +diff --git a/include/sound/soc.h b/include/sound/soc.h +index 447232c..9e6d13e 100644 +--- a/include/sound/soc.h ++++ b/include/sound/soc.h +@@ -268,6 +268,11 @@ enum snd_soc_compress_type { + SND_SOC_RBTREE_COMPRESSION + }; + ++enum snd_soc_pcm_subclass { ++ SND_SOC_PCM_CLASS_PCM = 0, ++ SND_SOC_PCM_CLASS_BE = 1, ++}; ++ + int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, + unsigned int freq, int dir); + int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, +@@ -806,6 +811,9 @@ struct snd_soc_pcm_runtime { + struct device dev; + struct snd_soc_card *card; + struct snd_soc_dai_link *dai_link; ++ struct mutex pcm_mutex; ++ enum snd_soc_pcm_subclass pcm_subclass; ++ struct snd_pcm_ops ops; + + unsigned int complete:1; + unsigned int dev_registered:1; +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index f5ec7d8..71cf27f 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -1034,6 +1034,7 @@ static int soc_post_component_init(struct snd_soc_card *card, + rtd->dev.parent = card->dev; + rtd->dev.release = rtd_release; + rtd->dev.init_name = name; ++ mutex_init(&rtd->pcm_mutex); + ret = device_register(&rtd->dev); + if (ret < 0) { + dev_err(card->dev, +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index 9bebee8..f4864b0 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -81,7 +81,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) + struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; + int ret = 0; + +- mutex_lock(&pcm_mutex); ++ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + + /* startup the audio subsystem */ + if (cpu_dai->driver->ops->startup) { +@@ -211,7 +211,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) + cpu_dai->active++; + codec_dai->active++; + rtd->codec->active++; +- mutex_unlock(&pcm_mutex); ++ mutex_unlock(&rtd->pcm_mutex); + return 0; + + config_err: +@@ -230,7 +230,7 @@ platform_err: + if (cpu_dai->driver->ops->shutdown) + cpu_dai->driver->ops->shutdown(substream, cpu_dai); + out: +- mutex_unlock(&pcm_mutex); ++ mutex_unlock(&rtd->pcm_mutex); + return ret; + } + +@@ -245,7 +245,7 @@ static void close_delayed_work(struct work_struct *work) + container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); + struct snd_soc_dai *codec_dai = rtd->codec_dai; + +- mutex_lock(&pcm_mutex); ++ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + + pr_debug("pop wq checking: %s status: %s waiting: %s\n", + codec_dai->driver->playback.stream_name, +@@ -260,7 +260,7 @@ static void close_delayed_work(struct work_struct *work) + SND_SOC_DAPM_STREAM_STOP); + } + +- mutex_unlock(&pcm_mutex); ++ mutex_unlock(&rtd->pcm_mutex); + } + + /* +@@ -276,7 +276,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = rtd->codec; + +- mutex_lock(&pcm_mutex); ++ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + cpu_dai->playback_active--; +@@ -321,7 +321,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) + SND_SOC_DAPM_STREAM_STOP); + } + +- mutex_unlock(&pcm_mutex); ++ mutex_unlock(&rtd->pcm_mutex); + return 0; + } + +@@ -338,7 +338,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret = 0; + +- mutex_lock(&pcm_mutex); ++ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + + if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { + ret = rtd->dai_link->ops->prepare(substream); +@@ -391,7 +391,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) + snd_soc_dai_digital_mute(codec_dai, 0); + + out: +- mutex_unlock(&pcm_mutex); ++ mutex_unlock(&rtd->pcm_mutex); + return ret; + } + +@@ -409,7 +409,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret = 0; + +- mutex_lock(&pcm_mutex); ++ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + + if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { + ret = rtd->dai_link->ops->hw_params(substream, params); +@@ -449,7 +449,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, + rtd->rate = params_rate(params); + + out: +- mutex_unlock(&pcm_mutex); ++ mutex_unlock(&rtd->pcm_mutex); + return ret; + + platform_err: +@@ -464,7 +464,7 @@ codec_err: + if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) + rtd->dai_link->ops->hw_free(substream); + +- mutex_unlock(&pcm_mutex); ++ mutex_unlock(&rtd->pcm_mutex); + return ret; + } + +@@ -479,7 +479,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = rtd->codec; + +- mutex_lock(&pcm_mutex); ++ mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + + /* apply codec digital mute */ + if (!codec->active) +@@ -500,7 +500,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) + if (cpu_dai->driver->ops->hw_free) + cpu_dai->driver->ops->hw_free(substream, cpu_dai); + +- mutex_unlock(&pcm_mutex); ++ mutex_unlock(&rtd->pcm_mutex); + return 0; + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0078-ASoC-Allow-DAI-formats-to-be-specified-in-the-dai_li.patch b/patches.kzm9g/0078-ASoC-Allow-DAI-formats-to-be-specified-in-the-dai_li.patch new file mode 100644 index 00000000000000..6bf720a1e7e90b --- /dev/null +++ b/patches.kzm9g/0078-ASoC-Allow-DAI-formats-to-be-specified-in-the-dai_li.patch @@ -0,0 +1,148 @@ +From 8e48ac5598f4d6425d2b703b87a3d51a7a546ba4 Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@opensource.wolfsonmicro.com> +Date: Tue, 27 Sep 2011 16:41:01 +0100 +Subject: ASoC: Allow DAI formats to be specified in the dai_link + +For almost all machines the DAI format is a constant, always set to the +same thing. This means that not only should we normally set it on init +rather than in hw_params() (where it has been for historical reasons) we +should also allow users to configure this by setting a variable in the +dai_link structure. The combination of these two will make many machine +drivers even more data driven. + +Implement a new dai_fmt field in the dai_link doing just that. Since 0 is +a valid value for many format flags and we need to be able to tell if the +field is actually set also add one to all the values used to configure +formats. + +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 75d9ac46b99280f5f381927ae75a9eaf21844d20) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/sound/soc-dai.h | 34 +++++++++++++++++----------------- + include/sound/soc.h | 2 ++ + sound/soc/soc-core.c | 21 +++++++++++++++++++++ + 3 files changed, 40 insertions(+), 17 deletions(-) + +diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h +index 5ad5f3a..5d56a06 100644 +--- a/include/sound/soc-dai.h ++++ b/include/sound/soc-dai.h +@@ -24,13 +24,13 @@ struct snd_pcm_substream; + * Describes the physical PCM data formating and clocking. Add new formats + * to the end. + */ +-#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */ +-#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right Justified mode */ +-#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */ +-#define SND_SOC_DAIFMT_DSP_A 3 /* L data MSB after FRM LRC */ +-#define SND_SOC_DAIFMT_DSP_B 4 /* L data MSB during FRM LRC */ +-#define SND_SOC_DAIFMT_AC97 5 /* AC97 */ +-#define SND_SOC_DAIFMT_PDM 6 /* Pulse density modulation */ ++#define SND_SOC_DAIFMT_I2S 1 /* I2S mode */ ++#define SND_SOC_DAIFMT_RIGHT_J 2 /* Right Justified mode */ ++#define SND_SOC_DAIFMT_LEFT_J 3 /* Left Justified mode */ ++#define SND_SOC_DAIFMT_DSP_A 4 /* L data MSB after FRM LRC */ ++#define SND_SOC_DAIFMT_DSP_B 5 /* L data MSB during FRM LRC */ ++#define SND_SOC_DAIFMT_AC97 6 /* AC97 */ ++#define SND_SOC_DAIFMT_PDM 7 /* Pulse density modulation */ + + /* left and right justified also known as MSB and LSB respectively */ + #define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J +@@ -42,8 +42,8 @@ struct snd_pcm_substream; + * DAI bit clocks can be be gated (disabled) when the DAI is not + * sending or receiving PCM data in a frame. This can be used to save power. + */ +-#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */ +-#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated */ ++#define SND_SOC_DAIFMT_CONT (1 << 4) /* continuous clock */ ++#define SND_SOC_DAIFMT_GATED (2 << 4) /* clock is gated */ + + /* + * DAI hardware signal inversions. +@@ -51,10 +51,10 @@ struct snd_pcm_substream; + * Specifies whether the DAI can also support inverted clocks for the specified + * format. + */ +-#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */ +-#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal BCLK + inv FRM */ +-#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert BCLK + nor FRM */ +-#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert BCLK + FRM */ ++#define SND_SOC_DAIFMT_NB_NF (1 << 8) /* normal bit clock + frame */ ++#define SND_SOC_DAIFMT_NB_IF (2 << 8) /* normal BCLK + inv FRM */ ++#define SND_SOC_DAIFMT_IB_NF (3 << 8) /* invert BCLK + nor FRM */ ++#define SND_SOC_DAIFMT_IB_IF (4 << 8) /* invert BCLK + FRM */ + + /* + * DAI hardware clock masters. +@@ -63,10 +63,10 @@ struct snd_pcm_substream; + * i.e. if the codec is clk and FRM master then the interface is + * clk and frame slave. + */ +-#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & FRM master */ +-#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & FRM master */ +-#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */ +-#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & FRM slave */ ++#define SND_SOC_DAIFMT_CBM_CFM (1 << 12) /* codec clk & FRM master */ ++#define SND_SOC_DAIFMT_CBS_CFM (2 << 12) /* codec clk slave & FRM master */ ++#define SND_SOC_DAIFMT_CBM_CFS (3 << 12) /* codec clk master & frame slave */ ++#define SND_SOC_DAIFMT_CBS_CFS (4 << 12) /* codec clk & FRM slave */ + + #define SND_SOC_DAIFMT_FORMAT_MASK 0x000f + #define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 +diff --git a/include/sound/soc.h b/include/sound/soc.h +index 9e6d13e..811474e 100644 +--- a/include/sound/soc.h ++++ b/include/sound/soc.h +@@ -683,6 +683,8 @@ struct snd_soc_dai_link { + const char *cpu_dai_name; + const char *codec_dai_name; + ++ unsigned int dai_fmt; /* format to set on init */ ++ + /* Keep DAI active over suspend */ + unsigned int ignore_suspend:1; + +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index 71cf27f..11a889c 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -1285,6 +1285,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) + struct snd_soc_codec *codec; + struct snd_soc_codec_conf *codec_conf; + enum snd_soc_compress_type compress_type; ++ struct snd_soc_dai_link *dai_link; + int ret, i, order; + + mutex_lock(&card->mutex); +@@ -1397,6 +1398,26 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) + snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, + card->num_dapm_routes); + ++ for (i = 0; i < card->num_links; i++) { ++ dai_link = &card->dai_link[i]; ++ ++ if (dai_link->dai_fmt) { ++ ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai, ++ dai_link->dai_fmt); ++ if (ret != 0) ++ dev_warn(card->rtd[i].codec_dai->dev, ++ "Failed to set DAI format: %d\n", ++ ret); ++ ++ ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai, ++ dai_link->dai_fmt); ++ if (ret != 0) ++ dev_warn(card->rtd[i].cpu_dai->dev, ++ "Failed to set DAI format: %d\n", ++ ret); ++ } ++ } ++ + snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), + "%s", card->name); + snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0079-ASoC-Hold-runtime-PM-references-to-components-of-act.patch b/patches.kzm9g/0079-ASoC-Hold-runtime-PM-references-to-components-of-act.patch new file mode 100644 index 00000000000000..5f75399fc1f070 --- /dev/null +++ b/patches.kzm9g/0079-ASoC-Hold-runtime-PM-references-to-components-of-act.patch @@ -0,0 +1,78 @@ +From a34733d7e91c1defeb73b851cb78e76db67a5e48 Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@opensource.wolfsonmicro.com> +Date: Sat, 3 Dec 2011 20:14:31 +0000 +Subject: ASoC: Hold runtime PM references to components of active DAIs + +Every device that implements runtime power management for DAIs is doing +it in pretty much the same way: in the startup callback they take a +runtime PM reference and then in the shutdown callback they release that +reference, keeping the device active while the DAI is active. Given the +frequency with which this is done and the obviousness of the need to keep +the device active in this period factor the code out into the core, taking +references on the device for each CPU DAI, CODEC DAI and DMA device in the +core. + +As runtime PM is reference counted this shouldn't interfere with any +other reference holding by the drivers, and since (in common with the +existing implementations) we don't check for errors on enabling it +shouldn't matter if the device actually has runtime PM enabled or not. + +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Tested-by: Peter Ujfalusi <peter.ujfalusi@ti.com> +(cherry picked from commit d6652ef8229e9953543f41d8e081c23e653f0044) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/soc-pcm.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index f4864b0..3047db8 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -19,6 +19,7 @@ + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/delay.h> ++#include <linux/pm_runtime.h> + #include <linux/slab.h> + #include <linux/workqueue.h> + #include <sound/core.h> +@@ -81,6 +82,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) + struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; + int ret = 0; + ++ pm_runtime_get_sync(cpu_dai->dev); ++ pm_runtime_get_sync(codec_dai->dev); ++ pm_runtime_get_sync(platform->dev); ++ + mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + + /* startup the audio subsystem */ +@@ -231,6 +236,11 @@ platform_err: + cpu_dai->driver->ops->shutdown(substream, cpu_dai); + out: + mutex_unlock(&rtd->pcm_mutex); ++ ++ pm_runtime_put(platform->dev); ++ pm_runtime_put(codec_dai->dev); ++ pm_runtime_put(cpu_dai->dev); ++ + return ret; + } + +@@ -322,6 +332,11 @@ static int soc_codec_close(struct snd_pcm_substream *substream) + } + + mutex_unlock(&rtd->pcm_mutex); ++ ++ pm_runtime_put(platform->dev); ++ pm_runtime_put(codec_dai->dev); ++ pm_runtime_put(cpu_dai->dev); ++ + return 0; + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0080-ASoC-sh-fsi-tidyup-parameter-of-fsi_stream_push.patch b/patches.kzm9g/0080-ASoC-sh-fsi-tidyup-parameter-of-fsi_stream_push.patch new file mode 100644 index 00000000000000..6da2adc2603c4c --- /dev/null +++ b/patches.kzm9g/0080-ASoC-sh-fsi-tidyup-parameter-of-fsi_stream_push.patch @@ -0,0 +1,64 @@ +From 239b4f1f31ed777afdb5bc02f968e831232f856b Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 May 2011 20:45:57 +0900 +Subject: ASoC: sh: fsi: tidyup parameter of fsi_stream_push + +It is possible to create buff_len and period_len +from substream->runtime. +This patch is preparation of tidyup unclear variable naming patch. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 0ffe296addcfb8414ebad3d399859f9bf8f955d2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 14 +++++--------- + 1 file changed, 5 insertions(+), 9 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 339a1df..9666a26 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -344,16 +344,15 @@ static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) + + static void fsi_stream_push(struct fsi_priv *fsi, + int is_play, +- struct snd_pcm_substream *substream, +- u32 buffer_len, +- u32 period_len) ++ struct snd_pcm_substream *substream) + { + struct fsi_stream *io = fsi_get_stream(fsi, is_play); ++ struct snd_pcm_runtime *runtime = substream->runtime; + + io->substream = substream; +- io->buff_len = buffer_len; ++ io->buff_len = frames_to_bytes(runtime, runtime->buffer_size); + io->buff_offset = 0; +- io->period_len = period_len; ++ io->period_len = frames_to_bytes(runtime, runtime->period_size); + io->period_num = 0; + io->oerr_num = -1; /* ignore 1st err */ + io->uerr_num = -1; /* ignore 1st err */ +@@ -844,15 +843,12 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) + { + struct fsi_priv *fsi = fsi_get_priv(substream); +- struct snd_pcm_runtime *runtime = substream->runtime; + int is_play = fsi_is_play(substream); + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: +- fsi_stream_push(fsi, is_play, substream, +- frames_to_bytes(runtime, runtime->buffer_size), +- frames_to_bytes(runtime, runtime->period_size)); ++ fsi_stream_push(fsi, is_play, substream); + ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); + fsi_irq_enable(fsi, is_play); + fsi_port_start(fsi); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0081-ASoC-sh-fsi-add-fsi_set_master_clk.patch b/patches.kzm9g/0081-ASoC-sh-fsi-add-fsi_set_master_clk.patch new file mode 100644 index 00000000000000..51db7c0ddad5e8 --- /dev/null +++ b/patches.kzm9g/0081-ASoC-sh-fsi-add-fsi_set_master_clk.patch @@ -0,0 +1,273 @@ +From 6bddd5bd7705307cc504b2929d66939103b1d401 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 May 2011 20:46:18 +0900 +Subject: ASoC: sh: fsi: add fsi_set_master_clk + +Current FSI driver is using set_rate call back function which is for +master mode. +By this patch, it is used from fsi_set_master_clk. +This patch is preparation of cleanup suspend/resume patch. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 4f56cde17e3373219b56d2e9a91dbcd0ad228af7) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 164 ++++++++++++++++++++++++++++------------------------- + 1 file changed, 87 insertions(+), 77 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 9666a26..78a1631 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -558,6 +558,82 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) + /* + * clock function + */ ++static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, ++ long rate, int enable) ++{ ++ struct fsi_master *master = fsi_get_master(fsi); ++ set_rate_func set_rate = fsi_get_info_set_rate(master); ++ int fsi_ver = master->core->ver; ++ int ret; ++ ++ ret = set_rate(dev, fsi_is_port_a(fsi), rate, enable); ++ if (ret < 0) /* error */ ++ return ret; ++ ++ if (!enable) ++ return 0; ++ ++ if (ret > 0) { ++ u32 data = 0; ++ ++ switch (ret & SH_FSI_ACKMD_MASK) { ++ default: ++ /* FALL THROUGH */ ++ case SH_FSI_ACKMD_512: ++ data |= (0x0 << 12); ++ break; ++ case SH_FSI_ACKMD_256: ++ data |= (0x1 << 12); ++ break; ++ case SH_FSI_ACKMD_128: ++ data |= (0x2 << 12); ++ break; ++ case SH_FSI_ACKMD_64: ++ data |= (0x3 << 12); ++ break; ++ case SH_FSI_ACKMD_32: ++ if (fsi_ver < 2) ++ dev_err(dev, "unsupported ACKMD\n"); ++ else ++ data |= (0x4 << 12); ++ break; ++ } ++ ++ switch (ret & SH_FSI_BPFMD_MASK) { ++ default: ++ /* FALL THROUGH */ ++ case SH_FSI_BPFMD_32: ++ data |= (0x0 << 8); ++ break; ++ case SH_FSI_BPFMD_64: ++ data |= (0x1 << 8); ++ break; ++ case SH_FSI_BPFMD_128: ++ data |= (0x2 << 8); ++ break; ++ case SH_FSI_BPFMD_256: ++ data |= (0x3 << 8); ++ break; ++ case SH_FSI_BPFMD_512: ++ data |= (0x4 << 8); ++ break; ++ case SH_FSI_BPFMD_16: ++ if (fsi_ver < 2) ++ dev_err(dev, "unsupported ACKMD\n"); ++ else ++ data |= (0x7 << 8); ++ break; ++ } ++ ++ fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); ++ udelay(10); ++ ret = 0; ++ } ++ ++ return ret; ++ ++} ++ + #define fsi_module_init(m, d) __fsi_module_clk_ctrl(m, d, 1) + #define fsi_module_kill(m, d) __fsi_module_clk_ctrl(m, d, 0) + static void __fsi_module_clk_ctrl(struct fsi_master *master, +@@ -826,13 +902,11 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, + { + struct fsi_priv *fsi = fsi_get_priv(substream); + int is_play = fsi_is_play(substream); +- struct fsi_master *master = fsi_get_master(fsi); +- set_rate_func set_rate = fsi_get_info_set_rate(master); + + fsi_irq_disable(fsi, is_play); + + if (fsi_is_clk_master(fsi)) +- set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); ++ fsi_set_master_clk(dai->dev, fsi, fsi->rate, 0); + + fsi->rate = 0; + +@@ -960,79 +1034,19 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { + struct fsi_priv *fsi = fsi_get_priv(substream); +- struct fsi_master *master = fsi_get_master(fsi); +- set_rate_func set_rate = fsi_get_info_set_rate(master); +- int fsi_ver = master->core->ver; + long rate = params_rate(params); + int ret; + + if (!fsi_is_clk_master(fsi)) + return 0; + +- ret = set_rate(dai->dev, fsi_is_port_a(fsi), rate, 1); +- if (ret < 0) /* error */ ++ ret = fsi_set_master_clk(dai->dev, fsi, rate, 1); ++ if (ret < 0) + return ret; + + fsi->rate = rate; +- if (ret > 0) { +- u32 data = 0; +- +- switch (ret & SH_FSI_ACKMD_MASK) { +- default: +- /* FALL THROUGH */ +- case SH_FSI_ACKMD_512: +- data |= (0x0 << 12); +- break; +- case SH_FSI_ACKMD_256: +- data |= (0x1 << 12); +- break; +- case SH_FSI_ACKMD_128: +- data |= (0x2 << 12); +- break; +- case SH_FSI_ACKMD_64: +- data |= (0x3 << 12); +- break; +- case SH_FSI_ACKMD_32: +- if (fsi_ver < 2) +- dev_err(dai->dev, "unsupported ACKMD\n"); +- else +- data |= (0x4 << 12); +- break; +- } +- +- switch (ret & SH_FSI_BPFMD_MASK) { +- default: +- /* FALL THROUGH */ +- case SH_FSI_BPFMD_32: +- data |= (0x0 << 8); +- break; +- case SH_FSI_BPFMD_64: +- data |= (0x1 << 8); +- break; +- case SH_FSI_BPFMD_128: +- data |= (0x2 << 8); +- break; +- case SH_FSI_BPFMD_256: +- data |= (0x3 << 8); +- break; +- case SH_FSI_BPFMD_512: +- data |= (0x4 << 8); +- break; +- case SH_FSI_BPFMD_16: +- if (fsi_ver < 2) +- dev_err(dai->dev, "unsupported ACKMD\n"); +- else +- data |= (0x7 << 8); +- break; +- } +- +- fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); +- udelay(10); +- ret = 0; +- } + + return ret; +- + } + + static struct snd_soc_dai_ops fsi_dai_ops = { +@@ -1301,8 +1315,7 @@ static int fsi_remove(struct platform_device *pdev) + } + + static void __fsi_suspend(struct fsi_priv *fsi, +- struct device *dev, +- set_rate_func set_rate) ++ struct device *dev) + { + fsi->saved_do_fmt = fsi_reg_read(fsi, DO_FMT); + fsi->saved_di_fmt = fsi_reg_read(fsi, DI_FMT); +@@ -1311,12 +1324,11 @@ static void __fsi_suspend(struct fsi_priv *fsi, + fsi->saved_out_sel = fsi_reg_read(fsi, OUT_SEL); + + if (fsi_is_clk_master(fsi)) +- set_rate(dev, fsi_is_port_a(fsi), fsi->rate, 0); ++ fsi_set_master_clk(dev, fsi, fsi->rate, 0); + } + + static void __fsi_resume(struct fsi_priv *fsi, +- struct device *dev, +- set_rate_func set_rate) ++ struct device *dev) + { + fsi_reg_write(fsi, DO_FMT, fsi->saved_do_fmt); + fsi_reg_write(fsi, DI_FMT, fsi->saved_di_fmt); +@@ -1325,18 +1337,17 @@ static void __fsi_resume(struct fsi_priv *fsi, + fsi_reg_write(fsi, OUT_SEL, fsi->saved_out_sel); + + if (fsi_is_clk_master(fsi)) +- set_rate(dev, fsi_is_port_a(fsi), fsi->rate, 1); ++ fsi_set_master_clk(dev, fsi, fsi->rate, 1); + } + + static int fsi_suspend(struct device *dev) + { + struct fsi_master *master = dev_get_drvdata(dev); +- set_rate_func set_rate = fsi_get_info_set_rate(master); + + pm_runtime_get_sync(dev); + +- __fsi_suspend(&master->fsia, dev, set_rate); +- __fsi_suspend(&master->fsib, dev, set_rate); ++ __fsi_suspend(&master->fsia, dev); ++ __fsi_suspend(&master->fsib, dev); + + master->saved_a_mclk = fsi_core_read(master, a_mclk); + master->saved_b_mclk = fsi_core_read(master, b_mclk); +@@ -1355,7 +1366,6 @@ static int fsi_suspend(struct device *dev) + static int fsi_resume(struct device *dev) + { + struct fsi_master *master = dev_get_drvdata(dev); +- set_rate_func set_rate = fsi_get_info_set_rate(master); + + pm_runtime_get_sync(dev); + +@@ -1368,8 +1378,8 @@ static int fsi_resume(struct device *dev) + fsi_core_mask_set(master, iemsk, 0xffff, master->saved_iemsk); + fsi_core_mask_set(master, imsk, 0xffff, master->saved_imsk); + +- __fsi_resume(&master->fsia, dev, set_rate); +- __fsi_resume(&master->fsib, dev, set_rate); ++ __fsi_resume(&master->fsia, dev); ++ __fsi_resume(&master->fsib, dev); + + pm_runtime_put_sync(dev); + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0082-ASoC-sh-fsi-irq-control-moves-to-fsi_port_start-stop.patch b/patches.kzm9g/0082-ASoC-sh-fsi-irq-control-moves-to-fsi_port_start-stop.patch new file mode 100644 index 00000000000000..98b7a8a5a53f8e --- /dev/null +++ b/patches.kzm9g/0082-ASoC-sh-fsi-irq-control-moves-to-fsi_port_start-stop.patch @@ -0,0 +1,74 @@ +From 640c889570e0563c5a0e3bc7caf89bba5244d8b4 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 May 2011 20:46:23 +0900 +Subject: ASoC: sh: fsi: irq control moves to fsi_port_start/stop + +Using fsi_irq_enable/disable in fsi_port_start/stop is very natural. +This patch is preparation of cleanup suspend/resume patch. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 1ddddd36353c40fbf8faad955fcc26e05f656121) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 78a1631..c445e86 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -654,15 +654,20 @@ static void __fsi_module_clk_ctrl(struct fsi_master *master, + pm_runtime_put_sync(dev); + } + +-#define fsi_port_start(f) __fsi_port_clk_ctrl(f, 1) +-#define fsi_port_stop(f) __fsi_port_clk_ctrl(f, 0) +-static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int enable) ++#define fsi_port_start(f, i) __fsi_port_clk_ctrl(f, i, 1) ++#define fsi_port_stop(f, i) __fsi_port_clk_ctrl(f, i, 0) ++static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable) + { + struct fsi_master *master = fsi_get_master(fsi); + u32 soft = fsi_is_port_a(fsi) ? PASR : PBSR; + u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; + int is_master = fsi_is_clk_master(fsi); + ++ if (enable) ++ fsi_irq_enable(fsi, is_play); ++ else ++ fsi_irq_disable(fsi, is_play); ++ + fsi_master_mask_set(master, SOFT_RST, soft, (enable) ? soft : 0); + if (is_master) + fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); +@@ -901,9 +906,6 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { + struct fsi_priv *fsi = fsi_get_priv(substream); +- int is_play = fsi_is_play(substream); +- +- fsi_irq_disable(fsi, is_play); + + if (fsi_is_clk_master(fsi)) + fsi_set_master_clk(dai->dev, fsi, fsi->rate, 0); +@@ -924,12 +926,10 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, + case SNDRV_PCM_TRIGGER_START: + fsi_stream_push(fsi, is_play, substream); + ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); +- fsi_irq_enable(fsi, is_play); +- fsi_port_start(fsi); ++ fsi_port_start(fsi, is_play); + break; + case SNDRV_PCM_TRIGGER_STOP: +- fsi_port_stop(fsi); +- fsi_irq_disable(fsi, is_play); ++ fsi_port_stop(fsi, is_play); + fsi_stream_pop(fsi, is_play); + break; + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0083-ASoC-sh-fsi-tidyup-unclear-variable-naming.patch b/patches.kzm9g/0083-ASoC-sh-fsi-tidyup-unclear-variable-naming.patch new file mode 100644 index 00000000000000..98e9e9570ab38d --- /dev/null +++ b/patches.kzm9g/0083-ASoC-sh-fsi-tidyup-unclear-variable-naming.patch @@ -0,0 +1,344 @@ +From f958aa05f1e92cc702ef0aabb8230172eb6f6275 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 May 2011 20:46:03 +0900 +Subject: ASoC: sh: fsi: tidyup unclear variable naming + +Some variables on this driver were a unclear naming, +and were different unit (byte, frame, sample). +And some functions had wrong name +(ex. it returned "sample width" but name was "fsi_get_frame_width"). +This patch tidy-up this issue, and the minimum unit become "sample". +Special thanks to Takashi YOSHII. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 2e651bafa959c6e2620601c2c2e9b7c26f6a9c1a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 182 +++++++++++++++++++++++++++++------------------------ + 1 file changed, 100 insertions(+), 82 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index c445e86..98c8296 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -118,10 +118,38 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena + /* + * FSI driver use below type name for variable + * +- * xxx_len : data length +- * xxx_width : data width +- * xxx_offset : data offset + * xxx_num : number of data ++ * xxx_pos : position of data ++ * xxx_capa : capacity of data ++ */ ++ ++/* ++ * period/frame/sample image ++ * ++ * ex) PCM (2ch) ++ * ++ * period pos period pos ++ * [n] [n + 1] ++ * |<-------------------- period--------------------->| ++ * ==|============================================ ... =|== ++ * | | ++ * ||<----- frame ----->|<------ frame ----->| ... | ++ * |+--------------------+--------------------+- ... | ++ * ||[ sample ][ sample ]|[ sample ][ sample ]| ... | ++ * |+--------------------+--------------------+- ... | ++ * ==|============================================ ... =|== ++ */ ++ ++/* ++ * FSI FIFO image ++ * ++ * | | ++ * | | ++ * | [ sample ] | ++ * | [ sample ] | ++ * | [ sample ] | ++ * | [ sample ] | ++ * --> go to codecs + */ + + /* +@@ -131,12 +159,11 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena + struct fsi_stream { + struct snd_pcm_substream *substream; + +- int fifo_max_num; +- +- int buff_offset; +- int buff_len; +- int period_len; +- int period_num; ++ int fifo_sample_capa; /* sample capacity of FSI FIFO */ ++ int buff_sample_capa; /* sample capacity of ALSA buffer */ ++ int buff_sample_pos; /* sample position of ALSA buffer */ ++ int period_samples; /* sample number / 1 period */ ++ int period_pos; /* current period position */ + + int uerr_num; + int oerr_num; +@@ -342,6 +369,16 @@ static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) + return shift; + } + ++static int fsi_frame2sample(struct fsi_priv *fsi, int frames) ++{ ++ return frames * fsi->chan_num; ++} ++ ++static int fsi_sample2frame(struct fsi_priv *fsi, int samples) ++{ ++ return samples / fsi->chan_num; ++} ++ + static void fsi_stream_push(struct fsi_priv *fsi, + int is_play, + struct snd_pcm_substream *substream) +@@ -350,10 +387,10 @@ static void fsi_stream_push(struct fsi_priv *fsi, + struct snd_pcm_runtime *runtime = substream->runtime; + + io->substream = substream; +- io->buff_len = frames_to_bytes(runtime, runtime->buffer_size); +- io->buff_offset = 0; +- io->period_len = frames_to_bytes(runtime, runtime->period_size); +- io->period_num = 0; ++ io->buff_sample_capa = fsi_frame2sample(fsi, runtime->buffer_size); ++ io->buff_sample_pos = 0; ++ io->period_samples = fsi_frame2sample(fsi, runtime->period_size); ++ io->period_pos = 0; + io->oerr_num = -1; /* ignore 1st err */ + io->uerr_num = -1; /* ignore 1st err */ + } +@@ -371,47 +408,26 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) + dev_err(dai->dev, "under_run = %d\n", io->uerr_num); + + io->substream = NULL; +- io->buff_len = 0; +- io->buff_offset = 0; +- io->period_len = 0; +- io->period_num = 0; ++ io->buff_sample_capa = 0; ++ io->buff_sample_pos = 0; ++ io->period_samples = 0; ++ io->period_pos = 0; + io->oerr_num = 0; + io->uerr_num = 0; + } + +-static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) ++static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play) + { + u32 status; +- int data_num; ++ int frames; + + status = is_play ? + fsi_reg_read(fsi, DOFF_ST) : + fsi_reg_read(fsi, DIFF_ST); + +- data_num = 0x1ff & (status >> 8); +- data_num *= fsi->chan_num; +- +- return data_num; +-} +- +-static int fsi_len2num(int len, int width) +-{ +- return len / width; +-} ++ frames = 0x1ff & (status >> 8); + +-#define fsi_num2offset(a, b) fsi_num2len(a, b) +-static int fsi_num2len(int num, int width) +-{ +- return num * width; +-} +- +-static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play) +-{ +- struct fsi_stream *io = fsi_get_stream(fsi, is_play); +- struct snd_pcm_substream *substream = io->substream; +- struct snd_pcm_runtime *runtime = substream->runtime; +- +- return frames_to_bytes(runtime, 1) / fsi->chan_num; ++ return fsi_frame2sample(fsi, frames); + } + + static void fsi_count_fifo_err(struct fsi_priv *fsi) +@@ -443,8 +459,10 @@ static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream) + { + int is_play = fsi_stream_is_play(stream); + struct fsi_stream *io = fsi_get_stream(fsi, is_play); ++ struct snd_pcm_runtime *runtime = io->substream->runtime; + +- return io->substream->runtime->dma_area + io->buff_offset; ++ return runtime->dma_area + ++ samples_to_bytes(runtime, io->buff_sample_pos); + } + + static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num) +@@ -683,13 +701,14 @@ static void fsi_fifo_init(struct fsi_priv *fsi, + struct fsi_master *master = fsi_get_master(fsi); + struct fsi_stream *io = fsi_get_stream(fsi, is_play); + u32 shift, i; ++ int frame_capa; + + /* get on-chip RAM capacity */ + shift = fsi_master_read(master, FIFO_SZ); + shift >>= fsi_get_port_shift(fsi, is_play); + shift &= FIFO_SZ_MASK; +- io->fifo_max_num = 256 << shift; +- dev_dbg(dai->dev, "fifo = %d words\n", io->fifo_max_num); ++ frame_capa = 256 << shift; ++ dev_dbg(dai->dev, "fifo = %d words\n", frame_capa); + + /* + * The maximum number of sample data varies depending +@@ -711,9 +730,11 @@ static void fsi_fifo_init(struct fsi_priv *fsi, + * 8 channels: 32 ( 32 x 8 = 256) + */ + for (i = 1; i < fsi->chan_num; i <<= 1) +- io->fifo_max_num >>= 1; ++ frame_capa >>= 1; + dev_dbg(dai->dev, "%d channel %d store\n", +- fsi->chan_num, io->fifo_max_num); ++ fsi->chan_num, frame_capa); ++ ++ io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa); + + /* + * set interrupt generation factor +@@ -734,10 +755,10 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + struct snd_pcm_substream *substream = NULL; + int is_play = fsi_stream_is_play(stream); + struct fsi_stream *io = fsi_get_stream(fsi, is_play); +- int data_residue_num; +- int data_num; +- int data_num_max; +- int ch_width; ++ int sample_residues; ++ int sample_width; ++ int samples; ++ int samples_max; + int over_period; + void (*fn)(struct fsi_priv *fsi, int size); + +@@ -753,36 +774,35 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + /* FSI FIFO has limit. + * So, this driver can not send periods data at a time + */ +- if (io->buff_offset >= +- fsi_num2offset(io->period_num + 1, io->period_len)) { ++ if (io->buff_sample_pos >= ++ io->period_samples * (io->period_pos + 1)) { + + over_period = 1; +- io->period_num = (io->period_num + 1) % runtime->periods; ++ io->period_pos = (io->period_pos + 1) % runtime->periods; + +- if (0 == io->period_num) +- io->buff_offset = 0; ++ if (0 == io->period_pos) ++ io->buff_sample_pos = 0; + } + +- /* get 1 channel data width */ +- ch_width = fsi_get_frame_width(fsi, is_play); ++ /* get 1 sample data width */ ++ sample_width = samples_to_bytes(runtime, 1); + +- /* get residue data number of alsa */ +- data_residue_num = fsi_len2num(io->buff_len - io->buff_offset, +- ch_width); ++ /* get number of residue samples */ ++ sample_residues = io->buff_sample_capa - io->buff_sample_pos; + + if (is_play) { + /* + * for play-back + * +- * data_num_max : number of FSI fifo free space +- * data_num : number of ALSA residue data ++ * samples_max : number of FSI fifo free samples space ++ * samples : number of ALSA residue samples + */ +- data_num_max = io->fifo_max_num * fsi->chan_num; +- data_num_max -= fsi_get_fifo_data_num(fsi, is_play); ++ samples_max = io->fifo_sample_capa; ++ samples_max -= fsi_get_current_fifo_samples(fsi, is_play); + +- data_num = data_residue_num; ++ samples = sample_residues; + +- switch (ch_width) { ++ switch (sample_width) { + case 2: + fn = fsi_dma_soft_push16; + break; +@@ -796,13 +816,13 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + /* + * for capture + * +- * data_num_max : number of ALSA free space +- * data_num : number of data in FSI fifo ++ * samples_max : number of ALSA free samples space ++ * samples : number of samples in FSI fifo + */ +- data_num_max = data_residue_num; +- data_num = fsi_get_fifo_data_num(fsi, is_play); ++ samples_max = sample_residues; ++ samples = fsi_get_current_fifo_samples(fsi, is_play); + +- switch (ch_width) { ++ switch (sample_width) { + case 2: + fn = fsi_dma_soft_pop16; + break; +@@ -814,12 +834,12 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + } + } + +- data_num = min(data_num, data_num_max); ++ samples = min(samples, samples_max); + +- fn(fsi, data_num); ++ fn(fsi, samples); + +- /* update buff_offset */ +- io->buff_offset += fsi_num2offset(data_num, ch_width); ++ /* update buff_sample_pos */ ++ io->buff_sample_pos += samples; + + if (over_period) + snd_pcm_period_elapsed(substream); +@@ -1107,16 +1127,14 @@ static int fsi_hw_free(struct snd_pcm_substream *substream) + + static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) + { +- struct snd_pcm_runtime *runtime = substream->runtime; + struct fsi_priv *fsi = fsi_get_priv(substream); + struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream)); +- long location; ++ int samples_pos = io->buff_sample_pos - 1; + +- location = (io->buff_offset - 1); +- if (location < 0) +- location = 0; ++ if (samples_pos < 0) ++ samples_pos = 0; + +- return bytes_to_frames(runtime, location); ++ return fsi_sample2frame(fsi, samples_pos); + } + + static struct snd_pcm_ops fsi_pcm_ops = { +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0084-ASoC-sh-fsi-remove-pm_runtime-from-fsi_dai_set_fmt.patch b/patches.kzm9g/0084-ASoC-sh-fsi-remove-pm_runtime-from-fsi_dai_set_fmt.patch new file mode 100644 index 00000000000000..af2fc0db301d94 --- /dev/null +++ b/patches.kzm9g/0084-ASoC-sh-fsi-remove-pm_runtime-from-fsi_dai_set_fmt.patch @@ -0,0 +1,160 @@ +From 387c7967931d638fd30d2a63ec171e42c71477bd Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 May 2011 20:46:07 +0900 +Subject: ASoC: sh: fsi: remove pm_runtime from fsi_dai_set_fmt. + +pm_runtime_get/put_sync were used to access FSI register in fsi_dai_set_fmt +which is called when ALSA probe. +But this register value will disappear after pm_runtime_put_sync +if platform is supporting RuntimePM. +To solve this issue, this patch adds new variable for format, +and remove pm_runtime_get/put_sync from fsi_dai_set_fmt. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 9478e0b60fb4a7adde72d4a86b826d396b607a61) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 52 ++++++++++++++++++++++++++++++++-------------------- + 1 file changed, 32 insertions(+), 20 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 98c8296..0a09ea2 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -176,8 +176,12 @@ struct fsi_priv { + struct fsi_stream playback; + struct fsi_stream capture; + ++ u32 do_fmt; ++ u32 di_fmt; ++ + int chan_num:16; + int clk_master:1; ++ int spdif:1; + + long rate; + +@@ -298,6 +302,11 @@ static int fsi_is_port_a(struct fsi_priv *fsi) + return fsi->master->base == fsi->base; + } + ++static int fsi_is_spdif(struct fsi_priv *fsi) ++{ ++ return fsi->spdif; ++} ++ + static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) + { + struct snd_soc_pcm_runtime *rtd = substream->private_data; +@@ -893,11 +902,16 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, + { + struct fsi_priv *fsi = fsi_get_priv(substream); + u32 flags = fsi_get_info_flags(fsi); +- u32 data; ++ u32 data = 0; + int is_play = fsi_is_play(substream); + + pm_runtime_get_sync(dai->dev); + ++ /* clock setting */ ++ if (fsi_is_clk_master(fsi)) ++ data = DIMD | DOMD; ++ ++ fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); + + /* clock inversion (CKG2) */ + data = 0; +@@ -912,6 +926,16 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, + + fsi_reg_write(fsi, CKG2, data); + ++ /* set format */ ++ fsi_reg_write(fsi, DO_FMT, fsi->do_fmt); ++ fsi_reg_write(fsi, DI_FMT, fsi->di_fmt); ++ ++ /* spdif ? */ ++ if (fsi_is_spdif(fsi)) { ++ fsi_spdif_clk_ctrl(fsi, 1); ++ fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); ++ } ++ + /* irq clear */ + fsi_irq_disable(fsi, is_play); + fsi_irq_clear_status(fsi); +@@ -974,8 +998,8 @@ static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt) + return -EINVAL; + } + +- fsi_reg_write(fsi, DO_FMT, data); +- fsi_reg_write(fsi, DI_FMT, data); ++ fsi->do_fmt = data; ++ fsi->di_fmt = data; + + return 0; + } +@@ -990,11 +1014,10 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi) + + data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; + fsi->chan_num = 2; +- fsi_spdif_clk_ctrl(fsi, 1); +- fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); ++ fsi->spdif = 1; + +- fsi_reg_write(fsi, DO_FMT, data); +- fsi_reg_write(fsi, DI_FMT, data); ++ fsi->do_fmt = data; ++ fsi->di_fmt = data; + + return 0; + } +@@ -1005,32 +1028,24 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) + struct fsi_master *master = fsi_get_master(fsi); + set_rate_func set_rate = fsi_get_info_set_rate(master); + u32 flags = fsi_get_info_flags(fsi); +- u32 data = 0; + int ret; + +- pm_runtime_get_sync(dai->dev); +- + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: +- data = DIMD | DOMD; + fsi->clk_master = 1; + break; + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: +- ret = -EINVAL; +- goto set_fmt_exit; ++ return -EINVAL; + } + + if (fsi_is_clk_master(fsi) && !set_rate) { + dev_err(dai->dev, "platform doesn't have set_rate\n"); +- ret = -EINVAL; +- goto set_fmt_exit; ++ return -EINVAL; + } + +- fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); +- + /* set format */ + switch (flags & SH_FSI_FMT_MASK) { + case SH_FSI_FMT_DAI: +@@ -1043,9 +1058,6 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) + ret = -EINVAL; + } + +-set_fmt_exit: +- pm_runtime_put_sync(dai->dev); +- + return ret; + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0085-ASoC-sh-fsi-make-sure-fsi_stream_push-pop-access-by-.patch b/patches.kzm9g/0085-ASoC-sh-fsi-make-sure-fsi_stream_push-pop-access-by-.patch new file mode 100644 index 00000000000000..577fe89dd9c4f3 --- /dev/null +++ b/patches.kzm9g/0085-ASoC-sh-fsi-make-sure-fsi_stream_push-pop-access-by-.patch @@ -0,0 +1,62 @@ +From 9a2ab68a1322eb35bf0ac8176cf8d14052c4aefa Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 May 2011 20:46:13 +0900 +Subject: ASoC: sh: fsi: make sure fsi_stream_push/pop access by spin lock + +fsi_stream_push/pop might be called in same time. +This patch protect it. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 2da658927c9e28425ecb6b6a7a03094a012e8620) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 0a09ea2..e371db8 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -394,7 +394,10 @@ static void fsi_stream_push(struct fsi_priv *fsi, + { + struct fsi_stream *io = fsi_get_stream(fsi, is_play); + struct snd_pcm_runtime *runtime = substream->runtime; ++ struct fsi_master *master = fsi_get_master(fsi); ++ unsigned long flags; + ++ spin_lock_irqsave(&master->lock, flags); + io->substream = substream; + io->buff_sample_capa = fsi_frame2sample(fsi, runtime->buffer_size); + io->buff_sample_pos = 0; +@@ -402,13 +405,17 @@ static void fsi_stream_push(struct fsi_priv *fsi, + io->period_pos = 0; + io->oerr_num = -1; /* ignore 1st err */ + io->uerr_num = -1; /* ignore 1st err */ ++ spin_unlock_irqrestore(&master->lock, flags); + } + + static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) + { + struct fsi_stream *io = fsi_get_stream(fsi, is_play); + struct snd_soc_dai *dai = fsi_get_dai(io->substream); ++ struct fsi_master *master = fsi_get_master(fsi); ++ unsigned long flags; + ++ spin_lock_irqsave(&master->lock, flags); + + if (io->oerr_num > 0) + dev_err(dai->dev, "over_run = %d\n", io->oerr_num); +@@ -423,6 +430,7 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) + io->period_pos = 0; + io->oerr_num = 0; + io->uerr_num = 0; ++ spin_unlock_irqrestore(&master->lock, flags); + } + + static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0086-ASoC-sh-fsi-remove-fsi_module_init-kill.patch b/patches.kzm9g/0086-ASoC-sh-fsi-remove-fsi_module_init-kill.patch new file mode 100644 index 00000000000000..f6c8defb17fe75 --- /dev/null +++ b/patches.kzm9g/0086-ASoC-sh-fsi-remove-fsi_module_init-kill.patch @@ -0,0 +1,106 @@ +From 775ff31c0db6d3de98d58f4f4f6c1d7614eb0ebc Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 May 2011 20:46:30 +0900 +Subject: ASoC: sh: fsi: remove fsi_module_init/kill + +FSIA/B ports is enabled by default when power-on, +and current FSI is supporting RuntimePM. +In addition, current fsi_module_init/kill doesn't care +simultaneous playback/recorde. +This mean FSI port control is not needed. +This patch remove fsi_module_init/kill + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 4c481253311dd5940ae7c26eaff6c6f63bd41fd8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 30 ------------------------------ + 1 file changed, 30 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index e371db8..c9cf84d 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -669,32 +669,11 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, + + } + +-#define fsi_module_init(m, d) __fsi_module_clk_ctrl(m, d, 1) +-#define fsi_module_kill(m, d) __fsi_module_clk_ctrl(m, d, 0) +-static void __fsi_module_clk_ctrl(struct fsi_master *master, +- struct device *dev, +- int enable) +-{ +- pm_runtime_get_sync(dev); +- +- if (enable) { +- /* enable only SR */ +- fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR); +- fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0); +- } else { +- /* clear all registers */ +- fsi_master_mask_set(master, SOFT_RST, FSISR, 0); +- } +- +- pm_runtime_put_sync(dev); +-} +- + #define fsi_port_start(f, i) __fsi_port_clk_ctrl(f, i, 1) + #define fsi_port_stop(f, i) __fsi_port_clk_ctrl(f, i, 0) + static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable) + { + struct fsi_master *master = fsi_get_master(fsi); +- u32 soft = fsi_is_port_a(fsi) ? PASR : PBSR; + u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; + int is_master = fsi_is_clk_master(fsi); + +@@ -703,7 +682,6 @@ static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable) + else + fsi_irq_disable(fsi, is_play); + +- fsi_master_mask_set(master, SOFT_RST, soft, (enable) ? soft : 0); + if (is_master) + fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); + } +@@ -1294,8 +1272,6 @@ static int fsi_probe(struct platform_device *pdev) + pm_runtime_enable(&pdev->dev); + dev_set_drvdata(&pdev->dev, master); + +- fsi_module_init(master, &pdev->dev); +- + ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, + id_entry->name, master); + if (ret) { +@@ -1338,8 +1314,6 @@ static int fsi_remove(struct platform_device *pdev) + + master = dev_get_drvdata(&pdev->dev); + +- fsi_module_kill(master, &pdev->dev); +- + free_irq(master->irq, master); + pm_runtime_disable(&pdev->dev); + +@@ -1394,8 +1368,6 @@ static int fsi_suspend(struct device *dev) + master->saved_clk_rst = fsi_master_read(master, CLK_RST); + master->saved_soft_rst = fsi_master_read(master, SOFT_RST); + +- fsi_module_kill(master, dev); +- + pm_runtime_put_sync(dev); + + return 0; +@@ -1407,8 +1379,6 @@ static int fsi_resume(struct device *dev) + + pm_runtime_get_sync(dev); + +- fsi_module_init(master, dev); +- + fsi_master_mask_set(master, SOFT_RST, 0xffff, master->saved_soft_rst); + fsi_master_mask_set(master, CLK_RST, 0xffff, master->saved_clk_rst); + fsi_core_mask_set(master, a_mclk, 0xffff, master->saved_a_mclk); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0087-ASoC-sh-fsi-cleanup-suspend-resume.patch b/patches.kzm9g/0087-ASoC-sh-fsi-cleanup-suspend-resume.patch new file mode 100644 index 00000000000000..2396a52cbfcd75 --- /dev/null +++ b/patches.kzm9g/0087-ASoC-sh-fsi-cleanup-suspend-resume.patch @@ -0,0 +1,202 @@ +From fd2a98f748b7982d546c368f12e9c96d29e11559 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 May 2011 20:46:35 +0900 +Subject: ASoC: sh: fsi: cleanup suspend/resume + +Current FSI driver was using saved_xxx variable for suspend/resume. +OTOH, the start and stop of power/clock are controlled by +fsi_hw_startup/fsi_hw_shutdown in current FSI driver. +The all necessary registers value are set by fsi_hw_startup. + +So, if fsi_hw_shutdown is called when "suspend" is generated, +and fsi_hw_startup is called at "resume", +the saved_xxx are not needed. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit cda828cafe9df9a8b0687f1b8a17be2cd9cf1950) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 97 +++++++++++++++++++++++------------------------------- + 1 file changed, 42 insertions(+), 55 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index c9cf84d..d2e28e4 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -184,13 +184,6 @@ struct fsi_priv { + int spdif:1; + + long rate; +- +- /* for suspend/resume */ +- u32 saved_do_fmt; +- u32 saved_di_fmt; +- u32 saved_ckg1; +- u32 saved_ckg2; +- u32 saved_out_sel; + }; + + struct fsi_core { +@@ -211,14 +204,6 @@ struct fsi_master { + struct fsi_core *core; + struct sh_fsi_platform_info *info; + spinlock_t lock; +- +- /* for suspend/resume */ +- u32 saved_a_mclk; +- u32 saved_b_mclk; +- u32 saved_iemsk; +- u32 saved_imsk; +- u32 saved_clk_rst; +- u32 saved_soft_rst; + }; + + /* +@@ -388,6 +373,21 @@ static int fsi_sample2frame(struct fsi_priv *fsi, int samples) + return samples / fsi->chan_num; + } + ++static int fsi_stream_is_working(struct fsi_priv *fsi, ++ int is_play) ++{ ++ struct fsi_stream *io = fsi_get_stream(fsi, is_play); ++ struct fsi_master *master = fsi_get_master(fsi); ++ unsigned long flags; ++ int ret; ++ ++ spin_lock_irqsave(&master->lock, flags); ++ ret = !!io->substream; ++ spin_unlock_irqrestore(&master->lock, flags); ++ ++ return ret; ++} ++ + static void fsi_stream_push(struct fsi_priv *fsi, + int is_play, + struct snd_pcm_substream *substream) +@@ -666,7 +666,6 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, + } + + return ret; +- + } + + #define fsi_port_start(f, i) __fsi_port_clk_ctrl(f, i, 1) +@@ -675,14 +674,13 @@ static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable) + { + struct fsi_master *master = fsi_get_master(fsi); + u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; +- int is_master = fsi_is_clk_master(fsi); + + if (enable) + fsi_irq_enable(fsi, is_play); + else + fsi_irq_disable(fsi, is_play); + +- if (is_master) ++ if (fsi_is_clk_master(fsi)) + fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); + } + +@@ -1327,48 +1325,43 @@ static int fsi_remove(struct platform_device *pdev) + } + + static void __fsi_suspend(struct fsi_priv *fsi, ++ int is_play, + struct device *dev) + { +- fsi->saved_do_fmt = fsi_reg_read(fsi, DO_FMT); +- fsi->saved_di_fmt = fsi_reg_read(fsi, DI_FMT); +- fsi->saved_ckg1 = fsi_reg_read(fsi, CKG1); +- fsi->saved_ckg2 = fsi_reg_read(fsi, CKG2); +- fsi->saved_out_sel = fsi_reg_read(fsi, OUT_SEL); ++ if (!fsi_stream_is_working(fsi, is_play)) ++ return; + +- if (fsi_is_clk_master(fsi)) +- fsi_set_master_clk(dev, fsi, fsi->rate, 0); ++ fsi_port_stop(fsi, is_play); ++ fsi_hw_shutdown(fsi, is_play, dev); + } + + static void __fsi_resume(struct fsi_priv *fsi, ++ int is_play, + struct device *dev) + { +- fsi_reg_write(fsi, DO_FMT, fsi->saved_do_fmt); +- fsi_reg_write(fsi, DI_FMT, fsi->saved_di_fmt); +- fsi_reg_write(fsi, CKG1, fsi->saved_ckg1); +- fsi_reg_write(fsi, CKG2, fsi->saved_ckg2); +- fsi_reg_write(fsi, OUT_SEL, fsi->saved_out_sel); ++ if (!fsi_stream_is_working(fsi, is_play)) ++ return; + +- if (fsi_is_clk_master(fsi)) ++ fsi_hw_startup(fsi, is_play, dev); ++ ++ if (fsi_is_clk_master(fsi) && fsi->rate) + fsi_set_master_clk(dev, fsi, fsi->rate, 1); ++ ++ fsi_port_start(fsi, is_play); ++ + } + + static int fsi_suspend(struct device *dev) + { + struct fsi_master *master = dev_get_drvdata(dev); ++ struct fsi_priv *fsia = &master->fsia; ++ struct fsi_priv *fsib = &master->fsib; + +- pm_runtime_get_sync(dev); +- +- __fsi_suspend(&master->fsia, dev); +- __fsi_suspend(&master->fsib, dev); ++ __fsi_suspend(fsia, 1, dev); ++ __fsi_suspend(fsia, 0, dev); + +- master->saved_a_mclk = fsi_core_read(master, a_mclk); +- master->saved_b_mclk = fsi_core_read(master, b_mclk); +- master->saved_iemsk = fsi_core_read(master, iemsk); +- master->saved_imsk = fsi_core_read(master, imsk); +- master->saved_clk_rst = fsi_master_read(master, CLK_RST); +- master->saved_soft_rst = fsi_master_read(master, SOFT_RST); +- +- pm_runtime_put_sync(dev); ++ __fsi_suspend(fsib, 1, dev); ++ __fsi_suspend(fsib, 0, dev); + + return 0; + } +@@ -1376,20 +1369,14 @@ static int fsi_suspend(struct device *dev) + static int fsi_resume(struct device *dev) + { + struct fsi_master *master = dev_get_drvdata(dev); ++ struct fsi_priv *fsia = &master->fsia; ++ struct fsi_priv *fsib = &master->fsib; + +- pm_runtime_get_sync(dev); +- +- fsi_master_mask_set(master, SOFT_RST, 0xffff, master->saved_soft_rst); +- fsi_master_mask_set(master, CLK_RST, 0xffff, master->saved_clk_rst); +- fsi_core_mask_set(master, a_mclk, 0xffff, master->saved_a_mclk); +- fsi_core_mask_set(master, b_mclk, 0xffff, master->saved_b_mclk); +- fsi_core_mask_set(master, iemsk, 0xffff, master->saved_iemsk); +- fsi_core_mask_set(master, imsk, 0xffff, master->saved_imsk); +- +- __fsi_resume(&master->fsia, dev); +- __fsi_resume(&master->fsib, dev); ++ __fsi_resume(fsia, 1, dev); ++ __fsi_resume(fsia, 0, dev); + +- pm_runtime_put_sync(dev); ++ __fsi_resume(fsib, 1, dev); ++ __fsi_resume(fsib, 0, dev); + + return 0; + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0088-ASoC-sh-fsi-add-fsi_hw_startup-shutdown.patch b/patches.kzm9g/0088-ASoC-sh-fsi-add-fsi_hw_startup-shutdown.patch new file mode 100644 index 00000000000000..ab0f66604fdf31 --- /dev/null +++ b/patches.kzm9g/0088-ASoC-sh-fsi-add-fsi_hw_startup-shutdown.patch @@ -0,0 +1,116 @@ +From fb099115bddf1865f0de965e6c137b8d8048e37f Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 May 2011 20:46:26 +0900 +Subject: ASoC: sh: fsi: add fsi_hw_startup/shutdown + +This patch is preparation of cleanup suspend/resume patch. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Liam Girdwood <lrg@ti.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 23ca853392aebdaa56c8138746deb2002e03d827) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 43 +++++++++++++++++++++++++++++-------------- + 1 file changed, 29 insertions(+), 14 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index d2e28e4..8e112cc 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -689,7 +689,7 @@ static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable) + */ + static void fsi_fifo_init(struct fsi_priv *fsi, + int is_play, +- struct snd_soc_dai *dai) ++ struct device *dev) + { + struct fsi_master *master = fsi_get_master(fsi); + struct fsi_stream *io = fsi_get_stream(fsi, is_play); +@@ -701,7 +701,7 @@ static void fsi_fifo_init(struct fsi_priv *fsi, + shift >>= fsi_get_port_shift(fsi, is_play); + shift &= FIFO_SZ_MASK; + frame_capa = 256 << shift; +- dev_dbg(dai->dev, "fifo = %d words\n", frame_capa); ++ dev_dbg(dev, "fifo = %d words\n", frame_capa); + + /* + * The maximum number of sample data varies depending +@@ -724,7 +724,7 @@ static void fsi_fifo_init(struct fsi_priv *fsi, + */ + for (i = 1; i < fsi->chan_num; i <<= 1) + frame_capa >>= 1; +- dev_dbg(dai->dev, "%d channel %d store\n", ++ dev_dbg(dev, "%d channel %d store\n", + fsi->chan_num, frame_capa); + + io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa); +@@ -881,15 +881,14 @@ static irqreturn_t fsi_interrupt(int irq, void *data) + * dai ops + */ + +-static int fsi_dai_startup(struct snd_pcm_substream *substream, +- struct snd_soc_dai *dai) ++static int fsi_hw_startup(struct fsi_priv *fsi, ++ int is_play, ++ struct device *dev) + { +- struct fsi_priv *fsi = fsi_get_priv(substream); + u32 flags = fsi_get_info_flags(fsi); + u32 data = 0; +- int is_play = fsi_is_play(substream); + +- pm_runtime_get_sync(dai->dev); ++ pm_runtime_get_sync(dev); + + /* clock setting */ + if (fsi_is_clk_master(fsi)) +@@ -925,22 +924,38 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, + fsi_irq_clear_status(fsi); + + /* fifo init */ +- fsi_fifo_init(fsi, is_play, dai); ++ fsi_fifo_init(fsi, is_play, dev); + + return 0; + } + ++static void fsi_hw_shutdown(struct fsi_priv *fsi, ++ int is_play, ++ struct device *dev) ++{ ++ if (fsi_is_clk_master(fsi)) ++ fsi_set_master_clk(dev, fsi, fsi->rate, 0); ++ ++ pm_runtime_put_sync(dev); ++} ++ ++static int fsi_dai_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct fsi_priv *fsi = fsi_get_priv(substream); ++ int is_play = fsi_is_play(substream); ++ ++ return fsi_hw_startup(fsi, is_play, dai->dev); ++} ++ + static void fsi_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { + struct fsi_priv *fsi = fsi_get_priv(substream); ++ int is_play = fsi_is_play(substream); + +- if (fsi_is_clk_master(fsi)) +- fsi_set_master_clk(dai->dev, fsi, fsi->rate, 0); +- ++ fsi_hw_shutdown(fsi, is_play, dai->dev); + fsi->rate = 0; +- +- pm_runtime_put_sync(dai->dev); + } + + static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0089-sound-irq-Remove-IRQF_DISABLED.patch b/patches.kzm9g/0089-sound-irq-Remove-IRQF_DISABLED.patch new file mode 100644 index 00000000000000..b08c273864047a --- /dev/null +++ b/patches.kzm9g/0089-sound-irq-Remove-IRQF_DISABLED.patch @@ -0,0 +1,43 @@ +From 00e240dfffc278c30a57390dd1e129bcb4613e86 Mon Sep 17 00:00:00 2001 +From: Yong Zhang <yong.zhang0@gmail.com> +Date: Thu, 22 Sep 2011 16:59:20 +0800 +Subject: sound: irq: Remove IRQF_DISABLED + +Since commit [e58aa3d2: genirq: Run irq handlers with interrupts disabled], +We run all interrupt handlers with interrupts disabled +and we even check and yell when an interrupt handler +returns with interrupts enabled (see commit [b738a50a: +genirq: Warn when handler enables interrupts]). + +So now this flag is a NOOP and can be removed. + +Signed-off-by: Yong Zhang <yong.zhang0@gmail.com> +Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com> +Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +(cherry picked from commit 88e24c3a4b30a6bd361f2b5ce602667a8161b2e8) + +Cherry-picked changes for: + sound/soc/sh/fsi.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 8e112cc..1493ebf 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1285,7 +1285,7 @@ static int fsi_probe(struct platform_device *pdev) + pm_runtime_enable(&pdev->dev); + dev_set_drvdata(&pdev->dev, master); + +- ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, ++ ret = request_irq(irq, &fsi_interrupt, 0, + id_entry->name, master); + if (ret) { + dev_err(&pdev->dev, "irq request err\n"); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0090-ASoC-sh-use-correct-__iomem-annotations.patch b/patches.kzm9g/0090-ASoC-sh-use-correct-__iomem-annotations.patch new file mode 100644 index 00000000000000..306c72004b8ccd --- /dev/null +++ b/patches.kzm9g/0090-ASoC-sh-use-correct-__iomem-annotations.patch @@ -0,0 +1,66 @@ +From 03f1c40d29550119518b545adacb5cba60f2f67a Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann <arnd@arndb.de> +Date: Sun, 2 Oct 2011 22:28:02 +0200 +Subject: ASoC: sh: use correct __iomem annotations + +This removes a few unnecessary type casts and avoids +sparse warnings. + +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 00d579b1ea1200820b504a3e3cbbdb079a5ee808) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 1493ebf..a32fd16 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -210,7 +210,7 @@ struct fsi_master { + * basic read write function + */ + +-static void __fsi_reg_write(u32 reg, u32 data) ++static void __fsi_reg_write(u32 __iomem *reg, u32 data) + { + /* valid data area is 24bit */ + data &= 0x00ffffff; +@@ -218,12 +218,12 @@ static void __fsi_reg_write(u32 reg, u32 data) + __raw_writel(data, reg); + } + +-static u32 __fsi_reg_read(u32 reg) ++static u32 __fsi_reg_read(u32 __iomem *reg) + { + return __raw_readl(reg); + } + +-static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data) ++static void __fsi_reg_mask_set(u32 __iomem *reg, u32 mask, u32 data) + { + u32 val = __fsi_reg_read(reg); + +@@ -250,7 +250,7 @@ static u32 _fsi_master_read(struct fsi_master *master, u32 reg) + unsigned long flags; + + spin_lock_irqsave(&master->lock, flags); +- ret = __fsi_reg_read((u32)(master->base + reg)); ++ ret = __fsi_reg_read(master->base + reg); + spin_unlock_irqrestore(&master->lock, flags); + + return ret; +@@ -264,7 +264,7 @@ static void _fsi_master_mask_set(struct fsi_master *master, + unsigned long flags; + + spin_lock_irqsave(&master->lock, flags); +- __fsi_reg_mask_set((u32)(master->base + reg), mask, data); ++ __fsi_reg_mask_set(master->base + reg, mask, data); + spin_unlock_irqrestore(&master->lock, flags); + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0091-sound-Add-module.h-to-the-previously-silent-sound-us.patch b/patches.kzm9g/0091-sound-Add-module.h-to-the-previously-silent-sound-us.patch new file mode 100644 index 00000000000000..7ec039308d0198 --- /dev/null +++ b/patches.kzm9g/0091-sound-Add-module.h-to-the-previously-silent-sound-us.patch @@ -0,0 +1,63 @@ +From d8dddb115d296d8980cebee2527d6b4b875265b5 Mon Sep 17 00:00:00 2001 +From: Paul Gortmaker <paul.gortmaker@windriver.com> +Date: Fri, 15 Jul 2011 12:38:28 -0400 +Subject: sound: Add module.h to the previously silent sound users + +Lots of sound drivers were getting module.h via the implicit presence +of it in <linux/device.h> but we are going to clean that up. So +fix up those users now. + +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +(cherry picked from commit da155d5b40587815a4397e1a69382fe2366d940b) + +Cherry-picked changes to: + sound/soc/sh/fsi-ak4642.c + sound/soc/sh/fsi-da7210.c + sound/soc/sh/fsi.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi-ak4642.c | 1 + + sound/soc/sh/fsi-da7210.c | 1 + + sound/soc/sh/fsi.c | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c +index 770a71a..dff64b9 100644 +--- a/sound/soc/sh/fsi-ak4642.c ++++ b/sound/soc/sh/fsi-ak4642.c +@@ -10,6 +10,7 @@ + */ + + #include <linux/platform_device.h> ++#include <linux/module.h> + #include <sound/sh_fsi.h> + + struct fsi_ak4642_data { +diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c +index 59553fd..f5586b5b 100644 +--- a/sound/soc/sh/fsi-da7210.c ++++ b/sound/soc/sh/fsi-da7210.c +@@ -11,6 +11,7 @@ + */ + + #include <linux/platform_device.h> ++#include <linux/module.h> + #include <sound/sh_fsi.h> + + static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd) +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index a32fd16..3d7016e 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -16,6 +16,7 @@ + #include <linux/pm_runtime.h> + #include <linux/io.h> + #include <linux/slab.h> ++#include <linux/module.h> + #include <sound/soc.h> + #include <sound/sh_fsi.h> + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0092-ASoC-fsi-fixup-compile-warning.patch b/patches.kzm9g/0092-ASoC-fsi-fixup-compile-warning.patch new file mode 100644 index 00000000000000..2b2f7751945fa3 --- /dev/null +++ b/patches.kzm9g/0092-ASoC-fsi-fixup-compile-warning.patch @@ -0,0 +1,50 @@ +From 0d869ebdf0e3bbde84cf3a2ef58d98470f49cc07 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 31 Oct 2011 22:11:53 -0700 +Subject: ASoC: fsi: fixup compile warning + +This patch fixup below warning + +${linux}/sound/soc/sh/fsi.c:442:3:\ + warning: passing argument 1 of '__fsi_reg_read' makes pointer\ + from integer without a cast +${linux}/sound/soc/sh/fsi.c:517:3: \ + warning: passing argument 1 of '__fsi_reg_write' makes pointer\ + from integer without a cast +${linux}/sound/soc/sh/fsi.c:663:3: \ + warning: passing argument 1 of '__fsi_reg_mask_set' makes pointer\ + from integer without a cast + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 8918b843aff3236de6301b1137434d3f0bc0a0f5) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 3d7016e..e620cb1 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -235,13 +235,13 @@ static void __fsi_reg_mask_set(u32 __iomem *reg, u32 mask, u32 data) + } + + #define fsi_reg_write(p, r, d)\ +- __fsi_reg_write((u32)(p->base + REG_##r), d) ++ __fsi_reg_write((p->base + REG_##r), d) + + #define fsi_reg_read(p, r)\ +- __fsi_reg_read((u32)(p->base + REG_##r)) ++ __fsi_reg_read((p->base + REG_##r)) + + #define fsi_reg_mask_set(p, r, m, d)\ +- __fsi_reg_mask_set((u32)(p->base + REG_##r), m, d) ++ __fsi_reg_mask_set((p->base + REG_##r), m, d) + + #define fsi_master_read(p, r) _fsi_master_read(p, MST_##r) + #define fsi_core_read(p, r) _fsi_master_read(p, p->core->r) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0093-ASoC-fsi-add-valid-data-position-control-support.patch b/patches.kzm9g/0093-ASoC-fsi-add-valid-data-position-control-support.patch new file mode 100644 index 00000000000000..c1da63cccf9693 --- /dev/null +++ b/patches.kzm9g/0093-ASoC-fsi-add-valid-data-position-control-support.patch @@ -0,0 +1,62 @@ +From e763c47fab9fe188a39d5428a76ec75223742b2e Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 6 Nov 2011 22:05:25 -0800 +Subject: ASoC: fsi: add valid data position control support + +FSI2 can control valid data position, like +package in front/back or stream mode (16bit x 2). +But current fsi driver is assuming it was in-back. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 65ff03f4624d12ad6c19a01a0af7385eda09e4a6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index e620cb1..99ed610 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -32,7 +32,9 @@ + #define REG_DIDT 0x0020 + #define REG_DODT 0x0024 + #define REG_MUTE_ST 0x0028 ++#define REG_OUT_DMAC 0x002C + #define REG_OUT_SEL 0x0030 ++#define REG_IN_DMAC 0x0038 + + /* master register */ + #define MST_CLK_RST 0x0210 +@@ -886,6 +888,8 @@ static int fsi_hw_startup(struct fsi_priv *fsi, + int is_play, + struct device *dev) + { ++ struct fsi_master *master = fsi_get_master(fsi); ++ int fsi_ver = master->core->ver; + u32 flags = fsi_get_info_flags(fsi); + u32 data = 0; + +@@ -920,6 +924,17 @@ static int fsi_hw_startup(struct fsi_priv *fsi, + fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); + } + ++ /* ++ * FIXME ++ * ++ * FSI driver assumed that data package is in-back. ++ * FSI2 chip can select it. ++ */ ++ if (fsi_ver >= 2) { ++ fsi_reg_write(fsi, OUT_DMAC, (1 << 4)); ++ fsi_reg_write(fsi, IN_DMAC, (1 << 4)); ++ } ++ + /* irq clear */ + fsi_irq_disable(fsi, is_play); + fsi_irq_clear_status(fsi); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0094-ASoC-Constify-snd_soc_dai_ops-structs.patch b/patches.kzm9g/0094-ASoC-Constify-snd_soc_dai_ops-structs.patch new file mode 100644 index 00000000000000..7e67376df73f57 --- /dev/null +++ b/patches.kzm9g/0094-ASoC-Constify-snd_soc_dai_ops-structs.patch @@ -0,0 +1,169 @@ +From 1b06d3b9ab636321f4563d07584e88193bdbb245 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen <lars@metafoo.de> +Date: Wed, 23 Nov 2011 11:40:40 +0100 +Subject: ASoC: Constify snd_soc_dai_ops structs + +Commit 1ee46ebd("ASoC: Make the DAI ops constant in the DAI structure") +introduced the possibility to have constant DAI ops structures, yet this is +barley used in both existing drivers and also new drivers being submitted, +although none of them modifies its DAI ops structure. The later is not +surprising since existing drivers are often used as templates for new drivers. +So this patch just constifies all existing snd_soc_dai_ops structs to eliminate +the issue altogether. + +The patch was generated with the following coccinelle semantic patch: +// <smpl> +@@ +identifier ops; +@@ +-struct snd_soc_dai_ops ops = ++const struct snd_soc_dai_ops ops = +{ ... }; +// </smpl> + +Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 85e7652d89293a6dab42bfd31f276f8bc072d4c5) + +Commits: + + sound/soc/atmel/atmel_ssc_dai.c + sound/soc/au1x/psc-ac97.c + sound/soc/au1x/psc-i2s.c + sound/soc/blackfin/bf5xx-i2s.c + sound/soc/blackfin/bf5xx-tdm.c + sound/soc/codecs/88pm860x-codec.c + sound/soc/codecs/ac97.c + sound/soc/codecs/ad1836.c + sound/soc/codecs/ad193x.c + sound/soc/codecs/adau1373.c + sound/soc/codecs/adau1701.c + sound/soc/codecs/adav80x.c + sound/soc/codecs/ak4104.c + sound/soc/codecs/ak4535.c + sound/soc/codecs/ak4641.c + sound/soc/codecs/ak4642.c + sound/soc/codecs/ak4671.c + sound/soc/codecs/alc5623.c + sound/soc/codecs/alc5632.c + sound/soc/codecs/cq93vc.c + sound/soc/codecs/cs4270.c + sound/soc/codecs/cs4271.c + sound/soc/codecs/cs42l51.c + sound/soc/codecs/cs42l73.c + sound/soc/codecs/da7210.c + sound/soc/codecs/jz4740.c + sound/soc/codecs/max98088.c + sound/soc/codecs/max98095.c + sound/soc/codecs/max9850.c + sound/soc/codecs/rt5631.c + sound/soc/codecs/sgtl5000.c + sound/soc/codecs/sn95031.c + sound/soc/codecs/ssm2602.c + sound/soc/codecs/sta32x.c + sound/soc/codecs/stac9766.c + sound/soc/codecs/tlv320aic23.c + sound/soc/codecs/tlv320aic26.c + sound/soc/codecs/tlv320aic32x4.c + sound/soc/codecs/tlv320aic3x.c + sound/soc/codecs/tlv320dac33.c + sound/soc/codecs/twl4030.c + sound/soc/codecs/twl6040.c + sound/soc/codecs/uda134x.c + sound/soc/codecs/uda1380.c + sound/soc/codecs/wl1273.c + sound/soc/codecs/wm5100.c + sound/soc/codecs/wm8350.c + sound/soc/codecs/wm8400.c + sound/soc/codecs/wm8510.c + sound/soc/codecs/wm8523.c + sound/soc/codecs/wm8580.c + sound/soc/codecs/wm8711.c + sound/soc/codecs/wm8728.c + sound/soc/codecs/wm8731.c + sound/soc/codecs/wm8737.c + sound/soc/codecs/wm8741.c + sound/soc/codecs/wm8750.c + sound/soc/codecs/wm8753.c + sound/soc/codecs/wm8770.c + sound/soc/codecs/wm8776.c + sound/soc/codecs/wm8804.c + sound/soc/codecs/wm8900.c + sound/soc/codecs/wm8903.c + sound/soc/codecs/wm8904.c + sound/soc/codecs/wm8940.c + sound/soc/codecs/wm8955.c + sound/soc/codecs/wm8960.c + sound/soc/codecs/wm8961.c + sound/soc/codecs/wm8962.c + sound/soc/codecs/wm8971.c + sound/soc/codecs/wm8974.c + sound/soc/codecs/wm8978.c + sound/soc/codecs/wm8983.c + sound/soc/codecs/wm8985.c + sound/soc/codecs/wm8988.c + sound/soc/codecs/wm8990.c + sound/soc/codecs/wm8991.c + sound/soc/codecs/wm8993.c + sound/soc/codecs/wm8994.c + sound/soc/codecs/wm8995.c + sound/soc/codecs/wm8996.c + sound/soc/codecs/wm9081.c + sound/soc/codecs/wm9705.c + sound/soc/codecs/wm9712.c + sound/soc/codecs/wm9713.c + sound/soc/davinci/davinci-i2s.c + sound/soc/davinci/davinci-mcasp.c + sound/soc/davinci/davinci-vcif.c + sound/soc/ep93xx/ep93xx-ac97.c + sound/soc/ep93xx/ep93xx-i2s.c + sound/soc/fsl/fsl_ssi.c + sound/soc/fsl/mpc5200_psc_ac97.c + sound/soc/fsl/mpc5200_psc_i2s.c + sound/soc/imx/imx-ssi.c + sound/soc/jz4740/jz4740-i2s.c + sound/soc/kirkwood/kirkwood-i2s.c + sound/soc/mxs/mxs-saif.c + sound/soc/nuc900/nuc900-ac97.c + sound/soc/omap/ams-delta.c + sound/soc/omap/omap-hdmi.c + sound/soc/omap/omap-mcbsp.c + sound/soc/omap/omap-mcpdm.c + sound/soc/pxa/pxa-ssp.c + sound/soc/pxa/pxa2xx-ac97.c + sound/soc/pxa/pxa2xx-i2s.c + sound/soc/s6000/s6000-i2s.c + sound/soc/samsung/ac97.c + sound/soc/samsung/i2s.c + sound/soc/samsung/pcm.c + sound/soc/samsung/s3c2412-i2s.c + sound/soc/samsung/s3c24xx-i2s.c + sound/soc/samsung/spdif.c + sound/soc/sh/hac.c + sound/soc/sh/siu_dai.c + sound/soc/sh/ssi.c + sound/soc/soc-core.c + sound/soc/tegra/tegra_i2s.c + sound/soc/tegra/tegra_spdif.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 99ed610..aa30330 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1096,7 +1096,7 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, + return ret; + } + +-static struct snd_soc_dai_ops fsi_dai_ops = { ++static const struct snd_soc_dai_ops fsi_dai_ops = { + .startup = fsi_dai_startup, + .shutdown = fsi_dai_shutdown, + .trigger = fsi_dai_trigger, +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0095-ASoC-fsi-ak4642-modify-specification-method-of-FSI-a.patch b/patches.kzm9g/0095-ASoC-fsi-ak4642-modify-specification-method-of-FSI-a.patch new file mode 100644 index 00000000000000..4989859efecccf --- /dev/null +++ b/patches.kzm9g/0095-ASoC-fsi-ak4642-modify-specification-method-of-FSI-a.patch @@ -0,0 +1,272 @@ +From 8d40a58c9d7f03f7545bd01905bbe59ef789230a Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Wed, 23 Nov 2011 16:55:34 -0800 +Subject: ASoC: fsi-ak4642: modify specification method of FSI / ak464x + +Current fsi-ak4642 was using id_entry name in order to specify +FSI port and ak464x codec. +But it was no sense, no flexibility. +Platform can specify FSI/ak464x pair by this patch. + +Acked-by: Paul Mundt <lethal@linux-sh.org> +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 45f3121615b2b354f7d95d30f795bc5fe0043e92) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-ap4evb.c | 15 ++++- + arch/arm/mach-shmobile/board-mackerel.c | 14 +++- + arch/sh/boards/mach-se/7724/setup.c | 14 +++- + include/sound/sh_fsi.h | 12 ++++ + sound/soc/sh/fsi-ak4642.c | 114 +++----------------------------- + 5 files changed, 63 insertions(+), 106 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c +index 3cbf5bf..59f0d2c 100644 +--- a/arch/arm/mach-shmobile/board-ap4evb.c ++++ b/arch/arm/mach-shmobile/board-ap4evb.c +@@ -757,9 +757,22 @@ static struct platform_device fsi_device = { + }, + }; + ++static struct fsi_ak4642_info fsi2_ak4643_info = { ++ .name = "AK4643", ++ .card = "FSI2A-AK4643", ++ .cpu_dai = "fsia-dai", ++ .codec = "ak4642-codec.0-0013", ++ .platform = "sh_fsi2", ++ .id = FSI_PORT_A, ++}; ++ + static struct platform_device fsi_ak4643_device = { +- .name = "sh_fsi2_a_ak4643", ++ .name = "fsi-ak4642-audio", ++ .dev = { ++ .platform_data = &fsi_info, ++ }, + }; ++ + static struct sh_mobile_meram_cfg hdmi_meram_cfg = { + .icb[0] = { + .meram_size = 0x100, +diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c +index 70eca5a..c2faf11 100644 +--- a/arch/arm/mach-shmobile/board-mackerel.c ++++ b/arch/arm/mach-shmobile/board-mackerel.c +@@ -970,8 +970,20 @@ static struct platform_device fsi_device = { + }, + }; + ++static struct fsi_ak4642_info fsi2_ak4643_info = { ++ .name = "AK4643", ++ .card = "FSI2A-AK4643", ++ .cpu_dai = "fsia-dai", ++ .codec = "ak4642-codec.0-0013", ++ .platform = "sh_fsi2", ++ .id = FSI_PORT_A, ++}; ++ + static struct platform_device fsi_ak4643_device = { +- .name = "sh_fsi2_a_ak4643", ++ .name = "fsi-ak4642-audio", ++ .dev = { ++ .platform_data = &fsi2_ak4643_info, ++ }, + }; + + /* +diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c +index 1342feb..abc4d12 100644 +--- a/arch/sh/boards/mach-se/7724/setup.c ++++ b/arch/sh/boards/mach-se/7724/setup.c +@@ -314,8 +314,20 @@ static struct platform_device fsi_device = { + }, + }; + ++static struct fsi_ak4642_info fsi_ak4642_info = { ++ .name = "AK4642", ++ .card = "FSIA-AK4642", ++ .cpu_dai = "fsia-dai", ++ .codec = "ak4642-codec.0-0012", ++ .platform = "sh_fsi.0", ++ .id = FSI_PORT_A, ++}; ++ + static struct platform_device fsi_ak4642_device = { +- .name = "sh_fsi_a_ak4642", ++ .name = "fsi-ak4642-audio", ++ .dev = { ++ .platform_data = &fsi_ak4642_info, ++ }, + }; + + /* KEYSC in SoC (Needs SW33-2 set to ON) */ +diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h +index 9a155f9..9b1aaca 100644 +--- a/include/sound/sh_fsi.h ++++ b/include/sound/sh_fsi.h +@@ -78,4 +78,16 @@ struct sh_fsi_platform_info { + int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); + }; + ++/* ++ * for fsi-ak4642 ++ */ ++struct fsi_ak4642_info { ++ const char *name; ++ const char *card; ++ const char *cpu_dai; ++ const char *codec; ++ const char *platform; ++ int id; ++}; ++ + #endif /* __SOUND_FSI_H */ +diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c +index dff64b9..11d2d7f 100644 +--- a/sound/soc/sh/fsi-ak4642.c ++++ b/sound/soc/sh/fsi-ak4642.c +@@ -58,27 +58,23 @@ static struct platform_device *fsi_snd_device; + static int fsi_ak4642_probe(struct platform_device *pdev) + { + int ret = -ENOMEM; +- const struct platform_device_id *id_entry; +- struct fsi_ak4642_data *pdata; ++ struct fsi_ak4642_info *pinfo = pdev->dev.platform_data; + +- id_entry = pdev->id_entry; +- if (!id_entry) { +- dev_err(&pdev->dev, "unknown fsi ak4642\n"); +- return -ENODEV; ++ if (!pinfo) { ++ dev_err(&pdev->dev, "no info for fsi ak4642\n"); ++ goto out; + } + +- pdata = (struct fsi_ak4642_data *)id_entry->driver_data; +- +- fsi_snd_device = platform_device_alloc("soc-audio", pdata->id); ++ fsi_snd_device = platform_device_alloc("soc-audio", pinfo->id); + if (!fsi_snd_device) + goto out; + +- fsi_dai_link.name = pdata->name; +- fsi_dai_link.stream_name = pdata->name; +- fsi_dai_link.cpu_dai_name = pdata->cpu_dai; +- fsi_dai_link.platform_name = pdata->platform; +- fsi_dai_link.codec_name = pdata->codec; +- fsi_soc_card.name = pdata->card; ++ fsi_dai_link.name = pinfo->name; ++ fsi_dai_link.stream_name = pinfo->name; ++ fsi_dai_link.cpu_dai_name = pinfo->cpu_dai; ++ fsi_dai_link.platform_name = pinfo->platform; ++ fsi_dai_link.codec_name = pinfo->codec; ++ fsi_soc_card.name = pinfo->card; + + platform_set_drvdata(fsi_snd_device, &fsi_soc_card); + ret = platform_device_add(fsi_snd_device); +@@ -96,100 +92,12 @@ static int fsi_ak4642_remove(struct platform_device *pdev) + return 0; + } + +-static struct fsi_ak4642_data fsi_a_ak4642 = { +- .name = "AK4642", +- .card = "FSIA-AK4642", +- .cpu_dai = "fsia-dai", +- .codec = "ak4642-codec.0-0012", +- .platform = "sh_fsi.0", +- .id = FSI_PORT_A, +-}; +- +-static struct fsi_ak4642_data fsi_b_ak4642 = { +- .name = "AK4642", +- .card = "FSIB-AK4642", +- .cpu_dai = "fsib-dai", +- .codec = "ak4642-codec.0-0012", +- .platform = "sh_fsi.0", +- .id = FSI_PORT_B, +-}; +- +-static struct fsi_ak4642_data fsi_a_ak4643 = { +- .name = "AK4643", +- .card = "FSIA-AK4643", +- .cpu_dai = "fsia-dai", +- .codec = "ak4642-codec.0-0013", +- .platform = "sh_fsi.0", +- .id = FSI_PORT_A, +-}; +- +-static struct fsi_ak4642_data fsi_b_ak4643 = { +- .name = "AK4643", +- .card = "FSIB-AK4643", +- .cpu_dai = "fsib-dai", +- .codec = "ak4642-codec.0-0013", +- .platform = "sh_fsi.0", +- .id = FSI_PORT_B, +-}; +- +-static struct fsi_ak4642_data fsi2_a_ak4642 = { +- .name = "AK4642", +- .card = "FSI2A-AK4642", +- .cpu_dai = "fsia-dai", +- .codec = "ak4642-codec.0-0012", +- .platform = "sh_fsi2", +- .id = FSI_PORT_A, +-}; +- +-static struct fsi_ak4642_data fsi2_b_ak4642 = { +- .name = "AK4642", +- .card = "FSI2B-AK4642", +- .cpu_dai = "fsib-dai", +- .codec = "ak4642-codec.0-0012", +- .platform = "sh_fsi2", +- .id = FSI_PORT_B, +-}; +- +-static struct fsi_ak4642_data fsi2_a_ak4643 = { +- .name = "AK4643", +- .card = "FSI2A-AK4643", +- .cpu_dai = "fsia-dai", +- .codec = "ak4642-codec.0-0013", +- .platform = "sh_fsi2", +- .id = FSI_PORT_A, +-}; +- +-static struct fsi_ak4642_data fsi2_b_ak4643 = { +- .name = "AK4643", +- .card = "FSI2B-AK4643", +- .cpu_dai = "fsib-dai", +- .codec = "ak4642-codec.0-0013", +- .platform = "sh_fsi2", +- .id = FSI_PORT_B, +-}; +- +-static struct platform_device_id fsi_id_table[] = { +- /* FSI */ +- { "sh_fsi_a_ak4642", (kernel_ulong_t)&fsi_a_ak4642 }, +- { "sh_fsi_b_ak4642", (kernel_ulong_t)&fsi_b_ak4642 }, +- { "sh_fsi_a_ak4643", (kernel_ulong_t)&fsi_a_ak4643 }, +- { "sh_fsi_b_ak4643", (kernel_ulong_t)&fsi_b_ak4643 }, +- +- /* FSI 2 */ +- { "sh_fsi2_a_ak4642", (kernel_ulong_t)&fsi2_a_ak4642 }, +- { "sh_fsi2_b_ak4642", (kernel_ulong_t)&fsi2_b_ak4642 }, +- { "sh_fsi2_a_ak4643", (kernel_ulong_t)&fsi2_a_ak4643 }, +- { "sh_fsi2_b_ak4643", (kernel_ulong_t)&fsi2_b_ak4643 }, +- {}, +-}; +- + static struct platform_driver fsi_ak4642 = { + .driver = { + .name = "fsi-ak4642-audio", + }, + .probe = fsi_ak4642_probe, + .remove = fsi_ak4642_remove, +- .id_table = fsi_id_table, + }; + + static int __init fsi_ak4642_init(void) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0096-ASoC-Convert-sh-directory-to-module_platform_driver.patch b/patches.kzm9g/0096-ASoC-Convert-sh-directory-to-module_platform_driver.patch new file mode 100644 index 00000000000000..2d3ef26867c324 --- /dev/null +++ b/patches.kzm9g/0096-ASoC-Convert-sh-directory-to-module_platform_driver.patch @@ -0,0 +1,100 @@ +From 2233778f0f0d254f7583d8de6e7e2a0cdacd828a Mon Sep 17 00:00:00 2001 +From: Axel Lin <axel.lin@gmail.com> +Date: Fri, 25 Nov 2011 10:15:07 +0800 +Subject: ASoC: Convert sh directory to module_platform_driver + +Factor out some boilerplate code. + +Signed-off-by: Axel Lin <axel.lin@gmail.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit cb5e87387cfa8172faca36682e2df069b006efdf) + +Conflicts: + + sound/soc/sh/dma-sh7760.c + sound/soc/sh/hac.c + sound/soc/sh/siu_dai.c + sound/soc/sh/ssi.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi-ak4642.c | 13 +------------ + sound/soc/sh/fsi-hdmi.c | 13 +------------ + sound/soc/sh/fsi.c | 13 +------------ + 3 files changed, 3 insertions(+), 36 deletions(-) + +diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c +index 11d2d7f..eb52778 100644 +--- a/sound/soc/sh/fsi-ak4642.c ++++ b/sound/soc/sh/fsi-ak4642.c +@@ -100,18 +100,7 @@ static struct platform_driver fsi_ak4642 = { + .remove = fsi_ak4642_remove, + }; + +-static int __init fsi_ak4642_init(void) +-{ +- return platform_driver_register(&fsi_ak4642); +-} +- +-static void __exit fsi_ak4642_exit(void) +-{ +- platform_driver_unregister(&fsi_ak4642); +-} +- +-module_init(fsi_ak4642_init); +-module_exit(fsi_ak4642_exit); ++module_platform_driver(fsi_ak4642); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card"); +diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c +index d3d9fd8..31c4806 100644 +--- a/sound/soc/sh/fsi-hdmi.c ++++ b/sound/soc/sh/fsi-hdmi.c +@@ -109,18 +109,7 @@ static struct platform_driver fsi_hdmi = { + .id_table = fsi_id_table, + }; + +-static int __init fsi_hdmi_init(void) +-{ +- return platform_driver_register(&fsi_hdmi); +-} +- +-static void __exit fsi_hdmi_exit(void) +-{ +- platform_driver_unregister(&fsi_hdmi); +-} +- +-module_init(fsi_hdmi_init); +-module_exit(fsi_hdmi_exit); ++module_platform_driver(fsi_hdmi); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card"); +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index aa30330..a27c306 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1468,18 +1468,7 @@ static struct platform_driver fsi_driver = { + .id_table = fsi_id_table, + }; + +-static int __init fsi_mobile_init(void) +-{ +- return platform_driver_register(&fsi_driver); +-} +- +-static void __exit fsi_mobile_exit(void) +-{ +- platform_driver_unregister(&fsi_driver); +-} +- +-module_init(fsi_mobile_init); +-module_exit(fsi_mobile_exit); ++module_platform_driver(fsi_driver); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SuperH onchip FSI audio driver"); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0097-ASoC-Use-core-pm_runtime-callbacks-for-fsi.patch b/patches.kzm9g/0097-ASoC-Use-core-pm_runtime-callbacks-for-fsi.patch new file mode 100644 index 00000000000000..73ea9f9eb091b1 --- /dev/null +++ b/patches.kzm9g/0097-ASoC-Use-core-pm_runtime-callbacks-for-fsi.patch @@ -0,0 +1,41 @@ +From 8ed88c1062c61083442b13d3a30c68594fe8e8bb Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@opensource.wolfsonmicro.com> +Date: Sat, 3 Dec 2011 20:22:18 +0000 +Subject: ASoC: Use core pm_runtime callbacks for fsi + +Now that the core holds a pm_runtime reference to the device while the +link is active there is no need for the driver to do so. + +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 27f478a65ff7b67b843250f0a2d1e8b306bf57b6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index a27c306..db6c89a 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -893,8 +893,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi, + u32 flags = fsi_get_info_flags(fsi); + u32 data = 0; + +- pm_runtime_get_sync(dev); +- + /* clock setting */ + if (fsi_is_clk_master(fsi)) + data = DIMD | DOMD; +@@ -951,8 +949,6 @@ static void fsi_hw_shutdown(struct fsi_priv *fsi, + { + if (fsi_is_clk_master(fsi)) + fsi_set_master_clk(dev, fsi, fsi->rate, 0); +- +- pm_runtime_put_sync(dev); + } + + static int fsi_dai_startup(struct snd_pcm_substream *substream, +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0098-ASoC-sh-Add-.owner-to-struct-snd_soc_card.patch b/patches.kzm9g/0098-ASoC-sh-Add-.owner-to-struct-snd_soc_card.patch new file mode 100644 index 00000000000000..202ef0fdaad866 --- /dev/null +++ b/patches.kzm9g/0098-ASoC-sh-Add-.owner-to-struct-snd_soc_card.patch @@ -0,0 +1,67 @@ +From 5b12148992d0314cb7380b8112fda136fdfcea21 Mon Sep 17 00:00:00 2001 +From: Axel Lin <axel.lin@gmail.com> +Date: Fri, 23 Dec 2011 14:53:32 +0800 +Subject: ASoC: sh: Add .owner to struct snd_soc_card +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add missing .owner of struct snd_soc_card. This prevents the module from being +removed from underneath its users. + +Reported-by: Lothar Waßmann <LW@KARO-electronics.de> +Signed-off-by: Axel Lin <axel.lin@gmail.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 4a7042e59908231fc046aac88bd98454d886052d) + +Conflicts: + + sound/soc/sh/migor.c + sound/soc/sh/sh7760-ac97.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi-ak4642.c | 1 + + sound/soc/sh/fsi-da7210.c | 1 + + sound/soc/sh/fsi-hdmi.c | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c +index eb52778..97f540a 100644 +--- a/sound/soc/sh/fsi-ak4642.c ++++ b/sound/soc/sh/fsi-ak4642.c +@@ -49,6 +49,7 @@ static struct snd_soc_dai_link fsi_dai_link = { + }; + + static struct snd_soc_card fsi_soc_card = { ++ .owner = THIS_MODULE, + .dai_link = &fsi_dai_link, + .num_links = 1, + }; +diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c +index f5586b5b..1dd3354 100644 +--- a/sound/soc/sh/fsi-da7210.c ++++ b/sound/soc/sh/fsi-da7210.c +@@ -44,6 +44,7 @@ static struct snd_soc_dai_link fsi_da7210_dai = { + + static struct snd_soc_card fsi_soc_card = { + .name = "FSI-DA7210", ++ .owner = THIS_MODULE, + .dai_link = &fsi_da7210_dai, + .num_links = 1, + }; +diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c +index 31c4806..edb4359 100644 +--- a/sound/soc/sh/fsi-hdmi.c ++++ b/sound/soc/sh/fsi-hdmi.c +@@ -38,6 +38,7 @@ static struct snd_soc_dai_link fsi_dai_link = { + }; + + static struct snd_soc_card fsi_soc_card = { ++ .owner = THIS_MODULE, + .dai_link = &fsi_dai_link, + .num_links = 1, + }; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0099-ASoC-fsi-Remove-unneeded-empty-runtime-PM-callbacks.patch b/patches.kzm9g/0099-ASoC-fsi-Remove-unneeded-empty-runtime-PM-callbacks.patch new file mode 100644 index 00000000000000..17080d74156a09 --- /dev/null +++ b/patches.kzm9g/0099-ASoC-fsi-Remove-unneeded-empty-runtime-PM-callbacks.patch @@ -0,0 +1,47 @@ +From 9d4fdf34b1a908b8e82f8eaede7368f5a7eaed49 Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@opensource.wolfsonmicro.com> +Date: Wed, 25 Jan 2012 19:55:56 +0000 +Subject: ASoC: fsi: Remove unneeded empty runtime PM callbacks + +The runtime PM core no longer requires any callbacks so don't provide +empty ones for it any more. + +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit bc122e34469de6ec4b7ca96d3a41724f9e4b1cf4) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index db6c89a..3241e5b 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1408,23 +1408,9 @@ static int fsi_resume(struct device *dev) + return 0; + } + +-static int fsi_runtime_nop(struct device *dev) +-{ +- /* Runtime PM callback shared between ->runtime_suspend() +- * and ->runtime_resume(). Simply returns success. +- * +- * This driver re-initializes all registers after +- * pm_runtime_get_sync() anyway so there is no need +- * to save and restore registers here. +- */ +- return 0; +-} +- + static struct dev_pm_ops fsi_pm_ops = { + .suspend = fsi_suspend, + .resume = fsi_resume, +- .runtime_suspend = fsi_runtime_nop, +- .runtime_resume = fsi_runtime_nop, + }; + + static struct fsi_core fsi1_core = { +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0100-ASoC-fsi-reduce-runtime-calculation-by-using-pre-set.patch b/patches.kzm9g/0100-ASoC-fsi-reduce-runtime-calculation-by-using-pre-set.patch new file mode 100644 index 00000000000000..efef18df2ab60d --- /dev/null +++ b/patches.kzm9g/0100-ASoC-fsi-reduce-runtime-calculation-by-using-pre-set.patch @@ -0,0 +1,81 @@ +From cb292ccc4561167afa92984b935da321e74f7b6c Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:50:09 -0800 +Subject: ASoC: fsi: reduce runtime calculation by using pre-setting + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit c1e6f10ea94715f00cce4c9aaf7fc91fb34ec52d) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 3241e5b..0d78740 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -167,6 +167,7 @@ struct fsi_stream { + int buff_sample_pos; /* sample position of ALSA buffer */ + int period_samples; /* sample number / 1 period */ + int period_pos; /* current period position */ ++ int sample_width; /* sample width */ + + int uerr_num; + int oerr_num; +@@ -406,6 +407,7 @@ static void fsi_stream_push(struct fsi_priv *fsi, + io->buff_sample_pos = 0; + io->period_samples = fsi_frame2sample(fsi, runtime->period_size); + io->period_pos = 0; ++ io->sample_width = samples_to_bytes(runtime, 1); + io->oerr_num = -1; /* ignore 1st err */ + io->uerr_num = -1; /* ignore 1st err */ + spin_unlock_irqrestore(&master->lock, flags); +@@ -431,6 +433,7 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) + io->buff_sample_pos = 0; + io->period_samples = 0; + io->period_pos = 0; ++ io->sample_width = 0; + io->oerr_num = 0; + io->uerr_num = 0; + spin_unlock_irqrestore(&master->lock, flags); +@@ -752,7 +755,6 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + int is_play = fsi_stream_is_play(stream); + struct fsi_stream *io = fsi_get_stream(fsi, is_play); + int sample_residues; +- int sample_width; + int samples; + int samples_max; + int over_period; +@@ -780,9 +782,6 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + io->buff_sample_pos = 0; + } + +- /* get 1 sample data width */ +- sample_width = samples_to_bytes(runtime, 1); +- + /* get number of residue samples */ + sample_residues = io->buff_sample_capa - io->buff_sample_pos; + +@@ -798,7 +797,7 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + + samples = sample_residues; + +- switch (sample_width) { ++ switch (io->sample_width) { + case 2: + fn = fsi_dma_soft_push16; + break; +@@ -818,7 +817,7 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + samples_max = sample_residues; + samples = fsi_get_current_fifo_samples(fsi, is_play); + +- switch (sample_width) { ++ switch (io->sample_width) { + case 2: + fn = fsi_dma_soft_pop16; + break; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0101-ASoC-fsi-tidyup-fsi_stream_xx-functions-were-gathere.patch b/patches.kzm9g/0101-ASoC-fsi-tidyup-fsi_stream_xx-functions-were-gathere.patch new file mode 100644 index 00000000000000..9424b5e2f2a430 --- /dev/null +++ b/patches.kzm9g/0101-ASoC-fsi-tidyup-fsi_stream_xx-functions-were-gathere.patch @@ -0,0 +1,204 @@ +From 679d4975b9babdd83189da8b5f5d90f1a60a84d0 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:50:35 -0800 +Subject: ASoC: fsi: tidyup: fsi_stream_xx() functions were gathered + +This patch gathered fsi_stream_xxx() functions in order to make it readable. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 4e62d84d9da5190c303d6408180fbfee414d25bc) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 115 ++++++++++++++++++++++++++--------------------------- + 1 file changed, 57 insertions(+), 58 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 0d78740..162416e 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -338,22 +338,6 @@ static u32 fsi_get_info_flags(struct fsi_priv *fsi) + master->info->portb_flags; + } + +-static inline int fsi_stream_is_play(int stream) +-{ +- return stream == SNDRV_PCM_STREAM_PLAYBACK; +-} +- +-static inline int fsi_is_play(struct snd_pcm_substream *substream) +-{ +- return fsi_stream_is_play(substream->stream); +-} +- +-static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi, +- int is_play) +-{ +- return is_play ? &fsi->playback : &fsi->capture; +-} +- + static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) + { + int is_porta = fsi_is_port_a(fsi); +@@ -377,10 +361,60 @@ static int fsi_sample2frame(struct fsi_priv *fsi, int samples) + return samples / fsi->chan_num; + } + ++static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play) ++{ ++ u32 status; ++ int frames; ++ ++ status = is_play ? ++ fsi_reg_read(fsi, DOFF_ST) : ++ fsi_reg_read(fsi, DIFF_ST); ++ ++ frames = 0x1ff & (status >> 8); ++ ++ return fsi_frame2sample(fsi, frames); ++} ++ ++static void fsi_count_fifo_err(struct fsi_priv *fsi) ++{ ++ u32 ostatus = fsi_reg_read(fsi, DOFF_ST); ++ u32 istatus = fsi_reg_read(fsi, DIFF_ST); ++ ++ if (ostatus & ERR_OVER) ++ fsi->playback.oerr_num++; ++ ++ if (ostatus & ERR_UNDER) ++ fsi->playback.uerr_num++; ++ ++ if (istatus & ERR_OVER) ++ fsi->capture.oerr_num++; ++ ++ if (istatus & ERR_UNDER) ++ fsi->capture.uerr_num++; ++ ++ fsi_reg_write(fsi, DOFF_ST, 0); ++ fsi_reg_write(fsi, DIFF_ST, 0); ++} ++ ++/* ++ * fsi_stream_xx() function ++ */ ++#define fsi_is_play(substream) fsi_stream_is_play(substream->stream) ++static inline int fsi_stream_is_play(int stream) ++{ ++ return stream == SNDRV_PCM_STREAM_PLAYBACK; ++} ++ ++static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi, ++ int is_play) ++{ ++ return is_play ? &fsi->playback : &fsi->capture; ++} ++ + static int fsi_stream_is_working(struct fsi_priv *fsi, + int is_play) + { +- struct fsi_stream *io = fsi_get_stream(fsi, is_play); ++ struct fsi_stream *io = fsi_stream_get(fsi, is_play); + struct fsi_master *master = fsi_get_master(fsi); + unsigned long flags; + int ret; +@@ -396,7 +430,7 @@ static void fsi_stream_push(struct fsi_priv *fsi, + int is_play, + struct snd_pcm_substream *substream) + { +- struct fsi_stream *io = fsi_get_stream(fsi, is_play); ++ struct fsi_stream *io = fsi_stream_get(fsi, is_play); + struct snd_pcm_runtime *runtime = substream->runtime; + struct fsi_master *master = fsi_get_master(fsi); + unsigned long flags; +@@ -415,7 +449,7 @@ static void fsi_stream_push(struct fsi_priv *fsi, + + static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) + { +- struct fsi_stream *io = fsi_get_stream(fsi, is_play); ++ struct fsi_stream *io = fsi_stream_get(fsi, is_play); + struct snd_soc_dai *dai = fsi_get_dai(io->substream); + struct fsi_master *master = fsi_get_master(fsi); + unsigned long flags; +@@ -439,41 +473,6 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) + spin_unlock_irqrestore(&master->lock, flags); + } + +-static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play) +-{ +- u32 status; +- int frames; +- +- status = is_play ? +- fsi_reg_read(fsi, DOFF_ST) : +- fsi_reg_read(fsi, DIFF_ST); +- +- frames = 0x1ff & (status >> 8); +- +- return fsi_frame2sample(fsi, frames); +-} +- +-static void fsi_count_fifo_err(struct fsi_priv *fsi) +-{ +- u32 ostatus = fsi_reg_read(fsi, DOFF_ST); +- u32 istatus = fsi_reg_read(fsi, DIFF_ST); +- +- if (ostatus & ERR_OVER) +- fsi->playback.oerr_num++; +- +- if (ostatus & ERR_UNDER) +- fsi->playback.uerr_num++; +- +- if (istatus & ERR_OVER) +- fsi->capture.oerr_num++; +- +- if (istatus & ERR_UNDER) +- fsi->capture.uerr_num++; +- +- fsi_reg_write(fsi, DOFF_ST, 0); +- fsi_reg_write(fsi, DIFF_ST, 0); +-} +- + /* + * dma function + */ +@@ -481,7 +480,7 @@ static void fsi_count_fifo_err(struct fsi_priv *fsi) + static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream) + { + int is_play = fsi_stream_is_play(stream); +- struct fsi_stream *io = fsi_get_stream(fsi, is_play); ++ struct fsi_stream *io = fsi_stream_get(fsi, is_play); + struct snd_pcm_runtime *runtime = io->substream->runtime; + + return runtime->dma_area + +@@ -698,7 +697,7 @@ static void fsi_fifo_init(struct fsi_priv *fsi, + struct device *dev) + { + struct fsi_master *master = fsi_get_master(fsi); +- struct fsi_stream *io = fsi_get_stream(fsi, is_play); ++ struct fsi_stream *io = fsi_stream_get(fsi, is_play); + u32 shift, i; + int frame_capa; + +@@ -753,7 +752,7 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + struct snd_pcm_runtime *runtime; + struct snd_pcm_substream *substream = NULL; + int is_play = fsi_stream_is_play(stream); +- struct fsi_stream *io = fsi_get_stream(fsi, is_play); ++ struct fsi_stream *io = fsi_stream_get(fsi, is_play); + int sample_residues; + int samples; + int samples_max; +@@ -1150,7 +1149,7 @@ static int fsi_hw_free(struct snd_pcm_substream *substream) + static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) + { + struct fsi_priv *fsi = fsi_get_priv(substream); +- struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream)); ++ struct fsi_stream *io = fsi_stream_get(fsi, fsi_is_play(substream)); + int samples_pos = io->buff_sample_pos - 1; + + if (samples_pos < 0) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0102-ASoC-fsi-data-push-pop-calculation-part-was-divided.patch b/patches.kzm9g/0102-ASoC-fsi-data-push-pop-calculation-part-was-divided.patch new file mode 100644 index 00000000000000..e675f10253a609 --- /dev/null +++ b/patches.kzm9g/0102-ASoC-fsi-data-push-pop-calculation-part-was-divided.patch @@ -0,0 +1,159 @@ +From 3e4950e7f7503851e01dbdf5547513567442ac56 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:50:59 -0800 +Subject: ASoC: fsi: data push/pop calculation part was divided + +Next transfer data size of "push" and "pop" had calculated on shared function. +But it was not readable code. +This patch divided it into for push, and for pop. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 376cf38a90507f82d22b951b7776557aefe6109c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 104 +++++++++++++++++++++++------------------------------ + 1 file changed, 45 insertions(+), 59 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 162416e..cbb5643 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -747,17 +747,14 @@ static void fsi_fifo_init(struct fsi_priv *fsi, + } + } + +-static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) ++static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, struct fsi_stream *io, ++ void (*run16)(struct fsi_priv *fsi, int size), ++ void (*run32)(struct fsi_priv *fsi, int size), ++ int samples) + { + struct snd_pcm_runtime *runtime; +- struct snd_pcm_substream *substream = NULL; +- int is_play = fsi_stream_is_play(stream); +- struct fsi_stream *io = fsi_stream_get(fsi, is_play); +- int sample_residues; +- int samples; +- int samples_max; ++ struct snd_pcm_substream *substream; + int over_period; +- void (*fn)(struct fsi_priv *fsi, int size); + + if (!fsi || + !io->substream || +@@ -781,57 +778,17 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + io->buff_sample_pos = 0; + } + +- /* get number of residue samples */ +- sample_residues = io->buff_sample_capa - io->buff_sample_pos; +- +- if (is_play) { +- /* +- * for play-back +- * +- * samples_max : number of FSI fifo free samples space +- * samples : number of ALSA residue samples +- */ +- samples_max = io->fifo_sample_capa; +- samples_max -= fsi_get_current_fifo_samples(fsi, is_play); +- +- samples = sample_residues; +- +- switch (io->sample_width) { +- case 2: +- fn = fsi_dma_soft_push16; +- break; +- case 4: +- fn = fsi_dma_soft_push32; +- break; +- default: +- return -EINVAL; +- } +- } else { +- /* +- * for capture +- * +- * samples_max : number of ALSA free samples space +- * samples : number of samples in FSI fifo +- */ +- samples_max = sample_residues; +- samples = fsi_get_current_fifo_samples(fsi, is_play); +- +- switch (io->sample_width) { +- case 2: +- fn = fsi_dma_soft_pop16; +- break; +- case 4: +- fn = fsi_dma_soft_pop32; +- break; +- default: +- return -EINVAL; +- } ++ switch (io->sample_width) { ++ case 2: ++ run16(fsi, samples); ++ break; ++ case 4: ++ run32(fsi, samples); ++ break; ++ default: ++ return -EINVAL; + } + +- samples = min(samples, samples_max); +- +- fn(fsi, samples); +- + /* update buff_sample_pos */ + io->buff_sample_pos += samples; + +@@ -843,12 +800,41 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) + + static int fsi_data_pop(struct fsi_priv *fsi) + { +- return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_CAPTURE); ++ int is_play = fsi_stream_is_play(SNDRV_PCM_STREAM_CAPTURE); ++ int sample_residues; /* samples in FSI fifo */ ++ int sample_space; /* ALSA free samples space */ ++ int samples; ++ struct fsi_stream *io = fsi_stream_get(fsi, is_play); ++ ++ sample_residues = fsi_get_current_fifo_samples(fsi, is_play); ++ sample_space = io->buff_sample_capa - io->buff_sample_pos; ++ ++ samples = min(sample_residues, sample_space); ++ ++ return fsi_fifo_data_ctrl(fsi, io, ++ fsi_dma_soft_pop16, ++ fsi_dma_soft_pop32, ++ samples); + } + + static int fsi_data_push(struct fsi_priv *fsi) + { +- return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_PLAYBACK); ++ int is_play = fsi_stream_is_play(SNDRV_PCM_STREAM_PLAYBACK); ++ int sample_residues; /* ALSA residue samples */ ++ int sample_space; /* FSI fifo free samples space */ ++ int samples; ++ struct fsi_stream *io = fsi_stream_get(fsi, is_play); ++ ++ sample_residues = io->buff_sample_capa - io->buff_sample_pos; ++ sample_space = io->fifo_sample_capa - ++ fsi_get_current_fifo_samples(fsi, is_play); ++ ++ samples = min(sample_residues, sample_space); ++ ++ return fsi_fifo_data_ctrl(fsi, io, ++ fsi_dma_soft_push16, ++ fsi_dma_soft_push32, ++ samples); + } + + static irqreturn_t fsi_interrupt(int irq, void *data) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0103-ASoC-fsi-rename-fsi_dma_soft_xxx-to-fsi_pio_xxx.patch b/patches.kzm9g/0103-ASoC-fsi-rename-fsi_dma_soft_xxx-to-fsi_pio_xxx.patch new file mode 100644 index 00000000000000..e41eb638bfa5cf --- /dev/null +++ b/patches.kzm9g/0103-ASoC-fsi-rename-fsi_dma_soft_xxx-to-fsi_pio_xxx.patch @@ -0,0 +1,114 @@ +From ed808e04615f0b7e7ac019974418b8d32af510de Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:51:14 -0800 +Subject: ASoC: fsi: rename fsi_dma_soft_xxx() to fsi_pio_xxx() + +This is preparation for DMAEngine support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit d78629e2a4457149bd21fdb0cdbbb1c3ec019d96) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index cbb5643..05307ac 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -474,10 +474,10 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) + } + + /* +- * dma function ++ * pio function + */ + +-static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream) ++static u8 *fsi_pio_get_area(struct fsi_priv *fsi, int stream) + { + int is_play = fsi_stream_is_play(stream); + struct fsi_stream *io = fsi_stream_get(fsi, is_play); +@@ -487,47 +487,47 @@ static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream) + samples_to_bytes(runtime, io->buff_sample_pos); + } + +-static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num) ++static void fsi_pio_push16(struct fsi_priv *fsi, int num) + { + u16 *start; + int i; + +- start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK); ++ start = (u16 *)fsi_pio_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK); + + for (i = 0; i < num; i++) + fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8)); + } + +-static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int num) ++static void fsi_pio_pop16(struct fsi_priv *fsi, int num) + { + u16 *start; + int i; + +- start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE); ++ start = (u16 *)fsi_pio_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE); + + + for (i = 0; i < num; i++) + *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8); + } + +-static void fsi_dma_soft_push32(struct fsi_priv *fsi, int num) ++static void fsi_pio_push32(struct fsi_priv *fsi, int num) + { + u32 *start; + int i; + +- start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK); ++ start = (u32 *)fsi_pio_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK); + + + for (i = 0; i < num; i++) + fsi_reg_write(fsi, DODT, *(start + i)); + } + +-static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int num) ++static void fsi_pio_pop32(struct fsi_priv *fsi, int num) + { + u32 *start; + int i; + +- start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE); ++ start = (u32 *)fsi_pio_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE); + + for (i = 0; i < num; i++) + *(start + i) = fsi_reg_read(fsi, DIDT); +@@ -812,8 +812,8 @@ static int fsi_data_pop(struct fsi_priv *fsi) + samples = min(sample_residues, sample_space); + + return fsi_fifo_data_ctrl(fsi, io, +- fsi_dma_soft_pop16, +- fsi_dma_soft_pop32, ++ fsi_pio_pop16, ++ fsi_pio_pop32, + samples); + } + +@@ -832,8 +832,8 @@ static int fsi_data_push(struct fsi_priv *fsi) + samples = min(sample_residues, sample_space); + + return fsi_fifo_data_ctrl(fsi, io, +- fsi_dma_soft_push16, +- fsi_dma_soft_push32, ++ fsi_pio_push16, ++ fsi_pio_push32, + samples); + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0104-ASoC-fsi-tidyup-move-fsi_fifo_init-onto-fsi_hw_start.patch b/patches.kzm9g/0104-ASoC-fsi-tidyup-move-fsi_fifo_init-onto-fsi_hw_start.patch new file mode 100644 index 00000000000000..4d8d3d2e539940 --- /dev/null +++ b/patches.kzm9g/0104-ASoC-fsi-tidyup-move-fsi_fifo_init-onto-fsi_hw_start.patch @@ -0,0 +1,146 @@ +From 4960931dddb3441619911b0fc1913646252466f0 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:51:29 -0800 +Subject: ASoC: fsi: tidyup: move fsi_fifo_init() onto fsi_hw_startup() + +fsi_fifo_init() is called only from fsi_hw_startup() + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit b49e8027810b674dc0bf0ba3d629c5fae52d78f3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 109 ++++++++++++++++++++++++++--------------------------- + 1 file changed, 54 insertions(+), 55 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 05307ac..79485ed 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -692,61 +692,6 @@ static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable) + /* + * ctrl function + */ +-static void fsi_fifo_init(struct fsi_priv *fsi, +- int is_play, +- struct device *dev) +-{ +- struct fsi_master *master = fsi_get_master(fsi); +- struct fsi_stream *io = fsi_stream_get(fsi, is_play); +- u32 shift, i; +- int frame_capa; +- +- /* get on-chip RAM capacity */ +- shift = fsi_master_read(master, FIFO_SZ); +- shift >>= fsi_get_port_shift(fsi, is_play); +- shift &= FIFO_SZ_MASK; +- frame_capa = 256 << shift; +- dev_dbg(dev, "fifo = %d words\n", frame_capa); +- +- /* +- * The maximum number of sample data varies depending +- * on the number of channels selected for the format. +- * +- * FIFOs are used in 4-channel units in 3-channel mode +- * and in 8-channel units in 5- to 7-channel mode +- * meaning that more FIFOs than the required size of DPRAM +- * are used. +- * +- * ex) if 256 words of DP-RAM is connected +- * 1 channel: 256 (256 x 1 = 256) +- * 2 channels: 128 (128 x 2 = 256) +- * 3 channels: 64 ( 64 x 3 = 192) +- * 4 channels: 64 ( 64 x 4 = 256) +- * 5 channels: 32 ( 32 x 5 = 160) +- * 6 channels: 32 ( 32 x 6 = 192) +- * 7 channels: 32 ( 32 x 7 = 224) +- * 8 channels: 32 ( 32 x 8 = 256) +- */ +- for (i = 1; i < fsi->chan_num; i <<= 1) +- frame_capa >>= 1; +- dev_dbg(dev, "%d channel %d store\n", +- fsi->chan_num, frame_capa); +- +- io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa); +- +- /* +- * set interrupt generation factor +- * clear FIFO +- */ +- if (is_play) { +- fsi_reg_write(fsi, DOFF_CTL, IRQ_HALF); +- fsi_reg_mask_set(fsi, DOFF_CTL, FIFO_CLR, FIFO_CLR); +- } else { +- fsi_reg_write(fsi, DIFF_CTL, IRQ_HALF); +- fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR); +- } +-} +- + static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, struct fsi_stream *io, + void (*run16)(struct fsi_priv *fsi, int size), + void (*run32)(struct fsi_priv *fsi, int size), +@@ -867,6 +812,60 @@ static irqreturn_t fsi_interrupt(int irq, void *data) + /* + * dai ops + */ ++static void fsi_fifo_init(struct fsi_priv *fsi, ++ int is_play, ++ struct device *dev) ++{ ++ struct fsi_master *master = fsi_get_master(fsi); ++ struct fsi_stream *io = fsi_stream_get(fsi, is_play); ++ u32 shift, i; ++ int frame_capa; ++ ++ /* get on-chip RAM capacity */ ++ shift = fsi_master_read(master, FIFO_SZ); ++ shift >>= fsi_get_port_shift(fsi, is_play); ++ shift &= FIFO_SZ_MASK; ++ frame_capa = 256 << shift; ++ dev_dbg(dev, "fifo = %d words\n", frame_capa); ++ ++ /* ++ * The maximum number of sample data varies depending ++ * on the number of channels selected for the format. ++ * ++ * FIFOs are used in 4-channel units in 3-channel mode ++ * and in 8-channel units in 5- to 7-channel mode ++ * meaning that more FIFOs than the required size of DPRAM ++ * are used. ++ * ++ * ex) if 256 words of DP-RAM is connected ++ * 1 channel: 256 (256 x 1 = 256) ++ * 2 channels: 128 (128 x 2 = 256) ++ * 3 channels: 64 ( 64 x 3 = 192) ++ * 4 channels: 64 ( 64 x 4 = 256) ++ * 5 channels: 32 ( 32 x 5 = 160) ++ * 6 channels: 32 ( 32 x 6 = 192) ++ * 7 channels: 32 ( 32 x 7 = 224) ++ * 8 channels: 32 ( 32 x 8 = 256) ++ */ ++ for (i = 1; i < fsi->chan_num; i <<= 1) ++ frame_capa >>= 1; ++ dev_dbg(dev, "%d channel %d store\n", ++ fsi->chan_num, frame_capa); ++ ++ io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa); ++ ++ /* ++ * set interrupt generation factor ++ * clear FIFO ++ */ ++ if (is_play) { ++ fsi_reg_write(fsi, DOFF_CTL, IRQ_HALF); ++ fsi_reg_mask_set(fsi, DOFF_CTL, FIFO_CLR, FIFO_CLR); ++ } else { ++ fsi_reg_write(fsi, DIFF_CTL, IRQ_HALF); ++ fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR); ++ } ++} + + static int fsi_hw_startup(struct fsi_priv *fsi, + int is_play, +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0105-ASoC-fsi-remove-unnecessary-parameter-from-fsi_hw_sh.patch b/patches.kzm9g/0105-ASoC-fsi-remove-unnecessary-parameter-from-fsi_hw_sh.patch new file mode 100644 index 00000000000000..148b9f44361e29 --- /dev/null +++ b/patches.kzm9g/0105-ASoC-fsi-remove-unnecessary-parameter-from-fsi_hw_sh.patch @@ -0,0 +1,51 @@ +From 6e68b51cdc84f44faaaa97ca596a1c88260b89d8 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:51:53 -0800 +Subject: ASoC: fsi: remove unnecessary parameter from fsi_hw_shutdown() + +This is preparation for DMAEngine support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 41bba151939e21e21d18f7df005ce3a06714a69a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 79485ed..a0a9c36 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -927,7 +927,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi, + } + + static void fsi_hw_shutdown(struct fsi_priv *fsi, +- int is_play, + struct device *dev) + { + if (fsi_is_clk_master(fsi)) +@@ -947,9 +946,8 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { + struct fsi_priv *fsi = fsi_get_priv(substream); +- int is_play = fsi_is_play(substream); + +- fsi_hw_shutdown(fsi, is_play, dai->dev); ++ fsi_hw_shutdown(fsi, dai->dev); + fsi->rate = 0; + } + +@@ -1342,7 +1340,7 @@ static void __fsi_suspend(struct fsi_priv *fsi, + return; + + fsi_port_stop(fsi, is_play); +- fsi_hw_shutdown(fsi, is_play, dev); ++ fsi_hw_shutdown(fsi, dev); + } + + static void __fsi_resume(struct fsi_priv *fsi, +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0106-ASoC-fsi-rename-fsi_stream_push-pop-to-fsi_stream_in.patch b/patches.kzm9g/0106-ASoC-fsi-rename-fsi_stream_push-pop-to-fsi_stream_in.patch new file mode 100644 index 00000000000000..2da6f9f51d8d90 --- /dev/null +++ b/patches.kzm9g/0106-ASoC-fsi-rename-fsi_stream_push-pop-to-fsi_stream_in.patch @@ -0,0 +1,57 @@ +From 8c2feb4527500fa4c1cc1f060fb73985b18a5969 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:52:07 -0800 +Subject: ASoC: fsi: rename fsi_stream_push/pop() to fsi_stream_init/quit() + +This is preparation for DMAEngine support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 8c4152951cab90b52406afc72b62e9590bbe2d85) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index a0a9c36..2e2663b 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -426,7 +426,7 @@ static int fsi_stream_is_working(struct fsi_priv *fsi, + return ret; + } + +-static void fsi_stream_push(struct fsi_priv *fsi, ++static void fsi_stream_init(struct fsi_priv *fsi, + int is_play, + struct snd_pcm_substream *substream) + { +@@ -447,7 +447,7 @@ static void fsi_stream_push(struct fsi_priv *fsi, + spin_unlock_irqrestore(&master->lock, flags); + } + +-static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) ++static void fsi_stream_quit(struct fsi_priv *fsi, int is_play) + { + struct fsi_stream *io = fsi_stream_get(fsi, is_play); + struct snd_soc_dai *dai = fsi_get_dai(io->substream); +@@ -960,13 +960,13 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: +- fsi_stream_push(fsi, is_play, substream); ++ fsi_stream_init(fsi, is_play, substream); + ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); + fsi_port_start(fsi, is_play); + break; + case SNDRV_PCM_TRIGGER_STOP: + fsi_port_stop(fsi, is_play); +- fsi_stream_pop(fsi, is_play); ++ fsi_stream_quit(fsi, is_play); + break; + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0107-ASoC-fsi-modify-fsi_pio_get_area-parameter-and-using.patch b/patches.kzm9g/0107-ASoC-fsi-modify-fsi_pio_get_area-parameter-and-using.patch new file mode 100644 index 00000000000000..838c0ddddbcbd2 --- /dev/null +++ b/patches.kzm9g/0107-ASoC-fsi-modify-fsi_pio_get_area-parameter-and-using.patch @@ -0,0 +1,127 @@ +From 2994ced4ba0546e601874e43b36f9bc6011a49f6 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:52:38 -0800 +Subject: ASoC: fsi: modify fsi_pio_get_area() parameter and using position + +This patch modify fsi_pio_get_area() parameter to use +struct fsi_stream, and used it on fsi_fifo_data_ctrl(). +This is just prepare cleanup for DMAEngine support. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 95b0cf05976b7d0571e283b1fcd4c32095018cd6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 43 +++++++++++++++++-------------------------- + 1 file changed, 17 insertions(+), 26 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 2e2663b..c814d8a 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -477,58 +477,46 @@ static void fsi_stream_quit(struct fsi_priv *fsi, int is_play) + * pio function + */ + +-static u8 *fsi_pio_get_area(struct fsi_priv *fsi, int stream) ++static u8 *fsi_pio_get_area(struct fsi_priv *fsi, struct fsi_stream *io) + { +- int is_play = fsi_stream_is_play(stream); +- struct fsi_stream *io = fsi_stream_get(fsi, is_play); + struct snd_pcm_runtime *runtime = io->substream->runtime; + + return runtime->dma_area + + samples_to_bytes(runtime, io->buff_sample_pos); + } + +-static void fsi_pio_push16(struct fsi_priv *fsi, int num) ++static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int num) + { +- u16 *start; ++ u16 *start = (u16 *)_buf; + int i; + +- start = (u16 *)fsi_pio_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK); +- + for (i = 0; i < num; i++) + fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8)); + } + +-static void fsi_pio_pop16(struct fsi_priv *fsi, int num) ++static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int num) + { +- u16 *start; ++ u16 *start = (u16 *)_buf; + int i; + +- start = (u16 *)fsi_pio_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE); +- +- + for (i = 0; i < num; i++) + *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8); + } + +-static void fsi_pio_push32(struct fsi_priv *fsi, int num) ++static void fsi_pio_push32(struct fsi_priv *fsi, u8 *_buf, int num) + { +- u32 *start; ++ u32 *start = (u32 *)_buf; + int i; + +- start = (u32 *)fsi_pio_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK); +- +- + for (i = 0; i < num; i++) + fsi_reg_write(fsi, DODT, *(start + i)); + } + +-static void fsi_pio_pop32(struct fsi_priv *fsi, int num) ++static void fsi_pio_pop32(struct fsi_priv *fsi, u8 *_buf, int num) + { +- u32 *start; ++ u32 *start = (u32 *)_buf; + int i; + +- start = (u32 *)fsi_pio_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE); +- + for (i = 0; i < num; i++) + *(start + i) = fsi_reg_read(fsi, DIDT); + } +@@ -693,12 +681,13 @@ static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable) + * ctrl function + */ + static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, struct fsi_stream *io, +- void (*run16)(struct fsi_priv *fsi, int size), +- void (*run32)(struct fsi_priv *fsi, int size), +- int samples) ++ void (*run16)(struct fsi_priv *fsi, u8 *buf, int samples), ++ void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples), ++ int samples) + { + struct snd_pcm_runtime *runtime; + struct snd_pcm_substream *substream; ++ u8 *buf; + int over_period; + + if (!fsi || +@@ -723,12 +712,14 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, struct fsi_stream *io, + io->buff_sample_pos = 0; + } + ++ buf = fsi_pio_get_area(fsi, io); ++ + switch (io->sample_width) { + case 2: +- run16(fsi, samples); ++ run16(fsi, buf, samples); + break; + case 4: +- run32(fsi, samples); ++ run32(fsi, buf, samples); + break; + default: + return -EINVAL; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0108-ASoC-fsi-re-define-fsi_is_play-and-fsi_stream_is_pla.patch b/patches.kzm9g/0108-ASoC-fsi-re-define-fsi_is_play-and-fsi_stream_is_pla.patch new file mode 100644 index 00000000000000..c284e895279f66 --- /dev/null +++ b/patches.kzm9g/0108-ASoC-fsi-re-define-fsi_is_play-and-fsi_stream_is_pla.patch @@ -0,0 +1,70 @@ +From 3e44f2caa7c0f3ce9496d578f1fea695c5e5646f Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:54:02 -0800 +Subject: ASoC: fsi: re-define fsi_is_play() and fsi_stream_is_play() + +This patch re-define fsi_is_play() and fsi_stream_is_play(). +fsi_data_pop/push() function keeps direct value of "is_play" at this point, +but it will be removed soon. +This is just prepare cleanup for DMAEngine support. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit a449e46754616a13e1bee649e37bcdf10d1b794a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index c814d8a..1cbe474 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -296,6 +296,11 @@ static int fsi_is_spdif(struct fsi_priv *fsi) + return fsi->spdif; + } + ++static int fsi_is_play(struct snd_pcm_substream *substream) ++{ ++ return substream->stream == SNDRV_PCM_STREAM_PLAYBACK; ++} ++ + static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) + { + struct snd_soc_pcm_runtime *rtd = substream->private_data; +@@ -399,10 +404,10 @@ static void fsi_count_fifo_err(struct fsi_priv *fsi) + /* + * fsi_stream_xx() function + */ +-#define fsi_is_play(substream) fsi_stream_is_play(substream->stream) +-static inline int fsi_stream_is_play(int stream) ++static inline int fsi_stream_is_play(struct fsi_priv *fsi, ++ struct fsi_stream *io) + { +- return stream == SNDRV_PCM_STREAM_PLAYBACK; ++ return &fsi->playback == io; + } + + static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi, +@@ -736,7 +741,7 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, struct fsi_stream *io, + + static int fsi_data_pop(struct fsi_priv *fsi) + { +- int is_play = fsi_stream_is_play(SNDRV_PCM_STREAM_CAPTURE); ++ int is_play = 0; + int sample_residues; /* samples in FSI fifo */ + int sample_space; /* ALSA free samples space */ + int samples; +@@ -755,7 +760,7 @@ static int fsi_data_pop(struct fsi_priv *fsi) + + static int fsi_data_push(struct fsi_priv *fsi) + { +- int is_play = fsi_stream_is_play(SNDRV_PCM_STREAM_PLAYBACK); ++ int is_play = 1; + int sample_residues; /* ALSA residue samples */ + int sample_space; /* FSI fifo free samples space */ + int samples; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0109-ASoC-fsi-use-fsi_stream-in-fsi_get_current_fifo_samp.patch b/patches.kzm9g/0109-ASoC-fsi-use-fsi_stream-in-fsi_get_current_fifo_samp.patch new file mode 100644 index 00000000000000..0b895fb7e55e04 --- /dev/null +++ b/patches.kzm9g/0109-ASoC-fsi-use-fsi_stream-in-fsi_get_current_fifo_samp.patch @@ -0,0 +1,64 @@ +From 374adbfae43dc4d5b0f0f9e7b14841df24cceea1 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:55:26 -0800 +Subject: ASoC: fsi: use fsi_stream in fsi_get_current_fifo_samples() + parameter + +fsi_get_current_fifo_samples() uses fsi_stream instead of is_play. +This is just prepare cleanup for DMAEngine support. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 7b1b3331e65e47b6abb32be0a3db46bcf423145a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 1cbe474..24dbe16 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -210,6 +210,8 @@ struct fsi_master { + spinlock_t lock; + }; + ++static int fsi_stream_is_play(struct fsi_priv *fsi, struct fsi_stream *io); ++ + /* + * basic read write function + */ +@@ -366,8 +368,10 @@ static int fsi_sample2frame(struct fsi_priv *fsi, int samples) + return samples / fsi->chan_num; + } + +-static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play) ++static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, ++ struct fsi_stream *io) + { ++ int is_play = fsi_stream_is_play(fsi, io); + u32 status; + int frames; + +@@ -747,7 +751,7 @@ static int fsi_data_pop(struct fsi_priv *fsi) + int samples; + struct fsi_stream *io = fsi_stream_get(fsi, is_play); + +- sample_residues = fsi_get_current_fifo_samples(fsi, is_play); ++ sample_residues = fsi_get_current_fifo_samples(fsi, io); + sample_space = io->buff_sample_capa - io->buff_sample_pos; + + samples = min(sample_residues, sample_space); +@@ -768,7 +772,7 @@ static int fsi_data_push(struct fsi_priv *fsi) + + sample_residues = io->buff_sample_capa - io->buff_sample_pos; + sample_space = io->fifo_sample_capa - +- fsi_get_current_fifo_samples(fsi, is_play); ++ fsi_get_current_fifo_samples(fsi, io); + + samples = min(sample_residues, sample_space); + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0110-ASoC-fsi-add-fsi_stream_handler-and-PIO-handler.patch b/patches.kzm9g/0110-ASoC-fsi-add-fsi_stream_handler-and-PIO-handler.patch new file mode 100644 index 00000000000000..3346eefd93f023 --- /dev/null +++ b/patches.kzm9g/0110-ASoC-fsi-add-fsi_stream_handler-and-PIO-handler.patch @@ -0,0 +1,286 @@ +From bb1acd92639a1c3dae57bbc1d457fba98f084a6d Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:55:55 -0800 +Subject: ASoC: fsi: add fsi_stream_handler and PIO handler + +This patch adds struct fsi_stream_handler and defined fsi_pio_push/pop_handler. +these are controled by fsi_steam_xxx() function. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 5e97313ac483f03a9af661aada356980fe310e0d) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 118 insertions(+), 15 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 24dbe16..b02886a 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -159,18 +159,27 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena + * struct + */ + ++struct fsi_stream_handler; + struct fsi_stream { +- struct snd_pcm_substream *substream; + ++ /* ++ * these are initialized by fsi_stream_init() ++ */ ++ struct snd_pcm_substream *substream; + int fifo_sample_capa; /* sample capacity of FSI FIFO */ + int buff_sample_capa; /* sample capacity of ALSA buffer */ + int buff_sample_pos; /* sample position of ALSA buffer */ + int period_samples; /* sample number / 1 period */ + int period_pos; /* current period position */ + int sample_width; /* sample width */ +- + int uerr_num; + int oerr_num; ++ ++ /* ++ * thse are initialized by fsi_handler_init() ++ */ ++ struct fsi_stream_handler *handler; ++ struct fsi_priv *priv; + }; + + struct fsi_priv { +@@ -190,6 +199,16 @@ struct fsi_priv { + long rate; + }; + ++struct fsi_stream_handler { ++ int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io); ++ int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); ++ int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); ++}; ++#define fsi_stream_handler_call(io, func, args...) \ ++ (!(io) ? -ENODEV : \ ++ !((io)->handler->func) ? 0 : \ ++ (io)->handler->func(args)) ++ + struct fsi_core { + int ver; + +@@ -435,6 +454,11 @@ static int fsi_stream_is_working(struct fsi_priv *fsi, + return ret; + } + ++static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io) ++{ ++ return io->priv; ++} ++ + static void fsi_stream_init(struct fsi_priv *fsi, + int is_play, + struct snd_pcm_substream *substream) +@@ -482,6 +506,53 @@ static void fsi_stream_quit(struct fsi_priv *fsi, int is_play) + spin_unlock_irqrestore(&master->lock, flags); + } + ++static int fsi_stream_transfer(struct fsi_stream *io) ++{ ++ struct fsi_priv *fsi = fsi_stream_to_priv(io); ++ if (!fsi) ++ return -EIO; ++ ++ return fsi_stream_handler_call(io, transfer, fsi, io); ++} ++ ++static int fsi_stream_probe(struct fsi_priv *fsi) ++{ ++ struct fsi_stream *io; ++ int ret1, ret2; ++ ++ io = &fsi->playback; ++ ret1 = fsi_stream_handler_call(io, probe, fsi, io); ++ ++ io = &fsi->capture; ++ ret2 = fsi_stream_handler_call(io, probe, fsi, io); ++ ++ if (ret1 < 0) ++ return ret1; ++ if (ret2 < 0) ++ return ret2; ++ ++ return 0; ++} ++ ++static int fsi_stream_remove(struct fsi_priv *fsi) ++{ ++ struct fsi_stream *io; ++ int ret1, ret2; ++ ++ io = &fsi->playback; ++ ret1 = fsi_stream_handler_call(io, remove, fsi, io); ++ ++ io = &fsi->capture; ++ ret2 = fsi_stream_handler_call(io, remove, fsi, io); ++ ++ if (ret1 < 0) ++ return ret1; ++ if (ret2 < 0) ++ return ret2; ++ ++ return 0; ++} ++ + /* + * pio function + */ +@@ -743,13 +814,11 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, struct fsi_stream *io, + return 0; + } + +-static int fsi_data_pop(struct fsi_priv *fsi) ++static int fsi_pio_pop(struct fsi_priv *fsi, struct fsi_stream *io) + { +- int is_play = 0; + int sample_residues; /* samples in FSI fifo */ + int sample_space; /* ALSA free samples space */ + int samples; +- struct fsi_stream *io = fsi_stream_get(fsi, is_play); + + sample_residues = fsi_get_current_fifo_samples(fsi, io); + sample_space = io->buff_sample_capa - io->buff_sample_pos; +@@ -762,13 +831,11 @@ static int fsi_data_pop(struct fsi_priv *fsi) + samples); + } + +-static int fsi_data_push(struct fsi_priv *fsi) ++static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io) + { +- int is_play = 1; + int sample_residues; /* ALSA residue samples */ + int sample_space; /* FSI fifo free samples space */ + int samples; +- struct fsi_stream *io = fsi_stream_get(fsi, is_play); + + sample_residues = io->buff_sample_capa - io->buff_sample_pos; + sample_space = io->fifo_sample_capa - +@@ -782,6 +849,14 @@ static int fsi_data_push(struct fsi_priv *fsi) + samples); + } + ++static struct fsi_stream_handler fsi_pio_push_handler = { ++ .transfer = fsi_pio_push, ++}; ++ ++static struct fsi_stream_handler fsi_pio_pop_handler = { ++ .transfer = fsi_pio_pop, ++}; ++ + static irqreturn_t fsi_interrupt(int irq, void *data) + { + struct fsi_master *master = data; +@@ -792,13 +867,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data) + fsi_master_mask_set(master, SOFT_RST, IR, IR); + + if (int_st & AB_IO(1, AO_SHIFT)) +- fsi_data_push(&master->fsia); ++ fsi_stream_transfer(&master->fsia.playback); + if (int_st & AB_IO(1, BO_SHIFT)) +- fsi_data_push(&master->fsib); ++ fsi_stream_transfer(&master->fsib.playback); + if (int_st & AB_IO(1, AI_SHIFT)) +- fsi_data_pop(&master->fsia); ++ fsi_stream_transfer(&master->fsia.capture); + if (int_st & AB_IO(1, BI_SHIFT)) +- fsi_data_pop(&master->fsib); ++ fsi_stream_transfer(&master->fsib.capture); + + fsi_count_fifo_err(&master->fsia); + fsi_count_fifo_err(&master->fsib); +@@ -955,14 +1030,16 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) + { + struct fsi_priv *fsi = fsi_get_priv(substream); ++ struct fsi_stream *io = fsi_stream_get(fsi, fsi_is_play(substream)); + int is_play = fsi_is_play(substream); + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + fsi_stream_init(fsi, is_play, substream); +- ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); +- fsi_port_start(fsi, is_play); ++ ret = fsi_stream_transfer(io); ++ if (0 == ret) ++ fsi_port_start(fsi, is_play); + break; + case SNDRV_PCM_TRIGGER_STOP: + fsi_port_stop(fsi, is_play); +@@ -1224,6 +1301,13 @@ static struct snd_soc_platform_driver fsi_soc_platform = { + /* + * platform function + */ ++static void fsi_handler_init(struct fsi_priv *fsi) ++{ ++ fsi->playback.handler = &fsi_pio_push_handler; /* default PIO */ ++ fsi->playback.priv = fsi; ++ fsi->capture.handler = &fsi_pio_pop_handler; /* default PIO */ ++ fsi->capture.priv = fsi; ++} + + static int fsi_probe(struct platform_device *pdev) + { +@@ -1270,10 +1354,22 @@ static int fsi_probe(struct platform_device *pdev) + /* FSI A setting */ + master->fsia.base = master->base; + master->fsia.master = master; ++ fsi_handler_init(&master->fsia); ++ ret = fsi_stream_probe(&master->fsia); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "FSIA stream probe failed\n"); ++ goto exit_iounmap; ++ } + + /* FSI B setting */ + master->fsib.base = master->base + 0x40; + master->fsib.master = master; ++ fsi_handler_init(&master->fsib); ++ ret = fsi_stream_probe(&master->fsib); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "FSIB stream probe failed\n"); ++ goto exit_fsia; ++ } + + pm_runtime_enable(&pdev->dev); + dev_set_drvdata(&pdev->dev, master); +@@ -1282,7 +1378,7 @@ static int fsi_probe(struct platform_device *pdev) + id_entry->name, master); + if (ret) { + dev_err(&pdev->dev, "irq request err\n"); +- goto exit_iounmap; ++ goto exit_fsib; + } + + ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform); +@@ -1304,6 +1400,10 @@ exit_snd_soc: + snd_soc_unregister_platform(&pdev->dev); + exit_free_irq: + free_irq(irq, master); ++exit_fsib: ++ fsi_stream_remove(&master->fsib); ++exit_fsia: ++ fsi_stream_remove(&master->fsia); + exit_iounmap: + iounmap(master->base); + pm_runtime_disable(&pdev->dev); +@@ -1326,6 +1426,9 @@ static int fsi_remove(struct platform_device *pdev) + snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); + snd_soc_unregister_platform(&pdev->dev); + ++ fsi_stream_remove(&master->fsia); ++ fsi_stream_remove(&master->fsib); ++ + iounmap(master->base); + kfree(master); + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0111-ASoC-fsi-tidyup-fsi_pio_xxx-are-gathered.patch b/patches.kzm9g/0111-ASoC-fsi-tidyup-fsi_pio_xxx-are-gathered.patch new file mode 100644 index 00000000000000..2adddb04fdefd7 --- /dev/null +++ b/patches.kzm9g/0111-ASoC-fsi-tidyup-fsi_pio_xxx-are-gathered.patch @@ -0,0 +1,152 @@ +From e31af8e7b9e4d0bffdab4e6c614f6b181bea962b Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:56:27 -0800 +Subject: ASoC: fsi: tidyup: fsi_pio_xxx() are gathered + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 1b0ca1a0c056c7c97b18e363f939f0635ca093af) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 101 ++++++++++++++++++++++++++--------------------------- + 1 file changed, 49 insertions(+), 52 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index b02886a..7c93b7c 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -554,54 +554,6 @@ static int fsi_stream_remove(struct fsi_priv *fsi) + } + + /* +- * pio function +- */ +- +-static u8 *fsi_pio_get_area(struct fsi_priv *fsi, struct fsi_stream *io) +-{ +- struct snd_pcm_runtime *runtime = io->substream->runtime; +- +- return runtime->dma_area + +- samples_to_bytes(runtime, io->buff_sample_pos); +-} +- +-static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int num) +-{ +- u16 *start = (u16 *)_buf; +- int i; +- +- for (i = 0; i < num; i++) +- fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8)); +-} +- +-static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int num) +-{ +- u16 *start = (u16 *)_buf; +- int i; +- +- for (i = 0; i < num; i++) +- *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8); +-} +- +-static void fsi_pio_push32(struct fsi_priv *fsi, u8 *_buf, int num) +-{ +- u32 *start = (u32 *)_buf; +- int i; +- +- for (i = 0; i < num; i++) +- fsi_reg_write(fsi, DODT, *(start + i)); +-} +- +-static void fsi_pio_pop32(struct fsi_priv *fsi, u8 *_buf, int num) +-{ +- u32 *start = (u32 *)_buf; +- int i; +- +- for (i = 0; i < num; i++) +- *(start + i) = fsi_reg_read(fsi, DIDT); +-} +- +-/* + * irq function + */ + +@@ -757,10 +709,55 @@ static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable) + fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); + } + ++ + /* +- * ctrl function ++ * pio data transfer handler + */ +-static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, struct fsi_stream *io, ++static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples) ++{ ++ u16 *buf = (u16 *)_buf; ++ int i; ++ ++ for (i = 0; i < samples; i++) ++ fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8)); ++} ++ ++static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples) ++{ ++ u16 *buf = (u16 *)_buf; ++ int i; ++ ++ for (i = 0; i < samples; i++) ++ *(buf + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8); ++} ++ ++static void fsi_pio_push32(struct fsi_priv *fsi, u8 *_buf, int samples) ++{ ++ u32 *buf = (u32 *)_buf; ++ int i; ++ ++ for (i = 0; i < samples; i++) ++ fsi_reg_write(fsi, DODT, *(buf + i)); ++} ++ ++static void fsi_pio_pop32(struct fsi_priv *fsi, u8 *_buf, int samples) ++{ ++ u32 *buf = (u32 *)_buf; ++ int i; ++ ++ for (i = 0; i < samples; i++) ++ *(buf + i) = fsi_reg_read(fsi, DIDT); ++} ++ ++static u8 *fsi_pio_get_area(struct fsi_priv *fsi, struct fsi_stream *io) ++{ ++ struct snd_pcm_runtime *runtime = io->substream->runtime; ++ ++ return runtime->dma_area + ++ samples_to_bytes(runtime, io->buff_sample_pos); ++} ++ ++static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io, + void (*run16)(struct fsi_priv *fsi, u8 *buf, int samples), + void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples), + int samples) +@@ -825,7 +822,7 @@ static int fsi_pio_pop(struct fsi_priv *fsi, struct fsi_stream *io) + + samples = min(sample_residues, sample_space); + +- return fsi_fifo_data_ctrl(fsi, io, ++ return fsi_pio_transfer(fsi, io, + fsi_pio_pop16, + fsi_pio_pop32, + samples); +@@ -843,7 +840,7 @@ static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io) + + samples = min(sample_residues, sample_space); + +- return fsi_fifo_data_ctrl(fsi, io, ++ return fsi_pio_transfer(fsi, io, + fsi_pio_push16, + fsi_pio_push32, + samples); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0112-ASoC-fsi-don-t-use-is_play-as-a-parameter-of-fsi-fun.patch b/patches.kzm9g/0112-ASoC-fsi-don-t-use-is_play-as-a-parameter-of-fsi-fun.patch new file mode 100644 index 00000000000000..1c02a3dc1a42e8 --- /dev/null +++ b/patches.kzm9g/0112-ASoC-fsi-don-t-use-is_play-as-a-parameter-of-fsi-fun.patch @@ -0,0 +1,291 @@ +From a1e81ab5ca7241fefe487653f39c9bcb665e3c3e Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:56:57 -0800 +Subject: ASoC: fsi: don't use is_play as a parameter of fsi functions + +is_play should be kept as local valuable. +it prepare cleanup for DMAEngine support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 938e2a8da5b2c1cb21c200e97736259948a3d12c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 94 ++++++++++++++++++++++++++---------------------------- + 1 file changed, 45 insertions(+), 49 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 7c93b7c..7dec144 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -364,8 +364,9 @@ static u32 fsi_get_info_flags(struct fsi_priv *fsi) + master->info->portb_flags; + } + +-static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) ++static u32 fsi_get_port_shift(struct fsi_priv *fsi, struct fsi_stream *io) + { ++ int is_play = fsi_stream_is_play(fsi, io); + int is_porta = fsi_is_port_a(fsi); + u32 shift; + +@@ -434,15 +435,14 @@ static inline int fsi_stream_is_play(struct fsi_priv *fsi, + } + + static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi, +- int is_play) ++ struct snd_pcm_substream *substream) + { +- return is_play ? &fsi->playback : &fsi->capture; ++ return fsi_is_play(substream) ? &fsi->playback : &fsi->capture; + } + + static int fsi_stream_is_working(struct fsi_priv *fsi, +- int is_play) ++ struct fsi_stream *io) + { +- struct fsi_stream *io = fsi_stream_get(fsi, is_play); + struct fsi_master *master = fsi_get_master(fsi); + unsigned long flags; + int ret; +@@ -460,10 +460,9 @@ static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io) + } + + static void fsi_stream_init(struct fsi_priv *fsi, +- int is_play, ++ struct fsi_stream *io, + struct snd_pcm_substream *substream) + { +- struct fsi_stream *io = fsi_stream_get(fsi, is_play); + struct snd_pcm_runtime *runtime = substream->runtime; + struct fsi_master *master = fsi_get_master(fsi); + unsigned long flags; +@@ -480,9 +479,8 @@ static void fsi_stream_init(struct fsi_priv *fsi, + spin_unlock_irqrestore(&master->lock, flags); + } + +-static void fsi_stream_quit(struct fsi_priv *fsi, int is_play) ++static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io) + { +- struct fsi_stream *io = fsi_stream_get(fsi, is_play); + struct snd_soc_dai *dai = fsi_get_dai(io->substream); + struct fsi_master *master = fsi_get_master(fsi); + unsigned long flags; +@@ -557,18 +555,18 @@ static int fsi_stream_remove(struct fsi_priv *fsi) + * irq function + */ + +-static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) ++static void fsi_irq_enable(struct fsi_priv *fsi, struct fsi_stream *io) + { +- u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play)); ++ u32 data = AB_IO(1, fsi_get_port_shift(fsi, io)); + struct fsi_master *master = fsi_get_master(fsi); + + fsi_core_mask_set(master, imsk, data, data); + fsi_core_mask_set(master, iemsk, data, data); + } + +-static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) ++static void fsi_irq_disable(struct fsi_priv *fsi, struct fsi_stream *io) + { +- u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play)); ++ u32 data = AB_IO(1, fsi_get_port_shift(fsi, io)); + struct fsi_master *master = fsi_get_master(fsi); + + fsi_core_mask_set(master, imsk, data, 0); +@@ -585,8 +583,8 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi) + u32 data = 0; + struct fsi_master *master = fsi_get_master(fsi); + +- data |= AB_IO(1, fsi_get_port_shift(fsi, 0)); +- data |= AB_IO(1, fsi_get_port_shift(fsi, 1)); ++ data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->playback)); ++ data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->capture)); + + /* clear interrupt factor */ + fsi_core_mask_set(master, int_st, data, 0); +@@ -695,15 +693,16 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, + + #define fsi_port_start(f, i) __fsi_port_clk_ctrl(f, i, 1) + #define fsi_port_stop(f, i) __fsi_port_clk_ctrl(f, i, 0) +-static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable) ++static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, struct fsi_stream *io, ++ int enable) + { + struct fsi_master *master = fsi_get_master(fsi); + u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; + + if (enable) +- fsi_irq_enable(fsi, is_play); ++ fsi_irq_enable(fsi, io); + else +- fsi_irq_disable(fsi, is_play); ++ fsi_irq_disable(fsi, io); + + if (fsi_is_clk_master(fsi)) + fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); +@@ -885,17 +884,17 @@ static irqreturn_t fsi_interrupt(int irq, void *data) + * dai ops + */ + static void fsi_fifo_init(struct fsi_priv *fsi, +- int is_play, ++ struct fsi_stream *io, + struct device *dev) + { + struct fsi_master *master = fsi_get_master(fsi); +- struct fsi_stream *io = fsi_stream_get(fsi, is_play); ++ int is_play = fsi_stream_is_play(fsi, io); + u32 shift, i; + int frame_capa; + + /* get on-chip RAM capacity */ + shift = fsi_master_read(master, FIFO_SZ); +- shift >>= fsi_get_port_shift(fsi, is_play); ++ shift >>= fsi_get_port_shift(fsi, io); + shift &= FIFO_SZ_MASK; + frame_capa = 256 << shift; + dev_dbg(dev, "fifo = %d words\n", frame_capa); +@@ -940,7 +939,7 @@ static void fsi_fifo_init(struct fsi_priv *fsi, + } + + static int fsi_hw_startup(struct fsi_priv *fsi, +- int is_play, ++ struct fsi_stream *io, + struct device *dev) + { + struct fsi_master *master = fsi_get_master(fsi); +@@ -989,11 +988,11 @@ static int fsi_hw_startup(struct fsi_priv *fsi, + } + + /* irq clear */ +- fsi_irq_disable(fsi, is_play); ++ fsi_irq_disable(fsi, io); + fsi_irq_clear_status(fsi); + + /* fifo init */ +- fsi_fifo_init(fsi, is_play, dev); ++ fsi_fifo_init(fsi, io, dev); + + return 0; + } +@@ -1009,9 +1008,8 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { + struct fsi_priv *fsi = fsi_get_priv(substream); +- int is_play = fsi_is_play(substream); + +- return fsi_hw_startup(fsi, is_play, dai->dev); ++ return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev); + } + + static void fsi_dai_shutdown(struct snd_pcm_substream *substream, +@@ -1027,20 +1025,19 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) + { + struct fsi_priv *fsi = fsi_get_priv(substream); +- struct fsi_stream *io = fsi_stream_get(fsi, fsi_is_play(substream)); +- int is_play = fsi_is_play(substream); ++ struct fsi_stream *io = fsi_stream_get(fsi, substream); + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: +- fsi_stream_init(fsi, is_play, substream); ++ fsi_stream_init(fsi, io, substream); + ret = fsi_stream_transfer(io); + if (0 == ret) +- fsi_port_start(fsi, is_play); ++ fsi_port_start(fsi, io); + break; + case SNDRV_PCM_TRIGGER_STOP: +- fsi_port_stop(fsi, is_play); +- fsi_stream_quit(fsi, is_play); ++ fsi_port_stop(fsi, io); ++ fsi_stream_quit(fsi, io); + break; + } + +@@ -1206,7 +1203,7 @@ static int fsi_hw_free(struct snd_pcm_substream *substream) + static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) + { + struct fsi_priv *fsi = fsi_get_priv(substream); +- struct fsi_stream *io = fsi_stream_get(fsi, fsi_is_play(substream)); ++ struct fsi_stream *io = fsi_stream_get(fsi, substream); + int samples_pos = io->buff_sample_pos - 1; + + if (samples_pos < 0) +@@ -1433,30 +1430,29 @@ static int fsi_remove(struct platform_device *pdev) + } + + static void __fsi_suspend(struct fsi_priv *fsi, +- int is_play, ++ struct fsi_stream *io, + struct device *dev) + { +- if (!fsi_stream_is_working(fsi, is_play)) ++ if (!fsi_stream_is_working(fsi, io)) + return; + +- fsi_port_stop(fsi, is_play); ++ fsi_port_stop(fsi, io); + fsi_hw_shutdown(fsi, dev); + } + + static void __fsi_resume(struct fsi_priv *fsi, +- int is_play, ++ struct fsi_stream *io, + struct device *dev) + { +- if (!fsi_stream_is_working(fsi, is_play)) ++ if (!fsi_stream_is_working(fsi, io)) + return; + +- fsi_hw_startup(fsi, is_play, dev); ++ fsi_hw_startup(fsi, io, dev); + + if (fsi_is_clk_master(fsi) && fsi->rate) + fsi_set_master_clk(dev, fsi, fsi->rate, 1); + +- fsi_port_start(fsi, is_play); +- ++ fsi_port_start(fsi, io); + } + + static int fsi_suspend(struct device *dev) +@@ -1465,11 +1461,11 @@ static int fsi_suspend(struct device *dev) + struct fsi_priv *fsia = &master->fsia; + struct fsi_priv *fsib = &master->fsib; + +- __fsi_suspend(fsia, 1, dev); +- __fsi_suspend(fsia, 0, dev); ++ __fsi_suspend(fsia, &fsia->playback, dev); ++ __fsi_suspend(fsia, &fsia->capture, dev); + +- __fsi_suspend(fsib, 1, dev); +- __fsi_suspend(fsib, 0, dev); ++ __fsi_suspend(fsib, &fsib->playback, dev); ++ __fsi_suspend(fsib, &fsib->capture, dev); + + return 0; + } +@@ -1480,11 +1476,11 @@ static int fsi_resume(struct device *dev) + struct fsi_priv *fsia = &master->fsia; + struct fsi_priv *fsib = &master->fsib; + +- __fsi_resume(fsia, 1, dev); +- __fsi_resume(fsia, 0, dev); ++ __fsi_resume(fsia, &fsia->playback, dev); ++ __fsi_resume(fsia, &fsia->capture, dev); + +- __fsi_resume(fsib, 1, dev); +- __fsi_resume(fsib, 0, dev); ++ __fsi_resume(fsib, &fsib->playback, dev); ++ __fsi_resume(fsib, &fsib->capture, dev); + + return 0; + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0113-ASoC-fsi-add-.start_stop-handler-to-fsi_stream_handl.patch b/patches.kzm9g/0113-ASoC-fsi-add-.start_stop-handler-to-fsi_stream_handl.patch new file mode 100644 index 00000000000000..5ab76b525e120c --- /dev/null +++ b/patches.kzm9g/0113-ASoC-fsi-add-.start_stop-handler-to-fsi_stream_handl.patch @@ -0,0 +1,129 @@ +From fa8ef8395e2e672608fb808bdc7261b25c561d1d Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:57:25 -0800 +Subject: ASoC: fsi: add .start_stop handler to fsi_stream_handler + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 180346ede352b12c72c5aeba2fc806fd32880c16) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 51 +++++++++++++++++++++++++++++---------------------- + 1 file changed, 29 insertions(+), 22 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 7dec144..8d05e59 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -203,6 +203,8 @@ struct fsi_stream_handler { + int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io); + int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); + int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); ++ void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io, ++ int enable); + }; + #define fsi_stream_handler_call(io, func, args...) \ + (!(io) ? -ENODEV : \ +@@ -513,6 +515,12 @@ static int fsi_stream_transfer(struct fsi_stream *io) + return fsi_stream_handler_call(io, transfer, fsi, io); + } + ++#define fsi_stream_start(fsi, io)\ ++ fsi_stream_handler_call(io, start_stop, fsi, io, 1) ++ ++#define fsi_stream_stop(fsi, io)\ ++ fsi_stream_handler_call(io, start_stop, fsi, io, 0) ++ + static int fsi_stream_probe(struct fsi_priv *fsi) + { + struct fsi_stream *io; +@@ -691,24 +699,6 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, + return ret; + } + +-#define fsi_port_start(f, i) __fsi_port_clk_ctrl(f, i, 1) +-#define fsi_port_stop(f, i) __fsi_port_clk_ctrl(f, i, 0) +-static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, struct fsi_stream *io, +- int enable) +-{ +- struct fsi_master *master = fsi_get_master(fsi); +- u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; +- +- if (enable) +- fsi_irq_enable(fsi, io); +- else +- fsi_irq_disable(fsi, io); +- +- if (fsi_is_clk_master(fsi)) +- fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); +-} +- +- + /* + * pio data transfer handler + */ +@@ -845,12 +835,29 @@ static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io) + samples); + } + ++static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, ++ int enable) ++{ ++ struct fsi_master *master = fsi_get_master(fsi); ++ u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; ++ ++ if (enable) ++ fsi_irq_enable(fsi, io); ++ else ++ fsi_irq_disable(fsi, io); ++ ++ if (fsi_is_clk_master(fsi)) ++ fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); ++} ++ + static struct fsi_stream_handler fsi_pio_push_handler = { + .transfer = fsi_pio_push, ++ .start_stop = fsi_pio_start_stop, + }; + + static struct fsi_stream_handler fsi_pio_pop_handler = { + .transfer = fsi_pio_pop, ++ .start_stop = fsi_pio_start_stop, + }; + + static irqreturn_t fsi_interrupt(int irq, void *data) +@@ -1033,10 +1040,10 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, + fsi_stream_init(fsi, io, substream); + ret = fsi_stream_transfer(io); + if (0 == ret) +- fsi_port_start(fsi, io); ++ fsi_stream_start(fsi, io); + break; + case SNDRV_PCM_TRIGGER_STOP: +- fsi_port_stop(fsi, io); ++ fsi_stream_stop(fsi, io); + fsi_stream_quit(fsi, io); + break; + } +@@ -1436,7 +1443,7 @@ static void __fsi_suspend(struct fsi_priv *fsi, + if (!fsi_stream_is_working(fsi, io)) + return; + +- fsi_port_stop(fsi, io); ++ fsi_stream_stop(fsi, io); + fsi_hw_shutdown(fsi, dev); + } + +@@ -1452,7 +1459,7 @@ static void __fsi_resume(struct fsi_priv *fsi, + if (fsi_is_clk_master(fsi) && fsi->rate) + fsi_set_master_clk(dev, fsi, fsi->rate, 1); + +- fsi_port_start(fsi, io); ++ fsi_stream_start(fsi, io); + } + + static int fsi_suspend(struct device *dev) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0114-ASoC-fsi-fsi_stream_is_working-care-substream-runtim.patch b/patches.kzm9g/0114-ASoC-fsi-fsi_stream_is_working-care-substream-runtim.patch new file mode 100644 index 00000000000000..8ee621e129fe06 --- /dev/null +++ b/patches.kzm9g/0114-ASoC-fsi-fsi_stream_is_working-care-substream-runtim.patch @@ -0,0 +1,41 @@ +From fefc4953a08d796f8e66ab7e388b589f7a564aaa Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:57:40 -0800 +Subject: ASoC: fsi: fsi_stream_is_working() care substream->runtime + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 97df81873e9c1391319dd818bc4b6856517e4939) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 8d05e59..1e10184 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -450,7 +450,7 @@ static int fsi_stream_is_working(struct fsi_priv *fsi, + int ret; + + spin_lock_irqsave(&master->lock, flags); +- ret = !!io->substream; ++ ret = !!(io->substream && io->substream->runtime); + spin_unlock_irqrestore(&master->lock, flags); + + return ret; +@@ -756,9 +756,7 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io, + u8 *buf; + int over_period; + +- if (!fsi || +- !io->substream || +- !io->substream->runtime) ++ if (!fsi_stream_is_working(fsi, io)) + return -EINVAL; + + over_period = 0; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0115-ASoC-fsi-PortA-B-information-was-controlled-by-sh_fs.patch b/patches.kzm9g/0115-ASoC-fsi-PortA-B-information-was-controlled-by-sh_fs.patch new file mode 100644 index 00000000000000..c2e73b55c5f5c9 --- /dev/null +++ b/patches.kzm9g/0115-ASoC-fsi-PortA-B-information-was-controlled-by-sh_fs.patch @@ -0,0 +1,285 @@ +From f6427f8081fdd148aeefb37a02f1603584529935 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:58:48 -0800 +Subject: ASoC: fsi: PortA/B information was controlled by sh_fsi_port_info + +Current FSI got each PortA/B parameter by porta_flags/portb_flags from platform. +And .set_rate function was shared for PortA/B. +This structure was not readable and not flexible. +This patch adds sh_fsi_port_info, and its own settings was added on each platform. +it is preparation for DMAEngine support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit fec691e73bf20e1c8e6ecd8e3725e4745bec4e21) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-ap4evb.c | 30 +++++++++++------------------- + arch/arm/mach-shmobile/board-mackerel.c | 18 ++++++++---------- + arch/sh/boards/mach-ecovec24/setup.c | 4 +++- + arch/sh/boards/mach-se/7724/setup.c | 4 +++- + include/sound/sh_fsi.h | 10 +++++++--- + sound/soc/sh/fsi.c | 32 ++++++++++++++++---------------- + 6 files changed, 48 insertions(+), 50 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c +index 59f0d2c..e969a15 100644 +--- a/arch/arm/mach-shmobile/board-ap4evb.c ++++ b/arch/arm/mach-shmobile/board-ap4evb.c +@@ -712,26 +712,18 @@ fsi_set_rate_end: + return ret; + } + +-static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable) +-{ +- int ret; +- +- if (is_porta) +- ret = fsi_ak4642_set_rate(dev, rate, enable); +- else +- ret = fsi_hdmi_set_rate(dev, rate, enable); +- +- return ret; +-} +- + static struct sh_fsi_platform_info fsi_info = { +- .porta_flags = SH_FSI_BRS_INV, +- +- .portb_flags = SH_FSI_BRS_INV | +- SH_FSI_BRM_INV | +- SH_FSI_LRS_INV | +- SH_FSI_FMT_SPDIF, +- .set_rate = fsi_set_rate, ++ .port_a = { ++ .flags = SH_FSI_BRS_INV, ++ .set_rate = fsi_ak4642_set_rate, ++ }, ++ .port_b = { ++ .flags = SH_FSI_BRS_INV | ++ SH_FSI_BRM_INV | ++ SH_FSI_LRS_INV | ++ SH_FSI_FMT_SPDIF, ++ .set_rate = fsi_hdmi_set_rate, ++ }, + }; + + static struct resource fsi_resources[] = { +diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c +index c2faf11..9207a56 100644 +--- a/arch/arm/mach-shmobile/board-mackerel.c ++++ b/arch/arm/mach-shmobile/board-mackerel.c +@@ -881,7 +881,7 @@ static int __fsi_set_round_rate(struct clk *clk, long rate, int enable) + return clk_enable(clk); + } + +-static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable) ++static int fsi_b_set_rate(struct device *dev, int rate, int enable) + { + struct clk *fsib_clk; + struct clk *fdiv_clk = &sh7372_fsidivb_clk; +@@ -890,10 +890,6 @@ static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable) + int ackmd_bpfmd; + int ret; + +- /* FSIA is slave mode. nothing to do here */ +- if (is_porta) +- return 0; +- + /* clock start */ + switch (rate) { + case 44100: +@@ -937,14 +933,16 @@ fsi_set_rate_end: + } + + static struct sh_fsi_platform_info fsi_info = { +- .porta_flags = SH_FSI_BRS_INV, +- +- .portb_flags = SH_FSI_BRS_INV | ++ .port_a = { ++ .flags = SH_FSI_BRS_INV, ++ }, ++ .port_b = { ++ .flags = SH_FSI_BRS_INV | + SH_FSI_BRM_INV | + SH_FSI_LRS_INV | + SH_FSI_FMT_SPDIF, +- +- .set_rate = fsi_set_rate, ++ .set_rate = fsi_b_set_rate, ++ } + }; + + static struct resource fsi_resources[] = { +diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c +index 15e3bfd..9c09829 100644 +--- a/arch/sh/boards/mach-ecovec24/setup.c ++++ b/arch/sh/boards/mach-ecovec24/setup.c +@@ -790,7 +790,9 @@ static struct platform_device camera_devices[] = { + + /* FSI */ + static struct sh_fsi_platform_info fsi_info = { +- .portb_flags = SH_FSI_BRS_INV, ++ .port_b = { ++ .flags = SH_FSI_BRS_INV, ++ }, + }; + + static struct resource fsi_resources[] = { +diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c +index abc4d12..7c66a3d 100644 +--- a/arch/sh/boards/mach-se/7724/setup.c ++++ b/arch/sh/boards/mach-se/7724/setup.c +@@ -285,7 +285,9 @@ static struct platform_device ceu1_device = { + /* FSI */ + /* change J20, J21, J22 pin to 1-2 connection to use slave mode */ + static struct sh_fsi_platform_info fsi_info = { +- .porta_flags = SH_FSI_BRS_INV, ++ .port_a = { ++ .flags = SH_FSI_BRS_INV, ++ }, + }; + + static struct resource fsi_resources[] = { +diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h +index 9b1aaca..78cd77a 100644 +--- a/include/sound/sh_fsi.h ++++ b/include/sound/sh_fsi.h +@@ -72,10 +72,14 @@ + #define SH_FSI_BPFMD_32 (5 << 4) + #define SH_FSI_BPFMD_16 (6 << 4) + ++struct sh_fsi_port_info { ++ unsigned long flags; ++ int (*set_rate)(struct device *dev, int rate, int enable); ++}; ++ + struct sh_fsi_platform_info { +- unsigned long porta_flags; +- unsigned long portb_flags; +- int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); ++ struct sh_fsi_port_info port_a; ++ struct sh_fsi_port_info port_b; + }; + + /* +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 1e10184..75d0cda 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -116,7 +116,7 @@ + + #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) + +-typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int enable); ++typedef int (*set_rate_func)(struct device *dev, int rate, int enable); + + /* + * FSI driver use below type name for variable +@@ -185,6 +185,7 @@ struct fsi_stream { + struct fsi_priv { + void __iomem *base; + struct fsi_master *master; ++ struct sh_fsi_port_info *info; + + struct fsi_stream playback; + struct fsi_stream capture; +@@ -227,7 +228,6 @@ struct fsi_master { + struct fsi_priv fsia; + struct fsi_priv fsib; + struct fsi_core *core; +- struct sh_fsi_platform_info *info; + spinlock_t lock; + }; + +@@ -346,24 +346,20 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) + return fsi_get_priv_frm_dai(fsi_get_dai(substream)); + } + +-static set_rate_func fsi_get_info_set_rate(struct fsi_master *master) ++static set_rate_func fsi_get_info_set_rate(struct fsi_priv *fsi) + { +- if (!master->info) ++ if (!fsi->info) + return NULL; + +- return master->info->set_rate; ++ return fsi->info->set_rate; + } + + static u32 fsi_get_info_flags(struct fsi_priv *fsi) + { +- int is_porta = fsi_is_port_a(fsi); +- struct fsi_master *master = fsi_get_master(fsi); +- +- if (!master->info) ++ if (!fsi->info) + return 0; + +- return is_porta ? master->info->porta_flags : +- master->info->portb_flags; ++ return fsi->info->flags; + } + + static u32 fsi_get_port_shift(struct fsi_priv *fsi, struct fsi_stream *io) +@@ -628,11 +624,14 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, + long rate, int enable) + { + struct fsi_master *master = fsi_get_master(fsi); +- set_rate_func set_rate = fsi_get_info_set_rate(master); ++ set_rate_func set_rate = fsi_get_info_set_rate(fsi); + int fsi_ver = master->core->ver; + int ret; + +- ret = set_rate(dev, fsi_is_port_a(fsi), rate, enable); ++ if (!set_rate) ++ return 0; ++ ++ ret = set_rate(dev, rate, enable); + if (ret < 0) /* error */ + return ret; + +@@ -1093,8 +1092,7 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi) + static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) + { + struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); +- struct fsi_master *master = fsi_get_master(fsi); +- set_rate_func set_rate = fsi_get_info_set_rate(master); ++ set_rate_func set_rate = fsi_get_info_set_rate(fsi); + u32 flags = fsi_get_info_flags(fsi); + int ret; + +@@ -1312,6 +1310,7 @@ static int fsi_probe(struct platform_device *pdev) + { + struct fsi_master *master; + const struct platform_device_id *id_entry; ++ struct sh_fsi_platform_info *info = pdev->dev.platform_data; + struct resource *res; + unsigned int irq; + int ret; +@@ -1346,13 +1345,13 @@ static int fsi_probe(struct platform_device *pdev) + + /* master setting */ + master->irq = irq; +- master->info = pdev->dev.platform_data; + master->core = (struct fsi_core *)id_entry->driver_data; + spin_lock_init(&master->lock); + + /* FSI A setting */ + master->fsia.base = master->base; + master->fsia.master = master; ++ master->fsia.info = &info->port_a; + fsi_handler_init(&master->fsia); + ret = fsi_stream_probe(&master->fsia); + if (ret < 0) { +@@ -1363,6 +1362,7 @@ static int fsi_probe(struct platform_device *pdev) + /* FSI B setting */ + master->fsib.base = master->base + 0x40; + master->fsib.master = master; ++ master->fsib.info = &info->port_b; + fsi_handler_init(&master->fsib); + ret = fsi_stream_probe(&master->fsib); + if (ret < 0) { +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0116-ASoC-fsi-add-.init-.quit-handler-support.patch b/patches.kzm9g/0116-ASoC-fsi-add-.init-.quit-handler-support.patch new file mode 100644 index 00000000000000..c52a74dac8d60a --- /dev/null +++ b/patches.kzm9g/0116-ASoC-fsi-add-.init-.quit-handler-support.patch @@ -0,0 +1,48 @@ +From 9f742c8745ad3dc5d35f20f7960914021773b346 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:59:02 -0800 +Subject: ASoC: fsi: add .init/.quit handler support + +This is preparation for DMAEngine support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 83344027cacf1944fe180907fa98ee4116ef33ea) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 75d0cda..79a0afb 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -201,6 +201,8 @@ struct fsi_priv { + }; + + struct fsi_stream_handler { ++ int (*init)(struct fsi_priv *fsi, struct fsi_stream *io); ++ int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io); + int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io); + int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); + int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); +@@ -474,6 +476,7 @@ static void fsi_stream_init(struct fsi_priv *fsi, + io->sample_width = samples_to_bytes(runtime, 1); + io->oerr_num = -1; /* ignore 1st err */ + io->uerr_num = -1; /* ignore 1st err */ ++ fsi_stream_handler_call(io, init, fsi, io); + spin_unlock_irqrestore(&master->lock, flags); + } + +@@ -491,6 +494,7 @@ static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io) + if (io->uerr_num > 0) + dev_err(dai->dev, "under_run = %d\n", io->uerr_num); + ++ fsi_stream_handler_call(io, quit, fsi, io); + io->substream = NULL; + io->buff_sample_capa = 0; + io->buff_sample_pos = 0; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0117-ASoC-fsi-fixup-fsi_pointer-calculation-method.patch b/patches.kzm9g/0117-ASoC-fsi-fixup-fsi_pointer-calculation-method.patch new file mode 100644 index 00000000000000..92bbecdf5f1aff --- /dev/null +++ b/patches.kzm9g/0117-ASoC-fsi-fixup-fsi_pointer-calculation-method.patch @@ -0,0 +1,42 @@ +From a7a2edc574ad5ea06820d9c52a14a22981b8d6f0 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Wed, 8 Feb 2012 16:57:29 -0800 +Subject: ASoC: fsi: fixup fsi_pointer() calculation method + +current fsi_pointer() calculation was not correct for FSI driver. +This patch fix it up. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 1987877d869027ab63dc9df515e11f19279a8091) + +Conflicts: + + sound/soc/sh/fsi.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 79a0afb..1374680 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1211,12 +1211,8 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) + { + struct fsi_priv *fsi = fsi_get_priv(substream); + struct fsi_stream *io = fsi_stream_get(fsi, substream); +- int samples_pos = io->buff_sample_pos - 1; + +- if (samples_pos < 0) +- samples_pos = 0; +- +- return fsi_sample2frame(fsi, samples_pos); ++ return fsi_sample2frame(fsi, io->buff_sample_pos); + } + + static struct snd_pcm_ops fsi_pcm_ops = { +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0118-ASoC-fsi-Add-DMAEngine-support.patch b/patches.kzm9g/0118-ASoC-fsi-Add-DMAEngine-support.patch new file mode 100644 index 00000000000000..b54ad8d37586df --- /dev/null +++ b/patches.kzm9g/0118-ASoC-fsi-Add-DMAEngine-support.patch @@ -0,0 +1,316 @@ +From 815f3e601467b439fa67c58bc2386d7b148e89b7 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 3 Feb 2012 00:59:33 -0800 +Subject: ASoC: fsi: Add DMAEngine support + +This patch supports DMAEngine to FSI driver. +It supports only Tx case at this point. +If platform/cpu doesn't support DMAEngine, FSI driver will +use PIO transfer. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 7da9ced6066c654a22836c24bae509ef323e10a8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/sound/sh_fsi.h | 2 + + sound/soc/sh/fsi.c | 232 +++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 234 insertions(+) + +diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h +index 78cd77a..b457e87 100644 +--- a/include/sound/sh_fsi.h ++++ b/include/sound/sh_fsi.h +@@ -74,6 +74,8 @@ + + struct sh_fsi_port_info { + unsigned long flags; ++ int tx_id; ++ int rx_id; + int (*set_rate)(struct device *dev, int rate, int enable); + }; + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 1374680..378cc5b 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -13,8 +13,11 @@ + */ + + #include <linux/delay.h> ++#include <linux/dma-mapping.h> + #include <linux/pm_runtime.h> + #include <linux/io.h> ++#include <linux/scatterlist.h> ++#include <linux/sh_dma.h> + #include <linux/slab.h> + #include <linux/module.h> + #include <sound/soc.h> +@@ -53,6 +56,7 @@ + + /* DO_FMT */ + /* DI_FMT */ ++#define CR_BWS_MASK (0x3 << 20) /* FSI2 */ + #define CR_BWS_24 (0x0 << 20) /* FSI2 */ + #define CR_BWS_16 (0x1 << 20) /* FSI2 */ + #define CR_BWS_20 (0x2 << 20) /* FSI2 */ +@@ -68,6 +72,15 @@ + #define CR_TDM (0x4 << 4) + #define CR_TDM_D (0x5 << 4) + ++/* OUT_DMAC */ ++/* IN_DMAC */ ++#define VDMD_MASK (0x3 << 4) ++#define VDMD_FRONT (0x0 << 4) /* Package in front */ ++#define VDMD_BACK (0x1 << 4) /* Package in back */ ++#define VDMD_STREAM (0x2 << 4) /* Stream mode(16bit * 2) */ ++ ++#define DMA_ON (0x1 << 0) ++ + /* DOFF_CTL */ + /* DIFF_CTL */ + #define IRQ_HALF 0x00100000 +@@ -180,6 +193,14 @@ struct fsi_stream { + */ + struct fsi_stream_handler *handler; + struct fsi_priv *priv; ++ ++ /* ++ * these are for DMAEngine ++ */ ++ struct dma_chan *chan; ++ struct sh_dmae_slave slave; /* see fsi_handler_init() */ ++ struct tasklet_struct tasklet; ++ dma_addr_t dma; + }; + + struct fsi_priv { +@@ -889,6 +910,212 @@ static irqreturn_t fsi_interrupt(int irq, void *data) + } + + /* ++ * dma data transfer handler ++ */ ++static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) ++{ ++ struct snd_pcm_runtime *runtime = io->substream->runtime; ++ struct snd_soc_dai *dai = fsi_get_dai(io->substream); ++ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? ++ DMA_TO_DEVICE : DMA_FROM_DEVICE; ++ ++ io->dma = dma_map_single(dai->dev, runtime->dma_area, ++ snd_pcm_lib_buffer_bytes(io->substream), dir); ++ return 0; ++} ++ ++static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io) ++{ ++ struct snd_soc_dai *dai = fsi_get_dai(io->substream); ++ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? ++ DMA_TO_DEVICE : DMA_FROM_DEVICE; ++ ++ dma_unmap_single(dai->dev, io->dma, ++ snd_pcm_lib_buffer_bytes(io->substream), dir); ++ return 0; ++} ++ ++static void fsi_dma_complete(void *data) ++{ ++ struct fsi_stream *io = (struct fsi_stream *)data; ++ struct fsi_priv *fsi = fsi_stream_to_priv(io); ++ struct snd_pcm_runtime *runtime = io->substream->runtime; ++ struct snd_soc_dai *dai = fsi_get_dai(io->substream); ++ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? ++ DMA_TO_DEVICE : DMA_FROM_DEVICE; ++ ++ dma_sync_single_for_cpu(dai->dev, io->dma, ++ samples_to_bytes(runtime, io->period_samples), dir); ++ ++ io->buff_sample_pos += io->period_samples; ++ io->period_pos++; ++ ++ if (io->period_pos >= runtime->periods) { ++ io->period_pos = 0; ++ io->buff_sample_pos = 0; ++ } ++ ++ fsi_count_fifo_err(fsi); ++ fsi_stream_transfer(io); ++ ++ snd_pcm_period_elapsed(io->substream); ++} ++ ++static dma_addr_t fsi_dma_get_area(struct fsi_stream *io) ++{ ++ struct snd_pcm_runtime *runtime = io->substream->runtime; ++ ++ return io->dma + samples_to_bytes(runtime, io->buff_sample_pos); ++} ++ ++static void fsi_dma_do_tasklet(unsigned long data) ++{ ++ struct fsi_stream *io = (struct fsi_stream *)data; ++ struct fsi_priv *fsi = fsi_stream_to_priv(io); ++ struct dma_chan *chan; ++ struct snd_soc_dai *dai; ++ struct dma_async_tx_descriptor *desc; ++ struct scatterlist sg; ++ struct snd_pcm_runtime *runtime; ++ enum dma_data_direction dir; ++ dma_cookie_t cookie; ++ int is_play = fsi_stream_is_play(fsi, io); ++ int len; ++ dma_addr_t buf; ++ ++ if (!fsi_stream_is_working(fsi, io)) ++ return; ++ ++ dai = fsi_get_dai(io->substream); ++ chan = io->chan; ++ runtime = io->substream->runtime; ++ dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; ++ len = samples_to_bytes(runtime, io->period_samples); ++ buf = fsi_dma_get_area(io); ++ ++ dma_sync_single_for_device(dai->dev, io->dma, len, dir); ++ ++ sg_init_table(&sg, 1); ++ sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)), ++ len , offset_in_page(buf)); ++ sg_dma_address(&sg) = buf; ++ sg_dma_len(&sg) = len; ++ ++ desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir, ++ DMA_PREP_INTERRUPT | ++ DMA_CTRL_ACK); ++ if (!desc) { ++ dev_err(dai->dev, "device_prep_slave_sg() fail\n"); ++ return; ++ } ++ ++ desc->callback = fsi_dma_complete; ++ desc->callback_param = io; ++ ++ cookie = desc->tx_submit(desc); ++ if (cookie < 0) { ++ dev_err(dai->dev, "tx_submit() fail\n"); ++ return; ++ } ++ ++ dma_async_issue_pending(chan); ++ ++ /* ++ * FIXME ++ * ++ * In DMAEngine case, codec and FSI cannot be started simultaneously ++ * since FSI is using tasklet. ++ * Therefore, in capture case, probably FSI FIFO will have got ++ * overflow error in this point. ++ * in that case, DMA cannot start transfer until error was cleared. ++ */ ++ if (!is_play) { ++ if (ERR_OVER & fsi_reg_read(fsi, DIFF_ST)) { ++ fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR); ++ fsi_reg_write(fsi, DIFF_ST, 0); ++ } ++ } ++} ++ ++static bool fsi_dma_filter(struct dma_chan *chan, void *param) ++{ ++ struct sh_dmae_slave *slave = param; ++ ++ chan->private = slave; ++ ++ return true; ++} ++ ++static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) ++{ ++ tasklet_schedule(&io->tasklet); ++ ++ return 0; ++} ++ ++static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, ++ int start) ++{ ++ u32 bws; ++ u32 dma; ++ ++ switch (io->sample_width * start) { ++ case 2: ++ bws = CR_BWS_16; ++ dma = VDMD_STREAM | DMA_ON; ++ break; ++ case 4: ++ bws = CR_BWS_24; ++ dma = VDMD_BACK | DMA_ON; ++ break; ++ default: ++ bws = 0; ++ dma = 0; ++ } ++ ++ fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws); ++ fsi_reg_write(fsi, OUT_DMAC, dma); ++} ++ ++static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) ++{ ++ dma_cap_mask_t mask; ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ ++ io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave); ++ if (!io->chan) ++ return -EIO; ++ ++ tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io); ++ ++ return 0; ++} ++ ++static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) ++{ ++ tasklet_kill(&io->tasklet); ++ ++ fsi_stream_stop(fsi, io); ++ ++ if (io->chan) ++ dma_release_channel(io->chan); ++ ++ io->chan = NULL; ++ return 0; ++} ++ ++static struct fsi_stream_handler fsi_dma_push_handler = { ++ .init = fsi_dma_init, ++ .quit = fsi_dma_quit, ++ .probe = fsi_dma_probe, ++ .transfer = fsi_dma_transfer, ++ .remove = fsi_dma_remove, ++ .start_stop = fsi_dma_push_start_stop, ++}; ++ ++/* + * dai ops + */ + static void fsi_fifo_init(struct fsi_priv *fsi, +@@ -1304,6 +1531,11 @@ static void fsi_handler_init(struct fsi_priv *fsi) + fsi->playback.priv = fsi; + fsi->capture.handler = &fsi_pio_pop_handler; /* default PIO */ + fsi->capture.priv = fsi; ++ ++ if (fsi->info->tx_id) { ++ fsi->playback.slave.slave_id = fsi->info->tx_id; ++ fsi->playback.handler = &fsi_dma_push_handler; ++ } + } + + static int fsi_probe(struct platform_device *pdev) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0119-ASoC-fsi-update-for-dmaengine-prep_slave_sg-fallout.patch b/patches.kzm9g/0119-ASoC-fsi-update-for-dmaengine-prep_slave_sg-fallout.patch new file mode 100644 index 00000000000000..993e4a8926debb --- /dev/null +++ b/patches.kzm9g/0119-ASoC-fsi-update-for-dmaengine-prep_slave_sg-fallout.patch @@ -0,0 +1,47 @@ +From d6964a7fc8d9cfbc0257030e420ed6dddc4f9a87 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Tue, 17 Apr 2012 19:13:04 -0700 +Subject: ASoC: fsi: update for dmaengine prep_slave_sg fallout. + +Leading up to the ->device_prep_slave_sg change in +185ecb5f4fd43911c35956d4cc7d94a1da30417f 'dmaengine: add context +parameter to prep_slave_sg and prep_dma_cyclic' a generic wrapper was +added in place to guard against the API change, though the fsi driver +wasn't updated in the process (presumably its dmaengine support hadn't +been merged yet at the time). This trivially switches over to the new +wrapper and gets it building again. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit cdf27f373781d8740b874b0b5c18142df32ebb52) + +N.B: This is not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 378cc5b..74ed2df 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1001,11 +1001,10 @@ static void fsi_dma_do_tasklet(unsigned long data) + sg_dma_address(&sg) = buf; + sg_dma_len(&sg) = len; + +- desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir, +- DMA_PREP_INTERRUPT | +- DMA_CTRL_ACK); ++ desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) { +- dev_err(dai->dev, "device_prep_slave_sg() fail\n"); ++ dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n"); + return; + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0120-ASoC-add-generic-simple-card-support.patch b/patches.kzm9g/0120-ASoC-add-generic-simple-card-support.patch new file mode 100644 index 00000000000000..55e724c70d040d --- /dev/null +++ b/patches.kzm9g/0120-ASoC-add-generic-simple-card-support.patch @@ -0,0 +1,241 @@ +From 9e1c94e5b246c84b209c492495aee356c9c5a697 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 8 Apr 2012 21:17:50 -0700 +Subject: ASoC: add generic simple-card support + +Current ASoC requires card.c file to each platforms in order to +specifies its CPU and Codecs pair. +But the differences between these were only value/strings of setting. +In order to reduce duplicate driver, this patch adds generic/simple-card. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit f2390880ec0264a0ed26b32c23bc23435b4297da) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/sound/simple_card.h | 38 ++++++++++++++ + sound/soc/Kconfig | 3 ++ + sound/soc/Makefile | 1 + + sound/soc/generic/Kconfig | 4 ++ + sound/soc/generic/Makefile | 3 ++ + sound/soc/generic/simple-card.c | 114 ++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 163 insertions(+) + create mode 100644 include/sound/simple_card.h + create mode 100644 sound/soc/generic/Kconfig + create mode 100644 sound/soc/generic/Makefile + create mode 100644 sound/soc/generic/simple-card.c + +diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h +new file mode 100644 +index 0000000..4b62b8d +--- /dev/null ++++ b/include/sound/simple_card.h +@@ -0,0 +1,38 @@ ++/* ++ * ASoC simple sound card support ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> ++ * ++ * 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 __SIMPLE_CARD_H ++#define __SIMPLE_CARD_H ++ ++#include <sound/soc.h> ++ ++struct asoc_simple_dai_init_info { ++ unsigned int fmt; ++ unsigned int cpu_daifmt; ++ unsigned int codec_daifmt; ++ unsigned int sysclk; ++}; ++ ++struct asoc_simple_card_info { ++ const char *name; ++ const char *card; ++ const char *cpu_dai; ++ const char *codec; ++ const char *platform; ++ const char *codec_dai; ++ struct asoc_simple_dai_init_info *init; /* for snd_link.init */ ++ ++ /* used in simple-card.c */ ++ struct snd_soc_dai_link snd_link; ++ struct snd_soc_card snd_card; ++}; ++ ++#endif /* __SIMPLE_CARD_H */ +diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig +index 8224db5..73e4a6f 100644 +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -61,5 +61,8 @@ source "sound/soc/txx9/Kconfig" + # Supported codecs + source "sound/soc/codecs/Kconfig" + ++# generic frame-work ++source "sound/soc/generic/Kconfig" ++ + endif # SND_SOC + +diff --git a/sound/soc/Makefile b/sound/soc/Makefile +index adb5719..bb3caf8 100644 +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -2,6 +2,7 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o so + + obj-$(CONFIG_SND_SOC) += snd-soc-core.o + obj-$(CONFIG_SND_SOC) += codecs/ ++obj-$(CONFIG_SND_SOC) += generic/ + obj-$(CONFIG_SND_SOC) += atmel/ + obj-$(CONFIG_SND_SOC) += au1x/ + obj-$(CONFIG_SND_SOC) += blackfin/ +diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig +new file mode 100644 +index 0000000..610f612 +--- /dev/null ++++ b/sound/soc/generic/Kconfig +@@ -0,0 +1,4 @@ ++config SND_SIMPLE_CARD ++ tristate "ASoC Simple sound card support" ++ help ++ This option enables generic simple sound card support +diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile +new file mode 100644 +index 0000000..9c3b246 +--- /dev/null ++++ b/sound/soc/generic/Makefile +@@ -0,0 +1,3 @@ ++snd-soc-simple-card-objs := simple-card.o ++ ++obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o +diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c +new file mode 100644 +index 0000000..b4b4cab +--- /dev/null ++++ b/sound/soc/generic/simple-card.c +@@ -0,0 +1,114 @@ ++/* ++ * ASoC simple sound card support ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> ++ * ++ * 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. ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/module.h> ++#include <sound/simple_card.h> ++ ++#define asoc_simple_get_card_info(p) \ ++ container_of(p->dai_link, struct asoc_simple_card_info, snd_link) ++ ++static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct asoc_simple_card_info *cinfo = asoc_simple_get_card_info(rtd); ++ struct asoc_simple_dai_init_info *iinfo = cinfo->init; ++ struct snd_soc_dai *codec = rtd->codec_dai; ++ struct snd_soc_dai *cpu = rtd->cpu_dai; ++ unsigned int cpu_daifmt = iinfo->fmt | iinfo->cpu_daifmt; ++ unsigned int codec_daifmt = iinfo->fmt | iinfo->codec_daifmt; ++ int ret; ++ ++ if (codec_daifmt) { ++ ret = snd_soc_dai_set_fmt(codec, codec_daifmt); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (iinfo->sysclk) { ++ ret = snd_soc_dai_set_sysclk(codec, 0, iinfo->sysclk, 0); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (cpu_daifmt) { ++ ret = snd_soc_dai_set_fmt(cpu, cpu_daifmt); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int asoc_simple_card_probe(struct platform_device *pdev) ++{ ++ struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; ++ ++ if (!cinfo) { ++ dev_err(&pdev->dev, "no info for asoc-simple-card\n"); ++ return -EINVAL; ++ } ++ ++ if (!cinfo->name || ++ !cinfo->card || ++ !cinfo->cpu_dai || ++ !cinfo->codec || ++ !cinfo->platform || ++ !cinfo->codec_dai) { ++ dev_err(&pdev->dev, "insufficient asoc_simple_card_info settings\n"); ++ return -EINVAL; ++ } ++ ++ /* ++ * init snd_soc_dai_link ++ */ ++ cinfo->snd_link.name = cinfo->name; ++ cinfo->snd_link.stream_name = cinfo->name; ++ cinfo->snd_link.cpu_dai_name = cinfo->cpu_dai; ++ cinfo->snd_link.platform_name = cinfo->platform; ++ cinfo->snd_link.codec_name = cinfo->codec; ++ cinfo->snd_link.codec_dai_name = cinfo->codec_dai; ++ ++ /* enable snd_link.init if cinfo has settings */ ++ if (cinfo->init) ++ cinfo->snd_link.init = asoc_simple_card_dai_init; ++ ++ /* ++ * init snd_soc_card ++ */ ++ cinfo->snd_card.name = cinfo->card; ++ cinfo->snd_card.owner = THIS_MODULE; ++ cinfo->snd_card.dai_link = &cinfo->snd_link; ++ cinfo->snd_card.num_links = 1; ++ cinfo->snd_card.dev = &pdev->dev; ++ ++ return snd_soc_register_card(&cinfo->snd_card); ++} ++ ++static int asoc_simple_card_remove(struct platform_device *pdev) ++{ ++ struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; ++ ++ return snd_soc_unregister_card(&cinfo->snd_card); ++} ++ ++static struct platform_driver asoc_simple_card = { ++ .driver = { ++ .name = "asoc-simple-card", ++ }, ++ .probe = asoc_simple_card_probe, ++ .remove = asoc_simple_card_remove, ++}; ++ ++module_platform_driver(asoc_simple_card); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("ASoC Simple Sound Card"); ++MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0121-ASoC-sh-fsi-select-simple-card-on-Kconfig.patch b/patches.kzm9g/0121-ASoC-sh-fsi-select-simple-card-on-Kconfig.patch new file mode 100644 index 00000000000000..5c478bb8f2f33f --- /dev/null +++ b/patches.kzm9g/0121-ASoC-sh-fsi-select-simple-card-on-Kconfig.patch @@ -0,0 +1,34 @@ +From 466e94a3b185d97436c0ad54eac135d4127f2c61 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 8 Apr 2012 21:20:08 -0700 +Subject: ASoC: sh: fsi: select simple-card on Kconfig + +Current SuperH FSI require simple-card driver as sound card. +This patch select it on Kconfig when FSI was selected. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit cd04461e2f491c81d30fb3b234cf43db3f098103) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig +index d8e06a6..fb8abc1 100644 +--- a/sound/soc/sh/Kconfig ++++ b/sound/soc/sh/Kconfig +@@ -22,6 +22,7 @@ config SND_SOC_SH4_SSI + + config SND_SOC_SH4_FSI + tristate "SH4 FSI support" ++ select SND_SIMPLE_CARD + help + This option enables FSI sound support + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0122-ASoC-ak4642-convert-to-soc-cache.patch b/patches.kzm9g/0122-ASoC-ak4642-convert-to-soc-cache.patch new file mode 100644 index 00000000000000..8af07324da4b95 --- /dev/null +++ b/patches.kzm9g/0122-ASoC-ak4642-convert-to-soc-cache.patch @@ -0,0 +1,162 @@ +From 7e7b8eea233be75675adf28e0b77f8925cd3f294 Mon Sep 17 00:00:00 2001 +From: Axel Lin <axel.lin@gmail.com> +Date: Tue, 11 Oct 2011 20:20:53 +0800 +Subject: ASoC: ak4642: convert to soc-cache + +Signed-off-by: Axel Lin <axel.lin@gmail.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit b91470bb374ed7db0448696ec85a3ed4785da2ee) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/codecs/ak4642.c | 82 +++++++---------------------------------------- + 1 file changed, 12 insertions(+), 70 deletions(-) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index 7d45197..30c8e2c 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -156,7 +156,6 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { + struct ak4642_priv { + unsigned int sysclk; + enum snd_soc_control_type control_type; +- void *control_data; + }; + + /* +@@ -175,64 +174,6 @@ static const u8 ak4642_reg[AK4642_CACHEREGNUM] = { + 0x00, + }; + +-/* +- * read ak4642 register cache +- */ +-static inline unsigned int ak4642_read_reg_cache(struct snd_soc_codec *codec, +- unsigned int reg) +-{ +- u16 *cache = codec->reg_cache; +- if (reg >= AK4642_CACHEREGNUM) +- return -1; +- return cache[reg]; +-} +- +-/* +- * write ak4642 register cache +- */ +-static inline void ak4642_write_reg_cache(struct snd_soc_codec *codec, +- u16 reg, unsigned int value) +-{ +- u16 *cache = codec->reg_cache; +- if (reg >= AK4642_CACHEREGNUM) +- return; +- +- cache[reg] = value; +-} +- +-/* +- * write to the AK4642 register space +- */ +-static int ak4642_write(struct snd_soc_codec *codec, unsigned int reg, +- unsigned int value) +-{ +- u8 data[2]; +- +- /* data is +- * D15..D8 AK4642 register offset +- * D7...D0 register data +- */ +- data[0] = reg & 0xff; +- data[1] = value & 0xff; +- +- if (codec->hw_write(codec->control_data, data, 2) == 2) { +- ak4642_write_reg_cache(codec, reg, value); +- return 0; +- } else +- return -EIO; +-} +- +-static int ak4642_sync(struct snd_soc_codec *codec) +-{ +- u16 *cache = codec->reg_cache; +- int i, r = 0; +- +- for (i = 0; i < AK4642_CACHEREGNUM; i++) +- r |= ak4642_write(codec, i, cache[i]); +- +- return r; +-}; +- + static int ak4642_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { +@@ -252,8 +193,8 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, + */ + snd_soc_update_bits(codec, MD_CTL4, DACH, DACH); + snd_soc_update_bits(codec, MD_CTL3, BST1, BST1); +- ak4642_write(codec, L_IVC, 0x91); /* volume */ +- ak4642_write(codec, R_IVC, 0x91); /* volume */ ++ snd_soc_write(codec, L_IVC, 0x91); /* volume */ ++ snd_soc_write(codec, R_IVC, 0x91); /* volume */ + snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC, + PMVCM | PMMIN | PMDAC); + snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP); +@@ -272,9 +213,9 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, + * This operation came from example code of + * "ASAHI KASEI AK4642" (japanese) manual p94. + */ +- ak4642_write(codec, SG_SL1, PMMP | MGAIN0); +- ak4642_write(codec, TIMER, ZTM(0x3) | WTM(0x3)); +- ak4642_write(codec, ALC_CTL1, ALC | LMTH0); ++ snd_soc_write(codec, SG_SL1, PMMP | MGAIN0); ++ snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3)); ++ snd_soc_write(codec, ALC_CTL1, ALC | LMTH0); + snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL, + PMVCM | PMADL); + snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR); +@@ -462,7 +403,7 @@ static struct snd_soc_dai_driver ak4642_dai = { + + static int ak4642_resume(struct snd_soc_codec *codec) + { +- ak4642_sync(codec); ++ snd_soc_cache_sync(codec); + return 0; + } + +@@ -470,11 +411,15 @@ static int ak4642_resume(struct snd_soc_codec *codec) + static int ak4642_probe(struct snd_soc_codec *codec) + { + struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec); ++ int ret; + + dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION); + +- codec->hw_write = (hw_write_t)i2c_master_send; +- codec->control_data = ak4642->control_data; ++ ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type); ++ if (ret < 0) { ++ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); ++ return ret; ++ } + + snd_soc_add_controls(codec, ak4642_snd_controls, + ARRAY_SIZE(ak4642_snd_controls)); +@@ -485,8 +430,6 @@ static int ak4642_probe(struct snd_soc_codec *codec) + static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { + .probe = ak4642_probe, + .resume = ak4642_resume, +- .read = ak4642_read_reg_cache, +- .write = ak4642_write, + .reg_cache_size = ARRAY_SIZE(ak4642_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = ak4642_reg, +@@ -504,7 +447,6 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, + return -ENOMEM; + + i2c_set_clientdata(i2c, ak4642); +- ak4642->control_data = i2c; + ak4642->control_type = SND_SOC_I2C; + + ret = snd_soc_register_codec(&i2c->dev, +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0123-ASoC-ak4642-ak4642-was-tested.patch b/patches.kzm9g/0123-ASoC-ak4642-ak4642-was-tested.patch new file mode 100644 index 00000000000000..d2b3c3629faf05 --- /dev/null +++ b/patches.kzm9g/0123-ASoC-ak4642-ak4642-was-tested.patch @@ -0,0 +1,32 @@ +From 10f6b67d626f47c3a8e2ff83181f8ca85f8c39b9 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 6 Nov 2011 22:04:53 -0800 +Subject: ASoC: ak4642: ak4642 was tested + +ak4642 was tested by ms7724se board + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 202113912ba117b5c5f36e45529921b4cca4be6a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/codecs/ak4642.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index 30c8e2c..96f6e2f 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -18,7 +18,7 @@ + * This is very simple driver. + * It can use headphone output / stereo input only + * +- * AK4642 is not tested. ++ * AK4642 is tested. + * AK4643 is tested. + */ + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0124-ASoC-ak4642-add-ak4642_set_bias_level.patch b/patches.kzm9g/0124-ASoC-ak4642-add-ak4642_set_bias_level.patch new file mode 100644 index 00000000000000..734a854e68588f --- /dev/null +++ b/patches.kzm9g/0124-ASoC-ak4642-add-ak4642_set_bias_level.patch @@ -0,0 +1,88 @@ +From 9c25a0a4023775793af9678041183eb80b268ac5 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 10 Nov 2011 16:21:01 -0800 +Subject: ASoC: ak4642: add ak4642_set_bias_level() + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit ed2dd7da35cad3115c38fd42eecbecae899a1d7a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/codecs/ak4642.c | 33 +++++++++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index 96f6e2f..8946580 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -195,8 +195,8 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, + snd_soc_update_bits(codec, MD_CTL3, BST1, BST1); + snd_soc_write(codec, L_IVC, 0x91); /* volume */ + snd_soc_write(codec, R_IVC, 0x91); /* volume */ +- snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC, +- PMVCM | PMMIN | PMDAC); ++ snd_soc_update_bits(codec, PW_MGMT1, PMMIN | PMDAC, ++ PMMIN | PMDAC); + snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP); + snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN); + } else { +@@ -216,8 +216,7 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, + snd_soc_write(codec, SG_SL1, PMMP | MGAIN0); + snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3)); + snd_soc_write(codec, ALC_CTL1, ALC | LMTH0); +- snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL, +- PMVCM | PMADL); ++ snd_soc_update_bits(codec, PW_MGMT1, PMADL, PMADL); + snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR); + } + +@@ -375,6 +374,22 @@ static int ak4642_dai_hw_params(struct snd_pcm_substream *substream, + return 0; + } + ++static int ak4642_set_bias_level(struct snd_soc_codec *codec, ++ enum snd_soc_bias_level level) ++{ ++ switch (level) { ++ case SND_SOC_BIAS_OFF: ++ snd_soc_write(codec, PW_MGMT1, 0x00); ++ break; ++ default: ++ snd_soc_update_bits(codec, PW_MGMT1, PMVCM, PMVCM); ++ break; ++ } ++ codec->dapm.bias_level = level; ++ ++ return 0; ++} ++ + static struct snd_soc_dai_ops ak4642_dai_ops = { + .startup = ak4642_dai_startup, + .shutdown = ak4642_dai_shutdown, +@@ -424,12 +439,22 @@ static int ak4642_probe(struct snd_soc_codec *codec) + snd_soc_add_controls(codec, ak4642_snd_controls, + ARRAY_SIZE(ak4642_snd_controls)); + ++ ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); ++ ++ return 0; ++} ++ ++static int ak4642_remove(struct snd_soc_codec *codec) ++{ ++ ak4642_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; + } + + static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { + .probe = ak4642_probe, ++ .remove = ak4642_remove, + .resume = ak4642_resume, ++ .set_bias_level = ak4642_set_bias_level, + .reg_cache_size = ARRAY_SIZE(ak4642_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = ak4642_reg, +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0125-ASoC-ak4642-add-DAPM-support-for-HeadPhone-Output.patch b/patches.kzm9g/0125-ASoC-ak4642-add-DAPM-support-for-HeadPhone-Output.patch new file mode 100644 index 00000000000000..821fa3dc100ae5 --- /dev/null +++ b/patches.kzm9g/0125-ASoC-ak4642-add-DAPM-support-for-HeadPhone-Output.patch @@ -0,0 +1,95 @@ +From 846a99689a9e20740e47fa868766f9bc56afd969 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 10 Nov 2011 16:21:31 -0800 +Subject: ASoC: ak4642: add DAPM support for HeadPhone Output + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 24747daea5610676fd1e2c2ca603c8822a085c87) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/codecs/ak4642.c | 44 +++++++++++++++++++++++++++++++++++--------- + 1 file changed, 35 insertions(+), 9 deletions(-) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index 8946580..dd0c835 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -151,6 +151,37 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { + 0, 0xFF, 1, out_tlv), + }; + ++static const struct snd_kcontrol_new ak4642_hpout_mixer_controls[] = { ++ SOC_DAPM_SINGLE("DACH", MD_CTL4, 0, 1, 0), ++}; ++ ++static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = { ++ ++ /* Outputs */ ++ SND_SOC_DAPM_OUTPUT("HPOUTL"), ++ SND_SOC_DAPM_OUTPUT("HPOUTR"), ++ ++ SND_SOC_DAPM_MIXER("HPOUTL Mixer", PW_MGMT2, 5, 0, ++ &ak4642_hpout_mixer_controls[0], ++ ARRAY_SIZE(ak4642_hpout_mixer_controls)), ++ ++ SND_SOC_DAPM_MIXER("HPOUTR Mixer", PW_MGMT2, 4, 0, ++ &ak4642_hpout_mixer_controls[0], ++ ARRAY_SIZE(ak4642_hpout_mixer_controls)), ++ ++ /* DAC */ ++ SND_SOC_DAPM_DAC("DAC", "HiFi Playback", PW_MGMT1, 2, 0), ++}; ++ ++static const struct snd_soc_dapm_route ak4642_intercon[] = { ++ ++ /* Outputs */ ++ {"HPOUTL", NULL, "HPOUTL Mixer"}, ++ {"HPOUTR", NULL, "HPOUTR Mixer"}, ++ ++ {"HPOUTL Mixer", "DACH", "DAC"}, ++ {"HPOUTR Mixer", "DACH", "DAC"}, ++}; + + /* codec private data */ + struct ak4642_priv { +@@ -191,13 +222,8 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, + * This operation came from example code of + * "ASAHI KASEI AK4642" (japanese) manual p97. + */ +- snd_soc_update_bits(codec, MD_CTL4, DACH, DACH); +- snd_soc_update_bits(codec, MD_CTL3, BST1, BST1); + snd_soc_write(codec, L_IVC, 0x91); /* volume */ + snd_soc_write(codec, R_IVC, 0x91); /* volume */ +- snd_soc_update_bits(codec, PW_MGMT1, PMMIN | PMDAC, +- PMMIN | PMDAC); +- snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP); + snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN); + } else { + /* +@@ -232,10 +258,6 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream, + if (is_play) { + /* stop headphone output */ + snd_soc_update_bits(codec, PW_MGMT2, HPMTN, 0); +- snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0); +- snd_soc_update_bits(codec, PW_MGMT1, PMMIN | PMDAC, 0); +- snd_soc_update_bits(codec, MD_CTL3, BST1, 0); +- snd_soc_update_bits(codec, MD_CTL4, DACH, 0); + } else { + /* stop stereo input */ + snd_soc_update_bits(codec, PW_MGMT1, PMADL, 0); +@@ -458,6 +480,10 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { + .reg_cache_size = ARRAY_SIZE(ak4642_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = ak4642_reg, ++ .dapm_widgets = ak4642_dapm_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), ++ .dapm_routes = ak4642_intercon, ++ .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), + }; + + #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0126-ASoC-ak4642-add-headphone-mute-switch-control.patch b/patches.kzm9g/0126-ASoC-ak4642-add-headphone-mute-switch-control.patch new file mode 100644 index 00000000000000..9cb4990d757059 --- /dev/null +++ b/patches.kzm9g/0126-ASoC-ak4642-add-headphone-mute-switch-control.patch @@ -0,0 +1,47 @@ +From f77165fc08deee82107e20f35969d07a20340f94 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 10 Nov 2011 16:21:42 -0800 +Subject: ASoC: ak4642: add headphone mute switch control + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 3c7035268c2c89942fe51a61833d1066b4a766eb) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/codecs/ak4642.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index dd0c835..f728181 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -149,6 +149,8 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { + + SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC, + 0, 0xFF, 1, out_tlv), ++ ++ SOC_SINGLE("Headphone Switch", PW_MGMT2, 6, 1, 0), + }; + + static const struct snd_kcontrol_new ak4642_hpout_mixer_controls[] = { +@@ -224,7 +226,6 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, + */ + snd_soc_write(codec, L_IVC, 0x91); /* volume */ + snd_soc_write(codec, R_IVC, 0x91); /* volume */ +- snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN); + } else { + /* + * start stereo input +@@ -256,8 +257,6 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_codec *codec = dai->codec; + + if (is_play) { +- /* stop headphone output */ +- snd_soc_update_bits(codec, PW_MGMT2, HPMTN, 0); + } else { + /* stop stereo input */ + snd_soc_update_bits(codec, PW_MGMT1, PMADL, 0); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0127-ASoC-ak4642-add-Line-out-support.patch b/patches.kzm9g/0127-ASoC-ak4642-add-Line-out-support.patch new file mode 100644 index 00000000000000..7f11a0f54fa8b9 --- /dev/null +++ b/patches.kzm9g/0127-ASoC-ak4642-add-Line-out-support.patch @@ -0,0 +1,61 @@ +From 5b5d2d5ef56e2faf823428eecd05c9fdc6d5945f Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 10 Nov 2011 16:21:55 -0800 +Subject: ASoC: ak4642: add Line out support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit e8c83dbfb7fc0c3cec141112524906b029a1f413) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/codecs/ak4642.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index f728181..0f2ee7f 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -157,11 +157,16 @@ static const struct snd_kcontrol_new ak4642_hpout_mixer_controls[] = { + SOC_DAPM_SINGLE("DACH", MD_CTL4, 0, 1, 0), + }; + ++static const struct snd_kcontrol_new ak4642_lout_mixer_controls[] = { ++ SOC_DAPM_SINGLE("DACL", SG_SL1, 4, 1, 0), ++}; ++ + static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = { + + /* Outputs */ + SND_SOC_DAPM_OUTPUT("HPOUTL"), + SND_SOC_DAPM_OUTPUT("HPOUTR"), ++ SND_SOC_DAPM_OUTPUT("LINEOUT"), + + SND_SOC_DAPM_MIXER("HPOUTL Mixer", PW_MGMT2, 5, 0, + &ak4642_hpout_mixer_controls[0], +@@ -171,6 +176,10 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = { + &ak4642_hpout_mixer_controls[0], + ARRAY_SIZE(ak4642_hpout_mixer_controls)), + ++ SND_SOC_DAPM_MIXER("LINEOUT Mixer", PW_MGMT1, 3, 0, ++ &ak4642_lout_mixer_controls[0], ++ ARRAY_SIZE(ak4642_lout_mixer_controls)), ++ + /* DAC */ + SND_SOC_DAPM_DAC("DAC", "HiFi Playback", PW_MGMT1, 2, 0), + }; +@@ -180,9 +189,11 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = { + /* Outputs */ + {"HPOUTL", NULL, "HPOUTL Mixer"}, + {"HPOUTR", NULL, "HPOUTR Mixer"}, ++ {"LINEOUT", NULL, "LINEOUT Mixer"}, + + {"HPOUTL Mixer", "DACH", "DAC"}, + {"HPOUTR Mixer", "DACH", "DAC"}, ++ {"LINEOUT Mixer", "DACL", "DAC"}, + }; + + /* codec private data */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0128-ASoC-ak4642-add-ak4648-support.patch b/patches.kzm9g/0128-ASoC-ak4642-add-ak4648-support.patch new file mode 100644 index 00000000000000..4a8bd0825771a8 --- /dev/null +++ b/patches.kzm9g/0128-ASoC-ak4642-add-ak4648-support.patch @@ -0,0 +1,115 @@ +From 03977c4c632d21018c3b9bcc076c3b62aeb91579 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 10 Nov 2011 16:22:05 -0800 +Subject: ASoC: ak4642: add ak4648 support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit a9317e8b6b53ab61d3ee764b6456596efd8c83b7) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/codecs/ak4642.c | 44 ++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 36 insertions(+), 8 deletions(-) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index 0f2ee7f..8a12db4 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -20,6 +20,7 @@ + * + * AK4642 is tested. + * AK4643 is tested. ++ * AK4648 is tested. + */ + + #include <linux/delay.h> +@@ -70,8 +71,6 @@ + #define HP_MS 0x23 + #define SPK_MS 0x24 + +-#define AK4642_CACHEREGNUM 0x25 +- + /* PW_MGMT1*/ + #define PMVCM (1 << 6) /* VCOM Power Management */ + #define PMMIN (1 << 5) /* MIN Input Power Management */ +@@ -205,7 +204,7 @@ struct ak4642_priv { + /* + * ak4642 register cache + */ +-static const u8 ak4642_reg[AK4642_CACHEREGNUM] = { ++static const u8 ak4642_reg[] = { + 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0xe1, 0xe1, 0x18, 0x00, +@@ -218,6 +217,19 @@ static const u8 ak4642_reg[AK4642_CACHEREGNUM] = { + 0x00, + }; + ++static const u8 ak4648_reg[] = { ++ 0x00, 0x00, 0x01, 0x00, ++ 0x02, 0x00, 0x00, 0x00, ++ 0xe1, 0xe1, 0x18, 0x00, ++ 0xe1, 0x18, 0x11, 0xb8, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x88, 0x88, 0x08, ++}; ++ + static int ak4642_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { +@@ -487,9 +499,23 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { + .remove = ak4642_remove, + .resume = ak4642_resume, + .set_bias_level = ak4642_set_bias_level, +- .reg_cache_size = ARRAY_SIZE(ak4642_reg), ++ .reg_cache_default = ak4642_reg, /* ak4642 reg */ ++ .reg_cache_size = ARRAY_SIZE(ak4642_reg), /* ak4642 reg */ ++ .reg_word_size = sizeof(u8), ++ .dapm_widgets = ak4642_dapm_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), ++ .dapm_routes = ak4642_intercon, ++ .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), ++}; ++ ++static struct snd_soc_codec_driver soc_codec_dev_ak4648 = { ++ .probe = ak4642_probe, ++ .remove = ak4642_remove, ++ .resume = ak4642_resume, ++ .set_bias_level = ak4642_set_bias_level, ++ .reg_cache_default = ak4648_reg, /* ak4648 reg */ ++ .reg_cache_size = ARRAY_SIZE(ak4648_reg), /* ak4648 reg */ + .reg_word_size = sizeof(u8), +- .reg_cache_default = ak4642_reg, + .dapm_widgets = ak4642_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), + .dapm_routes = ak4642_intercon, +@@ -511,7 +537,8 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, + ak4642->control_type = SND_SOC_I2C; + + ret = snd_soc_register_codec(&i2c->dev, +- &soc_codec_dev_ak4642, &ak4642_dai, 1); ++ (struct snd_soc_codec_driver *)id->driver_data, ++ &ak4642_dai, 1); + if (ret < 0) + kfree(ak4642); + return ret; +@@ -525,8 +552,9 @@ static __devexit int ak4642_i2c_remove(struct i2c_client *client) + } + + static const struct i2c_device_id ak4642_i2c_id[] = { +- { "ak4642", 0 }, +- { "ak4643", 0 }, ++ { "ak4642", (kernel_ulong_t)&soc_codec_dev_ak4642 }, ++ { "ak4643", (kernel_ulong_t)&soc_codec_dev_ak4642 }, ++ { "ak4648", (kernel_ulong_t)&soc_codec_dev_ak4648 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0129-ASoC-Remove-driver-versioning-from-ak4642.patch b/patches.kzm9g/0129-ASoC-Remove-driver-versioning-from-ak4642.patch new file mode 100644 index 00000000000000..5b32a8991315bf --- /dev/null +++ b/patches.kzm9g/0129-ASoC-Remove-driver-versioning-from-ak4642.patch @@ -0,0 +1,41 @@ +From 5433d40ad2e432a05413d77baa7a3c0869fcc75c Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@opensource.wolfsonmicro.com> +Date: Sun, 27 Nov 2011 12:11:46 +0000 +Subject: ASoC: Remove driver versioning from ak4642 + +It's never been updated so it can't be that useful and it makes the +driver needlessly chatty. + +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 679acec1f240b433dc3879714655b6c6452385ea) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/codecs/ak4642.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index 8a12db4..a04eebf 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -31,8 +31,6 @@ + #include <sound/initval.h> + #include <sound/tlv.h> + +-#define AK4642_VERSION "0.0.1" +- + #define PW_MGMT1 0x00 + #define PW_MGMT2 0x01 + #define SG_SL1 0x02 +@@ -472,8 +470,6 @@ static int ak4642_probe(struct snd_soc_codec *codec) + struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec); + int ret; + +- dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION); +- + ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0130-ASoC-Convert-ak4642-to-devm_kzalloc.patch b/patches.kzm9g/0130-ASoC-Convert-ak4642-to-devm_kzalloc.patch new file mode 100644 index 00000000000000..a9af28c5a85b10 --- /dev/null +++ b/patches.kzm9g/0130-ASoC-Convert-ak4642-to-devm_kzalloc.patch @@ -0,0 +1,47 @@ +From de89e5feef647f18b97650663538b91a7c11754c Mon Sep 17 00:00:00 2001 +From: Axel Lin <axel.lin@gmail.com> +Date: Tue, 20 Dec 2011 14:40:12 +0800 +Subject: ASoC: Convert ak4642 to devm_kzalloc() + +Signed-off-by: Axel Lin <axel.lin@gmail.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 2ff49eea9b8a1d92c2ab09d803dfdc06f4f8e74b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/codecs/ak4642.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index a04eebf..2cdcea2 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -525,7 +525,8 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, + struct ak4642_priv *ak4642; + int ret; + +- ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); ++ ak4642 = devm_kzalloc(&i2c->dev, sizeof(struct ak4642_priv), ++ GFP_KERNEL); + if (!ak4642) + return -ENOMEM; + +@@ -535,15 +536,12 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, + ret = snd_soc_register_codec(&i2c->dev, + (struct snd_soc_codec_driver *)id->driver_data, + &ak4642_dai, 1); +- if (ret < 0) +- kfree(ak4642); + return ret; + } + + static __devexit int ak4642_i2c_remove(struct i2c_client *client) + { + snd_soc_unregister_codec(&client->dev); +- kfree(i2c_get_clientdata(client)); + return 0; + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0131-ASoC-ak4642-fixup-HeadPhone-L-R-dapm-settings.patch b/patches.kzm9g/0131-ASoC-ak4642-fixup-HeadPhone-L-R-dapm-settings.patch new file mode 100644 index 00000000000000..fb79827dfd5a65 --- /dev/null +++ b/patches.kzm9g/0131-ASoC-ak4642-fixup-HeadPhone-L-R-dapm-settings.patch @@ -0,0 +1,85 @@ +From 74ca5f2a0fe5cb5938687814e9dbceb6e0da98fd Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 20 Feb 2012 20:14:16 -0800 +Subject: ASoC: ak4642: fixup HeadPhone L/R dapm settings + +Current ak4642 driver had wrong dapm settings for headphone L/R. +If you select headphone L, and select R after that, +headphone L setting was removed by R settings. + +This patch fixes it up. +It provides just "Headphone Enable" to user side + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit e555cf363167f09efae96d32a363e24c4de16b7b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/codecs/ak4642.c | 31 ++++++++++++++++--------------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index 2cdcea2..6a9516ca 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -146,13 +146,10 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { + + SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC, + 0, 0xFF, 1, out_tlv), +- +- SOC_SINGLE("Headphone Switch", PW_MGMT2, 6, 1, 0), + }; + +-static const struct snd_kcontrol_new ak4642_hpout_mixer_controls[] = { +- SOC_DAPM_SINGLE("DACH", MD_CTL4, 0, 1, 0), +-}; ++static const struct snd_kcontrol_new ak4642_headphone_control = ++ SOC_DAPM_SINGLE("Switch", PW_MGMT2, 6, 1, 0); + + static const struct snd_kcontrol_new ak4642_lout_mixer_controls[] = { + SOC_DAPM_SINGLE("DACL", SG_SL1, 4, 1, 0), +@@ -165,13 +162,12 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = { + SND_SOC_DAPM_OUTPUT("HPOUTR"), + SND_SOC_DAPM_OUTPUT("LINEOUT"), + +- SND_SOC_DAPM_MIXER("HPOUTL Mixer", PW_MGMT2, 5, 0, +- &ak4642_hpout_mixer_controls[0], +- ARRAY_SIZE(ak4642_hpout_mixer_controls)), ++ SND_SOC_DAPM_PGA("HPL Out", PW_MGMT2, 5, 0, NULL, 0), ++ SND_SOC_DAPM_PGA("HPR Out", PW_MGMT2, 4, 0, NULL, 0), ++ SND_SOC_DAPM_SWITCH("Headphone Enable", SND_SOC_NOPM, 0, 0, ++ &ak4642_headphone_control), + +- SND_SOC_DAPM_MIXER("HPOUTR Mixer", PW_MGMT2, 4, 0, +- &ak4642_hpout_mixer_controls[0], +- ARRAY_SIZE(ak4642_hpout_mixer_controls)), ++ SND_SOC_DAPM_PGA("DACH", MD_CTL4, 0, 0, NULL, 0), + + SND_SOC_DAPM_MIXER("LINEOUT Mixer", PW_MGMT1, 3, 0, + &ak4642_lout_mixer_controls[0], +@@ -184,12 +180,17 @@ static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = { + static const struct snd_soc_dapm_route ak4642_intercon[] = { + + /* Outputs */ +- {"HPOUTL", NULL, "HPOUTL Mixer"}, +- {"HPOUTR", NULL, "HPOUTR Mixer"}, ++ {"HPOUTL", NULL, "HPL Out"}, ++ {"HPOUTR", NULL, "HPR Out"}, + {"LINEOUT", NULL, "LINEOUT Mixer"}, + +- {"HPOUTL Mixer", "DACH", "DAC"}, +- {"HPOUTR Mixer", "DACH", "DAC"}, ++ {"HPL Out", NULL, "Headphone Enable"}, ++ {"HPR Out", NULL, "Headphone Enable"}, ++ ++ {"Headphone Enable", "Switch", "DACH"}, ++ ++ {"DACH", NULL, "DAC"}, ++ + {"LINEOUT Mixer", "DACL", "DAC"}, + }; + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0132-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch b/patches.kzm9g/0132-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch new file mode 100644 index 00000000000000..6b9c9ad480c4c7 --- /dev/null +++ b/patches.kzm9g/0132-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch @@ -0,0 +1,54 @@ +From 08bfd254a0ea22a80db19e5b13cb6f7fa745ee5d Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:08:11 -0700 +Subject: ARM: mach-shmobile: clock-r8a7740: add SDHI clock + +N.B: Not present upstream yet + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 30535f4..5c6b548 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -356,8 +356,9 @@ enum { + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + + MSTP329, MSTP323, MSTP320, ++ MSTP314, MSTP313, + +- MSTP416, MSTP407, MSTP406, ++ MSTP416, MSTP415, MSTP407, MSTP406, + + MSTP_NR + }; +@@ -382,8 +383,11 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ + [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ + [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ ++ [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ ++ [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */ + + [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ ++ [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */ + [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */ + [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */ + }; +@@ -442,6 +446,10 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), + CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), + CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), ++ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), ++ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), ++ ++ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), + + /* ICK */ + CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]), +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0133-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch b/patches.kzm9g/0133-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch new file mode 100644 index 00000000000000..1540498275ec9a --- /dev/null +++ b/patches.kzm9g/0133-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch @@ -0,0 +1,45 @@ +From 1e625ddaa54bdddc2e7c97a6776634b257512de4 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:08:29 -0700 +Subject: ARM: mach-shmobile: clock-r8a7740: add MMCIF clock + +N.B: Not present upstream yet + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 5c6b548..927d42a 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -356,7 +356,7 @@ enum { + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + + MSTP329, MSTP323, MSTP320, +- MSTP314, MSTP313, ++ MSTP314, MSTP313, MSTP312, + + MSTP416, MSTP415, MSTP407, MSTP406, + +@@ -385,6 +385,7 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ + [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ + [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */ ++ [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */ + + [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ + [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */ +@@ -448,6 +449,7 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), + CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), + CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), ++ CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]), + + CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0134-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch b/patches.kzm9g/0134-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch new file mode 100644 index 00000000000000..932f3f973a4284 --- /dev/null +++ b/patches.kzm9g/0134-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch @@ -0,0 +1,44 @@ +From daaa13e4d7c9028792b6b51ef2e147993c6e9c91 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:10:05 -0700 +Subject: ARM: mach-shmobile: r8a7740: reserve DMA memory for the frame buffer + +The default 2MB size of DMA coherent memory isn't enough for allocate +frame buffer memory. + +N.B: Not present upstream yet + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/setup-r8a7740.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index 74e5234..5d92def 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -18,6 +18,7 @@ + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include <linux/delay.h> ++#include <linux/dma-mapping.h> + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/io.h> +@@ -59,6 +60,12 @@ static struct map_desc r8a7740_io_desc[] __initdata = { + void __init r8a7740_map_io(void) + { + iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc)); ++ ++ /* ++ * DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't ++ * enough to allocate the frame buffer memory. ++ */ ++ init_consistent_dma_size(12 << 20); + } + + /* SCIFA0 */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0135-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch b/patches.kzm9g/0135-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch new file mode 100644 index 00000000000000..4dd3b048f6d7a9 --- /dev/null +++ b/patches.kzm9g/0135-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch @@ -0,0 +1,45 @@ +From d46a82ccbc9c9caf9116bc62737f6ba9470012dc Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:20:41 -0700 +Subject: ARM: mach-shmobile: clock-r8a7740: add FSI clock + +N.B: Not present upstream yet + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 927d42a..89a2f9d 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -355,7 +355,7 @@ enum { + MSTP222, + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + +- MSTP329, MSTP323, MSTP320, ++ MSTP329, MSTP328, MSTP323, MSTP320, + MSTP314, MSTP313, MSTP312, + + MSTP416, MSTP415, MSTP407, MSTP406, +@@ -381,6 +381,7 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ + + [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ ++ [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */ + [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ + [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ + [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ +@@ -445,6 +446,7 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]), + + CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), ++ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), + CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), + CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), + CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0136-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch b/patches.kzm9g/0136-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch new file mode 100644 index 00000000000000..fa5ba75066c6ed --- /dev/null +++ b/patches.kzm9g/0136-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch @@ -0,0 +1,131 @@ +From f33fc2bf482665a0dc1d0fed1e0a180268235c11 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:09:19 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add SDHI0 support + +On armadillo800eva board, +CD (= Card Detect) pin is not connected to SDHI0_CD. +Then, we can use IRQ31 as card detect irq, +but it needs chattering removal operation. +We should use IRQ card detect in the future, +but this patch use polling mode at this point. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + +N.B: Not present upstream yet + +Conflicts: + + arch/arm/mach-shmobile/board-armadillo800eva.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 71 ++++++++++++++++++++++++++ + 1 file changed, 71 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index c2affc4..fa5b541 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -28,6 +28,9 @@ + #include <linux/gpio_keys.h> + #include <linux/sh_eth.h> + #include <linux/videodev2.h> ++#include <linux/mfd/tmio.h> ++#include <linux/mmc/host.h> ++#include <linux/mmc/sh_mobile_sdhi.h> + #include <mach/common.h> + #include <mach/irqs.h> + #include <asm/page.h> +@@ -184,6 +187,55 @@ static struct platform_device lcdc0_device = { + }, + }; + ++/* SDHI0 */ ++/* ++ * FIXME ++ * ++ * It use polling mode here, since ++ * CD (= Card Detect) pin is not connected to SDHI0_CD. ++ * We can use IRQ31 as card detect irq, ++ * but it needs chattering removal operation ++ */ ++#define IRQ31 evt2irq(0x33E0) ++static struct sh_mobile_sdhi_info sdhi0_info = { ++ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |\ ++ MMC_CAP_NEEDS_POLL, ++ .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, ++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, ++}; ++ ++static struct resource sdhi0_resources[] = { ++ { ++ .name = "SDHI0", ++ .start = 0xe6850000, ++ .end = 0xe6850100 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ /* ++ * no SH_MOBILE_SDHI_IRQ_CARD_DETECT here ++ */ ++ { ++ .name = SH_MOBILE_SDHI_IRQ_SDCARD, ++ .start = evt2irq(0x0E20), ++ .flags = IORESOURCE_IRQ, ++ }, ++ { ++ .name = SH_MOBILE_SDHI_IRQ_SDIO, ++ .start = evt2irq(0x0E40), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device sdhi0_device = { ++ .name = "sh_mobile_sdhi", ++ .id = 0, ++ .dev = { ++ .platform_data = &sdhi0_info, ++ }, ++ .num_resources = ARRAY_SIZE(sdhi0_resources), ++ .resource = sdhi0_resources, ++}; ++ + /* I2C */ + static struct i2c_board_info i2c0_devices[] = { + { +@@ -222,6 +274,7 @@ static struct platform_device *eva_devices[] __initdata = { + &lcdc0_device, + &gpio_keys_device, + &sh_eth_device, ++ &sdhi0_device, + }; + + /* +@@ -302,6 +355,24 @@ static void __init eva_init(void) + gpio_request(GPIO_PORT18, NULL); /* PHY_RST */ + gpio_direction_output(GPIO_PORT18, 1); + ++ /* SDHI0 */ ++ gpio_request(GPIO_FN_SDHI0_CMD, NULL); ++ gpio_request(GPIO_FN_SDHI0_CLK, NULL); ++ gpio_request(GPIO_FN_SDHI0_D0, NULL); ++ gpio_request(GPIO_FN_SDHI0_D1, NULL); ++ gpio_request(GPIO_FN_SDHI0_D2, NULL); ++ gpio_request(GPIO_FN_SDHI0_D3, NULL); ++ gpio_request(GPIO_FN_SDHI0_WP, NULL); ++ ++ gpio_request(GPIO_PORT17, NULL); /* SDHI0_18/33_B */ ++ gpio_request(GPIO_PORT74, NULL); /* SDHI0_PON */ ++ gpio_request(GPIO_PORT75, NULL); /* SDSLOT1_PON */ ++ gpio_direction_output(GPIO_PORT17, 0); ++ gpio_direction_output(GPIO_PORT74, 1); ++ gpio_direction_output(GPIO_PORT75, 1); ++ ++ /* we can use GPIO_FN_IRQ31_PORT167 here for SDHI0 CD irq */ ++ + /* + * CAUTION + * +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0137-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch b/patches.kzm9g/0137-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch new file mode 100644 index 00000000000000..95899dc599baa6 --- /dev/null +++ b/patches.kzm9g/0137-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch @@ -0,0 +1,110 @@ +From 4c5dd88a2bfcca6a2bf0119f8a792e40e3280b22 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:09:31 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add SDHI1 support + +We can switch CON8/CON14 by SW1.5 +SDHI1 is CON8 (SW1.5 = ON) + +N.B: Not present upstream yet + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 66 +++++++++++++++++++++++++- + 1 file changed, 65 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index fa5b541..2f4b7f9 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -90,7 +90,7 @@ + * 0 | Extension Bus | D8-D15 disable, eMMC enable + * 1 | Extension Bus | D8-D15 enable, eMMC disable + * -12345678-+---------------+---------------------------- +- * 0 | SDHI1 | COM8 enable, COM14 disable ++ * 0 | SDHI1 | COM8 disable, COM14 enable + * 1 | SDHI1 | COM8 enable, COM14 disable + * -12345678-+---------------+---------------------------- + * 00 | JTAG | SH-X2 +@@ -236,6 +236,44 @@ static struct platform_device sdhi0_device = { + .resource = sdhi0_resources, + }; + ++/* SDHI1 */ ++static struct sh_mobile_sdhi_info sdhi1_info = { ++ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, ++ .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, ++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, ++}; ++ ++static struct resource sdhi1_resources[] = { ++ [0] = { ++ .name = "SDHI1", ++ .start = 0xe6860000, ++ .end = 0xe6860100 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = evt2irq(0x0E80), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [2] = { ++ .start = evt2irq(0x0EA0), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [3] = { ++ .start = evt2irq(0x0EC0), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device sdhi1_device = { ++ .name = "sh_mobile_sdhi", ++ .id = 1, ++ .dev = { ++ .platform_data = &sdhi1_info, ++ }, ++ .num_resources = ARRAY_SIZE(sdhi1_resources), ++ .resource = sdhi1_resources, ++}; ++ + /* I2C */ + static struct i2c_board_info i2c0_devices[] = { + { +@@ -382,6 +420,32 @@ static void __init eva_init(void) + gpio_request(GPIO_PORT176, NULL); + gpio_direction_output(GPIO_PORT176, 1); + ++ /* ++ * We can switch CON8/CON14 by SW1.5, ++ * but it needs after DBGMD_SELECT_B ++ */ ++ gpio_request(GPIO_PORT6, NULL); ++ gpio_direction_input(GPIO_PORT6); ++ if (gpio_get_value(GPIO_PORT6)) { ++ /* CON14 enable */ ++ } else { ++ /* CON8 (SDHI1) enable */ ++ gpio_request(GPIO_FN_SDHI1_CLK, NULL); ++ gpio_request(GPIO_FN_SDHI1_CMD, NULL); ++ gpio_request(GPIO_FN_SDHI1_D0, NULL); ++ gpio_request(GPIO_FN_SDHI1_D1, NULL); ++ gpio_request(GPIO_FN_SDHI1_D2, NULL); ++ gpio_request(GPIO_FN_SDHI1_D3, NULL); ++ gpio_request(GPIO_FN_SDHI1_CD, NULL); ++ gpio_request(GPIO_FN_SDHI1_WP, NULL); ++ ++ gpio_request(GPIO_PORT16, NULL); /* SDSLOT2_PON */ ++ gpio_direction_output(GPIO_PORT16, 1); ++ ++ platform_device_register(&sdhi1_device); ++ } ++ ++ + #ifdef CONFIG_CACHE_L2X0 + /* Early BRESP enable, Shared attribute override enable, 32K*8way */ + l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0138-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch b/patches.kzm9g/0138-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch new file mode 100644 index 00000000000000..90e1fde9b80810 --- /dev/null +++ b/patches.kzm9g/0138-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch @@ -0,0 +1,105 @@ +From 31b40a107a29865822e41b242ffc8eb75f7faf08 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:09:42 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add MMCIF support + +N.B: Not present upstream yet + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 57 ++++++++++++++++++++++++++ + 1 file changed, 57 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 2f4b7f9..eb97618 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -30,6 +30,7 @@ + #include <linux/videodev2.h> + #include <linux/mfd/tmio.h> + #include <linux/mmc/host.h> ++#include <linux/mmc/sh_mmcif.h> + #include <linux/mmc/sh_mobile_sdhi.h> + #include <mach/common.h> + #include <mach/irqs.h> +@@ -274,6 +275,44 @@ static struct platform_device sdhi1_device = { + .resource = sdhi1_resources, + }; + ++/* MMCIF */ ++static struct sh_mmcif_plat_data sh_mmcif_plat = { ++ .sup_pclk = 0, ++ .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, ++ .caps = MMC_CAP_4_BIT_DATA | ++ MMC_CAP_8_BIT_DATA | ++ MMC_CAP_NONREMOVABLE, ++}; ++ ++static struct resource sh_mmcif_resources[] = { ++ [0] = { ++ .name = "MMCIF", ++ .start = 0xe6bd0000, ++ .end = 0xe6bd0100 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ /* MMC ERR */ ++ .start = evt2irq(0x1AC0), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [2] = { ++ /* MMC NOR */ ++ .start = evt2irq(0x1AE0), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device sh_mmcif_device = { ++ .name = "sh_mmcif", ++ .id = -1, ++ .dev = { ++ .platform_data = &sh_mmcif_plat, ++ }, ++ .num_resources = ARRAY_SIZE(sh_mmcif_resources), ++ .resource = sh_mmcif_resources, ++}; ++ + /* I2C */ + static struct i2c_board_info i2c0_devices[] = { + { +@@ -313,6 +352,7 @@ static struct platform_device *eva_devices[] __initdata = { + &gpio_keys_device, + &sh_eth_device, + &sdhi0_device, ++ &sh_mmcif_device, + }; + + /* +@@ -412,6 +452,23 @@ static void __init eva_init(void) + /* we can use GPIO_FN_IRQ31_PORT167 here for SDHI0 CD irq */ + + /* ++ * MMCIF ++ * ++ * Here doesn't care SW1.4 status, ++ * since CON2 is not mounted. ++ */ ++ gpio_request(GPIO_FN_MMC1_CLK_PORT103, NULL); ++ gpio_request(GPIO_FN_MMC1_CMD_PORT104, NULL); ++ gpio_request(GPIO_FN_MMC1_D0_PORT149, NULL); ++ gpio_request(GPIO_FN_MMC1_D1_PORT148, NULL); ++ gpio_request(GPIO_FN_MMC1_D2_PORT147, NULL); ++ gpio_request(GPIO_FN_MMC1_D3_PORT146, NULL); ++ gpio_request(GPIO_FN_MMC1_D4_PORT145, NULL); ++ gpio_request(GPIO_FN_MMC1_D5_PORT144, NULL); ++ gpio_request(GPIO_FN_MMC1_D6_PORT143, NULL); ++ gpio_request(GPIO_FN_MMC1_D7_PORT142, NULL); ++ ++ /* + * CAUTION + * + * DBGMD/LCDC0/FSIA MUX +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0139-ARM-mach-shmobile-armadillo800eva-Add-FSI-WM8978-sup.patch b/patches.kzm9g/0139-ARM-mach-shmobile-armadillo800eva-Add-FSI-WM8978-sup.patch new file mode 100644 index 00000000000000..eb3642658f3d70 --- /dev/null +++ b/patches.kzm9g/0139-ARM-mach-shmobile-armadillo800eva-Add-FSI-WM8978-sup.patch @@ -0,0 +1,181 @@ +From bbfe67adb04a9203585aa910f5697c13a89db7d8 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:20:57 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: Add FSI-WM8978 support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + +N.B: Not present upstream yet + +Conflicts: + + arch/arm/mach-shmobile/board-armadillo800eva.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/Kconfig | 1 + + arch/arm/mach-shmobile/board-armadillo800eva.c | 97 ++++++++++++++++++++++++++ + 2 files changed, 98 insertions(+) + +diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig +index 7a1b589..91a4f32 100644 +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -79,6 +79,7 @@ config MACH_ARMADILLO800EVA + bool "Armadillo-800 EVA board" + depends on ARCH_R8A7740 + select ARCH_REQUIRE_GPIOLIB ++ select SND_SOC_WM8978 if SND_SIMPLE_CARD + + comment "SH-Mobile System Configuration" + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index eb97618..0dc387b 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -42,6 +42,8 @@ + #include <asm/hardware/cache-l2x0.h> + #include <mach/r8a7740.h> + #include <video/sh_mobile_lcdc.h> ++#include <sound/sh_fsi.h> ++#include <sound/simple_card.h> + + /* + * CON1 Camera Module +@@ -101,6 +103,28 @@ + *-----------+---------------+---------------------------- + */ + ++/* ++ * FSI-WM8978 ++ * ++ * this command is required when playback. ++ * ++ * # amixer set "Headphone" 50 ++ */ ++ ++/* ++ * FIXME !! ++ * ++ * gpio_no_direction ++ * ++ * current gpio frame work doesn't have ++ * the method to control only pull up/down/free. ++ * this function should be replaced by correct gpio function ++ */ ++static void __init gpio_no_direction(u32 addr) ++{ ++ __raw_writeb(0x00, addr); ++} ++ + /* Ether */ + static struct sh_eth_plat_data sh_eth_platdata = { + .phy = 0x00, /* LAN8710A */ +@@ -313,12 +337,68 @@ static struct platform_device sh_mmcif_device = { + .resource = sh_mmcif_resources, + }; + ++/* FSI-WM8978 */ ++static struct sh_fsi_platform_info fsi_info = { ++ .port_a = { ++ }, ++}; ++ ++static struct resource fsi_resources[] = { ++ [0] = { ++ .name = "FSI", ++ .start = 0xfe1f0000, ++ .end = 0xfe1f8400 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = evt2irq(0x1840), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device fsi_device = { ++ .name = "sh_fsi2", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(fsi_resources), ++ .resource = fsi_resources, ++ .dev = { ++ .platform_data = &fsi_info, ++ }, ++}; ++ ++static struct asoc_simple_dai_init_info fsi_wm8978_init_info = { ++ .fmt = SND_SOC_DAIFMT_I2S, ++ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF, ++ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS, ++ .sysclk = 12288000, ++}; ++ ++static struct asoc_simple_card_info fsi_wm8978_info = { ++ .name = "wm8978", ++ .card = "FSI2A-WM8978", ++ .cpu_dai = "fsia-dai", ++ .codec = "wm8978.0-001a", ++ .platform = "sh_fsi2", ++ .codec_dai = "wm8978-hifi", ++ .init = &fsi_wm8978_init_info, ++}; ++ ++static struct platform_device fsi_wm8978_device = { ++ .name = "asoc-simple-card", ++ .dev = { ++ .platform_data = &fsi_wm8978_info, ++ }, ++}; ++ + /* I2C */ + static struct i2c_board_info i2c0_devices[] = { + { + I2C_BOARD_INFO("st1232-ts", 0x55), + .irq = evt2irq(0x0340), + }, ++ { ++ I2C_BOARD_INFO("wm8978", 0x1a), ++ }, + }; + + /* GPIO KEY */ +@@ -353,11 +433,15 @@ static struct platform_device *eva_devices[] __initdata = { + &sh_eth_device, + &sdhi0_device, + &sh_mmcif_device, ++ &fsi_device, ++ &fsi_wm8978_device, + }; + + /* + * board init + */ ++#define GPIO_PORT7CR 0xe6050007 ++#define GPIO_PORT8CR 0xe6050008 + static void __init eva_init(void) + { + r8a7740_pinmux_init(); +@@ -468,6 +552,19 @@ static void __init eva_init(void) + gpio_request(GPIO_FN_MMC1_D6_PORT143, NULL); + gpio_request(GPIO_FN_MMC1_D7_PORT142, NULL); + ++ /* FSI */ ++ gpio_request(GPIO_FN_FSIAIBT, NULL); ++ gpio_request(GPIO_FN_FSIAILR, NULL); ++ gpio_request(GPIO_FN_FSIAOMC, NULL); ++ gpio_request(GPIO_FN_FSIACK, NULL); ++ gpio_request(GPIO_FN_FSIAOSLD, NULL); ++ gpio_request(GPIO_FN_FSIAISLD_PORT5, NULL); ++ ++ gpio_request(GPIO_PORT7, NULL); ++ gpio_request(GPIO_PORT8, NULL); ++ gpio_no_direction(GPIO_PORT7CR); /* FSIAOBT needs no direction */ ++ gpio_no_direction(GPIO_PORT8CR); /* FSIAOLR needs no direction */ ++ + /* + * CAUTION + * +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0140-ARM-mach-shmobile-Add-support-for-PINT-though-INTC-m.patch b/patches.kzm9g/0140-ARM-mach-shmobile-Add-support-for-PINT-though-INTC-m.patch new file mode 100644 index 00000000000000..c4a8edb5e25d1b --- /dev/null +++ b/patches.kzm9g/0140-ARM-mach-shmobile-Add-support-for-PINT-though-INTC-m.patch @@ -0,0 +1,80 @@ +From 6bd2390c23f97b846328d2f6f87cd786b3954d6c Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Mon, 17 Oct 2011 18:00:35 +0900 +Subject: ARM: mach-shmobile: Add support for PINT though INTC macros + +Add a INTC_PINT() macro with various helper bits to allow SoCs +like sh73a0 to suppor the PINT hardware using regular INTC tables. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 91c088ae17c62f7741d9563e36935bc7a69a7e9e) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/intc.h | 51 ++++++++++++++++++++++++++++++ + 1 file changed, 51 insertions(+) + +diff --git a/arch/arm/mach-shmobile/include/mach/intc.h b/arch/arm/mach-shmobile/include/mach/intc.h +index 1cd8b36..8b22258 100644 +--- a/arch/arm/mach-shmobile/include/mach/intc.h ++++ b/arch/arm/mach-shmobile/include/mach/intc.h +@@ -192,4 +192,55 @@ static struct intc_desc p ## _desc __initdata = { \ + p ## _sense_registers, p ## _ack_registers) \ + } + ++#define INTC_PINT_E_EMPTY ++#define INTC_PINT_E_NONE 0, 0, 0, 0, 0, 0, 0, 0, ++#define INTC_PINT_E(p) \ ++ PINT ## p ## 0, PINT ## p ## 1, PINT ## p ## 2, PINT ## p ## 3, \ ++ PINT ## p ## 4, PINT ## p ## 5, PINT ## p ## 6, PINT ## p ## 7, ++ ++#define INTC_PINT_V_NONE ++#define INTC_PINT_V(p, vect) \ ++ vect(PINT ## p ## 0, 0), vect(PINT ## p ## 1, 1), \ ++ vect(PINT ## p ## 2, 2), vect(PINT ## p ## 3, 3), \ ++ vect(PINT ## p ## 4, 4), vect(PINT ## p ## 5, 5), \ ++ vect(PINT ## p ## 6, 6), vect(PINT ## p ## 7, 7), ++ ++#define INTC_PINT(p, mask_reg, sense_base, str, \ ++ enums_1, enums_2, enums_3, enums_4, \ ++ vect_1, vect_2, vect_3, vect_4, \ ++ mask_a, mask_b, mask_c, mask_d, \ ++ sense_a, sense_b, sense_c, sense_d) \ ++ \ ++enum { \ ++ PINT ## p ## _UNUSED = 0, \ ++ enums_1 enums_2 enums_3 enums_4 \ ++}; \ ++ \ ++static struct intc_vect p ## _vectors[] __initdata = { \ ++ vect_1 vect_2 vect_3 vect_4 \ ++}; \ ++ \ ++static struct intc_mask_reg p ## _mask_registers[] __initdata = { \ ++ { mask_reg, 0, 32, /* PINTER */ \ ++ { mask_a mask_b mask_c mask_d } } \ ++}; \ ++ \ ++static struct intc_sense_reg p ## _sense_registers[] __initdata = { \ ++ { sense_base + 0x00, 16, 2, /* PINTCR */ \ ++ { sense_a } }, \ ++ { sense_base + 0x04, 16, 2, /* PINTCR */ \ ++ { sense_b } }, \ ++ { sense_base + 0x08, 16, 2, /* PINTCR */ \ ++ { sense_c } }, \ ++ { sense_base + 0x0c, 16, 2, /* PINTCR */ \ ++ { sense_d } }, \ ++}; \ ++ \ ++static struct intc_desc p ## _desc __initdata = { \ ++ .name = str, \ ++ .hw = INTC_HW_DESC(p ## _vectors, NULL, \ ++ p ## _mask_registers, NULL, \ ++ p ## _sense_registers, NULL), \ ++} ++ + #endif /* __ASM_MACH_INTC_H */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0141-irq-Track-the-owner-of-irq-descriptor.patch b/patches.kzm9g/0141-irq-Track-the-owner-of-irq-descriptor.patch new file mode 100644 index 00000000000000..f8e709694bd6f8 --- /dev/null +++ b/patches.kzm9g/0141-irq-Track-the-owner-of-irq-descriptor.patch @@ -0,0 +1,260 @@ +From b26b3d7e3cb934148b64b1276087761b30a5b1be Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> +Date: Mon, 11 Jul 2011 12:17:31 +0200 +Subject: irq: Track the owner of irq descriptor + +Interrupt descriptors can be allocated from modules. The interrupts +are used by other modules, but we have no refcount on the module which +provides the interrupts and there is no way to establish one on the +device level as the interrupt using module is agnostic to the fact +that the interrupt is provided by a module rather than by some builtin +interrupt controller. + +To prevent removal of the interrupt providing module, we can track the +owner of the interrupt descriptor, which also provides the relevant +irq chip functions in the irq descriptor. + +request/setup_irq() can now acquire a refcount on the owner module to +prevent unloading. free_irq() drops the refcount. + +Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> +Link: http://lkml.kernel.org/r/20110711101731.GA13804@Chamillionaire.breakpoint.cc +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +(cherry picked from commit b6873807a7143b7d6d8b06809295e559d07d7deb) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/irq.h | 11 ++++++++++- + include/linux/irqdesc.h | 1 + + kernel/irq/irqdesc.c | 36 ++++++++++++++++++++++++------------ + kernel/irq/manage.c | 17 +++++++++++++---- + 4 files changed, 48 insertions(+), 17 deletions(-) + +diff --git a/include/linux/irq.h b/include/linux/irq.h +index 094c211..58d1e49 100644 +--- a/include/linux/irq.h ++++ b/include/linux/irq.h +@@ -23,6 +23,7 @@ + #include <linux/errno.h> + #include <linux/topology.h> + #include <linux/wait.h> ++#include <linux/module.h> + + #include <asm/irq.h> + #include <asm/ptrace.h> +@@ -548,7 +549,15 @@ static inline struct msi_desc *irq_data_get_msi(struct irq_data *d) + return d->msi_desc; + } + +-int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node); ++int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, ++ struct module *owner); ++ ++static inline int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, ++ int node) ++{ ++ return __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE); ++} ++ + void irq_free_descs(unsigned int irq, unsigned int cnt); + int irq_reserve_irqs(unsigned int from, unsigned int cnt); + +diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h +index 2d921b3..150134a 100644 +--- a/include/linux/irqdesc.h ++++ b/include/linux/irqdesc.h +@@ -66,6 +66,7 @@ struct irq_desc { + #ifdef CONFIG_PROC_FS + struct proc_dir_entry *dir; + #endif ++ struct module *owner; + const char *name; + } ____cacheline_internodealigned_in_smp; + +diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c +index 4c60a50..cb65d03 100644 +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -70,7 +70,8 @@ static inline void desc_smp_init(struct irq_desc *desc, int node) { } + static inline int desc_node(struct irq_desc *desc) { return 0; } + #endif + +-static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node) ++static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node, ++ struct module *owner) + { + int cpu; + +@@ -86,6 +87,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node) + desc->irq_count = 0; + desc->irqs_unhandled = 0; + desc->name = NULL; ++ desc->owner = owner; + for_each_possible_cpu(cpu) + *per_cpu_ptr(desc->kstat_irqs, cpu) = 0; + desc_smp_init(desc, node); +@@ -128,7 +130,7 @@ static void free_masks(struct irq_desc *desc) + static inline void free_masks(struct irq_desc *desc) { } + #endif + +-static struct irq_desc *alloc_desc(int irq, int node) ++static struct irq_desc *alloc_desc(int irq, int node, struct module *owner) + { + struct irq_desc *desc; + gfp_t gfp = GFP_KERNEL; +@@ -147,7 +149,7 @@ static struct irq_desc *alloc_desc(int irq, int node) + raw_spin_lock_init(&desc->lock); + lockdep_set_class(&desc->lock, &irq_desc_lock_class); + +- desc_set_defaults(irq, desc, node); ++ desc_set_defaults(irq, desc, node, owner); + + return desc; + +@@ -173,13 +175,14 @@ static void free_desc(unsigned int irq) + kfree(desc); + } + +-static int alloc_descs(unsigned int start, unsigned int cnt, int node) ++static int alloc_descs(unsigned int start, unsigned int cnt, int node, ++ struct module *owner) + { + struct irq_desc *desc; + int i; + + for (i = 0; i < cnt; i++) { +- desc = alloc_desc(start + i, node); ++ desc = alloc_desc(start + i, node, owner); + if (!desc) + goto err; + mutex_lock(&sparse_irq_lock); +@@ -227,7 +230,7 @@ int __init early_irq_init(void) + nr_irqs = initcnt; + + for (i = 0; i < initcnt; i++) { +- desc = alloc_desc(i, node); ++ desc = alloc_desc(i, node, NULL); + set_bit(i, allocated_irqs); + irq_insert_desc(i, desc); + } +@@ -261,7 +264,7 @@ int __init early_irq_init(void) + alloc_masks(&desc[i], GFP_KERNEL, node); + raw_spin_lock_init(&desc[i].lock); + lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); +- desc_set_defaults(i, &desc[i], node); ++ desc_set_defaults(i, &desc[i], node, NULL); + } + return arch_early_irq_init(); + } +@@ -276,8 +279,16 @@ static void free_desc(unsigned int irq) + dynamic_irq_cleanup(irq); + } + +-static inline int alloc_descs(unsigned int start, unsigned int cnt, int node) ++static inline int alloc_descs(unsigned int start, unsigned int cnt, int node, ++ struct module *owner) + { ++ u32 i; ++ ++ for (i = 0; i < cnt; i++) { ++ struct irq_desc *desc = irq_to_desc(start + i); ++ ++ desc->owner = owner; ++ } + return start; + } + +@@ -337,7 +348,8 @@ EXPORT_SYMBOL_GPL(irq_free_descs); + * Returns the first irq number or error code + */ + int __ref +-irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node) ++__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, ++ struct module *owner) + { + int start, ret; + +@@ -366,13 +378,13 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node) + + bitmap_set(allocated_irqs, start, cnt); + mutex_unlock(&sparse_irq_lock); +- return alloc_descs(start, cnt, node); ++ return alloc_descs(start, cnt, node, owner); + + err: + mutex_unlock(&sparse_irq_lock); + return ret; + } +-EXPORT_SYMBOL_GPL(irq_alloc_descs); ++EXPORT_SYMBOL_GPL(__irq_alloc_descs); + + /** + * irq_reserve_irqs - mark irqs allocated +@@ -440,7 +452,7 @@ void dynamic_irq_cleanup(unsigned int irq) + unsigned long flags; + + raw_spin_lock_irqsave(&desc->lock, flags); +- desc_set_defaults(irq, desc, desc_node(desc)); ++ desc_set_defaults(irq, desc, desc_node(desc), NULL); + raw_spin_unlock_irqrestore(&desc->lock, flags); + } + +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index bbc6a35..83fb6f5 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -889,6 +889,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) + + if (desc->irq_data.chip == &no_irq_chip) + return -ENOSYS; ++ if (!try_module_get(desc->owner)) ++ return -ENODEV; + /* + * Some drivers like serial.c use request_irq() heavily, + * so we have to be careful not to interfere with a +@@ -912,8 +914,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) + */ + nested = irq_settings_is_nested_thread(desc); + if (nested) { +- if (!new->thread_fn) +- return -EINVAL; ++ if (!new->thread_fn) { ++ ret = -EINVAL; ++ goto out_mput; ++ } + /* + * Replace the primary handler which was provided from + * the driver for non nested interrupt handling by the +@@ -935,8 +939,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) + + t = kthread_create(irq_thread, new, "irq/%d-%s", irq, + new->name); +- if (IS_ERR(t)) +- return PTR_ERR(t); ++ if (IS_ERR(t)) { ++ ret = PTR_ERR(t); ++ goto out_mput; ++ } + /* + * We keep the reference to the task struct even if + * the thread dies to avoid that the interrupt code +@@ -1133,6 +1139,8 @@ out_thread: + kthread_stop(t); + put_task_struct(t); + } ++out_mput: ++ module_put(desc->owner); + return ret; + } + +@@ -1241,6 +1249,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) + put_task_struct(action->thread); + } + ++ module_put(desc->owner); + return action; + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0142-irq-add-irq_domain-translation-infrastructure.patch b/patches.kzm9g/0142-irq-add-irq_domain-translation-infrastructure.patch new file mode 100644 index 00000000000000..bdee569a1a2b3c --- /dev/null +++ b/patches.kzm9g/0142-irq-add-irq_domain-translation-infrastructure.patch @@ -0,0 +1,400 @@ +From 9a23bed05c4e337589f8e76bed25c843979b77d5 Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Tue, 26 Jul 2011 03:19:06 -0600 +Subject: irq: add irq_domain translation infrastructure + +This patch adds irq_domain infrastructure for translating from +hardware irq numbers to linux irqs. This is particularly important +for architectures adding device tree support because the current +implementation (excluding PowerPC and SPARC) cannot handle +translation for more than a single interrupt controller. irq_domain +supports device tree translation for any number of interrupt +controllers. + +This patch converts x86, Microblaze, ARM and MIPS to use irq_domain +for device tree irq translation. x86 is untested beyond compiling it, +irq_domain is enabled for MIPS and Microblaze, but the old behaviour is +preserved until the core code is modified to actually register an +irq_domain yet. On ARM it works and is required for much of the new +ARM device tree board support. + +PowerPC has /not/ been converted to use this new infrastructure. It +is still missing some features before it can replace the virq +infrastructure already in powerpc (see documentation on +irq_domain_map/unmap for details). Followup patches will add the +missing pieces and migrate PowerPC to use irq_domain. + +SPARC has its own method of managing interrupts from the device tree +and is unaffected by this change. + +Acked-by: Ralf Baechle <ralf@linux-mips.org> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit 08a543ad33fc188650801bd36eed4ffe272643e1) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/Kconfig | 1 + + arch/arm/include/asm/prom.h | 5 -- + arch/arm/kernel/devtree.c | 14 ----- + include/linux/irq.h | 6 +++ + include/linux/irqdomain.h | 81 +++++++++++++++++++++++++++++ + include/linux/of_irq.h | 4 ++ + kernel/irq/Kconfig | 4 ++ + kernel/irq/Makefile | 1 + + kernel/irq/irqdomain.c | 122 ++++++++++++++++++++++++++++++++++++++++++++ + 9 files changed, 219 insertions(+), 19 deletions(-) + create mode 100644 include/linux/irqdomain.h + create mode 100644 kernel/irq/irqdomain.c + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index f9b212e..d7f1a02 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1705,6 +1705,7 @@ config USE_OF + bool "Flattened Device Tree support" + select OF + select OF_EARLY_FLATTREE ++ select IRQ_DOMAIN + help + Include support for flattened device tree machine descriptions. + +diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h +index 11b8708..6f65ca8 100644 +--- a/arch/arm/include/asm/prom.h ++++ b/arch/arm/include/asm/prom.h +@@ -16,11 +16,6 @@ + #include <asm/setup.h> + #include <asm/irq.h> + +-static inline void irq_dispose_mapping(unsigned int virq) +-{ +- return; +-} +- + extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys); + extern void arm_dt_memblock_reserve(void); + +diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c +index 0cdd7b4..1a33e9d 100644 +--- a/arch/arm/kernel/devtree.c ++++ b/arch/arm/kernel/devtree.c +@@ -132,17 +132,3 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) + + return mdesc_best; + } +- +-/** +- * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq# +- * +- * Currently the mapping mechanism is trivial; simple flat hwirq numbers are +- * mapped 1:1 onto Linux irq numbers. Cascaded irq controllers are not +- * supported. +- */ +-unsigned int irq_create_of_mapping(struct device_node *controller, +- const u32 *intspec, unsigned int intsize) +-{ +- return intspec[0]; +-} +-EXPORT_SYMBOL_GPL(irq_create_of_mapping); +diff --git a/include/linux/irq.h b/include/linux/irq.h +index 58d1e49..d65dfca 100644 +--- a/include/linux/irq.h ++++ b/include/linux/irq.h +@@ -114,14 +114,18 @@ enum { + }; + + struct msi_desc; ++struct irq_domain; + + /** + * struct irq_data - per irq and irq chip data passed down to chip functions + * @irq: interrupt number ++ * @hwirq: hardware interrupt number, local to the interrupt domain + * @node: node index useful for balancing + * @state_use_accessors: status information for irq chip functions. + * Use accessor functions to deal with it + * @chip: low level interrupt hardware access ++ * @domain: Interrupt translation domain; responsible for mapping ++ * between hwirq number and linux irq number. + * @handler_data: per-IRQ data for the irq_chip methods + * @chip_data: platform-specific per-chip private data for the chip + * methods, to allow shared chip implementations +@@ -134,9 +138,11 @@ struct msi_desc; + */ + struct irq_data { + unsigned int irq; ++ unsigned long hwirq; + unsigned int node; + unsigned int state_use_accessors; + struct irq_chip *chip; ++ struct irq_domain *domain; + void *handler_data; + void *chip_data; + struct msi_desc *msi_desc; +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +new file mode 100644 +index 0000000..8f2c10a +--- /dev/null ++++ b/include/linux/irqdomain.h +@@ -0,0 +1,81 @@ ++/* ++ * irq_domain - IRQ translation domains ++ * ++ * Translation infrastructure between hw and linux irq numbers. This is ++ * helpful for interrupt controllers to implement mapping between hardware ++ * irq numbers and the Linux irq number space. ++ * ++ * irq_domains also have a hook for translating device tree interrupt ++ * representation into a hardware irq number that can be mapped back to a ++ * Linux irq number without any extra platform support code. ++ * ++ * irq_domain is expected to be embedded in an interrupt controller's private ++ * data structure. ++ */ ++#ifndef _LINUX_IRQDOMAIN_H ++#define _LINUX_IRQDOMAIN_H ++ ++#include <linux/irq.h> ++ ++#ifdef CONFIG_IRQ_DOMAIN ++struct device_node; ++struct irq_domain; ++ ++/** ++ * struct irq_domain_ops - Methods for irq_domain objects ++ * @to_irq: (optional) given a local hardware irq number, return the linux ++ * irq number. If to_irq is not implemented, then the irq_domain ++ * will use this translation: irq = (domain->irq_base + hwirq) ++ * @dt_translate: Given a device tree node and interrupt specifier, decode ++ * the hardware irq number and linux irq type value. ++ */ ++struct irq_domain_ops { ++ unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq); ++ ++#ifdef CONFIG_OF ++ int (*dt_translate)(struct irq_domain *d, struct device_node *node, ++ const u32 *intspec, unsigned int intsize, ++ unsigned long *out_hwirq, unsigned int *out_type); ++#endif /* CONFIG_OF */ ++}; ++ ++/** ++ * struct irq_domain - Hardware interrupt number translation object ++ * @list: Element in global irq_domain list. ++ * @irq_base: Start of irq_desc range assigned to the irq_domain. The creator ++ * of the irq_domain is responsible for allocating the array of ++ * irq_desc structures. ++ * @nr_irq: Number of irqs managed by the irq domain ++ * @ops: pointer to irq_domain methods ++ * @priv: private data pointer for use by owner. Not touched by irq_domain ++ * core code. ++ * @of_node: (optional) Pointer to device tree nodes associated with the ++ * irq_domain. Used when decoding device tree interrupt specifiers. ++ */ ++struct irq_domain { ++ struct list_head list; ++ unsigned int irq_base; ++ unsigned int nr_irq; ++ const struct irq_domain_ops *ops; ++ void *priv; ++ struct device_node *of_node; ++}; ++ ++/** ++ * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number ++ * ++ * Returns the linux irq number associated with a hardware irq. By default, ++ * the mapping is irq == domain->irq_base + hwirq, but this mapping can ++ * be overridden if the irq_domain implements a .to_irq() hook. ++ */ ++static inline unsigned int irq_domain_to_irq(struct irq_domain *d, ++ unsigned long hwirq) ++{ ++ return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq; ++} ++ ++extern void irq_domain_add(struct irq_domain *domain); ++extern void irq_domain_del(struct irq_domain *domain); ++#endif /* CONFIG_IRQ_DOMAIN */ ++ ++#endif /* _LINUX_IRQDOMAIN_H */ +diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h +index e6955f5..cd2e61c 100644 +--- a/include/linux/of_irq.h ++++ b/include/linux/of_irq.h +@@ -63,6 +63,9 @@ extern int of_irq_map_one(struct device_node *device, int index, + extern unsigned int irq_create_of_mapping(struct device_node *controller, + const u32 *intspec, + unsigned int intsize); ++#ifdef CONFIG_IRQ_DOMAIN ++extern void irq_dispose_mapping(unsigned int irq); ++#endif + extern int of_irq_to_resource(struct device_node *dev, int index, + struct resource *r); + extern int of_irq_count(struct device_node *dev); +@@ -70,6 +73,7 @@ extern int of_irq_to_resource_table(struct device_node *dev, + struct resource *res, int nr_irqs); + extern struct device_node *of_irq_find_parent(struct device_node *child); + ++ + #endif /* CONFIG_OF_IRQ */ + #endif /* CONFIG_OF */ + #endif /* __OF_IRQ_H */ +diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig +index d1d051b3..5a38bf4 100644 +--- a/kernel/irq/Kconfig ++++ b/kernel/irq/Kconfig +@@ -52,6 +52,10 @@ config IRQ_EDGE_EOI_HANDLER + config GENERIC_IRQ_CHIP + bool + ++# Generic irq_domain hw <--> linux irq number translation ++config IRQ_DOMAIN ++ bool ++ + # Support forced irq threading + config IRQ_FORCED_THREADING + bool +diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile +index 7329005..fff1738 100644 +--- a/kernel/irq/Makefile ++++ b/kernel/irq/Makefile +@@ -2,6 +2,7 @@ + obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o + obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o + obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o ++obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o + obj-$(CONFIG_PROC_FS) += proc.o + obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o + obj-$(CONFIG_PM_SLEEP) += pm.o +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +new file mode 100644 +index 0000000..29c7bd4 +--- /dev/null ++++ b/kernel/irq/irqdomain.c +@@ -0,0 +1,122 @@ ++#include <linux/irq.h> ++#include <linux/irqdomain.h> ++#include <linux/module.h> ++#include <linux/mutex.h> ++#include <linux/of.h> ++ ++static LIST_HEAD(irq_domain_list); ++static DEFINE_MUTEX(irq_domain_mutex); ++ ++/** ++ * irq_domain_add() - Register an irq_domain ++ * @domain: ptr to initialized irq_domain structure ++ * ++ * Registers an irq_domain structure. The irq_domain must at a minimum be ++ * initialized with an ops structure pointer, and either a ->to_irq hook or ++ * a valid irq_base value. Everything else is optional. ++ */ ++void irq_domain_add(struct irq_domain *domain) ++{ ++ struct irq_data *d; ++ int hwirq; ++ ++ /* ++ * This assumes that the irq_domain owner has already allocated ++ * the irq_descs. This block will be removed when support for dynamic ++ * allocation of irq_descs is added to irq_domain. ++ */ ++ for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) { ++ d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq)); ++ if (d || d->domain) { ++ /* things are broken; just report, don't clean up */ ++ WARN(1, "error: irq_desc already assigned to a domain"); ++ return; ++ } ++ d->domain = domain; ++ d->hwirq = hwirq; ++ } ++ ++ mutex_lock(&irq_domain_mutex); ++ list_add(&domain->list, &irq_domain_list); ++ mutex_unlock(&irq_domain_mutex); ++} ++ ++/** ++ * irq_domain_del() - Unregister an irq_domain ++ * @domain: ptr to registered irq_domain. ++ */ ++void irq_domain_del(struct irq_domain *domain) ++{ ++ struct irq_data *d; ++ int hwirq; ++ ++ mutex_lock(&irq_domain_mutex); ++ list_del(&domain->list); ++ mutex_unlock(&irq_domain_mutex); ++ ++ /* Clear the irq_domain assignments */ ++ for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) { ++ d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq)); ++ d->domain = NULL; ++ } ++} ++ ++#if defined(CONFIG_OF_IRQ) ++/** ++ * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec ++ * ++ * Used by the device tree interrupt mapping code to translate a device tree ++ * interrupt specifier to a valid linux irq number. Returns either a valid ++ * linux IRQ number or 0. ++ * ++ * When the caller no longer need the irq number returned by this function it ++ * should arrange to call irq_dispose_mapping(). ++ */ ++unsigned int irq_create_of_mapping(struct device_node *controller, ++ const u32 *intspec, unsigned int intsize) ++{ ++ struct irq_domain *domain; ++ unsigned long hwirq; ++ unsigned int irq, type; ++ int rc = -EINVAL; ++ ++ /* Find a domain which can translate the irq spec */ ++ mutex_lock(&irq_domain_mutex); ++ list_for_each_entry(domain, &irq_domain_list, list) { ++ if (!domain->ops->dt_translate) ++ continue; ++ rc = domain->ops->dt_translate(domain, controller, ++ intspec, intsize, &hwirq, &type); ++ if (rc == 0) ++ break; ++ } ++ mutex_unlock(&irq_domain_mutex); ++ ++ if (rc != 0) ++ return 0; ++ ++ irq = irq_domain_to_irq(domain, hwirq); ++ if (type != IRQ_TYPE_NONE) ++ irq_set_irq_type(irq, type); ++ pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n", ++ controller->full_name, (int)hwirq, irq, type); ++ return irq; ++} ++EXPORT_SYMBOL_GPL(irq_create_of_mapping); ++ ++/** ++ * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping() ++ * @irq: linux irq number to be discarded ++ * ++ * Calling this function indicates the caller no longer needs a reference to ++ * the linux irq number returned by a prior call to irq_create_of_mapping(). ++ */ ++void irq_dispose_mapping(unsigned int irq) ++{ ++ /* ++ * nothing yet; will be filled when support for dynamic allocation of ++ * irq_descs is added to irq_domain ++ */ ++} ++EXPORT_SYMBOL_GPL(irq_dispose_mapping); ++#endif /* CONFIG_OF_IRQ */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0143-dt-irq-add-irq_domain_generate_simple-helper.patch b/patches.kzm9g/0143-dt-irq-add-irq_domain_generate_simple-helper.patch new file mode 100644 index 00000000000000..725586004ea22b --- /dev/null +++ b/patches.kzm9g/0143-dt-irq-add-irq_domain_generate_simple-helper.patch @@ -0,0 +1,122 @@ +From 3105f044552138b2b05fa35fd4af2290997dfcb1 Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Tue, 26 Jul 2011 03:19:06 -0600 +Subject: dt/irq: add irq_domain_generate_simple() helper + +irq_domain_generate_simple() is an easy way to generate an irq translation +domain for simple irq controllers. It assumes a flat 1:1 mapping from +hardware irq number to an offset of the first linux irq number assigned +to the controller + +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit 7e71330169d8056536b299290544980bccc6b300) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/irqdomain.h | 10 ++++++++ + kernel/irq/irqdomain.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+) + +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index 8f2c10a..e807ad6 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -16,6 +16,7 @@ + #define _LINUX_IRQDOMAIN_H + + #include <linux/irq.h> ++#include <linux/mod_devicetable.h> + + #ifdef CONFIG_IRQ_DOMAIN + struct device_node; +@@ -78,4 +79,13 @@ extern void irq_domain_add(struct irq_domain *domain); + extern void irq_domain_del(struct irq_domain *domain); + #endif /* CONFIG_IRQ_DOMAIN */ + ++#if defined(CONFIG_IRQ_DOMAIN) && defined(CONFIG_OF_IRQ) ++extern void irq_domain_add_simple(struct device_node *controller, int irq_base); ++extern void irq_domain_generate_simple(const struct of_device_id *match, ++ u64 phys_base, unsigned int irq_start); ++#else /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */ ++static inline void irq_domain_generate_simple(const struct of_device_id *match, ++ u64 phys_base, unsigned int irq_start) { } ++#endif /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */ ++ + #endif /* _LINUX_IRQDOMAIN_H */ +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 29c7bd4..d5828da 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -3,6 +3,8 @@ + #include <linux/module.h> + #include <linux/mutex.h> + #include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/slab.h> + + static LIST_HEAD(irq_domain_list); + static DEFINE_MUTEX(irq_domain_mutex); +@@ -119,4 +121,60 @@ void irq_dispose_mapping(unsigned int irq) + */ + } + EXPORT_SYMBOL_GPL(irq_dispose_mapping); ++ ++int irq_domain_simple_dt_translate(struct irq_domain *d, ++ struct device_node *controller, ++ const u32 *intspec, unsigned int intsize, ++ unsigned long *out_hwirq, unsigned int *out_type) ++{ ++ if (d->of_node != controller) ++ return -EINVAL; ++ if (intsize < 1) ++ return -EINVAL; ++ ++ *out_hwirq = intspec[0]; ++ *out_type = IRQ_TYPE_NONE; ++ if (intsize > 1) ++ *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; ++ return 0; ++} ++ ++struct irq_domain_ops irq_domain_simple_ops = { ++ .dt_translate = irq_domain_simple_dt_translate, ++}; ++EXPORT_SYMBOL_GPL(irq_domain_simple_ops); ++ ++/** ++ * irq_domain_create_simple() - Set up a 'simple' translation range ++ */ ++void irq_domain_add_simple(struct device_node *controller, int irq_base) ++{ ++ struct irq_domain *domain; ++ ++ domain = kzalloc(sizeof(*domain), GFP_KERNEL); ++ if (!domain) { ++ WARN_ON(1); ++ return; ++ } ++ ++ domain->irq_base = irq_base; ++ domain->of_node = of_node_get(controller); ++ domain->ops = &irq_domain_simple_ops; ++ irq_domain_add(domain); ++} ++EXPORT_SYMBOL_GPL(irq_domain_add_simple); ++ ++void irq_domain_generate_simple(const struct of_device_id *match, ++ u64 phys_base, unsigned int irq_start) ++{ ++ struct device_node *node; ++ pr_info("looking for phys_base=%llx, irq_start=%i\n", ++ (unsigned long long) phys_base, (int) irq_start); ++ node = of_find_matching_node_by_address(NULL, match, phys_base); ++ if (node) ++ irq_domain_add_simple(node, irq_start); ++ else ++ pr_info("no node found\n"); ++} ++EXPORT_SYMBOL_GPL(irq_domain_generate_simple); + #endif /* CONFIG_OF_IRQ */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0144-irq-Add-declaration-of-irq_domain_simple_ops-to-irqd.patch b/patches.kzm9g/0144-irq-Add-declaration-of-irq_domain_simple_ops-to-irqd.patch new file mode 100644 index 00000000000000..5b27c51a0589f8 --- /dev/null +++ b/patches.kzm9g/0144-irq-Add-declaration-of-irq_domain_simple_ops-to-irqd.patch @@ -0,0 +1,41 @@ +From b4ba6a778992d1529517e6a5cd03cf1778529292 Mon Sep 17 00:00:00 2001 +From: Rob Herring <robherring2@gmail.com> +Date: Wed, 14 Sep 2011 11:31:36 -0500 +Subject: irq: Add declaration of irq_domain_simple_ops to irqdomain.h + +irq_domain_simple_ops is exported, but is not declared in irqdomain.h, +so add it. + +Signed-off-by: Rob Herring <rob.herring@calxeda.com> +Cc: Grant Likely <grant.likely@secretlab.ca> +Cc: marc.zyngier@arm.com +Cc: thomas.abraham@linaro.org +Cc: jamie@jamieiles.com +Cc: b-cousson@ti.com +Cc: shawn.guo@linaro.org +Cc: linux-arm-kernel@lists.infradead.org +Cc: devicetree-discuss@lists.ozlabs.org +Link: http://lkml.kernel.org/r/1316017900-19918-2-git-send-email-robherring2@gmail.com +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +(cherry picked from commit 5bd078dda4d4fbdb4bd138a6bd5b6e274c019ed2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/irqdomain.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index e807ad6..3ad553e 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -80,6 +80,7 @@ extern void irq_domain_del(struct irq_domain *domain); + #endif /* CONFIG_IRQ_DOMAIN */ + + #if defined(CONFIG_IRQ_DOMAIN) && defined(CONFIG_OF_IRQ) ++extern struct irq_domain_ops irq_domain_simple_ops; + extern void irq_domain_add_simple(struct device_node *controller, int irq_base); + extern void irq_domain_generate_simple(const struct of_device_id *match, + u64 phys_base, unsigned int irq_start); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0145-irq-Fix-check-for-already-initialized-irq_domain-in-.patch b/patches.kzm9g/0145-irq-Fix-check-for-already-initialized-irq_domain-in-.patch new file mode 100644 index 00000000000000..5378b2c7454bfa --- /dev/null +++ b/patches.kzm9g/0145-irq-Fix-check-for-already-initialized-irq_domain-in-.patch @@ -0,0 +1,56 @@ +From e2aede6a87e8875da05a181d1b46d7ae99f3a3d6 Mon Sep 17 00:00:00 2001 +From: Rob Herring <robherring2@gmail.com> +Date: Wed, 14 Sep 2011 11:31:37 -0500 +Subject: irq: Fix check for already initialized irq_domain in irq_domain_add + +The sanity check in irq_domain_add() tests desc->irq_data != NULL or +irq_data->domain != NULL. This prevents adding an irq_domain to a irq +descriptor when irq_data exists, which true when the irq descriptor +exists. + +This went unnoticed so far as the simple domain code did not enter +this code path because domain->nr_irqs is always 0 for the simple domains. + +Split the check for irq_data == NULL out and have a separate warning +for it. + +[ tglx: Made the check for irq_data == NULL separate ] + +Signed-off-by: Rob Herring <rob.herring@calxeda.com> +Cc: Grant Likely <grant.likely@secretlab.ca> +Cc: marc.zyngier@arm.com +Cc: thomas.abraham@linaro.org +Cc: jamie@jamieiles.com +Cc: b-cousson@ti.com +Cc: shawn.guo@linaro.org +Cc: linux-arm-kernel@lists.infradead.org +Cc: devicetree-discuss@lists.ozlabs.org +Link: http://lkml.kernel.org/r/1316017900-19918-3-git-send-email-robherring2@gmail.com +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +(cherry picked from commit eef24afb28561a5a9f4be8f8da97735b7e6a826f) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index d5828da..b57a377 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -29,7 +29,11 @@ void irq_domain_add(struct irq_domain *domain) + */ + for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) { + d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq)); +- if (d || d->domain) { ++ if (!d) { ++ WARN(1, "error: assigning domain to non existant irq_desc"); ++ return; ++ } ++ if (d->domain) { + /* things are broken; just report, don't clean up */ + WARN(1, "error: irq_desc already assigned to a domain"); + return; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0146-irq-support-domains-with-non-zero-hwirq-base.patch b/patches.kzm9g/0146-irq-support-domains-with-non-zero-hwirq-base.patch new file mode 100644 index 00000000000000..0815ecc54dd9d4 --- /dev/null +++ b/patches.kzm9g/0146-irq-support-domains-with-non-zero-hwirq-base.patch @@ -0,0 +1,113 @@ +From a5214f58a7b1bd8881d0b99b2bf728149ece07df Mon Sep 17 00:00:00 2001 +From: Rob Herring <rob.herring@calxeda.com> +Date: Fri, 30 Sep 2011 10:48:38 -0500 +Subject: irq: support domains with non-zero hwirq base + +Interrupt controllers can have non-zero starting value for h/w irq numbers. +Adding support in irq_domain allows the domain hwirq numbering to match +the interrupt controllers' numbering. + +As this makes looping over irqs for a domain more complicated, add loop +iterators to iterate over all hwirqs and irqs for a domain. + +Signed-off-by: Rob Herring <rob.herring@calxeda.com> +Reviewed-by: Jamie Iles <jamie@jamieiles.com> +Tested-by: Thomas Abraham <thomas.abraham@linaro.org> +Acked-by: Grant Likely <grant.likely@secretlab.ca> +Acked-by: Thomas Gleixner <tglx@linutronix.de> +(cherry picked from commit 6d274309d0e64bdbdb6c50945ca2964596e8fa5a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/irqdomain.h | 16 +++++++++++++++- + kernel/irq/irqdomain.c | 12 ++++++------ + 2 files changed, 21 insertions(+), 7 deletions(-) + +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index 3ad553e..99834e58 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -47,6 +47,7 @@ struct irq_domain_ops { + * of the irq_domain is responsible for allocating the array of + * irq_desc structures. + * @nr_irq: Number of irqs managed by the irq domain ++ * @hwirq_base: Starting number for hwirqs managed by the irq domain + * @ops: pointer to irq_domain methods + * @priv: private data pointer for use by owner. Not touched by irq_domain + * core code. +@@ -57,6 +58,7 @@ struct irq_domain { + struct list_head list; + unsigned int irq_base; + unsigned int nr_irq; ++ unsigned int hwirq_base; + const struct irq_domain_ops *ops; + void *priv; + struct device_node *of_node; +@@ -72,9 +74,21 @@ struct irq_domain { + static inline unsigned int irq_domain_to_irq(struct irq_domain *d, + unsigned long hwirq) + { +- return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq; ++ if (d->ops->to_irq) ++ return d->ops->to_irq(d, hwirq); ++ if (WARN_ON(hwirq < d->hwirq_base)) ++ return 0; ++ return d->irq_base + hwirq - d->hwirq_base; + } + ++#define irq_domain_for_each_hwirq(d, hw) \ ++ for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++) ++ ++#define irq_domain_for_each_irq(d, hw, irq) \ ++ for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \ ++ hw < d->hwirq_base + d->nr_irq; \ ++ hw++, irq = irq_domain_to_irq(d, hw)) ++ + extern void irq_domain_add(struct irq_domain *domain); + extern void irq_domain_del(struct irq_domain *domain); + #endif /* CONFIG_IRQ_DOMAIN */ +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index b57a377..200ce83 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex); + void irq_domain_add(struct irq_domain *domain) + { + struct irq_data *d; +- int hwirq; ++ int hwirq, irq; + + /* + * This assumes that the irq_domain owner has already allocated + * the irq_descs. This block will be removed when support for dynamic + * allocation of irq_descs is added to irq_domain. + */ +- for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) { +- d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq)); ++ irq_domain_for_each_irq(domain, hwirq, irq) { ++ d = irq_get_irq_data(irq); + if (!d) { + WARN(1, "error: assigning domain to non existant irq_desc"); + return; +@@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain) + void irq_domain_del(struct irq_domain *domain) + { + struct irq_data *d; +- int hwirq; ++ int hwirq, irq; + + mutex_lock(&irq_domain_mutex); + list_del(&domain->list); + mutex_unlock(&irq_domain_mutex); + + /* Clear the irq_domain assignments */ +- for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) { +- d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq)); ++ irq_domain_for_each_irq(domain, hwirq, irq) { ++ d = irq_get_irq_data(irq); + d->domain = NULL; + } + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0147-genirq-Add-support-for-per-cpu-dev_id-interrupts.patch b/patches.kzm9g/0147-genirq-Add-support-for-per-cpu-dev_id-interrupts.patch new file mode 100644 index 00000000000000..4f7bf8b3c9170b --- /dev/null +++ b/patches.kzm9g/0147-genirq-Add-support-for-per-cpu-dev_id-interrupts.patch @@ -0,0 +1,769 @@ +From 2fa1dad96b9e8bff660071418480512a2539ce85 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier <marc.zyngier@arm.com> +Date: Fri, 23 Sep 2011 17:03:06 +0100 +Subject: genirq: Add support for per-cpu dev_id interrupts + +The ARM GIC interrupt controller offers per CPU interrupts (PPIs), +which are usually used to connect local timers to each core. Each CPU +has its own private interface to the GIC, and only sees the PPIs that +are directly connect to it. + +While these timers are separate devices and have a separate interrupt +line to a core, they all use the same IRQ number. + +For these devices, request_irq() is not the right API as it assumes +that an IRQ number is visible by a number of CPUs (through the +affinity setting), but makes it very awkward to express that an IRQ +number can be handled by all CPUs, and yet be a different interrupt +line on each CPU, requiring a different dev_id cookie to be passed +back to the handler. + +The *_percpu_irq() functions is designed to overcome these +limitations, by providing a per-cpu dev_id vector: + +int request_percpu_irq(unsigned int irq, irq_handler_t handler, + const char *devname, void __percpu *percpu_dev_id); +void free_percpu_irq(unsigned int, void __percpu *); +int setup_percpu_irq(unsigned int irq, struct irqaction *new); +void remove_percpu_irq(unsigned int irq, struct irqaction *act); +void enable_percpu_irq(unsigned int irq); +void disable_percpu_irq(unsigned int irq); + +The API has a number of limitations: +- no interrupt sharing +- no threading +- common handler across all the CPUs + +Once the interrupt is requested using setup_percpu_irq() or +request_percpu_irq(), it must be enabled by each core that wishes its +local interrupt to be delivered. + +Based on an initial patch by Thomas Gleixner. + +Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> +Cc: linux-arm-kernel@lists.infradead.org +Link: http://lkml.kernel.org/r/1316793788-14500-2-git-send-email-marc.zyngier@arm.com +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +(cherry picked from commit 31d9d9b6d83030f748d013e61502fa5477e2ac0e) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/interrupt.h | 38 ++++++--- + include/linux/irq.h | 16 +++- + include/linux/irqdesc.h | 1 + + kernel/irq/chip.c | 64 +++++++++++++-- + kernel/irq/internals.h | 19 +++-- + kernel/irq/irqdesc.c | 32 +++++++- + kernel/irq/manage.c | 202 +++++++++++++++++++++++++++++++++++++++++++--- + kernel/irq/settings.h | 7 ++ + 8 files changed, 345 insertions(+), 34 deletions(-) + +diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h +index b9490bf..6fe4e3c 100644 +--- a/include/linux/interrupt.h ++++ b/include/linux/interrupt.h +@@ -98,6 +98,7 @@ typedef irqreturn_t (*irq_handler_t)(int, void *); + * @flags: flags (see IRQF_* above) + * @name: name of the device + * @dev_id: cookie to identify the device ++ * @percpu_dev_id: cookie to identify the device + * @next: pointer to the next irqaction for shared interrupts + * @irq: interrupt number + * @dir: pointer to the proc/irq/NN/name entry +@@ -107,17 +108,18 @@ typedef irqreturn_t (*irq_handler_t)(int, void *); + * @thread_mask: bitmask for keeping track of @thread activity + */ + struct irqaction { +- irq_handler_t handler; +- unsigned long flags; +- void *dev_id; +- struct irqaction *next; +- int irq; +- irq_handler_t thread_fn; +- struct task_struct *thread; +- unsigned long thread_flags; +- unsigned long thread_mask; +- const char *name; +- struct proc_dir_entry *dir; ++ irq_handler_t handler; ++ unsigned long flags; ++ void *dev_id; ++ void __percpu *percpu_dev_id; ++ struct irqaction *next; ++ int irq; ++ irq_handler_t thread_fn; ++ struct task_struct *thread; ++ unsigned long thread_flags; ++ unsigned long thread_mask; ++ const char *name; ++ struct proc_dir_entry *dir; + } ____cacheline_internodealigned_in_smp; + + extern irqreturn_t no_action(int cpl, void *dev_id); +@@ -139,6 +141,10 @@ extern int __must_check + request_any_context_irq(unsigned int irq, irq_handler_t handler, + unsigned long flags, const char *name, void *dev_id); + ++extern int __must_check ++request_percpu_irq(unsigned int irq, irq_handler_t handler, ++ const char *devname, void __percpu *percpu_dev_id); ++ + extern void exit_irq_thread(void); + #else + +@@ -167,10 +173,18 @@ request_any_context_irq(unsigned int irq, irq_handler_t handler, + return request_irq(irq, handler, flags, name, dev_id); + } + ++static inline int __must_check ++request_percpu_irq(unsigned int irq, irq_handler_t handler, ++ const char *devname, void __percpu *percpu_dev_id) ++{ ++ return request_irq(irq, handler, 0, devname, percpu_dev_id); ++} ++ + static inline void exit_irq_thread(void) { } + #endif + + extern void free_irq(unsigned int, void *); ++extern void free_percpu_irq(unsigned int, void __percpu *); + + struct device; + +@@ -210,7 +224,9 @@ extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id); + + extern void disable_irq_nosync(unsigned int irq); + extern void disable_irq(unsigned int irq); ++extern void disable_percpu_irq(unsigned int irq); + extern void enable_irq(unsigned int irq); ++extern void enable_percpu_irq(unsigned int irq); + + /* The following three functions are for the core kernel use only. */ + #ifdef CONFIG_GENERIC_HARDIRQS +diff --git a/include/linux/irq.h b/include/linux/irq.h +index d65dfca..b6cbe62 100644 +--- a/include/linux/irq.h ++++ b/include/linux/irq.h +@@ -66,6 +66,7 @@ typedef void (*irq_preflow_handler_t)(struct irq_data *data); + * IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set) + * IRQ_MOVE_PCNTXT - Interrupt can be migrated from process context + * IRQ_NESTED_TRHEAD - Interrupt nests into another thread ++ * IRQ_PER_CPU_DEVID - Dev_id is a per-cpu variable + */ + enum { + IRQ_TYPE_NONE = 0x00000000, +@@ -88,12 +89,13 @@ enum { + IRQ_MOVE_PCNTXT = (1 << 14), + IRQ_NESTED_THREAD = (1 << 15), + IRQ_NOTHREAD = (1 << 16), ++ IRQ_PER_CPU_DEVID = (1 << 17), + }; + + #define IRQF_MODIFY_MASK \ + (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \ + IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \ +- IRQ_PER_CPU | IRQ_NESTED_THREAD) ++ IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID) + + #define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING) + +@@ -372,6 +374,8 @@ enum { + struct irqaction; + extern int setup_irq(unsigned int irq, struct irqaction *new); + extern void remove_irq(unsigned int irq, struct irqaction *act); ++extern int setup_percpu_irq(unsigned int irq, struct irqaction *new); ++extern void remove_percpu_irq(unsigned int irq, struct irqaction *act); + + extern void irq_cpu_online(void); + extern void irq_cpu_offline(void); +@@ -399,6 +403,7 @@ extern void handle_edge_irq(unsigned int irq, struct irq_desc *desc); + extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc); + extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc); + extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc); ++extern void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc); + extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc); + extern void handle_nested_irq(unsigned int irq); + +@@ -427,6 +432,8 @@ static inline void irq_set_chip_and_handler(unsigned int irq, struct irq_chip *c + irq_set_chip_and_handler_name(irq, chip, handle, NULL); + } + ++extern int irq_set_percpu_devid(unsigned int irq); ++ + extern void + __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, + const char *name); +@@ -488,6 +495,13 @@ static inline void irq_set_nested_thread(unsigned int irq, bool nest) + irq_clear_status_flags(irq, IRQ_NESTED_THREAD); + } + ++static inline void irq_set_percpu_devid_flags(unsigned int irq) ++{ ++ irq_set_status_flags(irq, ++ IRQ_NOAUTOEN | IRQ_PER_CPU | IRQ_NOTHREAD | ++ IRQ_NOPROBE | IRQ_PER_CPU_DEVID); ++} ++ + /* Handle dynamic irq creation and destruction */ + extern unsigned int create_irq_nr(unsigned int irq_want, int node); + extern int create_irq(void); +diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h +index 150134a..6b69c2c 100644 +--- a/include/linux/irqdesc.h ++++ b/include/linux/irqdesc.h +@@ -53,6 +53,7 @@ struct irq_desc { + unsigned long last_unhandled; /* Aging timer for unhandled count */ + unsigned int irqs_unhandled; + raw_spinlock_t lock; ++ struct cpumask *percpu_enabled; + #ifdef CONFIG_SMP + const struct cpumask *affinity_hint; + struct irq_affinity_notify *affinity_notify; +diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c +index 990965e..25784d6 100644 +--- a/kernel/irq/chip.c ++++ b/kernel/irq/chip.c +@@ -26,7 +26,7 @@ + int irq_set_chip(unsigned int irq, struct irq_chip *chip) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_lock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); + + if (!desc) + return -EINVAL; +@@ -54,7 +54,7 @@ EXPORT_SYMBOL(irq_set_chip); + int irq_set_irq_type(unsigned int irq, unsigned int type) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); + int ret = 0; + + if (!desc) +@@ -77,7 +77,7 @@ EXPORT_SYMBOL(irq_set_irq_type); + int irq_set_handler_data(unsigned int irq, void *data) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_lock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); + + if (!desc) + return -EINVAL; +@@ -97,7 +97,7 @@ EXPORT_SYMBOL(irq_set_handler_data); + int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_lock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); + + if (!desc) + return -EINVAL; +@@ -118,7 +118,7 @@ int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry) + int irq_set_chip_data(unsigned int irq, void *data) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_lock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); + + if (!desc) + return -EINVAL; +@@ -206,6 +206,24 @@ void irq_disable(struct irq_desc *desc) + } + } + ++void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu) ++{ ++ if (desc->irq_data.chip->irq_enable) ++ desc->irq_data.chip->irq_enable(&desc->irq_data); ++ else ++ desc->irq_data.chip->irq_unmask(&desc->irq_data); ++ cpumask_set_cpu(cpu, desc->percpu_enabled); ++} ++ ++void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu) ++{ ++ if (desc->irq_data.chip->irq_disable) ++ desc->irq_data.chip->irq_disable(&desc->irq_data); ++ else ++ desc->irq_data.chip->irq_mask(&desc->irq_data); ++ cpumask_clear_cpu(cpu, desc->percpu_enabled); ++} ++ + static inline void mask_ack_irq(struct irq_desc *desc) + { + if (desc->irq_data.chip->irq_mask_ack) +@@ -567,12 +585,44 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc) + chip->irq_eoi(&desc->irq_data); + } + ++/** ++ * handle_percpu_devid_irq - Per CPU local irq handler with per cpu dev ids ++ * @irq: the interrupt number ++ * @desc: the interrupt description structure for this irq ++ * ++ * Per CPU interrupts on SMP machines without locking requirements. Same as ++ * handle_percpu_irq() above but with the following extras: ++ * ++ * action->percpu_dev_id is a pointer to percpu variables which ++ * contain the real device id for the cpu on which this handler is ++ * called ++ */ ++void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc) ++{ ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ struct irqaction *action = desc->action; ++ void *dev_id = __this_cpu_ptr(action->percpu_dev_id); ++ irqreturn_t res; ++ ++ kstat_incr_irqs_this_cpu(irq, desc); ++ ++ if (chip->irq_ack) ++ chip->irq_ack(&desc->irq_data); ++ ++ trace_irq_handler_entry(irq, action); ++ res = action->handler(irq, dev_id); ++ trace_irq_handler_exit(irq, action, res); ++ ++ if (chip->irq_eoi) ++ chip->irq_eoi(&desc->irq_data); ++} ++ + void + __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, + const char *name) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0); + + if (!desc) + return; +@@ -616,7 +666,7 @@ irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, + void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_lock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); + + if (!desc) + return; +diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h +index 62efdc4..e1a8b64 100644 +--- a/kernel/irq/internals.h ++++ b/kernel/irq/internals.h +@@ -71,6 +71,8 @@ extern int irq_startup(struct irq_desc *desc, bool resend); + extern void irq_shutdown(struct irq_desc *desc); + extern void irq_enable(struct irq_desc *desc); + extern void irq_disable(struct irq_desc *desc); ++extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu); ++extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu); + extern void mask_irq(struct irq_desc *desc); + extern void unmask_irq(struct irq_desc *desc); + +@@ -114,14 +116,21 @@ static inline void chip_bus_sync_unlock(struct irq_desc *desc) + desc->irq_data.chip->irq_bus_sync_unlock(&desc->irq_data); + } + ++#define _IRQ_DESC_CHECK (1 << 0) ++#define _IRQ_DESC_PERCPU (1 << 1) ++ ++#define IRQ_GET_DESC_CHECK_GLOBAL (_IRQ_DESC_CHECK) ++#define IRQ_GET_DESC_CHECK_PERCPU (_IRQ_DESC_CHECK | _IRQ_DESC_PERCPU) ++ + struct irq_desc * +-__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus); ++__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus, ++ unsigned int check); + void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus); + + static inline struct irq_desc * +-irq_get_desc_buslock(unsigned int irq, unsigned long *flags) ++irq_get_desc_buslock(unsigned int irq, unsigned long *flags, unsigned int check) + { +- return __irq_get_desc_lock(irq, flags, true); ++ return __irq_get_desc_lock(irq, flags, true, check); + } + + static inline void +@@ -131,9 +140,9 @@ irq_put_desc_busunlock(struct irq_desc *desc, unsigned long flags) + } + + static inline struct irq_desc * +-irq_get_desc_lock(unsigned int irq, unsigned long *flags) ++irq_get_desc_lock(unsigned int irq, unsigned long *flags, unsigned int check) + { +- return __irq_get_desc_lock(irq, flags, false); ++ return __irq_get_desc_lock(irq, flags, false, check); + } + + static inline void +diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c +index cb65d03..028e377 100644 +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -423,11 +423,22 @@ unsigned int irq_get_next_irq(unsigned int offset) + } + + struct irq_desc * +-__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus) ++__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus, ++ unsigned int check) + { + struct irq_desc *desc = irq_to_desc(irq); + + if (desc) { ++ if (check & _IRQ_DESC_CHECK) { ++ if ((check & _IRQ_DESC_PERCPU) && ++ !irq_settings_is_per_cpu_devid(desc)) ++ return NULL; ++ ++ if (!(check & _IRQ_DESC_PERCPU) && ++ irq_settings_is_per_cpu_devid(desc)) ++ return NULL; ++ } ++ + if (bus) + chip_bus_lock(desc); + raw_spin_lock_irqsave(&desc->lock, *flags); +@@ -442,6 +453,25 @@ void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus) + chip_bus_sync_unlock(desc); + } + ++int irq_set_percpu_devid(unsigned int irq) ++{ ++ struct irq_desc *desc = irq_to_desc(irq); ++ ++ if (!desc) ++ return -EINVAL; ++ ++ if (desc->percpu_enabled) ++ return -EINVAL; ++ ++ desc->percpu_enabled = kzalloc(sizeof(*desc->percpu_enabled), GFP_KERNEL); ++ ++ if (!desc->percpu_enabled) ++ return -ENOMEM; ++ ++ irq_set_percpu_devid_flags(irq); ++ return 0; ++} ++ + /** + * dynamic_irq_cleanup - cleanup a dynamically allocated irq + * @irq: irq number to initialize +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index 83fb6f5..7923849 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -195,7 +195,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *mask) + int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_lock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); + + if (!desc) + return -EINVAL; +@@ -356,7 +356,7 @@ void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend) + static int __disable_irq_nosync(unsigned int irq) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); + + if (!desc) + return -EINVAL; +@@ -448,7 +448,7 @@ void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume) + void enable_irq(unsigned int irq) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); + + if (!desc) + return; +@@ -491,7 +491,7 @@ static int set_irq_wake_real(unsigned int irq, unsigned int on) + int irq_set_irq_wake(unsigned int irq, unsigned int on) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); + int ret = 0; + + if (!desc) +@@ -532,7 +532,7 @@ EXPORT_SYMBOL(irq_set_irq_wake); + int can_request_irq(unsigned int irq, unsigned long irqflags) + { + unsigned long flags; +- struct irq_desc *desc = irq_get_desc_lock(irq, &flags); ++ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); + int canrequest = 0; + + if (!desc) +@@ -1156,6 +1156,8 @@ int setup_irq(unsigned int irq, struct irqaction *act) + int retval; + struct irq_desc *desc = irq_to_desc(irq); + ++ if (WARN_ON(irq_settings_is_per_cpu_devid(desc))) ++ return -EINVAL; + chip_bus_lock(desc); + retval = __setup_irq(irq, desc, act); + chip_bus_sync_unlock(desc); +@@ -1164,7 +1166,7 @@ int setup_irq(unsigned int irq, struct irqaction *act) + } + EXPORT_SYMBOL_GPL(setup_irq); + +- /* ++/* + * Internal function to unregister an irqaction - used to free + * regular and special interrupts that are part of the architecture. + */ +@@ -1262,7 +1264,10 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) + */ + void remove_irq(unsigned int irq, struct irqaction *act) + { +- __free_irq(irq, act->dev_id); ++ struct irq_desc *desc = irq_to_desc(irq); ++ ++ if (desc && !WARN_ON(irq_settings_is_per_cpu_devid(desc))) ++ __free_irq(irq, act->dev_id); + } + EXPORT_SYMBOL_GPL(remove_irq); + +@@ -1284,7 +1289,7 @@ void free_irq(unsigned int irq, void *dev_id) + { + struct irq_desc *desc = irq_to_desc(irq); + +- if (!desc) ++ if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc))) + return; + + #ifdef CONFIG_SMP +@@ -1362,7 +1367,8 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler, + if (!desc) + return -EINVAL; + +- if (!irq_settings_can_request(desc)) ++ if (!irq_settings_can_request(desc) || ++ WARN_ON(irq_settings_is_per_cpu_devid(desc))) + return -EINVAL; + + if (!handler) { +@@ -1447,3 +1453,181 @@ int request_any_context_irq(unsigned int irq, irq_handler_t handler, + return !ret ? IRQC_IS_HARDIRQ : ret; + } + EXPORT_SYMBOL_GPL(request_any_context_irq); ++ ++void enable_percpu_irq(unsigned int irq) ++{ ++ unsigned int cpu = smp_processor_id(); ++ unsigned long flags; ++ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU); ++ ++ if (!desc) ++ return; ++ ++ irq_percpu_enable(desc, cpu); ++ irq_put_desc_unlock(desc, flags); ++} ++ ++void disable_percpu_irq(unsigned int irq) ++{ ++ unsigned int cpu = smp_processor_id(); ++ unsigned long flags; ++ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU); ++ ++ if (!desc) ++ return; ++ ++ irq_percpu_disable(desc, cpu); ++ irq_put_desc_unlock(desc, flags); ++} ++ ++/* ++ * Internal function to unregister a percpu irqaction. ++ */ ++static struct irqaction *__free_percpu_irq(unsigned int irq, void __percpu *dev_id) ++{ ++ struct irq_desc *desc = irq_to_desc(irq); ++ struct irqaction *action; ++ unsigned long flags; ++ ++ WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq); ++ ++ if (!desc) ++ return NULL; ++ ++ raw_spin_lock_irqsave(&desc->lock, flags); ++ ++ action = desc->action; ++ if (!action || action->percpu_dev_id != dev_id) { ++ WARN(1, "Trying to free already-free IRQ %d\n", irq); ++ goto bad; ++ } ++ ++ if (!cpumask_empty(desc->percpu_enabled)) { ++ WARN(1, "percpu IRQ %d still enabled on CPU%d!\n", ++ irq, cpumask_first(desc->percpu_enabled)); ++ goto bad; ++ } ++ ++ /* Found it - now remove it from the list of entries: */ ++ desc->action = NULL; ++ ++ raw_spin_unlock_irqrestore(&desc->lock, flags); ++ ++ unregister_handler_proc(irq, action); ++ ++ module_put(desc->owner); ++ return action; ++ ++bad: ++ raw_spin_unlock_irqrestore(&desc->lock, flags); ++ return NULL; ++} ++ ++/** ++ * remove_percpu_irq - free a per-cpu interrupt ++ * @irq: Interrupt line to free ++ * @act: irqaction for the interrupt ++ * ++ * Used to remove interrupts statically setup by the early boot process. ++ */ ++void remove_percpu_irq(unsigned int irq, struct irqaction *act) ++{ ++ struct irq_desc *desc = irq_to_desc(irq); ++ ++ if (desc && irq_settings_is_per_cpu_devid(desc)) ++ __free_percpu_irq(irq, act->percpu_dev_id); ++} ++ ++/** ++ * free_percpu_irq - free an interrupt allocated with request_percpu_irq ++ * @irq: Interrupt line to free ++ * @dev_id: Device identity to free ++ * ++ * Remove a percpu interrupt handler. The handler is removed, but ++ * the interrupt line is not disabled. This must be done on each ++ * CPU before calling this function. The function does not return ++ * until any executing interrupts for this IRQ have completed. ++ * ++ * This function must not be called from interrupt context. ++ */ ++void free_percpu_irq(unsigned int irq, void __percpu *dev_id) ++{ ++ struct irq_desc *desc = irq_to_desc(irq); ++ ++ if (!desc || !irq_settings_is_per_cpu_devid(desc)) ++ return; ++ ++ chip_bus_lock(desc); ++ kfree(__free_percpu_irq(irq, dev_id)); ++ chip_bus_sync_unlock(desc); ++} ++ ++/** ++ * setup_percpu_irq - setup a per-cpu interrupt ++ * @irq: Interrupt line to setup ++ * @act: irqaction for the interrupt ++ * ++ * Used to statically setup per-cpu interrupts in the early boot process. ++ */ ++int setup_percpu_irq(unsigned int irq, struct irqaction *act) ++{ ++ struct irq_desc *desc = irq_to_desc(irq); ++ int retval; ++ ++ if (!desc || !irq_settings_is_per_cpu_devid(desc)) ++ return -EINVAL; ++ chip_bus_lock(desc); ++ retval = __setup_irq(irq, desc, act); ++ chip_bus_sync_unlock(desc); ++ ++ return retval; ++} ++ ++/** ++ * request_percpu_irq - allocate a percpu interrupt line ++ * @irq: Interrupt line to allocate ++ * @handler: Function to be called when the IRQ occurs. ++ * @devname: An ascii name for the claiming device ++ * @dev_id: A percpu cookie passed back to the handler function ++ * ++ * This call allocates interrupt resources, but doesn't ++ * automatically enable the interrupt. It has to be done on each ++ * CPU using enable_percpu_irq(). ++ * ++ * Dev_id must be globally unique. It is a per-cpu variable, and ++ * the handler gets called with the interrupted CPU's instance of ++ * that variable. ++ */ ++int request_percpu_irq(unsigned int irq, irq_handler_t handler, ++ const char *devname, void __percpu *dev_id) ++{ ++ struct irqaction *action; ++ struct irq_desc *desc; ++ int retval; ++ ++ if (!dev_id) ++ return -EINVAL; ++ ++ desc = irq_to_desc(irq); ++ if (!desc || !irq_settings_can_request(desc) || ++ !irq_settings_is_per_cpu_devid(desc)) ++ return -EINVAL; ++ ++ action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); ++ if (!action) ++ return -ENOMEM; ++ ++ action->handler = handler; ++ action->flags = IRQF_PERCPU; ++ action->name = devname; ++ action->percpu_dev_id = dev_id; ++ ++ chip_bus_lock(desc); ++ retval = __setup_irq(irq, desc, action); ++ chip_bus_sync_unlock(desc); ++ ++ if (retval) ++ kfree(action); ++ ++ return retval; ++} +diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h +index f166783..1162f10 100644 +--- a/kernel/irq/settings.h ++++ b/kernel/irq/settings.h +@@ -13,6 +13,7 @@ enum { + _IRQ_MOVE_PCNTXT = IRQ_MOVE_PCNTXT, + _IRQ_NO_BALANCING = IRQ_NO_BALANCING, + _IRQ_NESTED_THREAD = IRQ_NESTED_THREAD, ++ _IRQ_PER_CPU_DEVID = IRQ_PER_CPU_DEVID, + _IRQF_MODIFY_MASK = IRQF_MODIFY_MASK, + }; + +@@ -24,6 +25,7 @@ enum { + #define IRQ_NOTHREAD GOT_YOU_MORON + #define IRQ_NOAUTOEN GOT_YOU_MORON + #define IRQ_NESTED_THREAD GOT_YOU_MORON ++#define IRQ_PER_CPU_DEVID GOT_YOU_MORON + #undef IRQF_MODIFY_MASK + #define IRQF_MODIFY_MASK GOT_YOU_MORON + +@@ -39,6 +41,11 @@ static inline bool irq_settings_is_per_cpu(struct irq_desc *desc) + return desc->status_use_accessors & _IRQ_PER_CPU; + } + ++static inline bool irq_settings_is_per_cpu_devid(struct irq_desc *desc) ++{ ++ return desc->status_use_accessors & _IRQ_PER_CPU_DEVID; ++} ++ + static inline void irq_settings_set_per_cpu(struct irq_desc *desc) + { + desc->status_use_accessors |= _IRQ_PER_CPU; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0148-ARM-introduce-handle_IRQ-not-to-dump-exception-stack.patch b/patches.kzm9g/0148-ARM-introduce-handle_IRQ-not-to-dump-exception-stack.patch new file mode 100644 index 00000000000000..32f68f4a6ed50c --- /dev/null +++ b/patches.kzm9g/0148-ARM-introduce-handle_IRQ-not-to-dump-exception-stack.patch @@ -0,0 +1,123 @@ +From ef24b31c6a52daa9cdf20cfe63c5dab8c8186926 Mon Sep 17 00:00:00 2001 +From: Russell King - ARM Linux <linux@arm.linux.org.uk> +Date: Mon, 11 Jul 2011 22:25:43 +0100 +Subject: ARM: introduce handle_IRQ() not to dump exception stack + +On Mon, Jul 11, 2011 at 3:52 PM, Russell King - ARM Linux +<linux@arm.linux.org.uk> wrote: + +... + +> The __exception annotation on a function causes this to happen: +> +> [<c002406c>] (asm_do_IRQ+0x6c/0x8c) from [<c0024b84>] +> (__irq_svc+0x44/0xcc) +> Exception stack(0xc3897c78 to 0xc3897cc0) +> 7c60: 4022d320 4022e000 +> 7c80: 08000075 00001000 c32273c0 c03ce1c0 c2b49b78 4022d000 c2b420b4 00000001 +> 7ca0: 00000000 c3897cfc 00000000 c3897cc0 c00afc54 c002edd8 00000013 ffffffff +> +> Where that stack dump represents the pt_regs for the exception which +> happened. Any function found in while unwinding will cause this to +> be printed. +> +> If you insert a C function between the IRQ assembly and asm_do_IRQ, +> the +> dump you get from asm_do_IRQ will be the stack for your function, +> not +> the pt_regs. That makes the feature useless. +> + +When __irq_svc - or any of the other exception handling assembly code - +calls the C code, the stack pointer will be pointing at the pt_regs +structure. + +All the entry points into C code from the exception handling code are +marked with __exception or __exception_irq_enter to indicate that they +are one of the functions which has pt_regs above them. + +Normally, when you've entered asm_do_IRQ() you will have this stack +layout (higher address towards top): + + pt_regs + asm_do_IRQ frame + +If you insert a C function between the exception assembly code and +asm_do_IRQ, you end up with this stack layout instead: + + pt_regs + your function frame + asm_do_IRQ frame + +This means when we unwind, we'll get to asm_do_IRQ, and rather than +dumping out the pt_regs, we'll dump out your functions stack frame +instead, because that's what is above the asm_do_IRQ stack frame +rather than the expected pt_regs structure. + +The fix is to introduce handle_IRQ() for no exception stack dump, so +it can be called with MULTI_IRQ_HANDLER is selected and a C function +is between the assembly code and the actual IRQ handling code. + +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +Signed-off-by: Eric Miao <eric.y.miao@gmail.com> +(cherry picked from commit a4841e39f7ca85ee2a40803ebac6221c6d8822c0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/include/asm/irq.h | 1 + + arch/arm/kernel/irq.c | 19 ++++++++++++++----- + 2 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h +index 2721a58..5a526af 100644 +--- a/arch/arm/include/asm/irq.h ++++ b/arch/arm/include/asm/irq.h +@@ -23,6 +23,7 @@ struct pt_regs; + extern void migrate_irqs(void); + + extern void asm_do_IRQ(unsigned int, struct pt_regs *); ++void handle_IRQ(unsigned int, struct pt_regs *); + void init_IRQ(void); + + #endif +diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c +index 83bbad0..dbc1f41 100644 +--- a/arch/arm/kernel/irq.c ++++ b/arch/arm/kernel/irq.c +@@ -67,12 +67,12 @@ int arch_show_interrupts(struct seq_file *p, int prec) + } + + /* +- * do_IRQ handles all hardware IRQ's. Decoded IRQs should not +- * come via this function. Instead, they should provide their +- * own 'handler' ++ * handle_IRQ handles all hardware IRQ's. Decoded IRQs should ++ * not come via this function. Instead, they should provide their ++ * own 'handler'. Used by platform code implementing C-based 1st ++ * level decoding. + */ +-asmlinkage void __exception_irq_entry +-asm_do_IRQ(unsigned int irq, struct pt_regs *regs) ++void handle_IRQ(unsigned int irq, struct pt_regs *regs) + { + struct pt_regs *old_regs = set_irq_regs(regs); + +@@ -97,6 +97,15 @@ asm_do_IRQ(unsigned int irq, struct pt_regs *regs) + set_irq_regs(old_regs); + } + ++/* ++ * asm_do_IRQ is the interface to be used from assembly code. ++ */ ++asmlinkage void __exception_irq_entry ++asm_do_IRQ(unsigned int irq, struct pt_regs *regs) ++{ ++ handle_IRQ(irq, regs); ++} ++ + void set_irq_flags(unsigned int irq, unsigned int iflags) + { + unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0149-ARM-GIC-move-gic_chip_data-structure-declaration-to-.patch b/patches.kzm9g/0149-ARM-GIC-move-gic_chip_data-structure-declaration-to-.patch new file mode 100644 index 00000000000000..fabd6f1a934fe0 --- /dev/null +++ b/patches.kzm9g/0149-ARM-GIC-move-gic_chip_data-structure-declaration-to-.patch @@ -0,0 +1,59 @@ +From eb34882abb20009f826539498f60d94406fd7aca Mon Sep 17 00:00:00 2001 +From: Changhwan Youn <chaos.youn@samsung.com> +Date: Sat, 16 Jul 2011 10:49:47 +0900 +Subject: ARM: GIC: move gic_chip_data structure declaration to header + +Since Samsung EXYNOS4210 cannot support register banking in GIC, +so needs to update CPU interface base address. +The 'gic_chip_data' is used for it, this patch moves gic_chip_data +structure declaraton to arch/arm/include/asm/hardware/gic.h to use +it. + +Cc: Russell King <rmk+kernel@arm.linux.org.uk> +Signed-off-by: Changhwan Youn <chaos.youn@samsung.com> +Signed-off-by: Kukjin Kim <kgene.kim@samsung.com> +(cherry picked from commit e807acbc6fd1d5ff115f9a8eae0c1af6cf1c46c6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 6 ------ + arch/arm/include/asm/hardware/gic.h | 6 ++++++ + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 4ddd0a6..23564ed 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -38,12 +38,6 @@ static DEFINE_SPINLOCK(irq_controller_lock); + /* Address of GIC 0 CPU interface */ + void __iomem *gic_cpu_base_addr __read_mostly; + +-struct gic_chip_data { +- unsigned int irq_offset; +- void __iomem *dist_base; +- void __iomem *cpu_base; +-}; +- + /* + * Supported arch specific GIC irq extension. + * Default make them NULL. +diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h +index 0691f9d..435d3f8 100644 +--- a/arch/arm/include/asm/hardware/gic.h ++++ b/arch/arm/include/asm/hardware/gic.h +@@ -41,6 +41,12 @@ void gic_secondary_init(unsigned int); + void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); + void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); + void gic_enable_ppi(unsigned int); ++ ++struct gic_chip_data { ++ unsigned int irq_offset; ++ void __iomem *dist_base; ++ void __iomem *cpu_base; ++}; + #endif + + #endif +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0150-ARM-CPU-hotplug-fix-abuse-of-irqdesc-node.patch b/patches.kzm9g/0150-ARM-CPU-hotplug-fix-abuse-of-irqdesc-node.patch new file mode 100644 index 00000000000000..d0fe540f728d32 --- /dev/null +++ b/patches.kzm9g/0150-ARM-CPU-hotplug-fix-abuse-of-irqdesc-node.patch @@ -0,0 +1,55 @@ +From 937519bccf58b2af70bfaf0b199c9fe8a6bab3b5 Mon Sep 17 00:00:00 2001 +From: Russell King <rmk+kernel@arm.linux.org.uk> +Date: Thu, 21 Jul 2011 14:51:13 +0100 +Subject: ARM: CPU hotplug: fix abuse of irqdesc->node + +irqdesc's node member is supposed to mark the numa node number for the +interrupt. Our use of it is non-standard. Remove this, replacing the +functionality with a test of the affinity mask. + +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit 2ef75701d1711a1feee2a82b42a2597ddc05f88b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 1 - + arch/arm/kernel/irq.c | 10 ++-------- + 2 files changed, 2 insertions(+), 9 deletions(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 23564ed..2ba61e5 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -183,7 +183,6 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, + bit = 1 << (cpu + shift); + + spin_lock(&irq_controller_lock); +- d->node = cpu; + val = readl_relaxed(reg) & ~mask; + writel_relaxed(val | bit, reg); + spin_unlock(&irq_controller_lock); +diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c +index dbc1f41..3e34b1f 100644 +--- a/arch/arm/kernel/irq.c ++++ b/arch/arm/kernel/irq.c +@@ -175,15 +175,9 @@ void migrate_irqs(void) + bool affinity_broken = false; + + raw_spin_lock(&desc->lock); +- do { +- if (desc->action == NULL) +- break; +- +- if (d->node != cpu) +- break; +- ++ if (desc->action != NULL && ++ cpumask_test_cpu(smp_processor_id(), d->affinity)) + affinity_broken = migrate_one_irq(d); +- } while (0); + raw_spin_unlock(&desc->lock); + + if (affinity_broken && printk_ratelimit()) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0151-ARM-GIC-avoid-routing-interrupts-to-offline-CPUs.patch b/patches.kzm9g/0151-ARM-GIC-avoid-routing-interrupts-to-offline-CPUs.patch new file mode 100644 index 00000000000000..dcf5e862855203 --- /dev/null +++ b/patches.kzm9g/0151-ARM-GIC-avoid-routing-interrupts-to-offline-CPUs.patch @@ -0,0 +1,52 @@ +From aada114ebfda78d2fba02d654fa67b075e31d27d Mon Sep 17 00:00:00 2001 +From: Russell King <rmk+kernel@arm.linux.org.uk> +Date: Thu, 21 Jul 2011 15:00:57 +0100 +Subject: ARM: GIC: avoid routing interrupts to offline CPUs + +The irq_set_affinity() method can be called with masks which include +offline CPUs. This allows offline CPUs to have interrupts routed to +them by writing to /proc/irq/*/smp_affinity after hotplug has taken +a CPU offline. Fix this by ensuring that we select a target CPU +present in both the required affinity and the online CPU mask. + +Ensure that we return IRQ_SET_MASK_OK (which happens to be 0) on +success to ensure generic code copies the new mask into the irq_data +structure. + +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit 5dfc54e087c15f823ee9b6541d2f0f314e69cbed) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 2ba61e5..3227ca9 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -173,10 +173,10 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, + { + void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); + unsigned int shift = (d->irq % 4) * 8; +- unsigned int cpu = cpumask_first(mask_val); ++ unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask); + u32 val, mask, bit; + +- if (cpu >= 8) ++ if (cpu >= 8 || cpu >= nr_cpu_ids) + return -EINVAL; + + mask = 0xff << shift; +@@ -187,7 +187,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, + writel_relaxed(val | bit, reg); + spin_unlock(&irq_controller_lock); + +- return 0; ++ return IRQ_SET_MASK_OK; + } + #endif + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0152-ARM-gic-Use-cpu-pm-notifiers-to-save-gic-state.patch b/patches.kzm9g/0152-ARM-gic-Use-cpu-pm-notifiers-to-save-gic-state.patch new file mode 100644 index 00000000000000..6e4f4718efcfe6 --- /dev/null +++ b/patches.kzm9g/0152-ARM-gic-Use-cpu-pm-notifiers-to-save-gic-state.patch @@ -0,0 +1,268 @@ +From ca0bcbc7836024b138b86d00c9c8e61c14ad4716 Mon Sep 17 00:00:00 2001 +From: Colin Cross <ccross@android.com> +Date: Thu, 10 Feb 2011 12:54:10 -0800 +Subject: ARM: gic: Use cpu pm notifiers to save gic state + +When the cpu is powered down in a low power mode, the gic cpu +interface may be reset, and when the cpu cluster is powered +down, the gic distributor may also be reset. + +This patch uses CPU_PM_ENTER and CPU_PM_EXIT notifiers to save +and restore the gic cpu interface registers, and the +CPU_CLUSTER_PM_ENTER and CPU_CLUSTER_PM_EXIT notifiers to save +and restore the gic distributor registers. + +Original-author: Gary King <gking@nvidia.com> +Signed-off-by: Colin Cross <ccross@android.com> +Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> +Tested-and-Acked-by: Shawn Guo <shawn.guo@linaro.org> +Tested-by: Vishwanath BS <vishwanath.bs@ti.com> +(cherry picked from commit 254056f3b12563c11e6dbcfad2fbfce20a4f3302) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 187 ++++++++++++++++++++++++++++++++++++ + arch/arm/include/asm/hardware/gic.h | 8 ++ + 2 files changed, 195 insertions(+) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 3227ca9..66c7c48 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -26,6 +26,7 @@ + #include <linux/kernel.h> + #include <linux/list.h> + #include <linux/smp.h> ++#include <linux/cpu_pm.h> + #include <linux/cpumask.h> + #include <linux/io.h> + +@@ -276,6 +277,8 @@ static void __init gic_dist_init(struct gic_chip_data *gic, + if (gic_irqs > 1020) + gic_irqs = 1020; + ++ gic->gic_irqs = gic_irqs; ++ + /* + * Set all global interrupts to be level triggered, active low. + */ +@@ -343,6 +346,189 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) + writel_relaxed(1, base + GIC_CPU_CTRL); + } + ++#ifdef CONFIG_CPU_PM ++/* ++ * Saves the GIC distributor registers during suspend or idle. Must be called ++ * with interrupts disabled but before powering down the GIC. After calling ++ * this function, no interrupts will be delivered by the GIC, and another ++ * platform-specific wakeup source must be enabled. ++ */ ++static void gic_dist_save(unsigned int gic_nr) ++{ ++ unsigned int gic_irqs; ++ void __iomem *dist_base; ++ int i; ++ ++ if (gic_nr >= MAX_GIC_NR) ++ BUG(); ++ ++ gic_irqs = gic_data[gic_nr].gic_irqs; ++ dist_base = gic_data[gic_nr].dist_base; ++ ++ if (!dist_base) ++ return; ++ ++ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++) ++ gic_data[gic_nr].saved_spi_conf[i] = ++ readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4); ++ ++ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) ++ gic_data[gic_nr].saved_spi_target[i] = ++ readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4); ++ ++ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) ++ gic_data[gic_nr].saved_spi_enable[i] = ++ readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4); ++} ++ ++/* ++ * Restores the GIC distributor registers during resume or when coming out of ++ * idle. Must be called before enabling interrupts. If a level interrupt ++ * that occured while the GIC was suspended is still present, it will be ++ * handled normally, but any edge interrupts that occured will not be seen by ++ * the GIC and need to be handled by the platform-specific wakeup source. ++ */ ++static void gic_dist_restore(unsigned int gic_nr) ++{ ++ unsigned int gic_irqs; ++ unsigned int i; ++ void __iomem *dist_base; ++ ++ if (gic_nr >= MAX_GIC_NR) ++ BUG(); ++ ++ gic_irqs = gic_data[gic_nr].gic_irqs; ++ dist_base = gic_data[gic_nr].dist_base; ++ ++ if (!dist_base) ++ return; ++ ++ writel_relaxed(0, dist_base + GIC_DIST_CTRL); ++ ++ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++) ++ writel_relaxed(gic_data[gic_nr].saved_spi_conf[i], ++ dist_base + GIC_DIST_CONFIG + i * 4); ++ ++ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) ++ writel_relaxed(0xa0a0a0a0, ++ dist_base + GIC_DIST_PRI + i * 4); ++ ++ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) ++ writel_relaxed(gic_data[gic_nr].saved_spi_target[i], ++ dist_base + GIC_DIST_TARGET + i * 4); ++ ++ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) ++ writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], ++ dist_base + GIC_DIST_ENABLE_SET + i * 4); ++ ++ writel_relaxed(1, dist_base + GIC_DIST_CTRL); ++} ++ ++static void gic_cpu_save(unsigned int gic_nr) ++{ ++ int i; ++ u32 *ptr; ++ void __iomem *dist_base; ++ void __iomem *cpu_base; ++ ++ if (gic_nr >= MAX_GIC_NR) ++ BUG(); ++ ++ dist_base = gic_data[gic_nr].dist_base; ++ cpu_base = gic_data[gic_nr].cpu_base; ++ ++ if (!dist_base || !cpu_base) ++ return; ++ ++ ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable); ++ for (i = 0; i < DIV_ROUND_UP(32, 32); i++) ++ ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4); ++ ++ ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf); ++ for (i = 0; i < DIV_ROUND_UP(32, 16); i++) ++ ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4); ++ ++} ++ ++static void gic_cpu_restore(unsigned int gic_nr) ++{ ++ int i; ++ u32 *ptr; ++ void __iomem *dist_base; ++ void __iomem *cpu_base; ++ ++ if (gic_nr >= MAX_GIC_NR) ++ BUG(); ++ ++ dist_base = gic_data[gic_nr].dist_base; ++ cpu_base = gic_data[gic_nr].cpu_base; ++ ++ if (!dist_base || !cpu_base) ++ return; ++ ++ ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable); ++ for (i = 0; i < DIV_ROUND_UP(32, 32); i++) ++ writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4); ++ ++ ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf); ++ for (i = 0; i < DIV_ROUND_UP(32, 16); i++) ++ writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4); ++ ++ for (i = 0; i < DIV_ROUND_UP(32, 4); i++) ++ writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); ++ ++ writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); ++ writel_relaxed(1, cpu_base + GIC_CPU_CTRL); ++} ++ ++static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_GIC_NR; i++) { ++ switch (cmd) { ++ case CPU_PM_ENTER: ++ gic_cpu_save(i); ++ break; ++ case CPU_PM_ENTER_FAILED: ++ case CPU_PM_EXIT: ++ gic_cpu_restore(i); ++ break; ++ case CPU_CLUSTER_PM_ENTER: ++ gic_dist_save(i); ++ break; ++ case CPU_CLUSTER_PM_ENTER_FAILED: ++ case CPU_CLUSTER_PM_EXIT: ++ gic_dist_restore(i); ++ break; ++ } ++ } ++ ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block gic_notifier_block = { ++ .notifier_call = gic_notifier, ++}; ++ ++static void __init gic_pm_init(struct gic_chip_data *gic) ++{ ++ gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4, ++ sizeof(u32)); ++ BUG_ON(!gic->saved_ppi_enable); ++ ++ gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4, ++ sizeof(u32)); ++ BUG_ON(!gic->saved_ppi_conf); ++ ++ cpu_pm_register_notifier(&gic_notifier_block); ++} ++#else ++static void __init gic_pm_init(struct gic_chip_data *gic) ++{ ++} ++#endif ++ + void __init gic_init(unsigned int gic_nr, unsigned int irq_start, + void __iomem *dist_base, void __iomem *cpu_base) + { +@@ -360,6 +546,7 @@ void __init gic_init(unsigned int gic_nr, unsigned int irq_start, + + gic_dist_init(gic, irq_start); + gic_cpu_init(gic); ++ gic_pm_init(gic); + } + + void __cpuinit gic_secondary_init(unsigned int gic_nr) +diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h +index 435d3f8..c562705 100644 +--- a/arch/arm/include/asm/hardware/gic.h ++++ b/arch/arm/include/asm/hardware/gic.h +@@ -46,6 +46,14 @@ struct gic_chip_data { + unsigned int irq_offset; + void __iomem *dist_base; + void __iomem *cpu_base; ++#ifdef CONFIG_CPU_PM ++ u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)]; ++ u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)]; ++ u32 saved_spi_target[DIV_ROUND_UP(1020, 4)]; ++ u32 __percpu *saved_ppi_enable; ++ u32 __percpu *saved_ppi_conf; ++#endif ++ unsigned int gic_irqs; + }; + #endif + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0153-ARM-7011-1-Add-ARM-cpu-topology-definition.patch b/patches.kzm9g/0153-ARM-7011-1-Add-ARM-cpu-topology-definition.patch new file mode 100644 index 00000000000000..f61fa457bdfa19 --- /dev/null +++ b/patches.kzm9g/0153-ARM-7011-1-Add-ARM-cpu-topology-definition.patch @@ -0,0 +1,351 @@ +From b20aa3f7ccd0f3add1c52a930cac2efa98acda7d Mon Sep 17 00:00:00 2001 +From: Vincent Guittot <vincent.guittot@linaro.org> +Date: Mon, 8 Aug 2011 13:21:59 +0100 +Subject: ARM: 7011/1: Add ARM cpu topology definition + +The affinity between ARM processors is defined in the MPIDR register. +We can identify which processors are in the same cluster, +and which ones have performance interdependency. We can define the +cpu topology of ARM platform, that is then used by sched_mc and sched_smt. + +The default state of sched_mc and sched_smt config is disable. +When enabled, the behavior of the scheduler can be modified with +sched_mc_power_savings and sched_smt_power_savings sysfs interfaces. + +Changes since v4 : +* Remove unnecessary parentheses and blank lines + +Changes since v3 : +* Update the format of printk message +* Remove blank line + +Changes since v2 : +* Update the commit message and some comments + +Changes since v1 : +* Update the commit message +* Add read_cpuid_mpidr in arch/arm/include/asm/cputype.h +* Modify header of arch/arm/kernel/topology.c +* Modify tests and manipulation of MPIDR's bitfields +* Modify the place and dependancy of the config +* Modify Noop functions + +Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org> +Reviewed-by: Amit Kucheria <amit.kucheria@linaro.org> +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit c9018aab8eee24b993c12c7aff7fc99d3d73f298) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/Kconfig | 25 +++++++ + arch/arm/include/asm/cputype.h | 6 ++ + arch/arm/include/asm/topology.h | 33 +++++++++ + arch/arm/kernel/Makefile | 1 + + arch/arm/kernel/smp.c | 5 ++ + arch/arm/kernel/topology.c | 148 ++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 218 insertions(+) + create mode 100644 arch/arm/kernel/topology.c + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index d7f1a02..7692bca 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1370,6 +1370,31 @@ config SMP_ON_UP + + If you don't know what to do here, say Y. + ++config ARM_CPU_TOPOLOGY ++ bool "Support cpu topology definition" ++ depends on SMP && CPU_V7 ++ default y ++ help ++ Support ARM cpu topology definition. The MPIDR register defines ++ affinity between processors which is then used to describe the cpu ++ topology of an ARM System. ++ ++config SCHED_MC ++ bool "Multi-core scheduler support" ++ depends on ARM_CPU_TOPOLOGY ++ help ++ Multi-core scheduler support improves the CPU scheduler's decision ++ making when dealing with multi-core CPU chips at a cost of slightly ++ increased overhead in some places. If unsure say N here. ++ ++config SCHED_SMT ++ bool "SMT scheduler support" ++ depends on ARM_CPU_TOPOLOGY ++ help ++ Improves the CPU scheduler's decision making when dealing with ++ MultiThreading at a cost of slightly increased overhead in some ++ places. If unsure say N here. ++ + config HAVE_ARM_SCU + bool + depends on SMP +diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h +index cd4458f..cb47d28 100644 +--- a/arch/arm/include/asm/cputype.h ++++ b/arch/arm/include/asm/cputype.h +@@ -8,6 +8,7 @@ + #define CPUID_CACHETYPE 1 + #define CPUID_TCM 2 + #define CPUID_TLBTYPE 3 ++#define CPUID_MPIDR 5 + + #define CPUID_EXT_PFR0 "c1, 0" + #define CPUID_EXT_PFR1 "c1, 1" +@@ -70,6 +71,11 @@ static inline unsigned int __attribute_const__ read_cpuid_tcmstatus(void) + return read_cpuid(CPUID_TCM); + } + ++static inline unsigned int __attribute_const__ read_cpuid_mpidr(void) ++{ ++ return read_cpuid(CPUID_MPIDR); ++} ++ + /* + * Intel's XScale3 core supports some v6 features (supersections, L2) + * but advertises itself as v5 as it does not support the v6 ISA. For +diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h +index accbd7c..a7e457e 100644 +--- a/arch/arm/include/asm/topology.h ++++ b/arch/arm/include/asm/topology.h +@@ -1,6 +1,39 @@ + #ifndef _ASM_ARM_TOPOLOGY_H + #define _ASM_ARM_TOPOLOGY_H + ++#ifdef CONFIG_ARM_CPU_TOPOLOGY ++ ++#include <linux/cpumask.h> ++ ++struct cputopo_arm { ++ int thread_id; ++ int core_id; ++ int socket_id; ++ cpumask_t thread_sibling; ++ cpumask_t core_sibling; ++}; ++ ++extern struct cputopo_arm cpu_topology[NR_CPUS]; ++ ++#define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id) ++#define topology_core_id(cpu) (cpu_topology[cpu].core_id) ++#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) ++#define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) ++ ++#define mc_capable() (cpu_topology[0].socket_id != -1) ++#define smt_capable() (cpu_topology[0].thread_id != -1) ++ ++void init_cpu_topology(void); ++void store_cpu_topology(unsigned int cpuid); ++const struct cpumask *cpu_coregroup_mask(unsigned int cpu); ++ ++#else ++ ++static inline void init_cpu_topology(void) { } ++static inline void store_cpu_topology(unsigned int cpuid) { } ++ ++#endif ++ + #include <asm-generic/topology.h> + + #endif /* _ASM_ARM_TOPOLOGY_H */ +diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile +index a5b31af..816a481 100644 +--- a/arch/arm/kernel/Makefile ++++ b/arch/arm/kernel/Makefile +@@ -61,6 +61,7 @@ obj-$(CONFIG_IWMMXT) += iwmmxt.o + obj-$(CONFIG_CPU_HAS_PMU) += pmu.o + obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o + AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt ++obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o + + ifneq ($(CONFIG_ARCH_EBSA110),y) + obj-y += io.o +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index e7f92a4..8e3a000 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -31,6 +31,7 @@ + #include <asm/cacheflush.h> + #include <asm/cpu.h> + #include <asm/cputype.h> ++#include <asm/topology.h> + #include <asm/mmu_context.h> + #include <asm/pgtable.h> + #include <asm/pgalloc.h> +@@ -268,6 +269,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid) + struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); + + cpu_info->loops_per_jiffy = loops_per_jiffy; ++ ++ store_cpu_topology(cpuid); + } + + /* +@@ -358,6 +361,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) + { + unsigned int ncores = num_possible_cpus(); + ++ init_cpu_topology(); ++ + smp_store_cpu_info(smp_processor_id()); + + /* +diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c +new file mode 100644 +index 0000000..1040c00 +--- /dev/null ++++ b/arch/arm/kernel/topology.c +@@ -0,0 +1,148 @@ ++/* ++ * arch/arm/kernel/topology.c ++ * ++ * Copyright (C) 2011 Linaro Limited. ++ * Written by: Vincent Guittot ++ * ++ * based on arch/sh/kernel/topology.c ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ */ ++ ++#include <linux/cpu.h> ++#include <linux/cpumask.h> ++#include <linux/init.h> ++#include <linux/percpu.h> ++#include <linux/node.h> ++#include <linux/nodemask.h> ++#include <linux/sched.h> ++ ++#include <asm/cputype.h> ++#include <asm/topology.h> ++ ++#define MPIDR_SMP_BITMASK (0x3 << 30) ++#define MPIDR_SMP_VALUE (0x2 << 30) ++ ++#define MPIDR_MT_BITMASK (0x1 << 24) ++ ++/* ++ * These masks reflect the current use of the affinity levels. ++ * The affinity level can be up to 16 bits according to ARM ARM ++ */ ++ ++#define MPIDR_LEVEL0_MASK 0x3 ++#define MPIDR_LEVEL0_SHIFT 0 ++ ++#define MPIDR_LEVEL1_MASK 0xF ++#define MPIDR_LEVEL1_SHIFT 8 ++ ++#define MPIDR_LEVEL2_MASK 0xFF ++#define MPIDR_LEVEL2_SHIFT 16 ++ ++struct cputopo_arm cpu_topology[NR_CPUS]; ++ ++const struct cpumask *cpu_coregroup_mask(unsigned int cpu) ++{ ++ return &cpu_topology[cpu].core_sibling; ++} ++ ++/* ++ * store_cpu_topology is called at boot when only one cpu is running ++ * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, ++ * which prevents simultaneous write access to cpu_topology array ++ */ ++void store_cpu_topology(unsigned int cpuid) ++{ ++ struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; ++ unsigned int mpidr; ++ unsigned int cpu; ++ ++ /* If the cpu topology has been already set, just return */ ++ if (cpuid_topo->core_id != -1) ++ return; ++ ++ mpidr = read_cpuid_mpidr(); ++ ++ /* create cpu topology mapping */ ++ if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) { ++ /* ++ * This is a multiprocessor system ++ * multiprocessor format & multiprocessor mode field are set ++ */ ++ ++ if (mpidr & MPIDR_MT_BITMASK) { ++ /* core performance interdependency */ ++ cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT) ++ & MPIDR_LEVEL0_MASK; ++ cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT) ++ & MPIDR_LEVEL1_MASK; ++ cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT) ++ & MPIDR_LEVEL2_MASK; ++ } else { ++ /* largely independent cores */ ++ cpuid_topo->thread_id = -1; ++ cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT) ++ & MPIDR_LEVEL0_MASK; ++ cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT) ++ & MPIDR_LEVEL1_MASK; ++ } ++ } else { ++ /* ++ * This is an uniprocessor system ++ * we are in multiprocessor format but uniprocessor system ++ * or in the old uniprocessor format ++ */ ++ cpuid_topo->thread_id = -1; ++ cpuid_topo->core_id = 0; ++ cpuid_topo->socket_id = -1; ++ } ++ ++ /* update core and thread sibling masks */ ++ for_each_possible_cpu(cpu) { ++ struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; ++ ++ if (cpuid_topo->socket_id == cpu_topo->socket_id) { ++ cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); ++ if (cpu != cpuid) ++ cpumask_set_cpu(cpu, ++ &cpuid_topo->core_sibling); ++ ++ if (cpuid_topo->core_id == cpu_topo->core_id) { ++ cpumask_set_cpu(cpuid, ++ &cpu_topo->thread_sibling); ++ if (cpu != cpuid) ++ cpumask_set_cpu(cpu, ++ &cpuid_topo->thread_sibling); ++ } ++ } ++ } ++ smp_wmb(); ++ ++ printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", ++ cpuid, cpu_topology[cpuid].thread_id, ++ cpu_topology[cpuid].core_id, ++ cpu_topology[cpuid].socket_id, mpidr); ++} ++ ++/* ++ * init_cpu_topology is called at boot when only one cpu is running ++ * which prevent simultaneous write access to cpu_topology array ++ */ ++void init_cpu_topology(void) ++{ ++ unsigned int cpu; ++ ++ /* init core mask */ ++ for_each_possible_cpu(cpu) { ++ struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); ++ ++ cpu_topo->thread_id = -1; ++ cpu_topo->core_id = -1; ++ cpu_topo->socket_id = -1; ++ cpumask_clear(&cpu_topo->core_sibling); ++ cpumask_clear(&cpu_topo->thread_sibling); ++ } ++ smp_wmb(); ++} +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0154-ARM-7060-1-smp-populate-logical-CPU-mapping-during-b.patch b/patches.kzm9g/0154-ARM-7060-1-smp-populate-logical-CPU-mapping-during-b.patch new file mode 100644 index 00000000000000..8fca38f510a270 --- /dev/null +++ b/patches.kzm9g/0154-ARM-7060-1-smp-populate-logical-CPU-mapping-during-b.patch @@ -0,0 +1,74 @@ +From febe036de3201edeaadd1290d3cee9544b1b05f3 Mon Sep 17 00:00:00 2001 +From: Will Deacon <will.deacon@arm.com> +Date: Tue, 23 Aug 2011 22:19:29 +0100 +Subject: ARM: 7060/1: smp: populate logical CPU mapping during boot + +To allow booting Linux on a CPU with physical ID != 0, we need to +provide a mapping from the logical CPU number to the physical CPU +number. + +This patch adds such a mapping and populates it during boot. + +Signed-off-by: Will Deacon <will.deacon@arm.com> +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit d6257288c4052465feeff7e283e35ec0ed06ca03) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/include/asm/smp.h | 6 ++++++ + arch/arm/kernel/smp.c | 15 +++++++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h +index e42d96a..674ebcd 100644 +--- a/arch/arm/include/asm/smp.h ++++ b/arch/arm/include/asm/smp.h +@@ -66,6 +66,12 @@ extern void platform_secondary_init(unsigned int cpu); + extern void platform_smp_prepare_cpus(unsigned int); + + /* ++ * Logical CPU mapping. ++ */ ++extern int __cpu_logical_map[NR_CPUS]; ++#define cpu_logical_map(cpu) __cpu_logical_map[cpu] ++ ++/* + * Initial data for bringing up a secondary CPU. + */ + struct secondary_data { +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index 8e3a000..4db266c 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -40,6 +40,7 @@ + #include <asm/tlbflush.h> + #include <asm/ptrace.h> + #include <asm/localtimer.h> ++#include <asm/smp_plat.h> + + /* + * as from 2.5, kernels no longer have an init_tasks structure +@@ -260,6 +261,20 @@ void __ref cpu_die(void) + } + #endif /* CONFIG_HOTPLUG_CPU */ + ++int __cpu_logical_map[NR_CPUS]; ++ ++void __init smp_setup_processor_id(void) ++{ ++ int i; ++ u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0; ++ ++ cpu_logical_map(0) = cpu; ++ for (i = 1; i < NR_CPUS; ++i) ++ cpu_logical_map(i) = i == cpu ? 0 : i; ++ ++ printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu); ++} ++ + /* + * Called by both boot and secondaries to move global data into + * per-processor storage. +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0155-ARM-gic-Allow-gic-arch-extensions-to-provide-irqchip.patch b/patches.kzm9g/0155-ARM-gic-Allow-gic-arch-extensions-to-provide-irqchip.patch new file mode 100644 index 00000000000000..d913adce00a8eb --- /dev/null +++ b/patches.kzm9g/0155-ARM-gic-Allow-gic-arch-extensions-to-provide-irqchip.patch @@ -0,0 +1,35 @@ +From 601c8c40dd8e17083b060418bb630c87e168be86 Mon Sep 17 00:00:00 2001 +From: Colin Cross <ccross@android.com> +Date: Mon, 13 Jun 2011 00:45:59 +0000 +Subject: ARM: gic: Allow gic arch extensions to provide irqchip flags + +Tegra can benefit from the IRQCHIP_MASK_ON_SUSPEND flag, allow it +to be passed to the gic irq chip. + +Signed-off-by: Colin Cross <ccross@android.com> +Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> +Reviewed-by: Kevin Hilman <khilman@ti.com> +Tested-and-Acked-by: Shawn Guo <shawn.guo@linaro.org> +Tested-by: Vishwanath BS <vishwanath.bs@ti.com> +(cherry picked from commit 9c12845ee49716209cb2b087c0b47c3e37096bde) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 66c7c48..734db99 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -544,6 +544,7 @@ void __init gic_init(unsigned int gic_nr, unsigned int irq_start, + if (gic_nr == 0) + gic_cpu_base_addr = cpu_base; + ++ gic_chip.flags |= gic_arch_extn.flags; + gic_dist_init(gic, irq_start); + gic_cpu_init(gic); + gic_pm_init(gic); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0156-ARM-7061-1-gic-convert-logical-CPU-numbers-into-phys.patch b/patches.kzm9g/0156-ARM-7061-1-gic-convert-logical-CPU-numbers-into-phys.patch new file mode 100644 index 00000000000000..35ff5eafc18b63 --- /dev/null +++ b/patches.kzm9g/0156-ARM-7061-1-gic-convert-logical-CPU-numbers-into-phys.patch @@ -0,0 +1,67 @@ +From 0ff6ee62ebe17adfa97c1847cc1d7aea76b49d55 Mon Sep 17 00:00:00 2001 +From: Will Deacon <will.deacon@arm.com> +Date: Tue, 23 Aug 2011 22:20:03 +0100 +Subject: ARM: 7061/1: gic: convert logical CPU numbers into physical numbers + +The GIC driver must convert logical CPU numbers passed in from Linux +into physical CPU numbers that are understood by the hardware. + +This patch uses the new cpu_logical_map macro for performing the +conversion inside the GIC driver. + +Signed-off-by: Will Deacon <will.deacon@arm.com> +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit 267840f3397fd9f6a2bdde14de38b9d29d525d7b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 734db99..8b5be72 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -181,7 +181,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, + return -EINVAL; + + mask = 0xff << shift; +- bit = 1 << (cpu + shift); ++ bit = 1 << (cpu_logical_map(cpu) + shift); + + spin_lock(&irq_controller_lock); + val = readl_relaxed(reg) & ~mask; +@@ -260,9 +260,15 @@ static void __init gic_dist_init(struct gic_chip_data *gic, + unsigned int irq_start) + { + unsigned int gic_irqs, irq_limit, i; ++ u32 cpumask; + void __iomem *base = gic->dist_base; +- u32 cpumask = 1 << smp_processor_id(); ++ u32 cpu = 0; + ++#ifdef CONFIG_SMP ++ cpu = cpu_logical_map(smp_processor_id()); ++#endif ++ ++ cpumask = 1 << cpu; + cpumask |= cpumask << 8; + cpumask |= cpumask << 16; + +@@ -570,7 +576,12 @@ void __cpuinit gic_enable_ppi(unsigned int irq) + #ifdef CONFIG_SMP + void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) + { +- unsigned long map = *cpus_addr(*mask); ++ int cpu; ++ unsigned long map = 0; ++ ++ /* Convert our logical CPU mask into a physical one. */ ++ for_each_cpu(cpu, mask) ++ map |= 1 << cpu_logical_map(cpu); + + /* + * Ensure that stores to Normal memory are visible to the +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0157-ARM-7123-1-smp-Add-an-IPI-handler-callable-from-C-co.patch b/patches.kzm9g/0157-ARM-7123-1-smp-Add-an-IPI-handler-callable-from-C-co.patch new file mode 100644 index 00000000000000..6f64a72920a5a6 --- /dev/null +++ b/patches.kzm9g/0157-ARM-7123-1-smp-Add-an-IPI-handler-callable-from-C-co.patch @@ -0,0 +1,53 @@ +From 32e451b349e7eb7f702b46dd50e57585b0471889 Mon Sep 17 00:00:00 2001 +From: Shawn Guo <shawn.guo@linaro.org> +Date: Thu, 6 Oct 2011 15:18:14 +0100 +Subject: ARM: 7123/1: smp: Add an IPI handler callable from C code + +In order to be able to handle IPI directly from C code instead of +assembly code, introduce handle_IPI(), which is modeled after handle_IRQ(). + +Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit 0b5a1b95dcdfa451125132d5ce3f79a27ffb0950) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/include/asm/smp.h | 5 +++++ + arch/arm/kernel/smp.c | 5 +++++ + 2 files changed, 10 insertions(+) + +diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h +index 674ebcd..0a17b62 100644 +--- a/arch/arm/include/asm/smp.h ++++ b/arch/arm/include/asm/smp.h +@@ -33,6 +33,11 @@ extern void show_ipi_list(struct seq_file *, int); + asmlinkage void do_IPI(int ipinr, struct pt_regs *regs); + + /* ++ * Called from C code, this handles an IPI. ++ */ ++void handle_IPI(int ipinr, struct pt_regs *regs); ++ ++/* + * Setup the set of possible CPUs (via set_cpu_possible) + */ + extern void smp_init_cpus(void); +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index 4db266c..74ac4bb 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -580,6 +580,11 @@ static void ipi_cpu_stop(unsigned int cpu) + */ + asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) + { ++ handle_IPI(ipinr, regs); ++} ++ ++void handle_IPI(int ipinr, struct pt_regs *regs) ++{ + unsigned int cpu = smp_processor_id(); + struct pt_regs *old_regs = set_irq_regs(regs); + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0158-ARM-7124-1-smp-Add-a-localtimer-handler-callable-fro.patch b/patches.kzm9g/0158-ARM-7124-1-smp-Add-a-localtimer-handler-callable-fro.patch new file mode 100644 index 00000000000000..d260cb8b62f735 --- /dev/null +++ b/patches.kzm9g/0158-ARM-7124-1-smp-Add-a-localtimer-handler-callable-fro.patch @@ -0,0 +1,53 @@ +From 3a88e40dec05b0d5d376ba18a7f6833b3f6d7be5 Mon Sep 17 00:00:00 2001 +From: Shawn Guo <shawn.guo@linaro.org> +Date: Thu, 6 Oct 2011 15:19:14 +0100 +Subject: ARM: 7124/1: smp: Add a localtimer handler callable from C code + +In order to be able to handle localtimer directly from C code instead of +assembly code, introduce handle_local_timer(), which is modeled after +handle_IRQ(). + +Signed-off-by: Shawn Guo <shawn.guo@linaro.org> +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit 0af8aa0069e43f90d59666510342c05e97d8c4b8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/include/asm/localtimer.h | 4 ++++ + arch/arm/kernel/smp.c | 5 +++++ + 2 files changed, 9 insertions(+) + +diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h +index 080d74f..3306f28 100644 +--- a/arch/arm/include/asm/localtimer.h ++++ b/arch/arm/include/asm/localtimer.h +@@ -22,6 +22,10 @@ void percpu_timer_setup(void); + */ + asmlinkage void do_local_timer(struct pt_regs *); + ++/* ++ * Called from C code ++ */ ++void handle_local_timer(struct pt_regs *); + + #ifdef CONFIG_LOCAL_TIMERS + +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index 74ac4bb..53aaa59 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -473,6 +473,11 @@ static void ipi_timer(void) + #ifdef CONFIG_LOCAL_TIMERS + asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) + { ++ handle_local_timer(regs); ++} ++ ++void handle_local_timer(struct pt_regs *regs) ++{ + struct pt_regs *old_regs = set_irq_regs(regs); + int cpu = smp_processor_id(); + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0159-ARM-gic-consolidate-PPI-handling.patch b/patches.kzm9g/0159-ARM-gic-consolidate-PPI-handling.patch new file mode 100644 index 00000000000000..28b7f97e736e35 --- /dev/null +++ b/patches.kzm9g/0159-ARM-gic-consolidate-PPI-handling.patch @@ -0,0 +1,561 @@ +From c05f2488f4b9c5a88e74afd7b22a986c4378fb2b Mon Sep 17 00:00:00 2001 +From: Marc Zyngier <marc.zyngier@arm.com> +Date: Wed, 20 Jul 2011 16:24:14 +0100 +Subject: ARM: gic: consolidate PPI handling + +PPI handling is a bit of an odd beast. It uses its own low level +handling code and is hardwired to the local timers (hence lacking +a registration interface). + +Instead, switch the low handling to the normal SPI handling code. +PPIs are handled by the handle_percpu_devid_irq flow. + +This also allows the removal of some duplicated code. + +Cc: Kukjin Kim <kgene.kim@samsung.com> +Cc: David Brown <davidb@codeaurora.org> +Cc: Bryan Huntsman <bryanh@codeaurora.org> +Cc: Tony Lindgren <tony@atomide.com> +Cc: Paul Mundt <lethal@linux-sh.org> +Cc: Magnus Damm <magnus.damm@gmail.com> +Cc: Thomas Gleixner <tglx@linutronix.de> +Acked-by: David Brown <davidb@codeaurora.org> +Tested-by: David Brown <davidb@codeaurora.org> +Tested-by: Shawn Guo <shawn.guo@linaro.org> +Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> +(cherry picked from commit 292b293ceef2eda1f96f0c90b96e954d7bdabd1c) + +Conflicts: + + arch/arm/mach-exynos4/include/mach/entry-macro.S + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 75 ++++++++++++++++++++++- + arch/arm/include/asm/entry-macro-multi.S | 7 --- + arch/arm/include/asm/hardirq.h | 3 - + arch/arm/include/asm/hardware/entry-macro-gic.S | 19 +----- + arch/arm/include/asm/localtimer.h | 11 ++-- + arch/arm/include/asm/smp.h | 5 -- + arch/arm/kernel/irq.c | 3 - + arch/arm/kernel/smp.c | 32 ++-------- + arch/arm/mach-exynos4/include/mach/entry-macro.S | 13 +--- + arch/arm/mach-msm/board-msm8x60.c | 11 ---- + arch/arm/mach-msm/include/mach/entry-macro-qgic.S | 73 +--------------------- + arch/arm/mach-omap2/include/mach/entry-macro.S | 14 +---- + arch/arm/mach-shmobile/entry-intc.S | 3 - + arch/arm/mach-shmobile/include/mach/entry-macro.S | 3 - + 14 files changed, 88 insertions(+), 184 deletions(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 8b5be72..95ad8d1 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -29,10 +29,14 @@ + #include <linux/cpu_pm.h> + #include <linux/cpumask.h> + #include <linux/io.h> ++#include <linux/interrupt.h> ++#include <linux/percpu.h> ++#include <linux/slab.h> + + #include <asm/irq.h> + #include <asm/mach/irq.h> + #include <asm/hardware/gic.h> ++#include <asm/localtimer.h> + + static DEFINE_SPINLOCK(irq_controller_lock); + +@@ -256,6 +260,32 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) + irq_set_chained_handler(irq, gic_handle_cascade_irq); + } + ++#ifdef CONFIG_LOCAL_TIMERS ++#define gic_ppi_handler percpu_timer_handler ++#else ++static irqreturn_t gic_ppi_handler(int irq, void *dev_id) ++{ ++ return IRQ_NONE; ++} ++#endif ++ ++#define PPI_IRQACT(nr) \ ++ { \ ++ .handler = gic_ppi_handler, \ ++ .flags = IRQF_PERCPU | IRQF_TIMER, \ ++ .irq = nr, \ ++ .name = "PPI-" # nr, \ ++ } ++ ++static struct irqaction ppi_irqaction_template[16] __initdata = { ++ PPI_IRQACT(0), PPI_IRQACT(1), PPI_IRQACT(2), PPI_IRQACT(3), ++ PPI_IRQACT(4), PPI_IRQACT(5), PPI_IRQACT(6), PPI_IRQACT(7), ++ PPI_IRQACT(8), PPI_IRQACT(9), PPI_IRQACT(10), PPI_IRQACT(11), ++ PPI_IRQACT(12), PPI_IRQACT(13), PPI_IRQACT(14), PPI_IRQACT(15), ++}; ++ ++static struct irqaction *ppi_irqaction; ++ + static void __init gic_dist_init(struct gic_chip_data *gic, + unsigned int irq_start) + { +@@ -263,6 +293,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic, + u32 cpumask; + void __iomem *base = gic->dist_base; + u32 cpu = 0; ++ u32 nrppis = 0, ppi_base = 0; + + #ifdef CONFIG_SMP + cpu = cpu_logical_map(smp_processor_id()); +@@ -286,6 +317,33 @@ static void __init gic_dist_init(struct gic_chip_data *gic, + gic->gic_irqs = gic_irqs; + + /* ++ * Nobody would be insane enough to use PPIs on a secondary ++ * GIC, right? ++ */ ++ if (gic == &gic_data[0]) { ++ nrppis = (32 - irq_start) & 31; ++ ++ /* The GIC only supports up to 16 PPIs. */ ++ if (nrppis > 16) ++ BUG(); ++ ++ ppi_base = gic->irq_offset + 32 - nrppis; ++ ++ ppi_irqaction = kmemdup(&ppi_irqaction_template[16 - nrppis], ++ sizeof(*ppi_irqaction) * nrppis, ++ GFP_KERNEL); ++ ++ if (nrppis && !ppi_irqaction) { ++ pr_err("GIC: Can't allocate PPI memory"); ++ nrppis = 0; ++ ppi_base = 0; ++ } ++ } ++ ++ pr_info("Configuring GIC with %d sources (%d PPIs)\n", ++ gic_irqs, (gic == &gic_data[0]) ? nrppis : 0); ++ ++ /* + * Set all global interrupts to be level triggered, active low. + */ + for (i = 32; i < gic_irqs; i += 16) +@@ -320,7 +378,22 @@ static void __init gic_dist_init(struct gic_chip_data *gic, + /* + * Setup the Linux IRQ subsystem. + */ +- for (i = irq_start; i < irq_limit; i++) { ++ for (i = 0; i < nrppis; i++) { ++ int ppi = i + ppi_base; ++ int err; ++ ++ irq_set_percpu_devid(ppi); ++ irq_set_chip_and_handler(ppi, &gic_chip, ++ handle_percpu_devid_irq); ++ irq_set_chip_data(ppi, gic); ++ set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN); ++ ++ err = setup_percpu_irq(ppi, &ppi_irqaction[i]); ++ if (err) ++ pr_err("GIC: can't setup PPI%d (%d)\n", ppi, err); ++ } ++ ++ for (i = irq_start + nrppis; i < irq_limit; i++) { + irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq); + irq_set_chip_data(i, gic); + set_irq_flags(i, IRQF_VALID | IRQF_PROBE); +diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S +index 2f1e209..88d6181 100644 +--- a/arch/arm/include/asm/entry-macro-multi.S ++++ b/arch/arm/include/asm/entry-macro-multi.S +@@ -25,13 +25,6 @@ + movne r1, sp + adrne lr, BSYM(1b) + bne do_IPI +- +-#ifdef CONFIG_LOCAL_TIMERS +- test_for_ltirq r0, r2, r6, lr +- movne r0, sp +- adrne lr, BSYM(1b) +- bne do_local_timer +-#endif + #endif + 9997: + .endm +diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h +index 89ad180..ddf07a9 100644 +--- a/arch/arm/include/asm/hardirq.h ++++ b/arch/arm/include/asm/hardirq.h +@@ -9,9 +9,6 @@ + + typedef struct { + unsigned int __softirq_pending; +-#ifdef CONFIG_LOCAL_TIMERS +- unsigned int local_timer_irqs; +-#endif + #ifdef CONFIG_SMP + unsigned int ipi_irqs[NR_IPI]; + #endif +diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S +index c115b82..74ebc80 100644 +--- a/arch/arm/include/asm/hardware/entry-macro-gic.S ++++ b/arch/arm/include/asm/hardware/entry-macro-gic.S +@@ -22,15 +22,11 @@ + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI +- * 16-28 are reserved +- * 29-31 are local. We allow 30 to be used for the watchdog. ++ * 16-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * +- * For now, we ignore all local interrupts so only return an interrupt if it's +- * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. +- * + * A simple read from the controller will tell us the number of the highest + * priority enabled interrupt. We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). +@@ -43,7 +39,7 @@ + + ldr \tmp, =1021 + bic \irqnr, \irqstat, #0x1c00 +- cmp \irqnr, #29 ++ cmp \irqnr, #15 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr +@@ -62,14 +58,3 @@ + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm +- +-/* As above, this assumes that irqstat and base are preserved.. */ +- +- .macro test_for_ltirq, irqnr, irqstat, base, tmp +- bic \irqnr, \irqstat, #0x1c00 +- mov \tmp, #0 +- cmp \irqnr, #29 +- moveq \tmp, #1 +- streq \irqstat, [\base, #GIC_CPU_EOI] +- cmp \tmp, #0 +- .endm +diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h +index 3306f28..5c8acb4 100644 +--- a/arch/arm/include/asm/localtimer.h ++++ b/arch/arm/include/asm/localtimer.h +@@ -10,6 +10,8 @@ + #ifndef __ASM_ARM_LOCALTIMER_H + #define __ASM_ARM_LOCALTIMER_H + ++#include <linux/interrupt.h> ++ + struct clock_event_device; + + /* +@@ -18,14 +20,9 @@ struct clock_event_device; + void percpu_timer_setup(void); + + /* +- * Called from assembly, this is the local timer IRQ handler +- */ +-asmlinkage void do_local_timer(struct pt_regs *); +- +-/* +- * Called from C code ++ * Per-cpu timer IRQ handler + */ +-void handle_local_timer(struct pt_regs *); ++irqreturn_t percpu_timer_handler(int irq, void *dev_id); + + #ifdef CONFIG_LOCAL_TIMERS + +diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h +index 0a17b62..1e5717a 100644 +--- a/arch/arm/include/asm/smp.h ++++ b/arch/arm/include/asm/smp.h +@@ -99,9 +99,4 @@ extern void platform_cpu_enable(unsigned int cpu); + extern void arch_send_call_function_single_ipi(int cpu); + extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); + +-/* +- * show local interrupt info +- */ +-extern void show_local_irqs(struct seq_file *, int); +- + #endif /* ifndef __ASM_ARM_SMP_H */ +diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c +index 3e34b1f..0ad5e98 100644 +--- a/arch/arm/kernel/irq.c ++++ b/arch/arm/kernel/irq.c +@@ -59,9 +59,6 @@ int arch_show_interrupts(struct seq_file *p, int prec) + #ifdef CONFIG_SMP + show_ipi_list(p, prec); + #endif +-#ifdef CONFIG_LOCAL_TIMERS +- show_local_irqs(p, prec); +-#endif + seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); + return 0; + } +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index 53aaa59..7db7120 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -450,10 +450,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu) + for (i = 0; i < NR_IPI; i++) + sum += __get_irq_stat(cpu, ipi_irqs[i]); + +-#ifdef CONFIG_LOCAL_TIMERS +- sum += __get_irq_stat(cpu, local_timer_irqs); +-#endif +- + return sum; + } + +@@ -471,34 +467,16 @@ static void ipi_timer(void) + } + + #ifdef CONFIG_LOCAL_TIMERS +-asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) +-{ +- handle_local_timer(regs); +-} +- +-void handle_local_timer(struct pt_regs *regs) ++irqreturn_t percpu_timer_handler(int irq, void *dev_id) + { +- struct pt_regs *old_regs = set_irq_regs(regs); +- int cpu = smp_processor_id(); ++ struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent); + + if (local_timer_ack()) { +- __inc_irq_stat(cpu, local_timer_irqs); +- ipi_timer(); ++ evt->event_handler(evt); ++ return IRQ_HANDLED; + } + +- set_irq_regs(old_regs); +-} +- +-void show_local_irqs(struct seq_file *p, int prec) +-{ +- unsigned int cpu; +- +- seq_printf(p, "%*s: ", prec, "LOC"); +- +- for_each_present_cpu(cpu) +- seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs)); +- +- seq_printf(p, " Local timer interrupts\n"); ++ return IRQ_NONE; + } + #endif + +diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S +index d8f38c2..9be072f 100644 +--- a/arch/arm/mach-exynos4/include/mach/entry-macro.S ++++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S +@@ -50,7 +50,7 @@ + + bic \irqnr, \irqstat, #0x1c00 + +- cmp \irqnr, #29 ++ cmp \irqnr, #15 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr +@@ -71,14 +71,3 @@ + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm +- +- /* As above, this assumes that irqstat and base are preserved.. */ +- +- .macro test_for_ltirq, irqnr, irqstat, base, tmp +- bic \irqnr, \irqstat, #0x1c00 +- mov \tmp, #0 +- cmp \irqnr, #29 +- moveq \tmp, #1 +- streq \irqstat, [\base, #GIC_CPU_EOI] +- cmp \tmp, #0 +- .endm +diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c +index 1163b6f..d70a2f6 100644 +--- a/arch/arm/mach-msm/board-msm8x60.c ++++ b/arch/arm/mach-msm/board-msm8x60.c +@@ -36,8 +36,6 @@ static void __init msm8x60_map_io(void) + + static void __init msm8x60_init_irq(void) + { +- unsigned int i; +- + gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, + (void *)MSM_QGIC_CPU_BASE); + +@@ -49,15 +47,6 @@ static void __init msm8x60_init_irq(void) + */ + if (!machine_is_msm8x60_sim()) + writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET); +- +- /* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet +- * as they are configured as level, which does not play nice with +- * handle_percpu_irq. +- */ +- for (i = GIC_PPI_START; i < GIC_SPI_START; i++) { +- if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE) +- irq_set_handler(i, handle_percpu_irq); +- } + } + + static void __init msm8x60_init(void) +diff --git a/arch/arm/mach-msm/include/mach/entry-macro-qgic.S b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S +index 1246715..717076f 100644 +--- a/arch/arm/mach-msm/include/mach/entry-macro-qgic.S ++++ b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S +@@ -8,81 +8,10 @@ + * warranty of any kind, whether express or implied. + */ + +-#include <mach/hardware.h> +-#include <asm/hardware/gic.h> ++#include <asm/hardware/entry-macro-gic.S> + + .macro disable_fiq + .endm + +- .macro get_irqnr_preamble, base, tmp +- ldr \base, =gic_cpu_base_addr +- ldr \base, [\base] +- .endm +- + .macro arch_ret_to_user, tmp1, tmp2 + .endm +- +- /* +- * The interrupt numbering scheme is defined in the +- * interrupt controller spec. To wit: +- * +- * Migrated the code from ARM MP port to be more consistent +- * with interrupt processing , the following still holds true +- * however, all interrupts are treated the same regardless of +- * if they are local IPI or PPI +- * +- * Interrupts 0-15 are IPI +- * 16-31 are PPI +- * (16-18 are the timers) +- * 32-1020 are global +- * 1021-1022 are reserved +- * 1023 is "spurious" (no interrupt) +- * +- * A simple read from the controller will tell us the number of the +- * highest priority enabled interrupt. We then just need to check +- * whether it is in the valid range for an IRQ (0-1020 inclusive). +- * +- * Base ARM code assumes that the local (private) peripheral interrupts +- * are not valid, we treat them differently, in that the privates are +- * handled like normal shared interrupts with the exception that only +- * one processor can register the interrupt and the handler must be +- * the same for all processors. +- */ +- +- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp +- +- ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU, +- 9-0 =int # */ +- +- bic \irqnr, \irqstat, #0x1c00 @mask src +- cmp \irqnr, #15 +- ldr \tmp, =1021 +- cmpcc \irqnr, \irqnr +- cmpne \irqnr, \tmp +- cmpcs \irqnr, \irqnr +- +- .endm +- +- /* We assume that irqstat (the raw value of the IRQ acknowledge +- * register) is preserved from the macro above. +- * If there is an IPI, we immediately signal end of interrupt on the +- * controller, since this requires the original irqstat value which +- * we won't easily be able to recreate later. +- */ +- .macro test_for_ipi, irqnr, irqstat, base, tmp +- bic \irqnr, \irqstat, #0x1c00 +- cmp \irqnr, #16 +- strcc \irqstat, [\base, #GIC_CPU_EOI] +- cmpcs \irqnr, \irqnr +- .endm +- +- /* As above, this assumes that irqstat and base are preserved.. */ +- +- .macro test_for_ltirq, irqnr, irqstat, base, tmp +- bic \irqnr, \irqstat, #0x1c00 +- mov \tmp, #0 +- cmp \irqnr, #16 +- moveq \tmp, #1 +- streq \irqstat, [\base, #GIC_CPU_EOI] +- cmp \tmp, #0 +- .endm +diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S +index a48690b..22d86ef 100644 +--- a/arch/arm/mach-omap2/include/mach/entry-macro.S ++++ b/arch/arm/mach-omap2/include/mach/entry-macro.S +@@ -78,7 +78,7 @@ + 4401: ldr \irqstat, [\base, #GIC_CPU_INTACK] + ldr \tmp, =1021 + bic \irqnr, \irqstat, #0x1c00 +- cmp \irqnr, #29 ++ cmp \irqnr, #15 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr +@@ -101,18 +101,6 @@ + it cs + cmpcs \irqnr, \irqnr + .endm +- +- /* As above, this assumes that irqstat and base are preserved */ +- +- .macro test_for_ltirq, irqnr, irqstat, base, tmp +- bic \irqnr, \irqstat, #0x1c00 +- mov \tmp, #0 +- cmp \irqnr, #29 +- itt eq +- moveq \tmp, #1 +- streq \irqstat, [\base, #GIC_CPU_EOI] +- cmp \tmp, #0 +- .endm + #endif /* CONFIG_SMP */ + + #else /* MULTI_OMAP2 */ +diff --git a/arch/arm/mach-shmobile/entry-intc.S b/arch/arm/mach-shmobile/entry-intc.S +index cac0a7a..1a1c00c 100644 +--- a/arch/arm/mach-shmobile/entry-intc.S ++++ b/arch/arm/mach-shmobile/entry-intc.S +@@ -51,7 +51,4 @@ + .macro test_for_ipi, irqnr, irqstat, base, tmp + .endm + +- .macro test_for_ltirq, irqnr, irqstat, base, tmp +- .endm +- + arch_irq_handler shmobile_handle_irq_intc +diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S +index d791f10..8d4a416 100644 +--- a/arch/arm/mach-shmobile/include/mach/entry-macro.S ++++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S +@@ -27,8 +27,5 @@ + .macro test_for_ipi, irqnr, irqstat, base, tmp + .endm + +- .macro test_for_ltirq, irqnr, irqstat, base, tmp +- .endm +- + .macro arch_ret_to_user, tmp1, tmp2 + .endm +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0160-ARM-GIC-Add-global-gic_handle_irq-function.patch b/patches.kzm9g/0160-ARM-GIC-Add-global-gic_handle_irq-function.patch new file mode 100644 index 00000000000000..3b5ba5af83e05a --- /dev/null +++ b/patches.kzm9g/0160-ARM-GIC-Add-global-gic_handle_irq-function.patch @@ -0,0 +1,81 @@ +From a0ef51f4b57f8a01b252ac767519d2a4002d2a4c Mon Sep 17 00:00:00 2001 +From: Marc Zyngier <marc.zyngier@arm.com> +Date: Tue, 6 Sep 2011 09:56:17 +0100 +Subject: ARM: GIC: Add global gic_handle_irq() function + +Provide the GIC code with a low level handler that can be used +by platforms using CONFIG_MULTI_IRQ_HANDLER. + +Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> +(cherry picked from commit 562e0027d21bf64838178e2f5157df3d5833972e) + +Conflicts: + + arch/arm/common/gic.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 27 ++++++++++++++++++++++++++- + arch/arm/include/asm/hardware/gic.h | 1 + + 2 files changed, 27 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 95ad8d1..7a73799 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -26,7 +26,6 @@ + #include <linux/kernel.h> + #include <linux/list.h> + #include <linux/smp.h> +-#include <linux/cpu_pm.h> + #include <linux/cpumask.h> + #include <linux/io.h> + #include <linux/interrupt.h> +@@ -211,6 +210,32 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) + #define gic_set_wake NULL + #endif + ++asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) ++{ ++ u32 irqstat, irqnr; ++ struct gic_chip_data *gic = &gic_data[0]; ++ void __iomem *cpu_base = gic->cpu_base; ++ ++ do { ++ irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); ++ irqnr = irqstat & ~0x1c00; ++ ++ if (likely(irqnr > 15 && irqnr < 1021)) { ++ //irqnr = irqnr + gic->irq_offset; ++ handle_IRQ(irqnr, regs); ++ continue; ++ } ++ if (irqnr < 16) { ++ writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); ++#ifdef CONFIG_SMP ++ handle_IPI(irqnr, regs); ++#endif ++ continue; ++ } ++ break; ++ } while (1); ++} ++ + static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) + { + struct gic_chip_data *chip_data = irq_get_handler_data(irq); +diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h +index c562705..615c336 100644 +--- a/arch/arm/include/asm/hardware/gic.h ++++ b/arch/arm/include/asm/hardware/gic.h +@@ -38,6 +38,7 @@ extern struct irq_chip gic_arch_extn; + + void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *); + void gic_secondary_init(unsigned int); ++void gic_handle_irq(struct pt_regs *regs); + void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); + void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); + void gic_enable_ppi(unsigned int); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0161-ARM-twd-register-clockevents-device-before-enabling-.patch b/patches.kzm9g/0161-ARM-twd-register-clockevents-device-before-enabling-.patch new file mode 100644 index 00000000000000..d48fa9face4e46 --- /dev/null +++ b/patches.kzm9g/0161-ARM-twd-register-clockevents-device-before-enabling-.patch @@ -0,0 +1,41 @@ +From 1322ac36bc746ca63e1968e96b8945ee1ab85fff Mon Sep 17 00:00:00 2001 +From: Will Deacon <will.deacon@arm.com> +Date: Wed, 20 Jul 2011 14:18:46 +0100 +Subject: ARM: twd: register clockevents device before enabling PPI + +The smp_twd clockevents driver currently enables the local timer PPI +before the clockevents device is registered. This can lead to a kernel +panic if a spurious timer interrupt is generated before registration +has completed since the kernel will treat it as an IPI timer. + +This patch moves the clockevents device registration before the IRQ +unmasking so that we can always handle timer interrupts once they can +occur. + +Acked-by: Marc Zyngier <marc.zyngier@arm.com> +Signed-off-by: Will Deacon <will.deacon@arm.com> +(cherry picked from commit dfc40b24c0a37593724f3317cd485c73ee878c18) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/kernel/smp_twd.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c +index 2c277d4..01c1862 100644 +--- a/arch/arm/kernel/smp_twd.c ++++ b/arch/arm/kernel/smp_twd.c +@@ -137,8 +137,8 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) + clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); + clk->min_delta_ns = clockevent_delta2ns(0xf, clk); + ++ clockevents_register_device(clk); ++ + /* Make sure our local interrupt controller has this enabled */ + gic_enable_ppi(clk->irq); +- +- clockevents_register_device(clk); + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0162-ARM-EXYNOS4-set-the-affinity-of-mct1-interrupt-using.patch b/patches.kzm9g/0162-ARM-EXYNOS4-set-the-affinity-of-mct1-interrupt-using.patch new file mode 100644 index 00000000000000..248a87aa58227b --- /dev/null +++ b/patches.kzm9g/0162-ARM-EXYNOS4-set-the-affinity-of-mct1-interrupt-using.patch @@ -0,0 +1,36 @@ +From bf7b78d246e27b2b276b600fb145f8ccef7246e7 Mon Sep 17 00:00:00 2001 +From: Changhwan Youn <chaos.youn@samsung.com> +Date: Sat, 16 Jul 2011 10:49:44 +0900 +Subject: ARM: EXYNOS4: set the affinity of mct1 interrupt using IRQ_MCT_L1 + +IRQ_MCT_L1 is connected directly to GIC in external GIC mapping, +while in internal GIC mapping, it is connected to GIC through +interrupt combiner. Therfore the affinity for mct1 event timer +interrupt should be changed through IRQ_MCT_L1. + +Signed-off-by: Changhwan Youn <chaos.youn@samsung.com> +Signed-off-by: Kukjin Kim <kgene.kim@samsung.com> +(cherry picked from commit a8769a594a6d061f8018048a7cd1546924c61a5c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-exynos4/mct.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c +index 14ac10b..1ae059b 100644 +--- a/arch/arm/mach-exynos4/mct.c ++++ b/arch/arm/mach-exynos4/mct.c +@@ -383,8 +383,8 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt) + setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq); + } else { + mct_tick1_event_irq.dev_id = &mct_tick[cpu]; +- irq_set_affinity(IRQ_MCT1, cpumask_of(1)); + setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq); ++ irq_set_affinity(IRQ_MCT_L1, cpumask_of(1)); + } + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0163-genirq-percpu-allow-interrupt-type-to-be-set-at-enab.patch b/patches.kzm9g/0163-genirq-percpu-allow-interrupt-type-to-be-set-at-enab.patch new file mode 100644 index 00000000000000..d60c9da5ca867a --- /dev/null +++ b/patches.kzm9g/0163-genirq-percpu-allow-interrupt-type-to-be-set-at-enab.patch @@ -0,0 +1,75 @@ +From 34377e3bf1795c5e592b3135913ae0f7147bbb85 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier <marc.zyngier@arm.com> +Date: Fri, 30 Sep 2011 10:48:47 +0100 +Subject: genirq: percpu: allow interrupt type to be set at enable time + +As request_percpu_irq() doesn't allow for a percpu interrupt to have +its type configured (it is generally impossible to configure it on all +CPUs at once), add a 'type' argument to enable_percpu_irq(). + +This allows some low-level, board specific init code to be switched to +a generic API. + +[ tglx: Added WARN_ON argument ] + +Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> +Cc: Abhijeet Dharmapurikar <adharmap@codeaurora.org> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +(cherry picked from commit 1e7c5fd29487ee88cb3abac945bafa60ae026146) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/interrupt.h | 2 +- + kernel/irq/manage.c | 15 ++++++++++++++- + 2 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h +index 6fe4e3c..8854a4c 100644 +--- a/include/linux/interrupt.h ++++ b/include/linux/interrupt.h +@@ -226,7 +226,7 @@ extern void disable_irq_nosync(unsigned int irq); + extern void disable_irq(unsigned int irq); + extern void disable_percpu_irq(unsigned int irq); + extern void enable_irq(unsigned int irq); +-extern void enable_percpu_irq(unsigned int irq); ++extern void enable_percpu_irq(unsigned int irq, unsigned int type); + + /* The following three functions are for the core kernel use only. */ + #ifdef CONFIG_GENERIC_HARDIRQS +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index 7923849..fea7c71 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -1454,7 +1454,7 @@ int request_any_context_irq(unsigned int irq, irq_handler_t handler, + } + EXPORT_SYMBOL_GPL(request_any_context_irq); + +-void enable_percpu_irq(unsigned int irq) ++void enable_percpu_irq(unsigned int irq, unsigned int type) + { + unsigned int cpu = smp_processor_id(); + unsigned long flags; +@@ -1463,7 +1463,20 @@ void enable_percpu_irq(unsigned int irq) + if (!desc) + return; + ++ type &= IRQ_TYPE_SENSE_MASK; ++ if (type != IRQ_TYPE_NONE) { ++ int ret; ++ ++ ret = __irq_set_trigger(desc, irq, type); ++ ++ if (ret) { ++ WARN(1, "failed to set type for IRQ%d\n, irq"); ++ goto out; ++ } ++ } ++ + irq_percpu_enable(desc, cpu); ++out: + irq_put_desc_unlock(desc, flags); + } + +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0164-ARM-gic-local-timers-use-the-request_percpu_irq-inte.patch b/patches.kzm9g/0164-ARM-gic-local-timers-use-the-request_percpu_irq-inte.patch new file mode 100644 index 00000000000000..e01ad13c8e072e --- /dev/null +++ b/patches.kzm9g/0164-ARM-gic-local-timers-use-the-request_percpu_irq-inte.patch @@ -0,0 +1,508 @@ +From f14b02ced1783bf8d9c2825ab79c26cd5d6bc635 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier <marc.zyngier@arm.com> +Date: Fri, 22 Jul 2011 12:52:37 +0100 +Subject: ARM: gic, local timers: use the request_percpu_irq() interface + +This patch remove the hardcoded link between local timers and PPIs, +and convert the PPI users (TWD, MCT and MSM timers) to the new +*_percpu_irq interface. Also some collateral cleanup +(local_timer_ack() is gone, and the interrupt handler is strictly +private to each driver). + +PPIs are now useable for more than just the local timers. + +Additional testing by David Brown (msm8250 and msm8660) and +Shawn Guo (imx6q). + +Cc: David Brown <davidb@codeaurora.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Acked-by: David Brown <davidb@codeaurora.org> +Tested-by: David Brown <davidb@codeaurora.org> +Tested-by: Shawn Guo <shawn.guo@linaro.org> +Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> +(cherry picked from commit 28af690a284dfcb627bd69d0963db1c0f412cb8c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 52 ---------------------------- + arch/arm/include/asm/hardware/gic.h | 1 - + arch/arm/include/asm/localtimer.h | 16 ++++----- + arch/arm/include/asm/smp_twd.h | 2 +- + arch/arm/kernel/smp.c | 16 +-------- + arch/arm/kernel/smp_twd.c | 47 +++++++++++++++++++++++-- + arch/arm/mach-exynos4/mct.c | 7 ++-- + arch/arm/mach-msm/timer.c | 69 +++++++++++++++++++++---------------- + 8 files changed, 99 insertions(+), 111 deletions(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 7a73799..5f7b4e2 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -35,7 +35,6 @@ + #include <asm/irq.h> + #include <asm/mach/irq.h> + #include <asm/hardware/gic.h> +-#include <asm/localtimer.h> + + static DEFINE_SPINLOCK(irq_controller_lock); + +@@ -285,32 +284,6 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) + irq_set_chained_handler(irq, gic_handle_cascade_irq); + } + +-#ifdef CONFIG_LOCAL_TIMERS +-#define gic_ppi_handler percpu_timer_handler +-#else +-static irqreturn_t gic_ppi_handler(int irq, void *dev_id) +-{ +- return IRQ_NONE; +-} +-#endif +- +-#define PPI_IRQACT(nr) \ +- { \ +- .handler = gic_ppi_handler, \ +- .flags = IRQF_PERCPU | IRQF_TIMER, \ +- .irq = nr, \ +- .name = "PPI-" # nr, \ +- } +- +-static struct irqaction ppi_irqaction_template[16] __initdata = { +- PPI_IRQACT(0), PPI_IRQACT(1), PPI_IRQACT(2), PPI_IRQACT(3), +- PPI_IRQACT(4), PPI_IRQACT(5), PPI_IRQACT(6), PPI_IRQACT(7), +- PPI_IRQACT(8), PPI_IRQACT(9), PPI_IRQACT(10), PPI_IRQACT(11), +- PPI_IRQACT(12), PPI_IRQACT(13), PPI_IRQACT(14), PPI_IRQACT(15), +-}; +- +-static struct irqaction *ppi_irqaction; +- + static void __init gic_dist_init(struct gic_chip_data *gic, + unsigned int irq_start) + { +@@ -353,16 +326,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic, + BUG(); + + ppi_base = gic->irq_offset + 32 - nrppis; +- +- ppi_irqaction = kmemdup(&ppi_irqaction_template[16 - nrppis], +- sizeof(*ppi_irqaction) * nrppis, +- GFP_KERNEL); +- +- if (nrppis && !ppi_irqaction) { +- pr_err("GIC: Can't allocate PPI memory"); +- nrppis = 0; +- ppi_base = 0; +- } + } + + pr_info("Configuring GIC with %d sources (%d PPIs)\n", +@@ -405,17 +368,12 @@ static void __init gic_dist_init(struct gic_chip_data *gic, + */ + for (i = 0; i < nrppis; i++) { + int ppi = i + ppi_base; +- int err; + + irq_set_percpu_devid(ppi); + irq_set_chip_and_handler(ppi, &gic_chip, + handle_percpu_devid_irq); + irq_set_chip_data(ppi, gic); + set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN); +- +- err = setup_percpu_irq(ppi, &ppi_irqaction[i]); +- if (err) +- pr_err("GIC: can't setup PPI%d (%d)\n", ppi, err); + } + + for (i = irq_start + nrppis; i < irq_limit; i++) { +@@ -661,16 +619,6 @@ void __cpuinit gic_secondary_init(unsigned int gic_nr) + gic_cpu_init(&gic_data[gic_nr]); + } + +-void __cpuinit gic_enable_ppi(unsigned int irq) +-{ +- unsigned long flags; +- +- local_irq_save(flags); +- irq_set_status_flags(irq, IRQ_NOPROBE); +- gic_unmask_irq(irq_get_irq_data(irq)); +- local_irq_restore(flags); +-} +- + #ifdef CONFIG_SMP + void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) + { +diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h +index 615c336..a61f11e 100644 +--- a/arch/arm/include/asm/hardware/gic.h ++++ b/arch/arm/include/asm/hardware/gic.h +@@ -41,7 +41,6 @@ void gic_secondary_init(unsigned int); + void gic_handle_irq(struct pt_regs *regs); + void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); + void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); +-void gic_enable_ppi(unsigned int); + + struct gic_chip_data { + unsigned int irq_offset; +diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h +index 5c8acb4..f5e1cec 100644 +--- a/arch/arm/include/asm/localtimer.h ++++ b/arch/arm/include/asm/localtimer.h +@@ -19,26 +19,20 @@ struct clock_event_device; + */ + void percpu_timer_setup(void); + +-/* +- * Per-cpu timer IRQ handler +- */ +-irqreturn_t percpu_timer_handler(int irq, void *dev_id); +- + #ifdef CONFIG_LOCAL_TIMERS + + #ifdef CONFIG_HAVE_ARM_TWD + + #include "smp_twd.h" + +-#define local_timer_ack() twd_timer_ack() ++#define local_timer_stop(c) twd_timer_stop((c)) + + #else + + /* +- * Platform provides this to acknowledge a local timer IRQ. +- * Returns true if the local timer IRQ is to be processed. ++ * Stop the local timer + */ +-int local_timer_ack(void); ++void local_timer_stop(struct clock_event_device *); + + #endif + +@@ -53,6 +47,10 @@ static inline int local_timer_setup(struct clock_event_device *evt) + { + return -ENXIO; + } ++ ++static inline void local_timer_stop(struct clock_event_device *evt) ++{ ++} + #endif + + #endif +diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h +index fed9981..ef9ffba9 100644 +--- a/arch/arm/include/asm/smp_twd.h ++++ b/arch/arm/include/asm/smp_twd.h +@@ -22,7 +22,7 @@ struct clock_event_device; + + extern void __iomem *twd_base; + +-int twd_timer_ack(void); + void twd_timer_setup(struct clock_event_device *); ++void twd_timer_stop(struct clock_event_device *); + + #endif +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index 7db7120..083d36e 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -466,20 +466,6 @@ static void ipi_timer(void) + irq_exit(); + } + +-#ifdef CONFIG_LOCAL_TIMERS +-irqreturn_t percpu_timer_handler(int irq, void *dev_id) +-{ +- struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent); +- +- if (local_timer_ack()) { +- evt->event_handler(evt); +- return IRQ_HANDLED; +- } +- +- return IRQ_NONE; +-} +-#endif +- + #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST + static void smp_timer_broadcast(const struct cpumask *mask) + { +@@ -530,7 +516,7 @@ static void percpu_timer_stop(void) + unsigned int cpu = smp_processor_id(); + struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); + +- evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); ++ local_timer_stop(evt); + } + #endif + +diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c +index 01c1862..a8a6682 100644 +--- a/arch/arm/kernel/smp_twd.c ++++ b/arch/arm/kernel/smp_twd.c +@@ -19,6 +19,7 @@ + #include <linux/io.h> + + #include <asm/smp_twd.h> ++#include <asm/localtimer.h> + #include <asm/hardware/gic.h> + + /* set up by the platform code */ +@@ -26,6 +27,8 @@ void __iomem *twd_base; + + static unsigned long twd_timer_rate; + ++static struct clock_event_device __percpu **twd_evt; ++ + static void twd_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) + { +@@ -80,6 +83,12 @@ int twd_timer_ack(void) + return 0; + } + ++void twd_timer_stop(struct clock_event_device *clk) ++{ ++ twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); ++ disable_percpu_irq(clk->irq); ++} ++ + static void __cpuinit twd_calibrate_rate(void) + { + unsigned long count; +@@ -119,11 +128,43 @@ static void __cpuinit twd_calibrate_rate(void) + } + } + ++static irqreturn_t twd_handler(int irq, void *dev_id) ++{ ++ struct clock_event_device *evt = *(struct clock_event_device **)dev_id; ++ ++ if (twd_timer_ack()) { ++ evt->event_handler(evt); ++ return IRQ_HANDLED; ++ } ++ ++ return IRQ_NONE; ++} ++ + /* + * Setup the local clock events for a CPU. + */ + void __cpuinit twd_timer_setup(struct clock_event_device *clk) + { ++ struct clock_event_device **this_cpu_clk; ++ ++ if (!twd_evt) { ++ int err; ++ ++ twd_evt = alloc_percpu(struct clock_event_device *); ++ if (!twd_evt) { ++ pr_err("twd: can't allocate memory\n"); ++ return; ++ } ++ ++ err = request_percpu_irq(clk->irq, twd_handler, ++ "twd", twd_evt); ++ if (err) { ++ pr_err("twd: can't register interrupt %d (%d)\n", ++ clk->irq, err); ++ return; ++ } ++ } ++ + twd_calibrate_rate(); + + clk->name = "local_timer"; +@@ -137,8 +178,10 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) + clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); + clk->min_delta_ns = clockevent_delta2ns(0xf, clk); + ++ this_cpu_clk = __this_cpu_ptr(twd_evt); ++ *this_cpu_clk = clk; ++ + clockevents_register_device(clk); + +- /* Make sure our local interrupt controller has this enabled */ +- gic_enable_ppi(clk->irq); ++ enable_percpu_irq(clk->irq, 0); + } +diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c +index 1ae059b..85a1bb7 100644 +--- a/arch/arm/mach-exynos4/mct.c ++++ b/arch/arm/mach-exynos4/mct.c +@@ -380,9 +380,11 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt) + + if (cpu == 0) { + mct_tick0_event_irq.dev_id = &mct_tick[cpu]; ++ evt->irq = IRQ_MCT_L0; + setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq); + } else { + mct_tick1_event_irq.dev_id = &mct_tick[cpu]; ++ evt->irq = IRQ_MCT_L1; + setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq); + irq_set_affinity(IRQ_MCT_L1, cpumask_of(1)); + } +@@ -394,9 +396,10 @@ void __cpuinit local_timer_setup(struct clock_event_device *evt) + exynos4_mct_tick_init(evt); + } + +-int local_timer_ack(void) ++void local_timer_stop(struct clock_event_device *evt) + { +- return 0; ++ evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); ++ disable_irq(evt->irq); + } + + #endif /* CONFIG_LOCAL_TIMERS */ +diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c +index 63621f1..afeeca5 100644 +--- a/arch/arm/mach-msm/timer.c ++++ b/arch/arm/mach-msm/timer.c +@@ -71,12 +71,16 @@ enum timer_location { + struct msm_clock { + struct clock_event_device clockevent; + struct clocksource clocksource; +- struct irqaction irq; ++ unsigned int irq; + void __iomem *regbase; + uint32_t freq; + uint32_t shift; + void __iomem *global_counter; + void __iomem *local_counter; ++ union { ++ struct clock_event_device *evt; ++ struct clock_event_device __percpu **percpu_evt; ++ }; + }; + + enum { +@@ -87,13 +91,10 @@ enum { + + + static struct msm_clock msm_clocks[]; +-static struct clock_event_device *local_clock_event; + + static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) + { +- struct clock_event_device *evt = dev_id; +- if (smp_processor_id() != 0) +- evt = local_clock_event; ++ struct clock_event_device *evt = *(struct clock_event_device **)dev_id; + if (evt->event_handler == NULL) + return IRQ_HANDLED; + evt->event_handler(evt); +@@ -171,13 +172,7 @@ static struct msm_clock msm_clocks[] = { + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }, +- .irq = { +- .name = "gp_timer", +- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING, +- .handler = msm_timer_interrupt, +- .dev_id = &msm_clocks[0].clockevent, +- .irq = INT_GP_TIMER_EXP +- }, ++ .irq = INT_GP_TIMER_EXP, + .freq = GPT_HZ, + }, + [MSM_CLOCK_DGT] = { +@@ -196,13 +191,7 @@ static struct msm_clock msm_clocks[] = { + .mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }, +- .irq = { +- .name = "dg_timer", +- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_RISING, +- .handler = msm_timer_interrupt, +- .dev_id = &msm_clocks[1].clockevent, +- .irq = INT_DEBUG_TIMER_EXP +- }, ++ .irq = INT_DEBUG_TIMER_EXP, + .freq = DGT_HZ >> MSM_DGT_SHIFT, + .shift = MSM_DGT_SHIFT, + } +@@ -261,10 +250,30 @@ static void __init msm_timer_init(void) + printk(KERN_ERR "msm_timer_init: clocksource_register " + "failed for %s\n", cs->name); + +- res = setup_irq(clock->irq.irq, &clock->irq); ++ ce->irq = clock->irq; ++ if (cpu_is_msm8x60() || cpu_is_msm8960()) { ++ clock->percpu_evt = alloc_percpu(struct clock_event_device *); ++ if (!clock->percpu_evt) { ++ pr_err("msm_timer_init: memory allocation " ++ "failed for %s\n", ce->name); ++ continue; ++ } ++ ++ *__this_cpu_ptr(clock->percpu_evt) = ce; ++ res = request_percpu_irq(ce->irq, msm_timer_interrupt, ++ ce->name, clock->percpu_evt); ++ if (!res) ++ enable_percpu_irq(ce->irq, 0); ++ } else { ++ clock->evt = ce; ++ res = request_irq(ce->irq, msm_timer_interrupt, ++ IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING, ++ ce->name, &clock->evt); ++ } ++ + if (res) +- printk(KERN_ERR "msm_timer_init: setup_irq " +- "failed for %s\n", cs->name); ++ pr_err("msm_timer_init: request_irq failed for %s\n", ++ ce->name); + + clockevents_register_device(ce); + } +@@ -273,6 +282,7 @@ static void __init msm_timer_init(void) + #ifdef CONFIG_SMP + int __cpuinit local_timer_setup(struct clock_event_device *evt) + { ++ static bool local_timer_inited; + struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER]; + + /* Use existing clock_event for cpu 0 */ +@@ -281,12 +291,13 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt) + + writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL); + +- if (!local_clock_event) { ++ if (!local_timer_inited) { + writel(0, clock->regbase + TIMER_ENABLE); + writel(0, clock->regbase + TIMER_CLEAR); + writel(~0, clock->regbase + TIMER_MATCH_VAL); ++ local_timer_inited = true; + } +- evt->irq = clock->irq.irq; ++ evt->irq = clock->irq; + evt->name = "local_timer"; + evt->features = CLOCK_EVT_FEAT_ONESHOT; + evt->rating = clock->clockevent.rating; +@@ -298,17 +309,17 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt) + clockevent_delta2ns(0xf0000000 >> clock->shift, evt); + evt->min_delta_ns = clockevent_delta2ns(4, evt); + +- local_clock_event = evt; +- +- gic_enable_ppi(clock->irq.irq); ++ *__this_cpu_ptr(clock->percpu_evt) = evt; ++ enable_percpu_irq(evt->irq, 0); + + clockevents_register_device(evt); + return 0; + } + +-inline int local_timer_ack(void) ++void local_timer_stop(struct clock_event_device *evt) + { +- return 1; ++ evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); ++ disable_percpu_irq(evt->irq); + } + + #endif +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0165-ARM-gic-add-irq_domain-support.patch b/patches.kzm9g/0165-ARM-gic-add-irq_domain-support.patch new file mode 100644 index 00000000000000..8d19407bf44649 --- /dev/null +++ b/patches.kzm9g/0165-ARM-gic-add-irq_domain-support.patch @@ -0,0 +1,288 @@ +From 6e52acb78212f9cfc7fb843fb01cb197a06d1b3e Mon Sep 17 00:00:00 2001 +From: Rob Herring <rob.herring@calxeda.com> +Date: Wed, 28 Sep 2011 21:25:31 -0500 +Subject: ARM: gic: add irq_domain support + +Convert the gic interrupt controller to use irq domains in preparation +for device-tree binding and MULTI_IRQ. This allows for translation between +GIC interrupt IDs and Linux irq numbers. + +The meaning of irq_offset has changed. It now is just the number of skipped +GIC interrupt IDs for the controller. It will be 16 for primary GIC and 32 +for secondary GICs. + +Signed-off-by: Rob Herring <rob.herring@calxeda.com> +Cc: Marc Zyngier <marc.zyngier@arm.com> +Reviewed-by: Jamie Iles <jamie@jamieiles.com> +Tested-by: Thomas Abraham <thomas.abraham@linaro.org> +Acked-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit 4294f8baaf174c9aa57886e7ed27caf4b02578f6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/Kconfig | 1 + + arch/arm/common/gic.c | 118 +++++++++++++++++------------------- + arch/arm/include/asm/hardware/gic.h | 7 ++- + 3 files changed, 63 insertions(+), 63 deletions(-) + +diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig +index 4b71766..74df9ca 100644 +--- a/arch/arm/common/Kconfig ++++ b/arch/arm/common/Kconfig +@@ -1,4 +1,5 @@ + config ARM_GIC ++ select IRQ_DOMAIN + bool + + config ARM_VIC +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 5f7b4e2..7286e89 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -24,10 +24,12 @@ + */ + #include <linux/init.h> + #include <linux/kernel.h> ++#include <linux/export.h> + #include <linux/list.h> + #include <linux/smp.h> + #include <linux/cpumask.h> + #include <linux/io.h> ++#include <linux/irqdomain.h> + #include <linux/interrupt.h> + #include <linux/percpu.h> + #include <linux/slab.h> +@@ -74,8 +76,7 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d) + + static inline unsigned int gic_irq(struct irq_data *d) + { +- struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); +- return d->irq - gic_data->irq_offset; ++ return d->hwirq; + } + + /* +@@ -83,7 +84,7 @@ static inline unsigned int gic_irq(struct irq_data *d) + */ + static void gic_mask_irq(struct irq_data *d) + { +- u32 mask = 1 << (d->irq % 32); ++ u32 mask = 1 << (gic_irq(d) % 32); + + spin_lock(&irq_controller_lock); + writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); +@@ -94,7 +95,7 @@ static void gic_mask_irq(struct irq_data *d) + + static void gic_unmask_irq(struct irq_data *d) + { +- u32 mask = 1 << (d->irq % 32); ++ u32 mask = 1 << (gic_irq(d) % 32); + + spin_lock(&irq_controller_lock); + if (gic_arch_extn.irq_unmask) +@@ -175,7 +176,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, + bool force) + { + void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); +- unsigned int shift = (d->irq % 4) * 8; ++ unsigned int shift = (gic_irq(d) % 4) * 8; + unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask); + u32 val, mask, bit; + +@@ -252,7 +253,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) + if (gic_irq == 1023) + goto out; + +- cascade_irq = gic_irq + chip_data->irq_offset; ++ cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq); + if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS)) + do_bad_IRQ(cascade_irq, desc); + else +@@ -284,14 +285,14 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) + irq_set_chained_handler(irq, gic_handle_cascade_irq); + } + +-static void __init gic_dist_init(struct gic_chip_data *gic, +- unsigned int irq_start) ++static void __init gic_dist_init(struct gic_chip_data *gic) + { +- unsigned int gic_irqs, irq_limit, i; ++ unsigned int i, irq; + u32 cpumask; ++ unsigned int gic_irqs = gic->gic_irqs; ++ struct irq_domain *domain = &gic->domain; + void __iomem *base = gic->dist_base; + u32 cpu = 0; +- u32 nrppis = 0, ppi_base = 0; + + #ifdef CONFIG_SMP + cpu = cpu_logical_map(smp_processor_id()); +@@ -304,34 +305,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic, + writel_relaxed(0, base + GIC_DIST_CTRL); + + /* +- * Find out how many interrupts are supported. +- * The GIC only supports up to 1020 interrupt sources. +- */ +- gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f; +- gic_irqs = (gic_irqs + 1) * 32; +- if (gic_irqs > 1020) +- gic_irqs = 1020; +- +- gic->gic_irqs = gic_irqs; +- +- /* +- * Nobody would be insane enough to use PPIs on a secondary +- * GIC, right? +- */ +- if (gic == &gic_data[0]) { +- nrppis = (32 - irq_start) & 31; +- +- /* The GIC only supports up to 16 PPIs. */ +- if (nrppis > 16) +- BUG(); +- +- ppi_base = gic->irq_offset + 32 - nrppis; +- } +- +- pr_info("Configuring GIC with %d sources (%d PPIs)\n", +- gic_irqs, (gic == &gic_data[0]) ? nrppis : 0); +- +- /* + * Set all global interrupts to be level triggered, active low. + */ + for (i = 32; i < gic_irqs; i += 16) +@@ -357,29 +330,20 @@ static void __init gic_dist_init(struct gic_chip_data *gic, + writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); + + /* +- * Limit number of interrupts registered to the platform maximum +- */ +- irq_limit = gic->irq_offset + gic_irqs; +- if (WARN_ON(irq_limit > NR_IRQS)) +- irq_limit = NR_IRQS; +- +- /* + * Setup the Linux IRQ subsystem. + */ +- for (i = 0; i < nrppis; i++) { +- int ppi = i + ppi_base; +- +- irq_set_percpu_devid(ppi); +- irq_set_chip_and_handler(ppi, &gic_chip, +- handle_percpu_devid_irq); +- irq_set_chip_data(ppi, gic); +- set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN); +- } +- +- for (i = irq_start + nrppis; i < irq_limit; i++) { +- irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq); +- irq_set_chip_data(i, gic); +- set_irq_flags(i, IRQF_VALID | IRQF_PROBE); ++ irq_domain_for_each_irq(domain, i, irq) { ++ if (i < 32) { ++ irq_set_percpu_devid(irq); ++ irq_set_chip_and_handler(irq, &gic_chip, ++ handle_percpu_devid_irq); ++ set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); ++ } else { ++ irq_set_chip_and_handler(irq, &gic_chip, ++ handle_fasteoi_irq); ++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); ++ } ++ irq_set_chip_data(irq, gic); + } + + writel_relaxed(1, base + GIC_DIST_CTRL); +@@ -591,23 +555,53 @@ static void __init gic_pm_init(struct gic_chip_data *gic) + } + #endif + ++const struct irq_domain_ops gic_irq_domain_ops = { ++}; ++ + void __init gic_init(unsigned int gic_nr, unsigned int irq_start, + void __iomem *dist_base, void __iomem *cpu_base) + { + struct gic_chip_data *gic; ++ struct irq_domain *domain; ++ int gic_irqs; + + BUG_ON(gic_nr >= MAX_GIC_NR); + + gic = &gic_data[gic_nr]; ++ domain = &gic->domain; + gic->dist_base = dist_base; + gic->cpu_base = cpu_base; +- gic->irq_offset = (irq_start - 1) & ~31; + +- if (gic_nr == 0) ++ /* ++ * For primary GICs, skip over SGIs. ++ * For secondary GICs, skip over PPIs, too. ++ */ ++ if (gic_nr == 0) { + gic_cpu_base_addr = cpu_base; ++ domain->hwirq_base = 16; ++ irq_start = (irq_start & ~31) + 16; ++ } else ++ domain->hwirq_base = 32; ++ ++ /* ++ * Find out how many interrupts are supported. ++ * The GIC only supports up to 1020 interrupt sources. ++ */ ++ gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f; ++ gic_irqs = (gic_irqs + 1) * 32; ++ if (gic_irqs > 1020) ++ gic_irqs = 1020; ++ gic->gic_irqs = gic_irqs; ++ ++ domain->nr_irq = gic_irqs - domain->hwirq_base; ++ domain->irq_base = irq_alloc_descs(-1, irq_start, domain->nr_irq, ++ numa_node_id()); ++ domain->priv = gic; ++ domain->ops = &gic_irq_domain_ops; ++ irq_domain_add(domain); + + gic_chip.flags |= gic_arch_extn.flags; +- gic_dist_init(gic, irq_start); ++ gic_dist_init(gic); + gic_cpu_init(gic); + gic_pm_init(gic); + } +diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h +index a61f11e..06a540b 100644 +--- a/arch/arm/include/asm/hardware/gic.h ++++ b/arch/arm/include/asm/hardware/gic.h +@@ -33,6 +33,9 @@ + #define GIC_DIST_SOFTINT 0xf00 + + #ifndef __ASSEMBLY__ ++#include <linux/irqdomain.h> ++struct device_node; ++ + extern void __iomem *gic_cpu_base_addr; + extern struct irq_chip gic_arch_extn; + +@@ -43,7 +46,6 @@ void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); + void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); + + struct gic_chip_data { +- unsigned int irq_offset; + void __iomem *dist_base; + void __iomem *cpu_base; + #ifdef CONFIG_CPU_PM +@@ -53,6 +55,9 @@ struct gic_chip_data { + u32 __percpu *saved_ppi_enable; + u32 __percpu *saved_ppi_conf; + #endif ++#ifdef CONFIG_IRQ_DOMAIN ++ struct irq_domain domain; ++#endif + unsigned int gic_irqs; + }; + #endif +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0166-ARM-gic-add-OF-based-initialization.patch b/patches.kzm9g/0166-ARM-gic-add-OF-based-initialization.patch new file mode 100644 index 00000000000000..58570564418f2d --- /dev/null +++ b/patches.kzm9g/0166-ARM-gic-add-OF-based-initialization.patch @@ -0,0 +1,195 @@ +From 5f7a0ce78ca6151ea78331f4f474e4984e9d70a1 Mon Sep 17 00:00:00 2001 +From: Rob Herring <rob.herring@calxeda.com> +Date: Wed, 28 Sep 2011 21:27:52 -0500 +Subject: ARM: gic: add OF based initialization + +This adds ARM gic interrupt controller initialization using device tree +data. + +The initialization function is intended to be called by of_irq_init +function like this: + +const static struct of_device_id irq_match[] = { + { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, + {} +}; + +static void __init init_irqs(void) +{ + of_irq_init(irq_match); +} + +Signed-off-by: Rob Herring <rob.herring@calxeda.com> +Reviewed-by: Jamie Iles <jamie@jamieiles.com> +Tested-by: Thomas Abraham <thomas.abraham@linaro.org> +Acked-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit b3f7ed0324091e2cb23fe1b3c10570700f614014) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + Documentation/devicetree/bindings/arm/gic.txt | 55 ++++++++++++++++++++++++ + arch/arm/common/gic.c | 61 +++++++++++++++++++++++++++ + arch/arm/include/asm/hardware/gic.h | 1 + + 3 files changed, 117 insertions(+) + create mode 100644 Documentation/devicetree/bindings/arm/gic.txt + +diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt +new file mode 100644 +index 0000000..52916b4 +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/gic.txt +@@ -0,0 +1,55 @@ ++* ARM Generic Interrupt Controller ++ ++ARM SMP cores are often associated with a GIC, providing per processor ++interrupts (PPI), shared processor interrupts (SPI) and software ++generated interrupts (SGI). ++ ++Primary GIC is attached directly to the CPU and typically has PPIs and SGIs. ++Secondary GICs are cascaded into the upward interrupt controller and do not ++have PPIs or SGIs. ++ ++Main node required properties: ++ ++- compatible : should be one of: ++ "arm,cortex-a9-gic" ++ "arm,arm11mp-gic" ++- interrupt-controller : Identifies the node as an interrupt controller ++- #interrupt-cells : Specifies the number of cells needed to encode an ++ interrupt source. The type shall be a <u32> and the value shall be 3. ++ ++ The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI ++ interrupts. ++ ++ The 2nd cell contains the interrupt number for the interrupt type. ++ SPI interrupts are in the range [0-987]. PPI interrupts are in the ++ range [0-15]. ++ ++ The 3rd cell is the flags, encoded as follows: ++ bits[3:0] trigger type and level flags. ++ 1 = low-to-high edge triggered ++ 2 = high-to-low edge triggered ++ 4 = active high level-sensitive ++ 8 = active low level-sensitive ++ bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of ++ the 8 possible cpus attached to the GIC. A bit set to '1' indicated ++ the interrupt is wired to that CPU. Only valid for PPI interrupts. ++ ++- reg : Specifies base physical address(s) and size of the GIC registers. The ++ first region is the GIC distributor register base and size. The 2nd region is ++ the GIC cpu interface register base and size. ++ ++Optional ++- interrupts : Interrupt source of the parent interrupt controller. Only ++ present on secondary GICs. ++ ++Example: ++ ++ intc: interrupt-controller@fff11000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <1>; ++ interrupt-controller; ++ reg = <0xfff11000 0x1000>, ++ <0xfff10100 0x100>; ++ }; ++ +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 7286e89..0976555 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -29,6 +29,9 @@ + #include <linux/smp.h> + #include <linux/cpumask.h> + #include <linux/io.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/of_irq.h> + #include <linux/irqdomain.h> + #include <linux/interrupt.h> + #include <linux/percpu.h> +@@ -555,7 +558,33 @@ static void __init gic_pm_init(struct gic_chip_data *gic) + } + #endif + ++#ifdef CONFIG_OF ++static int gic_irq_domain_dt_translate(struct irq_domain *d, ++ struct device_node *controller, ++ const u32 *intspec, unsigned int intsize, ++ unsigned long *out_hwirq, unsigned int *out_type) ++{ ++ if (d->of_node != controller) ++ return -EINVAL; ++ if (intsize < 3) ++ return -EINVAL; ++ ++ /* Get the interrupt number and add 16 to skip over SGIs */ ++ *out_hwirq = intspec[1] + 16; ++ ++ /* For SPIs, we need to add 16 more to get the GIC irq ID number */ ++ if (!intspec[0]) ++ *out_hwirq += 16; ++ ++ *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; ++ return 0; ++} ++#endif ++ + const struct irq_domain_ops gic_irq_domain_ops = { ++#ifdef CONFIG_OF ++ .dt_translate = gic_irq_domain_dt_translate, ++#endif + }; + + void __init gic_init(unsigned int gic_nr, unsigned int irq_start, +@@ -633,3 +662,35 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) + writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT); + } + #endif ++ ++#ifdef CONFIG_OF ++static int gic_cnt __initdata = 0; ++ ++int __init gic_of_init(struct device_node *node, struct device_node *parent) ++{ ++ void __iomem *cpu_base; ++ void __iomem *dist_base; ++ int irq; ++ struct irq_domain *domain = &gic_data[gic_cnt].domain; ++ ++ if (WARN_ON(!node)) ++ return -ENODEV; ++ ++ dist_base = of_iomap(node, 0); ++ WARN(!dist_base, "unable to map gic dist registers\n"); ++ ++ cpu_base = of_iomap(node, 1); ++ WARN(!cpu_base, "unable to map gic cpu registers\n"); ++ ++ domain->of_node = of_node_get(node); ++ ++ gic_init(gic_cnt, 16, dist_base, cpu_base); ++ ++ if (parent) { ++ irq = irq_of_parse_and_map(node, 0); ++ gic_cascade_irq(gic_cnt, irq); ++ } ++ gic_cnt++; ++ return 0; ++} ++#endif +diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h +index 06a540b..da822f6 100644 +--- a/arch/arm/include/asm/hardware/gic.h ++++ b/arch/arm/include/asm/hardware/gic.h +@@ -40,6 +40,7 @@ extern void __iomem *gic_cpu_base_addr; + extern struct irq_chip gic_arch_extn; + + void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *); ++int gic_of_init(struct device_node *node, struct device_node *parent); + void gic_secondary_init(unsigned int); + void gic_handle_irq(struct pt_regs *regs); + void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0167-ARM-gic-fix-irq_alloc_descs-handling-for-sparse-irq.patch b/patches.kzm9g/0167-ARM-gic-fix-irq_alloc_descs-handling-for-sparse-irq.patch new file mode 100644 index 00000000000000..3ca00b31596a53 --- /dev/null +++ b/patches.kzm9g/0167-ARM-gic-fix-irq_alloc_descs-handling-for-sparse-irq.patch @@ -0,0 +1,99 @@ +From 69c8cbbe40b940304234d68ffa5092a8f1197f45 Mon Sep 17 00:00:00 2001 +From: Rob Herring <rob.herring@calxeda.com> +Date: Fri, 21 Oct 2011 17:14:27 -0500 +Subject: ARM: gic: fix irq_alloc_descs handling for sparse irq + +Commit "ARM: gic: add irq_domain support" (b49b6ff) breaks SPARSE_IRQ +on platforms with GIC. When SPARSE_IRQ is enabled, all NR_IRQS or +mach_desc->nr_irqs will be allocated by arch_probe_nr_irqs(). This caused +irq_alloc_descs to allocate irq_descs after the pre-allocated space. + +Make irq_alloc_descs search for an exact irq range and assume it has +been pre-allocated on failure. For DT probing dynamic allocation is used. +DT enabled platforms should set their nr_irqs to NR_IRQ_LEGACY and have all +irq_chips allocate their irq_descs with irq_alloc_descs if SPARSE_IRQ is +enabled. + +gic_init irq_start param is changed to be signed with negative meaning do +dynamic Linux irq assigment. + +Signed-off-by: Rob Herring <rob.herring@calxeda.com> +(cherry picked from commit f37a53cc5d8a8fb199e41386d125d8c2ed9e54ef) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 15 +++++++++++---- + arch/arm/include/asm/hardware/gic.h | 2 +- + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 0976555..0ad3584 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -24,6 +24,7 @@ + */ + #include <linux/init.h> + #include <linux/kernel.h> ++#include <linux/err.h> + #include <linux/export.h> + #include <linux/list.h> + #include <linux/smp.h> +@@ -587,7 +588,7 @@ const struct irq_domain_ops gic_irq_domain_ops = { + #endif + }; + +-void __init gic_init(unsigned int gic_nr, unsigned int irq_start, ++void __init gic_init(unsigned int gic_nr, int irq_start, + void __iomem *dist_base, void __iomem *cpu_base) + { + struct gic_chip_data *gic; +@@ -608,7 +609,8 @@ void __init gic_init(unsigned int gic_nr, unsigned int irq_start, + if (gic_nr == 0) { + gic_cpu_base_addr = cpu_base; + domain->hwirq_base = 16; +- irq_start = (irq_start & ~31) + 16; ++ if (irq_start > 0) ++ irq_start = (irq_start & ~31) + 16; + } else + domain->hwirq_base = 32; + +@@ -623,8 +625,13 @@ void __init gic_init(unsigned int gic_nr, unsigned int irq_start, + gic->gic_irqs = gic_irqs; + + domain->nr_irq = gic_irqs - domain->hwirq_base; +- domain->irq_base = irq_alloc_descs(-1, irq_start, domain->nr_irq, ++ domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq, + numa_node_id()); ++ if (IS_ERR_VALUE(domain->irq_base)) { ++ WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", ++ irq_start); ++ domain->irq_base = irq_start; ++ } + domain->priv = gic; + domain->ops = &gic_irq_domain_ops; + irq_domain_add(domain); +@@ -684,7 +691,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) + + domain->of_node = of_node_get(node); + +- gic_init(gic_cnt, 16, dist_base, cpu_base); ++ gic_init(gic_cnt, -1, dist_base, cpu_base); + + if (parent) { + irq = irq_of_parse_and_map(node, 0); +diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h +index da822f6..b7641d6 100644 +--- a/arch/arm/include/asm/hardware/gic.h ++++ b/arch/arm/include/asm/hardware/gic.h +@@ -39,7 +39,7 @@ struct device_node; + extern void __iomem *gic_cpu_base_addr; + extern struct irq_chip gic_arch_extn; + +-void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *); ++void gic_init(unsigned int, int, void __iomem *, void __iomem *); + int gic_of_init(struct device_node *node, struct device_node *parent); + void gic_secondary_init(unsigned int); + void gic_handle_irq(struct pt_regs *regs); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0168-ARM-gic-use-module.h-instead-of-export.h.patch b/patches.kzm9g/0168-ARM-gic-use-module.h-instead-of-export.h.patch new file mode 100644 index 00000000000000..57daec9d76260e --- /dev/null +++ b/patches.kzm9g/0168-ARM-gic-use-module.h-instead-of-export.h.patch @@ -0,0 +1,32 @@ +From 821b37ef872cbc43bfd3b3c3d9b85aeebe863349 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann <arnd@arndb.de> +Date: Tue, 1 Nov 2011 00:28:37 +0100 +Subject: ARM: gic: use module.h instead of export.h + +The module.h cleanup series is not merged at this point, so use the +older header file for now, to make it build either way. + +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +(cherry picked from commit 7e1efcf5d2039fb7a91e21df32f4175dbca4d61c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 0ad3584..f4b2864 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -25,7 +25,7 @@ + #include <linux/init.h> + #include <linux/kernel.h> + #include <linux/err.h> +-#include <linux/export.h> ++#include <linux/module.h> + #include <linux/list.h> + #include <linux/smp.h> + #include <linux/cpumask.h> +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0169-ARM-7176-1-cpu_pm-register-GIC-PM-notifier-only-once.patch b/patches.kzm9g/0169-ARM-7176-1-cpu_pm-register-GIC-PM-notifier-only-once.patch new file mode 100644 index 00000000000000..2f1510de03f150 --- /dev/null +++ b/patches.kzm9g/0169-ARM-7176-1-cpu_pm-register-GIC-PM-notifier-only-once.patch @@ -0,0 +1,44 @@ +From c17eb62ef5e57dbca9e3789f931edae8d0af6247 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier <Marc.Zyngier@arm.com> +Date: Fri, 25 Nov 2011 17:58:19 +0100 +Subject: ARM: 7176/1: cpu_pm: register GIC PM notifier only once + +When multiple GICs exist on a platform (RealView PB1176/11MP), +we must make sure the PM notifier block is only registered +once, otherwise we end up corrupting the PM notifier list. + +The fix is to only register the notifier when initializing +the first GIC, as the power management functions seem +to iterate over all the registered GICs. + +Tested on PB11MP and PB1176. + +Reported-by: Will Deacon <will.deacon@arm.com> +Tested-by: Will Deacon <will.deacon@arm.com> +Cc: Colin Cross <ccross@android.com> +Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit abdd7b91dab2f8b2e32e90e4b7e809ffb462a662) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index f4b2864..432c879 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -551,7 +551,8 @@ static void __init gic_pm_init(struct gic_chip_data *gic) + sizeof(u32)); + BUG_ON(!gic->saved_ppi_conf); + +- cpu_pm_register_notifier(&gic_notifier_block); ++ if (gic == &gic_data[0]) ++ cpu_pm_register_notifier(&gic_notifier_block); + } + #else + static void __init gic_pm_init(struct gic_chip_data *gic) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0170-ARM-7177-1-GIC-avoid-skipping-non-existent-PPIs-in-i.patch b/patches.kzm9g/0170-ARM-7177-1-GIC-avoid-skipping-non-existent-PPIs-in-i.patch new file mode 100644 index 00000000000000..5ee8e3eb9bf4b4 --- /dev/null +++ b/patches.kzm9g/0170-ARM-7177-1-GIC-avoid-skipping-non-existent-PPIs-in-i.patch @@ -0,0 +1,52 @@ +From c7dd20bb08c673ce9ce055074c77d92760bc03ac Mon Sep 17 00:00:00 2001 +From: Will Deacon <will.deacon@arm.com> +Date: Fri, 25 Nov 2011 19:23:36 +0100 +Subject: ARM: 7177/1: GIC: avoid skipping non-existent PPIs in irq_start + calculation + +Commit 4294f8baa ("ARM: gic: add irq_domain support") defines irq_start +as irq_start = (irq_start & ~31) + 16; On a platform with a GIC and a +CPU without PPIs, this results in irq_start being off by 16. + +This patch fixes gic_init so that we only carve out a PPI space when +PPIs exist for the GIC being initialised. + +Cc: Rob Herring <rob.herring@calxeda.com> +Signed-off-by: Will Deacon <will.deacon@arm.com> +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit fe41db7b3aca512e19b8ef4fbd5ad55545005d25) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/common/gic.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c +index 432c879..0b95dc5 100644 +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -607,13 +607,16 @@ void __init gic_init(unsigned int gic_nr, int irq_start, + * For primary GICs, skip over SGIs. + * For secondary GICs, skip over PPIs, too. + */ ++ domain->hwirq_base = 32; + if (gic_nr == 0) { + gic_cpu_base_addr = cpu_base; +- domain->hwirq_base = 16; +- if (irq_start > 0) +- irq_start = (irq_start & ~31) + 16; +- } else +- domain->hwirq_base = 32; ++ ++ if ((irq_start & 31) > 0) { ++ domain->hwirq_base = 16; ++ if (irq_start != -1) ++ irq_start = (irq_start & ~31) + 16; ++ } ++ } + + /* + * Find out how many interrupts are supported. +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0171-ARM-mach-shmobile-clock-sh73a0-tidyup-CKSCR-main-clo.patch b/patches.kzm9g/0171-ARM-mach-shmobile-clock-sh73a0-tidyup-CKSCR-main-clo.patch new file mode 100644 index 00000000000000..4cdc9a6b45eb52 --- /dev/null +++ b/patches.kzm9g/0171-ARM-mach-shmobile-clock-sh73a0-tidyup-CKSCR-main-clo.patch @@ -0,0 +1,32 @@ +From f62259f22080ff97053936c271bb057b6cd2b7b1 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 26 Aug 2011 07:27:45 +0000 +Subject: ARM: mach-shmobile: clock-sh73a0: tidyup CKSCR main clock selecter + +MAINCKSEL is [29:28], not [27:24] + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 86d84083cfb15dd9594eefff7859e982770930d0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-sh73a0.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c +index 9fc2830..44a923d 100644 +--- a/arch/arm/mach-shmobile/clock-sh73a0.c ++++ b/arch/arm/mach-shmobile/clock-sh73a0.c +@@ -365,7 +365,7 @@ void __init sh73a0_clock_init(void) + __raw_writel(0x108, SD2CKCR); + + /* detect main clock parent */ +- switch ((__raw_readl(CKSCR) >> 24) & 0x03) { ++ switch ((__raw_readl(CKSCR) >> 28) & 0x03) { + case 0: + main_clk.parent = &sh73a0_extal1_clk; + break; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0172-ARM-mach-shmobile-sh73a0-PFC-pull-up-support-for-SDH.patch b/patches.kzm9g/0172-ARM-mach-shmobile-sh73a0-PFC-pull-up-support-for-SDH.patch new file mode 100644 index 00000000000000..6eaaca6e91668a --- /dev/null +++ b/patches.kzm9g/0172-ARM-mach-shmobile-sh73a0-PFC-pull-up-support-for-SDH.patch @@ -0,0 +1,189 @@ +From 78057d7b664fb1d2f584807f5511dca73e595df9 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Thu, 18 Aug 2011 04:32:08 +0000 +Subject: ARM: mach-shmobile: sh73a0 PFC pull-up support for SDHI0+2 + +Extend the existing sh73a0 PFC code with pull-ups for +SDHI0 and SDHI2. Without this patch only SDHI1 has +pull-up support on sh73a0. Needed by boards that make +use of the internal pull-up resistor support built in +the SoC. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 09dafe9e4e266c7868454a532c9ca762aa5c40a5) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/sh73a0.h | 13 +++++ + arch/arm/mach-shmobile/pfc-sh73a0.c | 77 ++++++++++++++++++++++------ + 2 files changed, 75 insertions(+), 15 deletions(-) + +diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h +index 216c3d6..b385e97 100644 +--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h ++++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h +@@ -451,11 +451,23 @@ enum { + GPIO_FN_KEYIN5_PU, + GPIO_FN_KEYIN6_PU, + GPIO_FN_KEYIN7_PU, ++ GPIO_FN_SDHICD0_PU, ++ GPIO_FN_SDHID0_0_PU, ++ GPIO_FN_SDHID0_1_PU, ++ GPIO_FN_SDHID0_2_PU, ++ GPIO_FN_SDHID0_3_PU, ++ GPIO_FN_SDHICMD0_PU, ++ GPIO_FN_SDHIWP0_PU, + GPIO_FN_SDHID1_0_PU, + GPIO_FN_SDHID1_1_PU, + GPIO_FN_SDHID1_2_PU, + GPIO_FN_SDHID1_3_PU, + GPIO_FN_SDHICMD1_PU, ++ GPIO_FN_SDHID2_0_PU, ++ GPIO_FN_SDHID2_1_PU, ++ GPIO_FN_SDHID2_2_PU, ++ GPIO_FN_SDHID2_3_PU, ++ GPIO_FN_SDHICMD2_PU, + GPIO_FN_MMCCMD0_PU, + GPIO_FN_MMCCMD1_PU, + GPIO_FN_FSIACK_PU, +@@ -463,6 +475,7 @@ enum { + GPIO_FN_FSIAIBT_PU, + GPIO_FN_FSIAISLD_PU, + }; ++ + /* DMA slave IDs */ + enum { + SHDMA_SLAVE_INVALID, +diff --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c +index d8915c6..599016e 100644 +--- a/arch/arm/mach-shmobile/pfc-sh73a0.c ++++ b/arch/arm/mach-shmobile/pfc-sh73a0.c +@@ -476,13 +476,26 @@ enum { + KEYIN5_PU_MARK, + KEYIN6_PU_MARK, + KEYIN7_PU_MARK, ++ SDHICD0_PU_MARK, ++ SDHID0_0_PU_MARK, ++ SDHID0_1_PU_MARK, ++ SDHID0_2_PU_MARK, ++ SDHID0_3_PU_MARK, ++ SDHICMD0_PU_MARK, ++ SDHIWP0_PU_MARK, + SDHID1_0_PU_MARK, + SDHID1_1_PU_MARK, + SDHID1_2_PU_MARK, + SDHID1_3_PU_MARK, + SDHICMD1_PU_MARK, ++ SDHID2_0_PU_MARK, ++ SDHID2_1_PU_MARK, ++ SDHID2_2_PU_MARK, ++ SDHID2_3_PU_MARK, ++ SDHICMD2_PU_MARK, + MMCCMD0_PU_MARK, + MMCCMD1_PU_MARK, ++ FSIBISLD_PU_MARK, + FSIACK_PU_MARK, + FSIAILR_PU_MARK, + FSIAIBT_PU_MARK, +@@ -1336,19 +1349,28 @@ static pinmux_enum_t pinmux_data[] = { + PINMUX_DATA(TS_SCK4_MARK, PORT268_FN3), + PINMUX_DATA(SDHICMD2_MARK, PORT269_FN1), + PINMUX_DATA(MMCCLK0_MARK, PORT270_FN1, MSEL4CR_MSEL15_0), +- PINMUX_DATA(MMCD0_0_MARK, PORT271_FN1, MSEL4CR_MSEL15_0), +- PINMUX_DATA(MMCD0_1_MARK, PORT272_FN1, MSEL4CR_MSEL15_0), +- PINMUX_DATA(MMCD0_2_MARK, PORT273_FN1, MSEL4CR_MSEL15_0), +- PINMUX_DATA(MMCD0_3_MARK, PORT274_FN1, MSEL4CR_MSEL15_0), +- PINMUX_DATA(MMCD0_4_MARK, PORT275_FN1, MSEL4CR_MSEL15_0), \ ++ PINMUX_DATA(MMCD0_0_MARK, PORT271_FN1, PORT271_IN_PU, ++ MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_1_MARK, PORT272_FN1, PORT272_IN_PU, ++ MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_2_MARK, PORT273_FN1, PORT273_IN_PU, ++ MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_3_MARK, PORT274_FN1, PORT274_IN_PU, ++ MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_4_MARK, PORT275_FN1, PORT275_IN_PU, ++ MSEL4CR_MSEL15_0), \ + PINMUX_DATA(TS_SPSYNC5_MARK, PORT275_FN3), +- PINMUX_DATA(MMCD0_5_MARK, PORT276_FN1, MSEL4CR_MSEL15_0), \ ++ PINMUX_DATA(MMCD0_5_MARK, PORT276_FN1, PORT276_IN_PU, ++ MSEL4CR_MSEL15_0), \ + PINMUX_DATA(TS_SDAT5_MARK, PORT276_FN3), +- PINMUX_DATA(MMCD0_6_MARK, PORT277_FN1, MSEL4CR_MSEL15_0), \ ++ PINMUX_DATA(MMCD0_6_MARK, PORT277_FN1, PORT277_IN_PU, ++ MSEL4CR_MSEL15_0), \ + PINMUX_DATA(TS_SDEN5_MARK, PORT277_FN3), +- PINMUX_DATA(MMCD0_7_MARK, PORT278_FN1, MSEL4CR_MSEL15_0), \ ++ PINMUX_DATA(MMCD0_7_MARK, PORT278_FN1, PORT278_IN_PU, ++ MSEL4CR_MSEL15_0), \ + PINMUX_DATA(TS_SCK5_MARK, PORT278_FN3), +- PINMUX_DATA(MMCCMD0_MARK, PORT279_FN1, MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCCMD0_MARK, PORT279_FN1, PORT279_IN_PU, ++ MSEL4CR_MSEL15_0), + PINMUX_DATA(RESETOUTS__MARK, PORT281_FN1), \ + PINMUX_DATA(EXTAL2OUT_MARK, PORT281_FN2), + PINMUX_DATA(MCP_WAIT__MCP_FRB_MARK, PORT288_FN1), +@@ -1465,16 +1487,29 @@ static pinmux_enum_t pinmux_data[] = { + PINMUX_DATA(KEYIN6_PU_MARK, PORT72_FN2, PORT72_IN_PU), + PINMUX_DATA(KEYIN7_PU_MARK, PORT73_FN2, PORT73_IN_PU), + +- PINMUX_DATA(SDHID1_0_PU_MARK, PORT259_IN_PU, PORT259_FN1), +- PINMUX_DATA(SDHID1_1_PU_MARK, PORT260_IN_PU, PORT260_FN1), +- PINMUX_DATA(SDHID1_2_PU_MARK, PORT261_IN_PU, PORT261_FN1), +- PINMUX_DATA(SDHID1_3_PU_MARK, PORT262_IN_PU, PORT262_FN1), +- PINMUX_DATA(SDHICMD1_PU_MARK, PORT263_IN_PU, PORT263_FN1), ++ PINMUX_DATA(SDHICD0_PU_MARK, PORT251_FN1, PORT251_IN_PU), ++ PINMUX_DATA(SDHID0_0_PU_MARK, PORT252_FN1, PORT252_IN_PU), ++ PINMUX_DATA(SDHID0_1_PU_MARK, PORT253_FN1, PORT253_IN_PU), ++ PINMUX_DATA(SDHID0_2_PU_MARK, PORT254_FN1, PORT254_IN_PU), ++ PINMUX_DATA(SDHID0_3_PU_MARK, PORT255_FN1, PORT255_IN_PU), ++ PINMUX_DATA(SDHICMD0_PU_MARK, PORT256_FN1, PORT256_IN_PU), ++ PINMUX_DATA(SDHIWP0_PU_MARK, PORT257_FN1, PORT256_IN_PU), ++ PINMUX_DATA(SDHID1_0_PU_MARK, PORT259_FN1, PORT259_IN_PU), ++ PINMUX_DATA(SDHID1_1_PU_MARK, PORT260_FN1, PORT260_IN_PU), ++ PINMUX_DATA(SDHID1_2_PU_MARK, PORT261_FN1, PORT261_IN_PU), ++ PINMUX_DATA(SDHID1_3_PU_MARK, PORT262_FN1, PORT262_IN_PU), ++ PINMUX_DATA(SDHICMD1_PU_MARK, PORT263_FN1, PORT263_IN_PU), ++ PINMUX_DATA(SDHID2_0_PU_MARK, PORT265_FN1, PORT265_IN_PU), ++ PINMUX_DATA(SDHID2_1_PU_MARK, PORT266_FN1, PORT266_IN_PU), ++ PINMUX_DATA(SDHID2_2_PU_MARK, PORT267_FN1, PORT267_IN_PU), ++ PINMUX_DATA(SDHID2_3_PU_MARK, PORT268_FN1, PORT268_IN_PU), ++ PINMUX_DATA(SDHICMD2_PU_MARK, PORT269_FN1, PORT269_IN_PU), + + PINMUX_DATA(MMCCMD0_PU_MARK, PORT279_FN1, PORT279_IN_PU, + MSEL4CR_MSEL15_0), +- PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT279_IN_PU, ++ PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT297_IN_PU, + MSEL4CR_MSEL15_1), ++ PINMUX_DATA(FSIBISLD_PU_MARK, PORT39_FN1, PORT39_IN_PU), + PINMUX_DATA(FSIACK_PU_MARK, PORT49_FN1, PORT49_IN_PU), + PINMUX_DATA(FSIAILR_PU_MARK, PORT50_FN5, PORT50_IN_PU), + PINMUX_DATA(FSIAIBT_PU_MARK, PORT51_FN5, PORT51_IN_PU), +@@ -2126,11 +2161,23 @@ static struct pinmux_gpio pinmux_gpios[] = { + GPIO_FN(KEYIN5_PU), + GPIO_FN(KEYIN6_PU), + GPIO_FN(KEYIN7_PU), ++ GPIO_FN(SDHICD0_PU), ++ GPIO_FN(SDHID0_0_PU), ++ GPIO_FN(SDHID0_1_PU), ++ GPIO_FN(SDHID0_2_PU), ++ GPIO_FN(SDHID0_3_PU), ++ GPIO_FN(SDHICMD0_PU), ++ GPIO_FN(SDHIWP0_PU), + GPIO_FN(SDHID1_0_PU), + GPIO_FN(SDHID1_1_PU), + GPIO_FN(SDHID1_2_PU), + GPIO_FN(SDHID1_3_PU), + GPIO_FN(SDHICMD1_PU), ++ GPIO_FN(SDHID2_0_PU), ++ GPIO_FN(SDHID2_1_PU), ++ GPIO_FN(SDHID2_2_PU), ++ GPIO_FN(SDHID2_3_PU), ++ GPIO_FN(SDHICMD2_PU), + GPIO_FN(MMCCMD0_PU), + GPIO_FN(MMCCMD1_PU), + GPIO_FN(FSIACK_PU), +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0173-ARM-shmobile-convert-logical-CPU-numbers-to-physical.patch b/patches.kzm9g/0173-ARM-shmobile-convert-logical-CPU-numbers-to-physical.patch new file mode 100644 index 00000000000000..b5b7d6d9163127 --- /dev/null +++ b/patches.kzm9g/0173-ARM-shmobile-convert-logical-CPU-numbers-to-physical.patch @@ -0,0 +1,51 @@ +From 99e07f2cb417d9c739ff222b73d8a4040486249f Mon Sep 17 00:00:00 2001 +From: Will Deacon <will.deacon@arm.com> +Date: Tue, 9 Aug 2011 12:13:53 +0100 +Subject: ARM: shmobile: convert logical CPU numbers to physical numbers + +This patch uses the new cpu_logical_map() macro for converting logical +CPU numbers into physical numbers when dealing with the SCU in the SMP +boot path for sh73a0. + +Cc: Magnus Damm <magnus.damm@gmail.com> +Cc: Paul Mundt <lethal@linux-sh.org> +Signed-off-by: Will Deacon <will.deacon@arm.com> +(cherry picked from commit f80ca52cab8f999246ed2e4daa90eb40cb810822) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/smp-sh73a0.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c +index 3ffdbc9..be1ade7 100644 +--- a/arch/arm/mach-shmobile/smp-sh73a0.c ++++ b/arch/arm/mach-shmobile/smp-sh73a0.c +@@ -74,6 +74,8 @@ void __cpuinit sh73a0_secondary_init(unsigned int cpu) + + int __cpuinit sh73a0_boot_secondary(unsigned int cpu) + { ++ cpu = cpu_logical_map(cpu); ++ + /* enable cache coherency */ + modify_scu_cpu_psr(0, 3 << (cpu * 8)); + +@@ -87,6 +89,8 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu) + + void __init sh73a0_smp_prepare_cpus(void) + { ++ int cpu = cpu_logical_map(0); ++ + scu_enable(scu_base_addr()); + + /* Map the reset vector (in headsmp.S) */ +@@ -94,5 +98,5 @@ void __init sh73a0_smp_prepare_cpus(void) + __raw_writel(__pa(shmobile_secondary_vector), __io(SBAR)); + + /* enable cache coherency on CPU0 */ +- modify_scu_cpu_psr(0, 3 << (0 * 8)); ++ modify_scu_cpu_psr(0, 3 << (cpu * 8)); + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0174-ARM-mach-shmobile-sh73a0-GPIO-IRQ-support.patch b/patches.kzm9g/0174-ARM-mach-shmobile-sh73a0-GPIO-IRQ-support.patch new file mode 100644 index 00000000000000..176239b986de4e --- /dev/null +++ b/patches.kzm9g/0174-ARM-mach-shmobile-sh73a0-GPIO-IRQ-support.patch @@ -0,0 +1,91 @@ +From ce81dcdbb5efaf6b9e1662138e6ce62833cb584d Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Wed, 28 Sep 2011 16:55:45 +0900 +Subject: ARM: mach-shmobile: sh73a0 GPIO IRQ support + +This patch adds support for sh73a0 GPIO IRQs by making use +of the PFC GPIO IRQ feature. Only IRQ pins are supported +at this time. In the future when PINT interrupts also are +supported properly we can easily extend the table with such +information. Also, the sh73a0 is currently making use of +the GIC for external interrupt which is rather unflexible +when it comes to triggering configuration at this point. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 13fc7e7c2cd08a884f76eeb940957160b296d5c3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/pfc-sh73a0.c | 41 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c +index 599016e..0e24ac4 100644 +--- a/arch/arm/mach-shmobile/pfc-sh73a0.c ++++ b/arch/arm/mach-shmobile/pfc-sh73a0.c +@@ -22,6 +22,7 @@ + #include <linux/kernel.h> + #include <linux/gpio.h> + #include <mach/sh73a0.h> ++#include <mach/irqs.h> + + #define CPU_ALL_PORT(fn, pfx, sfx) \ + PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \ +@@ -2698,6 +2699,43 @@ static struct pinmux_data_reg pinmux_data_regs[] = { + { }, + }; + ++#define EXT_IRQ(n) gic_spi((n) + 1) /* GIC SPI starting from 1 for IRQ0 */ ++ ++static struct pinmux_irq pinmux_irqs[] = { ++ PINMUX_IRQ(EXT_IRQ(19), PORT9_FN0), ++ PINMUX_IRQ(EXT_IRQ(1), PORT10_FN0), ++ PINMUX_IRQ(EXT_IRQ(0), PORT11_FN0), ++ PINMUX_IRQ(EXT_IRQ(18), PORT13_FN0), ++ PINMUX_IRQ(EXT_IRQ(20), PORT14_FN0), ++ PINMUX_IRQ(EXT_IRQ(21), PORT15_FN0), ++ PINMUX_IRQ(EXT_IRQ(31), PORT26_FN0), ++ PINMUX_IRQ(EXT_IRQ(30), PORT27_FN0), ++ PINMUX_IRQ(EXT_IRQ(29), PORT28_FN0), ++ PINMUX_IRQ(EXT_IRQ(22), PORT40_FN0), ++ PINMUX_IRQ(EXT_IRQ(23), PORT53_FN0), ++ PINMUX_IRQ(EXT_IRQ(10), PORT54_FN0), ++ PINMUX_IRQ(EXT_IRQ(9), PORT56_FN0), ++ PINMUX_IRQ(EXT_IRQ(26), PORT115_FN0), ++ PINMUX_IRQ(EXT_IRQ(27), PORT116_FN0), ++ PINMUX_IRQ(EXT_IRQ(28), PORT117_FN0), ++ PINMUX_IRQ(EXT_IRQ(24), PORT118_FN0), ++ PINMUX_IRQ(EXT_IRQ(6), PORT147_FN0), ++ PINMUX_IRQ(EXT_IRQ(2), PORT149_FN0), ++ PINMUX_IRQ(EXT_IRQ(7), PORT150_FN0), ++ PINMUX_IRQ(EXT_IRQ(12), PORT156_FN0), ++ PINMUX_IRQ(EXT_IRQ(4), PORT159_FN0), ++ PINMUX_IRQ(EXT_IRQ(25), PORT164_FN0), ++ PINMUX_IRQ(EXT_IRQ(8), PORT223_FN0), ++ PINMUX_IRQ(EXT_IRQ(3), PORT224_FN0), ++ PINMUX_IRQ(EXT_IRQ(5), PORT227_FN0), ++ PINMUX_IRQ(EXT_IRQ(17), PORT234_FN0), ++ PINMUX_IRQ(EXT_IRQ(11), PORT238_FN0), ++ PINMUX_IRQ(EXT_IRQ(13), PORT239_FN0), ++ PINMUX_IRQ(EXT_IRQ(16), PORT249_FN0), ++ PINMUX_IRQ(EXT_IRQ(14), PORT251_FN0), ++ PINMUX_IRQ(EXT_IRQ(9), PORT308_FN0), ++}; ++ + static struct pinmux_info sh73a0_pinmux_info = { + .name = "sh73a0_pfc", + .reserved_id = PINMUX_RESERVED, +@@ -2718,6 +2756,9 @@ static struct pinmux_info sh73a0_pinmux_info = { + + .gpio_data = pinmux_data, + .gpio_data_size = ARRAY_SIZE(pinmux_data), ++ ++ .gpio_irq = pinmux_irqs, ++ .gpio_irq_size = ARRAY_SIZE(pinmux_irqs), + }; + + void sh73a0_pinmux_init(void) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0175-ARM-mach-shmobile-Use-common-INTC-IRQ-code-on-sh73a0.patch b/patches.kzm9g/0175-ARM-mach-shmobile-Use-common-INTC-IRQ-code-on-sh73a0.patch new file mode 100644 index 00000000000000..40dc2454aad3d4 --- /dev/null +++ b/patches.kzm9g/0175-ARM-mach-shmobile-Use-common-INTC-IRQ-code-on-sh73a0.patch @@ -0,0 +1,259 @@ +From 3c8de348dc6f41d179ea079f2530837ce0808d97 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Wed, 12 Oct 2011 16:21:42 +0900 +Subject: ARM: mach-shmobile: Use common INTC IRQ code on sh73a0 + +Improve IRQ triggering support by making use of the macro +INTC_IRQ_PINS_32() for INTCA on sh73a0. Unfortunately it +is not as easy as just using the macro as-is, we need to +do mask and unmaks in the GIC but configure other bits +and ack in INTCA. Update GPIO IRQ mappings while at it. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit a1993055efcc14fd6d213b936d28a41ea52e1d3d) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/intc-sh73a0.c | 122 +++++++++++++++++++++++++++++++++++ + arch/arm/mach-shmobile/pfc-sh73a0.c | 68 +++++++++---------- + 2 files changed, 157 insertions(+), 33 deletions(-) + +diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c +index a911a60..836e815 100644 +--- a/arch/arm/mach-shmobile/intc-sh73a0.c ++++ b/arch/arm/mach-shmobile/intc-sh73a0.c +@@ -22,6 +22,7 @@ + #include <linux/irq.h> + #include <linux/io.h> + #include <linux/sh_intc.h> ++#include <mach/intc.h> + #include <asm/hardware/gic.h> + #include <asm/mach-types.h> + #include <asm/mach/arch.h> +@@ -255,20 +256,141 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on) + return 0; /* always allow wakeup */ + } + ++#define RELOC_BASE 0x1000 ++ ++/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */ ++#define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE) ++ ++INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000, ++ INTCS_VECT_RELOC, "sh73a0-intca-irq-pins"); ++ ++static int to_gic_irq(struct irq_data *data) ++{ ++ unsigned int vect = irq2evt(data->irq) - INTCS_VECT_BASE; ++ ++ if (vect >= 0x3200) ++ vect -= 0x3000; ++ else ++ vect -= 0x0200; ++ ++ return gic_spi((vect >> 5) + 1); ++} ++ ++static int to_intca_reloc_irq(struct irq_data *data) ++{ ++ return data->irq + (RELOC_BASE >> 5); ++} ++ ++#define irq_cb(cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq)) ++#define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p) ++ ++static void intca_gic_enable(struct irq_data *data) ++{ ++ irq_cb(irq_unmask, to_intca_reloc_irq(data)); ++ irq_cb(irq_unmask, to_gic_irq(data)); ++} ++ ++static void intca_gic_disable(struct irq_data *data) ++{ ++ irq_cb(irq_mask, to_gic_irq(data)); ++ irq_cb(irq_mask, to_intca_reloc_irq(data)); ++} ++ ++static void intca_gic_mask_ack(struct irq_data *data) ++{ ++ irq_cb(irq_mask, to_gic_irq(data)); ++ irq_cb(irq_mask_ack, to_intca_reloc_irq(data)); ++} ++ ++static void intca_gic_eoi(struct irq_data *data) ++{ ++ irq_cb(irq_eoi, to_gic_irq(data)); ++} ++ ++static int intca_gic_set_type(struct irq_data *data, unsigned int type) ++{ ++ return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type); ++} ++ ++static int intca_gic_set_wake(struct irq_data *data, unsigned int on) ++{ ++ return irq_cbp(irq_set_wake, to_intca_reloc_irq(data), on); ++} ++ ++#ifdef CONFIG_SMP ++static int intca_gic_set_affinity(struct irq_data *data, ++ const struct cpumask *cpumask, ++ bool force) ++{ ++ return irq_cbp(irq_set_affinity, to_gic_irq(data), cpumask, force); ++} ++#endif ++ ++struct irq_chip intca_gic_irq_chip = { ++ .name = "INTCA-GIC", ++ .irq_mask = intca_gic_disable, ++ .irq_unmask = intca_gic_enable, ++ .irq_mask_ack = intca_gic_mask_ack, ++ .irq_eoi = intca_gic_eoi, ++ .irq_enable = intca_gic_enable, ++ .irq_disable = intca_gic_disable, ++ .irq_shutdown = intca_gic_disable, ++ .irq_set_type = intca_gic_set_type, ++ .irq_set_wake = intca_gic_set_wake, ++#ifdef CONFIG_SMP ++ .irq_set_affinity = intca_gic_set_affinity, ++#endif ++}; ++ ++static int to_intc_vect(int irq) ++{ ++ unsigned int irq_pin = irq - gic_spi(1); ++ unsigned int offs; ++ ++ if (irq_pin < 16) ++ offs = 0x0200; ++ else ++ offs = 0x3000; ++ ++ return offs + (irq_pin << 5); ++} ++ ++static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id) ++{ ++ generic_handle_irq(intcs_evt2irq(to_intc_vect(irq))); ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction sh73a0_irq_pin_cascade[32]; ++ + void __init sh73a0_init_irq(void) + { + void __iomem *gic_dist_base = __io(0xf0001000); + void __iomem *gic_cpu_base = __io(0xf0000100); + void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); ++ int k, n; + + gic_init(0, 29, gic_dist_base, gic_cpu_base); + gic_arch_extn.irq_set_wake = sh73a0_set_wake; + + register_intc_controller(&intcs_desc); ++ register_intc_controller(&intca_irq_pins_desc); + + /* demux using INTEVTSA */ + sh73a0_intcs_cascade.name = "INTCS cascade"; + sh73a0_intcs_cascade.handler = sh73a0_intcs_demux; + sh73a0_intcs_cascade.dev_id = intevtsa; + setup_irq(gic_spi(50), &sh73a0_intcs_cascade); ++ ++ /* IRQ pins require special handling through INTCA and GIC */ ++ for (k = 0; k < 32; k++) { ++ sh73a0_irq_pin_cascade[k].name = "INTCA-GIC cascade"; ++ sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux; ++ setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]); ++ ++ n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k))); ++ irq_set_chip_and_handler_name(n, &intca_gic_irq_chip, ++ handle_level_irq, "level"); ++ set_irq_flags(n, IRQF_VALID); /* yuck */ ++ } + } +diff --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c +index 0e24ac4..cf7c7bb 100644 +--- a/arch/arm/mach-shmobile/pfc-sh73a0.c ++++ b/arch/arm/mach-shmobile/pfc-sh73a0.c +@@ -2699,41 +2699,43 @@ static struct pinmux_data_reg pinmux_data_regs[] = { + { }, + }; + +-#define EXT_IRQ(n) gic_spi((n) + 1) /* GIC SPI starting from 1 for IRQ0 */ ++/* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */ ++#define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5)) ++#define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5)) + + static struct pinmux_irq pinmux_irqs[] = { +- PINMUX_IRQ(EXT_IRQ(19), PORT9_FN0), +- PINMUX_IRQ(EXT_IRQ(1), PORT10_FN0), +- PINMUX_IRQ(EXT_IRQ(0), PORT11_FN0), +- PINMUX_IRQ(EXT_IRQ(18), PORT13_FN0), +- PINMUX_IRQ(EXT_IRQ(20), PORT14_FN0), +- PINMUX_IRQ(EXT_IRQ(21), PORT15_FN0), +- PINMUX_IRQ(EXT_IRQ(31), PORT26_FN0), +- PINMUX_IRQ(EXT_IRQ(30), PORT27_FN0), +- PINMUX_IRQ(EXT_IRQ(29), PORT28_FN0), +- PINMUX_IRQ(EXT_IRQ(22), PORT40_FN0), +- PINMUX_IRQ(EXT_IRQ(23), PORT53_FN0), +- PINMUX_IRQ(EXT_IRQ(10), PORT54_FN0), +- PINMUX_IRQ(EXT_IRQ(9), PORT56_FN0), +- PINMUX_IRQ(EXT_IRQ(26), PORT115_FN0), +- PINMUX_IRQ(EXT_IRQ(27), PORT116_FN0), +- PINMUX_IRQ(EXT_IRQ(28), PORT117_FN0), +- PINMUX_IRQ(EXT_IRQ(24), PORT118_FN0), +- PINMUX_IRQ(EXT_IRQ(6), PORT147_FN0), +- PINMUX_IRQ(EXT_IRQ(2), PORT149_FN0), +- PINMUX_IRQ(EXT_IRQ(7), PORT150_FN0), +- PINMUX_IRQ(EXT_IRQ(12), PORT156_FN0), +- PINMUX_IRQ(EXT_IRQ(4), PORT159_FN0), +- PINMUX_IRQ(EXT_IRQ(25), PORT164_FN0), +- PINMUX_IRQ(EXT_IRQ(8), PORT223_FN0), +- PINMUX_IRQ(EXT_IRQ(3), PORT224_FN0), +- PINMUX_IRQ(EXT_IRQ(5), PORT227_FN0), +- PINMUX_IRQ(EXT_IRQ(17), PORT234_FN0), +- PINMUX_IRQ(EXT_IRQ(11), PORT238_FN0), +- PINMUX_IRQ(EXT_IRQ(13), PORT239_FN0), +- PINMUX_IRQ(EXT_IRQ(16), PORT249_FN0), +- PINMUX_IRQ(EXT_IRQ(14), PORT251_FN0), +- PINMUX_IRQ(EXT_IRQ(9), PORT308_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(1), PORT10_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(0), PORT11_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(18), PORT13_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(20), PORT14_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(21), PORT15_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(31), PORT26_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(30), PORT27_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(29), PORT28_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(22), PORT40_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(23), PORT53_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(10), PORT54_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(9), PORT56_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(26), PORT115_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(27), PORT116_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(28), PORT117_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(24), PORT118_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(6), PORT147_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(2), PORT149_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(7), PORT150_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(12), PORT156_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(4), PORT159_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(25), PORT164_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(8), PORT223_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(3), PORT224_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(5), PORT227_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(17), PORT234_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(11), PORT238_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(13), PORT239_FN0), ++ PINMUX_IRQ(EXT_IRQ16H(16), PORT249_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(14), PORT251_FN0), ++ PINMUX_IRQ(EXT_IRQ16L(9), PORT308_FN0), + }; + + static struct pinmux_info sh73a0_pinmux_info = { +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0176-ARM-mach-shmobile-sh73a0-and-AG5EVM-PINT-support.patch b/patches.kzm9g/0176-ARM-mach-shmobile-sh73a0-and-AG5EVM-PINT-support.patch new file mode 100644 index 00000000000000..743aebd5c9a5fb --- /dev/null +++ b/patches.kzm9g/0176-ARM-mach-shmobile-sh73a0-and-AG5EVM-PINT-support.patch @@ -0,0 +1,174 @@ +From ba8cc79e847a7743d3c835c92fb2f73c32871f3d Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Mon, 17 Oct 2011 18:00:52 +0900 +Subject: ARM: mach-shmobile: sh73a0 and AG5EVM PINT support + +Support PINT on sh73a0 and AG5EVM using INTC PINT macros. + +With this patch applied the AG5EVM ethernet is handled +through one of the chained sh73a0 PINT interrupt controllers. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 566aad39df77211467078e0b3dcd62100f56b5e4) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-ag5evm.c | 17 +------- + arch/arm/mach-shmobile/include/mach/sh73a0.h | 4 ++ + arch/arm/mach-shmobile/intc-sh73a0.c | 65 ++++++++++++++++++++++++++++ + 3 files changed, 71 insertions(+), 15 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c +index f04ee16..430c723 100644 +--- a/arch/arm/mach-shmobile/board-ag5evm.c ++++ b/arch/arm/mach-shmobile/board-ag5evm.c +@@ -59,7 +59,7 @@ static struct resource smsc9220_resources[] = { + .flags = IORESOURCE_MEM, + }, + [1] = { +- .start = gic_spi(33), /* PINT1 */ ++ .start = SH73A0_PINT0_IRQ(2), /* PINTA2 */ + .flags = IORESOURCE_IRQ, + }, + }; +@@ -445,19 +445,6 @@ static void __init ag5evm_map_io(void) + shmobile_setup_console(); + } + +-#define PINTC_ADDR 0xe6900000 +-#define PINTER0A (PINTC_ADDR + 0xa0) +-#define PINTCR0A (PINTC_ADDR + 0xb0) +- +-void __init ag5evm_init_irq(void) +-{ +- sh73a0_init_irq(); +- +- /* setup PINT: enable PINTA2 as active low */ +- __raw_writel(__raw_readl(PINTER0A) | (1<<29), PINTER0A); +- __raw_writew(__raw_readw(PINTCR0A) | (2<<10), PINTCR0A); +-} +- + #define DSI0PHYCR 0xe615006c + + static void __init ag5evm_init(void) +@@ -584,7 +571,7 @@ struct sys_timer ag5evm_timer = { + + MACHINE_START(AG5EVM, "ag5evm") + .map_io = ag5evm_map_io, +- .init_irq = ag5evm_init_irq, ++ .init_irq = sh73a0_init_irq, + .handle_irq = shmobile_handle_irq_gic, + .init_machine = ag5evm_init, + .timer = &ag5evm_timer, +diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h +index b385e97..18ae6a9 100644 +--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h ++++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h +@@ -507,4 +507,8 @@ enum { + SHDMA_SLAVE_MMCIF_RX, + }; + ++/* PINT interrupts are located at Linux IRQ 768 and up */ ++#define SH73A0_PINT0_IRQ(irq) ((irq) + 768) ++#define SH73A0_PINT1_IRQ(irq) ((irq) + 800) ++ + #endif /* __ASM_SH73A0_H__ */ +diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c +index 836e815..1eda6b0 100644 +--- a/arch/arm/mach-shmobile/intc-sh73a0.c ++++ b/arch/arm/mach-shmobile/intc-sh73a0.c +@@ -23,6 +23,7 @@ + #include <linux/io.h> + #include <linux/sh_intc.h> + #include <mach/intc.h> ++#include <mach/sh73a0.h> + #include <asm/hardware/gic.h> + #include <asm/mach-types.h> + #include <asm/mach/arch.h> +@@ -363,6 +364,59 @@ static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id) + + static struct irqaction sh73a0_irq_pin_cascade[32]; + ++#define PINTER0 0xe69000a0 ++#define PINTER1 0xe69000a4 ++#define PINTRR0 0xe69000d0 ++#define PINTRR1 0xe69000d4 ++ ++#define PINT0A_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq)) ++#define PINT0B_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 8)) ++#define PINT0C_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 16)) ++#define PINT0D_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 24)) ++#define PINT1E_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT1_IRQ(irq)) ++ ++INTC_PINT(intc_pint0, PINTER0, 0xe69000b0, "sh73a0-pint0", \ ++ INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D), \ ++ INTC_PINT_V(A, PINT0A_IRQ), INTC_PINT_V(B, PINT0B_IRQ), \ ++ INTC_PINT_V(C, PINT0C_IRQ), INTC_PINT_V(D, PINT0D_IRQ), \ ++ INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D), \ ++ INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D)); ++ ++INTC_PINT(intc_pint1, PINTER1, 0xe69000c0, "sh73a0-pint1", \ ++ INTC_PINT_E(E), INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, \ ++ INTC_PINT_V(E, PINT1E_IRQ), INTC_PINT_V_NONE, \ ++ INTC_PINT_V_NONE, INTC_PINT_V_NONE, \ ++ INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E(E), \ ++ INTC_PINT_E(E), INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE); ++ ++static struct irqaction sh73a0_pint0_cascade; ++static struct irqaction sh73a0_pint1_cascade; ++ ++static void pint_demux(unsigned long rr, unsigned long er, int base_irq) ++{ ++ unsigned long value = ioread32(rr) & ioread32(er); ++ int k; ++ ++ for (k = 0; k < 32; k++) { ++ if (value & (1 << (31 - k))) { ++ generic_handle_irq(base_irq + k); ++ iowrite32(~(1 << (31 - k)), rr); ++ } ++ } ++} ++ ++static irqreturn_t sh73a0_pint0_demux(int irq, void *dev_id) ++{ ++ pint_demux(PINTRR0, PINTER0, SH73A0_PINT0_IRQ(0)); ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t sh73a0_pint1_demux(int irq, void *dev_id) ++{ ++ pint_demux(PINTRR1, PINTER1, SH73A0_PINT1_IRQ(0)); ++ return IRQ_HANDLED; ++} ++ + void __init sh73a0_init_irq(void) + { + void __iomem *gic_dist_base = __io(0xf0001000); +@@ -375,6 +429,8 @@ void __init sh73a0_init_irq(void) + + register_intc_controller(&intcs_desc); + register_intc_controller(&intca_irq_pins_desc); ++ register_intc_controller(&intc_pint0_desc); ++ register_intc_controller(&intc_pint1_desc); + + /* demux using INTEVTSA */ + sh73a0_intcs_cascade.name = "INTCS cascade"; +@@ -393,4 +449,13 @@ void __init sh73a0_init_irq(void) + handle_level_irq, "level"); + set_irq_flags(n, IRQF_VALID); /* yuck */ + } ++ ++ /* PINT pins are sanely tied to the GIC as SPI */ ++ sh73a0_pint0_cascade.name = "PINT0 cascade"; ++ sh73a0_pint0_cascade.handler = sh73a0_pint0_demux; ++ setup_irq(gic_spi(33), &sh73a0_pint0_cascade); ++ ++ sh73a0_pint1_cascade.name = "PINT1 cascade"; ++ sh73a0_pint1_cascade.handler = sh73a0_pint1_demux; ++ setup_irq(gic_spi(34), &sh73a0_pint1_cascade); + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0177-ARM-mach-shmobile-Kota2-TPU-LED-platform-data.patch b/patches.kzm9g/0177-ARM-mach-shmobile-Kota2-TPU-LED-platform-data.patch new file mode 100644 index 00000000000000..fa192b7c37d745 --- /dev/null +++ b/patches.kzm9g/0177-ARM-mach-shmobile-Kota2-TPU-LED-platform-data.patch @@ -0,0 +1,88 @@ +From 9335e7d7f5827af9446ac83c09eef75942d2cc90 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Tue, 22 Nov 2011 15:44:58 +0900 +Subject: ARM: mach-shmobile: Kota2 TPU LED platform data + +This patch updates the Kota2 board support code to +use the recently merged TPU LED driver whenever +possible. + +The sh73a0 SoC has 5 TPU hardware blocks each with +4 timer channels which in theory allows a total of +20 LEDs to be controlled by "leds-renesas-tpu" +driver instances. The Kota2 board has 4 LEDs connected +to GPIO pins that also come with TPU pin functions, so +this patch ties up these 4 LEDS and leaves the remaining +3 LEDS for the GPIO based LED driver. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 33661c9e2062865acde9d421c971f1c142cf99ca) + +Conflicts: + + arch/arm/mach-shmobile/board-kota2.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-sh73a0.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c +index 44a923d..7df1f11 100644 +--- a/arch/arm/mach-shmobile/clock-sh73a0.c ++++ b/arch/arm/mach-shmobile/clock-sh73a0.c +@@ -113,6 +113,12 @@ static struct clk main_clk = { + .ops = &main_clk_ops, + }; + ++/* Divide Main clock by two */ ++static struct clk main_div2_clk = { ++ .ops = &div2_clk_ops, ++ .parent = &main_clk, ++}; ++ + /* PLL0, PLL1, PLL2, PLL3 */ + static unsigned long pll_recalc(struct clk *clk) + { +@@ -181,6 +187,7 @@ static struct clk *main_clks[] = { + &extal1_div2_clk, + &extal2_div2_clk, + &main_clk, ++ &main_div2_clk, + &pll0_clk, + &pll1_clk, + &pll2_clk, +@@ -268,6 +275,7 @@ enum { MSTP001, + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + MSTP331, MSTP329, MSTP325, MSTP323, MSTP318, + MSTP314, MSTP313, MSTP312, MSTP311, ++ MSTP303, MSTP302, MSTP301, MSTP300, + MSTP411, MSTP410, MSTP403, + MSTP_NR }; + +@@ -301,6 +309,10 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */ + [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */ + [MSTP311] = MSTP(&div6_clks[DIV6_SDHI2], SMSTPCR3, 11, 0), /* SDHI2 */ ++ [MSTP303] = MSTP(&main_div2_clk, SMSTPCR3, 3, 0), /* TPU1 */ ++ [MSTP302] = MSTP(&main_div2_clk, SMSTPCR3, 2, 0), /* TPU2 */ ++ [MSTP301] = MSTP(&main_div2_clk, SMSTPCR3, 1, 0), /* TPU3 */ ++ [MSTP300] = MSTP(&main_div2_clk, SMSTPCR3, 0, 0), /* TPU4 */ + [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */ + [MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */ + [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ +@@ -350,6 +362,10 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ + CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ + CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */ ++ CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */ ++ CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */ ++ CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */ ++ CLKDEV_DEV_ID("leds-renesas-tpu.41", &mstp_clks[MSTP300]), /* TPU4 */ + CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */ + CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */ + CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0178-ARM-mach-shmobile-SH73A0-external-Ethernet-fix.patch b/patches.kzm9g/0178-ARM-mach-shmobile-SH73A0-external-Ethernet-fix.patch new file mode 100644 index 00000000000000..1b5f95e33a0a48 --- /dev/null +++ b/patches.kzm9g/0178-ARM-mach-shmobile-SH73A0-external-Ethernet-fix.patch @@ -0,0 +1,38 @@ +From 1eb5e4702a14dfefa6593c24c5bea8c6d3184407 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Tue, 22 Nov 2011 15:23:17 +0900 +Subject: ARM: mach-shmobile: SH73A0 external Ethernet fix + +Keep the ZB clock enabled on sh73a0 to allow the BSC +to access external peripherals hooked up to CS signals. + +This is needed to unbreak Ethernet support on sh73a0 boards +such as AG5EVM and Kota2 together with the following patch: + + 794d78f drivers: sh: late disabling of clocks V2 + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 9bcc0a5d0de137b3a154dc951c5ff70dce815879) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-sh73a0.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c +index 7df1f11..2985363 100644 +--- a/arch/arm/mach-shmobile/clock-sh73a0.c ++++ b/arch/arm/mach-shmobile/clock-sh73a0.c +@@ -250,7 +250,7 @@ static struct clk div6_clks[DIV6_NR] = { + [DIV6_VCK1] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR1, 0), + [DIV6_VCK2] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR2, 0), + [DIV6_VCK3] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR3, 0), +- [DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, 0), ++ [DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, CLK_ENABLE_ON_INIT), + [DIV6_FLCTL] = SH_CLK_DIV6(&pll1_div2_clk, FLCKCR, 0), + [DIV6_SDHI0] = SH_CLK_DIV6(&pll1_div2_clk, SD0CKCR, 0), + [DIV6_SDHI1] = SH_CLK_DIV6(&pll1_div2_clk, SD1CKCR, 0), +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0179-sh-clkfwk-clock-sh73a0-all-div6_clks-use-SH_CLK_DIV6.patch b/patches.kzm9g/0179-sh-clkfwk-clock-sh73a0-all-div6_clks-use-SH_CLK_DIV6.patch new file mode 100644 index 00000000000000..ac00157228b01d --- /dev/null +++ b/patches.kzm9g/0179-sh-clkfwk-clock-sh73a0-all-div6_clks-use-SH_CLK_DIV6.patch @@ -0,0 +1,233 @@ +From bad42bcc41d498bed5fd01177b1073d32e551584 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 5 Dec 2011 22:29:15 -0800 +Subject: sh: clkfwk: clock-sh73a0: all div6_clks use SH_CLK_DIV6_EXT() + +Current div6 clocks can specify their current parent clocks +from its register value if it is registered +by sh_clk_div6_reparent_register(). +This patch modifies all div6 clocks into SH_CLK_DIV6_EXT(). + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit d4775356bb39eaa305844cc6cc4c267236535956) + +Conflicts: + + arch/arm/mach-shmobile/clock-sh73a0.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-sh73a0.c | 141 ++++++++++++++++++++++----- + arch/arm/mach-shmobile/include/mach/common.h | 2 + + 2 files changed, 120 insertions(+), 23 deletions(-) + +diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c +index 2985363..462a964 100644 +--- a/arch/arm/mach-shmobile/clock-sh73a0.c ++++ b/arch/arm/mach-shmobile/clock-sh73a0.c +@@ -92,6 +92,24 @@ static struct clk_ops div2_clk_ops = { + .recalc = div2_recalc, + }; + ++static unsigned long div7_recalc(struct clk *clk) ++{ ++ return clk->parent->rate / 7; ++} ++ ++static struct clk_ops div7_clk_ops = { ++ .recalc = div7_recalc, ++}; ++ ++static unsigned long div13_recalc(struct clk *clk) ++{ ++ return clk->parent->rate / 13; ++} ++ ++static struct clk_ops div13_clk_ops = { ++ .recalc = div13_recalc, ++}; ++ + /* Divide extal1 by two */ + static struct clk extal1_div2_clk = { + .ops = &div2_clk_ops, +@@ -113,7 +131,6 @@ static struct clk main_clk = { + .ops = &main_clk_ops, + }; + +-/* Divide Main clock by two */ + static struct clk main_div2_clk = { + .ops = &div2_clk_ops, + .parent = &main_clk, +@@ -174,12 +191,29 @@ static struct clk pll3_clk = { + .enable_bit = 3, + }; + +-/* Divide PLL1 by two */ ++/* Divide PLL */ + static struct clk pll1_div2_clk = { + .ops = &div2_clk_ops, + .parent = &pll1_clk, + }; + ++static struct clk pll1_div7_clk = { ++ .ops = &div7_clk_ops, ++ .parent = &pll1_clk, ++}; ++ ++static struct clk pll1_div13_clk = { ++ .ops = &div13_clk_ops, ++ .parent = &pll1_clk, ++}; ++ ++/* External input clock */ ++struct clk sh73a0_extcki_clk = { ++}; ++ ++struct clk sh73a0_extalr_clk = { ++}; ++ + static struct clk *main_clks[] = { + &r_clk, + &sh73a0_extal1_clk, +@@ -193,6 +227,10 @@ static struct clk *main_clks[] = { + &pll2_clk, + &pll3_clk, + &pll1_div2_clk, ++ &pll1_div7_clk, ++ &pll1_div13_clk, ++ &sh73a0_extcki_clk, ++ &sh73a0_extalr_clk, + }; + + static void div4_kick(struct clk *clk) +@@ -246,27 +284,84 @@ enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1, + DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P, + DIV6_NR }; + ++static struct clk *vck_parent[8] = { ++ [0] = &pll1_div2_clk, ++ [1] = &pll2_clk, ++ [2] = &sh73a0_extcki_clk, ++ [3] = &sh73a0_extal2_clk, ++ [4] = &main_div2_clk, ++ [5] = &sh73a0_extalr_clk, ++ [6] = &main_clk, ++}; ++ ++static struct clk *pll_parent[4] = { ++ [0] = &pll1_div2_clk, ++ [1] = &pll2_clk, ++ [2] = &pll1_div13_clk, ++}; ++ ++static struct clk *hsi_parent[4] = { ++ [0] = &pll1_div2_clk, ++ [1] = &pll2_clk, ++ [2] = &pll1_div7_clk, ++}; ++ ++static struct clk *pll_extal2_parent[] = { ++ [0] = &pll1_div2_clk, ++ [1] = &pll2_clk, ++ [2] = &sh73a0_extal2_clk, ++ [3] = &sh73a0_extal2_clk, ++}; ++ ++static struct clk *dsi_parent[8] = { ++ [0] = &pll1_div2_clk, ++ [1] = &pll2_clk, ++ [2] = &main_clk, ++ [3] = &sh73a0_extal2_clk, ++ [4] = &sh73a0_extcki_clk, ++}; ++ + static struct clk div6_clks[DIV6_NR] = { +- [DIV6_VCK1] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR1, 0), +- [DIV6_VCK2] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR2, 0), +- [DIV6_VCK3] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR3, 0), +- [DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, CLK_ENABLE_ON_INIT), +- [DIV6_FLCTL] = SH_CLK_DIV6(&pll1_div2_clk, FLCKCR, 0), +- [DIV6_SDHI0] = SH_CLK_DIV6(&pll1_div2_clk, SD0CKCR, 0), +- [DIV6_SDHI1] = SH_CLK_DIV6(&pll1_div2_clk, SD1CKCR, 0), +- [DIV6_SDHI2] = SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0), +- [DIV6_FSIA] = SH_CLK_DIV6(&pll1_div2_clk, FSIACKCR, 0), +- [DIV6_FSIB] = SH_CLK_DIV6(&pll1_div2_clk, FSIBCKCR, 0), +- [DIV6_SUB] = SH_CLK_DIV6(&sh73a0_extal2_clk, SUBCKCR, 0), +- [DIV6_SPUA] = SH_CLK_DIV6(&pll1_div2_clk, SPUACKCR, 0), +- [DIV6_SPUV] = SH_CLK_DIV6(&pll1_div2_clk, SPUVCKCR, 0), +- [DIV6_MSU] = SH_CLK_DIV6(&pll1_div2_clk, MSUCKCR, 0), +- [DIV6_HSI] = SH_CLK_DIV6(&pll1_div2_clk, HSICKCR, 0), +- [DIV6_MFG1] = SH_CLK_DIV6(&pll1_div2_clk, MFCK1CR, 0), +- [DIV6_MFG2] = SH_CLK_DIV6(&pll1_div2_clk, MFCK2CR, 0), +- [DIV6_DSIT] = SH_CLK_DIV6(&pll1_div2_clk, DSITCKCR, 0), +- [DIV6_DSI0P] = SH_CLK_DIV6(&pll1_div2_clk, DSI0PCKCR, 0), +- [DIV6_DSI1P] = SH_CLK_DIV6(&pll1_div2_clk, DSI1PCKCR, 0), ++ [DIV6_VCK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0, ++ vck_parent, ARRAY_SIZE(vck_parent), 12, 3), ++ [DIV6_VCK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0, ++ vck_parent, ARRAY_SIZE(vck_parent), 12, 3), ++ [DIV6_VCK3] = SH_CLK_DIV6_EXT(VCLKCR3, 0, ++ vck_parent, ARRAY_SIZE(vck_parent), 12, 3), ++ [DIV6_ZB1] = SH_CLK_DIV6_EXT(ZBCKCR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 7, 1), ++ [DIV6_FLCTL] = SH_CLK_DIV6_EXT(FLCKCR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 7, 1), ++ [DIV6_SDHI0] = SH_CLK_DIV6_EXT(SD0CKCR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 6, 2), ++ [DIV6_SDHI1] = SH_CLK_DIV6_EXT(SD1CKCR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 6, 2), ++ [DIV6_SDHI2] = SH_CLK_DIV6_EXT(SD2CKCR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 6, 2), ++ [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 6, 1), ++ [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 6, 1), ++ [DIV6_SUB] = SH_CLK_DIV6_EXT(SUBCKCR, 0, ++ pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2), ++ [DIV6_SPUA] = SH_CLK_DIV6_EXT(SPUACKCR, 0, ++ pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2), ++ [DIV6_SPUV] = SH_CLK_DIV6_EXT(SPUVCKCR, 0, ++ pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2), ++ [DIV6_MSU] = SH_CLK_DIV6_EXT(MSUCKCR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 7, 1), ++ [DIV6_HSI] = SH_CLK_DIV6_EXT(HSICKCR, 0, ++ hsi_parent, ARRAY_SIZE(hsi_parent), 6, 2), ++ [DIV6_MFG1] = SH_CLK_DIV6_EXT(MFCK1CR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 7, 1), ++ [DIV6_MFG2] = SH_CLK_DIV6_EXT(MFCK2CR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 7, 1), ++ [DIV6_DSIT] = SH_CLK_DIV6_EXT(DSITCKCR, 0, ++ pll_parent, ARRAY_SIZE(pll_parent), 7, 1), ++ [DIV6_DSI0P] = SH_CLK_DIV6_EXT(DSI0PCKCR, 0, ++ dsi_parent, ARRAY_SIZE(dsi_parent), 12, 3), ++ [DIV6_DSI1P] = SH_CLK_DIV6_EXT(DSI1PCKCR, 0, ++ dsi_parent, ARRAY_SIZE(dsi_parent), 12, 3), + }; + + enum { MSTP001, +@@ -403,7 +498,7 @@ void __init sh73a0_clock_init(void) + ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); + + if (!ret) +- ret = sh_clk_div6_register(div6_clks, DIV6_NR); ++ ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR); + + if (!ret) + ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); +diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h +index 2e21a77..6ccc1a5 100644 +--- a/arch/arm/mach-shmobile/include/mach/common.h ++++ b/arch/arm/mach-shmobile/include/mach/common.h +@@ -48,6 +48,8 @@ extern void sh73a0_clock_init(void); + extern void sh73a0_pinmux_init(void); + extern struct clk sh73a0_extal1_clk; + extern struct clk sh73a0_extal2_clk; ++extern struct clk sh73a0_extcki_clk; ++extern struct clk sh73a0_extalr_clk; + + extern unsigned int sh73a0_get_core_count(void); + extern void sh73a0_secondary_init(unsigned int cpu); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0180-arm-mach-shmobile-add-a-resource-name-for-shdma.patch b/patches.kzm9g/0180-arm-mach-shmobile-add-a-resource-name-for-shdma.patch new file mode 100644 index 00000000000000..df953d69a43572 --- /dev/null +++ b/patches.kzm9g/0180-arm-mach-shmobile-add-a-resource-name-for-shdma.patch @@ -0,0 +1,62 @@ +From 40c376c78cee48972ac8e0486c07f5908c96bc32 Mon Sep 17 00:00:00 2001 +From: "Shimoda, Yoshihiro" <yoshihiro.shimoda.uh@renesas.com> +Date: Tue, 10 Jan 2012 14:21:31 +0900 +Subject: arm: mach-shmobile: add a resource name for shdma + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 20052462948795914011f2fea0e77767d55cb48b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/setup-sh7372.c | 6 +++--- + arch/arm/mach-shmobile/setup-sh73a0.c | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c +index cd807ee..8ddef91 100644 +--- a/arch/arm/mach-shmobile/setup-sh7372.c ++++ b/arch/arm/mach-shmobile/setup-sh7372.c +@@ -503,7 +503,7 @@ static struct resource sh7372_dmae0_resources[] = { + .flags = IORESOURCE_MEM, + }, + { +- /* DMA error IRQ */ ++ .name = "error_irq", + .start = evt2irq(0x20c0), + .end = evt2irq(0x20c0), + .flags = IORESOURCE_IRQ, +@@ -531,7 +531,7 @@ static struct resource sh7372_dmae1_resources[] = { + .flags = IORESOURCE_MEM, + }, + { +- /* DMA error IRQ */ ++ .name = "error_irq", + .start = evt2irq(0x21c0), + .end = evt2irq(0x21c0), + .flags = IORESOURCE_IRQ, +@@ -559,7 +559,7 @@ static struct resource sh7372_dmae2_resources[] = { + .flags = IORESOURCE_MEM, + }, + { +- /* DMA error IRQ */ ++ .name = "error_irq", + .start = evt2irq(0x22c0), + .end = evt2irq(0x22c0), + .flags = IORESOURCE_IRQ, +diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c +index e46821c..20e71e5 100644 +--- a/arch/arm/mach-shmobile/setup-sh73a0.c ++++ b/arch/arm/mach-shmobile/setup-sh73a0.c +@@ -607,7 +607,7 @@ static struct resource sh73a0_dmae_resources[] = { + .flags = IORESOURCE_MEM, + }, + { +- /* DMA error IRQ */ ++ .name = "error_irq", + .start = gic_spi(129), + .end = gic_spi(129), + .flags = IORESOURCE_IRQ, +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0181-ARM-mach-shmobile-sh73a0-PINT-IRQ-base-fix.patch b/patches.kzm9g/0181-ARM-mach-shmobile-sh73a0-PINT-IRQ-base-fix.patch new file mode 100644 index 00000000000000..664a4e23ed16ab --- /dev/null +++ b/patches.kzm9g/0181-ARM-mach-shmobile-sh73a0-PINT-IRQ-base-fix.patch @@ -0,0 +1,39 @@ +From 4e5dece84e3d3a529290121151c5acddcdf54c2f Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Tue, 17 Jan 2012 20:05:40 +0900 +Subject: ARM: mach-shmobile: sh73a0 PINT IRQ base fix + +Bump up the sh73a0 PINT IRQ base from 768 to 800 to avoid +collision with INTCS vectors for IRQ16->IRQ32 at 0x3xxx. + +Without this fix the sh73a0 IRQ pin handling code collides +with the PINT code which results in hangs on Kota2 during boot. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 0df1a838d678fc6ab49f983a19e905f6a42297a0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/sh73a0.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h +index 18ae6a9..8567d65 100644 +--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h ++++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h +@@ -507,8 +507,8 @@ enum { + SHDMA_SLAVE_MMCIF_RX, + }; + +-/* PINT interrupts are located at Linux IRQ 768 and up */ +-#define SH73A0_PINT0_IRQ(irq) ((irq) + 768) +-#define SH73A0_PINT1_IRQ(irq) ((irq) + 800) ++/* PINT interrupts are located at Linux IRQ 800 and up */ ++#define SH73A0_PINT0_IRQ(irq) ((irq) + 800) ++#define SH73A0_PINT1_IRQ(irq) ((irq) + 832) + + #endif /* __ASM_SH73A0_H__ */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0182-ARM-mach-shmobile-sh73a0-IRQ-sparse-alloc-fix.patch b/patches.kzm9g/0182-ARM-mach-shmobile-sh73a0-IRQ-sparse-alloc-fix.patch new file mode 100644 index 00000000000000..7728a5fe6f71b7 --- /dev/null +++ b/patches.kzm9g/0182-ARM-mach-shmobile-sh73a0-IRQ-sparse-alloc-fix.patch @@ -0,0 +1,44 @@ +From 10188333a01d34499c18ef18f31d7d44fcd1cd83 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Tue, 17 Jan 2012 20:10:49 +0900 +Subject: ARM: mach-shmobile: sh73a0 IRQ sparse alloc fix + +Fix the sh73a0 external IRQ pin code to properly support +CONFIG_SPARSE_IRQ=y by allocating IRQ descriptors for the +cascaded IRQs associated with external IRQ pins. + +Without this fix it is impossible to request IRQ0->IRQ31 +on the Kota2 board when sparse IRQs are enabled. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit e2c31b3fdd48274e9deb450e21279e54dfa02ccd) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/intc-sh73a0.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c +index 1eda6b0..9857595 100644 +--- a/arch/arm/mach-shmobile/intc-sh73a0.c ++++ b/arch/arm/mach-shmobile/intc-sh73a0.c +@@ -19,6 +19,7 @@ + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/interrupt.h> ++#include <linux/module.h> + #include <linux/irq.h> + #include <linux/io.h> + #include <linux/sh_intc.h> +@@ -445,6 +446,7 @@ void __init sh73a0_init_irq(void) + setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]); + + n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k))); ++ WARN_ON(irq_alloc_desc_at(n, numa_node_id()) != n); + irq_set_chip_and_handler_name(n, &intca_gic_irq_chip, + handle_level_irq, "level"); + set_irq_flags(n, IRQF_VALID); /* yuck */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0183-ARM-mach-shmobile-clock-sh73a0-add-DSIxPHY-clock-sup.patch b/patches.kzm9g/0183-ARM-mach-shmobile-clock-sh73a0-add-DSIxPHY-clock-sup.patch new file mode 100644 index 00000000000000..6fa182efb75a9b --- /dev/null +++ b/patches.kzm9g/0183-ARM-mach-shmobile-clock-sh73a0-add-DSIxPHY-clock-sup.patch @@ -0,0 +1,159 @@ +From 90907d664dd2f682cef86afd0ebe8f638f20d01c Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 22 Jan 2012 21:10:02 -0800 +Subject: ARM: mach-shmobile: clock-sh73a0: add DSIxPHY clock support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit f5948bac5f22e7697fc782e45bdca20a27368512) + +Conflicts: + + arch/arm/mach-shmobile/board-ag5evm.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-sh73a0.c | 113 ++++++++++++++++++++++++++++++++++ + 1 file changed, 113 insertions(+) + +diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c +index 462a964..4d8d140 100644 +--- a/arch/arm/mach-shmobile/clock-sh73a0.c ++++ b/arch/arm/mach-shmobile/clock-sh73a0.c +@@ -364,6 +364,114 @@ static struct clk div6_clks[DIV6_NR] = { + dsi_parent, ARRAY_SIZE(dsi_parent), 12, 3), + }; + ++/* DSI DIV */ ++static unsigned long dsiphy_recalc(struct clk *clk) ++{ ++ u32 value; ++ ++ value = __raw_readl(clk->mapping->base); ++ ++ /* FIXME */ ++ if (!(value & 0x000B8000)) ++ return clk->parent->rate; ++ ++ value &= 0x3f; ++ value += 1; ++ ++ if ((value < 12) || ++ (value > 33)) { ++ pr_err("DSIPHY has wrong value (%d)", value); ++ return 0; ++ } ++ ++ return clk->parent->rate / value; ++} ++ ++static long dsiphy_round_rate(struct clk *clk, unsigned long rate) ++{ ++ return clk_rate_mult_range_round(clk, 12, 33, rate); ++} ++ ++static void dsiphy_disable(struct clk *clk) ++{ ++ u32 value; ++ ++ value = __raw_readl(clk->mapping->base); ++ value &= ~0x000B8000; ++ ++ __raw_writel(value , clk->mapping->base); ++} ++ ++static int dsiphy_enable(struct clk *clk) ++{ ++ u32 value; ++ int multi; ++ ++ value = __raw_readl(clk->mapping->base); ++ multi = (value & 0x3f) + 1; ++ ++ if ((multi < 12) || (multi > 33)) ++ return -EIO; ++ ++ __raw_writel(value | 0x000B8000, clk->mapping->base); ++ ++ return 0; ++} ++ ++static int dsiphy_set_rate(struct clk *clk, unsigned long rate) ++{ ++ u32 value; ++ int idx; ++ ++ idx = rate / clk->parent->rate; ++ if ((idx < 12) || (idx > 33)) ++ return -EINVAL; ++ ++ idx += -1; ++ ++ value = __raw_readl(clk->mapping->base); ++ value = (value & ~0x3f) + idx; ++ ++ __raw_writel(value, clk->mapping->base); ++ ++ return 0; ++} ++ ++static struct clk_ops dsiphy_clk_ops = { ++ .recalc = dsiphy_recalc, ++ .round_rate = dsiphy_round_rate, ++ .set_rate = dsiphy_set_rate, ++ .enable = dsiphy_enable, ++ .disable = dsiphy_disable, ++}; ++ ++static struct clk_mapping dsi0phy_clk_mapping = { ++ .phys = DSI0PHYCR, ++ .len = 4, ++}; ++ ++static struct clk_mapping dsi1phy_clk_mapping = { ++ .phys = DSI1PHYCR, ++ .len = 4, ++}; ++ ++static struct clk dsi0phy_clk = { ++ .ops = &dsiphy_clk_ops, ++ .parent = &div6_clks[DIV6_DSI0P], /* late install */ ++ .mapping = &dsi0phy_clk_mapping, ++}; ++ ++static struct clk dsi1phy_clk = { ++ .ops = &dsiphy_clk_ops, ++ .parent = &div6_clks[DIV6_DSI1P], /* late install */ ++ .mapping = &dsi1phy_clk_mapping, ++}; ++ ++static struct clk *late_main_clks[] = { ++ &dsi0phy_clk, ++ &dsi1phy_clk, ++}; ++ + enum { MSTP001, + MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100, + MSTP219, +@@ -428,6 +536,8 @@ static struct clk_lookup lookups[] = { + CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), ++ CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.0", &dsi0phy_clk), ++ CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.1", &dsi1phy_clk), + + /* MSTP32 clocks */ + CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */ +@@ -503,6 +613,9 @@ void __init sh73a0_clock_init(void) + if (!ret) + ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ++ for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) ++ ret = clk_register(late_main_clks[k]); ++ + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + if (!ret) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0184-ARM-shmobile-remove-NR_IRQS.patch b/patches.kzm9g/0184-ARM-shmobile-remove-NR_IRQS.patch new file mode 100644 index 00000000000000..6d89d574930bd1 --- /dev/null +++ b/patches.kzm9g/0184-ARM-shmobile-remove-NR_IRQS.patch @@ -0,0 +1,54 @@ +From c62cfb4b929686d7bf2c9854d00677c2e9448648 Mon Sep 17 00:00:00 2001 +From: Rob Herring <rob.herring@calxeda.com> +Date: Tue, 3 Jan 2012 16:57:33 -0600 +Subject: ARM: shmobile: remove NR_IRQS + +Remove NR_IRQS and explicitly include mach/irqs.h as needed. shmobile +properly allocates irq_descs for each irqchip, so setting .nr_irqs for +each machine is not needed. + +Signed-off-by: Rob Herring <rob.herring@calxeda.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +(cherry picked from commit 250a27237e0e0694f8f8451594a0f03e0a4f5a73) + +Conflicts: + + arch/arm/mach-shmobile/board-ag5evm.c + arch/arm/mach-shmobile/board-bonito.c + arch/arm/mach-shmobile/board-g3evm.c + arch/arm/mach-shmobile/board-g4evm.c + arch/arm/mach-shmobile/board-kota2.c + arch/arm/mach-shmobile/board-mackerel.c + arch/arm/mach-shmobile/board-marzen.c + arch/arm/mach-shmobile/include/mach/irqs.h + arch/arm/mach-shmobile/intc-r8a7740.c + arch/arm/mach-shmobile/intc-sh7367.c + arch/arm/mach-shmobile/intc-sh7372.c + arch/arm/mach-shmobile/intc-sh7377.c + arch/arm/mach-shmobile/setup-r8a7740.c + arch/arm/mach-shmobile/setup-r8a7779.c + arch/arm/mach-shmobile/setup-sh7367.c + arch/arm/mach-shmobile/setup-sh7372.c + arch/arm/mach-shmobile/setup-sh7377.c + arch/arm/mach-shmobile/setup-sh73a0.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/setup-sh73a0.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c +index 20e71e5..7bf740e 100644 +--- a/arch/arm/mach-shmobile/setup-sh73a0.c ++++ b/arch/arm/mach-shmobile/setup-sh73a0.c +@@ -31,6 +31,7 @@ + #include <linux/sh_intc.h> + #include <linux/sh_timer.h> + #include <mach/hardware.h> ++#include <mach/irqs.h> + #include <mach/sh73a0.h> + #include <asm/mach-types.h> + #include <asm/mach/arch.h> +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0185-ARM-mach-shmobile-sh73a0-PSTR-32-bit-access-fix.patch b/patches.kzm9g/0185-ARM-mach-shmobile-sh73a0-PSTR-32-bit-access-fix.patch new file mode 100644 index 00000000000000..9bd9e8bce9fedb --- /dev/null +++ b/patches.kzm9g/0185-ARM-mach-shmobile-sh73a0-PSTR-32-bit-access-fix.patch @@ -0,0 +1,34 @@ +From 0a9ecd90d97895db2561a1dbaa0d106b293c52e0 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Mon, 30 Jan 2012 11:03:49 +0900 +Subject: ARM: mach-shmobile: sh73a0 PSTR 32-bit access fix + +Convert the sh73a0 SMP code to use 32-bit PSTR access. + +This fixes wakeup from deep sleep for sh73a0 secondary CPUs. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 689189fb014203965ed89833d8d5566424540c9d) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/smp-sh73a0.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c +index be1ade7..55d58c5 100644 +--- a/arch/arm/mach-shmobile/smp-sh73a0.c ++++ b/arch/arm/mach-shmobile/smp-sh73a0.c +@@ -79,7 +79,7 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu) + /* enable cache coherency */ + modify_scu_cpu_psr(0, 3 << (cpu * 8)); + +- if (((__raw_readw(__io(PSTR)) >> (4 * cpu)) & 3) == 3) ++ if (((__raw_readl(__io(PSTR)) >> (4 * cpu)) & 3) == 3) + __raw_writel(1 << cpu, __io(WUPCR)); /* wake up */ + else + __raw_writel(1 << cpu, __io(SRESCR)); /* reset */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0186-ARM-mach-shmobile-sh73a0-sh_clk_ops-rename.patch b/patches.kzm9g/0186-ARM-mach-shmobile-sh73a0-sh_clk_ops-rename.patch new file mode 100644 index 00000000000000..85ca1f56af2f27 --- /dev/null +++ b/patches.kzm9g/0186-ARM-mach-shmobile-sh73a0-sh_clk_ops-rename.patch @@ -0,0 +1,77 @@ +From f60efe916f290bb106e6578b3653af1f253f2dc6 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Wed, 29 Feb 2012 22:16:52 +0900 +Subject: ARM: mach-shmobile: sh73a0 sh_clk_ops rename + +Convert sh73a0 to use sh_clk_ops. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 7bcda508bfd9715c1a6a0589107c8c9d508f732e) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-sh73a0.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c +index 4d8d140..41f8293 100644 +--- a/arch/arm/mach-shmobile/clock-sh73a0.c ++++ b/arch/arm/mach-shmobile/clock-sh73a0.c +@@ -88,7 +88,7 @@ static unsigned long div2_recalc(struct clk *clk) + return clk->parent->rate / 2; + } + +-static struct clk_ops div2_clk_ops = { ++static struct sh_clk_ops div2_clk_ops = { + .recalc = div2_recalc, + }; + +@@ -97,7 +97,7 @@ static unsigned long div7_recalc(struct clk *clk) + return clk->parent->rate / 7; + } + +-static struct clk_ops div7_clk_ops = { ++static struct sh_clk_ops div7_clk_ops = { + .recalc = div7_recalc, + }; + +@@ -106,7 +106,7 @@ static unsigned long div13_recalc(struct clk *clk) + return clk->parent->rate / 13; + } + +-static struct clk_ops div13_clk_ops = { ++static struct sh_clk_ops div13_clk_ops = { + .recalc = div13_recalc, + }; + +@@ -122,7 +122,7 @@ static struct clk extal2_div2_clk = { + .parent = &sh73a0_extal2_clk, + }; + +-static struct clk_ops main_clk_ops = { ++static struct sh_clk_ops main_clk_ops = { + .recalc = followparent_recalc, + }; + +@@ -155,7 +155,7 @@ static unsigned long pll_recalc(struct clk *clk) + return clk->parent->rate * mult; + } + +-static struct clk_ops pll_clk_ops = { ++static struct sh_clk_ops pll_clk_ops = { + .recalc = pll_recalc, + }; + +@@ -437,7 +437,7 @@ static int dsiphy_set_rate(struct clk *clk, unsigned long rate) + return 0; + } + +-static struct clk_ops dsiphy_clk_ops = { ++static struct sh_clk_ops dsiphy_clk_ops = { + .recalc = dsiphy_recalc, + .round_rate = dsiphy_round_rate, + .set_rate = dsiphy_set_rate, +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0187-ARM-mach-shmobile-sh73a0-map_io-and-init_early-updat.patch b/patches.kzm9g/0187-ARM-mach-shmobile-sh73a0-map_io-and-init_early-updat.patch new file mode 100644 index 00000000000000..6f774b9048f285 --- /dev/null +++ b/patches.kzm9g/0187-ARM-mach-shmobile-sh73a0-map_io-and-init_early-updat.patch @@ -0,0 +1,129 @@ +From c46683358d9052c0bfb2388c2f046aeb20d3716b Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Wed, 29 Feb 2012 21:37:27 +0900 +Subject: ARM: mach-shmobile: sh73a0 map_io and init_early update + +Update the sh73a0 SoC and the AG5EVM and Kota2 boards to make use +of the functions sh73a0_map_io() and sh73a0_add_early_devices(). + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 50e15c34f0072324fee9faaae71b129e8b419913) + +Conflicts: + + arch/arm/mach-shmobile/board-ag5evm.c + arch/arm/mach-shmobile/board-kota2.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-ag5evm.c | 24 +----------------------- + arch/arm/mach-shmobile/include/mach/common.h | 1 + + arch/arm/mach-shmobile/setup-sh73a0.c | 22 ++++++++++++++++++++++ + 3 files changed, 24 insertions(+), 23 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c +index 430c723..7f50dab 100644 +--- a/arch/arm/mach-shmobile/board-ag5evm.c ++++ b/arch/arm/mach-shmobile/board-ag5evm.c +@@ -46,7 +46,6 @@ + #include <mach/common.h> + #include <asm/mach-types.h> + #include <asm/mach/arch.h> +-#include <asm/mach/map.h> + #include <asm/mach/time.h> + #include <asm/hardware/gic.h> + #include <asm/hardware/cache-l2x0.h> +@@ -424,27 +423,6 @@ static struct platform_device *ag5evm_devices[] __initdata = { + &sdhi1_device, + }; + +-static struct map_desc ag5evm_io_desc[] __initdata = { +- /* create a 1:1 entity map for 0xe6xxxxxx +- * used by CPGA, INTC and PFC. +- */ +- { +- .virtual = 0xe6000000, +- .pfn = __phys_to_pfn(0xe6000000), +- .length = 256 << 20, +- .type = MT_DEVICE_NONSHARED +- }, +-}; +- +-static void __init ag5evm_map_io(void) +-{ +- iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc)); +- +- /* setup early devices and console here as well */ +- sh73a0_add_early_devices(); +- shmobile_setup_console(); +-} +- + #define DSI0PHYCR 0xe615006c + + static void __init ag5evm_init(void) +@@ -570,7 +548,7 @@ struct sys_timer ag5evm_timer = { + }; + + MACHINE_START(AG5EVM, "ag5evm") +- .map_io = ag5evm_map_io, ++ .map_io = sh73a0_map_io, + .init_irq = sh73a0_init_irq, + .handle_irq = shmobile_handle_irq_gic, + .init_machine = ag5evm_init, +diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h +index 6ccc1a5..c77b3a1 100644 +--- a/arch/arm/mach-shmobile/include/mach/common.h ++++ b/arch/arm/mach-shmobile/include/mach/common.h +@@ -42,6 +42,7 @@ extern struct clk sh7372_extal1_clk; + extern struct clk sh7372_extal2_clk; + + extern void sh73a0_init_irq(void); ++extern void sh73a0_map_io(void); + extern void sh73a0_add_early_devices(void); + extern void sh73a0_add_standard_devices(void); + extern void sh73a0_clock_init(void); +diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c +index 7bf740e..ce9d5c8 100644 +--- a/arch/arm/mach-shmobile/setup-sh73a0.c ++++ b/arch/arm/mach-shmobile/setup-sh73a0.c +@@ -33,9 +33,28 @@ + #include <mach/hardware.h> + #include <mach/irqs.h> + #include <mach/sh73a0.h> ++#include <mach/common.h> + #include <asm/mach-types.h> ++#include <asm/mach/map.h> + #include <asm/mach/arch.h> + ++static struct map_desc sh73a0_io_desc[] __initdata = { ++ /* create a 1:1 entity map for 0xe6xxxxxx ++ * used by CPGA, INTC and PFC. ++ */ ++ { ++ .virtual = 0xe6000000, ++ .pfn = __phys_to_pfn(0xe6000000), ++ .length = 256 << 20, ++ .type = MT_DEVICE_NONSHARED ++ }, ++}; ++ ++void __init sh73a0_map_io(void) ++{ ++ iotable_init(sh73a0_io_desc, ARRAY_SIZE(sh73a0_io_desc)); ++} ++ + static struct plat_sci_port scif0_platform_data = { + .mapbase = 0xe6c40000, + .flags = UPF_BOOT_AUTOCONF, +@@ -672,4 +691,7 @@ void __init sh73a0_add_early_devices(void) + { + early_platform_add_devices(sh73a0_early_devices, + ARRAY_SIZE(sh73a0_early_devices)); ++ ++ /* setup early console here as well */ ++ shmobile_setup_console(); + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0188-ARM-mach-shmobile-sh73a0-AG5EVM-and-Kota2-timer-rewo.patch b/patches.kzm9g/0188-ARM-mach-shmobile-sh73a0-AG5EVM-and-Kota2-timer-rewo.patch new file mode 100644 index 00000000000000..eddd543811fe87 --- /dev/null +++ b/patches.kzm9g/0188-ARM-mach-shmobile-sh73a0-AG5EVM-and-Kota2-timer-rewo.patch @@ -0,0 +1,95 @@ +From c646dee2f2e54015d3930520d89364374e2b86ec Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Tue, 6 Mar 2012 17:36:45 +0900 +Subject: ARM: mach-shmobile: sh73a0, AG5EVM and Kota2 timer rework + +Move the SoC specific timer code from AG5EVM and Kota2 +to sh73a0 setup code. This makes is possible to share +the SoC specific timer code across boards and it also +removes the need for a board specific timer structure. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 3be26fdba82a2ae8ed568ab5d4a0a2e252f18b13) + +Conflicts: + + arch/arm/mach-shmobile/board-kota2.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-ag5evm.c | 14 +------------- + arch/arm/mach-shmobile/setup-sh73a0.c | 10 ++++++++++ + 2 files changed, 11 insertions(+), 13 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c +index 7f50dab..5c2fa46 100644 +--- a/arch/arm/mach-shmobile/board-ag5evm.c ++++ b/arch/arm/mach-shmobile/board-ag5evm.c +@@ -46,7 +46,6 @@ + #include <mach/common.h> + #include <asm/mach-types.h> + #include <asm/mach/arch.h> +-#include <asm/mach/time.h> + #include <asm/hardware/gic.h> + #include <asm/hardware/cache-l2x0.h> + #include <asm/traps.h> +@@ -536,21 +535,10 @@ static void __init ag5evm_init(void) + platform_add_devices(ag5evm_devices, ARRAY_SIZE(ag5evm_devices)); + } + +-static void __init ag5evm_timer_init(void) +-{ +- sh73a0_clock_init(); +- shmobile_timer.init(); +- return; +-} +- +-struct sys_timer ag5evm_timer = { +- .init = ag5evm_timer_init, +-}; +- + MACHINE_START(AG5EVM, "ag5evm") + .map_io = sh73a0_map_io, + .init_irq = sh73a0_init_irq, + .handle_irq = shmobile_handle_irq_gic, + .init_machine = ag5evm_init, +- .timer = &ag5evm_timer, ++ .timer = &shmobile_timer, + MACHINE_END +diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c +index ce9d5c8..5bebffc 100644 +--- a/arch/arm/mach-shmobile/setup-sh73a0.c ++++ b/arch/arm/mach-shmobile/setup-sh73a0.c +@@ -37,6 +37,7 @@ + #include <asm/mach-types.h> + #include <asm/mach/map.h> + #include <asm/mach/arch.h> ++#include <asm/mach/time.h> + + static struct map_desc sh73a0_io_desc[] __initdata = { + /* create a 1:1 entity map for 0xe6xxxxxx +@@ -687,6 +688,12 @@ void __init sh73a0_add_standard_devices(void) + ARRAY_SIZE(sh73a0_late_devices)); + } + ++static void __init sh73a0_earlytimer_init(void) ++{ ++ sh73a0_clock_init(); ++ shmobile_earlytimer_init(); ++} ++ + void __init sh73a0_add_early_devices(void) + { + early_platform_add_devices(sh73a0_early_devices, +@@ -694,4 +701,7 @@ void __init sh73a0_add_early_devices(void) + + /* setup early console here as well */ + shmobile_setup_console(); ++ ++ /* override timer setup with soc-specific code */ ++ shmobile_timer.init = sh73a0_earlytimer_init; + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0189-ARM-mach-shmobile-sh73a0-add-MMC-data-pin-pull-up.patch b/patches.kzm9g/0189-ARM-mach-shmobile-sh73a0-add-MMC-data-pin-pull-up.patch new file mode 100644 index 00000000000000..3b19b6c94a84c8 --- /dev/null +++ b/patches.kzm9g/0189-ARM-mach-shmobile-sh73a0-add-MMC-data-pin-pull-up.patch @@ -0,0 +1,130 @@ +From 9cdeaf23e42138066404492c82f3c7b1f0d1de64 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 10 Nov 2011 18:44:24 -0800 +Subject: ARM: mach-shmobile: sh73a0: add MMC data pin pull-up + +This patch adds MMC data pin pull-up option for pfc-sh73a0.c, +and select it on ag5evm board. +The MMC read/write will be error without this patch. + +Cc: Takashi YOSHII <takashi.yoshii.zj@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 052008edf31383f866b2ec1b12604fc411c2d986) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-ag5evm.c | 16 ++++++------- + arch/arm/mach-shmobile/include/mach/sh73a0.h | 8 +++++++ + arch/arm/mach-shmobile/pfc-sh73a0.c | 34 ++++++++++++++++++++++++++++ + 3 files changed, 50 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c +index 5c2fa46..6574235 100644 +--- a/arch/arm/mach-shmobile/board-ag5evm.c ++++ b/arch/arm/mach-shmobile/board-ag5evm.c +@@ -463,14 +463,14 @@ static void __init ag5evm_init(void) + /* enable MMCIF */ + gpio_request(GPIO_FN_MMCCLK0, NULL); + gpio_request(GPIO_FN_MMCCMD0_PU, NULL); +- gpio_request(GPIO_FN_MMCD0_0, NULL); +- gpio_request(GPIO_FN_MMCD0_1, NULL); +- gpio_request(GPIO_FN_MMCD0_2, NULL); +- gpio_request(GPIO_FN_MMCD0_3, NULL); +- gpio_request(GPIO_FN_MMCD0_4, NULL); +- gpio_request(GPIO_FN_MMCD0_5, NULL); +- gpio_request(GPIO_FN_MMCD0_6, NULL); +- gpio_request(GPIO_FN_MMCD0_7, NULL); ++ gpio_request(GPIO_FN_MMCD0_0_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_1_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_2_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_3_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_4_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_5_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_6_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_7_PU, NULL); + gpio_request(GPIO_PORT208, NULL); /* Reset */ + gpio_direction_output(GPIO_PORT208, 1); + +diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h +index 8567d65..cad5757 100644 +--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h ++++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h +@@ -470,6 +470,14 @@ enum { + GPIO_FN_SDHICMD2_PU, + GPIO_FN_MMCCMD0_PU, + GPIO_FN_MMCCMD1_PU, ++ GPIO_FN_MMCD0_0_PU, ++ GPIO_FN_MMCD0_1_PU, ++ GPIO_FN_MMCD0_2_PU, ++ GPIO_FN_MMCD0_3_PU, ++ GPIO_FN_MMCD0_4_PU, ++ GPIO_FN_MMCD0_5_PU, ++ GPIO_FN_MMCD0_6_PU, ++ GPIO_FN_MMCD0_7_PU, + GPIO_FN_FSIACK_PU, + GPIO_FN_FSIAILR_PU, + GPIO_FN_FSIAIBT_PU, +diff --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c +index cf7c7bb..e05634c 100644 +--- a/arch/arm/mach-shmobile/pfc-sh73a0.c ++++ b/arch/arm/mach-shmobile/pfc-sh73a0.c +@@ -496,6 +496,14 @@ enum { + SDHICMD2_PU_MARK, + MMCCMD0_PU_MARK, + MMCCMD1_PU_MARK, ++ MMCD0_0_PU_MARK, ++ MMCD0_1_PU_MARK, ++ MMCD0_2_PU_MARK, ++ MMCD0_3_PU_MARK, ++ MMCD0_4_PU_MARK, ++ MMCD0_5_PU_MARK, ++ MMCD0_6_PU_MARK, ++ MMCD0_7_PU_MARK, + FSIBISLD_PU_MARK, + FSIACK_PU_MARK, + FSIAILR_PU_MARK, +@@ -1510,6 +1518,24 @@ static pinmux_enum_t pinmux_data[] = { + MSEL4CR_MSEL15_0), + PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT297_IN_PU, + MSEL4CR_MSEL15_1), ++ ++ PINMUX_DATA(MMCD0_0_PU_MARK, ++ PORT271_FN1, PORT271_IN_PU, MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_1_PU_MARK, ++ PORT272_FN1, PORT272_IN_PU, MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_2_PU_MARK, ++ PORT273_FN1, PORT273_IN_PU, MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_3_PU_MARK, ++ PORT274_FN1, PORT274_IN_PU, MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_4_PU_MARK, ++ PORT275_FN1, PORT275_IN_PU, MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_5_PU_MARK, ++ PORT276_FN1, PORT276_IN_PU, MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_6_PU_MARK, ++ PORT277_FN1, PORT277_IN_PU, MSEL4CR_MSEL15_0), ++ PINMUX_DATA(MMCD0_7_PU_MARK, ++ PORT278_FN1, PORT278_IN_PU, MSEL4CR_MSEL15_0), ++ + PINMUX_DATA(FSIBISLD_PU_MARK, PORT39_FN1, PORT39_IN_PU), + PINMUX_DATA(FSIACK_PU_MARK, PORT49_FN1, PORT49_IN_PU), + PINMUX_DATA(FSIAILR_PU_MARK, PORT50_FN5, PORT50_IN_PU), +@@ -2181,6 +2207,14 @@ static struct pinmux_gpio pinmux_gpios[] = { + GPIO_FN(SDHICMD2_PU), + GPIO_FN(MMCCMD0_PU), + GPIO_FN(MMCCMD1_PU), ++ GPIO_FN(MMCD0_0_PU), ++ GPIO_FN(MMCD0_1_PU), ++ GPIO_FN(MMCD0_2_PU), ++ GPIO_FN(MMCD0_3_PU), ++ GPIO_FN(MMCD0_4_PU), ++ GPIO_FN(MMCD0_5_PU), ++ GPIO_FN(MMCD0_6_PU), ++ GPIO_FN(MMCD0_7_PU), + GPIO_FN(FSIACK_PU), + GPIO_FN(FSIAILR_PU), + GPIO_FN(FSIAIBT_PU), +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0190-ARM-Update-mach-types.patch b/patches.kzm9g/0190-ARM-Update-mach-types.patch new file mode 100644 index 00000000000000..ddd8004441b3bb --- /dev/null +++ b/patches.kzm9g/0190-ARM-Update-mach-types.patch @@ -0,0 +1,640 @@ +From cfb81e862a2f3eca3aa5225ed4a103da16ae27c4 Mon Sep 17 00:00:00 2001 +From: Russell King <rmk+kernel@arm.linux.org.uk> +Date: Thu, 26 Apr 2012 08:44:25 +0100 +Subject: ARM: Update mach-types + +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit d098bc7d58ebda22a6554b6c9df1056802d9900f) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/tools/mach-types | 505 +++++++++++++++++++++++++--------------------- + 1 file changed, 271 insertions(+), 234 deletions(-) + +diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types +index f9c9f33..2997e56 100644 +--- a/arch/arm/tools/mach-types ++++ b/arch/arm/tools/mach-types +@@ -16,7 +16,7 @@ + # are merged into mainline or have been edited in the machine database + # within the last 12 months. References to machine_is_NAME() do not count! + # +-# Last update: Tue Dec 6 11:07:38 2011 ++# Last update: Thu Apr 26 08:44:23 2012 + # + # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number + # +@@ -205,6 +205,7 @@ omap_fsample MACH_OMAP_FSAMPLE OMAP_FSAMPLE 970 + snapper_cl15 MACH_SNAPPER_CL15 SNAPPER_CL15 986 + omap_palmz71 MACH_OMAP_PALMZ71 OMAP_PALMZ71 993 + smdk2412 MACH_SMDK2412 SMDK2412 1009 ++bkde303 MACH_BKDE303 BKDE303 1021 + smdk2413 MACH_SMDK2413 SMDK2413 1022 + aml_m5900 MACH_AML_M5900 AML_M5900 1024 + balloon3 MACH_BALLOON3 BALLOON3 1029 +@@ -381,8 +382,6 @@ davinci_da850_evm MACH_DAVINCI_DA850_EVM DAVINCI_DA850_EVM 2157 + at91sam9g10ek MACH_AT91SAM9G10EK AT91SAM9G10EK 2159 + omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160 + magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162 +-btmavb101 MACH_BTMAVB101 BTMAVB101 2172 +-btmawb101 MACH_BTMAWB101 BTMAWB101 2173 + tx25 MACH_TX25 TX25 2177 + omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178 + anw6410 MACH_ANW6410 ANW6410 2183 +@@ -397,7 +396,6 @@ net2big_v2 MACH_NET2BIG_V2 NET2BIG_V2 2204 + net5big_v2 MACH_NET5BIG_V2 NET5BIG_V2 2206 + inetspace_v2 MACH_INETSPACE_V2 INETSPACE_V2 2208 + at91sam9g45ekes MACH_AT91SAM9G45EKES AT91SAM9G45EKES 2212 +-pc7302 MACH_PC7302 PC7302 2220 + spear600 MACH_SPEAR600 SPEAR600 2236 + spear300 MACH_SPEAR300 SPEAR300 2237 + lilly1131 MACH_LILLY1131 LILLY1131 2239 +@@ -407,7 +405,6 @@ d2net MACH_D2NET D2NET 2282 + bigdisk MACH_BIGDISK BIGDISK 2283 + at91sam9g20ek_2mmc MACH_AT91SAM9G20EK_2MMC AT91SAM9G20EK_2MMC 2288 + bcmring MACH_BCMRING BCMRING 2289 +-dp6xx MACH_DP6XX DP6XX 2302 + mahimahi MACH_MAHIMAHI MAHIMAHI 2304 + smdk6442 MACH_SMDK6442 SMDK6442 2324 + openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325 +@@ -444,8 +441,6 @@ mx28evk MACH_MX28EVK MX28EVK 2531 + smartq5 MACH_SMARTQ5 SMARTQ5 2534 + davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548 + mxt_td60 MACH_MXT_TD60 MXT_TD60 2550 +-riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576 +-riot_x37 MACH_RIOT_X37 RIOT_X37 2578 + pca101 MACH_PCA101 PCA101 2595 + capc7117 MACH_CAPC7117 CAPC7117 2612 + icontrol MACH_ICONTROL ICONTROL 2624 +@@ -460,7 +455,6 @@ spear320 MACH_SPEAR320 SPEAR320 2661 + aquila MACH_AQUILA AQUILA 2676 + esata_sheevaplug MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678 + msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679 +-ea2478devkit MACH_EA2478DEVKIT EA2478DEVKIT 2683 + terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697 + msm7x25_surf MACH_MSM7X25_SURF MSM7X25_SURF 2703 + msm7x25_ffa MACH_MSM7X25_FFA MSM7X25_FFA 2704 +@@ -479,8 +473,6 @@ wbd222 MACH_WBD222 WBD222 2753 + msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755 + msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756 + tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758 +-nanos MACH_NANOS NANOS 2759 +-stamp9g45 MACH_STAMP9G45 STAMP9G45 2761 + cns3420vb MACH_CNS3420VB CNS3420VB 2776 + omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791 + ti8168evm MACH_TI8168EVM TI8168EVM 2800 +@@ -490,12 +482,9 @@ eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35SD EUKREA_CPUIMX35SD 2821 + eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822 + eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823 + smdkc210 MACH_SMDKC210 SMDKC210 2838 +-pca102 MACH_PCA102 PCA102 2843 ++pcaal1 MACH_PCAAL1 PCAAL1 2843 + t5325 MACH_T5325 T5325 2846 + income MACH_INCOME INCOME 2849 +-vvbox_sdorig2 MACH_VVBOX_SDORIG2 VVBOX_SDORIG2 2857 +-vvbox_sdlite2 MACH_VVBOX_SDLITE2 VVBOX_SDLITE2 2858 +-vvbox_sdpro4 MACH_VVBOX_SDPRO4 VVBOX_SDPRO4 2859 + mx257sx MACH_MX257SX MX257SX 2861 + goni MACH_GONI GONI 2862 + bv07 MACH_BV07 BV07 2882 +@@ -504,6 +493,7 @@ devixp MACH_DEVIXP DEVIXP 2885 + miccpt MACH_MICCPT MICCPT 2886 + mic256 MACH_MIC256 MIC256 2887 + u5500 MACH_U5500 U5500 2890 ++pov15hd MACH_POV15HD POV15HD 2910 + linkstation_lschl MACH_LINKSTATION_LSCHL LINKSTATION_LSCHL 2913 + smdkv310 MACH_SMDKV310 SMDKV310 2925 + wm8505_7in_netbook MACH_WM8505_7IN_NETBOOK WM8505_7IN_NETBOOK 2928 +@@ -537,243 +527,24 @@ trimslice MACH_TRIMSLICE TRIMSLICE 3209 + mackerel MACH_MACKEREL MACKEREL 3211 + kaen MACH_KAEN KAEN 3217 + nokia_rm680 MACH_NOKIA_RM680 NOKIA_RM680 3220 +-dm6446_adbox MACH_DM6446_ADBOX DM6446_ADBOX 3226 +-quad_salsa MACH_QUAD_SALSA QUAD_SALSA 3227 +-abb_gma_1_1 MACH_ABB_GMA_1_1 ABB_GMA_1_1 3228 +-svcid MACH_SVCID SVCID 3229 + msm8960_sim MACH_MSM8960_SIM MSM8960_SIM 3230 + msm8960_rumi3 MACH_MSM8960_RUMI3 MSM8960_RUMI3 3231 +-icon_g MACH_ICON_G ICON_G 3232 +-mb3 MACH_MB3 MB3 3233 + gsia18s MACH_GSIA18S GSIA18S 3234 +-pivicc MACH_PIVICC PIVICC 3235 +-pcm048 MACH_PCM048 PCM048 3236 +-dds MACH_DDS DDS 3237 +-chalten_xa1 MACH_CHALTEN_XA1 CHALTEN_XA1 3238 +-ts48xx MACH_TS48XX TS48XX 3239 +-tonga2_tfttimer MACH_TONGA2_TFTTIMER TONGA2_TFTTIMER 3240 +-whistler MACH_WHISTLER WHISTLER 3241 +-asl_phoenix MACH_ASL_PHOENIX ASL_PHOENIX 3242 +-at91sam9263otlite MACH_AT91SAM9263OTLITE AT91SAM9263OTLITE 3243 +-ddplug MACH_DDPLUG DDPLUG 3244 +-d2plug MACH_D2PLUG D2PLUG 3245 +-kzm9d MACH_KZM9D KZM9D 3246 +-verdi_lte MACH_VERDI_LTE VERDI_LTE 3247 +-nanozoom MACH_NANOZOOM NANOZOOM 3248 +-dm3730_som_lv MACH_DM3730_SOM_LV DM3730_SOM_LV 3249 +-dm3730_torpedo MACH_DM3730_TORPEDO DM3730_TORPEDO 3250 +-anchovy MACH_ANCHOVY ANCHOVY 3251 +-re2rev20 MACH_RE2REV20 RE2REV20 3253 +-re2rev21 MACH_RE2REV21 RE2REV21 3254 +-cns21xx MACH_CNS21XX CNS21XX 3255 +-rider MACH_RIDER RIDER 3257 +-nsk330 MACH_NSK330 NSK330 3258 +-cns2133evb MACH_CNS2133EVB CNS2133EVB 3259 +-z3_816x_mod MACH_Z3_816X_MOD Z3_816X_MOD 3260 +-z3_814x_mod MACH_Z3_814X_MOD Z3_814X_MOD 3261 +-beect MACH_BEECT BEECT 3262 +-dma_thunderbug MACH_DMA_THUNDERBUG DMA_THUNDERBUG 3263 +-omn_at91sam9g20 MACH_OMN_AT91SAM9G20 OMN_AT91SAM9G20 3264 +-mx25_e2s_uc MACH_MX25_E2S_UC MX25_E2S_UC 3265 +-mione MACH_MIONE MIONE 3266 +-top9000_tcu MACH_TOP9000_TCU TOP9000_TCU 3267 +-top9000_bsl MACH_TOP9000_BSL TOP9000_BSL 3268 +-kingdom MACH_KINGDOM KINGDOM 3269 +-armadillo460 MACH_ARMADILLO460 ARMADILLO460 3270 +-lq2 MACH_LQ2 LQ2 3271 +-sweda_tms2 MACH_SWEDA_TMS2 SWEDA_TMS2 3272 + mx53_loco MACH_MX53_LOCO MX53_LOCO 3273 +-acer_a8 MACH_ACER_A8 ACER_A8 3275 +-acer_gauguin MACH_ACER_GAUGUIN ACER_GAUGUIN 3276 +-guppy MACH_GUPPY GUPPY 3277 +-mx61_ard MACH_MX61_ARD MX61_ARD 3278 + tx53 MACH_TX53 TX53 3279 +-omapl138_case_a3 MACH_OMAPL138_CASE_A3 OMAPL138_CASE_A3 3280 +-uemd MACH_UEMD UEMD 3281 +-ccwmx51mut MACH_CCWMX51MUT CCWMX51MUT 3282 +-rockhopper MACH_ROCKHOPPER ROCKHOPPER 3283 + encore MACH_ENCORE ENCORE 3284 +-hkdkc100 MACH_HKDKC100 HKDKC100 3285 +-ts42xx MACH_TS42XX TS42XX 3286 +-aebl MACH_AEBL AEBL 3287 + wario MACH_WARIO WARIO 3288 +-gfs_spm MACH_GFS_SPM GFS_SPM 3289 + cm_t3730 MACH_CM_T3730 CM_T3730 3290 +-isc3 MACH_ISC3 ISC3 3291 +-rascal MACH_RASCAL RASCAL 3292 + hrefv60 MACH_HREFV60 HREFV60 3293 +-tpt_2_0 MACH_TPT_2_0 TPT_2_0 3294 +-splendor MACH_SPLENDOR SPLENDOR 3296 +-msm8x60_qt MACH_MSM8X60_QT MSM8X60_QT 3298 +-htc_hd_mini MACH_HTC_HD_MINI HTC_HD_MINI 3299 +-athene MACH_ATHENE ATHENE 3300 +-deep_r_ek_1 MACH_DEEP_R_EK_1 DEEP_R_EK_1 3301 +-vivow_ct MACH_VIVOW_CT VIVOW_CT 3302 +-nery_1000 MACH_NERY_1000 NERY_1000 3303 +-rfl109145_ssrv MACH_RFL109145_SSRV RFL109145_SSRV 3304 +-nmh MACH_NMH NMH 3305 +-wn802t MACH_WN802T WN802T 3306 +-dragonet MACH_DRAGONET DRAGONET 3307 +-at91sam9263desk16l MACH_AT91SAM9263DESK16L AT91SAM9263DESK16L 3309 +-bcmhana_sv MACH_BCMHANA_SV BCMHANA_SV 3310 +-bcmhana_tablet MACH_BCMHANA_TABLET BCMHANA_TABLET 3311 +-koi MACH_KOI KOI 3312 +-ts4800 MACH_TS4800 TS4800 3313 +-tqma9263 MACH_TQMA9263 TQMA9263 3314 +-holiday MACH_HOLIDAY HOLIDAY 3315 +-pcats_overlay MACH_PCATS_OVERLAY PCATS_OVERLAY 3317 +-hwgw6410 MACH_HWGW6410 HWGW6410 3318 +-shenzhou MACH_SHENZHOU SHENZHOU 3319 +-cwme9210 MACH_CWME9210 CWME9210 3320 +-cwme9210js MACH_CWME9210JS CWME9210JS 3321 +-colibri_tegra2 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323 +-w21 MACH_W21 W21 3324 +-polysat1 MACH_POLYSAT1 POLYSAT1 3325 +-dataway MACH_DATAWAY DATAWAY 3326 +-cobral138 MACH_COBRAL138 COBRAL138 3327 +-roverpcs8 MACH_ROVERPCS8 ROVERPCS8 3328 +-marvelc MACH_MARVELC MARVELC 3329 +-navefihid MACH_NAVEFIHID NAVEFIHID 3330 +-dm365_cv100 MACH_DM365_CV100 DM365_CV100 3331 +-able MACH_ABLE ABLE 3332 +-legacy MACH_LEGACY LEGACY 3333 +-icong MACH_ICONG ICONG 3334 +-rover_g8 MACH_ROVER_G8 ROVER_G8 3335 +-t5388p MACH_T5388P T5388P 3336 +-dingo MACH_DINGO DINGO 3337 +-goflexhome MACH_GOFLEXHOME GOFLEXHOME 3338 +-lanreadyfn511 MACH_LANREADYFN511 LANREADYFN511 3340 +-omap3_baia MACH_OMAP3_BAIA OMAP3_BAIA 3341 +-omap3smartdisplay MACH_OMAP3SMARTDISPLAY OMAP3SMARTDISPLAY 3342 +-xilinx MACH_XILINX XILINX 3343 +-a2f MACH_A2F A2F 3344 +-sky25 MACH_SKY25 SKY25 3345 +-ccmx53 MACH_CCMX53 CCMX53 3346 +-ccmx53js MACH_CCMX53JS CCMX53JS 3347 +-ccwmx53 MACH_CCWMX53 CCWMX53 3348 +-ccwmx53js MACH_CCWMX53JS CCWMX53JS 3349 +-frisms MACH_FRISMS FRISMS 3350 +-msm7x27a_ffa MACH_MSM7X27A_FFA MSM7X27A_FFA 3351 +-msm7x27a_surf MACH_MSM7X27A_SURF MSM7X27A_SURF 3352 +-msm7x27a_rumi3 MACH_MSM7X27A_RUMI3 MSM7X27A_RUMI3 3353 +-dimmsam9g20 MACH_DIMMSAM9G20 DIMMSAM9G20 3354 +-dimm_imx28 MACH_DIMM_IMX28 DIMM_IMX28 3355 +-amk_a4 MACH_AMK_A4 AMK_A4 3356 +-gnet_sgme MACH_GNET_SGME GNET_SGME 3357 +-shooter_u MACH_SHOOTER_U SHOOTER_U 3358 +-vmx53 MACH_VMX53 VMX53 3359 +-rhino MACH_RHINO RHINO 3360 + armlex4210 MACH_ARMLEX4210 ARMLEX4210 3361 +-swarcoextmodem MACH_SWARCOEXTMODEM SWARCOEXTMODEM 3362 + snowball MACH_SNOWBALL SNOWBALL 3363 +-pcm049 MACH_PCM049 PCM049 3364 +-vigor MACH_VIGOR VIGOR 3365 +-oslo_amundsen MACH_OSLO_AMUNDSEN OSLO_AMUNDSEN 3366 +-gsl_diamond MACH_GSL_DIAMOND GSL_DIAMOND 3367 +-cv2201 MACH_CV2201 CV2201 3368 +-cv2202 MACH_CV2202 CV2202 3369 +-cv2203 MACH_CV2203 CV2203 3370 +-vit_ibox MACH_VIT_IBOX VIT_IBOX 3371 +-dm6441_esp MACH_DM6441_ESP DM6441_ESP 3372 +-at91sam9x5ek MACH_AT91SAM9X5EK AT91SAM9X5EK 3373 +-libra MACH_LIBRA LIBRA 3374 +-easycrrh MACH_EASYCRRH EASYCRRH 3375 +-tripel MACH_TRIPEL TRIPEL 3376 +-endian_mini MACH_ENDIAN_MINI ENDIAN_MINI 3377 + xilinx_ep107 MACH_XILINX_EP107 XILINX_EP107 3378 + nuri MACH_NURI NURI 3379 +-janus MACH_JANUS JANUS 3380 +-ddnas MACH_DDNAS DDNAS 3381 +-tag MACH_TAG TAG 3382 +-tagw MACH_TAGW TAGW 3383 +-nitrogen_vm_imx51 MACH_NITROGEN_VM_IMX51 NITROGEN_VM_IMX51 3384 +-viprinet MACH_VIPRINET VIPRINET 3385 +-bockw MACH_BOCKW BOCKW 3386 +-eva2000 MACH_EVA2000 EVA2000 3387 +-steelyard MACH_STEELYARD STEELYARD 3388 +-nsslsboard MACH_NSSLSBOARD NSSLSBOARD 3392 +-geneva_b5 MACH_GENEVA_B5 GENEVA_B5 3393 +-spear1340 MACH_SPEAR1340 SPEAR1340 3394 +-rexmas MACH_REXMAS REXMAS 3395 +-msm8960_cdp MACH_MSM8960_CDP MSM8960_CDP 3396 +-msm8960_fluid MACH_MSM8960_FLUID MSM8960_FLUID 3398 +-msm8960_apq MACH_MSM8960_APQ MSM8960_APQ 3399 +-helios_v2 MACH_HELIOS_V2 HELIOS_V2 3400 +-mif10p MACH_MIF10P MIF10P 3401 +-iam28 MACH_IAM28 IAM28 3402 +-picasso MACH_PICASSO PICASSO 3403 +-mr301a MACH_MR301A MR301A 3404 +-notle MACH_NOTLE NOTLE 3405 +-eelx2 MACH_EELX2 EELX2 3406 +-moon MACH_MOON MOON 3407 +-ruby MACH_RUBY RUBY 3408 +-goldengate MACH_GOLDENGATE GOLDENGATE 3409 +-ctbu_gen2 MACH_CTBU_GEN2 CTBU_GEN2 3410 +-kmp_am17_01 MACH_KMP_AM17_01 KMP_AM17_01 3411 + wtplug MACH_WTPLUG WTPLUG 3412 +-mx27su2 MACH_MX27SU2 MX27SU2 3413 +-nb31 MACH_NB31 NB31 3414 +-hjsdu MACH_HJSDU HJSDU 3415 +-td3_rev1 MACH_TD3_REV1 TD3_REV1 3416 +-eag_ci4000 MACH_EAG_CI4000 EAG_CI4000 3417 +-net5big_nand_v2 MACH_NET5BIG_NAND_V2 NET5BIG_NAND_V2 3418 +-cpx2 MACH_CPX2 CPX2 3419 +-net2big_nand_v2 MACH_NET2BIG_NAND_V2 NET2BIG_NAND_V2 3420 +-ecuv5 MACH_ECUV5 ECUV5 3421 +-hsgx6d MACH_HSGX6D HSGX6D 3422 +-dawad7 MACH_DAWAD7 DAWAD7 3423 +-sam9repeater MACH_SAM9REPEATER SAM9REPEATER 3424 +-gt_i5700 MACH_GT_I5700 GT_I5700 3425 +-ctera_plug_c2 MACH_CTERA_PLUG_C2 CTERA_PLUG_C2 3426 +-marvelct MACH_MARVELCT MARVELCT 3427 +-ag11005 MACH_AG11005 AG11005 3428 +-vangogh MACH_VANGOGH VANGOGH 3430 +-matrix505 MACH_MATRIX505 MATRIX505 3431 +-oce_nigma MACH_OCE_NIGMA OCE_NIGMA 3432 +-t55 MACH_T55 T55 3433 +-bio3k MACH_BIO3K BIO3K 3434 +-expressct MACH_EXPRESSCT EXPRESSCT 3435 +-cardhu MACH_CARDHU CARDHU 3436 +-aruba MACH_ARUBA ARUBA 3437 +-bonaire MACH_BONAIRE BONAIRE 3438 +-nuc700evb MACH_NUC700EVB NUC700EVB 3439 +-nuc710evb MACH_NUC710EVB NUC710EVB 3440 +-nuc740evb MACH_NUC740EVB NUC740EVB 3441 +-nuc745evb MACH_NUC745EVB NUC745EVB 3442 +-transcede MACH_TRANSCEDE TRANSCEDE 3443 +-mora MACH_MORA MORA 3444 +-nda_evm MACH_NDA_EVM NDA_EVM 3445 +-timu MACH_TIMU TIMU 3446 +-expressh MACH_EXPRESSH EXPRESSH 3447 + veridis_a300 MACH_VERIDIS_A300 VERIDIS_A300 3448 +-dm368_leopard MACH_DM368_LEOPARD DM368_LEOPARD 3449 +-omap_mcop MACH_OMAP_MCOP OMAP_MCOP 3450 +-tritip MACH_TRITIP TRITIP 3451 +-sm1k MACH_SM1K SM1K 3452 +-monch MACH_MONCH MONCH 3453 +-curacao MACH_CURACAO CURACAO 3454 + origen MACH_ORIGEN ORIGEN 3455 +-epc10 MACH_EPC10 EPC10 3456 +-sgh_i740 MACH_SGH_I740 SGH_I740 3457 +-tuna MACH_TUNA TUNA 3458 +-mx51_tulip MACH_MX51_TULIP MX51_TULIP 3459 +-mx51_aster7 MACH_MX51_ASTER7 MX51_ASTER7 3460 +-acro37xbrd MACH_ACRO37XBRD ACRO37XBRD 3461 +-elke MACH_ELKE ELKE 3462 +-sbc6000x MACH_SBC6000X SBC6000X 3463 +-r1801e MACH_R1801E R1801E 3464 +-h1600 MACH_H1600 H1600 3465 +-mini210 MACH_MINI210 MINI210 3466 +-mini8168 MACH_MINI8168 MINI8168 3467 +-pc7308 MACH_PC7308 PC7308 3468 +-kmm2m01 MACH_KMM2M01 KMM2M01 3470 +-mx51erebus MACH_MX51EREBUS MX51EREBUS 3471 + wm8650refboard MACH_WM8650REFBOARD WM8650REFBOARD 3472 +-tuxrail MACH_TUXRAIL TUXRAIL 3473 +-arthur MACH_ARTHUR ARTHUR 3474 +-doorboy MACH_DOORBOY DOORBOY 3475 + xarina MACH_XARINA XARINA 3476 +-roverx7 MACH_ROVERX7 ROVERX7 3477 + sdvr MACH_SDVR SDVR 3478 + acer_maya MACH_ACER_MAYA ACER_MAYA 3479 + pico MACH_PICO PICO 3480 +@@ -999,6 +770,7 @@ promwad_jade MACH_PROMWAD_JADE PROMWAD_JADE 3708 + amp MACH_AMP AMP 3709 + gnet_amp MACH_GNET_AMP GNET_AMP 3710 + toques MACH_TOQUES TOQUES 3711 ++apx4devkit MACH_APX4DEVKIT APX4DEVKIT 3712 + dct_storm MACH_DCT_STORM DCT_STORM 3713 + owl MACH_OWL OWL 3715 + cogent_csb1741 MACH_COGENT_CSB1741 COGENT_CSB1741 3716 +@@ -1063,7 +835,6 @@ shelter MACH_SHELTER SHELTER 3778 + omap3_devkit8500 MACH_OMAP3_DEVKIT8500 OMAP3_DEVKIT8500 3779 + edgetd MACH_EDGETD EDGETD 3780 + copperyard MACH_COPPERYARD COPPERYARD 3781 +-edge MACH_EDGE EDGE 3782 + edge_u MACH_EDGE_U EDGE_U 3783 + edge_td MACH_EDGE_TD EDGE_TD 3784 + wdss MACH_WDSS WDSS 3785 +@@ -1169,3 +940,269 @@ elite_ulk MACH_ELITE_ULK ELITE_ULK 3888 + pov2 MACH_POV2 POV2 3889 + ipod_touch_2g MACH_IPOD_TOUCH_2G IPOD_TOUCH_2G 3890 + da850_pqab MACH_DA850_PQAB DA850_PQAB 3891 ++fermi MACH_FERMI FERMI 3892 ++ccardwmx28 MACH_CCARDWMX28 CCARDWMX28 3893 ++ccardmx28 MACH_CCARDMX28 CCARDMX28 3894 ++fs20_fcm2050 MACH_FS20_FCM2050 FS20_FCM2050 3895 ++kinetis MACH_KINETIS KINETIS 3896 ++kai MACH_KAI KAI 3897 ++bcthb2 MACH_BCTHB2 BCTHB2 3898 ++inels3_cu MACH_INELS3_CU INELS3_CU 3899 ++da850_apollo MACH_DA850_APOLLO DA850_APOLLO 3901 ++tracnas MACH_TRACNAS TRACNAS 3902 ++mityarm335x MACH_MITYARM335X MITYARM335X 3903 ++xcgz7x MACH_XCGZ7X XCGZ7X 3904 ++cubox MACH_CUBOX CUBOX 3905 ++terminator MACH_TERMINATOR TERMINATOR 3906 ++eye03 MACH_EYE03 EYE03 3907 ++kota3 MACH_KOTA3 KOTA3 3908 ++pscpe MACH_PSCPE PSCPE 3910 ++akt1100 MACH_AKT1100 AKT1100 3911 ++pcaaxl2 MACH_PCAAXL2 PCAAXL2 3912 ++primodd_ct MACH_PRIMODD_CT PRIMODD_CT 3913 ++nsbc MACH_NSBC NSBC 3914 ++meson2_skt MACH_MESON2_SKT MESON2_SKT 3915 ++meson2_ref MACH_MESON2_REF MESON2_REF 3916 ++ccardwmx28js MACH_CCARDWMX28JS CCARDWMX28JS 3917 ++ccardmx28js MACH_CCARDMX28JS CCARDMX28JS 3918 ++indico MACH_INDICO INDICO 3919 ++msm8960dt MACH_MSM8960DT MSM8960DT 3920 ++primods MACH_PRIMODS PRIMODS 3921 ++beluga_m1388 MACH_BELUGA_M1388 BELUGA_M1388 3922 ++primotd MACH_PRIMOTD PRIMOTD 3923 ++varan_master MACH_VARAN_MASTER VARAN_MASTER 3924 ++primodd MACH_PRIMODD PRIMODD 3925 ++jetduo MACH_JETDUO JETDUO 3926 ++mx53_umobo MACH_MX53_UMOBO MX53_UMOBO 3927 ++trats MACH_TRATS TRATS 3928 ++starcraft MACH_STARCRAFT STARCRAFT 3929 ++qseven_tegra2 MACH_QSEVEN_TEGRA2 QSEVEN_TEGRA2 3930 ++lichee_sun4i_devbd MACH_LICHEE_SUN4I_DEVBD LICHEE_SUN4I_DEVBD 3931 ++movenow MACH_MOVENOW MOVENOW 3932 ++golf_u MACH_GOLF_U GOLF_U 3933 ++msm7627a_evb MACH_MSM7627A_EVB MSM7627A_EVB 3934 ++rambo MACH_RAMBO RAMBO 3935 ++golfu MACH_GOLFU GOLFU 3936 ++mango310 MACH_MANGO310 MANGO310 3937 ++dns343 MACH_DNS343 DNS343 3938 ++var_som_om44 MACH_VAR_SOM_OM44 VAR_SOM_OM44 3939 ++naon MACH_NAON NAON 3940 ++vp4000 MACH_VP4000 VP4000 3941 ++impcard MACH_IMPCARD IMPCARD 3942 ++smoovcam MACH_SMOOVCAM SMOOVCAM 3943 ++cobham3725 MACH_COBHAM3725 COBHAM3725 3944 ++cobham3730 MACH_COBHAM3730 COBHAM3730 3945 ++cobham3703 MACH_COBHAM3703 COBHAM3703 3946 ++quetzal MACH_QUETZAL QUETZAL 3947 ++apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948 ++apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949 ++apq8064_fluid MACH_APQ8064_FLUID APQ8064_FLUID 3950 ++apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951 ++mango210 MACH_MANGO210 MANGO210 3952 ++mango100 MACH_MANGO100 MANGO100 3953 ++mango24 MACH_MANGO24 MANGO24 3954 ++mango64 MACH_MANGO64 MANGO64 3955 ++nsa320 MACH_NSA320 NSA320 3956 ++elv_ccu2 MACH_ELV_CCU2 ELV_CCU2 3957 ++triton_x00 MACH_TRITON_X00 TRITON_X00 3958 ++triton_1500_2000 MACH_TRITON_1500_2000 TRITON_1500_2000 3959 ++pogoplugv4 MACH_POGOPLUGV4 POGOPLUGV4 3960 ++venus_cl MACH_VENUS_CL VENUS_CL 3961 ++vulcano_g20 MACH_VULCANO_G20 VULCANO_G20 3962 ++sgs_i9100 MACH_SGS_I9100 SGS_I9100 3963 ++stsv2 MACH_STSV2 STSV2 3964 ++csb1724 MACH_CSB1724 CSB1724 3965 ++omapl138_lcdk MACH_OMAPL138_LCDK OMAPL138_LCDK 3966 ++pvd_mx25 MACH_PVD_MX25 PVD_MX25 3968 ++meson6_skt MACH_MESON6_SKT MESON6_SKT 3969 ++meson6_ref MACH_MESON6_REF MESON6_REF 3970 ++pxm MACH_PXM PXM 3971 ++pogoplugv3 MACH_POGOPLUGV3 POGOPLUGV3 3973 ++mlp89626 MACH_MLP89626 MLP89626 3974 ++iomegahmndce MACH_IOMEGAHMNDCE IOMEGAHMNDCE 3975 ++pogoplugv3pci MACH_POGOPLUGV3PCI POGOPLUGV3PCI 3976 ++bntv250 MACH_BNTV250 BNTV250 3977 ++mx53_qseven MACH_MX53_QSEVEN MX53_QSEVEN 3978 ++gtl_it1100 MACH_GTL_IT1100 GTL_IT1100 3979 ++mx6q_sabresd MACH_MX6Q_SABRESD MX6Q_SABRESD 3980 ++mt4 MACH_MT4 MT4 3981 ++jumbo_d MACH_JUMBO_D JUMBO_D 3982 ++jumbo_i MACH_JUMBO_I JUMBO_I 3983 ++fs20_dmp MACH_FS20_DMP FS20_DMP 3984 ++dns320 MACH_DNS320 DNS320 3985 ++mx28bacos MACH_MX28BACOS MX28BACOS 3986 ++tl80 MACH_TL80 TL80 3987 ++polatis_nic_1001 MACH_POLATIS_NIC_1001 POLATIS_NIC_1001 3988 ++tely MACH_TELY TELY 3989 ++u8520 MACH_U8520 U8520 3990 ++manta MACH_MANTA MANTA 3991 ++mpq8064_cdp MACH_MPQ8064_CDP MPQ8064_CDP 3993 ++mpq8064_dtv MACH_MPQ8064_DTV MPQ8064_DTV 3995 ++dm368som MACH_DM368SOM DM368SOM 3996 ++gprisb2 MACH_GPRISB2 GPRISB2 3997 ++chammid MACH_CHAMMID CHAMMID 3998 ++seoul2 MACH_SEOUL2 SEOUL2 3999 ++omap4_nooktablet MACH_OMAP4_NOOKTABLET OMAP4_NOOKTABLET 4000 ++aalto MACH_AALTO AALTO 4001 ++metro MACH_METRO METRO 4002 ++cydm3730 MACH_CYDM3730 CYDM3730 4003 ++tqma53 MACH_TQMA53 TQMA53 4004 ++msm7627a_qrd3 MACH_MSM7627A_QRD3 MSM7627A_QRD3 4005 ++mx28_canby MACH_MX28_CANBY MX28_CANBY 4006 ++tiger MACH_TIGER TIGER 4007 ++pcats_9307_type_a MACH_PCATS_9307_TYPE_A PCATS_9307_TYPE_A 4008 ++pcats_9307_type_o MACH_PCATS_9307_TYPE_O PCATS_9307_TYPE_O 4009 ++pcats_9307_type_r MACH_PCATS_9307_TYPE_R PCATS_9307_TYPE_R 4010 ++streamplug MACH_STREAMPLUG STREAMPLUG 4011 ++icechicken_dev MACH_ICECHICKEN_DEV ICECHICKEN_DEV 4012 ++hedgehog MACH_HEDGEHOG HEDGEHOG 4013 ++yusend_obc MACH_YUSEND_OBC YUSEND_OBC 4014 ++imxninja MACH_IMXNINJA IMXNINJA 4015 ++omap4_jarod MACH_OMAP4_JAROD OMAP4_JAROD 4016 ++eco5_pk MACH_ECO5_PK ECO5_PK 4017 ++qj2440 MACH_QJ2440 QJ2440 4018 ++mx6q_mercury MACH_MX6Q_MERCURY MX6Q_MERCURY 4019 ++cm6810 MACH_CM6810 CM6810 4020 ++omap4_torpedo MACH_OMAP4_TORPEDO OMAP4_TORPEDO 4021 ++nsa310 MACH_NSA310 NSA310 4022 ++tmx536 MACH_TMX536 TMX536 4023 ++ktt20 MACH_KTT20 KTT20 4024 ++dragonix MACH_DRAGONIX DRAGONIX 4025 ++lungching MACH_LUNGCHING LUNGCHING 4026 ++bulogics MACH_BULOGICS BULOGICS 4027 ++mx535_sx MACH_MX535_SX MX535_SX 4028 ++ngui3250 MACH_NGUI3250 NGUI3250 4029 ++salutec_dac MACH_SALUTEC_DAC SALUTEC_DAC 4030 ++loco MACH_LOCO LOCO 4031 ++ctera_plug_usi MACH_CTERA_PLUG_USI CTERA_PLUG_USI 4032 ++scepter MACH_SCEPTER SCEPTER 4033 ++sga MACH_SGA SGA 4034 ++p_81_j5 MACH_P_81_J5 P_81_J5 4035 ++p_81_o4 MACH_P_81_O4 P_81_O4 4036 ++msm8625_surf MACH_MSM8625_SURF MSM8625_SURF 4037 ++carallon_shark MACH_CARALLON_SHARK CARALLON_SHARK 4038 ++ordog MACH_ORDOG ORDOG 4040 ++puente_io MACH_PUENTE_IO PUENTE_IO 4041 ++msm8625_evb MACH_MSM8625_EVB MSM8625_EVB 4042 ++ev_am1707 MACH_EV_AM1707 EV_AM1707 4043 ++ev_am1707e2 MACH_EV_AM1707E2 EV_AM1707E2 4044 ++ev_am3517e2 MACH_EV_AM3517E2 EV_AM3517E2 4045 ++calabria MACH_CALABRIA CALABRIA 4046 ++ev_imx287 MACH_EV_IMX287 EV_IMX287 4047 ++erau MACH_ERAU ERAU 4048 ++sichuan MACH_SICHUAN SICHUAN 4049 ++davinci_da850 MACH_DAVINCI_DA850 DAVINCI_DA850 4051 ++omap138_trunarc MACH_OMAP138_TRUNARC OMAP138_TRUNARC 4052 ++bcm4761 MACH_BCM4761 BCM4761 4053 ++picasso_e2 MACH_PICASSO_E2 PICASSO_E2 4054 ++picasso_mf MACH_PICASSO_MF PICASSO_MF 4055 ++miro MACH_MIRO MIRO 4056 ++at91sam9g20ewon3 MACH_AT91SAM9G20EWON3 AT91SAM9G20EWON3 4057 ++yoyo MACH_YOYO YOYO 4058 ++windjkl MACH_WINDJKL WINDJKL 4059 ++monarudo MACH_MONARUDO MONARUDO 4060 ++batan MACH_BATAN BATAN 4061 ++tadao MACH_TADAO TADAO 4062 ++baso MACH_BASO BASO 4063 ++mahon MACH_MAHON MAHON 4064 ++villec2 MACH_VILLEC2 VILLEC2 4065 ++asi1230 MACH_ASI1230 ASI1230 4066 ++alaska MACH_ALASKA ALASKA 4067 ++swarco_shdsl2 MACH_SWARCO_SHDSL2 SWARCO_SHDSL2 4068 ++oxrtu MACH_OXRTU OXRTU 4069 ++omap5_panda MACH_OMAP5_PANDA OMAP5_PANDA 4070 ++c8000 MACH_C8000 C8000 4072 ++bje_display3_5 MACH_BJE_DISPLAY3_5 BJE_DISPLAY3_5 4073 ++picomod7 MACH_PICOMOD7 PICOMOD7 4074 ++picocom5 MACH_PICOCOM5 PICOCOM5 4075 ++qblissa8 MACH_QBLISSA8 QBLISSA8 4076 ++armstonea8 MACH_ARMSTONEA8 ARMSTONEA8 4077 ++netdcu14 MACH_NETDCU14 NETDCU14 4078 ++at91sam9x5_epiphan MACH_AT91SAM9X5_EPIPHAN AT91SAM9X5_EPIPHAN 4079 ++p2u MACH_P2U P2U 4080 ++doris MACH_DORIS DORIS 4081 ++j49 MACH_J49 J49 4082 ++vdss2e MACH_VDSS2E VDSS2E 4083 ++vc300 MACH_VC300 VC300 4084 ++ns115_pad_test MACH_NS115_PAD_TEST NS115_PAD_TEST 4085 ++ns115_pad_ref MACH_NS115_PAD_REF NS115_PAD_REF 4086 ++ns115_phone_test MACH_NS115_PHONE_TEST NS115_PHONE_TEST 4087 ++ns115_phone_ref MACH_NS115_PHONE_REF NS115_PHONE_REF 4088 ++golfc MACH_GOLFC GOLFC 4089 ++xerox_olympus MACH_XEROX_OLYMPUS XEROX_OLYMPUS 4090 ++mx6sl_arm2 MACH_MX6SL_ARM2 MX6SL_ARM2 4091 ++csb1701_csb1726 MACH_CSB1701_CSB1726 CSB1701_CSB1726 4092 ++at91sam9xeek MACH_AT91SAM9XEEK AT91SAM9XEEK 4093 ++ebv210 MACH_EBV210 EBV210 4094 ++msm7627a_qrd7 MACH_MSM7627A_QRD7 MSM7627A_QRD7 4095 ++svthin MACH_SVTHIN SVTHIN 4096 ++duovero MACH_DUOVERO DUOVERO 4097 ++chupacabra MACH_CHUPACABRA CHUPACABRA 4098 ++scorpion MACH_SCORPION SCORPION 4099 ++davinci_he_hmi10 MACH_DAVINCI_HE_HMI10 DAVINCI_HE_HMI10 4100 ++topkick MACH_TOPKICK TOPKICK 4101 ++m3_auguestrush MACH_M3_AUGUESTRUSH M3_AUGUESTRUSH 4102 ++ipc335x MACH_IPC335X IPC335X 4103 ++sun4i MACH_SUN4I SUN4I 4104 ++imx233_olinuxino MACH_IMX233_OLINUXINO IMX233_OLINUXINO 4105 ++k2_wl MACH_K2_WL K2_WL 4106 ++k2_ul MACH_K2_UL K2_UL 4107 ++k2_cl MACH_K2_CL K2_CL 4108 ++minbari_w MACH_MINBARI_W MINBARI_W 4109 ++minbari_m MACH_MINBARI_M MINBARI_M 4110 ++k035 MACH_K035 K035 4111 ++ariel MACH_ARIEL ARIEL 4112 ++arielsaarc MACH_ARIELSAARC ARIELSAARC 4113 ++arieldkb MACH_ARIELDKB ARIELDKB 4114 ++armadillo810 MACH_ARMADILLO810 ARMADILLO810 4115 ++tam335x MACH_TAM335X TAM335X 4116 ++grouper MACH_GROUPER GROUPER 4117 ++mpcsa21_9g20 MACH_MPCSA21_9G20 MPCSA21_9G20 4118 ++m6u_cpu MACH_M6U_CPU M6U_CPU 4119 ++davinci_dp10 MACH_DAVINCI_DP10 DAVINCI_DP10 4120 ++ginkgo MACH_GINKGO GINKGO 4121 ++cgt_qmx6 MACH_CGT_QMX6 CGT_QMX6 4122 ++profpga MACH_PROFPGA PROFPGA 4123 ++acfx100oc MACH_ACFX100OC ACFX100OC 4124 ++acfx100nb MACH_ACFX100NB ACFX100NB 4125 ++capricorn MACH_CAPRICORN CAPRICORN 4126 ++pisces MACH_PISCES PISCES 4127 ++aries MACH_ARIES ARIES 4128 ++cancer MACH_CANCER CANCER 4129 ++leo MACH_LEO LEO 4130 ++virgo MACH_VIRGO VIRGO 4131 ++sagittarius MACH_SAGITTARIUS SAGITTARIUS 4132 ++devil MACH_DEVIL DEVIL 4133 ++ballantines MACH_BALLANTINES BALLANTINES 4134 ++omap3_procerusvpu MACH_OMAP3_PROCERUSVPU OMAP3_PROCERUSVPU 4135 ++my27 MACH_MY27 MY27 4136 ++sun6i MACH_SUN6I SUN6I 4137 ++sun5i MACH_SUN5I SUN5I 4138 ++mx512_mx MACH_MX512_MX MX512_MX 4139 ++kzm9g MACH_KZM9G KZM9G 4140 ++vdstbn MACH_VDSTBN VDSTBN 4141 ++cfa10036 MACH_CFA10036 CFA10036 4142 ++cfa10049 MACH_CFA10049 CFA10049 4143 ++pcm051 MACH_PCM051 PCM051 4144 ++vybrid_vf7xx MACH_VYBRID_VF7XX VYBRID_VF7XX 4145 ++vybrid_vf6xx MACH_VYBRID_VF6XX VYBRID_VF6XX 4146 ++vybrid_vf5xx MACH_VYBRID_VF5XX VYBRID_VF5XX 4147 ++vybrid_vf4xx MACH_VYBRID_VF4XX VYBRID_VF4XX 4148 ++aria_g25 MACH_ARIA_G25 ARIA_G25 4149 ++bcm21553 MACH_BCM21553 BCM21553 4150 ++smdk5410 MACH_SMDK5410 SMDK5410 4151 ++lpc18xx MACH_LPC18XX LPC18XX 4152 ++oratisparty MACH_ORATISPARTY ORATISPARTY 4153 ++qseven MACH_QSEVEN QSEVEN 4154 ++gmv_generic MACH_GMV_GENERIC GMV_GENERIC 4155 ++th_link_eth MACH_TH_LINK_ETH TH_LINK_ETH 4156 ++tn_muninn MACH_TN_MUNINN TN_MUNINN 4157 ++rampage MACH_RAMPAGE RAMPAGE 4158 ++visstrim_mv10 MACH_VISSTRIM_MV10 VISSTRIM_MV10 4159 ++mx28_wilma MACH_MX28_WILMA MX28_WILMA 4164 ++msm8625_ffa MACH_MSM8625_FFA MSM8625_FFA 4166 ++vpu101 MACH_VPU101 VPU101 4167 ++baileys MACH_BAILEYS BAILEYS 4169 ++familybox MACH_FAMILYBOX FAMILYBOX 4170 ++ensemble_mx35 MACH_ENSEMBLE_MX35 ENSEMBLE_MX35 4171 ++sc_sps_1 MACH_SC_SPS_1 SC_SPS_1 4172 +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0191-ARM-mach-shmobile-add-KZM-A9-GT-board-support.patch b/patches.kzm9g/0191-ARM-mach-shmobile-add-KZM-A9-GT-board-support.patch new file mode 100644 index 00000000000000..5dc9d3b14ed7ab --- /dev/null +++ b/patches.kzm9g/0191-ARM-mach-shmobile-add-KZM-A9-GT-board-support.patch @@ -0,0 +1,126 @@ +From c3845eb19812059fd44fb6a6993c5bef692ee796 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 10 Apr 2012 20:57:31 -0700 +Subject: ARM: mach-shmobile: add KZM-A9-GT board support + +This adds very basic KZM-A9-GT board (SH73a0) support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 5935278004610be17b89eab399d35ea0527bb6b2) + +Conflicts: + + arch/arm/mach-shmobile/Kconfig + arch/arm/mach-shmobile/Makefile + arch/arm/mach-shmobile/board-kzm9g.c + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/Kconfig | 5 +++ + arch/arm/mach-shmobile/Makefile | 1 + + arch/arm/mach-shmobile/board-kzm9g.c | 60 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 66 insertions(+) + create mode 100644 arch/arm/mach-shmobile/board-kzm9g.c + +diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig +index 91a4f32..23be741 100644 +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -81,6 +81,11 @@ config MACH_ARMADILLO800EVA + select ARCH_REQUIRE_GPIOLIB + select SND_SOC_WM8978 if SND_SIMPLE_CARD + ++config MACH_KZM9G ++ bool "KZM-A9-GT board" ++ depends on ARCH_SH73A0 ++ select ARCH_REQUIRE_GPIOLIB ++ + comment "SH-Mobile System Configuration" + + config CPU_HAS_INTEVT +diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile +index c599c5c..36bd37d 100644 +--- a/arch/arm/mach-shmobile/Makefile ++++ b/arch/arm/mach-shmobile/Makefile +@@ -45,6 +45,7 @@ obj-$(CONFIG_MACH_AP4EVB) += board-ap4evb.o + obj-$(CONFIG_MACH_AG5EVM) += board-ag5evm.o + obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o + obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o ++obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o + + # Framework support + obj-$(CONFIG_SMP) += $(smp-y) +diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c +new file mode 100644 +index 0000000..a7f05f6 +--- /dev/null ++++ b/arch/arm/mach-shmobile/board-kzm9g.c +@@ -0,0 +1,60 @@ ++/* ++ * KZM-A9-GT board support ++ * ++ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> ++ * ++ * 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; version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++#include <linux/gpio.h> ++#include <linux/io.h> ++#include <linux/irq.h> ++#include <linux/platform_device.h> ++#include <mach/sh73a0.h> ++#include <mach/common.h> ++#include <asm/hardware/cache-l2x0.h> ++#include <asm/hardware/gic.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++ ++static struct platform_device *kzm_devices[] __initdata = { ++}; ++ ++static void __init kzm_init(void) ++{ ++ sh73a0_pinmux_init(); ++ ++ /* enable SCIFA4 */ ++ gpio_request(GPIO_FN_SCIFA4_TXD, NULL); ++ gpio_request(GPIO_FN_SCIFA4_RXD, NULL); ++ gpio_request(GPIO_FN_SCIFA4_RTS_, NULL); ++ gpio_request(GPIO_FN_SCIFA4_CTS_, NULL); ++ ++#ifdef CONFIG_CACHE_L2X0 ++ /* Early BRESP enable, Shared attribute override enable, 64K*8way */ ++ l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff); ++#endif ++ ++ sh73a0_add_standard_devices(); ++ platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices)); ++} ++ ++MACHINE_START(KZM9G, "kzm9g") ++ .map_io = sh73a0_map_io, ++ .init_early = sh73a0_add_early_devices, ++ .nr_irqs = NR_IRQS_LEGACY, ++ .init_irq = sh73a0_init_irq, ++ .handle_irq = gic_handle_irq, ++ .init_machine = kzm_init, ++ .timer = &shmobile_timer, ++MACHINE_END +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0192-ARM-mach-shmobile-kzm9g-add-defconfig.patch b/patches.kzm9g/0192-ARM-mach-shmobile-kzm9g-add-defconfig.patch new file mode 100644 index 00000000000000..14a7dd42b1c4b0 --- /dev/null +++ b/patches.kzm9g/0192-ARM-mach-shmobile-kzm9g-add-defconfig.patch @@ -0,0 +1,155 @@ +From ed3eb21cec58c7403ba87eaf5b9a1fa79fc82432 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 10 Apr 2012 20:57:45 -0700 +Subject: ARM: mach-shmobile: kzm9g: add defconfig + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit e9ea2fb38c9d5f8cb80e359cc853fb6449f3635a) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/configs/kzm9g_defconfig | 127 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 127 insertions(+) + create mode 100644 arch/arm/configs/kzm9g_defconfig + +diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig +new file mode 100644 +index 0000000..164c5d2 +--- /dev/null ++++ b/arch/arm/configs/kzm9g_defconfig +@@ -0,0 +1,127 @@ ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++CONFIG_EXPERIMENTAL=y ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SYSVIPC=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++CONFIG_NAMESPACES=y ++# CONFIG_UTS_NS is not set ++# CONFIG_IPC_NS is not set ++# CONFIG_USER_NS is not set ++# CONFIG_PID_NS is not set ++# CONFIG_NET_NS is not set ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_EMBEDDED=y ++CONFIG_SLAB=y ++CONFIG_MODULES=y ++CONFIG_MODULE_FORCE_LOAD=y ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_IOSCHED_DEADLINE is not set ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_ARCH_SHMOBILE=y ++CONFIG_ARCH_SH73A0=y ++CONFIG_MACH_KZM9G=y ++CONFIG_MEMORY_START=0x41000000 ++CONFIG_MEMORY_SIZE=0x1f000000 ++CONFIG_ARM_ERRATA_743622=y ++CONFIG_ARM_ERRATA_754322=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_PREEMPT=y ++CONFIG_AEABI=y ++# CONFIG_OABI_COMPAT is not set ++CONFIG_HIGHMEM=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=serial" ++CONFIG_KEXEC=y ++CONFIG_VFP=y ++CONFIG_NEON=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_PM_RUNTIME=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_LRO is not set ++# CONFIG_INET_DIAG is not set ++# CONFIG_IPV6 is not set ++CONFIG_IRDA=y ++CONFIG_SH_IRDA=y ++# CONFIG_WIRELESS is not set ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_NETDEVICES=y ++CONFIG_SMSC911X=y ++# CONFIG_WLAN is not set ++CONFIG_INPUT_SPARSEKMAP=y ++# CONFIG_INPUT_MOUSEDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=y ++CONFIG_KEYBOARD_SH_KEYSC=y ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ST1232=y ++# CONFIG_LEGACY_PTYS is not set ++CONFIG_SERIAL_SH_SCI=y ++CONFIG_SERIAL_SH_SCI_NR_UARTS=9 ++CONFIG_SERIAL_SH_SCI_CONSOLE=y ++# CONFIG_HW_RANDOM is not set ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_SH_MOBILE=y ++CONFIG_POWER_SUPPLY=y ++# CONFIG_HWMON is not set ++CONFIG_FB=y ++CONFIG_FB_SH_MOBILE_LCDC=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++CONFIG_FB_SH_MOBILE_MERAM=y ++# CONFIG_HID_SUPPORT is not set ++CONFIG_USB=y ++CONFIG_USB_DEVICEFS=y ++CONFIG_USB_R8A66597_HCD=y ++CONFIG_USB_STORAGE=y ++CONFIG_MMC=y ++# CONFIG_MMC_BLOCK_BOUNCE is not set ++CONFIG_MMC_SDHI=y ++CONFIG_MMC_SH_MMCIF=y ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_RTC_CLASS=y ++CONFIG_DMADEVICES=y ++CONFIG_SH_DMAE=y ++CONFIG_ASYNC_TX_DMA=y ++CONFIG_STAGING=y ++# CONFIG_DNOTIFY is not set ++# CONFIG_INOTIFY_USER is not set ++CONFIG_VFAT_FS=y ++CONFIG_TMPFS=y ++# CONFIG_MISC_FILESYSTEMS is not set ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_V4_1=y ++CONFIG_ROOT_NFS=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_FTRACE is not set ++CONFIG_DEBUG_USER=y ++CONFIG_CRYPTO=y ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_MD5=y ++CONFIG_CRYPTO_DES=y ++CONFIG_CRC16=y +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0193-ARM-mach-shmobile-Invalidate-caches-when-booting-sec.patch b/patches.kzm9g/0193-ARM-mach-shmobile-Invalidate-caches-when-booting-sec.patch new file mode 100644 index 00000000000000..b473444b3267d9 --- /dev/null +++ b/patches.kzm9g/0193-ARM-mach-shmobile-Invalidate-caches-when-booting-sec.patch @@ -0,0 +1,97 @@ +From 2a87f8d5cd1d9ca2c80e4dcdab9adff42185567d Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Wed, 9 May 2012 16:24:59 +0900 +Subject: ARM / mach-shmobile: Invalidate caches when booting secondary cores + +Make sure L1 caches are invalidated when booting secondary +cores. Needed to boot all mach-shmobile SMP systems that +are using Cortex-A9 including sh73a0, r8a7779 and EMEV2. + +Thanks to imx and tegra guys for actual code. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 5fab7b501bf29c08c5b01627b496b6b766bd0165) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/headsmp.S | 56 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 55 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S +index 26079d9..75abb74 100644 +--- a/arch/arm/mach-shmobile/headsmp.S ++++ b/arch/arm/mach-shmobile/headsmp.S +@@ -16,6 +16,59 @@ + + __INIT + ++/* Cache invalidation nicked from arch/arm/mach-imx/head-v7.S, thanks! ++ * ++ * The secondary kernel init calls v7_flush_dcache_all before it enables ++ * the L1; however, the L1 comes out of reset in an undefined state, so ++ * the clean + invalidate performed by v7_flush_dcache_all causes a bunch ++ * of cache lines with uninitialized data and uninitialized tags to get ++ * written out to memory, which does really unpleasant things to the main ++ * processor. We fix this by performing an invalidate, rather than a ++ * clean + invalidate, before jumping into the kernel. ++ * ++ * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs ++ * to be called for both secondary cores startup and primary core resume ++ * procedures. Ideally, it should be moved into arch/arm/mm/cache-v7.S. ++ */ ++ENTRY(v7_invalidate_l1) ++ mov r0, #0 ++ mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache ++ mcr p15, 2, r0, c0, c0, 0 ++ mrc p15, 1, r0, c0, c0, 0 ++ ++ ldr r1, =0x7fff ++ and r2, r1, r0, lsr #13 ++ ++ ldr r1, =0x3ff ++ ++ and r3, r1, r0, lsr #3 @ NumWays - 1 ++ add r2, r2, #1 @ NumSets ++ ++ and r0, r0, #0x7 ++ add r0, r0, #4 @ SetShift ++ ++ clz r1, r3 @ WayShift ++ add r4, r3, #1 @ NumWays ++1: sub r2, r2, #1 @ NumSets-- ++ mov r3, r4 @ Temp = NumWays ++2: subs r3, r3, #1 @ Temp-- ++ mov r5, r3, lsl r1 ++ mov r6, r2, lsl r0 ++ orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift) ++ mcr p15, 0, r5, c7, c6, 2 ++ bgt 2b ++ cmp r2, #0 ++ bgt 1b ++ dsb ++ isb ++ mov pc, lr ++ENDPROC(v7_invalidate_l1) ++ ++ENTRY(shmobile_invalidate_start) ++ bl v7_invalidate_l1 ++ b secondary_startup ++ENDPROC(shmobile_invalidate_start) ++ + /* + * Reset vector for secondary CPUs. + * This will be mapped at address 0 by SBAR register. +@@ -24,4 +77,5 @@ + .align 12 + ENTRY(shmobile_secondary_vector) + ldr pc, 1f +-1: .long secondary_startup - PAGE_OFFSET + PLAT_PHYS_OFFSET ++1: .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET ++ENDPROC(shmobile_secondary_vector) +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0194-ARM-mach-shmobile-kzm9g-enable-SMP-boot.patch b/patches.kzm9g/0194-ARM-mach-shmobile-kzm9g-enable-SMP-boot.patch new file mode 100644 index 00000000000000..c1400e4c840887 --- /dev/null +++ b/patches.kzm9g/0194-ARM-mach-shmobile-kzm9g-enable-SMP-boot.patch @@ -0,0 +1,92 @@ +From 1b1b557076119efd097b7d294dd0a28b36e8842c Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 10 May 2012 00:10:29 -0700 +Subject: ARM: mach-shmobile: kzm9g: enable SMP boot + +Update the KZM9G defconfig and the code in platsmp.c to support SMP on +the sh73a0 based KZM9G board. Also fix up the earlyprintk setting that +was previously incorrect. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 1f3bcdd68cf4b27bddb128c401466c9fc7ba96bd) + +Conflicts: + + arch/arm/mach-shmobile/platsmp.c + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/configs/kzm9g_defconfig | 4 +++- + arch/arm/mach-shmobile/platsmp.c | 10 ++++++---- + 2 files changed, 9 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig +index 164c5d2..de8712b 100644 +--- a/arch/arm/configs/kzm9g_defconfig ++++ b/arch/arm/configs/kzm9g_defconfig +@@ -30,13 +30,15 @@ CONFIG_ARM_ERRATA_743622=y + CONFIG_ARM_ERRATA_754322=y + CONFIG_NO_HZ=y + CONFIG_HIGH_RES_TIMERS=y ++CONFIG_SMP=y ++CONFIG_SCHED_MC=y + CONFIG_PREEMPT=y + CONFIG_AEABI=y + # CONFIG_OABI_COMPAT is not set + CONFIG_HIGHMEM=y + CONFIG_ZBOOT_ROM_TEXT=0x0 + CONFIG_ZBOOT_ROM_BSS=0x0 +-CONFIG_CMDLINE="console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=serial" ++CONFIG_CMDLINE="console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200" + CONFIG_KEXEC=y + CONFIG_VFP=y + CONFIG_NEON=y +diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c +index f3888fe..2cc8930 100644 +--- a/arch/arm/mach-shmobile/platsmp.c ++++ b/arch/arm/mach-shmobile/platsmp.c +@@ -21,9 +21,11 @@ + #include <asm/mach-types.h> + #include <mach/common.h> + ++#define is_sh73a0() (machine_is_ag5evm() || machine_is_kzm9g()) ++ + static unsigned int __init shmobile_smp_get_core_count(void) + { +- if (machine_is_ag5evm()) ++ if (is_sh73a0()) + return sh73a0_get_core_count(); + + return 1; +@@ -31,7 +33,7 @@ static unsigned int __init shmobile_smp_get_core_count(void) + + static void __init shmobile_smp_prepare_cpus(void) + { +- if (machine_is_ag5evm()) ++ if (is_sh73a0()) + sh73a0_smp_prepare_cpus(); + } + +@@ -39,13 +41,13 @@ void __cpuinit platform_secondary_init(unsigned int cpu) + { + trace_hardirqs_off(); + +- if (machine_is_ag5evm()) ++ if (is_sh73a0()) + sh73a0_secondary_init(cpu); + } + + int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) + { +- if (machine_is_ag5evm()) ++ if (is_sh73a0()) + return sh73a0_boot_secondary(cpu); + + return -ENOSYS; +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0195-ARM-mach-shmobile-kzm9g-add-LCDC-support.patch b/patches.kzm9g/0195-ARM-mach-shmobile-kzm9g-add-LCDC-support.patch new file mode 100644 index 00000000000000..35748e50b4e097 --- /dev/null +++ b/patches.kzm9g/0195-ARM-mach-shmobile-kzm9g-add-LCDC-support.patch @@ -0,0 +1,204 @@ +From 769707e6bbe540cf277c165031d34f12fdd38f13 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 10 Apr 2012 20:58:33 -0700 +Subject: ARM: mach-shmobile: kzm9g: add LCDC support + +AS3711 chip initalization is required for enabling LCDC backlight, +but there is no driver for this chip. +So, this patch sends its settings when boot. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> + +Conflicts: + + arch/arm/mach-shmobile/board-kzm9g.c + +N.B: Not present in mainline yet + +Signed-off-by; Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-kzm9g.c | 144 +++++++++++++++++++++++++++++++++++ + 1 file changed, 144 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c +index a7f05f6..3e3da46 100644 +--- a/arch/arm/mach-shmobile/board-kzm9g.c ++++ b/arch/arm/mach-shmobile/board-kzm9g.c +@@ -16,20 +16,133 @@ + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ ++ ++#include <linux/delay.h> + #include <linux/gpio.h> + #include <linux/io.h> + #include <linux/irq.h> + #include <linux/platform_device.h> ++#include <linux/videodev2.h> ++#include <mach/irqs.h> + #include <mach/sh73a0.h> + #include <mach/common.h> + #include <asm/hardware/cache-l2x0.h> + #include <asm/hardware/gic.h> + #include <asm/mach-types.h> + #include <asm/mach/arch.h> ++#include <video/sh_mobile_lcdc.h> ++ ++/* LCDC */ ++static struct fb_videomode kzm_lcdc_mode = { ++ .name = "WVGA Panel", ++ .xres = 800, ++ .yres = 480, ++ .left_margin = 220, ++ .right_margin = 110, ++ .hsync_len = 70, ++ .upper_margin = 20, ++ .lower_margin = 5, ++ .vsync_len = 5, ++ .sync = 0, ++}; ++ ++static struct sh_mobile_lcdc_info lcdc_info = { ++ .clock_source = LCDC_CLK_BUS, ++ .ch[0] = { ++ .chan = LCDC_CHAN_MAINLCD, ++ .fourcc = V4L2_PIX_FMT_RGB565, ++ .interface_type = RGB24, ++ .lcd_modes = &kzm_lcdc_mode, ++ .num_modes = 1, ++ .clock_divider = 5, ++ .flags = 0, ++ .panel_cfg = { ++ .width = 152, ++ .height = 91, ++ }, ++ } ++}; ++ ++static struct resource lcdc_resources[] = { ++ [0] = { ++ .name = "LCDC", ++ .start = 0xfe940000, ++ .end = 0xfe943fff, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = intcs_evt2irq(0x580), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device lcdc_device = { ++ .name = "sh_mobile_lcdc_fb", ++ .num_resources = ARRAY_SIZE(lcdc_resources), ++ .resource = lcdc_resources, ++ .dev = { ++ .platform_data = &lcdc_info, ++ .coherent_dma_mask = ~0, ++ }, ++}; + + static struct platform_device *kzm_devices[] __initdata = { ++ &lcdc_device, + }; + ++/* ++ * FIXME ++ * ++ * This is quick hack for enabling LCDC backlight ++ */ ++static int __init as3711_enable_lcdc_backlight(void) ++{ ++ struct i2c_adapter *a = i2c_get_adapter(0); ++ struct i2c_msg msg; ++ int i, ret; ++ __u8 magic[] = { ++ 0x40, 0x2a, ++ 0x43, 0x3c, ++ 0x44, 0x3c, ++ 0x45, 0x3c, ++ 0x54, 0x03, ++ 0x51, 0x00, ++ 0x51, 0x01, ++ 0xff, 0x00, /* wait */ ++ 0x43, 0xf0, ++ 0x44, 0xf0, ++ 0x45, 0xf0, ++ }; ++ ++ if (!machine_is_kzm9g()) ++ return 0; ++ ++ if (!a) ++ return 0; ++ ++ msg.addr = 0x40; ++ msg.len = 2; ++ msg.flags = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(magic); i += 2) { ++ msg.buf = magic + i; ++ ++ if (0xff == msg.buf[0]) { ++ udelay(500); ++ continue; ++ } ++ ++ ret = i2c_transfer(a, &msg, 1); ++ if (ret < 0) { ++ pr_err("i2c transfer fail\n"); ++ break; ++ } ++ } ++ ++ return 0; ++} ++device_initcall(as3711_enable_lcdc_backlight); ++ + static void __init kzm_init(void) + { + sh73a0_pinmux_init(); +@@ -40,6 +153,37 @@ static void __init kzm_init(void) + gpio_request(GPIO_FN_SCIFA4_RTS_, NULL); + gpio_request(GPIO_FN_SCIFA4_CTS_, NULL); + ++ /* LCDC */ ++ gpio_request(GPIO_FN_LCDD23, NULL); ++ gpio_request(GPIO_FN_LCDD22, NULL); ++ gpio_request(GPIO_FN_LCDD21, NULL); ++ gpio_request(GPIO_FN_LCDD20, NULL); ++ gpio_request(GPIO_FN_LCDD19, NULL); ++ gpio_request(GPIO_FN_LCDD18, NULL); ++ gpio_request(GPIO_FN_LCDD17, NULL); ++ gpio_request(GPIO_FN_LCDD16, NULL); ++ gpio_request(GPIO_FN_LCDD15, NULL); ++ gpio_request(GPIO_FN_LCDD14, NULL); ++ gpio_request(GPIO_FN_LCDD13, NULL); ++ gpio_request(GPIO_FN_LCDD12, NULL); ++ gpio_request(GPIO_FN_LCDD11, NULL); ++ gpio_request(GPIO_FN_LCDD10, NULL); ++ gpio_request(GPIO_FN_LCDD9, NULL); ++ gpio_request(GPIO_FN_LCDD8, NULL); ++ gpio_request(GPIO_FN_LCDD7, NULL); ++ gpio_request(GPIO_FN_LCDD6, NULL); ++ gpio_request(GPIO_FN_LCDD5, NULL); ++ gpio_request(GPIO_FN_LCDD4, NULL); ++ gpio_request(GPIO_FN_LCDD3, NULL); ++ gpio_request(GPIO_FN_LCDD2, NULL); ++ gpio_request(GPIO_FN_LCDD1, NULL); ++ gpio_request(GPIO_FN_LCDD0, NULL); ++ gpio_request(GPIO_FN_LCDDISP, NULL); ++ gpio_request(GPIO_FN_LCDDCK, NULL); ++ ++ gpio_request(GPIO_PORT222, NULL); ++ gpio_direction_output(GPIO_PORT222, 1); ++ + #ifdef CONFIG_CACHE_L2X0 + /* Early BRESP enable, Shared attribute override enable, 64K*8way */ + l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0196-ARM-mach-shmobile-kzm9g-add-ST1232-Touchscreen-suppo.patch b/patches.kzm9g/0196-ARM-mach-shmobile-kzm9g-add-ST1232-Touchscreen-suppo.patch new file mode 100644 index 00000000000000..a01de3958ec6f4 --- /dev/null +++ b/patches.kzm9g/0196-ARM-mach-shmobile-kzm9g-add-ST1232-Touchscreen-suppo.patch @@ -0,0 +1,65 @@ +From ce9a312895c8fb5fc0115d5ed5f4434382d4ed8c Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 10 Apr 2012 20:58:45 -0700 +Subject: ARM: mach-shmobile: kzm9g: add ST1232 Touchscreen support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 3ab21c0e494efe064b425d48ac985cde5ee7f84b) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-kzm9g.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c +index 3e3da46..f6a0b4f 100644 +--- a/arch/arm/mach-shmobile/board-kzm9g.c ++++ b/arch/arm/mach-shmobile/board-kzm9g.c +@@ -21,6 +21,7 @@ + #include <linux/gpio.h> + #include <linux/io.h> + #include <linux/irq.h> ++#include <linux/i2c.h> + #include <linux/platform_device.h> + #include <linux/videodev2.h> + #include <mach/irqs.h> +@@ -86,6 +87,13 @@ static struct platform_device lcdc_device = { + }, + }; + ++static struct i2c_board_info i2c1_devices[] = { ++ { ++ I2C_BOARD_INFO("st1232-ts", 0x55), ++ .irq = intcs_evt2irq(0x300), /* IRQ8 */ ++ }, ++}; ++ + static struct platform_device *kzm_devices[] __initdata = { + &lcdc_device, + }; +@@ -184,11 +192,17 @@ static void __init kzm_init(void) + gpio_request(GPIO_PORT222, NULL); + gpio_direction_output(GPIO_PORT222, 1); + ++ /* Touchscreen */ ++ gpio_request(GPIO_PORT223, NULL); /* IRQ8 */ ++ gpio_direction_input(GPIO_PORT223); ++ + #ifdef CONFIG_CACHE_L2X0 + /* Early BRESP enable, Shared attribute override enable, 64K*8way */ + l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff); + #endif + ++ i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices)); ++ + sh73a0_add_standard_devices(); + platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices)); + } +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0197-ARM-mach-shmobile-pfc-sh73a0-fixup-MSEL2CR-MSEL18-fo.patch b/patches.kzm9g/0197-ARM-mach-shmobile-pfc-sh73a0-fixup-MSEL2CR-MSEL18-fo.patch new file mode 100644 index 00000000000000..2c262cfbe501ab --- /dev/null +++ b/patches.kzm9g/0197-ARM-mach-shmobile-pfc-sh73a0-fixup-MSEL2CR-MSEL18-fo.patch @@ -0,0 +1,44 @@ +From 035b90a42dfd87de422594b3f28649d5d8473bbf Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 22 Apr 2012 23:52:48 -0700 +Subject: ARM: mach-shmobile: pfc-sh73a0: fixup MSEL2CR MSEL18 for I2C-3 + +MSEL2CR MSEL18 should be 1 if I2C-3 + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 0abfeea3f3664f55f21691ac37e9570a60733d4a) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/pfc-sh73a0.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c +index e05634c..4a547b8 100644 +--- a/arch/arm/mach-shmobile/pfc-sh73a0.c ++++ b/arch/arm/mach-shmobile/pfc-sh73a0.c +@@ -829,14 +829,14 @@ static pinmux_enum_t pinmux_data[] = { + PINMUX_DATA(PORT27_I2C_SCL2_MARK, PORT27_FN2, MSEL2CR_MSEL17_0, + MSEL2CR_MSEL16_1), \ + PINMUX_DATA(PORT27_I2C_SCL3_MARK, PORT27_FN3, MSEL2CR_MSEL19_0, +- MSEL2CR_MSEL18_0), \ ++ MSEL2CR_MSEL18_1), \ + PINMUX_DATA(MFG0_OUT1_MARK, PORT27_FN4), \ + PINMUX_DATA(PORT27_IROUT_MARK, PORT27_FN7), + PINMUX_DATA(XDVFS2_MARK, PORT28_FN1), \ + PINMUX_DATA(PORT28_I2C_SDA2_MARK, PORT28_FN2, MSEL2CR_MSEL17_0, + MSEL2CR_MSEL16_1), \ + PINMUX_DATA(PORT28_I2C_SDA3_MARK, PORT28_FN3, MSEL2CR_MSEL19_0, +- MSEL2CR_MSEL18_0), \ ++ MSEL2CR_MSEL18_1), \ + PINMUX_DATA(PORT28_TPU1TO1_MARK, PORT28_FN7), + PINMUX_DATA(SIM_RST_MARK, PORT29_FN1), \ + PINMUX_DATA(PORT29_TPU1TO1_MARK, PORT29_FN4), +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0198-ARM-mach-shmobile-sh73a0.h-add-GPIO_NR.patch b/patches.kzm9g/0198-ARM-mach-shmobile-sh73a0.h-add-GPIO_NR.patch new file mode 100644 index 00000000000000..16e18fa18327ac --- /dev/null +++ b/patches.kzm9g/0198-ARM-mach-shmobile-sh73a0.h-add-GPIO_NR.patch @@ -0,0 +1,38 @@ +From 69ba92bca9d23c243e05e120711d7f08684b6ab6 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 22 Apr 2012 23:53:07 -0700 +Subject: ARM: mach-shmobile: sh73a0.h: add GPIO_NR + +GPIO_NR is added in order to clarify end of GPIO array. +We can add extra GPIO from it. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 9f75dc78817e88353e37fab381b26e7e2d825f82) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/sh73a0.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h +index cad5757..ac75857 100644 +--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h ++++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h +@@ -482,6 +482,9 @@ enum { + GPIO_FN_FSIAILR_PU, + GPIO_FN_FSIAIBT_PU, + GPIO_FN_FSIAISLD_PU, ++ ++ /* end of GPIO */ ++ GPIO_NR, + }; + + /* DMA slave IDs */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0199-ARM-mach-shmobile-kzm9g-correct-screen-direction.patch b/patches.kzm9g/0199-ARM-mach-shmobile-kzm9g-correct-screen-direction.patch new file mode 100644 index 00000000000000..4fee96b17089ab --- /dev/null +++ b/patches.kzm9g/0199-ARM-mach-shmobile-kzm9g-correct-screen-direction.patch @@ -0,0 +1,40 @@ +From d2ff6b7cebae68d0d9214c3da5494392fc7fca86 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 22 Apr 2012 23:53:24 -0700 +Subject: ARM: mach-shmobile: kzm9g: correct screen direction + +The correct screen direction of KZM9G board needs +PORT226/SC settings. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit d0e0f1d0aa08fc01530ce48dce490a4401d35a5d) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-kzm9g.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c +index f6a0b4f..5674147 100644 +--- a/arch/arm/mach-shmobile/board-kzm9g.c ++++ b/arch/arm/mach-shmobile/board-kzm9g.c +@@ -189,8 +189,10 @@ static void __init kzm_init(void) + gpio_request(GPIO_FN_LCDDISP, NULL); + gpio_request(GPIO_FN_LCDDCK, NULL); + +- gpio_request(GPIO_PORT222, NULL); ++ gpio_request(GPIO_PORT222, NULL); /* LCDCDON */ ++ gpio_request(GPIO_PORT226, NULL); /* SC */ + gpio_direction_output(GPIO_PORT222, 1); ++ gpio_direction_output(GPIO_PORT226, 1); + + /* Touchscreen */ + gpio_request(GPIO_PORT223, NULL); /* IRQ8 */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0200-ARM-mach-shmobile-kzm9g-add-MMCIF-support.patch b/patches.kzm9g/0200-ARM-mach-shmobile-kzm9g-add-MMCIF-support.patch new file mode 100644 index 00000000000000..9537d6f6f2dddc --- /dev/null +++ b/patches.kzm9g/0200-ARM-mach-shmobile-kzm9g-add-MMCIF-support.patch @@ -0,0 +1,106 @@ +From 29e424292a84c4db615e64beff9ed6ee66b11ca5 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 22 Apr 2012 23:53:40 -0700 +Subject: ARM: mach-shmobile: kzm9g: add MMCIF support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 9cf94db3e4281bd6597d6bb585253106226882f3) + +Conflicts: + + arch/arm/mach-shmobile/board-kzm9g.c + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-kzm9g.c | 49 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c +index 5674147..5b486ae 100644 +--- a/arch/arm/mach-shmobile/board-kzm9g.c ++++ b/arch/arm/mach-shmobile/board-kzm9g.c +@@ -22,6 +22,8 @@ + #include <linux/io.h> + #include <linux/irq.h> + #include <linux/i2c.h> ++#include <linux/mmc/host.h> ++#include <linux/mmc/sh_mmcif.h> + #include <linux/platform_device.h> + #include <linux/videodev2.h> + #include <mach/irqs.h> +@@ -87,6 +89,40 @@ static struct platform_device lcdc_device = { + }, + }; + ++/* MMCIF */ ++static struct resource sh_mmcif_resources[] = { ++ [0] = { ++ .name = "MMCIF", ++ .start = 0xe6bd0000, ++ .end = 0xe6bd00ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = gic_spi(141), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [2] = { ++ .start = gic_spi(140), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct sh_mmcif_plat_data sh_mmcif_platdata = { ++ .ocr = MMC_VDD_165_195, ++ .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, ++}; ++ ++static struct platform_device mmc_device = { ++ .name = "sh_mmcif", ++ .dev = { ++ .dma_mask = NULL, ++ .coherent_dma_mask = 0xffffffff, ++ .platform_data = &sh_mmcif_platdata, ++ }, ++ .num_resources = ARRAY_SIZE(sh_mmcif_resources), ++ .resource = sh_mmcif_resources, ++}; ++ + static struct i2c_board_info i2c1_devices[] = { + { + I2C_BOARD_INFO("st1232-ts", 0x55), +@@ -96,6 +132,7 @@ static struct i2c_board_info i2c1_devices[] = { + + static struct platform_device *kzm_devices[] __initdata = { + &lcdc_device, ++ &mmc_device, + }; + + /* +@@ -198,6 +235,18 @@ static void __init kzm_init(void) + gpio_request(GPIO_PORT223, NULL); /* IRQ8 */ + gpio_direction_input(GPIO_PORT223); + ++ /* enable MMCIF */ ++ gpio_request(GPIO_FN_MMCCLK0, NULL); ++ gpio_request(GPIO_FN_MMCCMD0_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_0_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_1_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_2_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_3_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_4_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_5_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_6_PU, NULL); ++ gpio_request(GPIO_FN_MMCD0_7_PU, NULL); ++ + #ifdef CONFIG_CACHE_L2X0 + /* Early BRESP enable, Shared attribute override enable, 64K*8way */ + l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0201-ARM-mach-shmobile-kzm9g-add-SDHI-support.patch b/patches.kzm9g/0201-ARM-mach-shmobile-kzm9g-add-SDHI-support.patch new file mode 100644 index 00000000000000..07c931e3a0a8e0 --- /dev/null +++ b/patches.kzm9g/0201-ARM-mach-shmobile-kzm9g-add-SDHI-support.patch @@ -0,0 +1,110 @@ +From 27b7da290bfcf60ddaac4156bebd710b96cfdcc0 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 22 Apr 2012 23:53:59 -0700 +Subject: ARM: mach-shmobile: kzm9g: add SDHI support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit d80a008054f895469e955975740bf07751c1449f) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-kzm9g.c | 57 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 57 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c +index 5b486ae..a964e56 100644 +--- a/arch/arm/mach-shmobile/board-kzm9g.c ++++ b/arch/arm/mach-shmobile/board-kzm9g.c +@@ -24,6 +24,8 @@ + #include <linux/i2c.h> + #include <linux/mmc/host.h> + #include <linux/mmc/sh_mmcif.h> ++#include <linux/mmc/sh_mobile_sdhi.h> ++#include <linux/mfd/tmio.h> + #include <linux/platform_device.h> + #include <linux/videodev2.h> + #include <mach/irqs.h> +@@ -123,6 +125,47 @@ static struct platform_device mmc_device = { + .resource = sh_mmcif_resources, + }; + ++/* SDHI */ ++static struct sh_mobile_sdhi_info sdhi0_info = { ++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, ++ .tmio_caps = MMC_CAP_SD_HIGHSPEED, ++ .tmio_ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29, ++}; ++ ++static struct resource sdhi0_resources[] = { ++ [0] = { ++ .name = "SDHI0", ++ .start = 0xee100000, ++ .end = 0xee1000ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT, ++ .start = gic_spi(83), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [2] = { ++ .name = SH_MOBILE_SDHI_IRQ_SDCARD, ++ .start = gic_spi(84), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [3] = { ++ .name = SH_MOBILE_SDHI_IRQ_SDIO, ++ .start = gic_spi(85), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device sdhi0_device = { ++ .name = "sh_mobile_sdhi", ++ .num_resources = ARRAY_SIZE(sdhi0_resources), ++ .resource = sdhi0_resources, ++ .dev = { ++ .platform_data = &sdhi0_info, ++ }, ++}; ++ ++/* I2C */ + static struct i2c_board_info i2c1_devices[] = { + { + I2C_BOARD_INFO("st1232-ts", 0x55), +@@ -133,6 +176,7 @@ static struct i2c_board_info i2c1_devices[] = { + static struct platform_device *kzm_devices[] __initdata = { + &lcdc_device, + &mmc_device, ++ &sdhi0_device, + }; + + /* +@@ -247,6 +291,19 @@ static void __init kzm_init(void) + gpio_request(GPIO_FN_MMCD0_6_PU, NULL); + gpio_request(GPIO_FN_MMCD0_7_PU, NULL); + ++ /* enable SD */ ++ gpio_request(GPIO_FN_SDHIWP0, NULL); ++ gpio_request(GPIO_FN_SDHICD0, NULL); ++ gpio_request(GPIO_FN_SDHICMD0, NULL); ++ gpio_request(GPIO_FN_SDHICLK0, NULL); ++ gpio_request(GPIO_FN_SDHID0_3, NULL); ++ gpio_request(GPIO_FN_SDHID0_2, NULL); ++ gpio_request(GPIO_FN_SDHID0_1, NULL); ++ gpio_request(GPIO_FN_SDHID0_0, NULL); ++ gpio_request(GPIO_FN_SDHI0_VCCQ_MC0_ON, NULL); ++ gpio_request(GPIO_PORT15, NULL); ++ gpio_direction_output(GPIO_PORT15, 1); /* power */ ++ + #ifdef CONFIG_CACHE_L2X0 + /* Early BRESP enable, Shared attribute override enable, 64K*8way */ + l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0202-ARM-mach-shmobile-kzm9g-add-PCF8757-gpio-key.patch b/patches.kzm9g/0202-ARM-mach-shmobile-kzm9g-add-PCF8757-gpio-key.patch new file mode 100644 index 00000000000000..5f9909fbcc14c3 --- /dev/null +++ b/patches.kzm9g/0202-ARM-mach-shmobile-kzm9g-add-PCF8757-gpio-key.patch @@ -0,0 +1,140 @@ +From f1f2cdcdd22c1c750f6cee76e6af0ce531fa5b21 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 22 Apr 2012 23:54:14 -0700 +Subject: ARM: mach-shmobile: kzm9g: add PCF8757 gpio-key + +This patch adds extra GPIO via PCF8757 chip, +and use it as gpio-key. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit d5fbabd3d5ab8c06d4f576efb63cd2af65a729ae) + +Conflicts: + + arch/arm/mach-shmobile/board-kzm9g.c + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-kzm9g.c | 59 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 59 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c +index a964e56..7289ed5 100644 +--- a/arch/arm/mach-shmobile/board-kzm9g.c ++++ b/arch/arm/mach-shmobile/board-kzm9g.c +@@ -19,9 +19,12 @@ + + #include <linux/delay.h> + #include <linux/gpio.h> ++#include <linux/gpio_keys.h> + #include <linux/io.h> + #include <linux/irq.h> + #include <linux/i2c.h> ++#include <linux/i2c/pcf857x.h> ++#include <linux/input.h> + #include <linux/mmc/host.h> + #include <linux/mmc/sh_mmcif.h> + #include <linux/mmc/sh_mobile_sdhi.h> +@@ -37,6 +40,18 @@ + #include <asm/mach/arch.h> + #include <video/sh_mobile_lcdc.h> + ++/* ++ * external GPIO ++ */ ++#define GPIO_PCF8575_BASE (GPIO_NR) ++#define GPIO_PCF8575_PORT10 (GPIO_NR + 8) ++#define GPIO_PCF8575_PORT11 (GPIO_NR + 9) ++#define GPIO_PCF8575_PORT12 (GPIO_NR + 10) ++#define GPIO_PCF8575_PORT13 (GPIO_NR + 11) ++#define GPIO_PCF8575_PORT14 (GPIO_NR + 12) ++#define GPIO_PCF8575_PORT15 (GPIO_NR + 13) ++#define GPIO_PCF8575_PORT16 (GPIO_NR + 14) ++ + /* LCDC */ + static struct fb_videomode kzm_lcdc_mode = { + .name = "WVGA Panel", +@@ -165,7 +180,38 @@ static struct platform_device sdhi0_device = { + }, + }; + ++/* KEY */ ++#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } ++ ++static struct gpio_keys_button gpio_buttons[] = { ++ GPIO_KEY(KEY_BACK, GPIO_PCF8575_PORT10, "SW3"), ++ GPIO_KEY(KEY_RIGHT, GPIO_PCF8575_PORT11, "SW2-R"), ++ GPIO_KEY(KEY_LEFT, GPIO_PCF8575_PORT12, "SW2-L"), ++ GPIO_KEY(KEY_ENTER, GPIO_PCF8575_PORT13, "SW2-P"), ++ GPIO_KEY(KEY_UP, GPIO_PCF8575_PORT14, "SW2-U"), ++ GPIO_KEY(KEY_DOWN, GPIO_PCF8575_PORT15, "SW2-D"), ++ GPIO_KEY(KEY_HOME, GPIO_PCF8575_PORT16, "SW1"), ++}; ++ ++static struct gpio_keys_platform_data gpio_key_info = { ++ .buttons = gpio_buttons, ++ .nbuttons = ARRAY_SIZE(gpio_buttons), ++ .poll_interval = 250, /* poling at this point */ ++}; ++ ++static struct platform_device gpio_keys_device = { ++ /* gpio-pcf857x.c driver doesn't support gpio_to_irq() */ ++ .name = "gpio-keys-polled", ++ .dev = { ++ .platform_data = &gpio_key_info, ++ }, ++}; ++ + /* I2C */ ++static struct pcf857x_platform_data pcf8575_pdata = { ++ .gpio_base = GPIO_PCF8575_BASE, ++}; ++ + static struct i2c_board_info i2c1_devices[] = { + { + I2C_BOARD_INFO("st1232-ts", 0x55), +@@ -173,10 +219,18 @@ static struct i2c_board_info i2c1_devices[] = { + }, + }; + ++static struct i2c_board_info i2c3_devices[] = { ++ { ++ I2C_BOARD_INFO("pcf8575", 0x20), ++ .platform_data = &pcf8575_pdata, ++ }, ++}; ++ + static struct platform_device *kzm_devices[] __initdata = { + &lcdc_device, + &mmc_device, + &sdhi0_device, ++ &gpio_keys_device, + }; + + /* +@@ -304,12 +358,17 @@ static void __init kzm_init(void) + gpio_request(GPIO_PORT15, NULL); + gpio_direction_output(GPIO_PORT15, 1); /* power */ + ++ /* I2C 3 */ ++ gpio_request(GPIO_FN_PORT27_I2C_SCL3, NULL); ++ gpio_request(GPIO_FN_PORT28_I2C_SDA3, NULL); ++ + #ifdef CONFIG_CACHE_L2X0 + /* Early BRESP enable, Shared attribute override enable, 64K*8way */ + l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff); + #endif + + i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices)); ++ i2c_register_board_info(3, i2c3_devices, ARRAY_SIZE(i2c3_devices)); + + sh73a0_add_standard_devices(); + platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices)); +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0203-ARM-mach-shmobile-kzm9g-defconfig-update.patch b/patches.kzm9g/0203-ARM-mach-shmobile-kzm9g-defconfig-update.patch new file mode 100644 index 00000000000000..1ccf5bdd609a8c --- /dev/null +++ b/patches.kzm9g/0203-ARM-mach-shmobile-kzm9g-defconfig-update.patch @@ -0,0 +1,88 @@ +From 68fa5ce1e0101a7d9d78d485dd3245b583ef88f6 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Wed, 25 Apr 2012 20:58:06 -0700 +Subject: ARM: mach-shmobile: kzm9g: defconfig update + +This patch enable GPIO-KEY/FSI, +and remove debug settings, +and be cleanuped by c2330e286f68f1c408b4aa6515ba49d57f05beae script + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit cc2504524b5b14dc03682dc1f04fb1644f692767) + +N.B: Not present in mainline yet + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/configs/kzm9g_defconfig | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig +index de8712b..e3ebc20 100644 +--- a/arch/arm/configs/kzm9g_defconfig ++++ b/arch/arm/configs/kzm9g_defconfig +@@ -22,6 +22,7 @@ CONFIG_MODULE_UNLOAD=y + # CONFIG_IOSCHED_DEADLINE is not set + # CONFIG_IOSCHED_CFQ is not set + CONFIG_ARCH_SHMOBILE=y ++CONFIG_KEYBOARD_GPIO_POLLED=y + CONFIG_ARCH_SH73A0=y + CONFIG_MACH_KZM9G=y + CONFIG_MEMORY_START=0x41000000 +@@ -69,8 +70,6 @@ CONFIG_INPUT_SPARSEKMAP=y + # CONFIG_INPUT_MOUSEDEV is not set + CONFIG_INPUT_EVDEV=y + # CONFIG_KEYBOARD_ATKBD is not set +-CONFIG_KEYBOARD_GPIO=y +-CONFIG_KEYBOARD_SH_KEYSC=y + # CONFIG_INPUT_MOUSE is not set + CONFIG_INPUT_TOUCHSCREEN=y + CONFIG_TOUCHSCREEN_ST1232=y +@@ -81,13 +80,22 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y + # CONFIG_HW_RANDOM is not set + CONFIG_I2C_CHARDEV=y + CONFIG_I2C_SH_MOBILE=y +-CONFIG_POWER_SUPPLY=y ++CONFIG_GPIO_PCF857X=y + # CONFIG_HWMON is not set + CONFIG_FB=y + CONFIG_FB_SH_MOBILE_LCDC=y + CONFIG_FRAMEBUFFER_CONSOLE=y + CONFIG_LOGO=y + CONFIG_FB_SH_MOBILE_MERAM=y ++CONFIG_SOUND=y ++CONFIG_SND=y ++# CONFIG_SND_SUPPORT_OLD_API is not set ++# CONFIG_SND_VERBOSE_PROCFS is not set ++# CONFIG_SND_DRIVERS is not set ++# CONFIG_SND_ARM is not set ++# CONFIG_SND_USB is not set ++CONFIG_SND_SOC=y ++CONFIG_SND_SOC_SH4_FSI=y + # CONFIG_HID_SUPPORT is not set + CONFIG_USB=y + CONFIG_USB_DEVICEFS=y +@@ -117,11 +125,13 @@ CONFIG_NFS_V4_1=y + CONFIG_ROOT_NFS=y + CONFIG_NLS_CODEPAGE_437=y + CONFIG_NLS_ISO8859_1=y +-CONFIG_MAGIC_SYSRQ=y +-CONFIG_DETECT_HUNG_TASK=y +-CONFIG_DEBUG_INFO=y ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_DEBUG_PREEMPT is not set ++# CONFIG_DEBUG_BUGVERBOSE is not set + # CONFIG_FTRACE is not set +-CONFIG_DEBUG_USER=y ++# CONFIG_ARM_UNWIND is not set + CONFIG_CRYPTO=y + CONFIG_CRYPTO_CBC=y + CONFIG_CRYPTO_MD5=y +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0204-ARM-mach-shmobile-clock-sh73a0-add-FSI-clock.patch b/patches.kzm9g/0204-ARM-mach-shmobile-clock-sh73a0-add-FSI-clock.patch new file mode 100644 index 00000000000000..270f943c78bf72 --- /dev/null +++ b/patches.kzm9g/0204-ARM-mach-shmobile-clock-sh73a0-add-FSI-clock.patch @@ -0,0 +1,46 @@ +From 390deea0373e34a3e2f85ca0917ebb7c595f84fb Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 Apr 2012 00:03:10 -0700 +Subject: ARM: mach-shmobile: clock-sh73a0: add FSI clock + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + +N.B: Not present upstream + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-sh73a0.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c +index 41f8293..012b284 100644 +--- a/arch/arm/mach-shmobile/clock-sh73a0.c ++++ b/arch/arm/mach-shmobile/clock-sh73a0.c +@@ -476,7 +476,7 @@ enum { MSTP001, + MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100, + MSTP219, + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, +- MSTP331, MSTP329, MSTP325, MSTP323, MSTP318, ++ MSTP331, MSTP329, MSTP328, MSTP325, MSTP323, MSTP318, + MSTP314, MSTP313, MSTP312, MSTP311, + MSTP303, MSTP302, MSTP301, MSTP300, + MSTP411, MSTP410, MSTP403, +@@ -505,6 +505,7 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ + [MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */ + [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ ++ [MSTP328] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /*FSI*/ + [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */ + [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */ + [MSTP318] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 18, 0), /* SY-DMAC */ +@@ -560,6 +561,7 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ + CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */ + CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ ++ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */ + CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */ + CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */ + CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP318]), /* SY-DMAC */ +-- +1.7.10.2.565.gbd578b5 + diff --git a/patches.kzm9g/0205-ARM-mach-shmobile-kzm9g-add-FSI-AK4648-support.patch b/patches.kzm9g/0205-ARM-mach-shmobile-kzm9g-add-FSI-AK4648-support.patch new file mode 100644 index 00000000000000..6c75eb1ffbbb74 --- /dev/null +++ b/patches.kzm9g/0205-ARM-mach-shmobile-kzm9g-add-FSI-AK4648-support.patch @@ -0,0 +1,162 @@ +From 850ebb2205ed29cae92c91419d06fb9e91a2cafa Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 23 Apr 2012 00:03:25 -0700 +Subject: ARM: mach-shmobile: kzm9g: add FSI-AK4648 support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + +Conflicts: + + arch/arm/mach-shmobile/board-kzm9g.c + +N.B: Not present upstream + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/Kconfig | 1 + + arch/arm/mach-shmobile/board-kzm9g.c | 79 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 80 insertions(+) + +diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig +index 23be741..9020c1b 100644 +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -85,6 +85,7 @@ config MACH_KZM9G + bool "KZM-A9-GT board" + depends on ARCH_SH73A0 + select ARCH_REQUIRE_GPIOLIB ++ select SND_SOC_AK4642 if SND_SIMPLE_CARD + + comment "SH-Mobile System Configuration" + +diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c +index 7289ed5..855ae85 100644 +--- a/arch/arm/mach-shmobile/board-kzm9g.c ++++ b/arch/arm/mach-shmobile/board-kzm9g.c +@@ -31,6 +31,8 @@ + #include <linux/mfd/tmio.h> + #include <linux/platform_device.h> + #include <linux/videodev2.h> ++#include <sound/sh_fsi.h> ++#include <sound/simple_card.h> + #include <mach/irqs.h> + #include <mach/sh73a0.h> + #include <mach/common.h> +@@ -52,6 +54,14 @@ + #define GPIO_PCF8575_PORT15 (GPIO_NR + 13) + #define GPIO_PCF8575_PORT16 (GPIO_NR + 14) + ++/* ++ * FSI-AK4648 ++ * ++ * this command is required when playback. ++ * ++ * # amixer set "LINEOUT Mixer DACL" on ++ */ ++ + /* LCDC */ + static struct fb_videomode kzm_lcdc_mode = { + .name = "WVGA Panel", +@@ -207,11 +217,70 @@ static struct platform_device gpio_keys_device = { + }, + }; + ++/* FSI-AK4648 */ ++static struct sh_fsi_platform_info fsi_info = { ++ .port_a = { ++ }, ++}; ++ ++static struct resource fsi_resources[] = { ++ [0] = { ++ .name = "FSI", ++ .start = 0xEC230000, ++ .end = 0xEC230400 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = gic_spi(146), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device fsi_device = { ++ .name = "sh_fsi2", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(fsi_resources), ++ .resource = fsi_resources, ++ .dev = { ++ .platform_data = &fsi_info, ++ }, ++}; ++ ++static struct asoc_simple_dai_init_info fsi2_ak4648_init_info = { ++ .fmt = SND_SOC_DAIFMT_LEFT_J, ++ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM, ++ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS, ++ .sysclk = 11289600, ++}; ++ ++static struct asoc_simple_card_info fsi2_ak4648_info = { ++ .name = "AK4648", ++ .card = "FSI2A-AK4648", ++ .cpu_dai = "fsia-dai", ++ .codec = "ak4642-codec.0-0012", ++ .platform = "sh_fsi2", ++ .codec_dai = "ak4642-hifi", ++ .init = &fsi2_ak4648_init_info, ++}; ++ ++static struct platform_device fsi_ak4648_device = { ++ .name = "asoc-simple-card", ++ .dev = { ++ .platform_data = &fsi2_ak4648_info, ++ }, ++}; ++ + /* I2C */ + static struct pcf857x_platform_data pcf8575_pdata = { + .gpio_base = GPIO_PCF8575_BASE, + }; + ++static struct i2c_board_info i2c0_devices[] = { ++ { ++ I2C_BOARD_INFO("ak4648", 0x12), ++ } ++}; ++ + static struct i2c_board_info i2c1_devices[] = { + { + I2C_BOARD_INFO("st1232-ts", 0x55), +@@ -231,6 +300,8 @@ static struct platform_device *kzm_devices[] __initdata = { + &mmc_device, + &sdhi0_device, + &gpio_keys_device, ++ &fsi_device, ++ &fsi_ak4648_device, + }; + + /* +@@ -362,11 +433,19 @@ static void __init kzm_init(void) + gpio_request(GPIO_FN_PORT27_I2C_SCL3, NULL); + gpio_request(GPIO_FN_PORT28_I2C_SDA3, NULL); + ++ /* enable FSI2 port A (ak4648) */ ++ gpio_request(GPIO_FN_FSIACK, NULL); ++ gpio_request(GPIO_FN_FSIAILR, NULL); ++ gpio_request(GPIO_FN_FSIAIBT, NULL); ++ gpio_request(GPIO_FN_FSIAISLD, NULL); ++ gpio_request(GPIO_FN_FSIAOSLD, NULL); ++ + #ifdef CONFIG_CACHE_L2X0 + /* Early BRESP enable, Shared attribute override enable, 64K*8way */ + l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff); + #endif + ++ i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); + i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices)); + i2c_register_board_info(3, i2c3_devices, ARRAY_SIZE(i2c3_devices)); + +-- +1.7.10.2.565.gbd578b5 + @@ -584,3 +584,210 @@ patches.pramfs/14-pramfs-memory-write-protection.patch patches.pramfs/15-pramfs-test-module.patch patches.pramfs/16-pramfs-ioctl-operations.patch patches.pramfs/17-pramfs-makefile-and-kconfig.patch + + +patches.kzm9g/0001-net-remove-mm.h-inclusion-from-netdevice.h.patch +patches.kzm9g/0002-Include-linux-dma-mapping.h-in-linux-dmaengine.h.patch +patches.kzm9g/0003-dmaengine-failure-to-get-a-specific-DMA-channel-is-n.patch +patches.kzm9g/0004-Improve-slave-cyclic-DMA-engine-documentation.patch +patches.kzm9g/0005-dmaengine-use-DEFINE_IDR-for-static-initialization.patch +patches.kzm9g/0006-dmaengine-add-helper-function-for-slave_single.patch +patches.kzm9g/0007-dmaengine-remove-struct-scatterlist-for-header.patch +patches.kzm9g/0008-dmaengine-add-new-enum-dma_transfer_direction.patch +patches.kzm9g/0009-linux-dmaengine.h-fix-implicit-use-of-bitmap.h-and-a.patch +patches.kzm9g/0010-DMAEngine-Define-interleaved-transfer-request-api.patch +patches.kzm9g/0011-dmaengine-add-DMA_TRANS_NONE-to-dma_transfer_directi.patch +patches.kzm9g/0012-dmaengine-Add-flow-controller-information-to-dma_sla.patch +patches.kzm9g/0013-dma-dmaengine-Distinguish-between-dmaengine-failed-t.patch +patches.kzm9g/0014-dmaengine-add-private-header-file.patch +patches.kzm9g/0015-dmaengine-dma_slave-introduce-inline-wrappers.patch +patches.kzm9g/0016-ARM-Add-init_consistent_dma_size.patch +patches.kzm9g/0017-mmc-add-a-card-hotplug-handler-context.patch +patches.kzm9g/0018-mmc-add-a-generic-GPIO-card-detect-helper.patch +patches.kzm9g/0019-mmc-simplify-mmc_cd_gpio_request-by-removing-two-par.patch +patches.kzm9g/0020-mmc-Standardize-header-file-inclusion-checks.patch +patches.kzm9g/0021-mmc-tmio-name-0xd8-as-CTL_DMA_ENABLE.patch +patches.kzm9g/0022-mmc-tmio-Share-register-access-functions.patch +patches.kzm9g/0023-mmc-sdhi-Add-write16_hook.patch +patches.kzm9g/0024-mmc-tmio-Fix-race-condition-resulting-in-spurious-in.patch +patches.kzm9g/0025-mmc-tmio-fix-recursive-spinlock-don-t-schedule-with-.patch +patches.kzm9g/0026-mmc-tmio-maximize-power-saving.patch +patches.kzm9g/0027-mmc-tmio-fix-a-recently-introduced-bug-in-DMA-code.patch +patches.kzm9g/0028-mmc-tmio-fix-a-deadlock.patch +patches.kzm9g/0029-net-remove-mm.h-inclusion-from-netdevice.h.patch +patches.kzm9g/0030-MMC-TMIO-Fix-build-issue-related-to-struct-scatterli.patch +patches.kzm9g/0031-mmc-tmio-eliminate-unused-variable-mmc-warning.patch +patches.kzm9g/0032-mmc-sdhi-initialise-mmc_data-flags-before-use.patch +patches.kzm9g/0033-mmc-tmio-Cache-interrupt-masks.patch +patches.kzm9g/0034-mmc-tmio-Provide-separate-interrupt-handlers.patch +patches.kzm9g/0035-mmc-sdhi-Allow-named-IRQs-to-use-specific-handlers.patch +patches.kzm9g/0036-mmc-irq-Remove-IRQF_DISABLED.patch +patches.kzm9g/0037-mmc-Add-module.h-to-drivers-mmc-users-assuming-impli.patch +patches.kzm9g/0038-mmc-replace-printk-with-appropriate-display-macro.patch +patches.kzm9g/0039-mmc-tmio-fix-clock-gating-on-platforms-with-a-.set_p.patch +patches.kzm9g/0040-mmc-convert-drivers-mmc-host-to-use-module_platform_.patch +patches.kzm9g/0041-mmc-remove-the-second-argument-of-k-un-map_atomic.patch +patches.kzm9g/0042-mmc-tmio_mmc-Hotplug-code-regrouping.patch +patches.kzm9g/0043-mmc-host-move-to-dma_transfer_direction.patch +patches.kzm9g/0044-mmc-tmio_mmc-fix-card-eject-during-IO-with-DMA.patch +patches.kzm9g/0045-mmc-tmio_mmc-do-not-enable-card-hotplug-interrupts-i.patch +patches.kzm9g/0046-mmc-tmio-calculate-the-native-hotplug-condition-only.patch +patches.kzm9g/0047-mmc-tmio_mmc-support-the-generic-MMC-GPIO-card-hotpl.patch +patches.kzm9g/0048-mmc-sh_mobile_sdhi-pass-card-hotplug-GPIO-number-to-.patch +patches.kzm9g/0049-mmc-tmio_mmc-power-status-flag-doesn-t-have-to-be-ex.patch +patches.kzm9g/0050-mmc-tmio_mmc-remove-unused-sdio_irq_enabled-flag.patch +patches.kzm9g/0051-mmc-sh_mobile_sdhi-do-not-manage-PM-clocks-manually.patch +patches.kzm9g/0052-mmc-tmio-cosmetic-prettify-the-tmio_mmc_set_ios-func.patch +patches.kzm9g/0053-mmc-sh_mobile_sdhi-add-a-callback-for-board-specific.patch +patches.kzm9g/0054-mmc-sh_mobile_sdhi-support-modular-mmc-core-with-non.patch +patches.kzm9g/0055-mmc-Standardize-header-file-inclusion-checks.patch +patches.kzm9g/0056-mmc-sh_mmcif-maximize-power-saving.patch +patches.kzm9g/0057-mmc-sh_mmcif-simplify-platform-data.patch +patches.kzm9g/0058-mmc-Add-module.h-to-drivers-mmc-users-assuming-impli.patch +patches.kzm9g/0059-mmc-host-move-to-dma_transfer_direction.patch +patches.kzm9g/0060-mmc-sh_mmcif-fix-clock-gating-on-platforms-with-a-.d.patch +patches.kzm9g/0061-mmc-sh_mmcif-simplify-clock-divisor-calculation.patch +patches.kzm9g/0062-mmc-convert-drivers-mmc-host-to-use-module_platform_.patch +patches.kzm9g/0063-mmc-sh_mmcif-process-error-interrupts-first.patch +patches.kzm9g/0064-mmc-sh_mmcif-cosmetic-clean-up.patch +patches.kzm9g/0065-mmc-sh_mmcif-process-requests-asynchronously.patch +patches.kzm9g/0066-mmc-sh_mmcif-remove-now-superfluous-sh_mmcif_host-da.patch +patches.kzm9g/0067-mmc-sh_mmcif-fix-MMC_GEN_CMD-setting.patch +patches.kzm9g/0068-mmc-sh_mmcif-simplify-bitmask-macros.patch +patches.kzm9g/0069-mmc-sh_mmcif-double-clock-speed.patch +patches.kzm9g/0070-mmc-sh_mmcif-mmc-f_max-should-be-half-of-the-bus-clo.patch +patches.kzm9g/0071-mmc-sh_mmcif-Simplify-calculation-of-mmc-f_min.patch +patches.kzm9g/0072-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch +patches.kzm9g/0073-ALSA-workaround-change-the-timing-of-alsa_sound_last.patch +patches.kzm9g/0074-ASoC-core-Optimise-and-refactor-pcm_new-to-pass-only.patch +patches.kzm9g/0075-ASoC-core-Allow-components-to-probe-remove-in-sequen.patch +patches.kzm9g/0076-ASoC-core-Separate-out-PCM-operations-into-new-file.patch +patches.kzm9g/0077-ASoC-core-PCM-mutex-per-rtd.patch +patches.kzm9g/0078-ASoC-Allow-DAI-formats-to-be-specified-in-the-dai_li.patch +patches.kzm9g/0079-ASoC-Hold-runtime-PM-references-to-components-of-act.patch +patches.kzm9g/0080-ASoC-sh-fsi-tidyup-parameter-of-fsi_stream_push.patch +patches.kzm9g/0081-ASoC-sh-fsi-add-fsi_set_master_clk.patch +patches.kzm9g/0082-ASoC-sh-fsi-irq-control-moves-to-fsi_port_start-stop.patch +patches.kzm9g/0083-ASoC-sh-fsi-tidyup-unclear-variable-naming.patch +patches.kzm9g/0084-ASoC-sh-fsi-remove-pm_runtime-from-fsi_dai_set_fmt.patch +patches.kzm9g/0085-ASoC-sh-fsi-make-sure-fsi_stream_push-pop-access-by-.patch +patches.kzm9g/0086-ASoC-sh-fsi-remove-fsi_module_init-kill.patch +patches.kzm9g/0087-ASoC-sh-fsi-cleanup-suspend-resume.patch +patches.kzm9g/0088-ASoC-sh-fsi-add-fsi_hw_startup-shutdown.patch +patches.kzm9g/0089-sound-irq-Remove-IRQF_DISABLED.patch +patches.kzm9g/0090-ASoC-sh-use-correct-__iomem-annotations.patch +patches.kzm9g/0091-sound-Add-module.h-to-the-previously-silent-sound-us.patch +patches.kzm9g/0092-ASoC-fsi-fixup-compile-warning.patch +patches.kzm9g/0093-ASoC-fsi-add-valid-data-position-control-support.patch +patches.kzm9g/0094-ASoC-Constify-snd_soc_dai_ops-structs.patch +patches.kzm9g/0095-ASoC-fsi-ak4642-modify-specification-method-of-FSI-a.patch +patches.kzm9g/0096-ASoC-Convert-sh-directory-to-module_platform_driver.patch +patches.kzm9g/0097-ASoC-Use-core-pm_runtime-callbacks-for-fsi.patch +patches.kzm9g/0098-ASoC-sh-Add-.owner-to-struct-snd_soc_card.patch +patches.kzm9g/0099-ASoC-fsi-Remove-unneeded-empty-runtime-PM-callbacks.patch +patches.kzm9g/0100-ASoC-fsi-reduce-runtime-calculation-by-using-pre-set.patch +patches.kzm9g/0101-ASoC-fsi-tidyup-fsi_stream_xx-functions-were-gathere.patch +patches.kzm9g/0102-ASoC-fsi-data-push-pop-calculation-part-was-divided.patch +patches.kzm9g/0103-ASoC-fsi-rename-fsi_dma_soft_xxx-to-fsi_pio_xxx.patch +patches.kzm9g/0104-ASoC-fsi-tidyup-move-fsi_fifo_init-onto-fsi_hw_start.patch +patches.kzm9g/0105-ASoC-fsi-remove-unnecessary-parameter-from-fsi_hw_sh.patch +patches.kzm9g/0106-ASoC-fsi-rename-fsi_stream_push-pop-to-fsi_stream_in.patch +patches.kzm9g/0107-ASoC-fsi-modify-fsi_pio_get_area-parameter-and-using.patch +patches.kzm9g/0108-ASoC-fsi-re-define-fsi_is_play-and-fsi_stream_is_pla.patch +patches.kzm9g/0109-ASoC-fsi-use-fsi_stream-in-fsi_get_current_fifo_samp.patch +patches.kzm9g/0110-ASoC-fsi-add-fsi_stream_handler-and-PIO-handler.patch +patches.kzm9g/0111-ASoC-fsi-tidyup-fsi_pio_xxx-are-gathered.patch +patches.kzm9g/0112-ASoC-fsi-don-t-use-is_play-as-a-parameter-of-fsi-fun.patch +patches.kzm9g/0113-ASoC-fsi-add-.start_stop-handler-to-fsi_stream_handl.patch +patches.kzm9g/0114-ASoC-fsi-fsi_stream_is_working-care-substream-runtim.patch +patches.kzm9g/0115-ASoC-fsi-PortA-B-information-was-controlled-by-sh_fs.patch +patches.kzm9g/0116-ASoC-fsi-add-.init-.quit-handler-support.patch +patches.kzm9g/0117-ASoC-fsi-fixup-fsi_pointer-calculation-method.patch +patches.kzm9g/0118-ASoC-fsi-Add-DMAEngine-support.patch +patches.kzm9g/0119-ASoC-fsi-update-for-dmaengine-prep_slave_sg-fallout.patch +patches.kzm9g/0120-ASoC-add-generic-simple-card-support.patch +patches.kzm9g/0121-ASoC-sh-fsi-select-simple-card-on-Kconfig.patch +patches.kzm9g/0122-ASoC-ak4642-convert-to-soc-cache.patch +patches.kzm9g/0123-ASoC-ak4642-ak4642-was-tested.patch +patches.kzm9g/0124-ASoC-ak4642-add-ak4642_set_bias_level.patch +patches.kzm9g/0125-ASoC-ak4642-add-DAPM-support-for-HeadPhone-Output.patch +patches.kzm9g/0126-ASoC-ak4642-add-headphone-mute-switch-control.patch +patches.kzm9g/0127-ASoC-ak4642-add-Line-out-support.patch +patches.kzm9g/0128-ASoC-ak4642-add-ak4648-support.patch +patches.kzm9g/0129-ASoC-Remove-driver-versioning-from-ak4642.patch +patches.kzm9g/0130-ASoC-Convert-ak4642-to-devm_kzalloc.patch +patches.kzm9g/0131-ASoC-ak4642-fixup-HeadPhone-L-R-dapm-settings.patch +patches.kzm9g/0132-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch +patches.kzm9g/0133-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch +patches.kzm9g/0134-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch +patches.kzm9g/0135-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch +patches.kzm9g/0136-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch +patches.kzm9g/0137-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch +patches.kzm9g/0138-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch +patches.kzm9g/0139-ARM-mach-shmobile-armadillo800eva-Add-FSI-WM8978-sup.patch +patches.kzm9g/0140-ARM-mach-shmobile-Add-support-for-PINT-though-INTC-m.patch +patches.kzm9g/0141-irq-Track-the-owner-of-irq-descriptor.patch +patches.kzm9g/0142-irq-add-irq_domain-translation-infrastructure.patch +patches.kzm9g/0143-dt-irq-add-irq_domain_generate_simple-helper.patch +patches.kzm9g/0144-irq-Add-declaration-of-irq_domain_simple_ops-to-irqd.patch +patches.kzm9g/0145-irq-Fix-check-for-already-initialized-irq_domain-in-.patch +patches.kzm9g/0146-irq-support-domains-with-non-zero-hwirq-base.patch +patches.kzm9g/0147-genirq-Add-support-for-per-cpu-dev_id-interrupts.patch +patches.kzm9g/0148-ARM-introduce-handle_IRQ-not-to-dump-exception-stack.patch +patches.kzm9g/0149-ARM-GIC-move-gic_chip_data-structure-declaration-to-.patch +patches.kzm9g/0150-ARM-CPU-hotplug-fix-abuse-of-irqdesc-node.patch +patches.kzm9g/0151-ARM-GIC-avoid-routing-interrupts-to-offline-CPUs.patch +patches.kzm9g/0152-ARM-gic-Use-cpu-pm-notifiers-to-save-gic-state.patch +patches.kzm9g/0153-ARM-7011-1-Add-ARM-cpu-topology-definition.patch +patches.kzm9g/0154-ARM-7060-1-smp-populate-logical-CPU-mapping-during-b.patch +patches.kzm9g/0155-ARM-gic-Allow-gic-arch-extensions-to-provide-irqchip.patch +patches.kzm9g/0156-ARM-7061-1-gic-convert-logical-CPU-numbers-into-phys.patch +patches.kzm9g/0157-ARM-7123-1-smp-Add-an-IPI-handler-callable-from-C-co.patch +patches.kzm9g/0158-ARM-7124-1-smp-Add-a-localtimer-handler-callable-fro.patch +patches.kzm9g/0159-ARM-gic-consolidate-PPI-handling.patch +patches.kzm9g/0160-ARM-GIC-Add-global-gic_handle_irq-function.patch +patches.kzm9g/0161-ARM-twd-register-clockevents-device-before-enabling-.patch +patches.kzm9g/0162-ARM-EXYNOS4-set-the-affinity-of-mct1-interrupt-using.patch +patches.kzm9g/0163-genirq-percpu-allow-interrupt-type-to-be-set-at-enab.patch +patches.kzm9g/0164-ARM-gic-local-timers-use-the-request_percpu_irq-inte.patch +patches.kzm9g/0165-ARM-gic-add-irq_domain-support.patch +patches.kzm9g/0166-ARM-gic-add-OF-based-initialization.patch +patches.kzm9g/0167-ARM-gic-fix-irq_alloc_descs-handling-for-sparse-irq.patch +patches.kzm9g/0168-ARM-gic-use-module.h-instead-of-export.h.patch +patches.kzm9g/0169-ARM-7176-1-cpu_pm-register-GIC-PM-notifier-only-once.patch +patches.kzm9g/0170-ARM-7177-1-GIC-avoid-skipping-non-existent-PPIs-in-i.patch +patches.kzm9g/0171-ARM-mach-shmobile-clock-sh73a0-tidyup-CKSCR-main-clo.patch +patches.kzm9g/0172-ARM-mach-shmobile-sh73a0-PFC-pull-up-support-for-SDH.patch +patches.kzm9g/0173-ARM-shmobile-convert-logical-CPU-numbers-to-physical.patch +patches.kzm9g/0174-ARM-mach-shmobile-sh73a0-GPIO-IRQ-support.patch +patches.kzm9g/0175-ARM-mach-shmobile-Use-common-INTC-IRQ-code-on-sh73a0.patch +patches.kzm9g/0176-ARM-mach-shmobile-sh73a0-and-AG5EVM-PINT-support.patch +patches.kzm9g/0177-ARM-mach-shmobile-Kota2-TPU-LED-platform-data.patch +patches.kzm9g/0178-ARM-mach-shmobile-SH73A0-external-Ethernet-fix.patch +patches.kzm9g/0179-sh-clkfwk-clock-sh73a0-all-div6_clks-use-SH_CLK_DIV6.patch +patches.kzm9g/0180-arm-mach-shmobile-add-a-resource-name-for-shdma.patch +patches.kzm9g/0181-ARM-mach-shmobile-sh73a0-PINT-IRQ-base-fix.patch +patches.kzm9g/0182-ARM-mach-shmobile-sh73a0-IRQ-sparse-alloc-fix.patch +patches.kzm9g/0183-ARM-mach-shmobile-clock-sh73a0-add-DSIxPHY-clock-sup.patch +patches.kzm9g/0184-ARM-shmobile-remove-NR_IRQS.patch +patches.kzm9g/0185-ARM-mach-shmobile-sh73a0-PSTR-32-bit-access-fix.patch +patches.kzm9g/0186-ARM-mach-shmobile-sh73a0-sh_clk_ops-rename.patch +patches.kzm9g/0187-ARM-mach-shmobile-sh73a0-map_io-and-init_early-updat.patch +patches.kzm9g/0188-ARM-mach-shmobile-sh73a0-AG5EVM-and-Kota2-timer-rewo.patch +patches.kzm9g/0189-ARM-mach-shmobile-sh73a0-add-MMC-data-pin-pull-up.patch +patches.kzm9g/0190-ARM-Update-mach-types.patch +patches.kzm9g/0191-ARM-mach-shmobile-add-KZM-A9-GT-board-support.patch +patches.kzm9g/0192-ARM-mach-shmobile-kzm9g-add-defconfig.patch +patches.kzm9g/0193-ARM-mach-shmobile-Invalidate-caches-when-booting-sec.patch +patches.kzm9g/0194-ARM-mach-shmobile-kzm9g-enable-SMP-boot.patch +patches.kzm9g/0195-ARM-mach-shmobile-kzm9g-add-LCDC-support.patch +patches.kzm9g/0196-ARM-mach-shmobile-kzm9g-add-ST1232-Touchscreen-suppo.patch +patches.kzm9g/0197-ARM-mach-shmobile-pfc-sh73a0-fixup-MSEL2CR-MSEL18-fo.patch +patches.kzm9g/0198-ARM-mach-shmobile-sh73a0.h-add-GPIO_NR.patch +patches.kzm9g/0199-ARM-mach-shmobile-kzm9g-correct-screen-direction.patch +patches.kzm9g/0200-ARM-mach-shmobile-kzm9g-add-MMCIF-support.patch +patches.kzm9g/0201-ARM-mach-shmobile-kzm9g-add-SDHI-support.patch +patches.kzm9g/0202-ARM-mach-shmobile-kzm9g-add-PCF8757-gpio-key.patch +patches.kzm9g/0203-ARM-mach-shmobile-kzm9g-defconfig-update.patch +patches.kzm9g/0204-ARM-mach-shmobile-clock-sh73a0-add-FSI-clock.patch +patches.kzm9g/0205-ARM-mach-shmobile-kzm9g-add-FSI-AK4648-support.patch |