* [PATCH v2 09/12] PCI: Remove ARCH_KIRKWOOD dependency
From: Bjorn Helgaas @ 2014-07-22 18:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405028192-9623-10-git-send-email-andrew@lunn.ch>
On Thu, Jul 10, 2014 at 11:36:29PM +0200, Andrew Lunn wrote:
> mach-kirkwood has been removed, now that kirkwood lives in mach-mvebu.
> ARCH_MVEBU is sufficient.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Applied with Jason's ack to pci/host-mvebu for v3.17, thanks!
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: linux-pci at vger.kernel.org
> ---
> drivers/pci/host/Kconfig | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index 21df477be0c8..88f4862fa452 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -3,7 +3,7 @@ menu "PCI host controller drivers"
>
> config PCI_MVEBU
> bool "Marvell EBU PCIe controller"
> - depends on ARCH_MVEBU || ARCH_DOVE || ARCH_KIRKWOOD
> + depends on ARCH_MVEBU || ARCH_DOVE
> depends on OF
>
> config PCIE_DW
> --
> 2.0.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [GIT PULL v2.1] Mediatek basic support for v3.17
From: Russell King - ARM Linux @ 2014-07-22 18:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CABuKBeLc=Bbpqrksdjoc_0Sx_rVpZLuY1aUY1WtK5Vp20Jiv8g@mail.gmail.com>
Your To: header contains many tens of people. Which person out of
all those do you expect to pull your changes?
Email has a way to identify whom you are talking _to_ and whom you wish
to _copy_ for information purposes.
These are the "To:" and "Cc:" fields on email. Those on the "To:" list
are those who you are directly addressing your message. Those on the
Cc: list are "Carbon Copy" recipients, in other words, ones you are
notifying for information purposes.
Let's say that you're an HR department. You're firing an employee.
You send your message "To" the employee and "To" the employee's managers.
Congratulations, you've just fired the employee along with his managers.
If instead, you send your message "To" the employee and "Cc" the
employee's managers, it's then clear that the employee's managers
are being copied for information purposes.
The same thing applies here. Send your pull request "To" the person
or group of people who you wish to action your request, and include
on the "Cc" those whom may be interested in seeing the pull request
for information purposes.
Please be more careful with your email addressing technique in the
future, thanks.
[No, I haven't pulled anything]
On Tue, Jul 22, 2014 at 06:34:17PM +0200, Matthias Brugger wrote:
> The patches 1-4 from the v10 series [0] of the patch set have been
> merged by Daniel Lezcano [1]. This pull request has just the remaining
> patches 5-7
>
> There is an Ack from Rob Herring for the SoC device tree binding patch.
> The other two patches lack an Ack from the maintainers.
>
> [0] http://thread.gmane.org/gmane.linux.documentation/25231
> [1] https://lkml.org/lkml/2014/7/21/291
>
> ---
>
> Changes for v2.1:
> - fix screwed up explanation
>
> Changes for v2:
> - request includes just patches 5-7 from the series
>
> ----------------------------------------------------------------
> The following changes since commit 7171511eaec5bf23fb06078f59784a3a0626b38f:
>
> Linux 3.16-rc1 (2014-06-15 17:45:28 -1000)
>
> are available in the git repository at:
>
> https://github.com/mbgg/linux-mediatek.git tags/v3.17-next-mediatek-support
>
> for you to fetch changes up to afaedea451149ab8f08c37ce688c8021ed347811:
>
> arm: mediatek: add dts for Aquaris5 mobile phone (2014-07-22 17:52:38 +0200)
>
> ----------------------------------------------------------------
> This patch set adds basic support for the Mediatek Cortex-A7 SoCs.
>
> Support is quite basic, as the only component working up to now are the
> timers.
>
> Signed-off-by: Matthias Brugger matthias.bgg at gmail.com
>
> ----------------------------------------------------------------
> Matthias Brugger (3):
> arm: add basic support for Mediatek MT6589 boards
> dt-bindings: add documentation for Mediatek SoC
> arm: mediatek: add dts for Aquaris5 mobile phone
>
> Documentation/devicetree/bindings/arm/mediatek.txt | 8 ++
> arch/arm/Kconfig | 2 +
> arch/arm/Makefile | 1 +
> arch/arm/boot/dts/mt6589-aquaris5.dts | 25 ++++++
> arch/arm/boot/dts/mt6589.dtsi | 94 ++++++++++++++++++++
> arch/arm/mach-mediatek/Kconfig | 6 ++
> arch/arm/mach-mediatek/Makefile | 1 +
> arch/arm/mach-mediatek/mediatek.c | 27 ++++++
> 8 files changed, 164 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/arm/mediatek.txt
> create mode 100644 arch/arm/boot/dts/mt6589-aquaris5.dts
> create mode 100644 arch/arm/boot/dts/mt6589.dtsi
> create mode 100644 arch/arm/mach-mediatek/Kconfig
> create mode 100644 arch/arm/mach-mediatek/Makefile
> create mode 100644 arch/arm/mach-mediatek/mediatek.c
--
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* [PATCH v3] platform: Make platform_bus device a platform device
From: Greg Kroah-Hartman @ 2014-07-22 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1406052069.25343.93.camel@hornet>
On Tue, Jul 22, 2014 at 07:01:09PM +0100, Pawel Moll wrote:
> On Tue, 2014-07-22 at 18:55 +0100, Pawel Moll wrote:
> > * replaced references to platform_bus.dev with NULL
> > in places where it shouldn't make any difference
>
> So now the leftovers...
>
> > diff --git a/arch/arm/mach-imx/devices/devices.c b/arch/arm/mach-imx/devices/devices.c
> > index 1b4366a..48c3817 100644
> > --- a/arch/arm/mach-imx/devices/devices.c
> > +++ b/arch/arm/mach-imx/devices/devices.c
> > @@ -24,12 +24,12 @@
> >
> > struct device mxc_aips_bus = {
> > .init_name = "mxc_aips",
> > - .parent = &platform_bus,
> > + .parent = &platform_bus.dev,
> > };
> >
> > struct device mxc_ahb_bus = {
> > .init_name = "mxc_ahb",
> > - .parent = &platform_bus,
> > + .parent = &platform_bus.dev,
> > };
> >
> > int __init mxc_device_init(void)
>
> Seems that the author meant to have those two bus devices hanging from
> the platform_bus in device hierarchy. Seems fair enough to me.
No, not at all, this is a different bus, put the root bus at the root of
the sysfs tree, not at some "arbritrary" point on a platform device.
> > diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
> > index bd37747..4e4b7a2 100644
> > --- a/drivers/char/tile-srom.c
> > +++ b/drivers/char/tile-srom.c
> > @@ -350,7 +350,7 @@ static int srom_setup_minor(struct srom_dev *srom, int index)
> > SROM_PAGE_SIZE_OFF, sizeof(srom->page_size)) < 0)
> > return -EIO;
> >
> > - dev = device_create(srom_class, &platform_bus,
> > + dev = device_create(srom_class, &platform_bus.dev,
> > MKDEV(srom_major, index), srom, "%d", index);
> > return PTR_ERR_OR_ZERO(dev);
> > }
>
> Again, non-platform device placed in the hierarchy.
Again, not ok. If it's a platform device, it's a platform device, and
make it one. If it isn't, like this one, make it a virtual device and
pass NULL here.
> > diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
> > index 7e834fb..9a2b0d0 100644
> > --- a/drivers/mmc/host/sdhci-pltfm.c
> > +++ b/drivers/mmc/host/sdhci-pltfm.c
> > @@ -137,7 +137,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
> > dev_err(&pdev->dev, "Invalid iomem size!\n");
> >
> > /* Some PCI-based MFD need the parent here */
> > - if (pdev->dev.parent != &platform_bus && !np)
> > + if (pdev->dev.parent != &platform_bus.dev && !np)
> > host = sdhci_alloc_host(pdev->dev.parent,
> > sizeof(struct sdhci_pltfm_host) + priv_size);
> > else
>
> Special treatment for non-platform devices.
Ugh, why should you care? I don't understand the logic here.
> > diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
> > index 3cbb57a..c14c36f 100644
> > --- a/drivers/scsi/hosts.c
> > +++ b/drivers/scsi/hosts.c
> > @@ -218,7 +218,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
> > goto fail;
> >
> > if (!shost->shost_gendev.parent)
> > - shost->shost_gendev.parent = dev ? dev : &platform_bus;
> > + shost->shost_gendev.parent = dev ? dev : &platform_bus.dev;
> > if (!dma_dev)
> > dma_dev = shost->shost_gendev.parent;
> >
>
> shost_gendev is a generic (as in struct device, non-platform one)
> device, that is being explicitly placed in the hierarchy.
Then make it a virtual device, as that's what it is, replace this with
NULL.
> So it makes it 4, not 3 ;-) places where referencing platform_bus
> *maybe* makes some sense.
Nope, see above :)
thanks,
greg k-h
^ permalink raw reply
* [PATCH v2] iio: exynos-adc: add experimental touchscreen support
From: Dmitry Torokhov @ 2014-07-22 18:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5068889.1KfVx3ksNo@wuerfel>
On Tue, Jul 22, 2014 at 03:03:12PM +0200, Arnd Bergmann wrote:
> This adds support for the touchscreen on Samsung s3c64xx.
> The driver is completely untested but shows roughly how
> it could be done, following the example of the at91 driver.
>
> Open questions include:
>
> - compared to the old plat-samsung/adc driver, there is
> no support for prioritizing ts over other clients, nor
> for oversampling. From my reading of the code, the
> priorities didn't actually have any effect at all, but
> the oversampling might be needed. Maybe the original
> authors have some insight.
>
> - We probably need to add support for platform_data as well,
> I've skipped this so far.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> This should address all previous comments, and I've also added
> a write to ADC_V1_DLY() as the old driver does.
>
> diff --git a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
> index cad81b666a67..ba30836c73cb 100644
> --- a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
> +++ b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
> @@ -43,6 +43,10 @@ Required properties:
> and compatible ADC block)
> - vdd-supply VDD input supply.
>
> +Optional properties:
> +- has-touchscreen: If present, indicates that a touchscreen is
> + connected an usable.
> +
> Note: child nodes can be added for auto probing from device tree.
>
> Example: adding device info in dtsi file
> diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
> index 420c5cda09c3..3b684a117b9c 100644
> --- a/drivers/iio/adc/exynos_adc.c
> +++ b/drivers/iio/adc/exynos_adc.c
> @@ -34,6 +34,7 @@
> #include <linux/regulator/consumer.h>
> #include <linux/of_platform.h>
> #include <linux/err.h>
> +#include <linux/input.h>
>
> #include <linux/iio/iio.h>
> #include <linux/iio/machine.h>
> @@ -66,6 +67,9 @@
>
> #define ADC_S3C2410_CON_SELMUX(x) (((x)&0x7)<<3)
>
> +/* touch screen always uses channel 0 */
> +#define ADC_S3C2410_MUX_TS 0
> +
> /* ADCTSC Register Bits */
> #define ADC_S3C2443_TSC_UD_SEN (1u << 8)
> #define ADC_S3C2410_TSC_YM_SEN (1u << 7)
> @@ -103,24 +107,32 @@
>
> /* Bit definitions common for ADC_V1 and ADC_V2 */
> #define ADC_CON_EN_START (1u << 0)
> +#define ADC_DATX_PRESSED (1u << 15)
> #define ADC_DATX_MASK 0xFFF
> +#define ADC_DATY_MASK 0xFFF
>
> #define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100))
>
> struct exynos_adc {
> struct exynos_adc_data *data;
> struct device *dev;
> + struct input_dev *input;
> void __iomem *regs;
> void __iomem *enable_reg;
> struct clk *clk;
> struct clk *sclk;
> unsigned int irq;
> + unsigned int tsirq;
> struct regulator *vdd;
>
> struct completion completion;
>
> u32 value;
> unsigned int version;
> +
> + bool read_ts;
> + u32 ts_x;
> + u32 ts_y;
> };
>
> struct exynos_adc_data {
> @@ -205,6 +217,9 @@ static void exynos_adc_v1_init_hw(struct exynos_adc *info)
> /* Enable 12-bit ADC resolution */
> con1 |= ADC_V1_CON_RES;
> writel(con1, ADC_V1_CON(info->regs));
> +
> + /* set default touchscreen delay */
> + writel(10000, ADC_V1_DLY(info->regs));
> }
>
> static void exynos_adc_v1_exit_hw(struct exynos_adc *info)
> @@ -390,12 +405,54 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
> return ret;
> }
>
> +static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y)
> +{
> + struct exynos_adc *info = iio_priv(indio_dev);
> + unsigned long timeout;
> + int ret;
> +
> + mutex_lock(&indio_dev->mlock);
> + info->read_ts = true;
> +
> + reinit_completion(&info->completion);
> +
> + writel(ADC_S3C2410_TSC_PULL_UP_DISABLE | ADC_TSC_AUTOPST,
> + ADC_V1_TSC(info->regs));
> +
> + /* Select the ts channel to be used and Trigger conversion */
> + info->data->start_conv(info, ADC_S3C2410_MUX_TS);
> +
> + timeout = wait_for_completion_timeout
> + (&info->completion, EXYNOS_ADC_TIMEOUT);
> + if (timeout == 0) {
> + dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n");
> + if (info->data->init_hw)
> + info->data->init_hw(info);
> + ret = -ETIMEDOUT;
> + } else {
> + *x = info->ts_x;
> + *y = info->ts_y;
> + ret = 0;
> + }
> +
> + info->read_ts = false;
> + mutex_unlock(&indio_dev->mlock);
> +
> + return ret;
> +}
> +
> static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
> {
> struct exynos_adc *info = (struct exynos_adc *)dev_id;
>
> /* Read value */
> - info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
> + if (info->read_ts) {
> + info->ts_x = readl(ADC_V1_DATX(info->regs));
> + info->ts_y = readl(ADC_V1_DATY(info->regs));
> + writel(ADC_TSC_WAIT4INT | ADC_S3C2443_TSC_UD_SEN, ADC_V1_TSC(info->regs));
> + } else {
> + info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
> + }
>
> /* clear irq */
> if (info->data->clear_irq)
> @@ -406,6 +463,46 @@ static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> +/*
> + * Here we (ab)use a threaded interrupt handler to stay running
> + * for as long as the touchscreen remains pressed, we report
> + * a new event with the latest data and then sleep until the
> + * next timer tick. This mirrors the behavior of the old
> + * driver, with much less code.
> + */
> +static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
> +{
> + struct exynos_adc *info = dev_id;
> + struct iio_dev *dev = dev_get_drvdata(info->dev);
> + u32 x, y;
> + bool pressed;
> + int ret;
> +
> + while (info->input->users) {
> + ret = exynos_read_s3c64xx_ts(dev, &x, &y);
> + if (ret == -ETIMEDOUT)
> + break;
> +
> + pressed = x & y & ADC_DATX_PRESSED;
> + if (!pressed) {
> + input_report_key(info->input, BTN_TOUCH, 0);
> + input_sync(info->input);
> + break;
> + }
> +
> + input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK);
> + input_report_abs(info->input, ABS_Y, y & ADC_DATY_MASK);
> + input_report_key(info->input, BTN_TOUCH, 1);
> + input_sync(info->input);
> +
> + msleep(1);
> + };
> +
> + writel(0, ADC_V1_CLRINTPNDNUP(info->regs));
> +
> + return IRQ_HANDLED;
> +}
> +
> static int exynos_adc_reg_access(struct iio_dev *indio_dev,
> unsigned reg, unsigned writeval,
> unsigned *readval)
> @@ -457,12 +554,66 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
> return 0;
> }
>
> +static int exynos_adc_ts_open(struct input_dev *dev)
> +{
> + struct exynos_adc *info = input_get_drvdata(dev);
> +
> + enable_irq(info->tsirq);
> +
> + return 0;
> +}
> +
> +static void exynos_adc_ts_close(struct input_dev *dev)
> +{
> + struct exynos_adc *info = input_get_drvdata(dev);
> +
> + disable_irq(info->tsirq);
> +}
> +
> +static int exynos_adc_ts_init(struct exynos_adc *info)
> +{
> + int ret;
> +
> + if (info->tsirq <= 0)
> + return -ENODEV;
> +
> + info->input = input_allocate_device();
> + if (!info->input)
> + return -ENOMEM;
> +
> + info->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> + info->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> +
> + input_set_abs_params(info->input, ABS_X, 0, 0x3FF, 0, 0);
> + input_set_abs_params(info->input, ABS_Y, 0, 0x3FF, 0, 0);
> +
> + info->input->name = "S3C24xx TouchScreen";
> + info->input->id.bustype = BUS_HOST;
> + info->input->open = exynos_adc_ts_open;
> + info->input->close = exynos_adc_ts_close;
> +
> + input_set_drvdata(info->input, info);
> +
> + ret = input_register_device(info->input);
> + if (ret)
> + input_free_device(info->input);
> +
> + disable_irq(info->tsirq);
> + ret = request_threaded_irq(info->tsirq, NULL, exynos_ts_isr,
> + 0, "touchscreen", info);
> + if (ret)
> + input_unregister_device(info->input);
> +
> + return ret;
> +}
> +
> static int exynos_adc_probe(struct platform_device *pdev)
> {
> struct exynos_adc *info = NULL;
> struct device_node *np = pdev->dev.of_node;
> struct iio_dev *indio_dev = NULL;
> struct resource *mem;
> + bool has_ts = false;
> int ret = -ENODEV;
> int irq;
>
> @@ -498,8 +649,14 @@ static int exynos_adc_probe(struct platform_device *pdev)
> dev_err(&pdev->dev, "no irq resource?\n");
> return irq;
> }
> -
> info->irq = irq;
> +
> + irq = platform_get_irq(pdev, 1);
> + if (irq == -EPROBE_DEFER)
> + return irq;
> +
> + info->tsirq = irq;
> +
> info->dev = &pdev->dev;
>
> init_completion(&info->completion);
> @@ -565,6 +722,15 @@ static int exynos_adc_probe(struct platform_device *pdev)
> if (info->data->init_hw)
> info->data->init_hw(info);
>
> + /* leave out any TS related code if unreachable */
> + if (IS_BUILTIN(CONFIG_INPUT) ||
> + (IS_MODULE(CONFIG_INPUT) && config_enabled(MODULE)))
This is ugly... We need IS_SUBSYSTEM_AVAILABLE() wrapper for this...
Anyway,
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> + has_ts = of_property_read_bool(pdev->dev.of_node, "has-touchscreen");
> + if (has_ts)
> + ret = exynos_adc_ts_init(info);
> + if (ret)
> + goto err_iio;
> +
> ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev);
> if (ret < 0) {
> dev_err(&pdev->dev, "failed adding child nodes\n");
> @@ -576,6 +742,11 @@ static int exynos_adc_probe(struct platform_device *pdev)
> err_of_populate:
> device_for_each_child(&indio_dev->dev, NULL,
> exynos_adc_remove_devices);
> + if (has_ts) {
> + input_unregister_device(info->input);
> + free_irq(info->tsirq, info);
> + }
> +err_iio:
> iio_device_unregister(indio_dev);
> err_irq:
> free_irq(info->irq, info);
> @@ -595,6 +766,11 @@ static int exynos_adc_remove(struct platform_device *pdev)
> struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> struct exynos_adc *info = iio_priv(indio_dev);
>
> + if (IS_BUILTIN(CONFIG_INPUT) ||
> + (IS_MODULE(CONFIG_INPUT) && config_enabled(MODULE))) {
> + free_irq(info->tsirq, info);
> + input_unregister_device(info->input);
> + }
> device_for_each_child(&indio_dev->dev, NULL,
> exynos_adc_remove_devices);
> iio_device_unregister(indio_dev);
>
--
Dmitry
^ permalink raw reply
* [PATCHv4 5/5] arm64: Add atomic pool for non-coherent and CMA allocations.
From: Arnd Bergmann @ 2014-07-22 18:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1404324218-4743-6-git-send-email-lauraa@codeaurora.org>
On Wednesday 02 July 2014, Laura Abbott wrote:
> + pgprot_t prot = __pgprot(PROT_NORMAL_NC);
> + unsigned long nr_pages = atomic_pool_size >> PAGE_SHIFT;
> + struct page *page;
> + void *addr;
> +
> +
> + if (dev_get_cma_area(NULL))
> + page = dma_alloc_from_contiguous(NULL, nr_pages,
> + get_order(atomic_pool_size));
> + else
> + page = alloc_pages(GFP_KERNEL, get_order(atomic_pool_size));
> +
> +
> + if (page) {
> + int ret;
> +
> + atomic_pool = gen_pool_create(PAGE_SHIFT, -1);
> + if (!atomic_pool)
> + goto free_page;
> +
> + addr = dma_common_contiguous_remap(page, atomic_pool_size,
> + VM_USERMAP, prot, atomic_pool_init);
> +
I just stumbled over this thread and noticed the code here: When you do
alloc_pages() above, you actually get pages that are already mapped into
the linear kernel mapping as cacheable pages. Your new
dma_common_contiguous_remap tries to map them as noncacheable. This
seems broken because it allows the CPU to treat both mappings as
cacheable, and that won't be coherent with device DMA.
> + if (!addr)
> + goto destroy_genpool;
> +
> + memset(addr, 0, atomic_pool_size);
> + __dma_flush_range(addr, addr + atomic_pool_size);
It also seems weird to flush the cache on a virtual address of
an uncacheable mapping. Is that well-defined? In the CMA case, the
original mapping should already be uncached here, so you don't need
to flush it. In the alloc_pages() case, I think you need to unmap
the pages from the linear mapping instead.
Arnd
^ permalink raw reply
* [PATCH] ARM: multi_v7_defconfig: major refresh
From: Olof Johansson @ 2014-07-22 18:01 UTC (permalink / raw)
To: linux-arm-kernel
This is a major refresh of the multi_v7_defconfig:
- Bring over a bunch of Samsung drivers to make ODROID-U3 and Chromebooks usable
* Enable big.LITTLE
* MCPM
* CYAPA touchpad
* Samsung-related MTD/regulator/clk/pinmux drivers
* Add some of the CrOS EC drivers
- Turn on TPM, HW_RANDOM
- OMAP_USB3 -> TI_PIPE3 option rename
- Enable MCPM/b.L for VEXPRESS
- Add new CONFIG_MTD_SPI_NOR since it otherwise masks off SPI NOR drivers
- CONFIG_LOGO, because penguins.
I took care to keep the new options that have been added for whose the
drivers are not yet in our for-next branch. This was pretty awkward so
we should sort out how to handle those better in the future.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
arch/arm/configs/multi_v7_defconfig | 74 +++++++++++++++++++++++++++--------
1 file changed, 58 insertions(+), 16 deletions(-)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 16518a7..c7654cf 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -50,6 +50,7 @@ CONFIG_MACH_SPEAR1310=y
CONFIG_MACH_SPEAR1340=y
CONFIG_ARCH_STI=y
CONFIG_ARCH_EXYNOS=y
+CONFIG_EXYNOS5420_MCPM=y
CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_SIRF=y
CONFIG_ARCH_TEGRA=y
@@ -57,21 +58,23 @@ CONFIG_ARCH_TEGRA_2x_SOC=y
CONFIG_ARCH_TEGRA_3x_SOC=y
CONFIG_ARCH_TEGRA_114_SOC=y
CONFIG_ARCH_TEGRA_124_SOC=y
-CONFIG_TEGRA_EMC_SCALING_ENABLE=y
CONFIG_ARCH_U8500=y
CONFIG_MACH_HREFV60=y
CONFIG_MACH_SNOWBALL=y
-CONFIG_MACH_UX500_DT=y
CONFIG_ARCH_VEXPRESS=y
CONFIG_ARCH_VEXPRESS_CA9X4=y
+CONFIG_ARCH_VEXPRESS_DCSCB=y
+CONFIG_ARCH_VEXPRESS_TC2_PM=y
CONFIG_ARCH_WM8850=y
CONFIG_ARCH_ZYNQ=y
-CONFIG_TRUSTED_FOUNDATIONS=y
CONFIG_PCI=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MVEBU=y
CONFIG_PCI_TEGRA=y
CONFIG_SMP=y
+CONFIG_BIG_LITTLE=y
+CONFIG_BL_SWITCHER=y
+CONFIG_BL_SWITCHER_DUMMY_IF=y
CONFIG_NR_CPUS=8
CONFIG_HIGHPTE=y
CONFIG_CMA=y
@@ -81,8 +84,10 @@ CONFIG_KEXEC=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT_DETAILS=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_ARM_BIG_LITTLE_CPUFREQ=y
+CONFIG_ARM_DT_BL_CPUFREQ=y
+CONFIG_ARM_VEXPRESS_SPC_CPUFREQ=y
CONFIG_CPU_IDLE=y
-CONFIG_NEON=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -100,14 +105,12 @@ CONFIG_IPV6_MIP6=m
CONFIG_IPV6_TUNNEL=m
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_CAN=y
-CONFIG_CAN_RAW=y
-CONFIG_CAN_BCM=y
-CONFIG_CAN_DEV=y
CONFIG_CAN_MCP251X=y
CONFIG_CFG80211=m
CONFIG_MAC80211=m
CONFIG_RFKILL=y
CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_REGULATOR=y
CONFIG_RFKILL_GPIO=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
@@ -116,6 +119,7 @@ CONFIG_CMA_SIZE_MBYTES=64
CONFIG_OMAP_OCP2SCP=y
CONFIG_MTD=y
CONFIG_MTD_M25P80=y
+CONFIG_MTD_SPI_NOR=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_ICS932S401=y
CONFIG_APDS9802ALS=y
@@ -156,10 +160,11 @@ CONFIG_RT2800USB=m
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_TEGRA=y
-CONFIG_KEYBOARD_SPEAR=y
CONFIG_KEYBOARD_ST_KEYSCAN=y
+CONFIG_KEYBOARD_SPEAR=y
CONFIG_KEYBOARD_CROS_EC=y
CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_MOUSE_CYAPA=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_STMPE=y
CONFIG_INPUT_MISC=y
@@ -190,8 +195,15 @@ CONFIG_SERIAL_FSL_LPUART=y
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
CONFIG_SERIAL_ST_ASC=y
CONFIG_SERIAL_ST_ASC_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_OMAP=m
+CONFIG_HW_RANDOM_OMAP3_ROM=m
+CONFIG_HW_RANDOM_EXYNOS=m
+CONFIG_HW_RANDOM_MSM=m
+CONFIG_TCG_TPM=y
+CONFIG_TCG_TIS_I2C_INFINEON=y
CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MUX=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_MUX_PINCTRL=y
CONFIG_I2C_CADENCE=y
@@ -199,12 +211,14 @@ CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_I2C_EXYNOS5=y
CONFIG_I2C_MV64XXX=y
CONFIG_I2C_SIRF=y
-CONFIG_I2C_TEGRA=y
CONFIG_I2C_ST=y
+CONFIG_I2C_TEGRA=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
CONFIG_SPI=y
CONFIG_SPI_OMAP24XX=y
CONFIG_SPI_ORION=y
CONFIG_SPI_PL022=y
+CONFIG_SPI_S3C64XX=y
CONFIG_SPI_SIRF=y
CONFIG_SPI_SUN4I=y
CONFIG_SPI_SUN6I=y
@@ -214,7 +228,6 @@ CONFIG_SPI_TEGRA20_SLINK=y
CONFIG_PINCTRL_AS3722=y
CONFIG_PINCTRL_PALMAS=y
CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_GENERIC_PLATFORM=y
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
@@ -233,14 +246,20 @@ CONFIG_THERMAL=y
CONFIG_ARMADA_THERMAL=y
CONFIG_ST_THERMAL_SYSCFG=y
CONFIG_ST_THERMAL_MEMMAP=y
+CONFIG_EXYNOS_THERMAL=y
+CONFIG_EXYNOS_THERMAL_CORE=y
CONFIG_WATCHDOG=y
+CONFIG_S3C2410_WATCHDOG=y
CONFIG_ORION_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=y
CONFIG_MFD_AS3722=y
CONFIG_MFD_BCM590XX=y
CONFIG_MFD_CROS_EC=y
+CONFIG_MFD_CROS_EC_I2C=y
CONFIG_MFD_CROS_EC_SPI=y
+CONFIG_MFD_MAX77686=y
CONFIG_MFD_MAX8907=y
+CONFIG_MFD_MAX8997=y
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_STMPE=y
CONFIG_MFD_PALMAS=y
@@ -253,6 +272,8 @@ CONFIG_REGULATOR_AS3722=y
CONFIG_REGULATOR_BCM590XX=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_MAX8907=y
+CONFIG_REGULATOR_MAX8997=y
+CONFIG_REGULATOR_MAX77686=y
CONFIG_REGULATOR_PALMAS=y
CONFIG_REGULATOR_S2MPS11=y
CONFIG_REGULATOR_S5M8767=y
@@ -274,13 +295,17 @@ CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_FB_ARMCLCD=y
CONFIG_FB_WM8505=y
CONFIG_FB_SIMPLE=y
+CONFIG_EXYNOS_VIDEO=y
+CONFIG_EXYNOS_MIPI_DSI=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_PWM=y
CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_SND_SOC_SNOW=y
CONFIG_SND_SOC_TEGRA=y
CONFIG_SND_SOC_TEGRA_RT5640=y
CONFIG_SND_SOC_TEGRA_WM8753=y
@@ -293,15 +318,19 @@ CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_MVEBU=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_EHCI_EXYNOS=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_ISP1760_HCD=y
CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_HSIC_USB3503=y
CONFIG_AB8500_USB=y
-CONFIG_OMAP_USB3=y
+CONFIG_TI_PIPE3=y
CONFIG_SAMSUNG_USB2PHY=y
CONFIG_SAMSUNG_USB3PHY=y
CONFIG_USB_GPIO_VBUS=y
@@ -316,18 +345,19 @@ CONFIG_MMC_SDHCI_OF_ARASAN=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_MMC_SDHCI_DOVE=y
CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_MMC_SDHCI_S3C=y
CONFIG_MMC_SDHCI_PXAV3=y
CONFIG_MMC_SDHCI_SPEAR=y
-CONFIG_MMC_SDHCI_S3C=y
CONFIG_MMC_SDHCI_S3C_DMA=y
CONFIG_MMC_SDHCI_BCM_KONA=y
CONFIG_MMC_SDHCI_ST=y
CONFIG_MMC_OMAP=y
CONFIG_MMC_OMAP_HS=y
CONFIG_MMC_MVSDIO=y
-CONFIG_MMC_SUNXI=y
CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
CONFIG_MMC_DW_EXYNOS=y
+CONFIG_MMC_SUNXI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_PWM=y
@@ -339,11 +369,14 @@ CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AS3722=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_MAX8907=y
+CONFIG_RTC_DRV_MAX77686=y
CONFIG_RTC_DRV_PALMAS=y
CONFIG_RTC_DRV_TWL4030=y
CONFIG_RTC_DRV_TPS6586X=y
CONFIG_RTC_DRV_TPS65910=y
CONFIG_RTC_DRV_EM3027=y
+CONFIG_RTC_DRV_S5M=y
+CONFIG_RTC_DRV_S3C=y
CONFIG_RTC_DRV_PL031=y
CONFIG_RTC_DRV_VT8500=y
CONFIG_RTC_DRV_SUNXI=y
@@ -369,21 +402,31 @@ CONFIG_KEYBOARD_NVEC=y
CONFIG_SERIO_NVEC_PS2=y
CONFIG_NVEC_POWER=y
CONFIG_QCOM_GSBI=y
+CONFIG_COMMON_CLK_MAX77686=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_MSM_GCC_8660=y
CONFIG_MSM_MMCC_8960=y
CONFIG_MSM_MMCC_8974=y
CONFIG_TEGRA_IOMMU_GART=y
CONFIG_TEGRA_IOMMU_SMMU=y
+CONFIG_EXYNOS_IOMMU=y
CONFIG_MEMORY=y
CONFIG_IIO=y
+CONFIG_EXYNOS_ADC=y
CONFIG_AK8975=y
CONFIG_PWM=y
+CONFIG_PWM_SAMSUNG=y
CONFIG_PWM_TEGRA=y
CONFIG_PWM_VT8500=y
CONFIG_OMAP_USB2=y
CONFIG_PHY_MIPHY365X=y
+CONFIG_PHY_EXYNOS5250_SATA=y
CONFIG_PHY_SUN4I_USB=y
+CONFIG_PHY_SAMSUNG_USB2=y
+CONFIG_PHY_EXYNOS4210_USB2=y
+CONFIG_PHY_EXYNOS4X12_USB2=y
+CONFIG_PHY_EXYNOS5250_USB2=y
+CONFIG_PHY_EXYNOS5_USBDRD=y
CONFIG_EXT4_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
@@ -398,4 +441,3 @@ CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_LOCKUP_DETECTOR=y
-CONFIG_CRYPTO_DEV_TEGRA_AES=y
--
1.7.10.4
^ permalink raw reply related
* [PATCH v3] platform: Make platform_bus device a platform device
From: Pawel Moll @ 2014-07-22 18:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1406051719-17354-1-git-send-email-pawel.moll@arm.com>
On Tue, 2014-07-22 at 18:55 +0100, Pawel Moll wrote:
> * replaced references to platform_bus.dev with NULL
> in places where it shouldn't make any difference
So now the leftovers...
> diff --git a/arch/arm/mach-imx/devices/devices.c b/arch/arm/mach-imx/devices/devices.c
> index 1b4366a..48c3817 100644
> --- a/arch/arm/mach-imx/devices/devices.c
> +++ b/arch/arm/mach-imx/devices/devices.c
> @@ -24,12 +24,12 @@
>
> struct device mxc_aips_bus = {
> .init_name = "mxc_aips",
> - .parent = &platform_bus,
> + .parent = &platform_bus.dev,
> };
>
> struct device mxc_ahb_bus = {
> .init_name = "mxc_ahb",
> - .parent = &platform_bus,
> + .parent = &platform_bus.dev,
> };
>
> int __init mxc_device_init(void)
Seems that the author meant to have those two bus devices hanging from
the platform_bus in device hierarchy. Seems fair enough to me.
> diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
> index bd37747..4e4b7a2 100644
> --- a/drivers/char/tile-srom.c
> +++ b/drivers/char/tile-srom.c
> @@ -350,7 +350,7 @@ static int srom_setup_minor(struct srom_dev *srom, int index)
> SROM_PAGE_SIZE_OFF, sizeof(srom->page_size)) < 0)
> return -EIO;
>
> - dev = device_create(srom_class, &platform_bus,
> + dev = device_create(srom_class, &platform_bus.dev,
> MKDEV(srom_major, index), srom, "%d", index);
> return PTR_ERR_OR_ZERO(dev);
> }
Again, non-platform device placed in the hierarchy.
> diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
> index 7e834fb..9a2b0d0 100644
> --- a/drivers/mmc/host/sdhci-pltfm.c
> +++ b/drivers/mmc/host/sdhci-pltfm.c
> @@ -137,7 +137,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
> dev_err(&pdev->dev, "Invalid iomem size!\n");
>
> /* Some PCI-based MFD need the parent here */
> - if (pdev->dev.parent != &platform_bus && !np)
> + if (pdev->dev.parent != &platform_bus.dev && !np)
> host = sdhci_alloc_host(pdev->dev.parent,
> sizeof(struct sdhci_pltfm_host) + priv_size);
> else
Special treatment for non-platform devices.
> diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
> index 3cbb57a..c14c36f 100644
> --- a/drivers/scsi/hosts.c
> +++ b/drivers/scsi/hosts.c
> @@ -218,7 +218,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
> goto fail;
>
> if (!shost->shost_gendev.parent)
> - shost->shost_gendev.parent = dev ? dev : &platform_bus;
> + shost->shost_gendev.parent = dev ? dev : &platform_bus.dev;
> if (!dma_dev)
> dma_dev = shost->shost_gendev.parent;
>
shost_gendev is a generic (as in struct device, non-platform one)
device, that is being explicitly placed in the hierarchy.
So it makes it 4, not 3 ;-) places where referencing platform_bus
*maybe* makes some sense.
Pawel
^ permalink raw reply
* [PATCH v3] platform: Make platform_bus device a platform device
From: Pawel Moll @ 2014-07-22 17:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140722173713.GA8959@kroah.com>
... describing the root of the device tree, so one can write
a platform driver initializing the platform.
There has been a lot of references to platform_bus device where
it didn't make any sense, because simply using NULL as a parent
will make the device be adopted by the top level anyway.
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
Changes since v2:
* replaced references to platform_bus.dev with NULL
in places where it shouldn't make any difference
Changes since v1:
* rebased on top of v3.16-rc6
* fixed up all new explicit references to platform_bus,
with majority in mach-shmobile; 99% of them seem completely
useless and I was *very* tempted to replace them with
NULL - all reasons for and against this are welcomed
arch/arm/mach-bcm/board_bcm21664.c | 3 +--
arch/arm/mach-bcm/board_bcm281xx.c | 3 +--
arch/arm/mach-clps711x/board-edb7211.c | 6 +++---
arch/arm/mach-clps711x/board-p720t.c | 6 +++---
arch/arm/mach-imx/devices/devices.c | 4 ++--
arch/arm/mach-imx/mach-mx27ads.c | 2 +-
arch/arm/mach-shmobile/board-ape6evm.c | 14 +++++++-------
arch/arm/mach-shmobile/board-bockw.c | 19 ++++++++----------
arch/arm/mach-shmobile/board-genmai.c | 5 ++---
arch/arm/mach-shmobile/board-koelsch.c | 26 ++++++++++++-------------
arch/arm/mach-shmobile/board-lager.c | 34 ++++++++++++++-------------------
arch/arm/mach-shmobile/board-marzen.c | 1 -
arch/arm/mach-shmobile/setup-r7s72100.c | 2 +-
arch/arm/mach-shmobile/setup-r8a73a4.c | 8 ++++----
arch/arm/mach-shmobile/setup-r8a7778.c | 13 ++++++-------
arch/arm/mach-shmobile/setup-r8a7779.c | 6 +++---
arch/arm/mach-shmobile/setup-r8a7790.c | 10 +++++-----
arch/arm/mach-shmobile/setup-r8a7791.c | 8 ++++----
arch/unicore32/kernel/puv3-core.c | 2 +-
arch/unicore32/kernel/puv3-nb0916.c | 6 +++---
drivers/base/platform.c | 18 +++++++++++------
drivers/char/tile-srom.c | 2 +-
drivers/mmc/host/sdhci-pltfm.c | 2 +-
drivers/scsi/hosts.c | 2 +-
include/linux/platform_device.h | 2 +-
25 files changed, 97 insertions(+), 107 deletions(-)
diff --git a/arch/arm/mach-bcm/board_bcm21664.c b/arch/arm/mach-bcm/board_bcm21664.c
index f0521cc..82ad568 100644
--- a/arch/arm/mach-bcm/board_bcm21664.c
+++ b/arch/arm/mach-bcm/board_bcm21664.c
@@ -60,8 +60,7 @@ static void bcm21664_restart(enum reboot_mode mode, const char *cmd)
static void __init bcm21664_init(void)
{
- of_platform_populate(NULL, of_default_bus_match_table, NULL,
- &platform_bus);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
kona_l2_cache_init();
}
diff --git a/arch/arm/mach-bcm/board_bcm281xx.c b/arch/arm/mach-bcm/board_bcm281xx.c
index 1ac59fc..2e367bd 100644
--- a/arch/arm/mach-bcm/board_bcm281xx.c
+++ b/arch/arm/mach-bcm/board_bcm281xx.c
@@ -58,8 +58,7 @@ static void bcm281xx_restart(enum reboot_mode mode, const char *cmd)
static void __init bcm281xx_init(void)
{
- of_platform_populate(NULL, of_default_bus_match_table, NULL,
- &platform_bus);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
kona_l2_cache_init();
}
diff --git a/arch/arm/mach-clps711x/board-edb7211.c b/arch/arm/mach-clps711x/board-edb7211.c
index f9828f8..6144fb5 100644
--- a/arch/arm/mach-clps711x/board-edb7211.c
+++ b/arch/arm/mach-clps711x/board-edb7211.c
@@ -158,16 +158,16 @@ static void __init edb7211_init_late(void)
gpio_request_array(edb7211_gpios, ARRAY_SIZE(edb7211_gpios));
platform_device_register(&edb7211_flash_pdev);
- platform_device_register_data(&platform_bus, "platform-lcd", 0,
+ platform_device_register_data(NULL, "platform-lcd", 0,
&edb7211_lcd_power_pdata,
sizeof(edb7211_lcd_power_pdata));
- platform_device_register_data(&platform_bus, "generic-bl", 0,
+ platform_device_register_data(NULL, "generic-bl", 0,
&edb7211_lcd_backlight_pdata,
sizeof(edb7211_lcd_backlight_pdata));
platform_device_register_simple("video-clps711x", 0, NULL, 0);
platform_device_register_simple("cs89x0", 0, edb7211_cs8900_resource,
ARRAY_SIZE(edb7211_cs8900_resource));
- platform_device_register_data(&platform_bus, "i2c-gpio", 0,
+ platform_device_register_data(NULL, "i2c-gpio", 0,
&edb7211_i2c_pdata,
sizeof(edb7211_i2c_pdata));
}
diff --git a/arch/arm/mach-clps711x/board-p720t.c b/arch/arm/mach-clps711x/board-p720t.c
index 0cf0e51..96bcc76 100644
--- a/arch/arm/mach-clps711x/board-p720t.c
+++ b/arch/arm/mach-clps711x/board-p720t.c
@@ -348,14 +348,14 @@ static void __init p720t_init_late(void)
{
WARN_ON(gpio_request_array(p720t_gpios, ARRAY_SIZE(p720t_gpios)));
- platform_device_register_data(&platform_bus, "platform-lcd", 0,
+ platform_device_register_data(NULL, "platform-lcd", 0,
&p720t_lcd_power_pdata,
sizeof(p720t_lcd_power_pdata));
- platform_device_register_data(&platform_bus, "generic-bl", 0,
+ platform_device_register_data(NULL, "generic-bl", 0,
&p720t_lcd_backlight_pdata,
sizeof(p720t_lcd_backlight_pdata));
platform_device_register_simple("video-clps711x", 0, NULL, 0);
- platform_device_register_data(&platform_bus, "leds-gpio", 0,
+ platform_device_register_data(NULL, "leds-gpio", 0,
&p720t_gpio_led_pdata,
sizeof(p720t_gpio_led_pdata));
}
diff --git a/arch/arm/mach-imx/devices/devices.c b/arch/arm/mach-imx/devices/devices.c
index 1b4366a..48c3817 100644
--- a/arch/arm/mach-imx/devices/devices.c
+++ b/arch/arm/mach-imx/devices/devices.c
@@ -24,12 +24,12 @@
struct device mxc_aips_bus = {
.init_name = "mxc_aips",
- .parent = &platform_bus,
+ .parent = &platform_bus.dev,
};
struct device mxc_ahb_bus = {
.init_name = "mxc_ahb",
- .parent = &platform_bus,
+ .parent = &platform_bus.dev,
};
int __init mxc_device_init(void)
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 2f834ce..eb1c347 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -245,7 +245,7 @@ static void __init mx27ads_regulator_init(void)
vchip->set = vgpio_set;
gpiochip_add(vchip);
- platform_device_register_data(&platform_bus, "reg-fixed-voltage",
+ platform_device_register_data(NULL, "reg-fixed-voltage",
PLATFORM_DEVID_AUTO,
&mx27ads_lcd_regulator_pdata,
sizeof(mx27ads_lcd_regulator_pdata));
diff --git a/arch/arm/mach-shmobile/board-ape6evm.c b/arch/arm/mach-shmobile/board-ape6evm.c
index fe071a9..7ab99a4 100644
--- a/arch/arm/mach-shmobile/board-ape6evm.c
+++ b/arch/arm/mach-shmobile/board-ape6evm.c
@@ -248,29 +248,29 @@ static void __init ape6evm_add_standard_devices(void)
regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
- platform_device_register_resndata(&platform_bus, "smsc911x", -1,
+ platform_device_register_resndata(NULL, "smsc911x", -1,
lan9220_res, ARRAY_SIZE(lan9220_res),
&lan9220_data, sizeof(lan9220_data));
regulator_register_always_on(1, "MMC0 Vcc", vcc_mmc0_consumers,
ARRAY_SIZE(vcc_mmc0_consumers), 2800000);
- platform_device_register_resndata(&platform_bus, "sh_mmcif", 0,
+ platform_device_register_resndata(NULL, "sh_mmcif", 0,
mmcif0_resources, ARRAY_SIZE(mmcif0_resources),
&mmcif0_pdata, sizeof(mmcif0_pdata));
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", 2,
+ platform_device_register_data(NULL, "reg-fixed-voltage", 2,
&vcc_sdhi0_info, sizeof(vcc_sdhi0_info));
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_pdata, sizeof(sdhi0_pdata));
regulator_register_always_on(3, "SDHI1 Vcc", vcc_sdhi1_consumers,
ARRAY_SIZE(vcc_sdhi1_consumers), 3300000);
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 1,
sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
&sdhi1_pdata, sizeof(sdhi1_pdata));
- platform_device_register_data(&platform_bus, "gpio-keys", -1,
+ platform_device_register_data(NULL, "gpio-keys", -1,
&ape6evm_keys_pdata,
sizeof(ape6evm_keys_pdata));
- platform_device_register_data(&platform_bus, "leds-gpio", -1,
+ platform_device_register_data(NULL, "leds-gpio", -1,
&ape6evm_leds_pdata,
sizeof(ape6evm_leds_pdata));
}
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
index f444be2..3ec82a4 100644
--- a/arch/arm/mach-shmobile/board-bockw.c
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -177,7 +177,7 @@ static struct renesas_usbhs_platform_info usbhs_info __initdata = {
#define USB1_DEVICE "renesas_usbhs"
#define ADD_USB_FUNC_DEVICE_IF_POSSIBLE() \
platform_device_register_resndata( \
- &platform_bus, "renesas_usbhs", -1, \
+ NULL, "renesas_usbhs", -1, \
usbhsf_resources, \
ARRAY_SIZE(usbhsf_resources), \
&usbhs_info, sizeof(struct renesas_usbhs_platform_info))
@@ -236,7 +236,6 @@ static struct sh_eth_plat_data ether_platform_data __initdata = {
};
static struct platform_device_info ether_info __initdata = {
- .parent = &platform_bus,
.name = "r8a777x-ether",
.id = -1,
.res = ether_resources,
@@ -322,7 +321,6 @@ static struct resource vin##idx##_resources[] __initdata = { \
}; \
\
static struct platform_device_info vin##idx##_info __initdata = { \
- .parent = &platform_bus, \
.name = "r8a7778-vin", \
.id = idx, \
.res = vin##idx##_resources, \
@@ -621,10 +619,10 @@ static void __init bockw_init(void)
/* VIN1 has a pin conflict with Ether */
if (!IS_ENABLED(CONFIG_SH_ETH))
platform_device_register_full(&vin1_info);
- platform_device_register_data(&platform_bus, "soc-camera-pdrv", 0,
+ platform_device_register_data(NULL, "soc-camera-pdrv", 0,
&iclink0_ml86v7667,
sizeof(iclink0_ml86v7667));
- platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
+ platform_device_register_data(NULL, "soc-camera-pdrv", 1,
&iclink1_ml86v7667,
sizeof(iclink1_ml86v7667));
@@ -637,12 +635,12 @@ static void __init bockw_init(void)
r8a7778_pinmux_init();
platform_device_register_resndata(
- &platform_bus, "sh_mmcif", -1,
+ NULL, "sh_mmcif", -1,
mmc_resources, ARRAY_SIZE(mmc_resources),
&sh_mmcif_plat, sizeof(struct sh_mmcif_plat_data));
platform_device_register_resndata(
- &platform_bus, "rcar_usb_phy", -1,
+ NULL, "rcar_usb_phy", -1,
usb_phy_resources,
ARRAY_SIZE(usb_phy_resources),
&usb_phy_platform_data,
@@ -668,7 +666,7 @@ static void __init bockw_init(void)
iowrite16(val, fpga + IRQ0MR);
platform_device_register_resndata(
- &platform_bus, "smsc911x", -1,
+ NULL, "smsc911x", -1,
smsc911x_resources, ARRAY_SIZE(smsc911x_resources),
&smsc911x_data, sizeof(smsc911x_data));
}
@@ -685,7 +683,7 @@ static void __init bockw_init(void)
iounmap(base);
platform_device_register_resndata(
- &platform_bus, "sh_mobile_sdhi", 0,
+ NULL, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
}
@@ -700,7 +698,7 @@ static void __init bockw_init(void)
"ak4554-adc-dac", 1, NULL, 0);
pdev = platform_device_register_resndata(
- &platform_bus, "rcar_sound", -1,
+ NULL, "rcar_sound", -1,
rsnd_resources, ARRAY_SIZE(rsnd_resources),
&rsnd_info, sizeof(rsnd_info));
@@ -710,7 +708,6 @@ static void __init bockw_init(void)
for (i = 0; i < ARRAY_SIZE(rsnd_card_info); i++) {
struct platform_device_info cardinfo = {
- .parent = &platform_bus,
.name = "asoc-simple-card",
.id = i,
.data = &rsnd_card_info[i],
diff --git a/arch/arm/mach-shmobile/board-genmai.c b/arch/arm/mach-shmobile/board-genmai.c
index c94201e..37184ff 100644
--- a/arch/arm/mach-shmobile/board-genmai.c
+++ b/arch/arm/mach-shmobile/board-genmai.c
@@ -46,7 +46,6 @@ static const struct resource ether_resources[] __initconst = {
};
static const struct platform_device_info ether_info __initconst = {
- .parent = &platform_bus,
.name = "r7s72100-ether",
.id = -1,
.res = ether_resources,
@@ -76,7 +75,7 @@ static const struct rspi_plat_data rspi_pdata __initconst = {
};
#define r7s72100_register_rspi(idx) \
- platform_device_register_resndata(&platform_bus, "rspi-rz", idx, \
+ platform_device_register_resndata(NULL, "rspi-rz", idx, \
rspi##idx##_resources, \
ARRAY_SIZE(rspi##idx##_resources), \
&rspi_pdata, sizeof(rspi_pdata))
@@ -118,7 +117,7 @@ R7S72100_SCIF(6, 0xe800a000, gic_iid(245));
R7S72100_SCIF(7, 0xe800a800, gic_iid(249));
#define r7s72100_register_scif(index) \
- platform_device_register_resndata(&platform_bus, "sh-sci", index, \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
scif##index##_resources, \
ARRAY_SIZE(scif##index##_resources), \
&scif##index##_platform_data, \
diff --git a/arch/arm/mach-shmobile/board-koelsch.c b/arch/arm/mach-shmobile/board-koelsch.c
index c6c6889..d3aa6ae 100644
--- a/arch/arm/mach-shmobile/board-koelsch.c
+++ b/arch/arm/mach-shmobile/board-koelsch.c
@@ -118,7 +118,6 @@ static const struct resource ether_resources[] __initconst = {
};
static const struct platform_device_info ether_info __initconst = {
- .parent = &platform_bus,
.name = "r8a7791-ether",
.id = -1,
.res = ether_resources,
@@ -230,7 +229,6 @@ static const struct resource sata0_resources[] __initconst = {
};
static const struct platform_device_info sata0_info __initconst = {
- .parent = &platform_bus,
.name = "sata-r8a7791",
.id = 0,
.res = sata0_resources,
@@ -439,13 +437,13 @@ static void __init koelsch_add_standard_devices(void)
r8a7791_pinmux_init();
r8a7791_add_standard_devices();
platform_device_register_full(ðer_info);
- platform_device_register_data(&platform_bus, "leds-gpio", -1,
+ platform_device_register_data(NULL, "leds-gpio", -1,
&koelsch_leds_pdata,
sizeof(koelsch_leds_pdata));
- platform_device_register_data(&platform_bus, "gpio-keys", -1,
+ platform_device_register_data(NULL, "gpio-keys", -1,
&koelsch_keys_pdata,
sizeof(koelsch_keys_pdata));
- platform_device_register_resndata(&platform_bus, "qspi", 0,
+ platform_device_register_resndata(NULL, "qspi", 0,
qspi_resources,
ARRAY_SIZE(qspi_resources),
&qspi_pdata, sizeof(qspi_pdata));
@@ -460,28 +458,28 @@ static void __init koelsch_add_standard_devices(void)
koelsch_add_i2c(4);
koelsch_add_i2c(5);
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", 0,
+ platform_device_register_data(NULL, "reg-fixed-voltage", 0,
&vcc_sdhi0_info, sizeof(struct fixed_voltage_config));
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", 1,
+ platform_device_register_data(NULL, "reg-fixed-voltage", 1,
&vcc_sdhi1_info, sizeof(struct fixed_voltage_config));
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", 2,
+ platform_device_register_data(NULL, "reg-fixed-voltage", 2,
&vcc_sdhi2_info, sizeof(struct fixed_voltage_config));
- platform_device_register_data(&platform_bus, "gpio-regulator", 0,
+ platform_device_register_data(NULL, "gpio-regulator", 0,
&vccq_sdhi0_info, sizeof(struct gpio_regulator_config));
- platform_device_register_data(&platform_bus, "gpio-regulator", 1,
+ platform_device_register_data(NULL, "gpio-regulator", 1,
&vccq_sdhi1_info, sizeof(struct gpio_regulator_config));
- platform_device_register_data(&platform_bus, "gpio-regulator", 2,
+ platform_device_register_data(NULL, "gpio-regulator", 2,
&vccq_sdhi2_info, sizeof(struct gpio_regulator_config));
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 1,
sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
&sdhi1_info, sizeof(struct sh_mobile_sdhi_info));
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 2,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 2,
sdhi2_resources, ARRAY_SIZE(sdhi2_resources),
&sdhi2_info, sizeof(struct sh_mobile_sdhi_info));
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index f8b1e05..d182961 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -277,7 +277,6 @@ static const struct resource ether_resources[] __initconst = {
};
static const struct platform_device_info ether_info __initconst = {
- .parent = &platform_bus,
.name = "r8a7790-ether",
.id = -1,
.res = ether_resources,
@@ -354,7 +353,6 @@ static void __init lager_add_vin_device(unsigned idx,
struct rcar_vin_platform_data *pdata)
{
struct platform_device_info vin_info = {
- .parent = &platform_bus,
.name = "r8a7790-vin",
.id = idx,
.res = &vin_resources[idx * 2],
@@ -391,7 +389,7 @@ LAGER_CAMERA(1, "adv7180", 0x20, NULL, RCAR_VIN_BT656);
static void __init lager_add_camera1_device(void)
{
- platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
+ platform_device_register_data(NULL, "soc-camera-pdrv", 1,
&cam1_link, sizeof(cam1_link));
lager_add_vin_device(1, &vin1_pdata);
}
@@ -403,7 +401,6 @@ static const struct resource sata1_resources[] __initconst = {
};
static const struct platform_device_info sata1_info __initconst = {
- .parent = &platform_bus,
.name = "sata-r8a7790",
.id = 1,
.res = sata1_resources,
@@ -533,7 +530,7 @@ static struct usbhs_private usbhs_priv __initdata = {
static void __init lager_register_usbhs(void)
{
usb_bind_phy("renesas_usbhs", 0, "usb_phy_rcar_gen2");
- platform_device_register_resndata(&platform_bus,
+ platform_device_register_resndata(NULL,
"renesas_usbhs", -1,
usbhs_resources,
ARRAY_SIZE(usbhs_resources),
@@ -608,7 +605,6 @@ static struct asoc_simple_card_info rsnd_card_info = {
static void __init lager_add_rsnd_device(void)
{
struct platform_device_info cardinfo = {
- .parent = &platform_bus,
.name = "asoc-simple-card",
.id = -1,
.data = &rsnd_card_info,
@@ -620,7 +616,7 @@ static void __init lager_add_rsnd_device(void)
ARRAY_SIZE(i2c2_devices));
platform_device_register_resndata(
- &platform_bus, "rcar_sound", -1,
+ NULL, "rcar_sound", -1,
rsnd_resources, ARRAY_SIZE(rsnd_resources),
&rsnd_info, sizeof(rsnd_info));
@@ -663,7 +659,6 @@ static const struct resource pci1_resources[] __initconst = {
};
static const struct platform_device_info pci1_info __initconst = {
- .parent = &platform_bus,
.name = "pci-rcar-gen2",
.id = 1,
.res = pci1_resources,
@@ -684,7 +679,6 @@ static const struct resource pci2_resources[] __initconst = {
};
static const struct platform_device_info pci2_info __initconst = {
- .parent = &platform_bus,
.name = "pci-rcar-gen2",
.id = 2,
.res = pci2_resources,
@@ -795,16 +789,16 @@ static void __init lager_add_standard_devices(void)
r8a7790_pinmux_init();
r8a7790_add_standard_devices();
- platform_device_register_data(&platform_bus, "leds-gpio", -1,
+ platform_device_register_data(NULL, "leds-gpio", -1,
&lager_leds_pdata,
sizeof(lager_leds_pdata));
- platform_device_register_data(&platform_bus, "gpio-keys", -1,
+ platform_device_register_data(NULL, "gpio-keys", -1,
&lager_keys_pdata,
sizeof(lager_keys_pdata));
regulator_register_always_on(fixed_regulator_idx++,
"fixed-3.3V", fixed3v3_power_consumers,
ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
- platform_device_register_resndata(&platform_bus, "sh_mmcif", 1,
+ platform_device_register_resndata(NULL, "sh_mmcif", 1,
mmcif1_resources, ARRAY_SIZE(mmcif1_resources),
&mmcif1_pdata, sizeof(mmcif1_pdata));
@@ -812,27 +806,27 @@ static void __init lager_add_standard_devices(void)
lager_add_du_device();
- platform_device_register_resndata(&platform_bus, "qspi", 0,
+ platform_device_register_resndata(NULL, "qspi", 0,
qspi_resources,
ARRAY_SIZE(qspi_resources),
&qspi_pdata, sizeof(qspi_pdata));
spi_register_board_info(spi_info, ARRAY_SIZE(spi_info));
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", fixed_regulator_idx++,
+ platform_device_register_data(NULL, "reg-fixed-voltage", fixed_regulator_idx++,
&vcc_sdhi0_info, sizeof(struct fixed_voltage_config));
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", fixed_regulator_idx++,
+ platform_device_register_data(NULL, "reg-fixed-voltage", fixed_regulator_idx++,
&vcc_sdhi2_info, sizeof(struct fixed_voltage_config));
- platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++,
+ platform_device_register_data(NULL, "gpio-regulator", gpio_regulator_idx++,
&vccq_sdhi0_info, sizeof(struct gpio_regulator_config));
- platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++,
+ platform_device_register_data(NULL, "gpio-regulator", gpio_regulator_idx++,
&vccq_sdhi2_info, sizeof(struct gpio_regulator_config));
lager_add_camera1_device();
platform_device_register_full(&sata1_info);
- platform_device_register_resndata(&platform_bus, "usb_phy_rcar_gen2",
+ platform_device_register_resndata(NULL, "usb_phy_rcar_gen2",
-1, usbhs_phy_resources,
ARRAY_SIZE(usbhs_phy_resources),
&usbhs_phy_pdata,
@@ -843,10 +837,10 @@ static void __init lager_add_standard_devices(void)
lager_add_rsnd_device();
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 2,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 2,
sdhi2_resources, ARRAY_SIZE(sdhi2_resources),
&sdhi2_info, sizeof(struct sh_mobile_sdhi_info));
}
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index d832a44..6ed324c 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -272,7 +272,6 @@ static struct resource vin##idx##_resources[] __initdata = { \
}; \
\
static struct platform_device_info vin##idx##_info __initdata = { \
- .parent = &platform_bus, \
.name = "r8a7779-vin", \
.id = idx, \
.res = vin##idx##_resources, \
diff --git a/arch/arm/mach-shmobile/setup-r7s72100.c b/arch/arm/mach-shmobile/setup-r7s72100.c
index 412e179..3885a59 100644
--- a/arch/arm/mach-shmobile/setup-r7s72100.c
+++ b/arch/arm/mach-shmobile/setup-r7s72100.c
@@ -33,7 +33,7 @@ static struct resource mtu2_resources[] __initdata = {
};
#define r7s72100_register_mtu2() \
- platform_device_register_resndata(&platform_bus, "sh-mtu2", \
+ platform_device_register_resndata(NULL, "sh-mtu2", \
-1, mtu2_resources, \
ARRAY_SIZE(mtu2_resources), \
NULL, 0)
diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c
index 9333770..aaaaf6e 100644
--- a/arch/arm/mach-shmobile/setup-r8a73a4.c
+++ b/arch/arm/mach-shmobile/setup-r8a73a4.c
@@ -68,7 +68,7 @@ R8A73A4_SCIFB(4, 0xe6ce0000, gic_spi(150)); /* SCIFB2 */
R8A73A4_SCIFB(5, 0xe6cf0000, gic_spi(151)); /* SCIFB3 */
#define r8a73a4_register_scif(index) \
- platform_device_register_resndata(&platform_bus, "sh-sci", index, \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
scif##index##_resources, \
ARRAY_SIZE(scif##index##_resources), \
&scif##index##_platform_data, \
@@ -149,7 +149,7 @@ static const struct resource irqc1_resources[] = {
};
#define r8a73a4_register_irqc(idx) \
- platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+ platform_device_register_resndata(NULL, "renesas_irqc", \
idx, irqc##idx##_resources, \
ARRAY_SIZE(irqc##idx##_resources), \
&irqc##idx##_data, \
@@ -179,7 +179,7 @@ static struct resource cmt1_resources[] = {
};
#define r8a7790_register_cmt(idx) \
- platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
+ platform_device_register_resndata(NULL, "sh-cmt-48-gen2", \
idx, cmt##idx##_resources, \
ARRAY_SIZE(cmt##idx##_resources), \
&cmt##idx##_platform_data, \
@@ -280,7 +280,7 @@ static struct resource dma_resources[] = {
};
#define r8a73a4_register_dmac() \
- platform_device_register_resndata(&platform_bus, "sh-dma-engine", 0, \
+ platform_device_register_resndata(NULL, "sh-dma-engine", 0, \
dma_resources, ARRAY_SIZE(dma_resources), \
&dma_pdata, sizeof(dma_pdata))
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c
index d311ef9..5de7b33 100644
--- a/arch/arm/mach-shmobile/setup-r8a7778.c
+++ b/arch/arm/mach-shmobile/setup-r8a7778.c
@@ -64,7 +64,7 @@ R8A7778_SCIF(4, 0xffe44000, gic_iid(0x6a));
R8A7778_SCIF(5, 0xffe45000, gic_iid(0x6b));
#define r8a7778_register_scif(index) \
- platform_device_register_resndata(&platform_bus, "sh-sci", index, \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
scif##index##_resources, \
ARRAY_SIZE(scif##index##_resources), \
&scif##index##_platform_data, \
@@ -84,7 +84,7 @@ static struct resource sh_tmu0_resources[] = {
#define r8a7778_register_tmu(idx) \
platform_device_register_resndata( \
- &platform_bus, "sh-tmu", idx, \
+ NULL, "sh-tmu", idx, \
sh_tmu##idx##_resources, \
ARRAY_SIZE(sh_tmu##idx##_resources), \
&sh_tmu##idx##_platform_data, \
@@ -173,7 +173,6 @@ static struct resource ohci_resources[] __initdata = {
#define USB_PLATFORM_INFO(hci) \
static struct platform_device_info hci##_info __initdata = { \
- .parent = &platform_bus, \
.name = #hci "-platform", \
.id = -1, \
.res = hci##_resources, \
@@ -212,7 +211,7 @@ R8A7778_GPIO(4);
#define r8a7778_register_gpio(idx) \
platform_device_register_resndata( \
- &platform_bus, "gpio_rcar", idx, \
+ NULL, "gpio_rcar", idx, \
r8a7778_gpio##idx##_resources, \
ARRAY_SIZE(r8a7778_gpio##idx##_resources), \
&r8a7778_gpio##idx##_platform_data, \
@@ -496,8 +495,8 @@ static struct resource hpb_dmae_resources[] __initdata = {
static void __init r8a7778_register_hpb_dmae(void)
{
- platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
- hpb_dmae_resources,
+ platform_device_register_resndata(NULL, "hpb-dma-engine",
+ -1, hpb_dmae_resources,
ARRAY_SIZE(hpb_dmae_resources),
&dma_platform_data,
sizeof(dma_platform_data));
@@ -565,7 +564,7 @@ void __init r8a7778_init_irq_extpin(int irlm)
r8a7778_init_irq_extpin_dt(irlm);
if (irlm)
platform_device_register_resndata(
- &platform_bus, "renesas_intc_irqpin", -1,
+ NULL, "renesas_intc_irqpin", -1,
irqpin_resources, ARRAY_SIZE(irqpin_resources),
&irqpin_platform_data, sizeof(irqpin_platform_data));
}
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index aba4ed6..9c79182 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -123,7 +123,7 @@ void __init r8a7779_init_irq_extpin(int irlm)
r8a7779_init_irq_extpin_dt(irlm);
if (irlm)
platform_device_register_resndata(
- &platform_bus, "renesas_intc_irqpin", -1,
+ NULL, "renesas_intc_irqpin", -1,
irqpin0_resources, ARRAY_SIZE(irqpin0_resources),
&irqpin0_platform_data, sizeof(irqpin0_platform_data));
}
@@ -632,8 +632,8 @@ static struct resource hpb_dmae_resources[] __initdata = {
static void __init r8a7779_register_hpb_dmae(void)
{
- platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
- hpb_dmae_resources,
+ platform_device_register_resndata(NULL, "hpb-dma-engine",
+ -1, hpb_dmae_resources,
ARRAY_SIZE(hpb_dmae_resources),
&dma_platform_data,
sizeof(dma_platform_data));
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index 6bd08b1..10e6768 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -113,7 +113,7 @@ static struct resource r8a7790_audio_dmac_resources[] = {
#define r8a7790_register_audio_dmac(id) \
platform_device_register_resndata( \
- &platform_bus, "sh-dma-engine", id, \
+ NULL, "sh-dma-engine", id, \
&r8a7790_audio_dmac_resources[id * 3], 3, \
&r8a7790_audio_dmac_platform_data, \
sizeof(r8a7790_audio_dmac_platform_data))
@@ -149,7 +149,7 @@ R8A7790_GPIO(4);
R8A7790_GPIO(5);
#define r8a7790_register_gpio(idx) \
- platform_device_register_resndata(&platform_bus, "gpio_rcar", idx, \
+ platform_device_register_resndata(NULL, "gpio_rcar", idx, \
r8a7790_gpio##idx##_resources, \
ARRAY_SIZE(r8a7790_gpio##idx##_resources), \
&r8a7790_gpio##idx##_platform_data, \
@@ -227,7 +227,7 @@ R8A7790_HSCIF(8, 0xe62c0000, gic_spi(154)); /* HSCIF0 */
R8A7790_HSCIF(9, 0xe62c8000, gic_spi(155)); /* HSCIF1 */
#define r8a7790_register_scif(index) \
- platform_device_register_resndata(&platform_bus, "sh-sci", index, \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
scif##index##_resources, \
ARRAY_SIZE(scif##index##_resources), \
&scif##index##_platform_data, \
@@ -246,7 +246,7 @@ static const struct resource irqc0_resources[] __initconst = {
};
#define r8a7790_register_irqc(idx) \
- platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+ platform_device_register_resndata(NULL, "renesas_irqc", \
idx, irqc##idx##_resources, \
ARRAY_SIZE(irqc##idx##_resources), \
&irqc##idx##_data, \
@@ -273,7 +273,7 @@ static struct resource cmt0_resources[] = {
};
#define r8a7790_register_cmt(idx) \
- platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
+ platform_device_register_resndata(NULL, "sh-cmt-48-gen2", \
idx, cmt##idx##_resources, \
ARRAY_SIZE(cmt##idx##_resources), \
&cmt##idx##_platform_data, \
diff --git a/arch/arm/mach-shmobile/setup-r8a7791.c b/arch/arm/mach-shmobile/setup-r8a7791.c
index 04a96dd..fd54437 100644
--- a/arch/arm/mach-shmobile/setup-r8a7791.c
+++ b/arch/arm/mach-shmobile/setup-r8a7791.c
@@ -65,7 +65,7 @@ R8A7791_GPIO(6, 0xe6055400, 32);
R8A7791_GPIO(7, 0xe6055800, 26);
#define r8a7791_register_gpio(idx) \
- platform_device_register_resndata(&platform_bus, "gpio_rcar", idx, \
+ platform_device_register_resndata(NULL, "gpio_rcar", idx, \
r8a7791_gpio##idx##_resources, \
ARRAY_SIZE(r8a7791_gpio##idx##_resources), \
&r8a7791_gpio##idx##_platform_data, \
@@ -122,7 +122,7 @@ R8A7791_SCIFA(13, 0xe6c78000, gic_spi(30)); /* SCIFA4 */
R8A7791_SCIFA(14, 0xe6c80000, gic_spi(31)); /* SCIFA5 */
#define r8a7791_register_scif(index) \
- platform_device_register_resndata(&platform_bus, "sh-sci", index, \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
scif##index##_resources, \
ARRAY_SIZE(scif##index##_resources), \
&scif##index##_platform_data, \
@@ -138,7 +138,7 @@ static struct resource cmt0_resources[] = {
};
#define r8a7791_register_cmt(idx) \
- platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
+ platform_device_register_resndata(NULL, "sh-cmt-48-gen2", \
idx, cmt##idx##_resources, \
ARRAY_SIZE(cmt##idx##_resources), \
&cmt##idx##_platform_data, \
@@ -163,7 +163,7 @@ static struct resource irqc0_resources[] = {
};
#define r8a7791_register_irqc(idx) \
- platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+ platform_device_register_resndata(NULL, "renesas_irqc", \
idx, irqc##idx##_resources, \
ARRAY_SIZE(irqc##idx##_resources), \
&irqc##idx##_data, \
diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
index 254adee..438dd2e 100644
--- a/arch/unicore32/kernel/puv3-core.c
+++ b/arch/unicore32/kernel/puv3-core.c
@@ -272,7 +272,7 @@ void __init puv3_core_init(void)
platform_device_register_simple("PKUnity-v3-UART", 1,
puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
- platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
+ platform_device_register_resndata(NULL, "musb_hdrc", -1,
puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
&puv3_usb_plat, sizeof(puv3_usb_plat));
}
diff --git a/arch/unicore32/kernel/puv3-nb0916.c b/arch/unicore32/kernel/puv3-nb0916.c
index 0c6618e..46ebfdc 100644
--- a/arch/unicore32/kernel/puv3-nb0916.c
+++ b/arch/unicore32/kernel/puv3-nb0916.c
@@ -112,13 +112,13 @@ int __init mach_nb0916_init(void)
platform_device_register_simple("PKUnity-v3-I2C", -1,
puv3_i2c_resources, ARRAY_SIZE(puv3_i2c_resources));
- platform_device_register_data(&platform_bus, "pwm-backlight", -1,
+ platform_device_register_data(NULL, "pwm-backlight", -1,
&nb0916_backlight_data, sizeof(nb0916_backlight_data));
- platform_device_register_data(&platform_bus, "gpio-keys", -1,
+ platform_device_register_data(NULL, "gpio-keys", -1,
&nb0916_gpio_button_data, sizeof(nb0916_gpio_button_data));
- platform_device_register_resndata(&platform_bus, "physmap-flash", -1,
+ platform_device_register_resndata(NULL, "physmap-flash", -1,
&physmap_flash_resource, 1,
&physmap_flash_data, sizeof(physmap_flash_data));
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index eee48c4..f272603 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -30,8 +30,8 @@
/* For automatically allocated device IDs */
static DEFINE_IDA(platform_devid_ida);
-struct device platform_bus = {
- .init_name = "platform",
+struct platform_device platform_bus = {
+ .name = "platform",
};
EXPORT_SYMBOL_GPL(platform_bus);
@@ -300,7 +300,7 @@ int platform_device_add(struct platform_device *pdev)
return -EINVAL;
if (!pdev->dev.parent)
- pdev->dev.parent = &platform_bus;
+ pdev->dev.parent = &platform_bus.dev;
pdev->dev.bus = &platform_bus_type;
@@ -946,12 +946,18 @@ int __init platform_bus_init(void)
early_platform_cleanup();
- error = device_register(&platform_bus);
+ dev_set_name(&platform_bus.dev, "%s", platform_bus.name);
+ error = device_register(&platform_bus.dev);
if (error)
return error;
error = bus_register(&platform_bus_type);
- if (error)
- device_unregister(&platform_bus);
+ if (!error) {
+ platform_bus.dev.of_node = of_allnodes;
+ platform_bus.dev.bus = &platform_bus_type;
+ bus_add_device(&platform_bus.dev);
+ } else {
+ device_unregister(&platform_bus.dev);
+ }
return error;
}
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
index bd37747..4e4b7a2 100644
--- a/drivers/char/tile-srom.c
+++ b/drivers/char/tile-srom.c
@@ -350,7 +350,7 @@ static int srom_setup_minor(struct srom_dev *srom, int index)
SROM_PAGE_SIZE_OFF, sizeof(srom->page_size)) < 0)
return -EIO;
- dev = device_create(srom_class, &platform_bus,
+ dev = device_create(srom_class, &platform_bus.dev,
MKDEV(srom_major, index), srom, "%d", index);
return PTR_ERR_OR_ZERO(dev);
}
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 7e834fb..9a2b0d0 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -137,7 +137,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
dev_err(&pdev->dev, "Invalid iomem size!\n");
/* Some PCI-based MFD need the parent here */
- if (pdev->dev.parent != &platform_bus && !np)
+ if (pdev->dev.parent != &platform_bus.dev && !np)
host = sdhci_alloc_host(pdev->dev.parent,
sizeof(struct sdhci_pltfm_host) + priv_size);
else
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 3cbb57a..c14c36f 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -218,7 +218,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
goto fail;
if (!shost->shost_gendev.parent)
- shost->shost_gendev.parent = dev ? dev : &platform_bus;
+ shost->shost_gendev.parent = dev ? dev : &platform_bus.dev;
if (!dma_dev)
dma_dev = shost->shost_gendev.parent;
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 16f6654..a99032a 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -44,7 +44,7 @@ extern int platform_device_register(struct platform_device *);
extern void platform_device_unregister(struct platform_device *);
extern struct bus_type platform_bus_type;
-extern struct device platform_bus;
+extern struct platform_device platform_bus;
extern void arch_setup_pdev_archdata(struct platform_device *);
extern struct resource *platform_get_resource(struct platform_device *,
--
1.9.1
^ permalink raw reply related
* Fix me in netx-regs.h
From: Nick Krause @ 2014-07-22 17:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <11713455.tffm2SOdyn@wuerfel>
On Tue, Jul 22, 2014 at 4:44 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 22 July 2014 00:16:26 Nick Krause wrote:
>> Hey Russell,
>> I did give thought to our previous conversations and I will still do
>> fix mes but am going to be more careful
>> with I submit them. Furthermore it seems #define
>> NETX_GPIO_COUNTER_CTRL_GPIO_RE is not defined
>> correctly. As the maintainer what should I define it to?
>
> Are you offering to become the maintainer for netx?
>
> Try to get hold of a reference manual for the chip. More importantly
> than the fixme, I think we should be able to move this platform into
> ARCH_MULTIPLATFORM. This means moving the contents of the header files
> into the places where they are used, and finding a better home for the
> pfifo driver.
>
> Arnd
Arnd,
I am not asking to me the maintainer of netx.
I was just trying to help out.
Cheers Nick
^ permalink raw reply
* [PATCH v2] platform: Make platform_bus device a platform device
From: Greg Kroah-Hartman @ 2014-07-22 17:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1406050206.25343.87.camel@hornet>
On Tue, Jul 22, 2014 at 06:30:06PM +0100, Pawel Moll wrote:
> On Tue, 2014-07-22 at 18:10 +0100, Greg Kroah-Hartman wrote:
> > On Tue, Jul 22, 2014 at 11:02:07AM +0100, Pawel Moll wrote:
> > > ... describing the root of the device tree, so one can write
> > > a platform driver initializing the platform.
> > >
> > > All references to platform_bus device have been fixed up,
> > > although in most cases they could be simply removed or
> > > replaced by NULL (platform devices with no parent are adopted
> > > by main platform_bus device automagically).
> >
> > In looking at this some more, I think all of these should be made NULL,
> > why are we exporting this symbol at all?
>
> I think there are about 3 non-obvious uses of it, which would probably
> need looking into. All other ones that simply do of_platform_populate()
> or platform_device_register*() with platform_bus as a parent, which has
> exactly the same effect as it was NULL.
>
> I can imagine situations where one would want to walk the device
> hierarchy stopping at platform_bus, how I'm not sure how "legitimate"
> that would be.
Not at all "legitimate", use the functions the kernel provides for you
if you really wanted to do that instead of trying to do it yourself.
> I'll post v3 with NULLs where I think it is enough so we can see the
> other cases.
Thanks, that would be great.
greg k-h
^ permalink raw reply
* [PATCH 5/8] of: Add Tegra124 EMC bindings
From: Stephen Warren @ 2014-07-22 17:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAL1qeaEkL+mxb0S4JhQbXBjyNyKJndffTSjMaAFQD6ooDJPd+Q@mail.gmail.com>
On 07/22/2014 11:22 AM, Andrew Bresticker wrote:
> On Tue, Jul 22, 2014 at 9:45 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>>
>> Does the bootloader adjust the DT that's passed to the kernel so that
>> only the relevant single set of EMC timings is contained in the DT?
>
> No, the DT contains all possible EMC timings for that board.
>
>> On a system where the boot ROM initializes RAM, and where the HW design
>> might have multiple SDRAM configuration, here's what usually happens:
>>
>> a) The BCT contains N sets of SDRAM configurations.
>>
>> b) The boot ROM reads the SDRAM strapping bits, and uses them to pick
>> the correct SDRAM configuration from the N sets in the BCT.
>>
>> c) The kernel DT has N sets of SDRAM configurations.
>>
>> d) The kernel reads the SDRAM strapping bits, and uses them to pick the
>> correct SDRAM configuration from the N sets in the DT.
>>
>> On the ChromeOS boards (so (a) and (b) above are irrelevant) where N is
>> too large to fit into APBDEV_PMC_STRAPPING_OPT_A_0[7:4], (c) and (d)
>> won't work. I assume the kernel DT therefore must be adjusted to only
>> contain the single SDRAM configuration that is relevant for the current HW?
>>
>> (isn't STRAPPING_OPT_A split into 2 2-bit fields; 2 bits for SDRAM index
>> and 2 bits for boot flash index, so max N is quite small?)
>
> Right, there are normally only 2 SDRAM strapping bits available.
> ChromeOS gets around this by having 4 identical boot device entries in
> the BCT, so all possible values of STRAPPING_OPT_A[7:6] map to the
> same boot device. This allows us to use all 4 strapping bits in
> coreboot to pick the SDRAM configuration.
OK, that explains how it works.
But that means that when the kernel reads the strapping options, it will
have to know if it uses just 2 bits (standard) or all 4 bits
(non-standard) to index into the DT's array of SDRAM configurations.
We'll need a DT property to represent that.
^ permalink raw reply
* [PATCH RESEND v2] bus: ARM CCN PMU driver
From: Pawel Moll @ 2014-07-22 17:32 UTC (permalink / raw)
To: linux-arm-kernel
Driver providing perf backend for ARM Cache Coherent Network
interconnect. Supports counting all hardware events and crosspoint
watchpoints.
Currently works with CCN-504 only, although there should be
no changes required for CCN-508 (just impossible to test it now).
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
Re-sending on Olof's request, to be pulled into arm-soc tree.
Changes from v1:
- removed unwanted hunks in Kconfig and Makefile (stupid rebasing
mistake)
Documentation/arm/CCN.txt | 52 +
Documentation/devicetree/bindings/arm/ccn.txt | 21 +
drivers/bus/Kconfig | 7 +
drivers/bus/Makefile | 4 +-
drivers/bus/arm-ccn.c | 1390 +++++++++++++++++++++++++
5 files changed, 1473 insertions(+), 1 deletion(-)
create mode 100644 Documentation/arm/CCN.txt
create mode 100644 Documentation/devicetree/bindings/arm/ccn.txt
create mode 100644 drivers/bus/arm-ccn.c
diff --git a/Documentation/arm/CCN.txt b/Documentation/arm/CCN.txt
new file mode 100644
index 0000000..0632b3a
--- /dev/null
+++ b/Documentation/arm/CCN.txt
@@ -0,0 +1,52 @@
+ARM Cache Coherent Network
+==========================
+
+CCN-504 is a ring-bus interconnect consisting of 11 crosspoints
+(XPs), with each crosspoint supporting up to two device ports,
+so nodes (devices) 0 and 1 are connected to crosspoint 0,
+nodes 2 and 3 to crosspoint 1 etc.
+
+PMU (perf) driver
+-----------------
+
+The CCN driver registers a perf PMU driver, which provides
+description of available events and configuration options
+in sysfs, see /sys/bus/event_source/devices/ccn*.
+
+The "format" directory describes format of the config, config1
+and config2 fields of the perf_event_attr structure. The "events"
+directory provides configuration templates for all documented
+events, that can be used with perf tool. For example "xp_valid_flit"
+is an equivalent of "type=0x8,event=0x4". Other parameters must be
+explicitly specified. For events originating from device, "node"
+defines its index. All crosspoint events require "xp" (index),
+"port" (device port number) and "vc" (virtual channel ID) and
+"dir" (direction). Watchpoints (special "event" value 0xfe) also
+require comparator values ("cmp_l" and "cmp_h") and "mask", being
+index of the comparator mask.
+
+Masks are defined separately from the event description
+(due to limited number of the config values) in the "cmp_mask"
+directory, with first 8 configurable by user and additional
+4 hardcoded for the most frequent use cases.
+
+Cycle counter is described by a "type" value 0xff and does
+not require any other settings.
+
+Example of perf tool use:
+
+/ # perf list | grep ccn
+ ccn/cycles/ [Kernel PMU event]
+<...>
+ ccn/xp_valid_flit/ [Kernel PMU event]
+<...>
+
+/ # perf stat -C 0 -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \
+ sleep 1
+
+The driver does not support sampling, therefore "perf record" will
+not work. Also notice that only single cpu is being selected
+("-C 0") - this is because perf framework does not support
+"non-CPU related" counters (yet?) so system-wide session ("-a")
+would try (and in most cases fail) to set up the same event
+per each CPU.
diff --git a/Documentation/devicetree/bindings/arm/ccn.txt b/Documentation/devicetree/bindings/arm/ccn.txt
new file mode 100644
index 0000000..b100d38
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/ccn.txt
@@ -0,0 +1,21 @@
+* ARM CCN (Cache Coherent Network)
+
+Required properties:
+
+- compatible: (standard compatible string) should be one of:
+ "arm,ccn-504"
+ "arm,ccn-508"
+
+- reg: (standard registers property) physical address and size
+ (16MB) of the configuration registers block
+
+- interrupts: (standard interrupt property) single interrupt
+ generated by the control block
+
+Example:
+
+ ccn at 0x2000000000 {
+ compatible = "arm,ccn-504";
+ reg = <0x20 0x00000000 0 0x1000000>;
+ interrupts = <0 181 4>;
+ };
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 1f37d98..5c0c276 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -50,6 +50,13 @@ config ARM_CCI
Driver supporting the CCI cache coherent interconnect for ARM
platforms.
+config ARM_CCN
+ bool "ARM CCN driver support"
+ depends on ARM || ARM64
+ help
+ PMU (perf) driver supporting the ARM CCN (Cache Coherent Network)
+ interconnect.
+
config VEXPRESS_CONFIG
bool "Versatile Express configuration bus"
default y if ARCH_VEXPRESS
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 6a4ea7e..2973c18 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -9,7 +9,9 @@ obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
# Interconnect bus driver for OMAP SoCs.
obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
-# CCI cache coherent interconnect for ARM platforms
+
+# Interconnect bus drivers for ARM platforms
obj-$(CONFIG_ARM_CCI) += arm-cci.o
+obj-$(CONFIG_ARM_CCN) += arm-ccn.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c
new file mode 100644
index 0000000..4f86bbb
--- /dev/null
+++ b/drivers/bus/arm-ccn.c
@@ -0,0 +1,1390 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2014 ARM Limited
+ */
+
+#include <linux/ctype.h>
+#include <linux/hrtimer.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define CCN_NUM_XP_PORTS 2
+#define CCN_NUM_VCS 4
+#define CCN_NUM_REGIONS 256
+#define CCN_REGION_SIZE 0x10000
+
+#define CCN_ALL_OLY_ID 0xff00
+#define CCN_ALL_OLY_ID__OLY_ID__SHIFT 0
+#define CCN_ALL_OLY_ID__OLY_ID__MASK 0x1f
+#define CCN_ALL_OLY_ID__NODE_ID__SHIFT 8
+#define CCN_ALL_OLY_ID__NODE_ID__MASK 0x3f
+
+#define CCN_MN_ERRINT_STATUS 0x0008
+#define CCN_MN_ERRINT_STATUS__INTREQ__DESSERT 0x11
+#define CCN_MN_ERRINT_STATUS__ALL_ERRORS__ENABLE 0x02
+#define CCN_MN_ERRINT_STATUS__ALL_ERRORS__DISABLED 0x20
+#define CCN_MN_ERRINT_STATUS__ALL_ERRORS__DISABLE 0x22
+#define CCN_MN_ERRINT_STATUS__CORRECTED_ERRORS_ENABLE 0x04
+#define CCN_MN_ERRINT_STATUS__CORRECTED_ERRORS_DISABLED 0x40
+#define CCN_MN_ERRINT_STATUS__CORRECTED_ERRORS_DISABLE 0x44
+#define CCN_MN_ERRINT_STATUS__PMU_EVENTS__ENABLE 0x08
+#define CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLED 0x80
+#define CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLE 0x88
+#define CCN_MN_OLY_COMP_LIST_63_0 0x01e0
+#define CCN_MN_ERR_SIG_VAL_63_0 0x0300
+#define CCN_MN_ERR_SIG_VAL_63_0__DT (1 << 1)
+
+#define CCN_DT_ACTIVE_DSM 0x0000
+#define CCN_DT_ACTIVE_DSM__DSM_ID__SHIFT(n) ((n) * 8)
+#define CCN_DT_ACTIVE_DSM__DSM_ID__MASK 0xff
+#define CCN_DT_CTL 0x0028
+#define CCN_DT_CTL__DT_EN (1 << 0)
+#define CCN_DT_PMEVCNT(n) (0x0100 + (n) * 0x8)
+#define CCN_DT_PMCCNTR 0x0140
+#define CCN_DT_PMCCNTRSR 0x0190
+#define CCN_DT_PMOVSR 0x0198
+#define CCN_DT_PMOVSR_CLR 0x01a0
+#define CCN_DT_PMCR 0x01a8
+#define CCN_DT_PMCR__OVFL_INTR_EN (1 << 6)
+#define CCN_DT_PMCR__PMU_EN (1 << 0)
+#define CCN_DT_PMSR 0x01b0
+#define CCN_DT_PMSR_REQ 0x01b8
+#define CCN_DT_PMSR_CLR 0x01c0
+
+#define CCN_HNF_PMU_EVENT_SEL 0x0600
+#define CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(n) ((n) * 4)
+#define CCN_HNF_PMU_EVENT_SEL__ID__MASK 0xf
+
+#define CCN_XP_DT_CONFIG 0x0300
+#define CCN_XP_DT_CONFIG__DT_CFG__SHIFT(n) ((n) * 4)
+#define CCN_XP_DT_CONFIG__DT_CFG__MASK 0xf
+#define CCN_XP_DT_CONFIG__DT_CFG__PASS_THROUGH 0x0
+#define CCN_XP_DT_CONFIG__DT_CFG__WATCHPOINT_0_OR_1 0x1
+#define CCN_XP_DT_CONFIG__DT_CFG__WATCHPOINT(n) (0x2 + (n))
+#define CCN_XP_DT_CONFIG__DT_CFG__XP_PMU_EVENT(n) (0x4 + (n))
+#define CCN_XP_DT_CONFIG__DT_CFG__DEVICE_PMU_EVENT(d, n) (0x8 + (d) * 4 + (n))
+#define CCN_XP_DT_INTERFACE_SEL 0x0308
+#define CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__SHIFT(n) (0 + (n) * 8)
+#define CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__MASK 0x1
+#define CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__SHIFT(n) (1 + (n) * 8)
+#define CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__MASK 0x1
+#define CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__SHIFT(n) (2 + (n) * 8)
+#define CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__MASK 0x3
+#define CCN_XP_DT_CMP_VAL_L(n) (0x0310 + (n) * 0x40)
+#define CCN_XP_DT_CMP_VAL_H(n) (0x0318 + (n) * 0x40)
+#define CCN_XP_DT_CMP_MASK_L(n) (0x0320 + (n) * 0x40)
+#define CCN_XP_DT_CMP_MASK_H(n) (0x0328 + (n) * 0x40)
+#define CCN_XP_DT_CONTROL 0x0370
+#define CCN_XP_DT_CONTROL__DT_ENABLE (1 << 0)
+#define CCN_XP_DT_CONTROL__WP_ARM_SEL__SHIFT(n) (12 + (n) * 4)
+#define CCN_XP_DT_CONTROL__WP_ARM_SEL__MASK 0xf
+#define CCN_XP_DT_CONTROL__WP_ARM_SEL__ALWAYS 0xf
+#define CCN_XP_PMU_EVENT_SEL 0x0600
+#define CCN_XP_PMU_EVENT_SEL__ID__SHIFT(n) ((n) * 7)
+#define CCN_XP_PMU_EVENT_SEL__ID__MASK 0x3f
+
+#define CCN_SBAS_PMU_EVENT_SEL 0x0600
+#define CCN_SBAS_PMU_EVENT_SEL__ID__SHIFT(n) ((n) * 4)
+#define CCN_SBAS_PMU_EVENT_SEL__ID__MASK 0xf
+
+#define CCN_RNI_PMU_EVENT_SEL 0x0600
+#define CCN_RNI_PMU_EVENT_SEL__ID__SHIFT(n) ((n) * 4)
+#define CCN_RNI_PMU_EVENT_SEL__ID__MASK 0xf
+
+#define CCN_TYPE_MN 0x01
+#define CCN_TYPE_DT 0x02
+#define CCN_TYPE_HNF 0x04
+#define CCN_TYPE_HNI 0x05
+#define CCN_TYPE_XP 0x08
+#define CCN_TYPE_SBSX 0x0c
+#define CCN_TYPE_SBAS 0x10
+#define CCN_TYPE_RNI_1P 0x14
+#define CCN_TYPE_RNI_2P 0x15
+#define CCN_TYPE_RNI_3P 0x16
+#define CCN_TYPE_RND_1P 0x18 /* RN-D = RN-I + DVM */
+#define CCN_TYPE_RND_2P 0x19
+#define CCN_TYPE_RND_3P 0x1a
+#define CCN_TYPE_CYCLES 0xff /* Pseudotype */
+
+#define CCN_EVENT_WATCHPOINT 0xfe /* Pseudoevent */
+
+#define CCN_NUM_PMU_EVENTS 4
+#define CCN_NUM_XP_WATCHPOINTS 2 /* See DT.dbg_id.num_watchpoints */
+#define CCN_NUM_PMU_EVENT_COUNTERS 8 /* See DT.dbg_id.num_pmucntr */
+#define CCN_IDX_PMU_CYCLE_COUNTER CCN_NUM_PMU_EVENT_COUNTERS
+
+#define CCN_NUM_PREDEFINED_MASKS 4
+#define CCN_IDX_MASK_ANY (CCN_NUM_PMU_EVENT_COUNTERS + 0)
+#define CCN_IDX_MASK_EXACT (CCN_NUM_PMU_EVENT_COUNTERS + 1)
+#define CCN_IDX_MASK_ORDER (CCN_NUM_PMU_EVENT_COUNTERS + 2)
+#define CCN_IDX_MASK_OPCODE (CCN_NUM_PMU_EVENT_COUNTERS + 3)
+
+struct arm_ccn_component {
+ void __iomem *base;
+ u32 type;
+
+ DECLARE_BITMAP(pmu_events_mask, CCN_NUM_PMU_EVENTS);
+ union {
+ struct {
+ DECLARE_BITMAP(dt_cmp_mask, CCN_NUM_XP_WATCHPOINTS);
+ } xp;
+ };
+};
+
+#define pmu_to_arm_ccn(_pmu) container_of(container_of(_pmu, \
+ struct arm_ccn_dt, pmu), struct arm_ccn, dt)
+
+struct arm_ccn_dt {
+ int id;
+ void __iomem *base;
+
+ spinlock_t config_lock;
+
+ DECLARE_BITMAP(pmu_counters_mask, CCN_NUM_PMU_EVENT_COUNTERS + 1);
+ struct {
+ struct arm_ccn_component *source;
+ struct perf_event *event;
+ } pmu_counters[CCN_NUM_PMU_EVENT_COUNTERS + 1];
+
+ struct {
+ u64 l, h;
+ } cmp_mask[CCN_NUM_PMU_EVENT_COUNTERS + CCN_NUM_PREDEFINED_MASKS];
+
+ struct hrtimer hrtimer;
+
+ struct pmu pmu;
+};
+
+struct arm_ccn {
+ struct device *dev;
+ void __iomem *base;
+ unsigned irq_used:1;
+ unsigned sbas_present:1;
+ unsigned sbsx_present:1;
+
+ int num_nodes;
+ struct arm_ccn_component *node;
+
+ int num_xps;
+ struct arm_ccn_component *xp;
+
+ struct arm_ccn_dt dt;
+};
+
+
+static int arm_ccn_node_to_xp(int node)
+{
+ return node / CCN_NUM_XP_PORTS;
+}
+
+static int arm_ccn_node_to_xp_port(int node)
+{
+ return node % CCN_NUM_XP_PORTS;
+}
+
+
+/*
+ * Bit shifts and masks in these defines must be kept in sync with
+ * arm_ccn_pmu_config_set() and CCN_FORMAT_ATTRs below!
+ */
+#define CCN_CONFIG_NODE(_config) (((_config) >> 0) & 0xff)
+#define CCN_CONFIG_XP(_config) (((_config) >> 0) & 0xff)
+#define CCN_CONFIG_TYPE(_config) (((_config) >> 8) & 0xff)
+#define CCN_CONFIG_EVENT(_config) (((_config) >> 16) & 0xff)
+#define CCN_CONFIG_PORT(_config) (((_config) >> 24) & 0x3)
+#define CCN_CONFIG_VC(_config) (((_config) >> 26) & 0x7)
+#define CCN_CONFIG_DIR(_config) (((_config) >> 29) & 0x1)
+#define CCN_CONFIG_MASK(_config) (((_config) >> 30) & 0xf)
+
+static void arm_ccn_pmu_config_set(u64 *config, u32 node_xp, u32 type, u32 port)
+{
+ *config &= ~((0xff << 0) | (0xff << 8) | (0xff << 24));
+ *config |= (node_xp << 0) | (type << 8) | (port << 24);
+}
+
+static ssize_t arm_ccn_pmu_format_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dev_ext_attribute *ea = container_of(attr,
+ struct dev_ext_attribute, attr);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", (char *)ea->var);
+}
+
+#define CCN_FORMAT_ATTR(_name, _config) \
+ struct dev_ext_attribute arm_ccn_pmu_format_attr_##_name = \
+ { __ATTR(_name, S_IRUGO, arm_ccn_pmu_format_show, \
+ NULL), _config }
+
+static CCN_FORMAT_ATTR(node, "config:0-7");
+static CCN_FORMAT_ATTR(xp, "config:0-7");
+static CCN_FORMAT_ATTR(type, "config:8-15");
+static CCN_FORMAT_ATTR(event, "config:16-23");
+static CCN_FORMAT_ATTR(port, "config:24-25");
+static CCN_FORMAT_ATTR(vc, "config:26-28");
+static CCN_FORMAT_ATTR(dir, "config:29-29");
+static CCN_FORMAT_ATTR(mask, "config:30-33");
+static CCN_FORMAT_ATTR(cmp_l, "config1:0-62");
+static CCN_FORMAT_ATTR(cmp_h, "config2:0-59");
+
+static struct attribute *arm_ccn_pmu_format_attrs[] = {
+ &arm_ccn_pmu_format_attr_node.attr.attr,
+ &arm_ccn_pmu_format_attr_xp.attr.attr,
+ &arm_ccn_pmu_format_attr_type.attr.attr,
+ &arm_ccn_pmu_format_attr_event.attr.attr,
+ &arm_ccn_pmu_format_attr_port.attr.attr,
+ &arm_ccn_pmu_format_attr_vc.attr.attr,
+ &arm_ccn_pmu_format_attr_dir.attr.attr,
+ &arm_ccn_pmu_format_attr_mask.attr.attr,
+ &arm_ccn_pmu_format_attr_cmp_l.attr.attr,
+ &arm_ccn_pmu_format_attr_cmp_h.attr.attr,
+ NULL
+};
+
+static struct attribute_group arm_ccn_pmu_format_attr_group = {
+ .name = "format",
+ .attrs = arm_ccn_pmu_format_attrs,
+};
+
+
+struct arm_ccn_pmu_event {
+ struct device_attribute attr;
+ u32 type;
+ u32 event;
+ int num_ports;
+ int num_vcs;
+ const char *def;
+ int mask;
+};
+
+#define CCN_EVENT_ATTR(_name) \
+ __ATTR(_name, S_IRUGO, arm_ccn_pmu_event_show, NULL)
+
+/*
+ * Events defined in TRM for MN, HN-I and SBSX are actually watchpoints set on
+ * their ports in XP they are connected to. For the sake of usability they are
+ * explicitly defined here (and translated into a relevant watchpoint in
+ * arm_ccn_pmu_event_init()) so the user can easily request them without deep
+ * knowledge of the flit format.
+ */
+
+#define CCN_EVENT_MN(_name, _def, _mask) { .attr = CCN_EVENT_ATTR(mn_##_name), \
+ .type = CCN_TYPE_MN, .event = CCN_EVENT_WATCHPOINT, \
+ .num_ports = CCN_NUM_XP_PORTS, .num_vcs = CCN_NUM_VCS, \
+ .def = _def, .mask = _mask, }
+
+#define CCN_EVENT_HNI(_name, _def, _mask) { \
+ .attr = CCN_EVENT_ATTR(hni_##_name), .type = CCN_TYPE_HNI, \
+ .event = CCN_EVENT_WATCHPOINT, .num_ports = CCN_NUM_XP_PORTS, \
+ .num_vcs = CCN_NUM_VCS, .def = _def, .mask = _mask, }
+
+#define CCN_EVENT_SBSX(_name, _def, _mask) { \
+ .attr = CCN_EVENT_ATTR(sbsx_##_name), .type = CCN_TYPE_SBSX, \
+ .event = CCN_EVENT_WATCHPOINT, .num_ports = CCN_NUM_XP_PORTS, \
+ .num_vcs = CCN_NUM_VCS, .def = _def, .mask = _mask, }
+
+#define CCN_EVENT_HNF(_name, _event) { .attr = CCN_EVENT_ATTR(hnf_##_name), \
+ .type = CCN_TYPE_HNF, .event = _event, }
+
+#define CCN_EVENT_XP(_name, _event) { .attr = CCN_EVENT_ATTR(xp_##_name), \
+ .type = CCN_TYPE_XP, .event = _event, \
+ .num_ports = CCN_NUM_XP_PORTS, .num_vcs = CCN_NUM_VCS, }
+
+/*
+ * RN-I & RN-D (RN-D = RN-I + DVM) nodes have different type ID depending
+ * on configuration. One of them is picked to represent the whole group,
+ * as they all share the same event types.
+ */
+#define CCN_EVENT_RNI(_name, _event) { .attr = CCN_EVENT_ATTR(rni_##_name), \
+ .type = CCN_TYPE_RNI_3P, .event = _event, }
+
+#define CCN_EVENT_SBAS(_name, _event) { .attr = CCN_EVENT_ATTR(sbas_##_name), \
+ .type = CCN_TYPE_SBAS, .event = _event, }
+
+#define CCN_EVENT_CYCLES(_name) { .attr = CCN_EVENT_ATTR(_name), \
+ .type = CCN_TYPE_CYCLES }
+
+
+static ssize_t arm_ccn_pmu_event_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct arm_ccn_pmu_event *event = container_of(attr,
+ struct arm_ccn_pmu_event, attr);
+ ssize_t res;
+
+ res = snprintf(buf, PAGE_SIZE, "type=0x%x", event->type);
+ if (event->event)
+ res += snprintf(buf + res, PAGE_SIZE - res, ",event=0x%x",
+ event->event);
+ if (event->def)
+ res += snprintf(buf + res, PAGE_SIZE - res, ",%s",
+ event->def);
+ if (event->mask)
+ res += snprintf(buf + res, PAGE_SIZE - res, ",mask=0x%x",
+ event->mask);
+ res += snprintf(buf + res, PAGE_SIZE - res, "\n");
+
+ return res;
+}
+
+static umode_t arm_ccn_pmu_events_is_visible(struct kobject *kobj,
+ struct attribute *attr, int index)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
+ struct device_attribute *dev_attr = container_of(attr,
+ struct device_attribute, attr);
+ struct arm_ccn_pmu_event *event = container_of(dev_attr,
+ struct arm_ccn_pmu_event, attr);
+
+ if (event->type == CCN_TYPE_SBAS && !ccn->sbas_present)
+ return 0;
+ if (event->type == CCN_TYPE_SBSX && !ccn->sbsx_present)
+ return 0;
+
+ return attr->mode;
+}
+
+static struct arm_ccn_pmu_event arm_ccn_pmu_events[] = {
+ CCN_EVENT_MN(eobarrier, "dir=0,vc=0,cmp_h=0x1c00", CCN_IDX_MASK_OPCODE),
+ CCN_EVENT_MN(ecbarrier, "dir=0,vc=0,cmp_h=0x1e00", CCN_IDX_MASK_OPCODE),
+ CCN_EVENT_MN(dvmop, "dir=0,vc=0,cmp_h=0x2800", CCN_IDX_MASK_OPCODE),
+ CCN_EVENT_HNI(txdatflits, "dir=1,vc=3", CCN_IDX_MASK_ANY),
+ CCN_EVENT_HNI(rxdatflits, "dir=0,vc=3", CCN_IDX_MASK_ANY),
+ CCN_EVENT_HNI(txreqflits, "dir=1,vc=0", CCN_IDX_MASK_ANY),
+ CCN_EVENT_HNI(rxreqflits, "dir=0,vc=0", CCN_IDX_MASK_ANY),
+ CCN_EVENT_HNI(rxreqflits_order, "dir=0,vc=0,cmp_h=0x8000",
+ CCN_IDX_MASK_ORDER),
+ CCN_EVENT_SBSX(txdatflits, "dir=1,vc=3", CCN_IDX_MASK_ANY),
+ CCN_EVENT_SBSX(rxdatflits, "dir=0,vc=3", CCN_IDX_MASK_ANY),
+ CCN_EVENT_SBSX(txreqflits, "dir=1,vc=0", CCN_IDX_MASK_ANY),
+ CCN_EVENT_SBSX(rxreqflits, "dir=0,vc=0", CCN_IDX_MASK_ANY),
+ CCN_EVENT_SBSX(rxreqflits_order, "dir=0,vc=0,cmp_h=0x8000",
+ CCN_IDX_MASK_ORDER),
+ CCN_EVENT_HNF(cache_miss, 0x1),
+ CCN_EVENT_HNF(l3_sf_cache_access, 0x02),
+ CCN_EVENT_HNF(cache_fill, 0x3),
+ CCN_EVENT_HNF(pocq_retry, 0x4),
+ CCN_EVENT_HNF(pocq_reqs_recvd, 0x5),
+ CCN_EVENT_HNF(sf_hit, 0x6),
+ CCN_EVENT_HNF(sf_evictions, 0x7),
+ CCN_EVENT_HNF(snoops_sent, 0x8),
+ CCN_EVENT_HNF(snoops_broadcast, 0x9),
+ CCN_EVENT_HNF(l3_eviction, 0xa),
+ CCN_EVENT_HNF(l3_fill_invalid_way, 0xb),
+ CCN_EVENT_HNF(mc_retries, 0xc),
+ CCN_EVENT_HNF(mc_reqs, 0xd),
+ CCN_EVENT_HNF(qos_hh_retry, 0xe),
+ CCN_EVENT_RNI(rdata_beats_p0, 0x1),
+ CCN_EVENT_RNI(rdata_beats_p1, 0x2),
+ CCN_EVENT_RNI(rdata_beats_p2, 0x3),
+ CCN_EVENT_RNI(rxdat_flits, 0x4),
+ CCN_EVENT_RNI(txdat_flits, 0x5),
+ CCN_EVENT_RNI(txreq_flits, 0x6),
+ CCN_EVENT_RNI(txreq_flits_retried, 0x7),
+ CCN_EVENT_RNI(rrt_full, 0x8),
+ CCN_EVENT_RNI(wrt_full, 0x9),
+ CCN_EVENT_RNI(txreq_flits_replayed, 0xa),
+ CCN_EVENT_XP(upload_starvation, 0x1),
+ CCN_EVENT_XP(download_starvation, 0x2),
+ CCN_EVENT_XP(respin, 0x3),
+ CCN_EVENT_XP(valid_flit, 0x4),
+ CCN_EVENT_XP(watchpoint, CCN_EVENT_WATCHPOINT),
+ CCN_EVENT_SBAS(rdata_beats_p0, 0x1),
+ CCN_EVENT_SBAS(rxdat_flits, 0x4),
+ CCN_EVENT_SBAS(txdat_flits, 0x5),
+ CCN_EVENT_SBAS(txreq_flits, 0x6),
+ CCN_EVENT_SBAS(txreq_flits_retried, 0x7),
+ CCN_EVENT_SBAS(rrt_full, 0x8),
+ CCN_EVENT_SBAS(wrt_full, 0x9),
+ CCN_EVENT_SBAS(txreq_flits_replayed, 0xa),
+ CCN_EVENT_CYCLES(cycles),
+};
+
+/* Populated in arm_ccn_init() */
+static struct attribute
+ *arm_ccn_pmu_events_attrs[ARRAY_SIZE(arm_ccn_pmu_events) + 1];
+
+static struct attribute_group arm_ccn_pmu_events_attr_group = {
+ .name = "events",
+ .is_visible = arm_ccn_pmu_events_is_visible,
+ .attrs = arm_ccn_pmu_events_attrs,
+};
+
+
+static u64 *arm_ccn_pmu_get_cmp_mask(struct arm_ccn *ccn, const char *name)
+{
+ unsigned long i;
+
+ if (WARN_ON(!name || !name[0] || !isxdigit(name[0]) || !name[1]))
+ return NULL;
+ i = isdigit(name[0]) ? name[0] - '0' : 0xa + tolower(name[0]) - 'a';
+
+ switch (name[1]) {
+ case 'l':
+ return &ccn->dt.cmp_mask[i].l;
+ case 'h':
+ return &ccn->dt.cmp_mask[i].h;
+ default:
+ return NULL;
+ }
+}
+
+static ssize_t arm_ccn_pmu_cmp_mask_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
+ u64 *mask = arm_ccn_pmu_get_cmp_mask(ccn, attr->attr.name);
+
+ return mask ? snprintf(buf, PAGE_SIZE, "0x%016llx\n", *mask) : -EINVAL;
+}
+
+static ssize_t arm_ccn_pmu_cmp_mask_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
+ u64 *mask = arm_ccn_pmu_get_cmp_mask(ccn, attr->attr.name);
+ int err = -EINVAL;
+
+ if (mask)
+ err = kstrtoull(buf, 0, mask);
+
+ return err ? err : count;
+}
+
+#define CCN_CMP_MASK_ATTR(_name) \
+ struct device_attribute arm_ccn_pmu_cmp_mask_attr_##_name = \
+ __ATTR(_name, S_IRUGO | S_IWUSR, \
+ arm_ccn_pmu_cmp_mask_show, arm_ccn_pmu_cmp_mask_store)
+
+#define CCN_CMP_MASK_ATTR_RO(_name) \
+ struct device_attribute arm_ccn_pmu_cmp_mask_attr_##_name = \
+ __ATTR(_name, S_IRUGO, arm_ccn_pmu_cmp_mask_show, NULL)
+
+static CCN_CMP_MASK_ATTR(0l);
+static CCN_CMP_MASK_ATTR(0h);
+static CCN_CMP_MASK_ATTR(1l);
+static CCN_CMP_MASK_ATTR(1h);
+static CCN_CMP_MASK_ATTR(2l);
+static CCN_CMP_MASK_ATTR(2h);
+static CCN_CMP_MASK_ATTR(3l);
+static CCN_CMP_MASK_ATTR(3h);
+static CCN_CMP_MASK_ATTR(4l);
+static CCN_CMP_MASK_ATTR(4h);
+static CCN_CMP_MASK_ATTR(5l);
+static CCN_CMP_MASK_ATTR(5h);
+static CCN_CMP_MASK_ATTR(6l);
+static CCN_CMP_MASK_ATTR(6h);
+static CCN_CMP_MASK_ATTR(7l);
+static CCN_CMP_MASK_ATTR(7h);
+static CCN_CMP_MASK_ATTR_RO(8l);
+static CCN_CMP_MASK_ATTR_RO(8h);
+static CCN_CMP_MASK_ATTR_RO(9l);
+static CCN_CMP_MASK_ATTR_RO(9h);
+static CCN_CMP_MASK_ATTR_RO(al);
+static CCN_CMP_MASK_ATTR_RO(ah);
+static CCN_CMP_MASK_ATTR_RO(bl);
+static CCN_CMP_MASK_ATTR_RO(bh);
+
+static struct attribute *arm_ccn_pmu_cmp_mask_attrs[] = {
+ &arm_ccn_pmu_cmp_mask_attr_0l.attr, &arm_ccn_pmu_cmp_mask_attr_0h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_1l.attr, &arm_ccn_pmu_cmp_mask_attr_1h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_2l.attr, &arm_ccn_pmu_cmp_mask_attr_2h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_3l.attr, &arm_ccn_pmu_cmp_mask_attr_3h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_4l.attr, &arm_ccn_pmu_cmp_mask_attr_4h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_5l.attr, &arm_ccn_pmu_cmp_mask_attr_5h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_6l.attr, &arm_ccn_pmu_cmp_mask_attr_6h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_7l.attr, &arm_ccn_pmu_cmp_mask_attr_7h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_8l.attr, &arm_ccn_pmu_cmp_mask_attr_8h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_9l.attr, &arm_ccn_pmu_cmp_mask_attr_9h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_al.attr, &arm_ccn_pmu_cmp_mask_attr_ah.attr,
+ &arm_ccn_pmu_cmp_mask_attr_bl.attr, &arm_ccn_pmu_cmp_mask_attr_bh.attr,
+ NULL
+};
+
+static struct attribute_group arm_ccn_pmu_cmp_mask_attr_group = {
+ .name = "cmp_mask",
+ .attrs = arm_ccn_pmu_cmp_mask_attrs,
+};
+
+
+/*
+ * Default poll period is 10ms, which is way over the top anyway,
+ * as in the worst case scenario (an event every cycle), with 1GHz
+ * clocked bus, the smallest, 32 bit counter will overflow in
+ * more than 4s.
+ */
+static unsigned int arm_ccn_pmu_poll_period_us = 10000;
+module_param_named(pmu_poll_period_us, arm_ccn_pmu_poll_period_us, uint,
+ S_IRUGO | S_IWUSR);
+
+static ktime_t arm_ccn_pmu_timer_period(void)
+{
+ return ns_to_ktime((u64)arm_ccn_pmu_poll_period_us * 1000);
+}
+
+
+static const struct attribute_group *arm_ccn_pmu_attr_groups[] = {
+ &arm_ccn_pmu_events_attr_group,
+ &arm_ccn_pmu_format_attr_group,
+ &arm_ccn_pmu_cmp_mask_attr_group,
+ NULL
+};
+
+
+static int arm_ccn_pmu_alloc_bit(unsigned long *bitmap, unsigned long size)
+{
+ int bit;
+
+ do {
+ bit = find_first_zero_bit(bitmap, size);
+ if (bit >= size)
+ return -EAGAIN;
+ } while (test_and_set_bit(bit, bitmap));
+
+ return bit;
+}
+
+/* All RN-I and RN-D nodes have identical PMUs */
+static int arm_ccn_pmu_type_eq(u32 a, u32 b)
+{
+ if (a == b)
+ return 1;
+
+ switch (a) {
+ case CCN_TYPE_RNI_1P:
+ case CCN_TYPE_RNI_2P:
+ case CCN_TYPE_RNI_3P:
+ case CCN_TYPE_RND_1P:
+ case CCN_TYPE_RND_2P:
+ case CCN_TYPE_RND_3P:
+ switch (b) {
+ case CCN_TYPE_RNI_1P:
+ case CCN_TYPE_RNI_2P:
+ case CCN_TYPE_RNI_3P:
+ case CCN_TYPE_RND_1P:
+ case CCN_TYPE_RND_2P:
+ case CCN_TYPE_RND_3P:
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int arm_ccn_pmu_event_init(struct perf_event *event)
+{
+ struct arm_ccn *ccn;
+ struct hw_perf_event *hw = &event->hw;
+ u32 node_xp, type, event_id;
+ int valid;
+ struct arm_ccn_component *source;
+ int i;
+
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ ccn = pmu_to_arm_ccn(event->pmu);
+
+ if (hw->sample_period) {
+ dev_warn(ccn->dev, "Sampling not supported!\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (has_branch_stack(event) || event->attr.exclude_user ||
+ event->attr.exclude_kernel || event->attr.exclude_hv ||
+ event->attr.exclude_idle) {
+ dev_warn(ccn->dev, "Can't exclude execution levels!\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (event->cpu < 0) {
+ dev_warn(ccn->dev, "Can't provide per-task data!\n");
+ return -EOPNOTSUPP;
+ }
+
+ node_xp = CCN_CONFIG_NODE(event->attr.config);
+ type = CCN_CONFIG_TYPE(event->attr.config);
+ event_id = CCN_CONFIG_EVENT(event->attr.config);
+
+ /* Validate node/xp vs topology */
+ switch (type) {
+ case CCN_TYPE_XP:
+ if (node_xp >= ccn->num_xps) {
+ dev_warn(ccn->dev, "Invalid XP ID %d!\n", node_xp);
+ return -EINVAL;
+ }
+ break;
+ case CCN_TYPE_CYCLES:
+ break;
+ default:
+ if (node_xp >= ccn->num_nodes) {
+ dev_warn(ccn->dev, "Invalid node ID %d!\n", node_xp);
+ return -EINVAL;
+ }
+ if (!arm_ccn_pmu_type_eq(type, ccn->node[node_xp].type)) {
+ dev_warn(ccn->dev, "Invalid type 0x%x for node %d!\n",
+ type, node_xp);
+ return -EINVAL;
+ }
+ break;
+ }
+
+ /* Validate event ID vs available for the type */
+ for (i = 0, valid = 0; i < ARRAY_SIZE(arm_ccn_pmu_events) && !valid;
+ i++) {
+ struct arm_ccn_pmu_event *e = &arm_ccn_pmu_events[i];
+ u32 port = CCN_CONFIG_PORT(event->attr.config);
+ u32 vc = CCN_CONFIG_VC(event->attr.config);
+
+ if (!arm_ccn_pmu_type_eq(type, e->type))
+ continue;
+ if (event_id != e->event)
+ continue;
+ if (e->num_ports && port >= e->num_ports) {
+ dev_warn(ccn->dev, "Invalid port %d for node/XP %d!\n",
+ port, node_xp);
+ return -EINVAL;
+ }
+ if (e->num_vcs && vc >= e->num_vcs) {
+ dev_warn(ccn->dev, "Invalid vc %d for node/XP %d!\n",
+ port, node_xp);
+ return -EINVAL;
+ }
+ valid = 1;
+ }
+ if (!valid) {
+ dev_warn(ccn->dev, "Invalid event 0x%x for node/XP %d!\n",
+ event_id, node_xp);
+ return -EINVAL;
+ }
+
+ /* Watchpoint-based event for a node is actually set on XP */
+ if (event_id == CCN_EVENT_WATCHPOINT && type != CCN_TYPE_XP) {
+ u32 port;
+
+ type = CCN_TYPE_XP;
+ port = arm_ccn_node_to_xp_port(node_xp);
+ node_xp = arm_ccn_node_to_xp(node_xp);
+
+ arm_ccn_pmu_config_set(&event->attr.config,
+ node_xp, type, port);
+ }
+
+ /* Allocate the cycle counter */
+ if (type == CCN_TYPE_CYCLES) {
+ if (test_and_set_bit(CCN_IDX_PMU_CYCLE_COUNTER,
+ ccn->dt.pmu_counters_mask))
+ return -EAGAIN;
+
+ hw->idx = CCN_IDX_PMU_CYCLE_COUNTER;
+ ccn->dt.pmu_counters[CCN_IDX_PMU_CYCLE_COUNTER].event = event;
+
+ return 0;
+ }
+
+ /* Allocate an event counter */
+ hw->idx = arm_ccn_pmu_alloc_bit(ccn->dt.pmu_counters_mask,
+ CCN_NUM_PMU_EVENT_COUNTERS);
+ if (hw->idx < 0) {
+ dev_warn(ccn->dev, "No more counters available!\n");
+ return -EAGAIN;
+ }
+
+ if (type == CCN_TYPE_XP)
+ source = &ccn->xp[node_xp];
+ else
+ source = &ccn->node[node_xp];
+ ccn->dt.pmu_counters[hw->idx].source = source;
+
+ /* Allocate an event source or a watchpoint */
+ if (type == CCN_TYPE_XP && event_id == CCN_EVENT_WATCHPOINT)
+ hw->config_base = arm_ccn_pmu_alloc_bit(source->xp.dt_cmp_mask,
+ CCN_NUM_XP_WATCHPOINTS);
+ else
+ hw->config_base = arm_ccn_pmu_alloc_bit(source->pmu_events_mask,
+ CCN_NUM_PMU_EVENTS);
+ if (hw->config_base < 0) {
+ dev_warn(ccn->dev, "No more event sources/watchpoints on node/XP %d!\n",
+ node_xp);
+ clear_bit(hw->idx, ccn->dt.pmu_counters_mask);
+ return -EAGAIN;
+ }
+
+ ccn->dt.pmu_counters[hw->idx].event = event;
+
+ return 0;
+}
+
+static void arm_ccn_pmu_event_free(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+
+ if (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER) {
+ clear_bit(CCN_IDX_PMU_CYCLE_COUNTER, ccn->dt.pmu_counters_mask);
+ } else {
+ struct arm_ccn_component *source =
+ ccn->dt.pmu_counters[hw->idx].source;
+
+ if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP &&
+ CCN_CONFIG_EVENT(event->attr.config) ==
+ CCN_EVENT_WATCHPOINT)
+ clear_bit(hw->config_base, source->xp.dt_cmp_mask);
+ else
+ clear_bit(hw->config_base, source->pmu_events_mask);
+ clear_bit(hw->idx, ccn->dt.pmu_counters_mask);
+ }
+
+ ccn->dt.pmu_counters[hw->idx].source = NULL;
+ ccn->dt.pmu_counters[hw->idx].event = NULL;
+}
+
+static u64 arm_ccn_pmu_read_counter(struct arm_ccn *ccn, int idx)
+{
+ u64 res;
+
+ if (idx == CCN_IDX_PMU_CYCLE_COUNTER) {
+#ifdef readq
+ res = readq(ccn->dt.base + CCN_DT_PMCCNTR);
+#else
+ /* 40 bit counter, can do snapshot and read in two parts */
+ writel(0x1, ccn->dt.base + CCN_DT_PMSR_REQ);
+ while (!(readl(ccn->dt.base + CCN_DT_PMSR) & 0x1))
+ ;
+ writel(0x1, ccn->dt.base + CCN_DT_PMSR_CLR);
+ res = readl(ccn->dt.base + CCN_DT_PMCCNTRSR + 4) & 0xff;
+ res <<= 32;
+ res |= readl(ccn->dt.base + CCN_DT_PMCCNTRSR);
+#endif
+ } else {
+ res = readl(ccn->dt.base + CCN_DT_PMEVCNT(idx));
+ }
+
+ return res;
+}
+
+static void arm_ccn_pmu_event_update(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ u64 prev_count, new_count, mask;
+
+ do {
+ prev_count = local64_read(&hw->prev_count);
+ new_count = arm_ccn_pmu_read_counter(ccn, hw->idx);
+ } while (local64_xchg(&hw->prev_count, new_count) != prev_count);
+
+ mask = (1LLU << (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER ? 40 : 32)) - 1;
+
+ local64_add((new_count - prev_count) & mask, &event->count);
+}
+
+static void arm_ccn_pmu_xp_dt_config(struct perf_event *event, int enable)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ struct arm_ccn_component *xp;
+ u32 val, dt_cfg;
+
+ if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP)
+ xp = &ccn->xp[CCN_CONFIG_XP(event->attr.config)];
+ else
+ xp = &ccn->xp[arm_ccn_node_to_xp(
+ CCN_CONFIG_NODE(event->attr.config))];
+
+ if (enable)
+ dt_cfg = hw->event_base;
+ else
+ dt_cfg = CCN_XP_DT_CONFIG__DT_CFG__PASS_THROUGH;
+
+ spin_lock(&ccn->dt.config_lock);
+
+ val = readl(xp->base + CCN_XP_DT_CONFIG);
+ val &= ~(CCN_XP_DT_CONFIG__DT_CFG__MASK <<
+ CCN_XP_DT_CONFIG__DT_CFG__SHIFT(hw->idx));
+ val |= dt_cfg << CCN_XP_DT_CONFIG__DT_CFG__SHIFT(hw->idx);
+ writel(val, xp->base + CCN_XP_DT_CONFIG);
+
+ spin_unlock(&ccn->dt.config_lock);
+}
+
+static void arm_ccn_pmu_event_start(struct perf_event *event, int flags)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+
+ local64_set(&event->hw.prev_count,
+ arm_ccn_pmu_read_counter(ccn, hw->idx));
+ hw->state = 0;
+
+ if (!ccn->irq_used)
+ hrtimer_start(&ccn->dt.hrtimer, arm_ccn_pmu_timer_period(),
+ HRTIMER_MODE_REL);
+
+ /* Set the DT bus input, engaging the counter */
+ arm_ccn_pmu_xp_dt_config(event, 1);
+}
+
+static void arm_ccn_pmu_event_stop(struct perf_event *event, int flags)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ u64 timeout;
+
+ /* Disable counting, setting the DT bus to pass-through mode */
+ arm_ccn_pmu_xp_dt_config(event, 0);
+
+ if (!ccn->irq_used)
+ hrtimer_cancel(&ccn->dt.hrtimer);
+
+ /* Let the DT bus drain */
+ timeout = arm_ccn_pmu_read_counter(ccn, CCN_IDX_PMU_CYCLE_COUNTER) +
+ ccn->num_xps;
+ while (arm_ccn_pmu_read_counter(ccn, CCN_IDX_PMU_CYCLE_COUNTER) <
+ timeout)
+ cpu_relax();
+
+ if (flags & PERF_EF_UPDATE)
+ arm_ccn_pmu_event_update(event);
+
+ hw->state |= PERF_HES_STOPPED;
+}
+
+static void arm_ccn_pmu_xp_watchpoint_config(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ struct arm_ccn_component *source =
+ ccn->dt.pmu_counters[hw->idx].source;
+ unsigned long wp = hw->config_base;
+ u32 val;
+ u64 cmp_l = event->attr.config1;
+ u64 cmp_h = event->attr.config2;
+ u64 mask_l = ccn->dt.cmp_mask[CCN_CONFIG_MASK(event->attr.config)].l;
+ u64 mask_h = ccn->dt.cmp_mask[CCN_CONFIG_MASK(event->attr.config)].h;
+
+ hw->event_base = CCN_XP_DT_CONFIG__DT_CFG__WATCHPOINT(wp);
+
+ /* Direction (RX/TX), device (port) & virtual channel */
+ val = readl(source->base + CCN_XP_DT_INTERFACE_SEL);
+ val &= ~(CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__MASK <<
+ CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__SHIFT(wp));
+ val |= CCN_CONFIG_DIR(event->attr.config) <<
+ CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__SHIFT(wp);
+ val &= ~(CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__MASK <<
+ CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__SHIFT(wp));
+ val |= CCN_CONFIG_PORT(event->attr.config) <<
+ CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__SHIFT(wp);
+ val &= ~(CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__MASK <<
+ CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__SHIFT(wp));
+ val |= CCN_CONFIG_VC(event->attr.config) <<
+ CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__SHIFT(wp);
+ writel(val, source->base + CCN_XP_DT_INTERFACE_SEL);
+
+ /* Comparison values */
+ writel(cmp_l & 0xffffffff, source->base + CCN_XP_DT_CMP_VAL_L(wp));
+ writel((cmp_l >> 32) & 0xefffffff,
+ source->base + CCN_XP_DT_CMP_VAL_L(wp) + 4);
+ writel(cmp_h & 0xffffffff, source->base + CCN_XP_DT_CMP_VAL_H(wp));
+ writel((cmp_h >> 32) & 0x0fffffff,
+ source->base + CCN_XP_DT_CMP_VAL_H(wp) + 4);
+
+ /* Mask */
+ writel(mask_l & 0xffffffff, source->base + CCN_XP_DT_CMP_MASK_L(wp));
+ writel((mask_l >> 32) & 0xefffffff,
+ source->base + CCN_XP_DT_CMP_MASK_L(wp) + 4);
+ writel(mask_h & 0xffffffff, source->base + CCN_XP_DT_CMP_MASK_H(wp));
+ writel((mask_h >> 32) & 0x0fffffff,
+ source->base + CCN_XP_DT_CMP_MASK_H(wp) + 4);
+}
+
+static void arm_ccn_pmu_xp_event_config(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ struct arm_ccn_component *source =
+ ccn->dt.pmu_counters[hw->idx].source;
+ u32 val, id;
+
+ hw->event_base = CCN_XP_DT_CONFIG__DT_CFG__XP_PMU_EVENT(hw->config_base);
+
+ id = (CCN_CONFIG_VC(event->attr.config) << 4) |
+ (CCN_CONFIG_PORT(event->attr.config) << 3) |
+ (CCN_CONFIG_EVENT(event->attr.config) << 0);
+
+ val = readl(source->base + CCN_XP_PMU_EVENT_SEL);
+ val &= ~(CCN_XP_PMU_EVENT_SEL__ID__MASK <<
+ CCN_XP_PMU_EVENT_SEL__ID__SHIFT(hw->config_base));
+ val |= id << CCN_XP_PMU_EVENT_SEL__ID__SHIFT(hw->config_base);
+ writel(val, source->base + CCN_XP_PMU_EVENT_SEL);
+}
+
+static void arm_ccn_pmu_node_event_config(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ struct arm_ccn_component *source =
+ ccn->dt.pmu_counters[hw->idx].source;
+ u32 type = CCN_CONFIG_TYPE(event->attr.config);
+ u32 val, port;
+
+ port = arm_ccn_node_to_xp_port(CCN_CONFIG_NODE(event->attr.config));
+ hw->event_base = CCN_XP_DT_CONFIG__DT_CFG__DEVICE_PMU_EVENT(port,
+ hw->config_base);
+
+ /* These *_event_sel regs should be identical, but let's make sure... */
+ BUILD_BUG_ON(CCN_HNF_PMU_EVENT_SEL != CCN_SBAS_PMU_EVENT_SEL);
+ BUILD_BUG_ON(CCN_SBAS_PMU_EVENT_SEL != CCN_RNI_PMU_EVENT_SEL);
+ BUILD_BUG_ON(CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(1) !=
+ CCN_SBAS_PMU_EVENT_SEL__ID__SHIFT(1));
+ BUILD_BUG_ON(CCN_SBAS_PMU_EVENT_SEL__ID__SHIFT(1) !=
+ CCN_RNI_PMU_EVENT_SEL__ID__SHIFT(1));
+ BUILD_BUG_ON(CCN_HNF_PMU_EVENT_SEL__ID__MASK !=
+ CCN_SBAS_PMU_EVENT_SEL__ID__MASK);
+ BUILD_BUG_ON(CCN_SBAS_PMU_EVENT_SEL__ID__MASK !=
+ CCN_RNI_PMU_EVENT_SEL__ID__MASK);
+ if (WARN_ON(type != CCN_TYPE_HNF && type != CCN_TYPE_SBAS &&
+ !arm_ccn_pmu_type_eq(type, CCN_TYPE_RNI_3P)))
+ return;
+
+ /* Set the event id for the pre-allocated counter */
+ val = readl(source->base + CCN_HNF_PMU_EVENT_SEL);
+ val &= ~(CCN_HNF_PMU_EVENT_SEL__ID__MASK <<
+ CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(hw->config_base));
+ val |= CCN_CONFIG_EVENT(event->attr.config) <<
+ CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(hw->config_base);
+ writel(val, source->base + CCN_HNF_PMU_EVENT_SEL);
+}
+
+static void arm_ccn_pmu_event_config(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ u32 xp, offset, val;
+
+ /* Cycle counter requires no setup */
+ if (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER)
+ return;
+
+ if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP)
+ xp = CCN_CONFIG_XP(event->attr.config);
+ else
+ xp = arm_ccn_node_to_xp(CCN_CONFIG_NODE(event->attr.config));
+
+ spin_lock(&ccn->dt.config_lock);
+
+ /* Set the DT bus "distance" register */
+ offset = (hw->idx / 4) * 4;
+ val = readl(ccn->dt.base + CCN_DT_ACTIVE_DSM + offset);
+ val &= ~(CCN_DT_ACTIVE_DSM__DSM_ID__MASK <<
+ CCN_DT_ACTIVE_DSM__DSM_ID__SHIFT(hw->idx % 4));
+ val |= xp << CCN_DT_ACTIVE_DSM__DSM_ID__SHIFT(hw->idx % 4);
+ writel(val, ccn->dt.base + CCN_DT_ACTIVE_DSM + offset);
+
+ if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP) {
+ if (CCN_CONFIG_EVENT(event->attr.config) ==
+ CCN_EVENT_WATCHPOINT)
+ arm_ccn_pmu_xp_watchpoint_config(event);
+ else
+ arm_ccn_pmu_xp_event_config(event);
+ } else {
+ arm_ccn_pmu_node_event_config(event);
+ }
+
+ spin_unlock(&ccn->dt.config_lock);
+}
+
+static int arm_ccn_pmu_event_add(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hw = &event->hw;
+
+ arm_ccn_pmu_event_config(event);
+
+ hw->state = PERF_HES_STOPPED;
+
+ if (flags & PERF_EF_START)
+ arm_ccn_pmu_event_start(event, PERF_EF_UPDATE);
+
+ return 0;
+}
+
+static void arm_ccn_pmu_event_del(struct perf_event *event, int flags)
+{
+ arm_ccn_pmu_event_stop(event, PERF_EF_UPDATE);
+
+ arm_ccn_pmu_event_free(event);
+}
+
+static void arm_ccn_pmu_event_read(struct perf_event *event)
+{
+ arm_ccn_pmu_event_update(event);
+}
+
+static irqreturn_t arm_ccn_pmu_overflow_handler(struct arm_ccn_dt *dt)
+{
+ u32 pmovsr = readl(dt->base + CCN_DT_PMOVSR);
+ int idx;
+
+ if (!pmovsr)
+ return IRQ_NONE;
+
+ writel(pmovsr, dt->base + CCN_DT_PMOVSR_CLR);
+
+ BUILD_BUG_ON(CCN_IDX_PMU_CYCLE_COUNTER != CCN_NUM_PMU_EVENT_COUNTERS);
+
+ for (idx = 0; idx < CCN_NUM_PMU_EVENT_COUNTERS + 1; idx++) {
+ struct perf_event *event = dt->pmu_counters[idx].event;
+ int overflowed = pmovsr & BIT(idx);
+
+ WARN_ON_ONCE(overflowed && !event);
+
+ if (!event || !overflowed)
+ continue;
+
+ arm_ccn_pmu_event_update(event);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static enum hrtimer_restart arm_ccn_pmu_timer_handler(struct hrtimer *hrtimer)
+{
+ struct arm_ccn_dt *dt = container_of(hrtimer, struct arm_ccn_dt,
+ hrtimer);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ arm_ccn_pmu_overflow_handler(dt);
+ local_irq_restore(flags);
+
+ hrtimer_forward_now(hrtimer, arm_ccn_pmu_timer_period());
+ return HRTIMER_RESTART;
+}
+
+
+static DEFINE_IDA(arm_ccn_pmu_ida);
+
+static int arm_ccn_pmu_init(struct arm_ccn *ccn)
+{
+ int i;
+ char *name;
+
+ /* Initialize DT subsystem */
+ ccn->dt.base = ccn->base + CCN_REGION_SIZE;
+ spin_lock_init(&ccn->dt.config_lock);
+ writel(CCN_DT_CTL__DT_EN, ccn->dt.base + CCN_DT_CTL);
+ writel(CCN_DT_PMCR__OVFL_INTR_EN | CCN_DT_PMCR__PMU_EN,
+ ccn->dt.base + CCN_DT_PMCR);
+ writel(0x1, ccn->dt.base + CCN_DT_PMSR_CLR);
+ for (i = 0; i < ccn->num_xps; i++) {
+ writel(0, ccn->xp[i].base + CCN_XP_DT_CONFIG);
+ writel((CCN_XP_DT_CONTROL__WP_ARM_SEL__ALWAYS <<
+ CCN_XP_DT_CONTROL__WP_ARM_SEL__SHIFT(0)) |
+ (CCN_XP_DT_CONTROL__WP_ARM_SEL__ALWAYS <<
+ CCN_XP_DT_CONTROL__WP_ARM_SEL__SHIFT(1)) |
+ CCN_XP_DT_CONTROL__DT_ENABLE,
+ ccn->xp[i].base + CCN_XP_DT_CONTROL);
+ }
+ ccn->dt.cmp_mask[CCN_IDX_MASK_ANY].l = ~0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_ANY].h = ~0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_EXACT].l = 0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_EXACT].h = 0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_ORDER].l = ~0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_ORDER].h = ~(0x1 << 15);
+ ccn->dt.cmp_mask[CCN_IDX_MASK_OPCODE].l = ~0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_OPCODE].h = ~(0x1f << 9);
+
+ /* Get a convenient /sys/event_source/devices/ name */
+ ccn->dt.id = ida_simple_get(&arm_ccn_pmu_ida, 0, 0, GFP_KERNEL);
+ if (ccn->dt.id == 0) {
+ name = "ccn";
+ } else {
+ int len = snprintf(NULL, 0, "ccn_%d", ccn->dt.id);
+
+ name = devm_kzalloc(ccn->dev, len + 1, GFP_KERNEL);
+ snprintf(name, len + 1, "ccn_%d", ccn->dt.id);
+ }
+
+ /* Perf driver registration */
+ ccn->dt.pmu = (struct pmu) {
+ .attr_groups = arm_ccn_pmu_attr_groups,
+ .task_ctx_nr = perf_invalid_context,
+ .event_init = arm_ccn_pmu_event_init,
+ .add = arm_ccn_pmu_event_add,
+ .del = arm_ccn_pmu_event_del,
+ .start = arm_ccn_pmu_event_start,
+ .stop = arm_ccn_pmu_event_stop,
+ .read = arm_ccn_pmu_event_read,
+ };
+
+ /* No overflow interrupt? Have to use a timer instead. */
+ if (!ccn->irq_used) {
+ dev_info(ccn->dev, "No access to interrupts, using timer.\n");
+ hrtimer_init(&ccn->dt.hrtimer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ ccn->dt.hrtimer.function = arm_ccn_pmu_timer_handler;
+ }
+
+ return perf_pmu_register(&ccn->dt.pmu, name, -1);
+}
+
+static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
+{
+ int i;
+
+ for (i = 0; i < ccn->num_xps; i++)
+ writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
+ writel(0, ccn->dt.base + CCN_DT_PMCR);
+ perf_pmu_unregister(&ccn->dt.pmu);
+ ida_simple_remove(&arm_ccn_pmu_ida, ccn->dt.id);
+}
+
+
+static int arm_ccn_for_each_valid_region(struct arm_ccn *ccn,
+ int (*callback)(struct arm_ccn *ccn, int region,
+ void __iomem *base, u32 type, u32 id))
+{
+ int region;
+
+ for (region = 0; region < CCN_NUM_REGIONS; region++) {
+ u32 val, type, id;
+ void __iomem *base;
+ int err;
+
+ val = readl(ccn->base + CCN_MN_OLY_COMP_LIST_63_0 +
+ 4 * (region / 32));
+ if (!(val & (1 << (region % 32))))
+ continue;
+
+ base = ccn->base + region * CCN_REGION_SIZE;
+ val = readl(base + CCN_ALL_OLY_ID);
+ type = (val >> CCN_ALL_OLY_ID__OLY_ID__SHIFT) &
+ CCN_ALL_OLY_ID__OLY_ID__MASK;
+ id = (val >> CCN_ALL_OLY_ID__NODE_ID__SHIFT) &
+ CCN_ALL_OLY_ID__NODE_ID__MASK;
+
+ err = callback(ccn, region, base, type, id);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int arm_ccn_get_nodes_num(struct arm_ccn *ccn, int region,
+ void __iomem *base, u32 type, u32 id)
+{
+
+ if (type == CCN_TYPE_XP && id >= ccn->num_xps)
+ ccn->num_xps = id + 1;
+ else if (id >= ccn->num_nodes)
+ ccn->num_nodes = id + 1;
+
+ return 0;
+}
+
+static int arm_ccn_init_nodes(struct arm_ccn *ccn, int region,
+ void __iomem *base, u32 type, u32 id)
+{
+ struct arm_ccn_component *component;
+
+ dev_dbg(ccn->dev, "Region %d: id=%u, type=0x%02x\n", region, id, type);
+
+ switch (type) {
+ case CCN_TYPE_MN:
+ case CCN_TYPE_DT:
+ return 0;
+ case CCN_TYPE_XP:
+ component = &ccn->xp[id];
+ break;
+ case CCN_TYPE_SBSX:
+ ccn->sbsx_present = 1;
+ component = &ccn->node[id];
+ break;
+ case CCN_TYPE_SBAS:
+ ccn->sbas_present = 1;
+ /* Fall-through */
+ default:
+ component = &ccn->node[id];
+ break;
+ }
+
+ component->base = base;
+ component->type = type;
+
+ return 0;
+}
+
+
+static irqreturn_t arm_ccn_error_handler(struct arm_ccn *ccn,
+ const u32 *err_sig_val)
+{
+ /* This should be really handled by firmware... */
+ dev_err(ccn->dev, "Error reported in %08x%08x%08x%08x%08x%08x.\n",
+ err_sig_val[5], err_sig_val[4], err_sig_val[3],
+ err_sig_val[2], err_sig_val[1], err_sig_val[0]);
+ dev_err(ccn->dev, "Disabling interrupt generation for all errors.\n");
+ writel(CCN_MN_ERRINT_STATUS__ALL_ERRORS__DISABLE,
+ ccn->base + CCN_MN_ERRINT_STATUS);
+
+ return IRQ_HANDLED;
+}
+
+
+static irqreturn_t arm_ccn_irq_handler(int irq, void *dev_id)
+{
+ irqreturn_t res = IRQ_NONE;
+ struct arm_ccn *ccn = dev_id;
+ u32 err_sig_val[6];
+ u32 err_or;
+ int i;
+
+ /* PMU overflow is a special case */
+ err_or = err_sig_val[0] = readl(ccn->base + CCN_MN_ERR_SIG_VAL_63_0);
+ if (err_or & CCN_MN_ERR_SIG_VAL_63_0__DT) {
+ err_or &= ~CCN_MN_ERR_SIG_VAL_63_0__DT;
+ res = arm_ccn_pmu_overflow_handler(&ccn->dt);
+ }
+
+ /* Have to read all err_sig_vals to clear them */
+ for (i = 1; i < ARRAY_SIZE(err_sig_val); i++) {
+ err_sig_val[i] = readl(ccn->base +
+ CCN_MN_ERR_SIG_VAL_63_0 + i * 4);
+ err_or |= err_sig_val[i];
+ }
+ if (err_or)
+ res |= arm_ccn_error_handler(ccn, err_sig_val);
+
+ if (res != IRQ_NONE)
+ writel(CCN_MN_ERRINT_STATUS__INTREQ__DESSERT,
+ ccn->base + CCN_MN_ERRINT_STATUS);
+
+ return res;
+}
+
+
+static int arm_ccn_probe(struct platform_device *pdev)
+{
+ struct arm_ccn *ccn;
+ struct resource *res;
+ int err;
+
+ ccn = devm_kzalloc(&pdev->dev, sizeof(*ccn), GFP_KERNEL);
+ if (!ccn)
+ return -ENOMEM;
+ ccn->dev = &pdev->dev;
+ platform_set_drvdata(pdev, ccn);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ if (!devm_request_mem_region(ccn->dev, res->start,
+ resource_size(res), pdev->name))
+ return -EBUSY;
+
+ ccn->base = devm_ioremap(ccn->dev, res->start,
+ resource_size(res));
+ if (!ccn->base)
+ return -EFAULT;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res)
+ return -EINVAL;
+
+ /* Check if we can use the interrupt */
+ writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLE,
+ ccn->base + CCN_MN_ERRINT_STATUS);
+ if (readl(ccn->base + CCN_MN_ERRINT_STATUS) &
+ CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLED) {
+ /* Can set 'disable' bits, so can acknowledge interrupts */
+ writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__ENABLE,
+ ccn->base + CCN_MN_ERRINT_STATUS);
+ err = devm_request_irq(ccn->dev, res->start,
+ arm_ccn_irq_handler, 0, dev_name(ccn->dev),
+ ccn);
+ if (err)
+ return err;
+
+ ccn->irq_used = 1;
+ }
+
+
+ /* Build topology */
+
+ err = arm_ccn_for_each_valid_region(ccn, arm_ccn_get_nodes_num);
+ if (err)
+ return err;
+
+ ccn->node = devm_kzalloc(ccn->dev, sizeof(*ccn->node) * ccn->num_nodes,
+ GFP_KERNEL);
+ ccn->xp = devm_kzalloc(ccn->dev, sizeof(*ccn->node) * ccn->num_xps,
+ GFP_KERNEL);
+ if (!ccn->node || !ccn->xp)
+ return -ENOMEM;
+
+ err = arm_ccn_for_each_valid_region(ccn, arm_ccn_init_nodes);
+ if (err)
+ return err;
+
+ return arm_ccn_pmu_init(ccn);
+}
+
+static int arm_ccn_remove(struct platform_device *pdev)
+{
+ struct arm_ccn *ccn = platform_get_drvdata(pdev);
+
+ arm_ccn_pmu_cleanup(ccn);
+
+ return 0;
+}
+
+static const struct of_device_id arm_ccn_match[] = {
+ { .compatible = "arm,ccn-504", },
+ {},
+};
+
+static struct platform_driver arm_ccn_driver = {
+ .driver = {
+ .name = "arm-ccn",
+ .of_match_table = arm_ccn_match,
+ },
+ .probe = arm_ccn_probe,
+ .remove = arm_ccn_remove,
+};
+
+static int __init arm_ccn_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(arm_ccn_pmu_events); i++)
+ arm_ccn_pmu_events_attrs[i] = &arm_ccn_pmu_events[i].attr.attr;
+
+ return platform_driver_register(&arm_ccn_driver);
+}
+
+static void __exit arm_ccn_exit(void)
+{
+ platform_driver_unregister(&arm_ccn_driver);
+}
+
+module_init(arm_ccn_init);
+module_exit(arm_ccn_exit);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_LICENSE("GPL");
--
1.9.1
^ permalink raw reply related
* [GIT PULL 4/5] Samsung exynos_mct update for v3.17
From: Daniel Lezcano @ 2014-07-22 17:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <01b601cfa59c$12c2c7f0$384857d0$@samsung.com>
On 07/22/2014 12:59 PM, Kukjin Kim wrote:
> Daniel Lezcano wrote:
>>
>> On 07/20/2014 12:06 AM, Olof Johansson wrote:
>>> On Sat, Jul 19, 2014 at 09:52:52AM +0900, Kukjin Kim wrote:
>>>> Note that this is also based on 3.16-rc5 because of dependency with
>>>> previous samsung fixes including exynos_mct already merged in
>>>> mainline during -rc.
>>>>
>>>> The following changes since commit 1795cd9b3a91d4b5473c97f491d63892442212ab:
>>>>
>>>> Linux 3.16-rc5 (2014-07-13 14:04:33 -0700)
>>>>
>>>> are available in the git repository at:
>>>>
>>>
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
>>>> tags/exynos-mct
>>>>
>>>> for you to fetch changes up to 1a631118c1d085fe162f3b6d44f710c72206ef2d:
>>>>
>>>> clocksource: exynos_mct: Only use 32-bits where possible
>>>> (2014-07-19 03:07:52 +0900)
>>>>
>>>> ----------------------------------------------------------------
>>>> exynos_mct update for v3.17
>>>> - only use 32-bit access for performance benefits on exynos
>>>> 32-bit system and this means ARCH timer should be supported
>>>> on exynos 64-bit system instead of current MCT.
>>>> - use readl_relaxed/writel_relaxed to consistently use the
>>>> proper functions in exynos_mct.
>>>
>>> There's no reason for these to go through arm-soc, is there? They should
>>> go through the clocksource tree (Daniel Lezcano / Thomas Gleixner). They
>>> also lack acks from them if they for some reason need to go through arm-soc.
>>
> Olof, you're right. The branch has no dependency with arm-soc so I agreed.
>
>> Yes, that's right. Furthermore I have been discussing with Doug about
>> these patches before.
>>
>> Kukjin, is there any dependency on these patches ?
>>
> Yeah, Daniel, it should be handled in the clocksource tree so how should I do
> for it?
I can pull your branch v3.17-next/mct-exynos and you drop the merge from
this branch in your master ?
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH v2] platform: Make platform_bus device a platform device
From: Pawel Moll @ 2014-07-22 17:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140722171013.GA6605@kroah.com>
On Tue, 2014-07-22 at 18:10 +0100, Greg Kroah-Hartman wrote:
> On Tue, Jul 22, 2014 at 11:02:07AM +0100, Pawel Moll wrote:
> > ... describing the root of the device tree, so one can write
> > a platform driver initializing the platform.
> >
> > All references to platform_bus device have been fixed up,
> > although in most cases they could be simply removed or
> > replaced by NULL (platform devices with no parent are adopted
> > by main platform_bus device automagically).
>
> In looking at this some more, I think all of these should be made NULL,
> why are we exporting this symbol at all?
I think there are about 3 non-obvious uses of it, which would probably
need looking into. All other ones that simply do of_platform_populate()
or platform_device_register*() with platform_bus as a parent, which has
exactly the same effect as it was NULL.
I can imagine situations where one would want to walk the device
hierarchy stopping at platform_bus, how I'm not sure how "legitimate"
that would be.
I'll post v3 with NULLs where I think it is enough so we can see the
other cases.
Pawel
^ permalink raw reply
* [PATCH] kvmtool: arm64: fix compilation error
From: Joel Schopp @ 2014-07-22 17:28 UTC (permalink / raw)
To: linux-arm-kernel
Currently tools/kvm doesn't build on arm64 when gtk3 is present. The error looks like this:
LINK lkvm
ui/gtk3.o: In function `kvm_gtk_key_press':
/extra/sb/linux-kvm/tools/kvm/ui/gtk3.c:201: undefined reference to `kbd_queue'
/extra/sb/linux-kvm/tools/kvm/ui/gtk3.c:204: undefined reference to `kbd_queue'
/extra/sb/linux-kvm/tools/kvm/ui/gtk3.c:216: undefined reference to `kbd_queue'
/extra/sb/linux-kvm/tools/kvm/ui/gtk3.c:217: undefined reference to `kbd_queue'
/extra/sb/linux-kvm/tools/kvm/ui/gtk3.c:218: undefined reference to `kbd_queue'
ui/gtk3.o:/extra/sb/linux-kvm/tools/kvm/ui/gtk3.c:219: more undefined references to `kbd_queue' follow
collect2: error: ld returned 1 exit status
make: *** [lkvm] Error 1
The patch below makes the error go away and the resulting lkvm runs on arm64.
Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Joel Schopp <joel.schopp@amd.com>
---
tools/kvm/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index 880d580..fba60f1 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -102,6 +102,7 @@ OBJS += hw/pci-shmem.o
OBJS += kvm-ipc.o
OBJS += builtin-sandbox.o
OBJS += virtio/mmio.o
+OBJS += hw/i8042.o
# Translate uname -m into ARCH string
ARCH ?= $(shell uname -m | sed -e s/i.86/i386/ -e s/ppc.*/powerpc/ \
@@ -129,7 +130,6 @@ ifeq ($(ARCH),x86)
OBJS += x86/kvm.o
OBJS += x86/kvm-cpu.o
OBJS += x86/mptable.o
- OBJS += hw/i8042.o
# Exclude BIOS object files from header dependencies.
OTHEROBJS += x86/bios.o
OTHEROBJS += x86/bios/bios-rom.o
^ permalink raw reply related
* [PATCH 2/2] arm: add early_ioremap support
From: Tomasz Figa @ 2014-07-22 17:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAL_Jsq+hRYySuT_40iGVwe-8GYuPBmHy+GbqQ6T5HSCDfCSMQw@mail.gmail.com>
On 22.07.2014 19:11, Rob Herring wrote:
> On Tue, Jul 22, 2014 at 11:48 AM, Tomasz Figa <t.figa@samsung.com> wrote:
>> Hi Leif,
>>
>> On 09.07.2014 11:39, Leif Lindholm wrote:
>>> From: Mark Salter <msalter@redhat.com>
>>>
>>> This patch uses the generic early_ioremap code to implement
>>> early_ioremap for ARM. The ARM-specific bits come mostly from
>>> an earlier patch from Leif Lindholm <leif.lindholm@linaro.org>
>>> here:
>>>
>>> https://lkml.org/lkml/2013/10/3/279
>>
>> [snip]
>>
>>> diff --git a/arch/arm/mm/early_ioremap.c b/arch/arm/mm/early_ioremap.c
>>> new file mode 100644
>>> index 0000000..1013109
>>> --- /dev/null
>>> +++ b/arch/arm/mm/early_ioremap.c
>>> @@ -0,0 +1,86 @@
>>> +/*
>>> + * early_ioremap() support for ARM
>>> + *
>>> + * Based on existing support in arch/x86/mm/ioremap.c
>>> + *
>>> + * Restrictions: currently only functional before paging_init()
>>
>> Uhm, that's bad... This would explain why my earlycon code generates a
>> fault as soon as something prints after paging_init(). I'd say this
>> feature would be much more useful if mappings were carried over
>> paging_init(), so that mapped devices are available later as well.
>>
>> I'll see if I can code this on top of your patch, but unfortunately it
>> might end up with -ENOTIME.
>
> I have fixmap support that's needed for earlycon. Here is the branch:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git fixmap
>
> It is based on an earlier version of patchset and not on the latest
> version from Leif. Unfortunately, I don't have more time to spend on
> it ATM.
Thanks Rob. I'll give it a try.
Best regards,
Tomasz
^ permalink raw reply
* [PATCH 5/8] of: Add Tegra124 EMC bindings
From: Andrew Bresticker @ 2014-07-22 17:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <53CE9514.1050903@wwwdotorg.org>
On Tue, Jul 22, 2014 at 9:45 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>
> Does the bootloader adjust the DT that's passed to the kernel so that
> only the relevant single set of EMC timings is contained in the DT?
No, the DT contains all possible EMC timings for that board.
> On a system where the boot ROM initializes RAM, and where the HW design
> might have multiple SDRAM configuration, here's what usually happens:
>
> a) The BCT contains N sets of SDRAM configurations.
>
> b) The boot ROM reads the SDRAM strapping bits, and uses them to pick
> the correct SDRAM configuration from the N sets in the BCT.
>
> c) The kernel DT has N sets of SDRAM configurations.
>
> d) The kernel reads the SDRAM strapping bits, and uses them to pick the
> correct SDRAM configuration from the N sets in the DT.
>
> On the ChromeOS boards (so (a) and (b) above are irrelevant) where N is
> too large to fit into APBDEV_PMC_STRAPPING_OPT_A_0[7:4], (c) and (d)
> won't work. I assume the kernel DT therefore must be adjusted to only
> contain the single SDRAM configuration that is relevant for the current HW?
>
> (isn't STRAPPING_OPT_A split into 2 2-bit fields; 2 bits for SDRAM index
> and 2 bits for boot flash index, so max N is quite small?)
Right, there are normally only 2 SDRAM strapping bits available.
ChromeOS gets around this by having 4 identical boot device entries in
the BCT, so all possible values of STRAPPING_OPT_A[7:6] map to the
same boot device. This allows us to use all 4 strapping bits in
coreboot to pick the SDRAM configuration.
^ permalink raw reply
* [PATCH 4/6] clk: tegra: add nvidia,tegra132-ccplex-clk binding
From: Stephen Warren @ 2014-07-22 17:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405437890-6468-5-git-send-email-pdeschrijver@nvidia.com>
On 07/15/2014 09:24 AM, Peter De Schrijver wrote:
> Tegra132 has a few new clocks for the CPU complex (ccplex).
> diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra132-ccplex-clk.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra132-ccplex-clk.txt
> +Example SoC include file:
> +
> +/ {
> + ccplex-clock at 0,70040000 {
> + compatible = "nvidia,tegra132-ccplex-clk";
> + reg = <0x0 0x70040000 0x0 0x1000>;
> + status = "okay";
That's the default, so it's not worth including that property.
^ permalink raw reply
* [PATCH 1/6] clk: tegra: don't abort clk init on error
From: Stephen Warren @ 2014-07-22 17:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405437890-6468-2-git-send-email-pdeschrijver@nvidia.com>
On 07/15/2014 09:24 AM, Peter De Schrijver wrote:
> Just continue initializing clocks if there's an error on one of them. This
> is useful if there's a mistake in the inittable, because the system could
> hang if clk_disable_unused() disables some of the critical clocks in this
> table.
If there's a problem in the init table, we should simply fix it instead
of working around it.
At the very least, we need to WARN on this rather than just ignoring
problems.
^ permalink raw reply
* [PATCH 2/6] clk: tegra: make tegra_clocks_apply_init_table arch_initcall
From: Stephen Warren @ 2014-07-22 17:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405437890-6468-3-git-send-email-pdeschrijver@nvidia.com>
On 07/15/2014 09:24 AM, Peter De Schrijver wrote:
> tegra_clocks_apply_init_table needs to be called after the udelay loop has
> been calibrated (see 441f199a37cfd66c5dd8dd45490bd3ea6971117d why that is).
Instead of just the commit ID, can you please mention the commit subject
too:
441f199a37cf "clk: tegra: defer application of init table"
> On existing Tegra SoCs this was done by calling tegra_clocks_apply_init_table
> from tegra_dt_init. To make this also work on ARM64, we need to
> change this into an initcall. tegra_dt_init is called from customize_machine
> which is an arch_initcall. Therefore this should also work on existing 32bit
> Tegra SoCs.
I still strongly dislike performing this basic initialization from
random separate initcalls. I think we should create a single initcall
for all the Tegra initialization, even if it isn't able to be a machine
descriptor hook function any more.
That said, discussions re: that are ongoing in other threads, so it's no
worth reworking this patch yet.
^ permalink raw reply
* [PATCH 2/2] arm: add early_ioremap support
From: Rob Herring @ 2014-07-22 17:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <53CE95C2.8090807@samsung.com>
On Tue, Jul 22, 2014 at 11:48 AM, Tomasz Figa <t.figa@samsung.com> wrote:
> Hi Leif,
>
> On 09.07.2014 11:39, Leif Lindholm wrote:
>> From: Mark Salter <msalter@redhat.com>
>>
>> This patch uses the generic early_ioremap code to implement
>> early_ioremap for ARM. The ARM-specific bits come mostly from
>> an earlier patch from Leif Lindholm <leif.lindholm@linaro.org>
>> here:
>>
>> https://lkml.org/lkml/2013/10/3/279
>
> [snip]
>
>> diff --git a/arch/arm/mm/early_ioremap.c b/arch/arm/mm/early_ioremap.c
>> new file mode 100644
>> index 0000000..1013109
>> --- /dev/null
>> +++ b/arch/arm/mm/early_ioremap.c
>> @@ -0,0 +1,86 @@
>> +/*
>> + * early_ioremap() support for ARM
>> + *
>> + * Based on existing support in arch/x86/mm/ioremap.c
>> + *
>> + * Restrictions: currently only functional before paging_init()
>
> Uhm, that's bad... This would explain why my earlycon code generates a
> fault as soon as something prints after paging_init(). I'd say this
> feature would be much more useful if mappings were carried over
> paging_init(), so that mapped devices are available later as well.
>
> I'll see if I can code this on top of your patch, but unfortunately it
> might end up with -ENOTIME.
I have fixmap support that's needed for earlycon. Here is the branch:
git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git fixmap
It is based on an earlier version of patchset and not on the latest
version from Leif. Unfortunately, I don't have more time to spend on
it ATM.
Rob
^ permalink raw reply
* [PATCH v2] platform: Make platform_bus device a platform device
From: Greg Kroah-Hartman @ 2014-07-22 17:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1406023327-18525-1-git-send-email-pawel.moll@arm.com>
On Tue, Jul 22, 2014 at 11:02:07AM +0100, Pawel Moll wrote:
> ... describing the root of the device tree, so one can write
> a platform driver initializing the platform.
>
> All references to platform_bus device have been fixed up,
> although in most cases they could be simply removed or
> replaced by NULL (platform devices with no parent are adopted
> by main platform_bus device automagically).
In looking at this some more, I think all of these should be made NULL,
why are we exporting this symbol at all?
I think we should remove all of these references, and just make
platform_bus static, like all other busses are, no reason platform
should be "special" here. It's "special" enough as it is :(
thanks,
greg k-h
^ permalink raw reply
* [PATCH] efi/arm64: efistub: don't abort if base of DRAM is occupied
From: Leif Lindholm @ 2014-07-22 17:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405516428.25580.58.camel@deneb.redhat.com>
(Argh, late reply due to broken mail filters.)
On Wed, Jul 16, 2014 at 09:13:48AM -0400, Mark Salter wrote:
> > > > > > > > Is the spin table area really allocated as BOOT_SERVICES_*?
> > > > > > >
> > > > > > > No. It is EFI_RESERVED_TYPE. But if UEFI is allowed below the kernel,
> > > > > > > then there could be BS code/data memory which we'd want to ignore.
> > > > > >
> > > > > > Well, if it is boot service code/data - then there is no need for us
> > > > > > to keep it around after ExitBootServices().
> > > > >
> > > > > One would think, but EFI has proven to be less than strictly compliant
> > > > > in that regard in the past. I'm inclined to keep the boot services
> > > > > around until after SetVirtualAddressMap just in case.
> > > >
> > > > But the function you add this clause to will still throw away all boot
> > > > services code/data regions - just with this modification it skips
> > > > those that happen to lie lower in the address space than the kernel.
> >
> > Returning to the actual code we are discussing here:
> > The hunk above has no bearing on whether boot services regions are
> > generally unmapped or not. It only filters explicitly those boot
> > services regions that happen to be lower in memory than the kernel,
> > and keep them around for the duration of the system.
>
> It doesn't filter them to keep them around, it filters them to avoid
> calling free_bootmem_late() with an invalid address. If there are UEFI
> regions below the kernel, we don't want to call memblock_reserve() or
> free_bootmem_late() for them.
Then why not just flip things around and do like the arm port and only
add the blocks we actually want to keep around to begin with?
> > > > (And I do agree with Mark R here - let's not work around bugs that
> > > > don't exist yet.)
> > > >
> > >
> > > I'm not sure if they still exist or not, but on Foundation, I saw a
> > > crash in SetVirtualAddressMap unless I kept BS regions around.
> >
> > For the topic of keeping boot services code around:
> > I did also see issues with not keeping boot services regions on v7 -
> > ages ago. I have not seen it this year, and I _really_ want to see if
> > any such issues resurface.
>
> My view is that a problem has been seen in the past with tianocore for
> arm64. There is no harm in delaying the freeing of BS regions.
There is a huge harm.
> The
> memory becomes usable for general kernel use at early_initcall time.
> This issue has also been seen with x86 firmware and some of those same
> vendors will be providing arm64 firmware.
This issue has been seen with x86 firmware because in the early days
(last year) noone bothered validating anything other than CSM. They no
longer have that luxury.
The Linux kernel, currently being the most avid tester of existing
arm64 UEFI firmware, falling over itself to cater for hypothetical
broken implementations pretty much guarantees the situation will end
up just as bad as it ever was on x86 - without us even having CSM.
> The problem isn't reproducible
> now, but I'm not sure if there was a bug fix for it or if it just went
> underground for some reason. Kernel boot may succeed by chance if some
> needed BS memory isn't reused by kernel.
And it may succeed by chance anyway.
I'm not saying we won't see broken firmware - I'm saying that this is
the window we have to try to _help_ people (and ourselves) by letting
broken firmware fail - before it happens in the data centre.
> > So post-3.16 I would quite like to see the
> > call to free_boot_services() moved earlier to flush out any such
> > issues before we see large-scale deployments.
> >
>
> You can just get rid of it altogether:
Well, clearly, that would not be my preference :)
> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> index 453b7f8..06b59d9 100644
> --- a/arch/arm64/kernel/efi.c
> +++ b/arch/arm64/kernel/efi.c
> @@ -177,9 +177,7 @@ static __init void reserve_regions(void)
> if (is_normal_ram(md))
> early_init_dt_add_memory_arch(paddr, size);
>
> - if (is_reserve_region(md) ||
> - md->type == EFI_BOOT_SERVICES_CODE ||
> - md->type == EFI_BOOT_SERVICES_DATA) {
> + if (is_reserve_region(md)) {
> memblock_reserve(paddr, size);
> if (uefi_debug)
> pr_cont("*");
> @@ -191,122 +189,6 @@ static __init void reserve_regions(void)
> }
>
>
> -static u64 __init free_one_region(u64 start, u64 end)
> -{
> - u64 size = end - start;
> -
> - if (uefi_debug)
> - pr_info(" EFI freeing: 0x%012llx-0x%012llx\n", start, end - 1);
> -
> - free_bootmem_late(start, size);
> - return size;
> -}
> -
> -static u64 __init free_region(u64 start, u64 end)
> -{
> - u64 map_start, map_end, total = 0;
> -
> - if (end <= start)
> - return total;
> -
> - map_start = (u64)memmap.phys_map;
> - map_end = PAGE_ALIGN(map_start + (memmap.map_end - memmap.map));
> - map_start &= PAGE_MASK;
> -
> - if (start < map_end && end > map_start) {
> - /* region overlaps UEFI memmap */
> - if (start < map_start)
> - total += free_one_region(start, map_start);
> -
> - if (map_end < end)
> - total += free_one_region(map_end, end);
> - } else
> - total += free_one_region(start, end);
> -
> - return total;
> -}
> -
> -static void __init free_boot_services(void)
> -{
> - u64 total_freed = 0;
> - u64 keep_end, free_start, free_end;
> - efi_memory_desc_t *md;
> -
> - /*
> - * If kernel uses larger pages than UEFI, we have to be careful
> - * not to inadvertantly free memory we want to keep if there is
> - * overlap at the kernel page size alignment. We do not want to
> - * free is_reserve_region() memory nor the UEFI memmap itself.
> - *
> - * The memory map is sorted, so we keep track of the end of
> - * any previous region we want to keep, remember any region
> - * we want to free and defer freeing it until we encounter
> - * the next region we want to keep. This way, before freeing
> - * it, we can clip it as needed to avoid freeing memory we
> - * want to keep for UEFI.
> - */
> -
> - keep_end = 0;
> - free_start = 0;
> -
> - for_each_efi_memory_desc(&memmap, md) {
> - u64 paddr, npages, size;
> -
> - if (is_reserve_region(md)) {
> - /*
> - * We don't want to free any memory from this region.
> - */
> - if (free_start) {
> - /* adjust free_end then free region */
> - if (free_end > md->phys_addr)
> - free_end -= PAGE_SIZE;
> - total_freed += free_region(free_start, free_end);
> - free_start = 0;
> - }
> - keep_end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
> - continue;
> - }
> -
> - if (md->type != EFI_BOOT_SERVICES_CODE &&
> - md->type != EFI_BOOT_SERVICES_DATA) {
> - /* no need to free this region */
> - continue;
> - }
> -
> - /*
> - * We want to free memory from this region.
> - */
> - paddr = md->phys_addr;
> - npages = md->num_pages;
> - memrange_efi_to_native(&paddr, &npages);
> - size = npages << PAGE_SHIFT;
> -
> - if (free_start) {
> - if (paddr <= free_end)
> - free_end = paddr + size;
> - else {
> - total_freed += free_region(free_start, free_end);
> - free_start = paddr;
> - free_end = paddr + size;
> - }
> - } else {
> - free_start = paddr;
> - free_end = paddr + size;
> - }
> - if (free_start < keep_end) {
> - free_start += PAGE_SIZE;
> - if (free_start >= free_end)
> - free_start = 0;
> - }
> - }
> - if (free_start)
> - total_freed += free_region(free_start, free_end);
> -
> - if (total_freed)
> - pr_info("Freed 0x%llx bytes of EFI boot services memory",
> - total_freed);
> -}
> -
> void __init efi_init(void)
> {
> struct efi_fdt_params params;
> @@ -439,8 +321,6 @@ static int __init arm64_enter_virtual_mode(void)
>
> kfree(virtmap);
>
> - free_boot_services();
> -
> if (status != EFI_SUCCESS) {
> pr_err("Failed to set EFI virtual address map! [%lx]\n",
> status);
>
>
>
^ permalink raw reply
* [GIT PULL 2/3] ARM: tegra: move fuse code out of arch/arm
From: Catalin Marinas @ 2014-07-22 17:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <53CE8FB1.4060307@wwwdotorg.org>
On Tue, Jul 22, 2014 at 05:22:09PM +0100, Stephen Warren wrote:
> On 07/22/2014 05:26 AM, Catalin Marinas wrote:
> > On Mon, Jul 21, 2014 at 05:38:25PM +0100, Stephen Warren wrote:
> >> On 07/21/2014 09:54 AM, Catalin Marinas wrote:
> >>> On arm64, I really want to get away from any SoC specific early
> >>> initcall. One of the main reason is for things like SCU, interconnects,
> >>> system cache configurations (even certain clocks) to be enabled in
> >>> firmware before Linux starts (it's an education process but that's a way
> >>> for example to prevent people sending patches to enable SoC coherency
> >>> because they haven't thought about it before upstreaming).
> >>>
> >>> It would be nice to be able to initialise SoC stuff at device_initcall()
> >>> level (and even keep such code as modules in initramfs) but one of the
> >>> problems we have is dependency on clocks (and the clock model which
> >>> doesn't follow the device/driver model). The of_platform_populate() is
> >>> called at arch_initcall_sync (after arch_initcall to still allow some
> >>> SoC code, if needed, to run at arch_initcall).
> >>
> >> The main thing I want to avoid is a ton of separate drivers that all
> >> rely on each-other getting resolved by deferred probe. While that might
> >> work out, it seems pointless to make the kernel try and probe a bunch of
> >> stuff just to have it fail and get repeated, when we know exactly which
> >> order everything should get initialized in.
> >
> > So of_platform_populate() is called at arch_initcall_sync() level on
> > arm64. This allows at least two levels of probing separation before
> > (e.g. drivers registered as arch_initcall) and after (device_initcall).
> > If you register a driver earlier than arch_initcall_sync (see for
> > example vexpress_osc_init), it will get probed when the platform devices
> > are populated. Any later device_initcalls will get probed when the
> > corresponding drivers are registered. If you need ordering between
> > device_initcalls, I would recommend deferred probing.
> >
> > The tricky part is if you need more drivers to be initialised at
> > arch_initcall_sync() in a specific order.
>
> I believe relying on initcall ordering, even in the case where there are
> enough initcall levels to achieve a particular SoC's needs, is
> completely and utterly the wrong way to go.
I don't like it either and I agree that there may not be enough
initcalls. But I'm ok with using two levels like arch_initcall() for
something like fuse and device_initcall() for the rest. If that's not
enough (I haven't looked in detail at Tegra), with Pawel's patch you can
get a SoC specific probe where you can call the initialisation in the
right order.
Tegra is not the first nor the last platform with such issue. Is there
anything we could do better at the DT or driver registration level
(other than introducing machine_desc)?
--
Catalin
^ permalink raw reply
* [PATCH v4] pcie: Add Xilinx PCIe Host Bridge IP driver
From: Michal Simek @ 2014-07-22 17:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAErSpo41HwMferWm8q69Sz0t-Cs1WHgwwVp1VKsoxxyvrgQhfQ@mail.gmail.com>
On 07/22/2014 06:08 PM, Bjorn Helgaas wrote:
> On Mon, Jul 21, 2014 at 11:10 PM, Srikanth Thokala <sthokal@xilinx.com> wrote:
>> On Wed, Jul 16, 2014 at 11:08 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>>> ...
>>> I see I forgot to ask for a MAINTAINERS entry for this driver. Can
>>> you add one?
>>
>> There was a discussion on this earlier and Michal mentioned it is not
>> required as it is
>> handled by our Xilinx record.
>>
>> Here is the reply from Michal to the MAINTAINERS update comment,
>>
>> < Reply from Michal >
>>
>>> Please also include a MAINTAINERS update for drivers/pci/host/pci-xilinx.c.
>>
>> This should be handle by our record that's why MAINTAINERS update is
>> not necessary.
>> (N: xilinx below)
>
> That's technically true in the sense that get_maintainer.pl will do
> the right thing, but I often review patches in email (without
> extracting them), so it's more convenient to just look in MAINTAINERS
> to see if they have the right acks. But I guess I can deal with it
> either way.
There is also another reason for using just this fragment.
Because developers and their responsibilities are changing so often
and I just know who is responsible for it at that time.
Thanks,
Michal
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox