Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] ARM: omap: timers: reduce rating of gp_timer clocksource
From: Grygorii Strashko @ 2016-12-02 18:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161202164714.GB4705@atomide.com>



On 12/02/2016 10:47 AM, Tony Lindgren wrote:
> * Grygorii Strashko <grygorii.strashko@ti.com> [161129 08:43]:
>>
>>
>> On 11/24/2016 12:19 AM, Keerthy wrote:
>>> From: Grygorii Strashko <grygorii.strashko@ti.com>
>>>
>>> Now ARM Global timer (rating 300) will not be selected as clocksource,
>>> because it's initialized after OMAP GP Timer (rating 300) and
>>> Timekeeping core will not allow to replace clocksource with new one if
>>> both of them have the same rating.
>>>
>>> Reduce rating of OMAP GP Timer (300->290) when it's used as
>>> clocksource device - this will allow to select ARM Global timer (300)
>>> as clocksource when enabled.
>>>
>>> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
>>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>>
>> Unfortunately, this patch has dependency [1] and can't be used alone as
>> it will cause ARM Global timer to be selected as clocksource
>> always on am437x and this will kill cpuidle, because ARM Global timer
>> is not in always_on domain.
>>
>> The intention of enabling ARM Global timer is only for non-pm aware use
>> cases for RT-kernel latency improvement - where deep cpuidle states are not
>> enabled.
>
> Yeah we need to fix up things to be able to change the clocksource
> in addition to clockevent. However, currently only cpuidle_coupled
> knows when the whole system is idle, so quite a bit of work is
> needed to do that in a sane way.

Also sched_clock and timer_delay ;)


>
> What about the first patch in this series?
>

Fist one is ok. It was originally posted long time ago.

-- 
regards,
-grygorii

^ permalink raw reply

* [PATCH 3/8] rtc: add STM32 RTC driver
From: Mathieu Poirier @ 2016-12-02 18:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480687801-19525-5-git-send-email-amelie.delaunay@st.com>

On Fri, Dec 02, 2016 at 03:09:56PM +0100, Amelie Delaunay wrote:
> This patch adds support for the STM32 RTC.
> 
> Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
> ---
>  drivers/rtc/Kconfig     |  10 +
>  drivers/rtc/Makefile    |   1 +
>  drivers/rtc/rtc-stm32.c | 777 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 788 insertions(+)
>  create mode 100644 drivers/rtc/rtc-stm32.c
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index e859d14..dd8b218 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -1706,6 +1706,16 @@ config RTC_DRV_PIC32
>  	   This driver can also be built as a module. If so, the module
>  	   will be called rtc-pic32
>  
> +config RTC_DRV_STM32
> +	tristate "STM32 On-Chip RTC"
> +	depends on ARCH_STM32
> +	help
> +	   If you say yes here you get support for the STM32 On-Chip
> +	   Real Time Clock.
> +
> +	   This driver can also be built as a module, if so, the module
> +	   will be called "rtc-stm32".
> +
>  comment "HID Sensor RTC drivers"
>  
>  config RTC_DRV_HID_SENSOR_TIME
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index 1ac694a..87bd9cc 100644
> --- a/drivers/rtc/Makefile
> +++ b/drivers/rtc/Makefile
> @@ -144,6 +144,7 @@ obj-$(CONFIG_RTC_DRV_SNVS)	+= rtc-snvs.o
>  obj-$(CONFIG_RTC_DRV_SPEAR)	+= rtc-spear.o
>  obj-$(CONFIG_RTC_DRV_STARFIRE)	+= rtc-starfire.o
>  obj-$(CONFIG_RTC_DRV_STK17TA8)	+= rtc-stk17ta8.o
> +obj-$(CONFIG_RTC_DRV_STM32) 	+= rtc-stm32.o
>  obj-$(CONFIG_RTC_DRV_STMP)	+= rtc-stmp3xxx.o
>  obj-$(CONFIG_RTC_DRV_ST_LPC)	+= rtc-st-lpc.o
>  obj-$(CONFIG_RTC_DRV_SUN4V)	+= rtc-sun4v.o
> diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
> new file mode 100644
> index 0000000..9e710ff
> --- /dev/null
> +++ b/drivers/rtc/rtc-stm32.c
> @@ -0,0 +1,777 @@
> +/*
> + * Copyright (C) Amelie Delaunay 2015
> + * Author:  Amelie Delaunay <adelaunay.stm32@gmail.com>
> + * License terms:  GNU General Public License (GPL), version 2
> + */
> +
> +#include <linux/bcd.h>
> +#include <linux/clk.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/ioport.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/rtc.h>
> +#include <linux/spinlock.h>
> +
> +#define DRIVER_NAME "stm32_rtc"
> +
> +/* STM32 RTC registers */
> +#define STM32_RTC_TR		0x00
> +#define STM32_RTC_DR		0x04
> +#define STM32_RTC_CR		0x08
> +#define STM32_RTC_ISR		0x0C
> +#define STM32_RTC_PRER		0x10
> +#define STM32_RTC_ALRMAR	0x1C
> +#define STM32_RTC_WPR		0x24
> +
> +/* STM32_RTC_TR bit fields  */
> +#define STM32_RTC_TR_SEC_SHIFT		0
> +#define STM32_RTC_TR_SEC		GENMASK(6, 0)
> +#define STM32_RTC_TR_MIN_SHIFT		8
> +#define STM32_RTC_TR_MIN		GENMASK(14, 8)
> +#define STM32_RTC_TR_HOUR_SHIFT		16
> +#define STM32_RTC_TR_HOUR		GENMASK(21, 16)
> +
> +/* STM32_RTC_DR bit fields */
> +#define STM32_RTC_DR_DATE_SHIFT		0
> +#define STM32_RTC_DR_DATE		GENMASK(5, 0)
> +#define STM32_RTC_DR_MONTH_SHIFT	8
> +#define STM32_RTC_DR_MONTH		GENMASK(11, 8)
> +#define STM32_RTC_DR_WDAY_SHIFT		13
> +#define STM32_RTC_DR_WDAY		GENMASK(15, 13)
> +#define STM32_RTC_DR_YEAR_SHIFT		16
> +#define STM32_RTC_DR_YEAR		GENMASK(23, 16)
> +
> +/* STM32_RTC_CR bit fields */
> +#define STM32_RTC_CR_FMT		BIT(6)
> +#define STM32_RTC_CR_ALRAE		BIT(8)
> +#define STM32_RTC_CR_ALRAIE		BIT(12)
> +
> +/* STM32_RTC_ISR bit fields */
> +#define STM32_RTC_ISR_ALRAWF		BIT(0)
> +#define STM32_RTC_ISR_INITS		BIT(4)
> +#define STM32_RTC_ISR_RSF		BIT(5)
> +#define STM32_RTC_ISR_INITF		BIT(6)
> +#define STM32_RTC_ISR_INIT		BIT(7)
> +#define STM32_RTC_ISR_ALRAF		BIT(8)
> +
> +/* STM32_RTC_PRER bit fields */
> +#define STM32_RTC_PRER_PRED_S_SHIFT	0
> +#define STM32_RTC_PRER_PRED_S		GENMASK(14, 0)
> +#define STM32_RTC_PRER_PRED_A_SHIFT	16
> +#define STM32_RTC_PRER_PRED_A		GENMASK(22, 16)
> +
> +/* STM32_RTC_ALRMAR and STM32_RTC_ALRMBR bit fields */
> +#define STM32_RTC_ALRMXR_SEC_SHIFT	0
> +#define STM32_RTC_ALRMXR_SEC		GENMASK(6, 0)
> +#define STM32_RTC_ALRMXR_SEC_MASK	BIT(7)
> +#define STM32_RTC_ALRMXR_MIN_SHIFT	8
> +#define STM32_RTC_ALRMXR_MIN		GENMASK(14, 8)
> +#define STM32_RTC_ALRMXR_MIN_MASK	BIT(15)
> +#define STM32_RTC_ALRMXR_HOUR_SHIFT	16
> +#define STM32_RTC_ALRMXR_HOUR		GENMASK(21, 16)
> +#define STM32_RTC_ALRMXR_PM		BIT(22)
> +#define STM32_RTC_ALRMXR_HOUR_MASK	BIT(23)
> +#define STM32_RTC_ALRMXR_DATE_SHIFT	24
> +#define STM32_RTC_ALRMXR_DATE		GENMASK(29, 24)
> +#define STM32_RTC_ALRMXR_WDSEL		BIT(30)
> +#define STM32_RTC_ALRMXR_WDAY_SHIFT	24
> +#define STM32_RTC_ALRMXR_WDAY		GENMASK(27, 24)
> +#define STM32_RTC_ALRMXR_DATE_MASK	BIT(31)
> +
> +/* STM32_RTC_WPR key constants */
> +#define RTC_WPR_1ST_KEY			0xCA
> +#define RTC_WPR_2ND_KEY			0x53
> +#define RTC_WPR_WRONG_KEY		0xFF
> +
> +/*
> + * RTC registers are protected agains parasitic write access.
> + * PWR_CR_DBP bit must be set to enable write access to RTC registers.
> + */
> +/* STM32_PWR_CR */
> +#define PWR_CR				0x00
> +/* STM32_PWR_CR bit field */
> +#define PWR_CR_DBP			BIT(8)
> +
> +static struct regmap *dbp;
> +
> +struct stm32_rtc {
> +	struct rtc_device *rtc_dev;
> +	void __iomem *base;
> +	struct clk *pclk;
> +	struct clk *ck_rtc;
> +	unsigned int clksrc;
> +	spinlock_t lock; /* Protects registers accesses */
> +	int irq_alarm;
> +	struct regmap *pwrcr;
> +};

One more thing... What did you want to do with pclk, clksrc and pwrcr?  They
aren't used in the driver.  If this is for future enhancement I suggest you
introduce those when you submit the patches.

> +
> +static inline unsigned int stm32_rtc_readl(struct stm32_rtc *rtc,
> +					   unsigned int offset)
> +{
> +	return readl_relaxed(rtc->base + offset);
> +}
> +
> +static inline void stm32_rtc_writel(struct stm32_rtc *rtc,
> +				    unsigned int offset, unsigned int value)
> +{
> +	writel_relaxed(value, rtc->base + offset);
> +}
> +
> +static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
> +{
> +//	if (dbp)
> +//		regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
> +
> +	stm32_rtc_writel(rtc, STM32_RTC_WPR, RTC_WPR_1ST_KEY);
> +	stm32_rtc_writel(rtc, STM32_RTC_WPR, RTC_WPR_2ND_KEY);
> +}
> +
> +static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc)
> +{
> +	stm32_rtc_writel(rtc, STM32_RTC_WPR, RTC_WPR_WRONG_KEY);
> +
> +//	if (dbp)
> +//		regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
> +}
> +
> +static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
> +{
> +	unsigned int isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
> +
> +	if (!(isr & STM32_RTC_ISR_INITF)) {
> +		isr |= STM32_RTC_ISR_INIT;
> +		stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
> +
> +		return readl_relaxed_poll_timeout_atomic(
> +					rtc->base + STM32_RTC_ISR,
> +					isr, (isr & STM32_RTC_ISR_INITF),
> +					10, 100000);
> +	}
> +
> +	return 0;
> +}
> +
> +static void stm32_rtc_exit_init_mode(struct stm32_rtc *rtc)
> +{
> +	unsigned int isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
> +
> +	isr &= ~STM32_RTC_ISR_INIT;
> +	stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
> +}
> +
> +static int stm32_rtc_wait_sync(struct stm32_rtc *rtc)
> +{
> +	unsigned int isr;
> +
> +	isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
> +
> +	isr &= ~STM32_RTC_ISR_RSF;
> +	stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
> +
> +	/* Wait the registers to be synchronised */
> +	return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
> +						 isr,
> +						 (isr & STM32_RTC_ISR_RSF),
> +						 10, 100000);
> +}
> +
> +static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id)
> +{
> +	struct stm32_rtc *rtc = (struct stm32_rtc *)dev_id;
> +	unsigned long irqflags, events = 0;
> +	unsigned int isr, cr;
> +
> +	spin_lock_irqsave(&rtc->lock, irqflags);
> +
> +	isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
> +	cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
> +
> +	if ((isr & STM32_RTC_ISR_ALRAF) &&
> +	    (cr & STM32_RTC_CR_ALRAIE)) {
> +		/* Alarm A flag - Alarm interrupt */
> +		events |= RTC_IRQF | RTC_AF;
> +		isr &= ~STM32_RTC_ISR_ALRAF;
> +	}
> +
> +	/* Clear event irqflags, otherwise new events won't be received */
> +	stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
> +
> +	spin_unlock_irqrestore(&rtc->lock, irqflags);
> +
> +	if (events) {
> +		dev_info(&rtc->rtc_dev->dev, "Alarm occurred\n");
> +
> +		/* Pass event to the kernel */
> +		rtc_update_irq(rtc->rtc_dev, 1, events);
> +		return IRQ_HANDLED;
> +	} else {
> +		return IRQ_NONE;
> +	}
> +}
> +
> +/* Convert rtc_time structure from bin to bcd format */
> +static void tm2bcd(struct rtc_time *tm)
> +{
> +	tm->tm_sec = bin2bcd(tm->tm_sec);
> +	tm->tm_min = bin2bcd(tm->tm_min);
> +	tm->tm_hour = bin2bcd(tm->tm_hour);
> +
> +	tm->tm_mday = bin2bcd(tm->tm_mday);
> +	tm->tm_mon = bin2bcd(tm->tm_mon + 1);
> +	tm->tm_year = bin2bcd(tm->tm_year - 100);
> +	/*
> +	 * Number of days since Sunday
> +	 * - on kernel side, 0=Sunday...6=Saturday
> +	 * - on rtc side, 0=invalid,1=Monday...7=Sunday
> +	 */
> +	tm->tm_wday = (!tm->tm_wday) ? 7 : tm->tm_wday;
> +}
> +
> +/* Convert rtc_time structure from bcd to bin format */
> +static void bcd2tm(struct rtc_time *tm)
> +{
> +	tm->tm_sec = bcd2bin(tm->tm_sec);
> +	tm->tm_min = bcd2bin(tm->tm_min);
> +	tm->tm_hour = bcd2bin(tm->tm_hour);
> +
> +	tm->tm_mday = bcd2bin(tm->tm_mday);
> +	tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
> +	tm->tm_year = bcd2bin(tm->tm_year) + 100;
> +	/*
> +	 * Number of days since Sunday
> +	 * - on kernel side, 0=Sunday...6=Saturday
> +	 * - on rtc side, 0=invalid,1=Monday...7=Sunday
> +	 */
> +	tm->tm_wday %= 7;
> +}
> +
> +static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct stm32_rtc *rtc = dev_get_drvdata(dev);
> +	unsigned int tr, dr;
> +	unsigned long irqflags;
> +
> +	spin_lock_irqsave(&rtc->lock, irqflags);
> +
> +	/* Time and Date in BCD format */
> +	tr = stm32_rtc_readl(rtc, STM32_RTC_TR);
> +	dr = stm32_rtc_readl(rtc, STM32_RTC_DR);
> +
> +	spin_unlock_irqrestore(&rtc->lock, irqflags);
> +
> +	tm->tm_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
> +	tm->tm_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
> +	tm->tm_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT;
> +
> +	tm->tm_mday = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
> +	tm->tm_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
> +	tm->tm_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT;
> +	tm->tm_wday = (dr & STM32_RTC_DR_WDAY) >> STM32_RTC_DR_WDAY_SHIFT;
> +
> +	/* We don't report tm_yday and tm_isdst */
> +
> +	bcd2tm(tm);
> +
> +	if (rtc_valid_tm(tm) < 0) {
> +		dev_err(dev, "%s: rtc_time is not valid.\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct stm32_rtc *rtc = dev_get_drvdata(dev);
> +	unsigned int tr, dr;
> +	unsigned long irqflags;
> +	int ret = 0;
> +
> +	if (rtc_valid_tm(tm) < 0) {
> +		dev_err(dev, "%s: rtc_time is not valid.\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	tm2bcd(tm);
> +
> +	/* Time in BCD format */
> +	tr = ((tm->tm_sec << STM32_RTC_TR_SEC_SHIFT) & STM32_RTC_TR_SEC) |
> +	     ((tm->tm_min << STM32_RTC_TR_MIN_SHIFT) & STM32_RTC_TR_MIN) |
> +	     ((tm->tm_hour << STM32_RTC_TR_HOUR_SHIFT) & STM32_RTC_TR_HOUR);
> +
> +	/* Date in BCD format */
> +	dr = ((tm->tm_mday << STM32_RTC_DR_DATE_SHIFT) & STM32_RTC_DR_DATE) |
> +	     ((tm->tm_mon << STM32_RTC_DR_MONTH_SHIFT) & STM32_RTC_DR_MONTH) |
> +	     ((tm->tm_year << STM32_RTC_DR_YEAR_SHIFT) & STM32_RTC_DR_YEAR) |
> +	     ((tm->tm_wday << STM32_RTC_DR_WDAY_SHIFT) & STM32_RTC_DR_WDAY);
> +
> +	spin_lock_irqsave(&rtc->lock, irqflags);
> +
> +	stm32_rtc_wpr_unlock(rtc);
> +
> +	ret = stm32_rtc_enter_init_mode(rtc);
> +	if (ret) {
> +		dev_err(dev, "Can't enter in init mode. Set time aborted.\n");
> +		goto end;
> +	}
> +
> +	stm32_rtc_writel(rtc, STM32_RTC_TR, tr);
> +	stm32_rtc_writel(rtc, STM32_RTC_DR, dr);
> +
> +	stm32_rtc_exit_init_mode(rtc);
> +
> +	ret = stm32_rtc_wait_sync(rtc);
> +end:
> +	stm32_rtc_wpr_lock(rtc);
> +
> +	spin_unlock_irqrestore(&rtc->lock, irqflags);
> +
> +	return ret;
> +}
> +
> +static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +	struct stm32_rtc *rtc = dev_get_drvdata(dev);
> +	struct rtc_time *tm = &alrm->time;
> +	unsigned int alrmar, cr, isr;
> +	unsigned long irqflags;
> +
> +	spin_lock_irqsave(&rtc->lock, irqflags);
> +
> +	alrmar = stm32_rtc_readl(rtc, STM32_RTC_ALRMAR);
> +	cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
> +	isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
> +
> +	spin_unlock_irqrestore(&rtc->lock, irqflags);
> +
> +	if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) {
> +		/*
> +		 * Date/day don't care in Alarm comparison so alarm triggers
> +		 * every day
> +		 */
> +		tm->tm_mday = -1;
> +		tm->tm_wday = -1;
> +	} else {
> +		if (alrmar & STM32_RTC_ALRMXR_WDSEL) {
> +			/* Alarm is set to a day of week */
> +			tm->tm_mday = -1;
> +			tm->tm_wday = (alrmar & STM32_RTC_ALRMXR_WDAY) >>
> +				      STM32_RTC_ALRMXR_WDAY_SHIFT;
> +			tm->tm_wday %= 7;
> +		} else {
> +			/* Alarm is set to a day of month */
> +			tm->tm_wday = -1;
> +			tm->tm_mday = (alrmar & STM32_RTC_ALRMXR_DATE) >>
> +				       STM32_RTC_ALRMXR_DATE_SHIFT;
> +		}
> +	}
> +
> +	if (alrmar & STM32_RTC_ALRMXR_HOUR_MASK) {
> +		/* Hours don't care in Alarm comparison */
> +		tm->tm_hour = -1;
> +	} else {
> +		tm->tm_hour = (alrmar & STM32_RTC_ALRMXR_HOUR) >>
> +			       STM32_RTC_ALRMXR_HOUR_SHIFT;
> +		if (alrmar & STM32_RTC_ALRMXR_PM)
> +			tm->tm_hour += 12;
> +	}
> +
> +	if (alrmar & STM32_RTC_ALRMXR_MIN_MASK) {
> +		/* Minutes don't care in Alarm comparison */
> +		tm->tm_min = -1;
> +	} else {
> +		tm->tm_min = (alrmar & STM32_RTC_ALRMXR_MIN) >>
> +			      STM32_RTC_ALRMXR_MIN_SHIFT;
> +	}
> +
> +	if (alrmar & STM32_RTC_ALRMXR_SEC_MASK) {
> +		/* Seconds don't care in Alarm comparison */
> +		tm->tm_sec = -1;
> +	} else {
> +		tm->tm_sec = (alrmar & STM32_RTC_ALRMXR_SEC) >>
> +			      STM32_RTC_ALRMXR_SEC_SHIFT;
> +	}
> +
> +	bcd2tm(tm);
> +
> +	alrm->enabled = (cr & STM32_RTC_CR_ALRAE) ? 1 : 0;
> +	alrm->pending = (isr & STM32_RTC_ISR_ALRAF) ? 1 : 0;
> +
> +	return 0;
> +}
> +
> +static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
> +{
> +	struct stm32_rtc *rtc = dev_get_drvdata(dev);
> +	unsigned long irqflags;
> +	unsigned int isr, cr;
> +
> +	cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
> +
> +	spin_lock_irqsave(&rtc->lock, irqflags);
> +
> +	stm32_rtc_wpr_unlock(rtc);
> +
> +	/* We expose Alarm A to the kernel */
> +	if (enabled)
> +		cr |= (STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
> +	else
> +		cr &= ~(STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
> +	stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
> +
> +	/* Clear event irqflags, otherwise new events won't be received */
> +	isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
> +	isr &= ~STM32_RTC_ISR_ALRAF;
> +	stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
> +
> +	stm32_rtc_wpr_lock(rtc);
> +
> +	spin_unlock_irqrestore(&rtc->lock, irqflags);
> +
> +	return 0;
> +}
> +
> +static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +	struct stm32_rtc *rtc = dev_get_drvdata(dev);
> +	struct rtc_time *tm = &alrm->time;
> +	unsigned long irqflags;
> +	unsigned int cr, isr, alrmar;
> +	int ret = 0;
> +
> +	if (rtc_valid_tm(tm)) {
> +		dev_err(dev, "Alarm time not valid.\n");
> +		return -EINVAL;
> +	}
> +
> +	tm2bcd(tm);
> +
> +	spin_lock_irqsave(&rtc->lock, irqflags);
> +
> +	stm32_rtc_wpr_unlock(rtc);
> +
> +	/* Disable Alarm */
> +	cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
> +	cr &= ~STM32_RTC_CR_ALRAE;
> +	stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
> +
> +	/* Poll Alarm write flag to be sure that Alarm update is allowed */
> +	ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
> +						isr,
> +						(isr & STM32_RTC_ISR_ALRAWF),
> +						10, 100);
> +
> +	if (ret) {
> +		dev_err(dev, "Alarm update not allowed\n");
> +		goto end;
> +	}
> +
> +	alrmar = 0;
> +
> +	if (tm->tm_mday < 0 && tm->tm_wday < 0) {
> +		/*
> +		 * Date/day don't care in Alarm comparison so alarm triggers
> +		 * every day
> +		 */
> +		alrmar |= STM32_RTC_ALRMXR_DATE_MASK;
> +	} else {
> +		if (tm->tm_mday > 0) {
> +			/* Date is selected (ignoring wday) */
> +			alrmar |= (tm->tm_mday << STM32_RTC_ALRMXR_DATE_SHIFT) &
> +				  STM32_RTC_ALRMXR_DATE;
> +		} else {
> +			/* Day of week is selected */
> +			int wday = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
> +
> +			alrmar |= STM32_RTC_ALRMXR_WDSEL;
> +			alrmar |= (wday << STM32_RTC_ALRMXR_WDAY_SHIFT) &
> +				  STM32_RTC_ALRMXR_WDAY;
> +		}
> +	}
> +
> +	if (tm->tm_hour < 0) {
> +		/* Hours don't care in Alarm comparison */
> +		alrmar |= STM32_RTC_ALRMXR_HOUR_MASK;
> +	} else {
> +		/* 24-hour format */
> +		alrmar &= ~STM32_RTC_ALRMXR_PM;
> +		alrmar |= (tm->tm_hour << STM32_RTC_ALRMXR_HOUR_SHIFT) &
> +			  STM32_RTC_ALRMXR_HOUR;
> +	}
> +
> +	if (tm->tm_min < 0) {
> +		/* Minutes don't care in Alarm comparison */
> +		alrmar |= STM32_RTC_ALRMXR_MIN_MASK;
> +	} else {
> +		alrmar |= (tm->tm_min << STM32_RTC_ALRMXR_MIN_SHIFT) &
> +			  STM32_RTC_ALRMXR_MIN;
> +	}
> +
> +	if (tm->tm_sec < 0) {
> +		/* Seconds don't care in Alarm comparison */
> +		alrmar |= STM32_RTC_ALRMXR_SEC_MASK;
> +	} else {
> +		alrmar |= (tm->tm_sec << STM32_RTC_ALRMXR_SEC_SHIFT) &
> +			  STM32_RTC_ALRMXR_SEC;
> +	}
> +
> +	/* Write to Alarm register */
> +	stm32_rtc_writel(rtc, STM32_RTC_ALRMAR, alrmar);
> +
> +	if (alrm->enabled)
> +		stm32_rtc_alarm_irq_enable(dev, 1);
> +	else
> +		stm32_rtc_alarm_irq_enable(dev, 0);
> +
> +end:
> +	stm32_rtc_wpr_lock(rtc);
> +
> +	spin_unlock_irqrestore(&rtc->lock, irqflags);
> +
> +	return ret;
> +}
> +
> +static const struct rtc_class_ops stm32_rtc_ops = {
> +	.read_time	= stm32_rtc_read_time,
> +	.set_time	= stm32_rtc_set_time,
> +	.read_alarm	= stm32_rtc_read_alarm,
> +	.set_alarm	= stm32_rtc_set_alarm,
> +	.alarm_irq_enable = stm32_rtc_alarm_irq_enable,
> +};
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id stm32_rtc_of_match[] = {
> +	{ .compatible = "st,stm32-rtc" },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
> +#endif
> +
> +static int stm32_rtc_init(struct platform_device *pdev,
> +			  struct stm32_rtc *rtc)
> +{
> +	unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
> +	unsigned int rate;
> +	unsigned long irqflags;
> +	int ret = 0;
> +
> +	rate = clk_get_rate(rtc->ck_rtc);
> +
> +	/* Find prediv_a and prediv_s to obtain the 1Hz calendar clock */
> +	pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
> +	pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT;
> +
> +	for (pred_a = pred_a_max; pred_a >= 0; pred_a--) {
> +		pred_s = (rate / (pred_a + 1)) - 1;
> +
> +		if (((pred_s + 1) * (pred_a + 1)) == rate)
> +			break;
> +	}
> +
> +	/*
> +	 * Can't find a 1Hz, so give priority to RTC power consumption
> +	 * by choosing the higher possible value for prediv_a
> +	 */
> +	if ((pred_s > pred_s_max) || (pred_a > pred_a_max)) {
> +		pred_a = pred_a_max;
> +		pred_s = (rate / (pred_a + 1)) - 1;
> +
> +		dev_warn(&pdev->dev, "ck_rtc is %s\n",
> +			 (rate - ((pred_a + 1) * (pred_s + 1)) < 0) ?
> +			 "fast" : "slow");
> +	}
> +
> +	spin_lock_irqsave(&rtc->lock, irqflags);
> +
> +	stm32_rtc_wpr_unlock(rtc);
> +
> +	ret = stm32_rtc_enter_init_mode(rtc);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"Can't enter in init mode. Prescaler config failed.\n");
> +		goto end;
> +	}
> +
> +	prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S;
> +	stm32_rtc_writel(rtc, STM32_RTC_PRER, prer);
> +	prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
> +	stm32_rtc_writel(rtc, STM32_RTC_PRER, prer);
> +
> +	/* Force 24h time format */
> +	cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
> +	cr &= ~STM32_RTC_CR_FMT;
> +	stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
> +
> +	stm32_rtc_exit_init_mode(rtc);
> +
> +	ret = stm32_rtc_wait_sync(rtc);
> +
> +	if (stm32_rtc_readl(rtc, STM32_RTC_ISR) & STM32_RTC_ISR_INITS)
> +		dev_warn(&pdev->dev, "Date/Time must be initialized\n");
> +end:
> +	stm32_rtc_wpr_lock(rtc);
> +
> +	spin_unlock_irqrestore(&rtc->lock, irqflags);
> +
> +	return ret;
> +}
> +
> +static int stm32_rtc_probe(struct platform_device *pdev)
> +{
> +	struct stm32_rtc *rtc;
> +	struct resource *res;
> +	int ret;
> +
> +	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
> +	if (!rtc)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	rtc->base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(rtc->base))
> +		return PTR_ERR(rtc->base);
> +
> +	dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "st,syscfg");
> +	if (IS_ERR(dbp)) {
> +		dev_err(&pdev->dev, "no st,syscfg\n");
> +		return PTR_ERR(dbp);
> +	}
> +
> +	spin_lock_init(&rtc->lock);
> +
> +	rtc->ck_rtc = devm_clk_get(&pdev->dev, "ck_rtc");
> +	if (IS_ERR(rtc->ck_rtc)) {
> +		dev_err(&pdev->dev, "no ck_rtc clock");
> +		return PTR_ERR(rtc->ck_rtc);
> +	}
> +
> +	ret = clk_prepare_enable(rtc->ck_rtc);
> +	if (ret)
> +		return ret;
> +
> +	if (dbp)
> +		regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
> +
> +	ret = stm32_rtc_init(pdev, rtc);
> +	if (ret)
> +		goto err;
> +
> +	rtc->irq_alarm = platform_get_irq_byname(pdev, "alarm");
> +	if (rtc->irq_alarm <= 0) {
> +		dev_err(&pdev->dev, "no alarm irq\n");
> +		ret = -ENOENT;
> +		goto err;
> +	}
> +
> +	platform_set_drvdata(pdev, rtc);
> +
> +	device_init_wakeup(&pdev->dev, true);
> +
> +	rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
> +			&stm32_rtc_ops, THIS_MODULE);
> +	if (IS_ERR(rtc->rtc_dev)) {
> +		ret = PTR_ERR(rtc->rtc_dev);
> +		dev_err(&pdev->dev, "rtc device registration failed, err=%d\n",
> +			ret);
> +		goto err;
> +	}
> +
> +	/* Handle RTC alarm interrupts */
> +	ret = devm_request_irq(&pdev->dev, rtc->irq_alarm,
> +			       stm32_rtc_alarm_irq, IRQF_TRIGGER_RISING,
> +			       dev_name(&rtc->rtc_dev->dev), rtc);
> +	if (ret) {
> +		dev_err(&pdev->dev, "IRQ%d (alarm interrupt) already claimed\n",
> +			rtc->irq_alarm);
> +		goto err;
> +	}
> +
> +	return 0;
> +err:
> +	clk_disable_unprepare(rtc->ck_rtc);
> +
> +	if (dbp)
> +		regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
> +
> +	device_init_wakeup(&pdev->dev, false);
> +
> +	return ret;
> +}
> +
> +static int __exit stm32_rtc_remove(struct platform_device *pdev)
> +{
> +	struct stm32_rtc *rtc = platform_get_drvdata(pdev);
> +	unsigned int cr;
> +
> +	/* Disable interrupts */
> +	stm32_rtc_wpr_unlock(rtc);
> +	cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
> +	cr &= ~STM32_RTC_CR_ALRAIE;
> +	stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
> +	stm32_rtc_wpr_lock(rtc);
> +
> +	clk_disable_unprepare(rtc->ck_rtc);
> +
> +	/* Enable backup domain write protection */
> +	if (dbp)
> +		regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
> +
> +	device_init_wakeup(&pdev->dev, false);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int stm32_rtc_suspend(struct device *dev)
> +{
> +	struct stm32_rtc *rtc = dev_get_drvdata(dev);
> +
> +	if (device_may_wakeup(dev))
> +		return enable_irq_wake(rtc->irq_alarm);
> +
> +	return 0;
> +}
> +
> +static int stm32_rtc_resume(struct device *dev)
> +{
> +	struct stm32_rtc *rtc = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	ret = stm32_rtc_wait_sync(rtc);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (device_may_wakeup(dev))
> +		return disable_irq_wake(rtc->irq_alarm);
> +
> +	return ret;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(stm32_rtc_pm_ops,
> +			 stm32_rtc_suspend, stm32_rtc_resume);
> +
> +static struct platform_driver stm32_rtc_driver = {
> +	.probe		= stm32_rtc_probe,
> +	.remove		= stm32_rtc_remove,
> +	.driver		= {
> +		.name	= DRIVER_NAME,
> +		.pm	= &stm32_rtc_pm_ops,
> +		.of_match_table = stm32_rtc_of_match,
> +	},
> +};
> +
> +module_platform_driver(stm32_rtc_driver);
> +
> +MODULE_ALIAS("platform:" DRIVER_NAME);
> +MODULE_AUTHOR("Amelie Delaunay <amelie.delaunay@st.com>");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 Real Time Clock driver");
> +MODULE_LICENSE("GPL v2");
> -- 
> 1.9.1
> 

^ permalink raw reply

* [RFC PATCH 00/29] arm64: Scalable Vector Extension core support
From: Dave Martin @ 2016-12-02 18:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.20.1612021648580.16956@digraph.polyomino.org.uk>

On Fri, Dec 02, 2016 at 04:59:27PM +0000, Joseph Myers wrote:
> On Fri, 2 Dec 2016, Florian Weimer wrote:
> 
> > > However, it would be necessary to prevent GCC from moving any code
> > > across these statements -- in particular, SVE code that access VL-
> > > dependent data spilled on the stack is liable to go wrong if reordered
> > > with the above.  So the sequence would need to go in an external
> > > function (or a single asm...)
> > 
> > I would talk to GCC folks?we have similar issues with changing the FPU
> > rounding mode, I assume.
> 
> In general, GCC doesn't track the implicit uses of thread-local state 
> involved in floating-point exceptions and rounding modes, and so doesn't 
> avoid moving code across manipulations of such state; there are various 
> open bugs in this area (though many of the open bugs are for local rather 
> than global issues with code generation or local optimizations not 
> respecting exceptions and rounding modes, which are easier to fix).  Hence 
> glibc using various macros such as math_opt_barrier and math_force_eval 
> which use asms to prevent such motion.

Presumably the C language specs specify that fenv manipulations cannot
be reordered with respect to evaluation or floating-point expressions?
Sanity would seem to require this, though I've not dug into the specs
myself yet.

This doesn't get us off the hook for prctl() -- the C specs can only
define constraints on reordering for things that appear in the C spec.
prctl() is just an external function call in this context, and doesn't
enjoy the same guarantees.

> I'm not familiar enough with the optimizers to judge the right way to 
> address such issues with implicit use of thread-local state.  And I 
> haven't thought much yet about how to implement TS 18661-1 constant 
> rounding modes, which would involve the compiler implicitly inserting 
> rounding modes changes, though I think it would be fairly straightforward 
> given underlying support for avoiding inappropriate code motion.

My concern is that the compiler has no clue about what code motions are
appropriate or not with respect to a system call, beyond what applies
to a system call in general (i.e., asm volatile ( ::: "memory" ) for
GCC).

?

Cheers
---Dave

^ permalink raw reply

* [PATCH 2/2] ARM: omap: timers: reduce rating of gp_timer clocksource
From: Tony Lindgren @ 2016-12-02 18:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <14878d85-1b08-5df1-4e67-6f982ba72019@ti.com>

* Grygorii Strashko <grygorii.strashko@ti.com> [161202 10:02]:
> 
> 
> On 12/02/2016 10:47 AM, Tony Lindgren wrote:
> > * Grygorii Strashko <grygorii.strashko@ti.com> [161129 08:43]:
> > > 
> > > 
> > > On 11/24/2016 12:19 AM, Keerthy wrote:
> > > > From: Grygorii Strashko <grygorii.strashko@ti.com>
> > > > 
> > > > Now ARM Global timer (rating 300) will not be selected as clocksource,
> > > > because it's initialized after OMAP GP Timer (rating 300) and
> > > > Timekeeping core will not allow to replace clocksource with new one if
> > > > both of them have the same rating.
> > > > 
> > > > Reduce rating of OMAP GP Timer (300->290) when it's used as
> > > > clocksource device - this will allow to select ARM Global timer (300)
> > > > as clocksource when enabled.
> > > > 
> > > > Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> > > > Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> > > > Signed-off-by: Keerthy <j-keerthy@ti.com>
> > > 
> > > Unfortunately, this patch has dependency [1] and can't be used alone as
> > > it will cause ARM Global timer to be selected as clocksource
> > > always on am437x and this will kill cpuidle, because ARM Global timer
> > > is not in always_on domain.
> > > 
> > > The intention of enabling ARM Global timer is only for non-pm aware use
> > > cases for RT-kernel latency improvement - where deep cpuidle states are not
> > > enabled.
> > 
> > Yeah we need to fix up things to be able to change the clocksource
> > in addition to clockevent. However, currently only cpuidle_coupled
> > knows when the whole system is idle, so quite a bit of work is
> > needed to do that in a sane way.
> 
> Also sched_clock and timer_delay ;)

Yeah sched_clock would need something to save and restore it..
Not nice :)

> > What about the first patch in this series?
> > 
> 
> Fist one is ok. It was originally posted long time ago.

OK so can you please resend that one more time with proper
Fixes tag on it?

Regards,

Tony

^ permalink raw reply

* [PATCH net-next v2] net: thunderx: Fix transmit queue timeout issue
From: David Miller @ 2016-12-02 18:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480596868-17693-1-git-send-email-sunil.kovvuri@gmail.com>

From: sunil.kovvuri@gmail.com
Date: Thu,  1 Dec 2016 18:24:28 +0530

> From: Sunil Goutham <sgoutham@cavium.com>
> 
> Transmit queue timeout issue is seen in two cases
> - Due to a race condition btw setting stop_queue at xmit()
>   and checking for stopped_queue in NAPI poll routine, at times
>   transmission from a SQ comes to a halt. This is fixed
>   by using barriers and also added a check for SQ free descriptors,
>   incase SQ is stopped and there are only CQE_RX i.e no CQE_TX.
> - Contrary to an assumption, a HW errata where HW doesn't stop transmission
>   even though there are not enough CQEs available for a CQE_TX is
>   not fixed in T88 pass 2.x. This results in a Qset error with
>   'CQ_WR_FULL' stalling transmission. This is fixed by adjusting
>   RXQ's  RED levels for CQ level such that there is always enough
>   space left for CQE_TXs.
> 
> Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
> ---
> v2: As suggested by David, replaced netif_tx_start_queue with 
>     netif_tx_wake_queue.

Applied, thanks.

^ permalink raw reply

* [PATCH 1/3] Documentation: dt: Add TI SCI clock driver
From: Rob Herring @ 2016-12-02 18:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <8579b123-f214-22f1-0236-e5b98ab51597@ti.com>

On Fri, Dec 2, 2016 at 2:19 AM, Tero Kristo <t-kristo@ti.com> wrote:
> On 21/11/16 10:14, Tero Kristo wrote:
>>
>> On 18/11/16 19:20, Rob Herring wrote:
>>>
>>> On Mon, Oct 31, 2016 at 7:50 AM, Tero Kristo <t-kristo@ti.com> wrote:
>>>>
>>>> On 30/10/16 22:41, Rob Herring wrote:
>>>>>
>>>>>
>>>>> On Fri, Oct 21, 2016 at 03:45:59PM +0300, Tero Kristo wrote:
>>>>>>
>>>>>>
>>>>>> Add a clock implementation, TI SCI clock, that will hook to the common
>>>>>> clock framework, and allow each clock to be controlled via TI SCI
>>>>>> protocol.
>>>>>>
>>>>>> Signed-off-by: Tero Kristo <t-kristo@ti.com>
>>>>>> ---
>>>>>>  .../devicetree/bindings/clock/ti,sci-clk.txt       | 37
>>>>>> ++++++++++++++++++++++
>>>>>>  MAINTAINERS                                        |  1 +
>>>>>>  2 files changed, 38 insertions(+)
>>>>>>  create mode 100644
>>>>>> Documentation/devicetree/bindings/clock/ti,sci-clk.txt
>>>>>>
>>>>>> diff --git a/Documentation/devicetree/bindings/clock/ti,sci-clk.txt
>>>>>> b/Documentation/devicetree/bindings/clock/ti,sci-clk.txt
>>>>>> new file mode 100644
>>>>>> index 0000000..bfc3ca4
>>>>>> --- /dev/null
>>>>>> +++ b/Documentation/devicetree/bindings/clock/ti,sci-clk.txt
>>>>>> @@ -0,0 +1,37 @@
>>>>>> +Texas Instruments TI-SCI Clocks
>>>>>> +===============================
>>>>>> +
>>>>>> +All clocks on Texas Instruments' SoCs that contain a System
>>>>>> Controller,
>>>>>> +are only controlled by this entity. Communication between a host
>>>>>> processor
>>>>>> +running an OS and the System Controller happens through a protocol
>>>>>> known
>>>>>> +as TI-SCI[1]. This clock implementation plugs into the common clock
>>>>>> +framework and makes use of the TI-SCI protocol on clock API requests.
>>>>>> +
>>>>>> +[1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
>>>>>> +
>>>>>> +Required properties:
>>>>>> +-------------------
>>>>>> +- compatible: Must be "ti,k2g-sci-clk"
>>>>>> +- #clock-cells: Shall be 2.
>>>>>> +  In clock consumers, this cell represents the device ID and clock ID
>>>>>> +  exposed by the PM firmware. The assignments can be found in the
>>>>>> header
>>>>>> +  files <dt-bindings/genpd/<soc>.h> (which covers the device IDs) and
>>>>>> +  <dt-bindings/clock/<soc>.h> (which covers the clock IDs), where
>>>>>> <soc>
>>>>>> +  is the SoC involved, for example 'k2g'.
>>>>>> +
>>>>>> +Examples:
>>>>>> +--------
>>>>>> +
>>>>>> +pmmc: pmmc {
>>>>>> +       compatible = "ti,k2g-sci";
>>>>>> +
>>>>>> +       k2g_clks: k2g_clks {
>>>>>
>>>>>
>>>>>
>>>>> Use "clocks" for node name instead.
>>>>>
>>>>>> +               compatible = "ti,k2g-sci-clk";
>>>>>
>>>>>
>>>>>
>>>>> I'm starting to think all these child nodes for SCI are pointless. Is
>>>>> there any reason why the parent node can't be the clock provider (along
>>>>> with all the other providers it acks as)?
>>>>
>>>>
>>>>
>>>> I believe the only reason to keep them separate is to have kernel
>>>> side of
>>>> things modular. If we have separate nodes, the drivers can be probed
>>>> separately.
>>>>
>>>> If not, we need to build one huge blob with all the features in it,
>>>> so the
>>>> main driver can probe everything in one go, with annoying back-and-forth
>>>> callbacks in place (assuming we still want to keep stuff somehow
>>>> modular.)
>>>
>>>
>>> Since when is DT the only way to create a device? The main driver can
>>> create devices for all the sub-functions like clocks. This is the same
>>> as MFDs which have been done both ways.
>>
>>
>> Yes obviously this can be done, my main point was that it will require
>> building some sort of infra within the driver to handle this. With
>> separate nodes, none of this is going to be needed. Also, we will lose
>> any kind of configurability via DT if we don't have separate nodes; now
>> we can select the available clocks / genpds via the compatible string of
>> the clocks/genpd nodes themselves (this isn't clearly evident as of now
>> as we only support a grand total of one device, which is k2g-evm.)
>> Otherwise we need to probe against the main node and add a separate
>> compatible string for every device, and carry this information to the
>> sibling devices also somehow. It is just so much simpler if we can just
>> keep separate nodes for them.
>>
>> Also, plenty of things are doing this kind of stuff already in
>> DT/kernel, having a parent node in place and sub-functions added
>> separately for ease of use, with apparently no visible point for having
>> the nodes within the DT.
>
>
> Rob, any response on this one? I see you have acked the reset part of the
> bindings which is doing pretty much the same thing as the clock part is
> doing here, namely adding child node under the main SCI node. Is it okay to
> do this same for other parts of the TI SCI?

Yes. It would be silly to allow for one and not others...

Rob

^ permalink raw reply

* [PATCH v6 net-next 0/7] Support Armada 37xx SoC (ARMv8 64-bits) in mvneta driver
From: David Miller @ 2016-12-02 18:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.dd374b7aaa358be0211d7ead81129a399fa692f4.1480611779.git-series.gregory.clement@free-electrons.com>

From: Gregory CLEMENT <gregory.clement@free-electrons.com>
Date: Thu,  1 Dec 2016 18:03:03 +0100

> The Armada 37xx is a new ARMv8 SoC from Marvell using same network
> controller as the older Armada 370/38x/XP SoCs. This series adapts the
> driver in order to be able to use it on this new SoC. The main changes
> are:
> 
> - 64-bits support: the first patches allow using the driver on a 64-bit
>   architecture.
> 
> - MBUS support: the mbus configuration is different on Armada 37xx
>   from the older SoCs.
> 
> - per cpu interrupt: Armada 37xx do not support per cpu interrupt for
>   the NETA IP, the non-per-CPU behavior was added back.
> 
> The first patch is an optimization in the rx path in swbm mode.
> The second patch remove unnecessary allocation for HWBM.
> The first item is solved by patches 4 and 5.
> The 2 last items are solved by patch 6.
> In patch 7 the dt support is added.
> 
> Beside Armada 37xx, this series have been again tested on Armada XP
> and Armada 38x (with Hardware Buffer Management and with Software
> Buffer Management).
 ...

Series applied, thanks.

^ permalink raw reply

* [PATCH v11 0/7] Enable PMUs in ACPI systems
From: Jeremy Linton @ 2016-12-02 18:55 UTC (permalink / raw)
  To: linux-arm-kernel

This patch expands and reworks the patches published by Mark Salter
in order to clean up a few of the previous review comments, as well as
add support for newer CPUs and big/little configurations.

v11:
- Add is_smp() check to read_specific_cpuid() for arch/arm. Update
  c_show() and various routines in arm_pmu_acpi() to use the macro.
- Moved the duplicate "generic" pmu detection code into its own
  patch and hoist it into arm_pmu_device_probe() so it works
  for DT based systems as well.

v10:
- Rebase to 4.9
- Rework the arm_perf_start_cpu changes to support the 4.9 hotplug
  changes.
- Remove the call to acpi_register_gsi() from the cpu online code path.
  Instead the GSI's are registered during the initcall. This changes
  the error handling a bit because we now try to clean up the
  previously registered GSIs in a couple important places. This
  was also a result of the rebase.
- Dropped the MIDR partnumber usage, its no longer necessary to
  differentiate by only the partnum, so this helps to clarify the code
  a bit. 
- Shuffle some code around and rename a few variables.
- Added a few comments to hopefully clarify some questions people have
  previously had about unused MADT entries, skipping processing cores
  with MIDR=0, etc.

v9:
- Add/cleanup an additional hotplug patch I've had sitting around. This
  patch brings the ACPI PMU mostly on par with the DT functionality with
  respect to having CPUs offline during boot. This should help clarify
  some of the code structuring.
- Cleanup the list of PMU types early if we fail to allocate memory for an
  additional pmu type.

v8:
- Rebase to 4.8rc4
- Assorted minor comment/hunk placement/etc tweaks per Punit Agrawal

v7:
- Rebase to 4.8rc3
- Remove cpu affinity sysfs entry. While providing a CPU mask for
  ARMv8 PMU's is really helpful in big/little environments, reworking
  the PMU code to support the cpumask attribute for !arm64 PMUs is out
  of the scope of this patch set.
- Fix CPU miscount problem where an alloc failure followed by successfully
  allocating the structure can result in under counting the CPUs associated
  with the PMU. This bug was created in v6 with the conversion to a linked
  list.
-  Remove initial platform device creation code by Mark Salter, and re-squash
   multiple platform device creation code together with helper routines.
   Other minor tweakage.

v6:
- Added cpu affinity sysfs entry
- Converted pmu_types array, to linked list
- Restrict use of the armv8_pmu_probe_table to ACPI systems
- Rename MADT parsing routines in smp.c
- Convert sysfs PMU name to use index rather than partnum
- Remove pr_devel statements
- Other Minor cleanups
- Add Partial Ack-by Will Deacon

v5:
- Remove list of CPU types for ACPI systems. We now match a generic
  event list, and use the PMCIED[01] to select events which exist on
  the given PMU. This avoids the need to update the kernel every time
  a new CPU is released.
- Update the maintainers list to include the new file.

v4:
- Correct build issues with ARM (!ARM64) kernels.
- Add ThunderX to list of PMU types.

v3:
- Enable ARM performance monitoring units on ACPI/arm64 machines.

Jeremy Linton (6):
  arm64: Rename the common MADT parse routine
  arm: arm64: Add routine to determine cpuid of other cpus
  arm: arm64: pmu: Assign platform PMU CPU affinity
  arm64: pmu: Detect multiple generic PMUs and append counter
  arm64: pmu: Detect and enable multiple PMUs in an ACPI system
  arm: pmu: Add PMU definitions for cores not initially online

Mark Salter (1):
  arm64: pmu: Cache PMU interrupt numbers from MADT parse

 arch/arm/include/asm/cputype.h   |   4 +
 arch/arm/kernel/setup.c          |   2 +-
 arch/arm64/include/asm/cputype.h |   3 +
 arch/arm64/kernel/perf_event.c   |   2 +-
 arch/arm64/kernel/smp.c          |  18 ++-
 drivers/perf/Kconfig             |   4 +
 drivers/perf/Makefile            |   1 +
 drivers/perf/arm_pmu.c           | 107 ++++++++++++++--
 drivers/perf/arm_pmu_acpi.c      | 271 +++++++++++++++++++++++++++++++++++++++
 include/linux/perf/arm_pmu.h     |  12 ++
 10 files changed, 404 insertions(+), 20 deletions(-)
 create mode 100644 drivers/perf/arm_pmu_acpi.c

-- 
2.5.5

^ permalink raw reply

* [PATCH v11 1/7] arm64: Rename the common MADT parse routine
From: Jeremy Linton @ 2016-12-02 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480704961-6910-1-git-send-email-jeremy.linton@arm.com>

The MADT parser in smp.c is now being used to parse
out NUMA, PMU and ACPI parking protocol information as
well as the GIC information for which it was originally
created. Rename it to avoid a misleading name.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/kernel/smp.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 8507703..f3f1c90 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -511,13 +511,14 @@ static unsigned int cpu_count = 1;
 
 #ifdef CONFIG_ACPI
 /*
- * acpi_map_gic_cpu_interface - parse processor MADT entry
+ * acpi_verify_and_map_madt - parse processor MADT entry
  *
  * Carry out sanity checks on MADT processor entry and initialize
- * cpu_logical_map on success
+ * cpu_logical_map, the ACPI parking protocol, NUMA mapping
+ * and the PMU interrupts on success
  */
 static void __init
-acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
+acpi_verify_and_map_madt(struct acpi_madt_generic_interrupt *processor)
 {
 	u64 hwid = processor->arm_mpidr;
 
@@ -571,7 +572,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
 }
 
 static int __init
-acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,
+acpi_parse_madt_common(struct acpi_subtable_header *header,
 			     const unsigned long end)
 {
 	struct acpi_madt_generic_interrupt *processor;
@@ -582,7 +583,7 @@ acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,
 
 	acpi_table_print_madt_entry(header);
 
-	acpi_map_gic_cpu_interface(processor);
+	acpi_verify_and_map_madt(processor);
 
 	return 0;
 }
@@ -666,7 +667,7 @@ void __init smp_init_cpus(void)
 		 * we need for SMP init
 		 */
 		acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
-				      acpi_parse_gic_cpu_interface, 0);
+				      acpi_parse_madt_common, 0);
 
 	if (cpu_count > nr_cpu_ids)
 		pr_warn("Number of cores (%d) exceeds configured maximum of %d - clipping\n",
-- 
2.5.5

^ permalink raw reply related

* [PATCH v11 2/7] arm: arm64: Add routine to determine cpuid of other cpus
From: Jeremy Linton @ 2016-12-02 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480704961-6910-1-git-send-email-jeremy.linton@arm.com>

It is helpful if we can read the cpuid/midr of other CPUs
in the system independent of arm/arm64.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm/include/asm/cputype.h   | 4 ++++
 arch/arm/kernel/setup.c          | 2 +-
 arch/arm64/include/asm/cputype.h | 3 +++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 522b5fe..1e87d06 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -235,6 +235,10 @@ static inline unsigned int __attribute_const__ read_cpuid_mpidr(void)
 #define cpu_is_sa1100() (read_cpuid_part() == ARM_CPU_PART_SA1100)
 #define cpu_is_sa1110() (read_cpuid_part() == ARM_CPU_PART_SA1110)
 
+#define read_specific_cpuid(cpu_num) (is_smp() ? \
+				      per_cpu_ptr(&cpu_data, cpu_num)->cpuid \
+				      : read_cpuid_id())
+
 /*
  * 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/kernel/setup.c b/arch/arm/kernel/setup.c
index 34e3f3c..d443c97 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -1217,7 +1217,7 @@ static int c_show(struct seq_file *m, void *v)
 		 * "processor".  Give glibc what it expects.
 		 */
 		seq_printf(m, "processor\t: %d\n", i);
-		cpuid = is_smp() ? per_cpu(cpu_data, i).cpuid : read_cpuid_id();
+		cpuid = read_specific_cpuid(i);
 		seq_printf(m, "model name\t: %s rev %d (%s)\n",
 			   cpu_name, cpuid & 15, elf_platform);
 
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 26a68dd..a6d26e1 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -124,6 +124,9 @@ static inline u32 __attribute_const__ read_cpuid_cachetype(void)
 {
 	return read_cpuid(CTR_EL0);
 }
+
+#define read_specific_cpuid(cpu_num) per_cpu_ptr(&cpu_data, cpu_num)->reg_midr
+
 #endif /* __ASSEMBLY__ */
 
 #endif
-- 
2.5.5

^ permalink raw reply related

* [PATCH v11 3/7] arm64: pmu: Cache PMU interrupt numbers from MADT parse
From: Jeremy Linton @ 2016-12-02 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480704961-6910-1-git-send-email-jeremy.linton@arm.com>

From: Mark Salter <msalter@redhat.com>

In the case of ACPI, the PMU IRQ information is contained in the
MADT table. Also, since the PMU does not exist as a device in the
ACPI DSDT table, it is necessary to create a platform device so
that the appropriate driver probing is triggered. Since the platform
device creation needs to happen after the CPU's have been started, and
the MADT parsing needs to happen before, we save off the interrupt
numbers discovered during the parsing.

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/kernel/smp.c      |  5 +++++
 drivers/perf/Kconfig         |  4 ++++
 drivers/perf/Makefile        |  1 +
 drivers/perf/arm_pmu_acpi.c  | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/perf/arm_pmu.h |  7 +++++++
 5 files changed, 57 insertions(+)
 create mode 100644 drivers/perf/arm_pmu_acpi.c

diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index f3f1c90..e350ccc 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -37,6 +37,7 @@
 #include <linux/completion.h>
 #include <linux/of.h>
 #include <linux/irq_work.h>
+#include <linux/perf/arm_pmu.h>
 
 #include <asm/alternative.h>
 #include <asm/atomic.h>
@@ -546,6 +547,7 @@ acpi_verify_and_map_madt(struct acpi_madt_generic_interrupt *processor)
 		}
 		bootcpu_valid = true;
 		early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid));
+		arm_pmu_parse_acpi(0, processor);
 		return;
 	}
 
@@ -566,6 +568,9 @@ acpi_verify_and_map_madt(struct acpi_madt_generic_interrupt *processor)
 	 */
 	acpi_set_mailbox_entry(cpu_count, processor);
 
+	/* get PMU irq info */
+	arm_pmu_parse_acpi(cpu_count, processor);
+
 	early_map_cpu_to_node(cpu_count, acpi_numa_get_nid(cpu_count, hwid));
 
 	cpu_count++;
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 4d5c5f9..697df05 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -19,4 +19,8 @@ config XGENE_PMU
         help
           Say y if you want to use APM X-Gene SoC performance monitors.
 
+config ARM_PMU_ACPI
+	def_bool y
+	depends on ARM_PMU && ACPI
+
 endmenu
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
index b116e98..d1d7762 100644
--- a/drivers/perf/Makefile
+++ b/drivers/perf/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ARM_PMU) += arm_pmu.o
 obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o
+obj-$(CONFIG_ARM_PMU_ACPI) += arm_pmu_acpi.o
diff --git a/drivers/perf/arm_pmu_acpi.c b/drivers/perf/arm_pmu_acpi.c
new file mode 100644
index 0000000..2008001
--- /dev/null
+++ b/drivers/perf/arm_pmu_acpi.c
@@ -0,0 +1,40 @@
+/*
+ * ARM ACPI PMU support
+ *
+ * Copyright (C) 2015 Red Hat Inc.
+ * Author: Mark Salter <msalter@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include <asm/cpu.h>
+#include <linux/acpi.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
+#include <linux/list.h>
+#include <linux/perf/arm_pmu.h>
+#include <linux/platform_device.h>
+
+struct pmu_irq {
+	int  gsi;
+	int  trigger;
+	bool used;
+};
+
+static struct pmu_irq pmu_irqs[NR_CPUS];
+
+/*
+ * Called from acpi_verify_and_map_madt()'s MADT parsing during boot.
+ * This routine saves off the GSI's and their trigger state for use when we are
+ * ready to build the PMU platform device.
+ */
+void __init arm_pmu_parse_acpi(int cpu, struct acpi_madt_generic_interrupt *gic)
+{
+	pmu_irqs[cpu].gsi = gic->performance_interrupt;
+	if (gic->flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
+		pmu_irqs[cpu].trigger = ACPI_EDGE_SENSITIVE;
+	else
+		pmu_irqs[cpu].trigger = ACPI_LEVEL_SENSITIVE;
+}
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index 8462da2..df1ba55 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -164,4 +164,11 @@ int arm_pmu_device_probe(struct platform_device *pdev,
 
 #endif /* CONFIG_ARM_PMU */
 
+#ifdef CONFIG_ARM_PMU_ACPI
+struct acpi_madt_generic_interrupt;
+void arm_pmu_parse_acpi(int cpu, struct acpi_madt_generic_interrupt *gic);
+#else
+#define arm_pmu_parse_acpi(a, b) do { } while (0)
+#endif /* CONFIG_ARM_PMU_ACPI */
+
 #endif /* __ARM_PMU_H__ */
-- 
2.5.5

^ permalink raw reply related

* [PATCH v11 4/7] arm: arm64: pmu: Assign platform PMU CPU affinity
From: Jeremy Linton @ 2016-12-02 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480704961-6910-1-git-send-email-jeremy.linton@arm.com>

On systems with multiple PMU types the PMU to CPU affinity
needs to be detected and set. The CPU to interrupt affinity
should also be set.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 drivers/perf/arm_pmu.c | 43 +++++++++++++++++++++++++++++++++----------
 1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index b37b572..00e98c5 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -11,6 +11,7 @@
  */
 #define pr_fmt(fmt) "hw perfevents: " fmt
 
+#include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <linux/cpumask.h>
 #include <linux/cpu_pm.h>
@@ -24,6 +25,7 @@
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
 
+#include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/irq_regs.h>
 
@@ -889,25 +891,47 @@ static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu)
 }
 
 /*
- * CPU PMU identification and probing.
+ * CPU PMU identification and probing. Its possible to have
+ * multiple CPU types in an ARM machine. Assure that we are
+ * picking the right PMU types based on the CPU in question
  */
-static int probe_current_pmu(struct arm_pmu *pmu,
-			     const struct pmu_probe_info *info)
+static int probe_plat_pmu(struct arm_pmu *pmu,
+			     const struct pmu_probe_info *info,
+			     unsigned int pmuid)
 {
-	int cpu = get_cpu();
-	unsigned int cpuid = read_cpuid_id();
 	int ret = -ENODEV;
+	int cpu;
+	int aff_ctr = 0;
+	struct platform_device *pdev = pmu->plat_device;
+	int irq = platform_get_irq(pdev, 0);
 
-	pr_info("probing PMU on CPU %d\n", cpu);
+	if (irq >= 0 && !irq_is_percpu(irq)) {
+		pmu->irq_affinity = kcalloc(pdev->num_resources, sizeof(int),
+					    GFP_KERNEL);
+		if (!pmu->irq_affinity)
+			return -ENOMEM;
+	}
+
+	for_each_possible_cpu(cpu) {
+		unsigned int cpuid = read_specific_cpuid(cpu);
+
+		if (cpuid == pmuid) {
+			cpumask_set_cpu(cpu, &pmu->supported_cpus);
+			if (pmu->irq_affinity) {
+				pmu->irq_affinity[aff_ctr] = cpu;
+				aff_ctr++;
+			}
+		}
+	}
 
+	/* find the type of PMU given the CPU */
 	for (; info->init != NULL; info++) {
-		if ((cpuid & info->mask) != info->cpuid)
+		if ((pmuid & info->mask) != info->cpuid)
 			continue;
 		ret = info->init(pmu);
 		break;
 	}
 
-	put_cpu();
 	return ret;
 }
 
