Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/9] usb: musb_am335x: source cleanup
From: Felipe Balbi @ 2014-07-18 13:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405675890-8802-4-git-send-email-LW@KARO-electronics.de>

On Fri, Jul 18, 2014 at 11:31:24AM +0200, Lothar Wa?mann wrote:
> - remove comma after end of list delimiter
>   The empty entry must always be the last item in the list, thus there
>   is no point in having a trailing comma to facilitate adding
>   succeding entries.
>   Remove the comma, so that inadvertedly adding an entry after the end
>   of list sentinel will produce a compile time error rather than an
>   unreachable entry in the list.
> - consistently use tabs for indentation
> 
> Signed-off-by: Lothar Wa?mann <LW@KARO-electronics.de>
> ---
>  drivers/usb/musb/musb_am335x.c |    6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/musb/musb_am335x.c b/drivers/usb/musb/musb_am335x.c
> index 1e58ed2..164c868 100644
> --- a/drivers/usb/musb/musb_am335x.c
> +++ b/drivers/usb/musb/musb_am335x.c
> @@ -21,14 +21,14 @@ err:
>  
>  static const struct of_device_id am335x_child_of_match[] = {
>  	{ .compatible = "ti,am33xx-usb" },
> -	{  },
> +	{  }

makes not difference, but fine.

>  };
>  MODULE_DEVICE_TABLE(of, am335x_child_of_match);
>  
>  static struct platform_driver am335x_child_driver = {
>  	.probe		= am335x_child_probe,
> -	.driver         = {
> -		.name   = "am335x-usb-childs",
> +	.driver		= {
> +		.name	= "am335x-usb-childs",

thanks, still not a bug fix.

>  		.of_match_table	= am335x_child_of_match,
>  	},
>  };
> -- 
> 1.7.10.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140718/d650a9f3/attachment.sig>

^ permalink raw reply

* [PATCH 2/9] usb: phy: am335x: group the #includes by subdirs
From: Felipe Balbi @ 2014-07-18 13:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405675890-8802-3-git-send-email-LW@KARO-electronics.de>

On Fri, Jul 18, 2014 at 11:31:23AM +0200, Lothar Wa?mann wrote:
> 

no commit log. Not a bug fix.

> Signed-off-by: Lothar Wa?mann <LW@KARO-electronics.de>
> ---
>  drivers/usb/phy/phy-am335x.c |    6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
> index b70e055..91c71ab 100644
> --- a/drivers/usb/phy/phy-am335x.c
> +++ b/drivers/usb/phy/phy-am335x.c
> @@ -1,13 +1,13 @@
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
>  #include <linux/dma-mapping.h>
> -#include <linux/usb/otg.h>
> -#include <linux/usb/usb_phy_generic.h>
>  #include <linux/slab.h>
>  #include <linux/clk.h>
> -#include <linux/regulator/consumer.h>
>  #include <linux/of.h>
>  #include <linux/of_address.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/usb/otg.h>
> +#include <linux/usb/usb_phy_generic.h>
>  
>  #include "am35x-phy-control.h"
>  #include "phy-generic.h"
> -- 
> 1.7.10.4
> 

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140718/9b96c750/attachment.sig>

^ permalink raw reply

* [PATCH 1/9] usb: musb: core: cleanup - remove some useless 'break's from switch statements
From: Felipe Balbi @ 2014-07-18 13:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405675890-8802-2-git-send-email-LW@KARO-electronics.de>

HI,

On Fri, Jul 18, 2014 at 11:31:22AM +0200, Lothar Wa?mann wrote:
> 

no commit log == no commit, also the worst thing you can do is have your
bug fixes depend on cleanups. This is *not* a bug fix by any stretch of
the imagination.

> Signed-off-by: Lothar Wa?mann <LW@KARO-electronics.de>
> ---
>  drivers/usb/musb/musb_core.c |    4 ----
>  1 file changed, 4 deletions(-)
> 
> diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
> index b841ee0..8623112 100644
> --- a/drivers/usb/musb/musb_core.c
> +++ b/drivers/usb/musb/musb_core.c
> @@ -680,7 +680,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
>  		default:
>  			/* "should not happen" */
>  			musb->is_active = 0;
> -			break;
>  		}
>  	}
>  
> @@ -737,7 +736,6 @@ b_host:
>  				if (hcd)
>  					hcd->self.is_b_host = 0;
>  			}
> -			break;
>  		}
>  
>  		musb_host_poke_root_hub(musb);
> @@ -787,7 +785,6 @@ b_host:
>  		default:
>  			WARNING("unhandled DISCONNECT transition (%s)\n",
>  				usb_otg_state_string(musb->xceiv->state));
> -			break;
>  		}
>  	}
>  
> @@ -2015,7 +2012,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
>  		break;
>  	default:
>  		dev_err(dev, "unsupported port mode %d\n", musb->port_mode);
> -		break;
>  	}
>  
>  	if (status < 0)
> -- 
> 1.7.10.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140718/3981912b/attachment-0001.sig>

^ permalink raw reply

* [PATCHv4 5/5] arm64: Add atomic pool for non-coherent and CMA allocations.
From: Catalin Marinas @ 2014-07-18 13:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1404324218-4743-6-git-send-email-lauraa@codeaurora.org>

On Wed, Jul 02, 2014 at 07:03:38PM +0100, Laura Abbott wrote:
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index 4164c5a..a2487f1 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
[...]
>  static void *__dma_alloc_coherent(struct device *dev, size_t size,
>  				  dma_addr_t *dma_handle, gfp_t flags,
>  				  struct dma_attrs *attrs)
> @@ -53,7 +103,8 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
>  	if (IS_ENABLED(CONFIG_ZONE_DMA) &&
>  	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
>  		flags |= GFP_DMA;
> -	if (IS_ENABLED(CONFIG_DMA_CMA)) {
> +
> +	if (!(flags & __GFP_WAIT) && IS_ENABLED(CONFIG_DMA_CMA)) {
>  		struct page *page;
>  
>  		size = PAGE_ALIGN(size);

I think that's the wrong condition here. You want to use CMA if
(flags & __GFP_WAIT). CMA does not support atomic allocations so it can
fall back to swiotlb_alloc_coherent().

> @@ -73,50 +124,56 @@ static void __dma_free_coherent(struct device *dev, size_t size,
>  				void *vaddr, dma_addr_t dma_handle,
>  				struct dma_attrs *attrs)
>  {
> +	bool freed;
> +	phys_addr_t paddr = dma_to_phys(dev, dma_handle);
> +
>  	if (dev == NULL) {
>  		WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
>  		return;
>  	}
>  
> -	if (IS_ENABLED(CONFIG_DMA_CMA)) {
> -		phys_addr_t paddr = dma_to_phys(dev, dma_handle);
>  
> -		dma_release_from_contiguous(dev,
> +	freed = dma_release_from_contiguous(dev,
>  					phys_to_page(paddr),
>  					size >> PAGE_SHIFT);
> -	} else {
> +	if (!freed)
>  		swiotlb_free_coherent(dev, size, vaddr, dma_handle);
> -	}
>  }

Is __dma_free_coherent() ever called in atomic context? If yes, the
dma_release_from_contiguous() may not like it since it tries to acquire
a mutex. But since we don't have the gfp flags here, we don't have an
easy way to know what to call.

So the initial idea of always calling __alloc_from_pool() for both
coherent/non-coherent cases would work better (but still with a single
shared pool, see below).

>  static void *__dma_alloc_noncoherent(struct device *dev, size_t size,
>  				     dma_addr_t *dma_handle, gfp_t flags,
>  				     struct dma_attrs *attrs)
>  {
> -	struct page *page, **map;
> +	struct page *page;
>  	void *ptr, *coherent_ptr;
> -	int order, i;
>  
>  	size = PAGE_ALIGN(size);
> -	order = get_order(size);
> +
> +	if (!(flags & __GFP_WAIT)) {
> +		struct page *page = NULL;
> +		void *addr = __alloc_from_pool(size, &page);
> +
> +		if (addr)
> +			*dma_handle = phys_to_dma(dev, page_to_phys(page));
> +
> +		return addr;
> +
> +	}

If we do the above for the __dma_alloc_coherent() case, we could use the
same pool but instead of returning addr it could just return
page_address(page). The downside of sharing the pool is that you need
cache flushing for every allocation (which we already do for the
non-atomic case).

> @@ -332,6 +391,67 @@ static struct notifier_block amba_bus_nb = {
>  
>  extern int swiotlb_late_init_with_default_size(size_t default_size);
>  
> +static int __init atomic_pool_init(void)
> +{
> +	pgprot_t prot = __pgprot(PROT_NORMAL_NC);
> +	unsigned long nr_pages = atomic_pool_size >> PAGE_SHIFT;
> +	struct page *page;
> +	void *addr;
> +
> +
> +	if (dev_get_cma_area(NULL))

Is it worth using this condition for other places where we check
IS_ENABLED(CONFIG_DMA_CMA) (maybe as a separate patch).

> +		page = dma_alloc_from_contiguous(NULL, nr_pages,
> +					get_order(atomic_pool_size));
> +	else
> +		page = alloc_pages(GFP_KERNEL, get_order(atomic_pool_size));

One problem here is that the atomic pool wouldn't be able to honour
GFP_DMA (in the latest kernel, CMA is by default in ZONE_DMA). You
should probably pass GFP_KERNEL|GFP_DMA here. You could also use the
swiotlb_alloc_coherent() which, with a NULL dev, assumes 32-bit DMA mask
but it still expects GFP_DMA to be passed.

> +	if (page) {
> +		int ret;
> +
> +		atomic_pool = gen_pool_create(PAGE_SHIFT, -1);
> +		if (!atomic_pool)
> +			goto free_page;
> +
> +		addr = dma_common_contiguous_remap(page, atomic_pool_size,
> +					VM_USERMAP, prot, atomic_pool_init);
> +
> +		if (!addr)
> +			goto destroy_genpool;
> +
> +		memset(addr, 0, atomic_pool_size);
> +		__dma_flush_range(addr, addr + atomic_pool_size);

If you add the flushing in the __dma_alloc_noncoherent(), it won't be
needed here (of course, more efficient here but it would not work if we
share the pool).

> +postcore_initcall(atomic_pool_init);

Why not arch_initcall? Or even better, we could have a common DMA init
function that calls swiotlb_late_init() and atomic_pool_init() (in this
order if you decide to use swiotlb allocation above).

-- 
Catalin

^ permalink raw reply

* [PATCHv6] mmc: dw_mmc: change to use recommended reset procedure
From: Seungwon Jeon @ 2014-07-18 13:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405375591-13409-1-git-send-email-sonnyrao@chromium.org>

On Tue, July 15, 2014, Sonny Rao wrote:
> This patch changes the fifo reset code to follow the reset procedure
> outlined in the documentation of Synopsys Mobile storage host databook.
> 
> Signed-off-by: Sonny Rao <sonnyrao@chromium.org>
> Signed-off-by: Yuvaraj Kumar C D <yuvaraj.cd@samsung.com>

Acked-by: Seungwon Jeon <tgih.jun@samsung.com>

Thanks,
Seungwon Jeon

> ---
> v2: Add Generic DMA support
>     per the documentation, move interrupt clear before wait
>     make the test for DMA host->use_dma rather than host->using_dma
>     add proper return values (although it appears no caller checks)
> v3: rename fifo reset function, and change callers
>     use this combined reset function in dw_mci_resume()
>     just one caller left (probe), so get rid of dw_mci_ctrl_all_reset()
>     use DMA reset bit for all systems which use DMA
>     remove extra IDMAC reset in dw_mci_work_routine_card()
>     do CIU clock update in error path, if CIU reset cleared
> v4: remove comment about FIFO reset in dw_mci_work_routine_card()
>     move down error message when control reset clears but others don't
>      and clarify the error stating that we will still update clocks
>     make flags for all reset bits a macro
> v5: don't use dw_mci_reset() in dw_mci_resume() and instead match what
>     is done in dw_mci_probe() and don't force inline dw_mci_resume()
> v6: add newlines to dev_err() messages
> ---
>  drivers/mmc/host/dw_mmc.c | 86 ++++++++++++++++++++++++++++++++++-------------
>  drivers/mmc/host/dw_mmc.h |  5 +++
>  2 files changed, 68 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 55cd110..0c0aecb 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -111,8 +111,7 @@ static const u8 tuning_blk_pattern_8bit[] = {
>  	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
>  };
> 
> -static inline bool dw_mci_fifo_reset(struct dw_mci *host);
> -static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host);
> +static bool dw_mci_reset(struct dw_mci *host);
> 
>  #if defined(CONFIG_DEBUG_FS)
>  static int dw_mci_req_show(struct seq_file *s, void *v)
> @@ -1254,7 +1253,7 @@ static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data)
>  		 * After an error, there may be data lingering
>  		 * in the FIFO
>  		 */
> -		dw_mci_fifo_reset(host);
> +		dw_mci_reset(host);
>  	} else {
>  		data->bytes_xfered = data->blocks * data->blksz;
>  		data->error = 0;
> @@ -1371,7 +1370,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
> 
>  			/* CMD error in data command */
>  			if (mrq->cmd->error && mrq->data)
> -				dw_mci_fifo_reset(host);
> +				dw_mci_reset(host);
> 
>  			host->cmd = NULL;
>  			host->data = NULL;
> @@ -1982,14 +1981,8 @@ static void dw_mci_work_routine_card(struct work_struct *work)
>  			}
> 
>  			/* Power down slot */
> -			if (present == 0) {
> -				/* Clear down the FIFO */
> -				dw_mci_fifo_reset(host);
> -#ifdef CONFIG_MMC_DW_IDMAC
> -				dw_mci_idmac_reset(host);
> -#endif
> -
> -			}
> +			if (present == 0)
> +				dw_mci_reset(host);
> 
>  			spin_unlock_bh(&host->lock);
> 
> @@ -2323,8 +2316,11 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
>  	return false;
>  }
> 
> -static inline bool dw_mci_fifo_reset(struct dw_mci *host)
> +static bool dw_mci_reset(struct dw_mci *host)
>  {
> +	u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET;
> +	bool ret = false;
> +
>  	/*
>  	 * Reseting generates a block interrupt, hence setting
>  	 * the scatter-gather pointer to NULL.
> @@ -2334,15 +2330,59 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host)
>  		host->sg = NULL;
>  	}
> 
> -	return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET);
> -}
> +	if (host->use_dma)
> +		flags |= SDMMC_CTRL_DMA_RESET;
> 
> -static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host)
> -{
> -	return dw_mci_ctrl_reset(host,
> -				 SDMMC_CTRL_FIFO_RESET |
> -				 SDMMC_CTRL_RESET |
> -				 SDMMC_CTRL_DMA_RESET);
> +	if (dw_mci_ctrl_reset(host, flags)) {
> +		/*
> +		 * In all cases we clear the RAWINTS register to clear any
> +		 * interrupts.
> +		 */
> +		mci_writel(host, RINTSTS, 0xFFFFFFFF);
> +
> +		/* if using dma we wait for dma_req to clear */
> +		if (host->use_dma) {
> +			unsigned long timeout = jiffies + msecs_to_jiffies(500);
> +			u32 status;
> +			do {
> +				status = mci_readl(host, STATUS);
> +				if (!(status & SDMMC_STATUS_DMA_REQ))
> +					break;
> +				cpu_relax();
> +			} while (time_before(jiffies, timeout));
> +
> +			if (status & SDMMC_STATUS_DMA_REQ) {
> +				dev_err(host->dev,
> +					"%s: Timeout waiting for dma_req to "
> +					"clear during reset\n", __func__);
> +				goto ciu_out;
> +			}
> +
> +			/* when using DMA next we reset the fifo again */
> +			if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET))
> +				goto ciu_out;
> +		}
> +	} else {
> +		/* if the controller reset bit did clear, then set clock regs */
> +		if (!(mci_readl(host, CTRL) & SDMMC_CTRL_RESET)) {
> +			dev_err(host->dev, "%s: fifo/dma reset bits didn't "
> +				"clear but ciu was reset, doing clock update\n",
> +				__func__);
> +			goto ciu_out;
> +		}
> +	}
> +
> +	if (IS_ENABLED(CONFIG_MMC_DW_IDMAC))
> +		/* It is also recommended that we reset and reprogram idmac */
> +		dw_mci_idmac_reset(host);
> +
> +	ret = true;
> +
> +ciu_out:
> +	/* After a CTRL reset we need to have CIU set clock registers  */
> +	mci_send_cmd(host->cur_slot, SDMMC_CMD_UPD_CLK, 0);
> +
> +	return ret;
>  }
> 
>  #ifdef CONFIG_OF
> @@ -2555,7 +2595,7 @@ int dw_mci_probe(struct dw_mci *host)
>  	}
> 
>  	/* Reset all blocks */
> -	if (!dw_mci_ctrl_all_reset(host))
> +	if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS))
>  		return -ENODEV;
> 
>  	host->dma_ops = host->pdata->dma_ops;
> @@ -2744,7 +2784,7 @@ int dw_mci_resume(struct dw_mci *host)
>  		}
>  	}
> 
> -	if (!dw_mci_ctrl_all_reset(host)) {
> +	if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) {
>  		ret = -ENODEV;
>  		return ret;
>  	}
> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> index 6bf24ab..9ab8ccd 100644
> --- a/drivers/mmc/host/dw_mmc.h
> +++ b/drivers/mmc/host/dw_mmc.h
> @@ -129,6 +129,7 @@
>  #define SDMMC_CMD_INDX(n)		((n) & 0x1F)
>  /* Status register defines */
>  #define SDMMC_GET_FCNT(x)		(((x)>>17) & 0x1FFF)
> +#define SDMMC_STATUS_DMA_REQ		BIT(31)
>  /* FIFOTH register defines */
>  #define SDMMC_SET_FIFOTH(m, r, t)	(((m) & 0x7) << 28 | \
>  					 ((r) & 0xFFF) << 16 | \
> @@ -150,6 +151,10 @@
>  /* Card read threshold */
>  #define SDMMC_SET_RD_THLD(v, x)		(((v) & 0x1FFF) << 16 | (x))
> 
> +/* All ctrl reset bits */
> +#define SDMMC_CTRL_ALL_RESET_FLAGS \
> +	(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)
> +
>  /* Register access macros */
>  #define mci_readl(dev, reg)			\
>  	__raw_readl((dev)->regs + SDMMC_##reg)
> --
> 2.0.0.526.g5318336
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [GIT PULL] ARM: mvebu: DT changes for v3.17
From: Arnd Bergmann @ 2014-07-18 13:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140717123550.GH13108@titan.lakedaemon.net>

On Thursday 17 July 2014 08:35:50 Jason Cooper wrote:
> Olof, Arnd, please merge this request.  I can re-send if you need.
> 
> We have more changes pending in mvebu/dt on top of this, and we're
> getting very close to the cutoff for the merge window.

Please send both pull requests now so we can look at the whole
picture. No need for you to wait for this to be merged before
sending the follow-up pull request.

I think we should just merge, there is no nice solution for
the technical problem and the approach you have taken looks
like the least problematic one to me.

Olof, any further thoughts on this?

	Arnd

^ permalink raw reply

* [PATCH] irqchip: gicv2m: Clean up logic for detecting MSI support
From: suravee.suthikulpanit at amd.com @ 2014-07-18 13:26 UTC (permalink / raw)
  To: linux-arm-kernel

From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>

It's not quite clear that msi-controller is already checked
by of_msi_chip_add. So, this patch add a note to clarify.

Also, clean up redundant logic and unnecessary pr_info.

Cc: Mark Rutland <Mark.Rutland@arm.com>
Cc: Marc Zyngier <Marc.Zyngier@arm.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Catalin Marinas <Catalin.Marinas@arm.com>
Cc: Will Deacon <Will.Deacon@arm.com>
Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
---

Note: This patch is created against irqchip/gic branch.

 drivers/irqchip/irq-gic-v2m.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index e54ca1d..94ed8d6 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -235,15 +235,15 @@ gicv2m_of_init(struct device_node *node, struct device_node *parent)
 	gic->msi_chip.teardown_irq = gicv2m_teardown_msi_irq;
 	ret = of_pci_msi_chip_add(&gic->msi_chip);
 	if (ret) {
-		/* MSI is optional and not supported here */
-		pr_info("GICv2m: MSI is not supported.\n");
+		/*
+		* Note: msi-controller is checked in of_pci_msi_chip_add().
+		* MSI support is optional, and enabled only if msi-controller
+		* is specified. Hence, return 0.
+		*/
 		return 0;
 	}
 
-	ret = gicv2m_msi_init(node, &gic->v2m_data);
-	if (ret)
-		return ret;
-	return ret;
+	return gicv2m_msi_init(node, &gic->v2m_data);
 }
 
 IRQCHIP_DECLARE(arm_gic_400_v2m, "arm,gic-400-v2m", gicv2m_of_init);
-- 
1.9.0

^ permalink raw reply related

* [PATCH v10 4/8] ata: libahci: allow to use multiple PHYs
From: Lothar Waßmann @ 2014-07-18 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405686607-8126-5-git-send-email-antoine.tenart@free-electrons.com>

Hi,

Antoine T?nart wrote:
> The current implementation of the libahci does not allow to use multiple
> PHYs. This patch adds the support of multiple PHYs by the libahci while
> keeping the old bindings valid for device tree compatibility.
> 
> This introduce a new way of defining SATA ports in the device tree, with
> one port per sub-node. This as the advantage of allowing a per port
> configuration. Because some ports may be accessible but disabled in the
> device tree, the port_map mask is computed automatically when using
> this.
> 
> Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
> ---
>  drivers/ata/ahci.h             |   3 +-
>  drivers/ata/libahci_platform.c | 179 ++++++++++++++++++++++++++++++++---------
>  2 files changed, 142 insertions(+), 40 deletions(-)
> 
> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> index cb8d58926851..b0ea7b077d6e 100644
> --- a/drivers/ata/ahci.h
> +++ b/drivers/ata/ahci.h
> @@ -332,7 +332,8 @@ struct ahci_host_priv {
>  	bool			got_runtime_pm; /* Did we do pm_runtime_get? */
>  	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
>  	struct regulator	*target_pwr;	/* Optional */
> -	struct phy		*phy;		/* If platform uses phy */
> +	struct phy		**phys;		/* If platform uses phys */
> +	unsigned		nphys;		/* Number of phys */
>  	void			*plat_data;	/* Other platform data */
>  	/*
>  	 * Optional ahci_start_engine override, if not set this gets set to the
> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> index db9b90d876dd..2c2439b4101d 100644
> --- a/drivers/ata/libahci_platform.c
> +++ b/drivers/ata/libahci_platform.c
> @@ -39,6 +39,61 @@ static struct scsi_host_template ahci_platform_sht = {
>  };
>  
>  /**
> + * ahci_platform_enable_phys - Enable PHYs
> + * @hpriv: host private area to store config values
> + *
> + * This function enables all the PHYs found in hpriv->phys, if any.
> + * If a PHY fails to be enabled, it disables all the PHYs already
> + * enabled in reverse order and returns an error.
> + *
> + * RETURNS:
> + * 0 on success otherwise a negative error code
> + */
> +int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
> +{
> +	int i, rc = 0;
> +
You shouldn't have to initialize rc here, or does your gcc falsely
complain about an uninitialized variable if you don't?

> +	for (i = 0; i < hpriv->nphys; i++) {
> +		rc = phy_init(hpriv->phys[i]);
> +		if (rc)
> +			goto disable_phys;
> +
> +		rc = phy_power_on(hpriv->phys[i]);
> +		if (rc) {
> +			phy_exit(hpriv->phys[i]);
> +			goto disable_phys;
> +		}
> +	}
> +
> +	return 0;
> +
> +disable_phys:
> +	while (--i >= 0) {
> +		phy_power_off(hpriv->phys[i]);
> +		phy_exit(hpriv->phys[i]);
> +	}
> +	return rc;
> +}


Lothar Wa?mann
-- 
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch?ftsf?hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info at karo-electronics.de
___________________________________________________________

^ permalink raw reply

* [PATCH] irqchip: gic: Fix core ID calculation when topology is read from DT
From: Jason Cooper @ 2014-07-18 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405610624-18722-1-git-send-email-t.figa@samsung.com>

On Thu, Jul 17, 2014 at 05:23:44PM +0200, Tomasz Figa wrote:
> Certain GIC implementation, namely those found on earlier, single
> cluster, Exynos SoCs, have registers mapped without per-CPU banking,
> which means that the driver needs to use different offset for each CPU.
> 
> Currently the driver calculates the offset by multiplying value returned
> by cpu_logical_map() by CPU offset parsed from DT. This is correct when
> CPU topology is not specified in DT and aforementioned function returns
> core ID alone. However when DT contains CPU topology, the function
> changes to return cluster ID as well, which is non-zero on mentioned
> SoCs and so breaks the calculation in GIC driver.
> 
> This patch fixes this by masking out cluster ID in CPU offset
> calculation so that only core ID is considered. Multi-cluster Exynos
> SoCs already have banked GIC implementations, so this simple fix should
> be enough.
> 
> Reported-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Reported-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Tomasz Figa <t.figa@samsung.com>
> ---
>  drivers/irqchip/irq-gic.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
> index ddee133..5c15a09 100644
> --- a/drivers/irqchip/irq-gic.c
> +++ b/drivers/irqchip/irq-gic.c
> @@ -40,6 +40,7 @@
>  #include <linux/irqchip/chained_irq.h>
>  #include <linux/irqchip/arm-gic.h>

Applied to irqchip/urgent and Cc'd to stable for v3.3+

thx,

Jason.

^ permalink raw reply

* [PATCH v2 4/4] mfd: pm8921: rename pm8921-core driver
From: Prakash Burla @ 2014-07-18 13:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405613855-27572-5-git-send-email-svarbanov@mm-sol.com>

On Thu, Jul 17, 2014 at 9:47 PM, Stanimir Varbanov <svarbanov@mm-sol.com> wrote:
> The pm8921-core driver presently supports pm8921 and pm8058
> Qualcomm PMICs.  To avoid confusion with new generation PMICs
> (like pm8941) rename the pm8921-core driver to more
> appropriate name pm8xxx-ssbi, which reflects better that
> those chips use SSBI interface.
>
> Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
> ---
>  drivers/mfd/Kconfig                          |   14 +++++-----
>  drivers/mfd/Makefile                         |    2 +-
>  drivers/mfd/{pm8921-core.c => pm8xxx-ssbi.c} |   38 +++++++++++++-------------
>  3 files changed, 27 insertions(+), 27 deletions(-)
>  rename drivers/mfd/{pm8921-core.c => pm8xxx-ssbi.c} (92%)
 .
 [Nope]
>  MODULE_LICENSE("GPL v2");
> -MODULE_DESCRIPTION("PMIC 8921 core driver");
> +MODULE_DESCRIPTION("PMIC PM8XXX SSBI driver");
>  MODULE_VERSION("1.0");
> -MODULE_ALIAS("platform:pm8921-core");
> +MODULE_ALIAS("platform:pm8xxx-ssbi");
 >How about adding the module author as svarbanov at mm-sol.com/qcom?
      MODULE_AUTHOR("SVARBANOV<svarbanov@mm-sol.com>");
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* [PATCH 1/2] clk: samsung: exynos4x12: Enable ARMCLK down feature
From: Tomasz Figa @ 2014-07-18 13:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405677186-18678-1-git-send-email-k.kozlowski@samsung.com>

Hi Krzysztof,

On 18.07.2014 11:53, Krzysztof Kozlowski wrote:
> Enable ARMCLK down and up features on Exynos4212 and 4412 SoCs. The
> frequency of ARMCLK will be reduced upon entering idle mode (WFI or
> WFE).  Additionally upon exiting from idle mode the divider for ARMCLK
> will be brought back to 1.
> 
> These are exactly the same settings as for Exynos5250
> (clk-exynos5250.c), except of Exynos4412 where ARMCLK down is enabled
> for all 4 cores.

Could you add a sentence or two about the purpose of this change? E.g.
what it improves, in what conditions, etc.

> 
> Tested on Trats2 board (Exynos4412) and Samsung Gear 1 (Exynos4212).
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
> ---
>  drivers/clk/samsung/clk-exynos4.c | 53 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
> index 7f4a473a7ad7..b8ea37b23984 100644
> --- a/drivers/clk/samsung/clk-exynos4.c
> +++ b/drivers/clk/samsung/clk-exynos4.c
> @@ -114,11 +114,34 @@
>  #define DIV_CPU1		0x14504
>  #define GATE_SCLK_CPU		0x14800
>  #define GATE_IP_CPU		0x14900
> +#define PWR_CTRL1		0x15020
> +#define PWR_CTRL2		0x15024

I guess these registers should be also added to save/restore list below
in this driver.

>  #define E4X12_DIV_ISP0		0x18300
>  #define E4X12_DIV_ISP1		0x18304
>  #define E4X12_GATE_ISP0		0x18800
>  #define E4X12_GATE_ISP1		0x18804
>  
> +/* Below definitions are used for PWR_CTRL settings */
> +#define PWR_CTRL1_CORE2_DOWN_RATIO		(7 << 28)
> +#define PWR_CTRL1_CORE1_DOWN_RATIO		(7 << 16)

I think these macros could be defined to take the ratio as its argument,
e.g.

#define PWR_CTRL1_CORE2_DOWN_RATIO(x)		((x) << 28)

> +#define PWR_CTRL1_DIV2_DOWN_EN			(1 << 9)
> +#define PWR_CTRL1_DIV1_DOWN_EN			(1 << 8)
> +#define PWR_CTRL1_USE_CORE3_WFE			(1 << 7)
> +#define PWR_CTRL1_USE_CORE2_WFE			(1 << 6)
> +#define PWR_CTRL1_USE_CORE1_WFE			(1 << 5)
> +#define PWR_CTRL1_USE_CORE0_WFE			(1 << 4)
> +#define PWR_CTRL1_USE_CORE3_WFI			(1 << 3)
> +#define PWR_CTRL1_USE_CORE2_WFI			(1 << 2)
> +#define PWR_CTRL1_USE_CORE1_WFI			(1 << 1)
> +#define PWR_CTRL1_USE_CORE0_WFI			(1 << 0)
> +
> +#define PWR_CTRL2_DIV2_UP_EN			(1 << 25)
> +#define PWR_CTRL2_DIV1_UP_EN			(1 << 24)
> +#define PWR_CTRL2_DUR_STANDBY2_VAL		(1 << 16)
> +#define PWR_CTRL2_DUR_STANDBY1_VAL		(1 << 8)

These two too.

> +#define PWR_CTRL2_CORE2_UP_RATIO		(1 << 4)
> +#define PWR_CTRL2_CORE1_UP_RATIO		(1 << 0)

These two as well.

> +
>  /* the exynos4 soc type */
>  enum exynos4_soc {
>  	EXYNOS4210,
> @@ -1164,6 +1187,34 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
>  			VPLL_LOCK, VPLL_CON0, NULL),
>  };
>  
> +static void __init exynos4_core_down_clock(void)
> +{
> +	unsigned int tmp;
> +
> +	/*
> +	 * Enable arm clock down (in idle) and set arm divider
> +	 * ratios in WFI/WFE state.
> +	 */
> +	tmp = (PWR_CTRL1_CORE2_DOWN_RATIO | PWR_CTRL1_CORE1_DOWN_RATIO |
> +		PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
> +		PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
> +		PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
> +	if (of_machine_is_compatible("samsung,exynos4412"))

Maybe you could use num_possible_cpus() here instead?

> +		tmp |= PWR_CTRL1_USE_CORE3_WFE | PWR_CTRL1_USE_CORE2_WFE |
> +		       PWR_CTRL1_USE_CORE3_WFI | PWR_CTRL1_USE_CORE2_WFI;
> +	__raw_writel(tmp, reg_base + PWR_CTRL1);
> +
> +	/*
> +	 * Enable arm clock up (on exiting idle). Set arm divider
> +	 * ratios when not in idle along with the standby duration
> +	 * ratios.
> +	 */
> +	tmp = (PWR_CTRL2_DIV2_UP_EN | PWR_CTRL2_DIV1_UP_EN |
> +		PWR_CTRL2_DUR_STANDBY2_VAL | PWR_CTRL2_DUR_STANDBY1_VAL |
> +		PWR_CTRL2_CORE2_UP_RATIO | PWR_CTRL2_CORE1_UP_RATIO);
> +	__raw_writel(tmp, reg_base + PWR_CTRL2);

Do we need the clock up feature at all? The values you set seem to
configure both dividers to 2 (resulting in arm_clk = apll / 4) for a
very short period of time (16 ticks of some, unfortunately unspecified,
clock) between wake-up and setting the frequency back to normal.
Moreover, for certain settings (div_core * div_core2 set to > 4 by
cpufreq) this might cause issues with activating higher frequency than
current voltage allows.

I believe the same comments apply for patch 2/2 as well.

Best regards,
Tomasz

^ permalink raw reply

* [PATCH v10 1/8] phy: add a driver for the Berlin SATA PHY
From: Varka Bhadram @ 2014-07-18 12:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405686607-8126-2-git-send-email-antoine.tenart@free-electrons.com>

On 07/18/2014 06:00 PM, Antoine T?nart wrote:
> The Berlin SoC has a two SATA ports. Add a PHY driver to handle them.
>
> The mode selection can let us think this PHY can be configured to fit
> other purposes. But there are reasons to think the SATA mode will be
> the only one usable: the PHY registers are only accessible indirectly
> through two registers in the SATA range, the PHY seems to be integrated
> and no information tells us the contrary. For these reasons, make the
> driver a SATA PHY driver.
>
(...)

> +
> +static const struct of_device_id phy_berlin_sata_of_match[] = {
> +	{ .compatible = "marvell,berlin2q-sata-phy" },
> +	{ },
> +};
> +
> +static struct platform_driver phy_berlin_sata_driver = {
> +	.probe	= phy_berlin_sata_probe,
> +	.driver	= {
> +		.name		= "phy-berlin-sata",
> +		.owner		= THIS_MODULE,

owner filed automatically update with module_platform_driver().

see:http://lxr.free-electrons.com/source/include/linux/platform_device.h#L190
  

-- 
Regards,
Varka Bhadram.

^ permalink raw reply

* [PATCH v10 01/11] irq: gic: support hip04 gic
From: Mark Rutland @ 2014-07-18 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140718120526.GC24496@titan.lakedaemon.net>

On Fri, Jul 18, 2014 at 01:05:26PM +0100, Jason Cooper wrote:
> Haojian,
> 
> On Thu, Jul 10, 2014 at 10:04:00AM +0800, Haojian Zhuang wrote:
> > There's a little difference between ARM GIC and HiP04 GIC.
> > 
> > * HiP04 GIC could support 16 cores at most, and ARM GIC could support
> > 8 cores at most. So the difination on GIC_DIST_TARGET registers are
> > different since CPU interfaces are increased from 8-bit to 16-bit.
> > 
> > * HiP04 GIC could support 510 interrupts at most, and ARM GIC could
> > support 1020 interrupts at most.
> > 
> > Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> > ---
> >  Documentation/devicetree/bindings/arm/gic.txt |   1 +
> >  drivers/irqchip/irq-gic.c                     | 141 +++++++++++++++++++-------
> >  2 files changed, 108 insertions(+), 34 deletions(-)
> 
> I need to apologize.  This is my first full cycle maintaining irqchip
> and I'm still coming up to speed.  The tl;dr is, I'm just not
> comfortable with the approach in this patch.
> 
> If irq-gic.c was only used by one SoC, it'd be different, but in the
> scenario we have, I think it would be best if this were a separate
> driver, say irq-gic-hip04.c.  You can link in irq-gic-common.o to get
> gic_dist_config(), and you'll be able to remove a lot of the static
> functions and conditionals.

A better approach might be to have some function pointers with each
compatible string, and then have associated with the HiP04 compatible
string, and then have those call common (inline) function variants. The
compiler can then deal with the different variants and we don't end up
with multiple GIC drivers getting out-of-sync.

Thanks,
Mark.

^ permalink raw reply

* [RFC Patch V1 21/30] mm, irqchip: Use cpu_to_mem()/numa_mem_id() to support memoryless node
From: Jason Cooper @ 2014-07-18 12:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405064267-11678-22-git-send-email-jiang.liu@linux.intel.com>

On Fri, Jul 11, 2014 at 03:37:38PM +0800, Jiang Liu wrote:
> When CONFIG_HAVE_MEMORYLESS_NODES is enabled, cpu_to_node()/numa_node_id()
> may return a node without memory, and later cause system failure/panic
> when calling kmalloc_node() and friends with returned node id.
> So use cpu_to_mem()/numa_mem_id() instead to get the nearest node with
> memory for the/current cpu.
> 
> If CONFIG_HAVE_MEMORYLESS_NODES is disabled, cpu_to_mem()/numa_mem_id()
> is the same as cpu_to_node()/numa_node_id().
> 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>  drivers/irqchip/irq-clps711x.c |    2 +-
>  drivers/irqchip/irq-gic.c      |    2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)

Do you have anything depending on this?  Can apply it to irqchip?  If
you need to keep it with other changes,

Acked-by: Jason Cooper <jason@lakedaemon.net>

But please do let me know if I can take it.

thx,

Jason.

^ permalink raw reply

* [PATCH 0/4 V3] irqchip: gic: Introduce ARM GICv2m MSI(-X) support
From: Mark Rutland @ 2014-07-18 12:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140718123140.GD24496@titan.lakedaemon.net>

On Fri, Jul 18, 2014 at 01:31:40PM +0100, Jason Cooper wrote:
> On Fri, Jul 18, 2014 at 10:02:05AM +0100, Mark Rutland wrote:
> > On Thu, Jul 17, 2014 at 03:12:35PM +0100, Jason Cooper wrote:
> > > On Thu, Jul 17, 2014 at 02:55:34PM +0100, Mark Rutland wrote:
> > > > Hi Jason,
> > > > 
> > > > On Thu, Jul 17, 2014 at 02:18:54PM +0100, Jason Cooper wrote:
> > > > > On Wed, Jul 09, 2014 at 06:05:00PM -0500, suravee.suthikulpanit at amd.com wrote:
> > > > > > From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> > > > > > 
> > > > > > This patch set introduces support for MSI(-X) in GICv2m specification,
> > > > > > which is implemented in some variation of GIC400.
> > > > > > 
> > > > > > This depends on and has been tested with the V7 of"Add support for PCI in AArch64"
> > > > > > (https://lkml.org/lkml/2014/3/14/320).
> > > > > > 
> > > > > > Changes in V3:
> > > > > >     * Rebase to git://git.infradead.org/users/jcooper/linux.git irqchip/gic
> > > > > >       (per Jason Cooper request)
> > > > > >     * Misc fix/clean up per Mark Rutland comments
> > > > > >     * Minor Clean up in the driver/irqchip/irq-gic-v2m.c: alloc_msi_irqs()
> > > > > >     * Patch 4 is new to the series:
> > > > > >         * Add ARM64-specific version arch_setup_msi_irqs() to allow support
> > > > > >           for Multiple MSI.
> > > > > >         * Add support for Multiple MSI for GICv2m.
> > > > > > 
> > > > > > Suravee Suthikulpanit (4):
> > > > > >   irqchip: gic: Add binding probe for ARM GIC400
> > > > > >   irqchip: gic: Restructuring ARM GIC code
> > > > > >   irqchip: gic: Add supports for ARM GICv2m MSI(-X)
> > > > > >   irqchip: gicv2m: Add support for multiple MSI for ARM64 GICv2m
> > > > > 
> > > > > Ok, patch #1 applied to irqchip/urgent.  Patches 2 and 3 applied to
> > > > > irqchip/gic with irqchip/urgent merged in.  To facilitate
> > > > > testing/merging, I've prepared an unsigned tag for you on the
> > > > > irqchip/gic branch:
> > > > 
> > > > I'm a little concerned that this is all going through for v3.17 without
> > > > a {Reviewed,Acked}-by from Marc or anyone working with GIC{,v2m}.
> > > 
> > > Well, that's why it's not in irqchip/core yet. ;-)  It can be undone if
> > > needed.
> > 
> > Ah, perhaps I was a litte premature. :)
> >  
> > > > While his comments on v1 have been addressed, he has not had a chance to
> > > > acknowledge the solutions. I appreciate Marc's holiday is unfortunately
> > > > timed.
> > > > 
> > > > I also have an open concern with the binding with regard to the
> > > > orthogonality of GICV GICH and the MSI registers.
> > > > 
> > > > Suravee, do you need this urgently for v3.17? I was under the impression
> > > > that we wouldn't have full PCIe support by then.
> > > 
> > > If Suravee is ok with it, I can drop them for now and he can resend for
> > > v3.18.  Since we've worked out a way to merge it all in one window, I
> > > don't think it would hurt anything to wait.
> > 
> > Ok.
> > 
> > > I'll leave these in irqchip/for-next until I hear from Suravee, then
> > > I'll drop the lot till we hear from Marc and look at the timing.
> > 
> > Keeping it in for-next for testing sounds like a good idea, but until we
> > hear from Marc I wouldn't want to see this queued for mainline. So the
> > above sounds fine to me.
> 
> Ok, here's what I did:
> 
> [jason at triton] $ git ldo --graph v3.16-rc1^..irqchip/gic-v2m
> * 3e44358c12cc (HEAD, irqchip/gic-v2m) irqchip: gic: Add support for ARM GICv2m MSI(-X)
> * fe7ac63fe539 irqchip: gic: Restructuring ARM GIC code
> *   6bf0be3f077e Merge branch 'irqchip/urgent' into irqchip/gic
> |\  
> | * 144cb08864ed (irqchip/urgent) irqchip: gic: Add binding probe for ARM GIC400
> | * a97e8027b1d2 irqchip: gic: Add support for cortex a7 compatible string
> | * 4f4366033945 (tag: irqchip-urgent-3.16) irqchip: spear_shirq: Fix interrupt offset
> | * 00ac20279174 irqchip: brcmstb-l2: Level-2 interrupts are edge sensitive
> | * b73842b75646 irqchip: armada-370-xp: Mask all interrupts during initialization.
> * | 021f653791ad (tag: deps-irqchip-gic-3.17, irqchip/gic) irqchip: gic-v3: Initial support for GICv3
> * | d51d0af43b30 irqchip: gic: Move some bits of GICv2 to a library-type file
> |/  
> * 7171511eaec5 (tag: v3.16-rc1) Linux 3.16-rc1
> 
> remote branches removed for clarity.
> 
> Basically, I reset irqchip/gic back to tags/deps-irqchip-gic-3.17 (The
> stable tag for GICv3 support), and made the MSI series irqchip/gic-v2m.
> 
> I've also removed the dep tag for gic-v2m (tags/dep-irqchip-gic-3.17-2).
> Please consider irqchip/gic-v2m to be completely unstable and drop-able.
> It'll be in -next, but until I hear from Marc, it's not going anywhere.
> 
> No commit IDs have changed during this process.  The only problem that
> may occur is if the guys depending on GICv3 pulled the branch *and*
> updated it yesterday.  If they pulled the tag as I provided, then
> they're fine.

Ok, let's hope that's the case for now. I'll keep an eye out just in
case.

> Sorry for the confusion, I hope I've made it clear above.

Nothing to worry about, thanks for dealing with this quickly and
effectively. I think we're on the same page now.

Cheers,
Mark.

^ permalink raw reply

* [PATCH 0/4 V3] irqchip: gic: Introduce ARM GICv2m MSI(-X) support
From: Jason Cooper @ 2014-07-18 12:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140718090204.GB25180@leverpostej>

On Fri, Jul 18, 2014 at 10:02:05AM +0100, Mark Rutland wrote:
> On Thu, Jul 17, 2014 at 03:12:35PM +0100, Jason Cooper wrote:
> > On Thu, Jul 17, 2014 at 02:55:34PM +0100, Mark Rutland wrote:
> > > Hi Jason,
> > > 
> > > On Thu, Jul 17, 2014 at 02:18:54PM +0100, Jason Cooper wrote:
> > > > On Wed, Jul 09, 2014 at 06:05:00PM -0500, suravee.suthikulpanit at amd.com wrote:
> > > > > From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> > > > > 
> > > > > This patch set introduces support for MSI(-X) in GICv2m specification,
> > > > > which is implemented in some variation of GIC400.
> > > > > 
> > > > > This depends on and has been tested with the V7 of"Add support for PCI in AArch64"
> > > > > (https://lkml.org/lkml/2014/3/14/320).
> > > > > 
> > > > > Changes in V3:
> > > > >     * Rebase to git://git.infradead.org/users/jcooper/linux.git irqchip/gic
> > > > >       (per Jason Cooper request)
> > > > >     * Misc fix/clean up per Mark Rutland comments
> > > > >     * Minor Clean up in the driver/irqchip/irq-gic-v2m.c: alloc_msi_irqs()
> > > > >     * Patch 4 is new to the series:
> > > > >         * Add ARM64-specific version arch_setup_msi_irqs() to allow support
> > > > >           for Multiple MSI.
> > > > >         * Add support for Multiple MSI for GICv2m.
> > > > > 
> > > > > Suravee Suthikulpanit (4):
> > > > >   irqchip: gic: Add binding probe for ARM GIC400
> > > > >   irqchip: gic: Restructuring ARM GIC code
> > > > >   irqchip: gic: Add supports for ARM GICv2m MSI(-X)
> > > > >   irqchip: gicv2m: Add support for multiple MSI for ARM64 GICv2m
> > > > 
> > > > Ok, patch #1 applied to irqchip/urgent.  Patches 2 and 3 applied to
> > > > irqchip/gic with irqchip/urgent merged in.  To facilitate
> > > > testing/merging, I've prepared an unsigned tag for you on the
> > > > irqchip/gic branch:
> > > 
> > > I'm a little concerned that this is all going through for v3.17 without
> > > a {Reviewed,Acked}-by from Marc or anyone working with GIC{,v2m}.
> > 
> > Well, that's why it's not in irqchip/core yet. ;-)  It can be undone if
> > needed.
> 
> Ah, perhaps I was a litte premature. :)
>  
> > > While his comments on v1 have been addressed, he has not had a chance to
> > > acknowledge the solutions. I appreciate Marc's holiday is unfortunately
> > > timed.
> > > 
> > > I also have an open concern with the binding with regard to the
> > > orthogonality of GICV GICH and the MSI registers.
> > > 
> > > Suravee, do you need this urgently for v3.17? I was under the impression
> > > that we wouldn't have full PCIe support by then.
> > 
> > If Suravee is ok with it, I can drop them for now and he can resend for
> > v3.18.  Since we've worked out a way to merge it all in one window, I
> > don't think it would hurt anything to wait.
> 
> Ok.
> 
> > I'll leave these in irqchip/for-next until I hear from Suravee, then
> > I'll drop the lot till we hear from Marc and look at the timing.
> 
> Keeping it in for-next for testing sounds like a good idea, but until we
> hear from Marc I wouldn't want to see this queued for mainline. So the
> above sounds fine to me.

Ok, here's what I did:

[jason at triton] $ git ldo --graph v3.16-rc1^..irqchip/gic-v2m
* 3e44358c12cc (HEAD, irqchip/gic-v2m) irqchip: gic: Add support for ARM GICv2m MSI(-X)
* fe7ac63fe539 irqchip: gic: Restructuring ARM GIC code
*   6bf0be3f077e Merge branch 'irqchip/urgent' into irqchip/gic
|\  
| * 144cb08864ed (irqchip/urgent) irqchip: gic: Add binding probe for ARM GIC400
| * a97e8027b1d2 irqchip: gic: Add support for cortex a7 compatible string
| * 4f4366033945 (tag: irqchip-urgent-3.16) irqchip: spear_shirq: Fix interrupt offset
| * 00ac20279174 irqchip: brcmstb-l2: Level-2 interrupts are edge sensitive
| * b73842b75646 irqchip: armada-370-xp: Mask all interrupts during initialization.
* | 021f653791ad (tag: deps-irqchip-gic-3.17, irqchip/gic) irqchip: gic-v3: Initial support for GICv3
* | d51d0af43b30 irqchip: gic: Move some bits of GICv2 to a library-type file
|/  
* 7171511eaec5 (tag: v3.16-rc1) Linux 3.16-rc1

remote branches removed for clarity.

Basically, I reset irqchip/gic back to tags/deps-irqchip-gic-3.17 (The
stable tag for GICv3 support), and made the MSI series irqchip/gic-v2m.

I've also removed the dep tag for gic-v2m (tags/dep-irqchip-gic-3.17-2).
Please consider irqchip/gic-v2m to be completely unstable and drop-able.
It'll be in -next, but until I hear from Marc, it's not going anywhere.

No commit IDs have changed during this process.  The only problem that
may occur is if the guys depending on GICv3 pulled the branch *and*
updated it yesterday.  If they pulled the tag as I provided, then
they're fine.

Sorry for the confusion, I hope I've made it clear above.

thx,

Jason.
> 
> Cheers,
> Mark.

^ permalink raw reply

* [PATCH v10 8/8] ARM: berlin: enable the eSATA interface on the BG2Q DMP
From: Antoine Ténart @ 2014-07-18 12:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405686607-8126-1-git-send-email-antoine.tenart@free-electrons.com>

The BG2Q has an AHCI SATA controller with an eSATA interface. Enable it.
Only enable the first port, the BG2Q DMP does not support the second one.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2q-marvell-dmp.dts | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
index 995150f93795..385f6af64d0c 100644
--- a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
+++ b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
@@ -37,3 +37,11 @@
 &uart0 {
 	status = "okay";
 };
+
+&sata0 {
+	status = "okay";
+};
+
+&sata_phy {
+	status = "okay";
+};
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 7/8] ARM: berlin: add the AHCI node for the BG2Q
From: Antoine Ténart @ 2014-07-18 12:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405686607-8126-1-git-send-email-antoine.tenart@free-electrons.com>

The BG2Q has an AHCI SATA controller. Add the corresponding nodes
(AHCI, PHY) into its device tree.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 arch/arm/boot/dts/berlin2q.dtsi | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index 635a16a64cb4..fa34ae6657ac 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -303,6 +303,45 @@
 			clock-names = "refclk";
 		};
 
+		ahci: sata at e90000 {
+			compatible = "generic-ahci";
+			reg = <0xe90000 0x1000>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&chip CLKID_SATA>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			sata0: sata-port at 0 {
+				reg = <0>;
+				phys = <&sata_phy 0>;
+				status = "disabled";
+			};
+
+			sata1: sata-port at 1 {
+				reg = <1>;
+				phys = <&sata_phy 1>;
+				status = "disabled";
+			};
+		};
+
+		sata_phy: phy at e900a0 {
+			compatible = "marvell,berlin2q-sata-phy";
+			reg = <0xe900a0 0x200>;
+			clocks = <&chip CLKID_SATA>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#phy-cells = <1>;
+			status = "disabled";
+
+			sata-phy at 0 {
+				reg = <0>;
+			};
+
+			sata-phy at 1 {
+				reg = <1>;
+			};
+		};
+
 		apb at fc0000 {
 			compatible = "simple-bus";
 			#address-cells = <1>;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 6/8] Documentation: bindings: document the sub-nodes AHCI bindings
From: Antoine Ténart @ 2014-07-18 12:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405686607-8126-1-git-send-email-antoine.tenart@free-electrons.com>

The libahci now allows to use multiple PHYs and to represent each port
as a sub-node. Add these bindings to the documentation.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 .../devicetree/bindings/ata/ahci-platform.txt      | 37 ++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index c96d8dcf98fd..24d95fccfb4a 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -3,6 +3,10 @@
 SATA nodes are defined to describe on-chip Serial ATA controllers.
 Each SATA controller should have its own node.
 
+It is possible, but not required, to represent each port as a sub-node.
+It allows to enable each port independently when dealing with multiple
+PHYs.
+
 Required properties:
 - compatible        : compatible string, one of:
   - "allwinner,sun4i-a10-ahci"
@@ -14,6 +18,7 @@ Required properties:
   - "snps,dwc-ahci"
   - "snps,exynos5440-ahci"
   - "snps,spear-ahci"
+  - "generic-ahci"
 - interrupts        : <interrupt mapping for SATA IRQ>
 - reg               : <registers mapping>
 
@@ -21,11 +26,23 @@ Optional properties:
 - dma-coherent      : Present if dma operations are coherent
 - clocks            : a list of phandle + clock specifier pairs
 - target-supply     : regulator for SATA target power
+- phys              : reference to the SATA PHY node
+- phy-names         : must be "sata-phy"
 
 "fsl,imx53-ahci", "fsl,imx6q-ahci" required properties:
 - clocks            : must contain the sata, sata_ref and ahb clocks
 - clock-names       : must contain "ahb" for the ahb clock
 
+Required properties when using sub-nodes:
+- #address-cells    : number of cells to encode an address
+- #size-cells       : number of cells representing the size of an address
+
+
+Sub-nodes required properties:
+- reg               : the port number
+- phys              : reference to the SATA PHY node
+
+
 Examples:
         sata at ffe08000 {
 		compatible = "snps,spear-ahci";
@@ -40,3 +57,23 @@ Examples:
 		clocks = <&pll6 0>, <&ahb_gates 25>;
 		target-supply = <&reg_ahci_5v>;
 	};
+
+With sub-nodes:
+	sata at f7e90000 {
+		compatible = "generic-ahci";
+		reg = <0xe90000 0x1000>;
+		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&chip CLKID_SATA>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		sata0: sata-port at 0 {
+			reg = <0>;
+			phys = <&sata_phy 0>;
+		};
+
+		sata1: sata-port at 1 {
+			reg = <1>;
+			phys = <&sata_phy 1>;
+		};
+	};
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 5/8] ata: ahci_platform: add a generic AHCI compatible
From: Antoine Ténart @ 2014-07-18 12:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405686607-8126-1-git-send-email-antoine.tenart@free-electrons.com>

The ahci_platform driver is a generic driver using the libahci_platform
functions. Add a generic compatible to avoid having an endless list of
compatibles with no differences for the same driver.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 drivers/ata/ahci_platform.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 95f9ca82082a..61b15e784020 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -77,6 +77,8 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
 			 ahci_platform_resume);
 
 static const struct of_device_id ahci_of_match[] = {
+	{ .compatible = "generic-ahci", },
+	/* Keep the following compatibles for device tree compatibility */
 	{ .compatible = "snps,spear-ahci", },
 	{ .compatible = "snps,exynos5440-ahci", },
 	{ .compatible = "ibm,476gtr-ahci", },
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 4/8] ata: libahci: allow to use multiple PHYs
From: Antoine Ténart @ 2014-07-18 12:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405686607-8126-1-git-send-email-antoine.tenart@free-electrons.com>

The current implementation of the libahci does not allow to use multiple
PHYs. This patch adds the support of multiple PHYs by the libahci while
keeping the old bindings valid for device tree compatibility.

This introduce a new way of defining SATA ports in the device tree, with
one port per sub-node. This as the advantage of allowing a per port
configuration. Because some ports may be accessible but disabled in the
device tree, the port_map mask is computed automatically when using
this.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 drivers/ata/ahci.h             |   3 +-
 drivers/ata/libahci_platform.c | 179 ++++++++++++++++++++++++++++++++---------
 2 files changed, 142 insertions(+), 40 deletions(-)

diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index cb8d58926851..b0ea7b077d6e 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -332,7 +332,8 @@ struct ahci_host_priv {
 	bool			got_runtime_pm; /* Did we do pm_runtime_get? */
 	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
 	struct regulator	*target_pwr;	/* Optional */
-	struct phy		*phy;		/* If platform uses phy */
+	struct phy		**phys;		/* If platform uses phys */
+	unsigned		nphys;		/* Number of phys */
 	void			*plat_data;	/* Other platform data */
 	/*
 	 * Optional ahci_start_engine override, if not set this gets set to the
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index db9b90d876dd..2c2439b4101d 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -39,6 +39,61 @@ static struct scsi_host_template ahci_platform_sht = {
 };
 
 /**
+ * ahci_platform_enable_phys - Enable PHYs
+ * @hpriv: host private area to store config values
+ *
+ * This function enables all the PHYs found in hpriv->phys, if any.
+ * If a PHY fails to be enabled, it disables all the PHYs already
+ * enabled in reverse order and returns an error.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
+{
+	int i, rc = 0;
+
+	for (i = 0; i < hpriv->nphys; i++) {
+		rc = phy_init(hpriv->phys[i]);
+		if (rc)
+			goto disable_phys;
+
+		rc = phy_power_on(hpriv->phys[i]);
+		if (rc) {
+			phy_exit(hpriv->phys[i]);
+			goto disable_phys;
+		}
+	}
+
+	return 0;
+
+disable_phys:
+	while (--i >= 0) {
+		phy_power_off(hpriv->phys[i]);
+		phy_exit(hpriv->phys[i]);
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_enable_phys);
+
+/**
+ * ahci_platform_disable_phys - Enable PHYs
+ * @hpriv: host private area to store config values
+ *
+ * This function disables all PHYs found in hpriv->phys.
+ */
+void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
+{
+	int i;
+
+	for (i = 0; i < hpriv->nphys; i++) {
+		phy_power_off(hpriv->phys[i]);
+		phy_exit(hpriv->phys[i]);
+	}
+}
+EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
+
+/**
  * ahci_platform_enable_clks - Enable platform clocks
  * @hpriv: host private area to store config values
  *
@@ -92,7 +147,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
  * following order:
  * 1) Regulator
  * 2) Clocks (through ahci_platform_enable_clks)
- * 3) Phy
+ * 3) Phys
  *
  * If resource enabling fails at any point the previous enabled resources
  * are disabled in reverse order.
@@ -114,17 +169,9 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
 	if (rc)
 		goto disable_regulator;
 
-	if (hpriv->phy) {
-		rc = phy_init(hpriv->phy);
-		if (rc)
-			goto disable_clks;
-
-		rc = phy_power_on(hpriv->phy);
-		if (rc) {
-			phy_exit(hpriv->phy);
-			goto disable_clks;
-		}
-	}
+	rc = ahci_platform_enable_phys(hpriv);
+	if (rc)
+		goto disable_clks;
 
 	return 0;
 
@@ -144,16 +191,13 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
  *
  * This function disables all ahci_platform managed resources in the
  * following order:
- * 1) Phy
+ * 1) Phys
  * 2) Clocks (through ahci_platform_disable_clks)
  * 3) Regulator
  */
 void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
 {
-	if (hpriv->phy) {
-		phy_power_off(hpriv->phy);
-		phy_exit(hpriv->phy);
-	}
+	ahci_platform_disable_phys(hpriv);
 
 	ahci_platform_disable_clks(hpriv);
 
@@ -187,7 +231,7 @@ static void ahci_platform_put_resources(struct device *dev, void *res)
  * 2) regulator for controlling the targets power (optional)
  * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
  *    or for non devicetree enabled platforms a single clock
- *	4) phy (optional)
+ *	4) phys (optional)
  *
  * RETURNS:
  * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
@@ -197,7 +241,9 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct ahci_host_priv *hpriv;
 	struct clk *clk;
-	int i, rc = -ENOMEM;
+	struct device_node *child;
+	int i, nports, rc = -ENOMEM;
+	u32 mask_port_map = 0;
 
 	if (!devres_open_group(dev, NULL, GFP_KERNEL))
 		return ERR_PTR(-ENOMEM);
@@ -246,27 +292,82 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
 		hpriv->clks[i] = clk;
 	}
 
-	hpriv->phy = devm_phy_get(dev, "sata-phy");
-	if (IS_ERR(hpriv->phy)) {
-		rc = PTR_ERR(hpriv->phy);
-		switch (rc) {
-		case -ENOSYS:
-			/* No PHY support. Check if PHY is required. */
-			if (of_find_property(dev->of_node, "phys", NULL)) {
-				dev_err(dev, "couldn't get sata-phy: ENOSYS\n");
+	nports = of_get_child_count(dev->of_node);
+
+	if (nports) {
+		hpriv->phys = devm_kzalloc(dev, nports * sizeof(*hpriv->phys),
+					   GFP_KERNEL);
+		if (!hpriv->phys) {
+			rc = -ENOMEM;
+			goto err_out;
+		}
+
+		for_each_child_of_node(dev->of_node, child) {
+			u32 port;
+
+			if (!of_device_is_available(child))
+				continue;
+
+			if (of_property_read_u32(child, "reg", &port)) {
+				rc = -EINVAL;
 				goto err_out;
 			}
-		case -ENODEV:
-			/* continue normally */
-			hpriv->phy = NULL;
-			break;
 
-		case -EPROBE_DEFER:
-			goto err_out;
+			mask_port_map |= BIT(port);
 
-		default:
-			dev_err(dev, "couldn't get sata-phy\n");
-			goto err_out;
+			hpriv->phys[hpriv->nphys] = devm_of_phy_get(dev, child,
+								    NULL);
+			if (IS_ERR(hpriv->phys[hpriv->nphys])) {
+				rc = PTR_ERR(hpriv->phys[hpriv->nphys]);
+				dev_err(dev,
+					"couldn't get PHY in node %s: %d\n",
+					child->name, rc);
+				goto err_out;
+			}
+
+			hpriv->nphys++;
+		}
+		if (!hpriv->nphys) {
+			dev_warn(dev, "No port enabled\n");
+			return ERR_PTR(-ENODEV);
+		}
+
+		if (!hpriv->mask_port_map)
+			hpriv->mask_port_map = mask_port_map;
+	} else {
+		/*
+		 * If no sub-node was found, keep this for device tree
+		 * compatibility
+		 */
+		struct phy *phy = devm_phy_get(dev, "sata-phy");
+		if (!IS_ERR(phy)) {
+			hpriv->phys = devm_kzalloc(dev, sizeof(*hpriv->phys),
+						   GFP_KERNEL);
+			if (!hpriv->phys) {
+				rc = -ENOMEM;
+				goto err_out;
+			}
+
+			hpriv->phys[0] = phy;
+			hpriv->nphys = 1;
+		} else {
+			rc = PTR_ERR(phy);
+			switch (rc) {
+				case -ENOSYS:
+					/* No PHY support. Check if PHY is required. */
+					if (of_find_property(dev->of_node, "phys", NULL)) {
+						dev_err(dev, "couldn't get sata-phy: ENOSYS\n");
+						goto err_out;
+					}
+				case -ENODEV:
+					/* continue normally */
+					hpriv->phys = NULL;
+					break;
+
+				default:
+					goto err_out;
+
+			}
 		}
 	}
 
@@ -291,7 +392,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
  * @host_flags: ahci host flags used in ahci_host_priv
  *
  * This function does all the usual steps needed to bring up an
- * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * ahci-platform host, note any necessary resources (ie clks, phys, etc.)
  * must be initialized / enabled before calling this.
  *
  * RETURNS:
@@ -395,7 +496,7 @@ static void ahci_host_stop(struct ata_host *host)
  * @dev: device pointer for the host
  *
  * This function does all the usual steps needed to suspend an
- * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * ahci-platform host, note any necessary resources (ie clks, phys, etc.)
  * must be disabled after calling this.
  *
  * RETURNS:
@@ -432,7 +533,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
  * @dev: device pointer for the host
  *
  * This function does all the usual steps needed to resume an ahci-platform
- * host, note any necessary resources (ie clks, phy, etc.)  must be
+ * host, note any necessary resources (ie clks, phys, etc.)  must be
  * initialized / enabled before calling this.
  *
  * RETURNS:
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 3/8] ata: libahci_platform: move port_map parameters into the AHCI structure
From: Antoine Ténart @ 2014-07-18 12:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405686607-8126-1-git-send-email-antoine.tenart@free-electrons.com>

This patch moves force_port_map and mask_port_map into the
ahci_host_priv structure. This allows to modify them into the AHCI
framework. This is needed by the new dt bindings representing ports as
the port_map mask is computed automatically.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 drivers/ata/ahci.h             |  6 +++---
 drivers/ata/ahci_da850.c       |  3 +--
 drivers/ata/ahci_imx.c         |  3 +--
 drivers/ata/ahci_mvebu.c       |  3 +--
 drivers/ata/ahci_platform.c    |  3 +--
 drivers/ata/ahci_st.c          |  2 +-
 drivers/ata/ahci_sunxi.c       |  2 +-
 drivers/ata/ahci_xgene.c       |  2 +-
 drivers/ata/libahci.c          | 17 +++++++----------
 drivers/ata/libahci_platform.c |  8 ++------
 include/linux/ahci_platform.h  |  4 +---
 11 files changed, 20 insertions(+), 33 deletions(-)

diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 5513296e5e2e..cb8d58926851 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -321,6 +321,8 @@ struct ahci_host_priv {
 	u32			cap;		/* cap to use */
 	u32			cap2;		/* cap2 to use */
 	u32			port_map;	/* port map to use */
+	u32			force_port_map;	/* force port map */
+	u32			mask_port_map;	/* mask out particular bits */
 	u32			saved_cap;	/* saved initial cap */
 	u32			saved_cap2;	/* saved initial cap2 */
 	u32			saved_port_map;	/* saved initial port_map */
@@ -361,9 +363,7 @@ unsigned int ahci_dev_classify(struct ata_port *ap);
 void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
 			u32 opts);
 void ahci_save_initial_config(struct device *dev,
-			      struct ahci_host_priv *hpriv,
-			      unsigned int force_port_map,
-			      unsigned int mask_port_map);
+			      struct ahci_host_priv *hpriv);
 void ahci_init_controller(struct ata_host *host);
 int ahci_reset_controller(struct ata_host *host);
 
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
index 2b77d53bccf8..33b862b2c5db 100644
--- a/drivers/ata/ahci_da850.c
+++ b/drivers/ata/ahci_da850.c
@@ -85,8 +85,7 @@ static int ahci_da850_probe(struct platform_device *pdev)
 
 	da850_sata_init(dev, pwrdn_reg, hpriv->mmio);
 
-	rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info,
-				     0, 0, 0);
+	rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info, 0);
 	if (rc)
 		goto disable_resources;
 
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index cac4360f272a..c8eef2d745d8 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -454,8 +454,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
 	reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
 	writel(reg_val, hpriv->mmio + IMX_TIMER1MS);
 