@@ -1043,8 +1067,7 @@ int arm_pmu_device_probe(struct platform_device *pdev,
 		if (!ret)
 			ret = init_fn(pmu);
 	} else if (probe_table) {
-		cpumask_setall(&pmu->supported_cpus);
-		ret = probe_current_pmu(pmu, probe_table);
+		ret = probe_plat_pmu(pmu, probe_table, read_cpuid_id());
 	}
 
 	if (ret) {
-- 
2.5.5

^ permalink raw reply related

* [PATCH v11 5/7] arm64: pmu: Detect multiple generic PMUs and append counter
From: Jeremy Linton @ 2016-12-02 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480704961-6910-1-git-send-email-jeremy.linton@arm.com>

In heterogeneous CPU systems its likely that there are multiple
PMU types. If a system is using the generic armv8_pmuv3 rather
than a PMU with a hard-coded set of events then we want to uniquely
identify each PMU in /sys. We do this by appending an "_x" to the
pmu name. This then creates PMUs like, "armv8_pmuv3" and
"armv8_pmuv3_1", "armv8_pmuv3_2" for a system with 3 PMU types.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/kernel/perf_event.c |  2 +-
 drivers/perf/arm_pmu.c         | 20 ++++++++++++++++++++
 include/linux/perf/arm_pmu.h   |  1 +
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 57ae9d9..0fbd7ef 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -1002,7 +1002,7 @@ static void armv8_pmu_init(struct arm_pmu *cpu_pmu)
 static int armv8_pmuv3_init(struct arm_pmu *cpu_pmu)
 {
 	armv8_pmu_init(cpu_pmu);
-	cpu_pmu->name			= "armv8_pmuv3";
+	cpu_pmu->name			= ARMV8_PMUV3_DESCRIPTION;
 	cpu_pmu->map_event		= armv8_pmuv3_map_event;
 	cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] =
 		&armv8_pmuv3_events_attr_group;
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 00e98c5..f676573 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -1035,6 +1035,7 @@ int arm_pmu_device_probe(struct platform_device *pdev,
 			 const struct of_device_id *of_table,
 			 const struct pmu_probe_info *probe_table)
 {
+	static int duplicate_pmus;
 	const struct of_device_id *of_id;
 	const int (*init_fn)(struct arm_pmu *);
 	struct device_node *node = pdev->dev.of_node;
@@ -1075,6 +1076,25 @@ int arm_pmu_device_probe(struct platform_device *pdev,
 		goto out_free;
 	}
 
+	/*
+	 * if this pmu declaration is a generic pmu and we have
+	 * previously found a generic pmu on this platform
+	 * then append a PMU number to the pmu name. This avoids
+	 * changing the names of PMUs that are specific to a class
+	 * of CPUs. The assumption is that if we match a specific PMU
+	 * then it's unique, and another PMU in the system will match
+	 * a different entry rather than needing the _number to
+	 * assure its unique.
+	 */
+	if (!strcmp(pmu->name, ARMV8_PMUV3_DESCRIPTION)) {
+		if (duplicate_pmus) {
+			pmu->name = kasprintf(GFP_KERNEL, "%s_%d",
+					      pmu->name, duplicate_pmus);
+			if (!pmu->name)
+				goto out_free;
+		}
+		duplicate_pmus++;
+	}
 
 	ret = cpu_pmu_init(pmu);
 	if (ret)
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index df1ba55..42b5edb 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -161,6 +161,7 @@ int arm_pmu_device_probe(struct platform_device *pdev,
 			 const struct pmu_probe_info *probe_table);
 
 #define ARMV8_PMU_PDEV_NAME "armv8-pmu"
+#define ARMV8_PMUV3_DESCRIPTION "armv8_pmuv3"
 
 #endif /* CONFIG_ARM_PMU */
 
-- 
2.5.5

^ permalink raw reply related

* [PATCH v11 6/7] arm64: pmu: Detect and enable multiple PMUs in an ACPI system
From: Jeremy Linton @ 2016-12-02 18:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480704961-6910-1-git-send-email-jeremy.linton@arm.com>

Its possible that an ACPI system has multiple CPU types in it
with differing PMU counters. Iterate the CPU's and make a determination
about how many of each type exist in the system. Then take and create
a PMU platform device for each type, and assign it the interrupts parsed
from the MADT. Creating a platform device is necessary because the PMUs
are not described as devices in the DSDT table.

This code is loosely based on earlier work by Mark Salter.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 drivers/perf/arm_pmu.c      |   8 +-
 drivers/perf/arm_pmu_acpi.c | 231 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 238 insertions(+), 1 deletion(-)

diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index f676573..fa40294 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -1068,7 +1068,13 @@ int arm_pmu_device_probe(struct platform_device *pdev,
 		if (!ret)
 			ret = init_fn(pmu);
 	} else if (probe_table) {
-		ret = probe_plat_pmu(pmu, probe_table, read_cpuid_id());
+		if (acpi_disabled) {
+			/* use the current cpu. */
+			ret = probe_plat_pmu(pmu, probe_table,
+					     read_cpuid_id());
+		} else {
+			ret = probe_plat_pmu(pmu, probe_table, pdev->id);
+		}
 	}
 
 	if (ret) {
diff --git a/drivers/perf/arm_pmu_acpi.c b/drivers/perf/arm_pmu_acpi.c
index 2008001..e4e107c 100644
--- a/drivers/perf/arm_pmu_acpi.c
+++ b/drivers/perf/arm_pmu_acpi.c
@@ -2,13 +2,17 @@
  * ARM ACPI PMU support
  *
  * Copyright (C) 2015 Red Hat Inc.
+ * Copyright (C) 2016 ARM Ltd.
  * Author: Mark Salter <msalter@redhat.com>
+ *	   Jeremy Linton <jeremy.linton@arm.com>
  *
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
  *
  */
 
+#define pr_fmt(fmt) "ACPI-PMU: " fmt
+
 #include <asm/cpu.h>
 #include <linux/acpi.h>
 #include <linux/irq.h>
@@ -20,9 +24,16 @@
 struct pmu_irq {
 	int  gsi;
 	int  trigger;
+	int  irq;
 	bool used;
 };
 
+struct pmu_types {
+	struct list_head list;
+	int		 cpu_type;
+	int		 cpu_count;
+};
+
 static struct pmu_irq pmu_irqs[NR_CPUS];
 
 /*
@@ -38,3 +49,223 @@ void __init arm_pmu_parse_acpi(int cpu, struct acpi_madt_generic_interrupt *gic)
 	else
 		pmu_irqs[cpu].trigger = ACPI_LEVEL_SENSITIVE;
 }
+
+static void __init arm_pmu_acpi_handle_alloc_failure(struct list_head *pmus)
+{
+	int i;
+	struct pmu_types *pmu, *safe_temp;
+
+	list_for_each_entry_safe(pmu, safe_temp, pmus, list) {
+		list_del(&pmu->list);
+		kfree(pmu);
+	}
+
+	for_each_possible_cpu(i)
+		if (pmu_irqs[i].irq > 0)
+			acpi_unregister_gsi(pmu_irqs[i].gsi);
+}
+
+/*
+ * Count number and type of CPU cores in the system. Returns the number
+ * of "unused" MADT entries we could not associate with a PMU. This can
+ * be the result of CPU's not being online,  or errors in the MADT.
+ * Under normal circumstances this will be 0.
+ */
+static int __init arm_pmu_acpi_determine_cpu_types(struct list_head *pmus)
+{
+	int i;
+	int unused_madt_entries = 0;
+
+	for_each_possible_cpu(i) {
+		u32 reg_midr = read_specific_cpuid(i);
+		struct pmu_types *pmu;
+
+		/*
+		 * Ignore GSI registration failure for now, as
+		 * some of the MADT entries may not be used.
+		 */
+		pmu_irqs[i].irq = acpi_register_gsi(NULL, pmu_irqs[i].gsi,
+						    pmu_irqs[i].trigger,
+						    ACPI_ACTIVE_HIGH);
+		/* likely not online */
+		if (reg_midr == 0) {
+			unused_madt_entries++;
+			continue;
+		}
+
+		list_for_each_entry(pmu, pmus, list) {
+			if (pmu->cpu_type == reg_midr) {
+				pmu->cpu_count++;
+				break;
+			}
+		}
+
+		/* we didn't find the CPU type, add an entry to identify it */
+		if (&pmu->list == pmus) {
+			pmu = kzalloc(sizeof(struct pmu_types), GFP_KERNEL);
+			if (!pmu) {
+				pr_err("Unable to allocate pmu_types\n");
+				arm_pmu_acpi_handle_alloc_failure(pmus);
+				break;
+			}
+			pmu->cpu_type = reg_midr;
+			pmu->cpu_count++;
+			list_add_tail(&pmu->list, pmus);
+		}
+	}
+
+	return unused_madt_entries;
+}
+
+static int __init arm_pmu_acpi_register_device(int count, struct resource *res,
+					       int cpu_id)
+{
+	struct platform_device *pdev;
+	int err = -ENOMEM;
+
+	pdev = platform_device_alloc(ARMV8_PMU_PDEV_NAME, cpu_id);
+	if (pdev) {
+		err = platform_device_add_resources(pdev, res, count);
+		if (!err)
+			err = platform_device_add(pdev);
+		if (err) {
+			pr_warn("Unable to register PMU device\n");
+			platform_device_put(pdev);
+		}
+	} else {
+	    pr_warn("Unable to allocate platform device\n");
+	}
+
+	return err;
+}
+
+static void __init arm_pmu_acpi_unregister_pmu_gsi(int cpu_id)
+{
+	int i;
+
+	for_each_possible_cpu(i) {
+
+		if (read_specific_cpuid(i) == cpu_id) {
+			pmu_irqs[i].used = false;
+			if (pmu_irqs[i].irq > 0)
+				acpi_unregister_gsi(pmu_irqs[i].gsi);
+			pmu_irqs[i].gsi = -ENODEV;
+		}
+	}
+}
+
+/*
+ * Registers the group of PMU interfaces which correspond to the 'cpu_id'.
+ * This group utilizes 'count' resources in the 'res'.
+ */
+static int __init arm_pmu_acpi_register_pmu(int count, struct resource *res,
+					    int cpu_id)
+{
+	int err;
+
+	err = arm_pmu_acpi_register_device(count, res, cpu_id);
+
+	/* unmark and unregister GSIs for this PMU */
+	if (err)
+		arm_pmu_acpi_unregister_pmu_gsi(cpu_id);
+
+	return err;
+}
+
+int arm_pmu_acpi_retrieve_irq(struct resource *res, int cpu)
+{
+	int irq = -ENODEV;
+
+	if (pmu_irqs[cpu].used) {
+		pr_info("CPU %d's interrupt is already used\n", cpu);
+	} else {
+		pmu_irqs[cpu].used = true;
+		res->start = pmu_irqs[cpu].irq;
+		res->end = pmu_irqs[cpu].irq;
+		res->flags = IORESOURCE_IRQ;
+		if (pmu_irqs[cpu].trigger == ACPI_EDGE_SENSITIVE)
+			res->flags |= IORESOURCE_IRQ_HIGHEDGE;
+		else
+			res->flags |= IORESOURCE_IRQ_HIGHLEVEL;
+	}
+	return irq;
+}
+
+/*
+ * For the given cpu/pmu type, walk all known GSIs, register them, and add
+ * them to the resource structure. Return the number of GSI's contained
+ * in the res structure, and the id of the last CPU/PMU we added.
+ */
+static int __init arm_pmu_acpi_gsi_res(struct pmu_types *pmus,
+				       struct resource *res)
+{
+	int i, count;
+
+	/* lets group all the PMU's from similar CPU's together */
+	count = 0;
+	for_each_possible_cpu(i) {
+		u32 reg_midr = read_specific_cpuid(i);
+
+		if (pmus->cpu_type == reg_midr) {
+			if ((pmu_irqs[i].gsi == 0) && (reg_midr != 0))
+				continue;
+
+			/* likely not online */
+			if (!reg_midr)
+				continue;
+
+			arm_pmu_acpi_retrieve_irq(&res[count], i);
+			count++;
+		}
+	}
+	return count;
+}
+
+static int __init pmu_acpi_register(struct pmu_types *pmu)
+{
+	int count;
+	int err = -ENOMEM;
+	struct resource	*res;
+
+	res = kcalloc(pmu->cpu_count, sizeof(struct resource), GFP_KERNEL);
+
+	/* for a given PMU type, collect all the GSIs. */
+	if (res) {
+		count = arm_pmu_acpi_gsi_res(pmu, res);
+		/* register this set of interrupts with a new PMU device */
+		err = arm_pmu_acpi_register_pmu(pmu->cpu_count, res,
+						pmu->cpu_type);
+		if (!err)
+			pr_info("Register %d devices for %X\n", count,
+				pmu->cpu_type);
+		kfree(res);
+	} else {
+		pr_warn("PMU unable to allocate interrupt resource\n");
+		arm_pmu_acpi_unregister_pmu_gsi(pmu->cpu_type);
+	}
+	return err;
+}
+
+static int __init pmu_acpi_init(void)
+{
+	struct pmu_types *pmu, *safe_temp;
+	bool unused_madt_entries;
+	LIST_HEAD(pmus);
+
+	if (acpi_disabled)
+		return 0;
+
+	unused_madt_entries = arm_pmu_acpi_determine_cpu_types(&pmus);
+
+	list_for_each_entry_safe(pmu, safe_temp, &pmus, list) {
+		pmu->cpu_count += unused_madt_entries;
+		pmu_acpi_register(pmu);
+
+		list_del(&pmu->list);
+		kfree(pmu);
+	}
+
+	return 0;
+}
+
+arch_initcall(pmu_acpi_init);
-- 
2.5.5

^ permalink raw reply related

* [PATCH v11 7/7] arm: pmu: Add PMU definitions for cores not initially online
From: Jeremy Linton @ 2016-12-02 18:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480704961-6910-1-git-send-email-jeremy.linton@arm.com>

ACPI CPUs aren't associated with a PMU until they have been put
online. This means that we potentially have to update a PMU
definition the first time a CPU is hot added to the machine.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 drivers/perf/arm_pmu.c       | 38 ++++++++++++++++++++++++++++++++++++--
 include/linux/perf/arm_pmu.h |  4 ++++
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index fa40294..4abb2fe 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -711,6 +711,30 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
 	return 0;
 }
 
+static DEFINE_SPINLOCK(arm_pmu_resource_lock);
+
+static void arm_perf_associate_new_cpu(struct arm_pmu *lpmu, unsigned int cpu)
+{
+	struct platform_device *pdev = lpmu->plat_device;
+	struct resource *res;
+	struct pmu_hw_events *events;
+	int num_res;
+
+	spin_lock(&arm_pmu_resource_lock);
+	for (num_res = 0; num_res < pdev->num_resources; num_res++) {
+		if (!pdev->resource[num_res].flags)
+			break;
+	}
+	res = &pdev->resource[num_res];
+	arm_pmu_acpi_retrieve_irq(res, cpu);
+	events = per_cpu_ptr(lpmu->hw_events, cpu);
+	cpumask_set_cpu(cpu, &lpmu->supported_cpus);
+	if (lpmu->irq_affinity)
+		lpmu->irq_affinity[num_res] = cpu;
+	events->percpu_pmu = lpmu;
+	spin_unlock(&arm_pmu_resource_lock);
+}
+
 /*
  * PMU hardware loses all context when a CPU goes offline.
  * When a CPU is hotplugged back in, since some hardware registers are
@@ -721,10 +745,18 @@ static int arm_perf_starting_cpu(unsigned int cpu, struct hlist_node *node)
 {
 	struct arm_pmu *pmu = hlist_entry_safe(node, struct arm_pmu, node);
 
-	if (!cpumask_test_cpu(cpu, &pmu->supported_cpus))
-		return 0;
+	if (!cpumask_test_cpu(cpu, &pmu->supported_cpus)) {
+		unsigned int cpuid = read_specific_cpuid(cpu);
+
+		if (acpi_disabled)
+			return 0;
+		if (cpuid != pmu->id)
+			return 0;
+		arm_perf_associate_new_cpu(pmu, cpu);
+	}
 	if (pmu->reset)
 		pmu->reset(pmu);
+
 	return 0;
 }
 
@@ -905,6 +937,8 @@ static int probe_plat_pmu(struct arm_pmu *pmu,
 	struct platform_device *pdev = pmu->plat_device;
 	int irq = platform_get_irq(pdev, 0);
 
+	pmu->id = pmuid;
+
 	if (irq >= 0 && !irq_is_percpu(irq)) {
 		pmu->irq_affinity = kcalloc(pdev->num_resources, sizeof(int),
 					    GFP_KERNEL);
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index 42b5edb..f652cd1 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -112,6 +112,7 @@ struct arm_pmu {
 	struct mutex	reserve_mutex;
 	u64		max_period;
 	bool		secure_access; /* 32-bit ARM only */
+	unsigned int	id;
 #define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40
 	DECLARE_BITMAP(pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
 	struct platform_device	*plat_device;
@@ -168,8 +169,11 @@ int arm_pmu_device_probe(struct platform_device *pdev,
 #ifdef CONFIG_ARM_PMU_ACPI
 struct acpi_madt_generic_interrupt;
 void arm_pmu_parse_acpi(int cpu, struct acpi_madt_generic_interrupt *gic);
+int arm_pmu_acpi_retrieve_irq(struct resource *pdev, int cpu);
 #else
 #define arm_pmu_parse_acpi(a, b) do { } while (0)
+#define arm_pmu_acpi_retrieve_irq(pdev, cpu) \
+	do { } while (0)
 #endif /* CONFIG_ARM_PMU_ACPI */
 
 #endif /* __ARM_PMU_H__ */
-- 
2.5.5

^ permalink raw reply related

* [PATCH 1/2] arm64: Get rid of asm/opcodes.h
From: Stefano Stabellini @ 2016-12-02 18:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161202105808.GA16090@e104818-lin.cambridge.arm.com>

On Fri, 2 Dec 2016, Catalin Marinas wrote:
> On Thu, Dec 01, 2016 at 10:44:33AM +0000, Marc Zyngier wrote:
> > The opcodes.h drags in a lot of definition from the 32bit port, most
> > of which is not required at all. Clean things up a bit by moving
> > the bare minimum of what is required next to the actual users,
> > and drop the include file.
> > 
> > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> > ---
> >  arch/arm64/include/asm/opcodes.h     |  5 -----
> >  arch/arm64/include/asm/sysreg.h      | 16 ++++++++++------
> >  arch/arm64/kernel/armv8_deprecated.c |  5 ++++-
> >  arch/arm64/kernel/insn.c             |  1 -
> 
> I applied the first patch. I assume the second one, once it gets into
> its final shape, will be merged via the Xen tree.

Sure

^ permalink raw reply

* [PATCH 1/3] Documentation: dt: Add TI SCI clock driver
From: Stephen Boyd @ 2016-12-02 18:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAL_JsqKox9WVXh=i1jSCijJDTACC35uiNtS-bg9fdyDrX0svRQ@mail.gmail.com>

On 12/02/2016 10:45 AM, Rob Herring wrote:
> On Fri, Dec 2, 2016 at 2:19 AM, Tero Kristo <t-kristo@ti.com> wrote:
>>
>> Rob, any response on this one? I see you have acked the reset part of the
>> bindings which is doing pretty much the same thing as the clock part is
>> doing here, namely adding child node under the main SCI node. Is it okay to
>> do this same for other parts of the TI SCI?
> Yes. It would be silly to allow for one and not others...
>

I'm expecting a respin for the node name (clocks or clock-controller).
I'll also make a review pass on patch 3 today so please don't respin
until after that.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH 1/2] clk: bcm: Support rate change propagation on bcm2835 clocks
From: Eric Anholt @ 2016-12-02 19:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480626020-20031-2-git-send-email-boris.brezillon@free-electrons.com>

Boris Brezillon <boris.brezillon@free-electrons.com> writes:

> Some peripheral clocks, like the VEC (Video EnCoder) clock need to be set
> to a precise rate (in our case 108MHz). With the current implementation,
> where peripheral clocks are not allowed to forward rate change requests
> to their parents, it is impossible to match this requirement unless the
> bootloader has configured things correctly, or a specific rate has been
> assigned through the DT (with the assigned-clk-rates property).
>
> Add a new field to struct bcm2835_clock_data to specify which parent
> clocks accept rate change propagation, and support set rate propagation
> in bcm2835_clock_determine_rate().
>
> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>

A possible simplification would be to limit VEC to only PLLH_AUX, since
that was how the HW designers intended it to be used.  Then you could
just have SET_RATE_PARENT flag, rather than the bitfield.

Still, this seems to be correct and fixes the bug.  Both patches are:

Reviewed-by: Eric Anholt <eric@anholt.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161202/54cee9b5/attachment.sig>

^ permalink raw reply

* [PATCH v4 1/1] PCI/ACPI: xgene: Add ECAM quirk for X-Gene PCIe controller
From: Duc Dang @ 2016-12-02 19:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <175F32B0-C73F-4250-9E60-3CE7409F0B0C@redhat.com>

On Fri, Dec 2, 2016 at 12:11 AM, Jon Masters <jcm@redhat.com> wrote:
> You're welcome.
>
> (Unrelated) Note that I added a console= and earlycon in my test (and got the baud rate wrong for the console but nevermind...was ssh'd in after the earlycon output I cared about anyway) because of some other cleanup work for the SPCR parsing that apparently is still not quite fixed for upstream, or rather, there is a need to match on the 32-bit access required for the UART and that isn't happening so it's not getting setup. Folks are tracking that one and fixing it though.

I don't see this console issue on X-Gene1 (Mustang board). I tried
with X-Gene 2 as well. I used both console=ttyS0,115200 and
earlycon=uart8250,mmio32,0x1c020000. Are you setting baudrate to
115200 or something else?

>
> --
> Computer Architect | Sent from my 64-bit #ARM Powered phone
>
>> On Dec 2, 2016, at 02:37, Duc Dang <dhdang@apm.com> wrote:
>>
>>> On Thu, Dec 1, 2016 at 11:12 PM, Jon Masters <jcm@redhat.com> wrote:
>>>> On 12/01/2016 09:27 PM, Duc Dang wrote:
>>>> PCIe controllers in X-Gene SoCs is not ECAM compliant: software
>>>> needs to configure additional controller's register to address
>>>> device at bus:dev:function.
>>>>
>>>> The quirk will discover controller MMIO register space and configure
>>>> controller registers to select and address the target secondary device.
>>>>
>>>> The quirk will only be applied for X-Gene PCIe MCFG table with
>>>> OEM revison 1, 2, 3 or 4 (PCIe controller v1 and v2 on X-Gene SoCs).
>>>>
>>>> Signed-off-by: Duc Dang <dhdang@apm.com>
>>>
>>> So far I've tested this on an HPE ProLiant m400 (Moonshot) cartridge
>>> and will test it on some other reference platforms soon. Bootlog for
>>> the m400 attached in case Bjorn wants to see the output. Here's
>>> what I see in /proc/iomem btw on that platform:
>>>
>>> # cat /proc/iomem
>>> 10520000-10523fff : APMC0D18:00
>>>  10520000-10523fff : APMC0D18:00
>>> 10524000-10527fff : APMC0D17:00
>>> 10540000-1054a0ff : APMC0D01:00
>>>  10546000-10546fff : APMC0D50:00
>>>  1054a000-1054a00f : APMC0D12:03
>>>    1054a000-1054a00f : APMC0D12:02
>>>      1054a000-1054a00f : APMC0D12:01
>>>        1054a000-1054a00f : APMC0D12:00
>>> 17000000-17000fff : APMC0D01:00
>>> 17001000-17001fff : APMC0D01:00
>>>  17001000-170013ff : APMC0D15:00
>>>    17001000-170013ff : APMC0D15:00
>>> 1701c000-1701cfff : APMC0D14:00
>>> 1a800000-1a800fff : APMC0D0D:00
>>>  1a800000-1a800fff : APMC0D0D:00
>>> 1c000200-1c0002ff : APMC0D06:00
>>> 1c021000-1c0210ff : APMC0D08:00
>>>  1c021000-1c02101f : serial
>>> 1c024000-1c024fff : APMC0D07:00
>>> 1f230000-1f230fff : APMC0D0D:00
>>>  1f230000-1f230fff : APMC0D0D:00
>>> 1f23d000-1f23dfff : APMC0D0D:00
>>>  1f23d000-1f23dfff : APMC0D0D:00
>>> 1f23e000-1f23efff : APMC0D0D:00
>>>  1f23e000-1f23efff : APMC0D0D:00
>>> 1f2a0000-1f31ffff : APMC0D06:00
>>> 1f500000-1f50ffff : PCI Bus 0000:00
>>>  1f500000-1f50ffff : PNP0A08:00
>>> 78800000-78800fff : APMC0D13:00
>>>  78800000-78800fff : APMC0D12:03
>>>    78800000-78800fff : APMC0D12:02
>>>      78800000-78800fff : APMC0D12:01
>>>        78800000-78800fff : APMC0D12:00
>>>          78800000-78800fff : APMC0D11:00
>>>          78800000-78800fff : APMC0D10:03
>>>          78800000-78800fff : APMC0D10:02
>>>          78800000-78800fff : APMC0D10:01
>>>          78800000-78800fff : APMC0D10:00
>>> 79000000-798fffff : APMC0D0E:00
>>> 7c000000-7c1fffff : APMC0D12:00
>>> 7c200000-7c3fffff : APMC0D12:01
>>> 7c400000-7c5fffff : APMC0D12:02
>>> 7c600000-7c7fffff : APMC0D12:03
>>> 7e000000-7e000fff : APMC0D13:00
>>> 7e200000-7e200fff : APMC0D10:03
>>>  7e200000-7e200fff : APMC0D10:02
>>>    7e200000-7e200fff : APMC0D10:01
>>>      7e200000-7e200fff : APMC0D10:00
>>> 7e600000-7e600fff : APMC0D11:00
>>> 7e700000-7e700fff : APMC0D10:03
>>>  7e700000-7e700fff : APMC0D10:02
>>>    7e700000-7e700fff : APMC0D10:01
>>>      7e700000-7e700fff : APMC0D10:00
>>> 7e720000-7e720fff : APMC0D10:03
>>>  7e720000-7e720fff : APMC0D10:02
>>>    7e720000-7e720fff : APMC0D10:01
>>>      7e720000-7e720fff : APMC0D10:00
>>> 7e800000-7e800fff : APMC0D10:00
>>> 7e840000-7e840fff : APMC0D10:01
>>> 7e880000-7e880fff : APMC0D10:02
>>> 7e8c0000-7e8c0fff : APMC0D10:03
>>> 7e930000-7e930fff : APMC0D13:00
>>> 4000000000-4001ffffff : System RAM
>>>  4000080000-4000c3ffff : Kernel code
>>>  4000db0000-400165ffff : Kernel data
>>> 40023a0000-4ff733ffff : System RAM
>>> 4ff7340000-4ff77cffff : reserved
>>> 4ff77d0000-4ff79cffff : System RAM
>>> 4ff79d0000-4ff7e7ffff : reserved
>>> 4ff7e80000-4ff7e8ffff : System RAM
>>> 4ff7e90000-4ff7efffff : reserved
>>> 4ff7f10000-4ff800ffff : reserved
>>> 4ff8010000-4fffffffff : System RAM
>>> a020000000-a03fffffff : PCI Bus 0000:00
>>>  a020000000-a0201fffff : PCI Bus 0000:01
>>>    a020000000-a0200fffff : 0000:01:00.0
>>>      a020000000-a0200fffff : mlx4_core
>>>    a020100000-a0201fffff : 0000:01:00.0
>>> a060000000-a07fffffff : PCI Bus 0000:00
>>> a0d0000000-a0dfffffff : PCI ECAM
>>> a110000000-a14fffffff : PCI Bus 0000:00
>>>  a110000000-a121ffffff : PCI Bus 0000:01
>>>    a110000000-a111ffffff : 0000:01:00.0
>>>      a110000000-a111ffffff : mlx4_core
>>>    a112000000-a121ffffff : 0000:01:00.0
>>>
>>> Adding a Tested-by for the record:
>>>
>>> Tested-by: Jon Masters <jcm@redhat.com>
>>
>> Thanks a lot for testing this, Jon.
>>>
>>> Jon.
>>>
>>> --
>>> Computer Architect | Sent from my Fedora powered laptop
>>>
>> Regards,
>> Duc Dang.

^ permalink raw reply

* [PATCH 1/2] clk: bcm: Support rate change propagation on bcm2835 clocks
From: Boris Brezillon @ 2016-12-02 19:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87lgvyf956.fsf@eliezer.anholt.net>

On Fri, 02 Dec 2016 11:01:09 -0800
Eric Anholt <eric@anholt.net> wrote:

> Boris Brezillon <boris.brezillon@free-electrons.com> writes:
> 
> > Some peripheral clocks, like the VEC (Video EnCoder) clock need to be set
> > to a precise rate (in our case 108MHz). With the current implementation,
> > where peripheral clocks are not allowed to forward rate change requests
> > to their parents, it is impossible to match this requirement unless the
> > bootloader has configured things correctly, or a specific rate has been
> > assigned through the DT (with the assigned-clk-rates property).
> >
> > Add a new field to struct bcm2835_clock_data to specify which parent
> > clocks accept rate change propagation, and support set rate propagation
> > in bcm2835_clock_determine_rate().
> >
> > Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>  
> 
> A possible simplification would be to limit VEC to only PLLH_AUX, since
> that was how the HW designers intended it to be used.  Then you could
> just have SET_RATE_PARENT flag, rather than the bitfield.
> 

I can rework the patches to do that if you prefer.

This being said, I already had a similar issue with atmel clocks [1],
where a peripheral requires a specific rate and the periph clk can
take its source from 2 different PLLs: one that is widely used by other
peripherals and which cannot be modified and the other which is not so
widely used and can be customized to generate the rate we need.
Maybe that's something we should address with a generic solution at
some point: clk constraint propagation, clk rate lock or something
else (Mike mentioned another approach here [1]).

In the meantime, the patch here should do the trick for the bcm2835
platform.

> Still, this seems to be correct and fixes the bug.  Both patches are:
> 
> Reviewed-by: Eric Anholt <eric@anholt.net>

[1]https://patchwork.kernel.org/patch/6204221/

^ permalink raw reply

* [PATCH v2] arm/arm64: xen: Move shared architecture headers to include/xen/arm
From: Stefano Stabellini @ 2016-12-02 19:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480688375-25961-1-git-send-email-marc.zyngier@arm.com>

On Fri, 2 Dec 2016, Marc Zyngier wrote:
> ARM and arm64 Xen ports share a number of headers, leading to
> packaging issues when these headers needs to be exported, as it
> breaks the reasonable requirement that an architecture port
> has self-contained headers.
> 
> Fix the issue by moving the 5 header files to include/xen/arm,
> and keep local placeholders to include the relevant files.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>

Applied to xentip/for-linus-4.10


> * From v1:
>   - Move offending include files to include/xen/arm
> 
>  arch/arm/include/asm/xen/hypercall.h               |  88 +--------------
>  arch/arm/include/asm/xen/hypervisor.h              |  40 +------
>  arch/arm/include/asm/xen/interface.h               |  86 +-------------
>  arch/arm/include/asm/xen/page-coherent.h           |  99 +----------------
>  arch/arm/include/asm/xen/page.h                    | 123 +--------------------
>  arch/arm64/include/asm/xen/hypercall.h             |   2 +-
>  arch/arm64/include/asm/xen/hypervisor.h            |   2 +-
>  arch/arm64/include/asm/xen/interface.h             |   2 +-
>  arch/arm64/include/asm/xen/page-coherent.h         |   2 +-
>  arch/arm64/include/asm/xen/page.h                  |   2 +-
>  .../asm/xen => include/xen/arm}/hypercall.h        |   0
>  .../asm/xen => include/xen/arm}/hypervisor.h       |   0
>  .../asm/xen => include/xen/arm}/interface.h        |   0
>  .../asm/xen => include/xen/arm}/page-coherent.h    |   0
>  .../arm/include/asm/xen => include/xen/arm}/page.h |   0
>  15 files changed, 10 insertions(+), 436 deletions(-)
>  copy {arch/arm/include/asm/xen => include/xen/arm}/hypercall.h (100%)
>  copy {arch/arm/include/asm/xen => include/xen/arm}/hypervisor.h (100%)
>  copy {arch/arm/include/asm/xen => include/xen/arm}/interface.h (100%)
>  copy {arch/arm/include/asm/xen => include/xen/arm}/page-coherent.h (100%)
>  copy {arch/arm/include/asm/xen => include/xen/arm}/page.h (100%)
> 
> diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h
> index 9d874db..3522cba 100644
> --- a/arch/arm/include/asm/xen/hypercall.h
> +++ b/arch/arm/include/asm/xen/hypercall.h
> @@ -1,87 +1 @@
> -/******************************************************************************
> - * hypercall.h
> - *
> - * Linux-specific hypervisor handling.
> - *
> - * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> - *
> - * 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; or, when distributed
> - * separately from the Linux kernel or incorporated into other
> - * software packages, subject to the following license:
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a copy
> - * of this source file (the "Software"), to deal in the Software without
> - * restriction, including without limitation the rights to use, copy, modify,
> - * merge, publish, distribute, sublicense, and/or sell copies of the Software,
> - * and to permit persons to whom the Software is furnished to do so, subject to
> - * the following conditions:
> - *
> - * The above copyright notice and this permission notice shall be included in
> - * all copies or substantial portions of the Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> - * IN THE SOFTWARE.
> - */
> -
> -#ifndef _ASM_ARM_XEN_HYPERCALL_H
> -#define _ASM_ARM_XEN_HYPERCALL_H
> -
> -#include <linux/bug.h>
> -
> -#include <xen/interface/xen.h>
> -#include <xen/interface/sched.h>
> -#include <xen/interface/platform.h>
> -
> -long privcmd_call(unsigned call, unsigned long a1,
> -		unsigned long a2, unsigned long a3,
> -		unsigned long a4, unsigned long a5);
> -int HYPERVISOR_xen_version(int cmd, void *arg);
> -int HYPERVISOR_console_io(int cmd, int count, char *str);
> -int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
> -int HYPERVISOR_sched_op(int cmd, void *arg);
> -int HYPERVISOR_event_channel_op(int cmd, void *arg);
> -unsigned long HYPERVISOR_hvm_op(int op, void *arg);
> -int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
> -int HYPERVISOR_physdev_op(int cmd, void *arg);
> -int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args);
> -int HYPERVISOR_tmem_op(void *arg);
> -int HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type);
> -int HYPERVISOR_platform_op_raw(void *arg);
> -static inline int HYPERVISOR_platform_op(struct xen_platform_op *op)
> -{
> -	op->interface_version = XENPF_INTERFACE_VERSION;
> -	return HYPERVISOR_platform_op_raw(op);
> -}
> -int HYPERVISOR_multicall(struct multicall_entry *calls, uint32_t nr);
> -
> -static inline int
> -HYPERVISOR_suspend(unsigned long start_info_mfn)
> -{
> -	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
> -
> -	/* start_info_mfn is unused on ARM */
> -	return HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
> -}
> -
> -static inline void
> -MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
> -			unsigned int new_val, unsigned long flags)
> -{
> -	BUG();
> -}
> -
> -static inline void
> -MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
> -		 int count, int *success_count, domid_t domid)
> -{
> -	BUG();
> -}
> -
> -#endif /* _ASM_ARM_XEN_HYPERCALL_H */
> +#include <xen/arm/hypercall.h>
> diff --git a/arch/arm/include/asm/xen/hypervisor.h b/arch/arm/include/asm/xen/hypervisor.h
> index 9525151..d6e7709 100644
> --- a/arch/arm/include/asm/xen/hypervisor.h
> +++ b/arch/arm/include/asm/xen/hypervisor.h
> @@ -1,39 +1 @@
> -#ifndef _ASM_ARM_XEN_HYPERVISOR_H
> -#define _ASM_ARM_XEN_HYPERVISOR_H
> -
> -#include <linux/init.h>
> -
> -extern struct shared_info *HYPERVISOR_shared_info;
> -extern struct start_info *xen_start_info;
> -
> -/* Lazy mode for batching updates / context switch */
> -enum paravirt_lazy_mode {
> -	PARAVIRT_LAZY_NONE,
> -	PARAVIRT_LAZY_MMU,
> -	PARAVIRT_LAZY_CPU,
> -};
> -
> -static inline enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
> -{
> -	return PARAVIRT_LAZY_NONE;
> -}
> -
> -extern struct dma_map_ops *xen_dma_ops;
> -
> -#ifdef CONFIG_XEN
> -void __init xen_early_init(void);
> -#else
> -static inline void xen_early_init(void) { return; }
> -#endif
> -
> -#ifdef CONFIG_HOTPLUG_CPU
> -static inline void xen_arch_register_cpu(int num)
> -{
> -}
> -
> -static inline void xen_arch_unregister_cpu(int num)
> -{
> -}
> -#endif
> -
> -#endif /* _ASM_ARM_XEN_HYPERVISOR_H */
> +#include <xen/arm/hypervisor.h>
> diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h
> index 75d5968..88c0d75 100644
> --- a/arch/arm/include/asm/xen/interface.h
> +++ b/arch/arm/include/asm/xen/interface.h
> @@ -1,85 +1 @@
> -/******************************************************************************
> - * Guest OS interface to ARM Xen.
> - *
> - * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> - */
> -
> -#ifndef _ASM_ARM_XEN_INTERFACE_H
> -#define _ASM_ARM_XEN_INTERFACE_H
> -
> -#include <linux/types.h>
> -
> -#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
> -
> -#define __DEFINE_GUEST_HANDLE(name, type) \
> -	typedef struct { union { type *p; uint64_aligned_t q; }; }  \
> -        __guest_handle_ ## name
> -
> -#define DEFINE_GUEST_HANDLE_STRUCT(name) \
> -	__DEFINE_GUEST_HANDLE(name, struct name)
> -#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
> -#define GUEST_HANDLE(name)        __guest_handle_ ## name
> -
> -#define set_xen_guest_handle(hnd, val)			\
> -	do {						\
> -		if (sizeof(hnd) == 8)			\
> -			*(uint64_t *)&(hnd) = 0;	\
> -		(hnd).p = val;				\
> -	} while (0)
> -
> -#define __HYPERVISOR_platform_op_raw __HYPERVISOR_platform_op
> -
> -#ifndef __ASSEMBLY__
> -/* Explicitly size integers that represent pfns in the interface with
> - * Xen so that we can have one ABI that works for 32 and 64 bit guests.
> - * Note that this means that the xen_pfn_t type may be capable of
> - * representing pfn's which the guest cannot represent in its own pfn
> - * type. However since pfn space is controlled by the guest this is
> - * fine since it simply wouldn't be able to create any sure pfns in
> - * the first place.
> - */
> -typedef uint64_t xen_pfn_t;
> -#define PRI_xen_pfn "llx"
> -typedef uint64_t xen_ulong_t;
> -#define PRI_xen_ulong "llx"
> -typedef int64_t xen_long_t;
> -#define PRI_xen_long "llx"
> -/* Guest handles for primitive C types. */
> -__DEFINE_GUEST_HANDLE(uchar, unsigned char);
> -__DEFINE_GUEST_HANDLE(uint,  unsigned int);
> -DEFINE_GUEST_HANDLE(char);
> -DEFINE_GUEST_HANDLE(int);
> -DEFINE_GUEST_HANDLE(void);
> -DEFINE_GUEST_HANDLE(uint64_t);
> -DEFINE_GUEST_HANDLE(uint32_t);
> -DEFINE_GUEST_HANDLE(xen_pfn_t);
> -DEFINE_GUEST_HANDLE(xen_ulong_t);
> -
> -/* Maximum number of virtual CPUs in multi-processor guests. */
> -#define MAX_VIRT_CPUS 1
> -
> -struct arch_vcpu_info { };
> -struct arch_shared_info { };
> -
> -/* TODO: Move pvclock definitions some place arch independent */
> -struct pvclock_vcpu_time_info {
> -	u32   version;
> -	u32   pad0;
> -	u64   tsc_timestamp;
> -	u64   system_time;
> -	u32   tsc_to_system_mul;
> -	s8    tsc_shift;
> -	u8    flags;
> -	u8    pad[2];
> -} __attribute__((__packed__)); /* 32 bytes */
> -
> -/* It is OK to have a 12 bytes struct with no padding because it is packed */
> -struct pvclock_wall_clock {
> -	u32   version;
> -	u32   sec;
> -	u32   nsec;
> -	u32   sec_hi;
> -} __attribute__((__packed__));
> -#endif
> -
> -#endif /* _ASM_ARM_XEN_INTERFACE_H */
> +#include <xen/arm/interface.h>
> diff --git a/arch/arm/include/asm/xen/page-coherent.h b/arch/arm/include/asm/xen/page-coherent.h
> index 95ce6ac..b3ef061 100644
> --- a/arch/arm/include/asm/xen/page-coherent.h
> +++ b/arch/arm/include/asm/xen/page-coherent.h
> @@ -1,98 +1 @@
> -#ifndef _ASM_ARM_XEN_PAGE_COHERENT_H
> -#define _ASM_ARM_XEN_PAGE_COHERENT_H
> -
> -#include <asm/page.h>
> -#include <linux/dma-mapping.h>
> -
> -void __xen_dma_map_page(struct device *hwdev, struct page *page,
> -	     dma_addr_t dev_addr, unsigned long offset, size_t size,
> -	     enum dma_data_direction dir, unsigned long attrs);
> -void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
> -		size_t size, enum dma_data_direction dir,
> -		unsigned long attrs);
> -void __xen_dma_sync_single_for_cpu(struct device *hwdev,
> -		dma_addr_t handle, size_t size, enum dma_data_direction dir);
> -
> -void __xen_dma_sync_single_for_device(struct device *hwdev,
> -		dma_addr_t handle, size_t size, enum dma_data_direction dir);
> -
> -static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
> -		dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
> -{
> -	return __generic_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
> -}
> -
> -static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
> -		void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
> -{
> -	__generic_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
> -}
> -
> -static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
> -	     dma_addr_t dev_addr, unsigned long offset, size_t size,
> -	     enum dma_data_direction dir, unsigned long attrs)
> -{
> -	unsigned long page_pfn = page_to_xen_pfn(page);
> -	unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
> -	unsigned long compound_pages =
> -		(1<<compound_order(page)) * XEN_PFN_PER_PAGE;
> -	bool local = (page_pfn <= dev_pfn) &&
> -		(dev_pfn - page_pfn < compound_pages);
> -
> -	/*
> -	 * Dom0 is mapped 1:1, while the Linux page can span across
> -	 * multiple Xen pages, it's not possible for it to contain a
> -	 * mix of local and foreign Xen pages. So if the first xen_pfn
> -	 * == mfn the page is local otherwise it's a foreign page
> -	 * grant-mapped in dom0. If the page is local we can safely
> -	 * call the native dma_ops function, otherwise we call the xen
> -	 * specific function.
> -	 */
> -	if (local)
> -		__generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
> -	else
> -		__xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
> -}
> -
> -static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
> -		size_t size, enum dma_data_direction dir, unsigned long attrs)
> -{
> -	unsigned long pfn = PFN_DOWN(handle);
> -	/*
> -	 * Dom0 is mapped 1:1, while the Linux page can be spanned accross
> -	 * multiple Xen page, it's not possible to have a mix of local and
> -	 * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
> -	 * foreign mfn will always return false. If the page is local we can
> -	 * safely call the native dma_ops function, otherwise we call the xen
> -	 * specific function.
> -	 */
> -	if (pfn_valid(pfn)) {
> -		if (__generic_dma_ops(hwdev)->unmap_page)
> -			__generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
> -	} else
> -		__xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
> -}
> -
> -static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
> -		dma_addr_t handle, size_t size, enum dma_data_direction dir)
> -{
> -	unsigned long pfn = PFN_DOWN(handle);
> -	if (pfn_valid(pfn)) {
> -		if (__generic_dma_ops(hwdev)->sync_single_for_cpu)
> -			__generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
> -	} else
> -		__xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
> -}
> -
> -static inline void xen_dma_sync_single_for_device(struct device *hwdev,
> -		dma_addr_t handle, size_t size, enum dma_data_direction dir)
> -{
> -	unsigned long pfn = PFN_DOWN(handle);
> -	if (pfn_valid(pfn)) {
> -		if (__generic_dma_ops(hwdev)->sync_single_for_device)
> -			__generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
> -	} else
> -		__xen_dma_sync_single_for_device(hwdev, handle, size, dir);
> -}
> -
> -#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
> +#include <xen/arm/page-coherent.h>
> diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h
> index 415dbc6..31bbc80 100644
> --- a/arch/arm/include/asm/xen/page.h
> +++ b/arch/arm/include/asm/xen/page.h
> @@ -1,122 +1 @@
> -#ifndef _ASM_ARM_XEN_PAGE_H
> -#define _ASM_ARM_XEN_PAGE_H
> -
> -#include <asm/page.h>
> -#include <asm/pgtable.h>
> -
> -#include <linux/pfn.h>
> -#include <linux/types.h>
> -#include <linux/dma-mapping.h>
> -
> -#include <xen/xen.h>
> -#include <xen/interface/grant_table.h>
> -
> -#define phys_to_machine_mapping_valid(pfn) (1)
> -
> -/* Xen machine address */
> -typedef struct xmaddr {
> -	phys_addr_t maddr;
> -} xmaddr_t;
> -
> -/* Xen pseudo-physical address */
> -typedef struct xpaddr {
> -	phys_addr_t paddr;
> -} xpaddr_t;
> -
> -#define XMADDR(x)	((xmaddr_t) { .maddr = (x) })
> -#define XPADDR(x)	((xpaddr_t) { .paddr = (x) })
> -
> -#define INVALID_P2M_ENTRY      (~0UL)
> -
> -/*
> - * The pseudo-physical frame (pfn) used in all the helpers is always based
> - * on Xen page granularity (i.e 4KB).
> - *
> - * A Linux page may be split across multiple non-contiguous Xen page so we
> - * have to keep track with frame based on 4KB page granularity.
> - *
> - * PV drivers should never make a direct usage of those helpers (particularly
> - * pfn_to_gfn and gfn_to_pfn).
> - */
> -
> -unsigned long __pfn_to_mfn(unsigned long pfn);
> -extern struct rb_root phys_to_mach;
> -
> -/* Pseudo-physical <-> Guest conversion */
> -static inline unsigned long pfn_to_gfn(unsigned long pfn)
> -{
> -	return pfn;
> -}
> -
> -static inline unsigned long gfn_to_pfn(unsigned long gfn)
> -{
> -	return gfn;
> -}
> -
> -/* Pseudo-physical <-> BUS conversion */
> -static inline unsigned long pfn_to_bfn(unsigned long pfn)
> -{
> -	unsigned long mfn;
> -
> -	if (phys_to_mach.rb_node != NULL) {
> -		mfn = __pfn_to_mfn(pfn);
> -		if (mfn != INVALID_P2M_ENTRY)
> -			return mfn;
> -	}
> -
> -	return pfn;
> -}
> -
> -static inline unsigned long bfn_to_pfn(unsigned long bfn)
> -{
> -	return bfn;
> -}
> -
> -#define bfn_to_local_pfn(bfn)	bfn_to_pfn(bfn)
> -
> -/* VIRT <-> GUEST conversion */
> -#define virt_to_gfn(v)		(pfn_to_gfn(virt_to_phys(v) >> XEN_PAGE_SHIFT))
> -#define gfn_to_virt(m)		(__va(gfn_to_pfn(m) << XEN_PAGE_SHIFT))
> -
> -/* Only used in PV code. But ARM guests are always HVM. */
> -static inline xmaddr_t arbitrary_virt_to_machine(void *vaddr)
> -{
> -	BUG();
> -}
> -
> -/* TODO: this shouldn't be here but it is because the frontend drivers
> - * are using it (its rolled in headers) even though we won't hit the code path.
> - * So for right now just punt with this.
> - */
> -static inline pte_t *lookup_address(unsigned long address, unsigned int *level)
> -{
> -	BUG();
> -	return NULL;
> -}
> -
> -extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
> -				   struct gnttab_map_grant_ref *kmap_ops,
> -				   struct page **pages, unsigned int count);
> -
> -extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
> -				     struct gnttab_unmap_grant_ref *kunmap_ops,
> -				     struct page **pages, unsigned int count);
> -
> -bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
> -bool __set_phys_to_machine_multi(unsigned long pfn, unsigned long mfn,
> -		unsigned long nr_pages);
> -
> -static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
> -{
> -	return __set_phys_to_machine(pfn, mfn);
> -}
> -
> -#define xen_remap(cookie, size) ioremap_cache((cookie), (size))
> -#define xen_unmap(cookie) iounmap((cookie))
> -
> -bool xen_arch_need_swiotlb(struct device *dev,
> -			   phys_addr_t phys,
> -			   dma_addr_t dev_addr);
> -unsigned long xen_get_swiotlb_free_pages(unsigned int order);
> -
> -#endif /* _ASM_ARM_XEN_PAGE_H */
> +#include <xen/arm/page.h>
> diff --git a/arch/arm64/include/asm/xen/hypercall.h b/arch/arm64/include/asm/xen/hypercall.h
> index 74b0c42..3522cba 100644
> --- a/arch/arm64/include/asm/xen/hypercall.h
> +++ b/arch/arm64/include/asm/xen/hypercall.h
> @@ -1 +1 @@
> -#include <../../arm/include/asm/xen/hypercall.h>
> +#include <xen/arm/hypercall.h>
> diff --git a/arch/arm64/include/asm/xen/hypervisor.h b/arch/arm64/include/asm/xen/hypervisor.h
> index f263da8..d6e7709 100644
> --- a/arch/arm64/include/asm/xen/hypervisor.h
> +++ b/arch/arm64/include/asm/xen/hypervisor.h
> @@ -1 +1 @@
> -#include <../../arm/include/asm/xen/hypervisor.h>
> +#include <xen/arm/hypervisor.h>
> diff --git a/arch/arm64/include/asm/xen/interface.h b/arch/arm64/include/asm/xen/interface.h
> index 44457ae..88c0d75 100644
> --- a/arch/arm64/include/asm/xen/interface.h
> +++ b/arch/arm64/include/asm/xen/interface.h
> @@ -1 +1 @@
> -#include <../../arm/include/asm/xen/interface.h>
> +#include <xen/arm/interface.h>
> diff --git a/arch/arm64/include/asm/xen/page-coherent.h b/arch/arm64/include/asm/xen/page-coherent.h
> index 2052102..b3ef061 100644
> --- a/arch/arm64/include/asm/xen/page-coherent.h
> +++ b/arch/arm64/include/asm/xen/page-coherent.h
> @@ -1 +1 @@
> -#include <../../arm/include/asm/xen/page-coherent.h>
> +#include <xen/arm/page-coherent.h>
> diff --git a/arch/arm64/include/asm/xen/page.h b/arch/arm64/include/asm/xen/page.h
> index bed87ec..31bbc80 100644
> --- a/arch/arm64/include/asm/xen/page.h
> +++ b/arch/arm64/include/asm/xen/page.h
> @@ -1 +1 @@
> -#include <../../arm/include/asm/xen/page.h>
> +#include <xen/arm/page.h>
> diff --git a/arch/arm/include/asm/xen/hypercall.h b/include/xen/arm/hypercall.h
> similarity index 100%
> copy from arch/arm/include/asm/xen/hypercall.h
> copy to include/xen/arm/hypercall.h
> diff --git a/arch/arm/include/asm/xen/hypervisor.h b/include/xen/arm/hypervisor.h
> similarity index 100%
> copy from arch/arm/include/asm/xen/hypervisor.h
> copy to include/xen/arm/hypervisor.h
> diff --git a/arch/arm/include/asm/xen/interface.h b/include/xen/arm/interface.h
> similarity index 100%
> copy from arch/arm/include/asm/xen/interface.h
> copy to include/xen/arm/interface.h
> diff --git a/arch/arm/include/asm/xen/page-coherent.h b/include/xen/arm/page-coherent.h
> similarity index 100%
> copy from arch/arm/include/asm/xen/page-coherent.h
> copy to include/xen/arm/page-coherent.h
> diff --git a/arch/arm/include/asm/xen/page.h b/include/xen/arm/page.h
> similarity index 100%
> copy from arch/arm/include/asm/xen/page.h
> copy to include/xen/arm/page.h
> -- 
> 2.1.4
> 

^ permalink raw reply

* [PATCH v4 1/1] PCI/ACPI: xgene: Add ECAM quirk for X-Gene PCIe controller
From: Jon Masters @ 2016-12-02 19:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CADaLNDmWRn+UKzF8PH2LmYCSF+NhHaw26RTN+QoaByh1wS7jfQ@mail.gmail.com>

On 12/02/2016 02:39 PM, Duc Dang wrote:
> On Fri, Dec 2, 2016 at 12:11 AM, Jon Masters <jcm@redhat.com> wrote:
>> You're welcome.
>>
>> (Unrelated) Note that I added a console= and earlycon in my test (and got the baud rate wrong for the console but nevermind...was ssh'd in after the earlycon output I cared about anyway) because of some other cleanup work for the SPCR parsing that apparently is still not quite fixed for upstream, or rather, there is a need to match on the 32-bit access required for the UART and that isn't happening so it's not getting setup. Folks are tracking that one and fixing it though.
> 
> I don't see this console issue on X-Gene1 (Mustang board). I tried
> with X-Gene 2 as well. I used both console=ttyS0,115200 and
> earlycon=uart8250,mmio32,0x1c020000. Are you setting baudrate to
> 115200 or something else?

It's an m400 issue in that their SPCR needs updating to convey the
required 32-bit access width for the 8250 dw IP or similar. It's one
of those things someone described the other day and it made sense but
I haven't yet dug into the exact situation, other than that I know
the access width in the m400 ACPI table isn't quite right.

My understanding is that it's in hand. I'll catch up on exactly what's
up, check with my own mustangs, and followup separately.

Jon.

-- 
Computer Architect | Sent from my Fedora powered laptop

^ permalink raw reply

* [PATCH v2 1/2] arm64: dts: zx: Fix gic GICR property
From: Arnd Bergmann @ 2016-12-02 20:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <a243d381-f7ab-abed-ca21-f0951abb04fd@arm.com>

On Friday, December 2, 2016 5:02:28 PM CET Marc Zyngier wrote:
> On 13/10/16 13:31, Jun Nie wrote:
> > GICR for multiple CPU can be described with start address and stride,
> > or with multiple address. Current multiple address and stride are
> > both used. Fix it.
> > 
> > vmalloc patch 727a7f5a9 triggered this bug:
> > [    0.097146] Unable to handle kernel paging request at virtual address ffff000008060008
> > [    0.097150] pgd = ffff000008602000
> > [    0.097160] [ffff000008060008] *pgd=000000007fffe003, *pud=000000007fffd003, *pmd=000000007fffc003, *pte=0000000000000000
> > [    0.097165] Internal error: Oops: 96000007 [#1] PREEMPT SMP
> > [    0.097170] Modules linked in:
> > [    0.097177] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.8.0+ #1474
> > [    0.097179] Hardware name: ZTE zx296718 evaluation board (DT)
> > [    0.097183] task: ffff80003e8c8b80 task.stack: ffff80003e8d0000
> > [    0.097197] PC is at gic_populate_rdist+0x74/0x15c
> > [    0.097202] LR is at gic_starting_cpu+0xc/0x20
> > [    0.097206] pc : [<ffff0000082b1b18>] lr : [<ffff0000082b26e0>] pstate: 600001c5
> > 
> > Signed-off-by: Jun Nie <jun.nie@linaro.org>
> > ---
> >  arch/arm64/boot/dts/zte/zx296718.dtsi | 11 +++--------
> >  1 file changed, 3 insertions(+), 8 deletions(-)
> > 
> > diff --git a/arch/arm64/boot/dts/zte/zx296718.dtsi b/arch/arm64/boot/dts/zte/zx296718.dtsi
> > index a223066..6b239a3 100644
> > --- a/arch/arm64/boot/dts/zte/zx296718.dtsi
> > +++ b/arch/arm64/boot/dts/zte/zx296718.dtsi
> > @@ -239,16 +239,11 @@
> >               compatible = "arm,gic-v3";
> >               #interrupt-cells = <3>;
> >               #address-cells = <0>;
> > -             #redistributor-regions = <6>;
> > -             redistributor-stride = <0x0 0x40000>;
> > +             #redistributor-regions = <1>;
> > +             redistributor-stride = <0x20000>;
> 
> Why is that stride specified? Is the GIC implementation so busted that
> the GICR_TYPER do not report a GICv3 redistributor, which implies a
> 128kB stride?

Given that there is any concern about the patch now, and the merge
window is almost open, I'm moving both patches to the
next/fixes-non-critical branch and will merge it for v4.10 instead
of sending it for v4.9.

If you end up deciding that the patch is wrong, please follow up
with a fix on top. Once the situation is resolved and the patch
merged upstream, feel free to ask stable at vger.kernel.org for a
backport to stable kernels to get it into v4.9.x.

	Arnd

^ permalink raw reply

* [PATCH 1/3] Documentation: dt: Add TI SCI clock driver
From: Tero Kristo @ 2016-12-02 21:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5f146fb6-ec88-b7ee-ef5b-a5ad32c54a74@codeaurora.org>

On 02/12/16 20:58, Stephen Boyd wrote:
> On 12/02/2016 10:45 AM, Rob Herring wrote:
>> On Fri, Dec 2, 2016 at 2:19 AM, Tero Kristo <t-kristo@ti.com> wrote:
>>>
>>> Rob, any response on this one? I see you have acked the reset part of the
>>> bindings which is doing pretty much the same thing as the clock part is
>>> doing here, namely adding child node under the main SCI node. Is it okay to
>>> do this same for other parts of the TI SCI?
>> Yes. It would be silly to allow for one and not others...
>>
>
> I'm expecting a respin for the node name (clocks or clock-controller).
> I'll also make a review pass on patch 3 today so please don't respin
> until after that.

Yeah, I need to fix that and re-send. This series will be most likely 
delayed until 4.11 though seeing its very late in 4.9-rc already (and 
the genpd part dependency is still not ready either) so we are not in a 
rush right now.

-Tero

^ permalink raw reply

* [PATCH 1/2] clk: bcm: Support rate change propagation on bcm2835 clocks
From: Eric Anholt @ 2016-12-02 21:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161202205021.074fd441@bbrezillon>

Boris Brezillon <boris.brezillon@free-electrons.com> writes:

> On Fri, 02 Dec 2016 11:01:09 -0800
> Eric Anholt <eric@anholt.net> wrote:
>
>> Boris Brezillon <boris.brezillon@free-electrons.com> writes:
>> 
>> > Some peripheral clocks, like the VEC (Video EnCoder) clock need to be set
>> > to a precise rate (in our case 108MHz). With the current implementation,
>> > where peripheral clocks are not allowed to forward rate change requests
>> > to their parents, it is impossible to match this requirement unless the
>> > bootloader has configured things correctly, or a specific rate has been
>> > assigned through the DT (with the assigned-clk-rates property).
>> >
>> > Add a new field to struct bcm2835_clock_data to specify which parent
>> > clocks accept rate change propagation, and support set rate propagation
>> > in bcm2835_clock_determine_rate().
>> >
>> > Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>  
>> 
>> A possible simplification would be to limit VEC to only PLLH_AUX, since
>> that was how the HW designers intended it to be used.  Then you could
>> just have SET_RATE_PARENT flag, rather than the bitfield.
>> 
>
> I can rework the patches to do that if you prefer.

I'm fine with the patches as is, just throwing the idea out there.

In general, I think the only automatic parent switching I've heard of
being useful in the platform is I2S's clock being able to get a
non-MASHed clock when the rate divides evenly off of something.  Other
than that, automatic parent switching seems to just get us in trouble
(we've had bugs with PLLC, and we wouldn't want any non-VEC clock to end
up on PLLH_AUX either).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161202/32e5bcae/attachment.sig>

^ 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