-	ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info,
-				      0, 0, 0);
+	ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, 0);
 	if (ret)
 		goto disable_sata;
 
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c
index fd3dfd733b84..0ba0cf7a9ba9 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_mvebu.c
@@ -88,8 +88,7 @@ static int ahci_mvebu_probe(struct platform_device *pdev)
 	ahci_mvebu_mbus_config(hpriv, dram);
 	ahci_mvebu_regret_option(hpriv);
 
-	rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info,
-				     0, 0, 0);
+	rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info, 0);
 	if (rc)
 		goto disable_resources;
 
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index b10d81ddb528..95f9ca82082a 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -60,8 +60,7 @@ static int ahci_probe(struct platform_device *pdev)
 	if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci"))
 		hflags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
 
-	rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info,
-				     hflags, 0, 0);
+	rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, hflags);
 	if (rc)
 		goto pdata_exit;
 
diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c
index 2595598df9ce..6767c7790b4a 100644
--- a/drivers/ata/ahci_st.c
+++ b/drivers/ata/ahci_st.c
@@ -166,7 +166,7 @@ static int st_ahci_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, 0, 0, 0);
+	err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, 0);
 	if (err) {
 		ahci_platform_disable_resources(hpriv);
 		return err;
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
index 02002f125bd4..9f8ff1f9e912 100644
--- a/drivers/ata/ahci_sunxi.c
+++ b/drivers/ata/ahci_sunxi.c
@@ -188,7 +188,7 @@ static int ahci_sunxi_probe(struct platform_device *pdev)
 		 AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ;
 
 	rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info,
-				     hflags, 0, 0);
+				     hflags);
 	if (rc)
 		goto disable_resources;
 
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index ee3a3659bd9e..87d39fbe616b 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -487,7 +487,7 @@ static int xgene_ahci_probe(struct platform_device *pdev)
 	hflags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ;
 
 	rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info,
-				     hflags, 0, 0);
+				     hflags);
 	if (rc)
 		goto disable_resources;
 
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index d72ce0470309..3c0b623747bd 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -398,10 +398,7 @@ static ssize_t ahci_show_em_supported(struct device *dev,
  *	LOCKING:
  *	None.
  */
-void ahci_save_initial_config(struct device *dev,
-			      struct ahci_host_priv *hpriv,
-			      unsigned int force_port_map,
-			      unsigned int mask_port_map)
+void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 {
 	void __iomem *mmio = hpriv->mmio;
 	u32 cap, cap2, vers, port_map;
@@ -468,17 +465,17 @@ void ahci_save_initial_config(struct device *dev,
 		cap &= ~HOST_CAP_FBS;
 	}
 
-	if (force_port_map && port_map != force_port_map) {
+	if (hpriv->force_port_map && port_map != hpriv->force_port_map) {
 		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
-			 port_map, force_port_map);
-		port_map = force_port_map;
+			 port_map, hpriv->force_port_map);
+		port_map = hpriv->force_port_map;
 	}
 
-	if (mask_port_map) {
+	if (hpriv->mask_port_map) {
 		dev_warn(dev, "masking port_map 0x%x -> 0x%x\n",
 			port_map,
-			port_map & mask_port_map);
-		port_map &= mask_port_map;
+			port_map & hpriv->mask_port_map);
+		port_map &= hpriv->mask_port_map;
 	}
 
 	/* cross check port_map and cap.n_ports */
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index b0077589f065..db9b90d876dd 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -289,8 +289,6 @@ EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
  * @hpriv: ahci-host private data for the host
  * @pi_template: template for the ata_port_info to use
  * @host_flags: ahci host flags used in ahci_host_priv
- * @force_port_map: param passed to ahci_save_initial_config
- * @mask_port_map: param passed to ahci_save_initial_config
  *
  * This function does all the usual steps needed to bring up an
  * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
@@ -302,9 +300,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
 int ahci_platform_init_host(struct platform_device *pdev,
 			    struct ahci_host_priv *hpriv,
 			    const struct ata_port_info *pi_template,
-			    unsigned long host_flags,
-			    unsigned int force_port_map,
-			    unsigned int mask_port_map)
+			    unsigned long host_flags)
 {
 	struct device *dev = &pdev->dev;
 	struct ata_port_info pi = *pi_template;
@@ -322,7 +318,7 @@ int ahci_platform_init_host(struct platform_device *pdev,
 	pi.private_data = (void *)host_flags;
 	hpriv->flags |= host_flags;
 
-	ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
+	ahci_save_initial_config(dev, hpriv);
 
 	if (hpriv->cap & HOST_CAP_NCQ)
 		pi.flags |= ATA_FLAG_NCQ;
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 6dfd51a04d77..554bcafa7eb4 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -44,9 +44,7 @@ struct ahci_host_priv *ahci_platform_get_resources(
 int ahci_platform_init_host(struct platform_device *pdev,
 			    struct ahci_host_priv *hpriv,
 			    const struct ata_port_info *pi_template,
-			    unsigned long host_flags,
-			    unsigned int force_port_map,
-			    unsigned int mask_port_map);
+			    unsigned long host_flags);
 
 int ahci_platform_suspend_host(struct device *dev);
 int ahci_platform_resume_host(struct device *dev);
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 2/8] Documentation: bindings: add the Berlin SATA PHY
From: Antoine Ténart @ 2014-07-18 12:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405686607-8126-1-git-send-email-antoine.tenart@free-electrons.com>

The Berlin SATA PHY drives the PHY related to the SATA interface. Add
the corresponding documentation.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 .../devicetree/bindings/phy/berlin-sata-phy.txt    | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/berlin-sata-phy.txt

diff --git a/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt b/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
new file mode 100644
index 000000000000..88f8c23384c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
@@ -0,0 +1,34 @@
+Berlin SATA PHY
+---------------
+
+Required properties:
+- compatible: should be "marvell,berlin2q-sata-phy"
+- address-cells: should be 1
+- size-cells: should be 0
+- phy-cells: from the generic PHY bindings, must be 1
+- reg: address and length of the register
+- clocks: reference to the clock entry
+
+Sub-nodes:
+Each PHY should be represented as a sub-node.
+
+Sub-nodes required properties:
+- reg: the PHY number
+
+Example:
+	sata_phy: phy at f7e900a0 {
+		compatible = "marvell,berlin2q-sata-phy";
+		reg = <0xf7e900a0 0x200>;
+		clocks = <&chip CLKID_SATA>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#phy-cells = <1>;
+
+		sata-phy at 0 {
+			reg = <0>;
+		};
+
+		sata-phy at 1 {
+			reg = <1>;
+		};
+	};
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 1/8] phy: add a driver for the Berlin SATA PHY
From: Antoine Ténart @ 2014-07-18 12:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405686607-8126-1-git-send-email-antoine.tenart@free-electrons.com>

The Berlin SoC has a two SATA ports. Add a PHY driver to handle them.

The mode selection can let us think this PHY can be configured to fit
other purposes. But there are reasons to think the SATA mode will be
the only one usable: the PHY registers are only accessible indirectly
through two registers in the SATA range, the PHY seems to be integrated
and no information tells us the contrary. For these reasons, make the
driver a SATA PHY driver.

Signed-off-by: Antoine T?nart <antoine.tenart@free-electrons.com>
---
 drivers/phy/Kconfig           |   7 ++
 drivers/phy/Makefile          |   1 +
 drivers/phy/phy-berlin-sata.c | 284 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 292 insertions(+)
 create mode 100644 drivers/phy/phy-berlin-sata.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 64b98d242ea6..458b15ae2e81 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -15,6 +15,13 @@ config GENERIC_PHY
 	  phy users can obtain reference to the PHY. All the users of this
 	  framework should select this config.
 
+config PHY_BERLIN_SATA
+	tristate "Marvell Berlin SATA PHY driver"
+	depends on ARCH_BERLIN && HAS_IOMEM && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the SATA PHY on Marvell Berlin SoCs.
+
 config PHY_EXYNOS_MIPI_VIDEO
 	tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
 	depends on HAS_IOMEM
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index b4f1d5770601..a137a2e23218 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
+obj-$(CONFIG_PHY_BERLIN_SATA)		+= phy-berlin-sata.o
 obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
 obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
new file mode 100644
index 000000000000..c5e688b0899f
--- /dev/null
+++ b/drivers/phy/phy-berlin-sata.c
@@ -0,0 +1,284 @@
+/*
+ * Marvell Berlin SATA PHY driver
+ *
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine T?nart <antoine.tenart@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#define HOST_VSA_ADDR		0x0
+#define HOST_VSA_DATA		0x4
+#define PORT_SCR_CTL		0x2c
+#define PORT_VSR_ADDR		0x78
+#define PORT_VSR_DATA		0x7c
+
+#define CONTROL_REGISTER	0x0
+#define MBUS_SIZE_CONTROL	0x4
+
+#define POWER_DOWN_PHY0			BIT(6)
+#define POWER_DOWN_PHY1			BIT(14)
+#define MBUS_WRITE_REQUEST_SIZE_128	(BIT(2) << 16)
+#define MBUS_READ_REQUEST_SIZE_128	(BIT(2) << 19)
+
+#define PHY_BASE		0x200
+
+/* register 0x01 */
+#define REF_FREF_SEL_25		BIT(0)
+#define PHY_MODE_SATA		(0x0 << 5)
+
+/* register 0x02 */
+#define USE_MAX_PLL_RATE	BIT(12)
+
+/* register 0x23 */
+#define DATA_BIT_WIDTH_10	(0x0 << 10)
+#define DATA_BIT_WIDTH_20	(0x1 << 10)
+#define DATA_BIT_WIDTH_40	(0x2 << 10)
+
+/* register 0x25 */
+#define PHY_GEN_MAX_1_5		(0x0 << 10)
+#define PHY_GEN_MAX_3_0		(0x1 << 10)
+#define PHY_GEN_MAX_6_0		(0x2 << 10)
+
+struct phy_berlin_desc {
+	struct phy	*phy;
+	u32		power_bit;
+	unsigned	index;
+};
+
+struct phy_berlin_priv {
+	void __iomem		*base;
+	spinlock_t		lock;
+	struct clk		*clk;
+	struct phy_berlin_desc	**phys;
+	unsigned		nphys;
+};
+
+static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg, u32 reg,
+					       u32 mask, u32 val)
+{
+	u32 regval;
+
+	/* select register */
+	writel(PHY_BASE + reg, ctrl_reg + PORT_VSR_ADDR);
+
+	/* set bits */
+	regval = readl(ctrl_reg + PORT_VSR_DATA);
+	regval &= ~mask;
+	regval |= val;
+	writel(regval, ctrl_reg + PORT_VSR_DATA);
+}
+
+static int phy_berlin_sata_power_on(struct phy *phy)
+{
+	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+	void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
+	int ret = 0;
+	u32 regval;
+
+	clk_prepare_enable(priv->clk);
+
+	spin_lock(&priv->lock);
+
+	/* Power on PHY */
+	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval &= ~desc->power_bit;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	/* Configure MBus */
+	writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	/* set PHY mode and ref freq to 25 MHz */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x1, 0xff,
+				    REF_FREF_SEL_25 | PHY_MODE_SATA);
+
+	/* set PHY up to 6 Gbps */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x25, 0xc00, PHY_GEN_MAX_6_0);
+
+	/* set 40 bits width */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x23,  0xc00, DATA_BIT_WIDTH_40);
+
+	/* use max pll rate */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x2, 0x0, USE_MAX_PLL_RATE);
+
+	/* set Gen3 controller speed */
+	regval = readl(ctrl_reg + PORT_SCR_CTL);
+	regval &= ~GENMASK(7, 4);
+	regval |= 0x30;
+	writel(regval, ctrl_reg + PORT_SCR_CTL);
+
+	spin_unlock(&priv->lock);
+
+	clk_disable_unprepare(priv->clk);
+
+	return ret;
+}
+
+static int phy_berlin_sata_power_off(struct phy *phy)
+{
+	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+	u32 regval;
+
+	clk_prepare_enable(priv->clk);
+
+	spin_lock(&priv->lock);
+
+	/* Power down PHY */
+	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval |= desc->power_bit;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	spin_unlock(&priv->lock);
+
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
+					     struct of_phandle_args *args)
+{
+	struct phy_berlin_priv *priv = dev_get_drvdata(dev);
+	int i;
+
+	if (WARN_ON(args->args[0] >= priv->nphys))
+		return ERR_PTR(-ENODEV);
+
+	for (i = 0; i < priv->nphys; i++) {
+		if (priv->phys[i]->index == args->args[0])
+			break;
+	}
+
+	if (i == priv->nphys)
+		return ERR_PTR(-ENODEV);
+
+	return priv->phys[i]->phy;
+}
+
+static struct phy_ops phy_berlin_sata_ops = {
+	.power_on	= phy_berlin_sata_power_on,
+	.power_off	= phy_berlin_sata_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static u32 phy_berlin_power_down_bits[] = {
+	POWER_DOWN_PHY0,
+	POWER_DOWN_PHY1,
+};
+
+static int phy_berlin_sata_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *child;
+	struct phy *phy;
+	struct phy_provider *phy_provider;
+	struct phy_berlin_priv *priv;
+	struct resource *res;
+	int i = 0;
+	u32 phy_id;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	priv->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk))
+		return PTR_ERR(priv->clk);
+
+	priv->nphys = of_get_child_count(dev->of_node);
+	if (priv->nphys == 0)
+		return -ENODEV;
+
+	priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys),
+				  GFP_KERNEL);
+	if (!priv->phys)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, priv);
+	spin_lock_init(&priv->lock);
+
+	for_each_available_child_of_node(dev->of_node, child) {
+		struct phy_berlin_desc *phy_desc;
+
+		if (of_property_read_u32(child, "reg", &phy_id)) {
+			dev_err(dev, "missing reg property in node %s\n",
+				child->name);
+			return -EINVAL;
+		}
+
+		if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
+			dev_err(dev, "invalid reg in node %s\n", child->name);
+			return -EINVAL;
+		}
+
+		phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
+		if (!phy_desc)
+			return -ENOMEM;
+
+		phy = devm_phy_create(dev, &phy_berlin_sata_ops, NULL);
+		if (IS_ERR(phy)) {
+			dev_err(dev, "failed to create PHY %d\n", phy_id);
+			return PTR_ERR(phy);
+		}
+
+		phy_desc->phy = phy;
+		phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
+		phy_desc->index = phy_id;
+		phy_set_drvdata(phy, phy_desc);
+
+		priv->phys[i++] = phy_desc;
+
+		/* Make sure the PHY is off */
+		phy_berlin_sata_power_off(phy);
+	}
+
+	phy_provider =
+		devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	return 0;
+}
+
+static const struct of_device_id phy_berlin_sata_of_match[] = {
+	{ .compatible = "marvell,berlin2q-sata-phy" },
+	{ },
+};
+
+static struct platform_driver phy_berlin_sata_driver = {
+	.probe	= phy_berlin_sata_probe,
+	.driver	= {
+		.name		= "phy-berlin-sata",
+		.owner		= THIS_MODULE,
+		.of_match_table	= phy_berlin_sata_of_match,
+	},
+};
+module_platform_driver(phy_berlin_sata_driver);
+
+MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
+MODULE_AUTHOR("Antoine T?nart <antoine.tenart@free-electrons.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 0/8] ARM: berlin: add AHCI support
From: Antoine Ténart @ 2014-07-18 12:29 UTC (permalink / raw)
  To: linux-arm-kernel

Tejun, Kishon, Sebastian,

I looked into the AHCI framework to see how to map PHYs and ports
information. I see two ways of doing this:
  - We can attach the ahci_port_priv to the ahci_host_priv structure,
    but that would require quite a lot of changes since the
    ahci_port_priv is initialized at the very end (in port_start()) and
    because ahci_port_priv is currently retrieved from the ata_port
    structure in libahci functions. We do want to parse the dt ports
    early in the AHCI initialization to be able to generate the right
    port_map mask. Tests would be needed to ensure nothing is broken.
  - We can move the PHY handling to where the ports are handled, moving
    PHYs from ahci_host_priv to ahci_port_priv. This also would require
    to perform some tests as PHY operations would be moved from
    libahci_platform to libahci.

In both cases we do not have time to do this for the next release, as
the request popped up quite late.

So as of now:
  - Either the series is merged as is and changes to the AHCI framework
    can be made for 3.18, as it's not particularly linked to this
    series.
  - Or you really do not want it. Then that would be great if patches
    1-2 and 7-8 could be merged so that we do not end up with this big
    series going for yet another cycle... I think Kishon already took
    patches 1-2.

I've done the required modifications so that port_map is not used
anymore as a mask during the initialization (patch 3).

Thanks,

Antoine


Changes since v9:
        - moved port_map parameters into the AHCI structure

Changes since v8:
        - stopped reset the controller from the PHY driver
        - removed fixed array sizes
        - got rid of the custom to_berlin_sata_phy_priv() macro
        - added dependency to HAS_IOMEM

Changes since v7:
        - got back to the each PHY as a sub-node representation
        - renamed the power bit in the PHY driver

Changes since v6:
        - added the 'clocks' property and support in the PHY driver
        - updated the PHY compatible

Changes since v5:
        - rebased on top of v3.16-rc1
        - added the 'clocks' property in the sata node

Changes since v4:
        - updated PHY driver as tristate
        - handled the case were no SATA port is enabled
        - updated the compatible to a generic one
        - cosmetic fixups

Changes since v3:
        - moved all PHY operations to the PHY driver
        - removed PHY sub-nodes
        - removed the custom Berlin AHCI driver and switched to
          ahci_platform
        - added multiple PHYs support to the libahci_platform

Changes since v2:
        - modeled each PHY as a sub-node
        - cosmetic fixups

Changes since v1:
        - added a PHY driver, allowing to enable each port
          individually and removed the 'force-port-map' property
        - made the drivers a bit less magic :)
        - wrote a function to select and configure registers in the
          AHCI driver
        - removed BG2 / BG2CD nodes

Antoine T?nart (8):
  phy: add a driver for the Berlin SATA PHY
  Documentation: bindings: add the Berlin SATA PHY
  ata: libahci_platform: move port_map parameters into the AHCI
    structure
  ata: libahci: allow to use multiple PHYs
  ata: ahci_platform: add a generic AHCI compatible
  Documentation: bindings: document the sub-nodes AHCI bindings
  ARM: berlin: add the AHCI node for the BG2Q
  ARM: berlin: enable the eSATA interface on the BG2Q DMP

 .../devicetree/bindings/ata/ahci-platform.txt      |  37 +++
 .../devicetree/bindings/phy/berlin-sata-phy.txt    |  34 +++
 arch/arm/boot/dts/berlin2q-marvell-dmp.dts         |   8 +
 arch/arm/boot/dts/berlin2q.dtsi                    |  39 +++
 drivers/ata/ahci.h                                 |   9 +-
 drivers/ata/ahci_da850.c                           |   3 +-
 drivers/ata/ahci_imx.c                             |   3 +-
 drivers/ata/ahci_mvebu.c                           |   3 +-
 drivers/ata/ahci_platform.c                        |   5 +-
 drivers/ata/ahci_st.c                              |   2 +-
 drivers/ata/ahci_sunxi.c                           |   2 +-
 drivers/ata/ahci_xgene.c                           |   2 +-
 drivers/ata/libahci.c                              |  17 +-
 drivers/ata/libahci_platform.c                     | 187 ++++++++++----
 drivers/phy/Kconfig                                |   7 +
 drivers/phy/Makefile                               |   1 +
 drivers/phy/phy-berlin-sata.c                      | 284 +++++++++++++++++++++
 include/linux/ahci_platform.h                      |   4 +-
 18 files changed, 574 insertions(+), 73 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
 create mode 100644 drivers/phy/phy-berlin-sata.c

-- 
1.9.1

^ permalink raw reply


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