All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Glauber <jan.glauber@caviumnetworks.com>
To: Ulf Hansson <ulf.hansson@linaro.org>
Cc: "linux-mmc@vger.kernel.org" <linux-mmc@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	David Daney <ddaney@caviumnetworks.com>,
	"Steven J . Hill" <Steven.Hill@cavium.com>
Subject: Re: [PATCH v12 6/9] mmc: cavium: Add MMC PCI driver for ThunderX SOCs
Date: Thu, 23 Mar 2017 09:58:12 +0100	[thread overview]
Message-ID: <20170323085812.GA2250@hardcore> (raw)
In-Reply-To: <CAPDyKFp2-KOSYy41QCFcqdU_Rzfncea8Q4QvjHSmho+tAMYMKg@mail.gmail.com>

On Fri, Mar 17, 2017 at 03:58:26PM +0100, Ulf Hansson wrote:
> On 10 March 2017 at 14:25, Jan Glauber <jglauber@cavium.com> wrote:
> > Add a platform driver for ThunderX ARM SOCs.
> >
> > Signed-off-by: Jan Glauber <jglauber@cavium.com>
> > ---
> >  drivers/mmc/host/Kconfig               |  10 ++
> >  drivers/mmc/host/Makefile              |   2 +
> >  drivers/mmc/host/cavium-mmc.h          |  10 +-
> >  drivers/mmc/host/cavium-pci-thunderx.c | 198 +++++++++++++++++++++++++++++++++
> >  4 files changed, 218 insertions(+), 2 deletions(-)
> >  create mode 100644 drivers/mmc/host/cavium-pci-thunderx.c
> >
> > diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> > index 68cc811..3983dee 100644
> > --- a/drivers/mmc/host/Kconfig
> > +++ b/drivers/mmc/host/Kconfig
> > @@ -632,6 +632,16 @@ config MMC_CAVIUM_OCTEON
> >
> >           If unsure, say N.
> >
> > +config MMC_CAVIUM_THUNDERX
> > +       tristate "Cavium ThunderX SD/MMC Card Interface support"
> > +       depends on PCI && 64BIT && (ARM64 || COMPILE_TEST)
> > +       select GPIO_THUNDERX
> 
> Do you really need to select GPIO_THUNDERX? What is the relationship?

I don't know much about gpio, but in the end despite all these layers
there must be a gpio set function called doing the writeq on our SOC
to enable/disable the power gpio, right?

GPIO_THUNDERX implements this gpio set function for Cavium's SOC.

> Maybe "depends on GPIOLIB" instead?
> 
> > +       help
> > +         This selects Cavium ThunderX SD/MMC Card Interface.
> > +         If you have an Cavium ARM64 board with a Multimedia Card slot
> > +         or builtin eMMC chip say Y or M here. If built as a module
> > +         the module will be called thunderx_mmc.ko.
> > +
> >  config MMC_DW
> >         tristate "Synopsys DesignWare Memory Card Interface"
> >         depends on HAS_DMA
> > diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> > index c7f0ccf..0068610 100644
> > --- a/drivers/mmc/host/Makefile
> > +++ b/drivers/mmc/host/Makefile
> > @@ -44,6 +44,8 @@ obj-$(CONFIG_MMC_VIA_SDMMC)   += via-sdmmc.o
> >  obj-$(CONFIG_SDH_BFIN)         += bfin_sdh.o
> >  octeon-mmc-objs := cavium-mmc.o cavium-pltfm-octeon.o
> >  obj-$(CONFIG_MMC_CAVIUM_OCTEON) += octeon-mmc.o
> > +thunderx-mmc-objs := cavium-mmc.o cavium-pci-thunderx.o
> > +obj-$(CONFIG_MMC_CAVIUM_THUNDERX) += thunderx-mmc.o
> >  obj-$(CONFIG_MMC_DW)           += dw_mmc.o
> >  obj-$(CONFIG_MMC_DW_PLTFM)     += dw_mmc-pltfm.o
> >  obj-$(CONFIG_MMC_DW_EXYNOS)    += dw_mmc-exynos.o
> > diff --git a/drivers/mmc/host/cavium-mmc.h b/drivers/mmc/host/cavium-mmc.h
> > index 4b22432..fb82aee 100644
> > --- a/drivers/mmc/host/cavium-mmc.h
> > +++ b/drivers/mmc/host/cavium-mmc.h
> > @@ -22,8 +22,12 @@
> >  #define CAVIUM_MAX_MMC         4
> >
> >  /* DMA register addresses */
> > -#define MIO_EMM_DMA_CFG(x)     (0x00 + x->reg_off_dma)
> > -#define MIO_EMM_DMA_ADR(x)     (0x08 + x->reg_off_dma)
> > +#define MIO_EMM_DMA_CFG(x)     (0x20 + x->reg_off_dma)
> > +#define MIO_EMM_DMA_ADR(x)     (0x28 + x->reg_off_dma)
> > +#define MIO_EMM_DMA_INT(x)     (0x30 + x->reg_off_dma)
> > +#define MIO_EMM_DMA_INT_W1S(x) (0x38 + x->reg_off_dma)
> > +#define MIO_EMM_DMA_INT_ENA_W1S(x) (0x40 + x->reg_off_dma)
> > +#define MIO_EMM_DMA_INT_ENA_W1C(x) (0x48 + x->reg_off_dma)
> >
> >  /* register addresses */
> >  #define MIO_EMM_CFG(x)         (0x00 + x->reg_off)
> > @@ -39,6 +43,8 @@
> >  #define MIO_EMM_SAMPLE(x)      (0x90 + x->reg_off)
> >  #define MIO_EMM_STS_MASK(x)    (0x98 + x->reg_off)
> >  #define MIO_EMM_RCA(x)         (0xa0 + x->reg_off)
> > +#define MIO_EMM_INT_EN_SET(x)  (0xb0 + x->reg_off)
> > +#define MIO_EMM_INT_EN_CLR(x)  (0xb8 + x->reg_off)
> >  #define MIO_EMM_BUF_IDX(x)     (0xe0 + x->reg_off)
> >  #define MIO_EMM_BUF_DAT(x)     (0xe8 + x->reg_off)
> >
> > diff --git a/drivers/mmc/host/cavium-pci-thunderx.c b/drivers/mmc/host/cavium-pci-thunderx.c
> > new file mode 100644
> > index 0000000..6ad36b4
> > --- /dev/null
> > +++ b/drivers/mmc/host/cavium-pci-thunderx.c
> > @@ -0,0 +1,198 @@
> > +/*
> > + * Driver for MMC and SSD cards for Cavium ThunderX SOCs.
> > + *
> > + * This file is subject to the terms and conditions of the GNU General Public
> > + * License.  See the file "COPYING" in the main directory of this archive
> > + * for more details.
> > + *
> > + * Copyright (C) 2016 Cavium Inc.
> > + */
> > +#include <linux/dma-mapping.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/mmc/mmc.h>
> > +#include <linux/mmc/slot-gpio.h>
> > +#include <linux/module.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/pci.h>
> > +#include "cavium-mmc.h"
> > +
> > +struct platform_device *slot_pdev[2];
> 
> Let's not be lazy. We don't want global arrays of platform devices,
> whatever the reason.

OK, I'll move this into the host struct.

> > +
> > +static void thunder_mmc_acquire_bus(struct cvm_mmc_host *host)
> > +{
> > +       down(&host->mmc_serializer);
> > +}
> > +
> > +static void thunder_mmc_release_bus(struct cvm_mmc_host *host)
> > +{
> > +       up(&host->mmc_serializer);
> > +}
> > +
> > +static void thunder_mmc_int_enable(struct cvm_mmc_host *host, u64 val)
> > +{
> > +       writeq(val, host->base + MIO_EMM_INT(host));
> > +       writeq(val, host->base + MIO_EMM_INT_EN_SET(host));
> > +}
> > +
> > +static int thunder_mmc_register_interrupts(struct cvm_mmc_host *host,
> > +                                          struct pci_dev *pdev)
> > +{
> > +       int nvec, ret, i;
> > +
> > +       nvec = pci_alloc_irq_vectors(pdev, 1, 9, PCI_IRQ_MSIX);
> > +       if (nvec < 0)
> > +               return nvec;
> > +
> > +       /* register interrupts */
> > +       for (i = 0; i < nvec; i++) {
> > +               ret = devm_request_irq(&pdev->dev, pci_irq_vector(pdev, i),
> > +                                      cvm_mmc_interrupt,
> > +                                      0, cvm_mmc_irq_names[i], host);
> > +               if (ret)
> > +                       return ret;
> > +       }
> > +       return 0;
> > +}
> > +
> > +static int thunder_mmc_probe(struct pci_dev *pdev,
> > +                            const struct pci_device_id *id)
> > +{
> > +       struct device_node *node = pdev->dev.of_node;
> > +       struct device *dev = &pdev->dev;
> > +       struct device_node *child_node;
> > +       struct cvm_mmc_host *host;
> > +       int ret, i = 0;
> > +
> > +       host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
> > +       if (!host)
> > +               return -ENOMEM;
> > +
> > +       pci_set_drvdata(pdev, host);
> > +       ret = pcim_enable_device(pdev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret = pci_request_regions(pdev, KBUILD_MODNAME);
> > +       if (ret)
> > +               return ret;
> > +
> > +       host->base = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0));
> > +       if (!host->base)
> > +               return -EINVAL;
> > +
> > +       /* On ThunderX these are identical */
> > +       host->dma_base = host->base;
> > +
> > +       host->reg_off = 0x2000;
> > +       host->reg_off_dma = 0x160;
> > +
> > +       host->clk = devm_clk_get(dev, NULL);
> > +       if (IS_ERR(host->clk))
> > +               return PTR_ERR(host->clk);
> > +
> > +       ret = clk_prepare_enable(host->clk);
> > +       if (ret)
> > +               return ret;
> > +       host->sys_freq = clk_get_rate(host->clk);
> > +
> > +       spin_lock_init(&host->irq_handler_lock);
> > +       sema_init(&host->mmc_serializer, 1);
> > +
> > +       host->dev = dev;
> > +       host->acquire_bus = thunder_mmc_acquire_bus;
> > +       host->release_bus = thunder_mmc_release_bus;
> > +       host->int_enable = thunder_mmc_int_enable;
> > +
> > +       host->big_dma_addr = true;
> > +       host->need_irq_handler_lock = true;
> > +       host->last_slot = -1;
> > +
> > +       ret = dma_set_mask(dev, DMA_BIT_MASK(48));
> > +       if (ret)
> > +               goto error;
> > +
> > +       /*
> > +        * Clear out any pending interrupts that may be left over from
> > +        * bootloader. Writing 1 to the bits clears them.
> > +        */
> > +       writeq(127, host->base + MIO_EMM_INT_EN(host));
> > +       writeq(3, host->base + MIO_EMM_DMA_INT_ENA_W1C(host));
> > +
> > +       ret = thunder_mmc_register_interrupts(host, pdev);
> > +       if (ret)
> > +               goto error;
> > +
> > +       for_each_child_of_node(node, child_node) {
> > +               /*
> > +                * TODO: mmc_of_parse and devm* require one device per slot.
> 
> I guess the TODO is about fixing this behavior in the mmc core, such
> we can use mmc_of_parse() in more flexible manner. You may want to
> remove the "TODO", but please keep the comment.

OK.

> > +                * Create a dummy device per slot and set the node pointer to
> > +                * the slot. The easiest way to get this is using
> > +                * of_platform_device_create.
> > +                */
> > +               if (!slot_pdev[i])
> > +                       slot_pdev[i] = of_platform_device_create(child_node, NULL,
> > +                                                     &pdev->dev);
> 
> Seems like we should verify that this is a slot node, by checking the
> compatible, before creating a platform device for it. No?

Not sure I understand you correctly. Before creating the platform device
I don't have a device for the slot. Looking at functions I could use to
check the compatible all of these need a device, which I'm just going to
create. Can you point me to a function I can use here?

> > +               if (!slot_pdev[i])
> > +                       continue;
> > +               ret = cvm_mmc_of_slot_probe(&slot_pdev[i]->dev, host);
> > +               if (ret)
> > +                       goto error;
> > +               i++;
> > +       }
> > +       dev_info(dev, "probed\n");
> > +       return 0;
> > +
> > +error:
> > +       clk_disable_unprepare(host->clk);
> > +       return ret;
> > +}
> > +
> > +static void thunder_mmc_remove(struct pci_dev *pdev)
> > +{
> > +       struct cvm_mmc_host *host = pci_get_drvdata(pdev);
> > +       u64 dma_cfg;
> > +       int i;
> > +
> > +       for (i = 0; i < CAVIUM_MAX_MMC; i++)
> > +               if (host->slot[i]) {
> > +                       cvm_mmc_of_slot_remove(host->slot[i]);
> > +                       platform_device_del(slot_pdev[i]);
> > +               }
> > +
> > +       dma_cfg = readq(host->dma_base + MIO_EMM_DMA_CFG(host));
> > +       dma_cfg &= ~MIO_EMM_DMA_CFG_EN;
> > +       writeq(dma_cfg, host->dma_base + MIO_EMM_DMA_CFG(host));
> > +
> > +       clk_disable_unprepare(host->clk);
> > +}
> > +
> > +static const struct pci_device_id thunder_mmc_id_table[] = {
> > +       { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa010) },
> > +       { 0, }  /* end of table */
> > +};
> > +
> > +static struct pci_driver thunder_mmc_driver = {
> > +       .name = KBUILD_MODNAME,
> > +       .id_table = thunder_mmc_id_table,
> > +       .probe = thunder_mmc_probe,
> > +       .remove = thunder_mmc_remove,
> > +};
> > +
> > +static int __init thunder_mmc_init_module(void)
> > +{
> > +       return pci_register_driver(&thunder_mmc_driver);
> > +}
> > +
> > +static void __exit thunder_mmc_exit_module(void)
> > +{
> > +       pci_unregister_driver(&thunder_mmc_driver);
> > +}
> > +
> > +module_init(thunder_mmc_init_module);
> > +module_exit(thunder_mmc_exit_module);
> > +
> > +MODULE_AUTHOR("Cavium Inc.");
> > +MODULE_DESCRIPTION("Cavium ThunderX eMMC Driver");
> > +MODULE_LICENSE("GPL");
> > +MODULE_DEVICE_TABLE(pci, thunder_mmc_id_table);
> > --
> > 2.9.0.rc0.21.g7777322
> >
> 
> Kind regards
> Uffe

  reply	other threads:[~2017-03-23  8:58 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-10 13:24 [PATCH v12 0/9] Cavium MMC driver Jan Glauber
2017-03-10 13:24 ` [PATCH v12 1/9] dt-bindings: mmc: Add Cavium SOCs MMC bindings Jan Glauber
2017-03-17  8:31   ` Ulf Hansson
     [not found]     ` <CAPDyKFqVHN--=AWttMz_uDEkGTO+aX8APM34enDuVxqM6XKYJg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-03-17 10:51       ` Jan Glauber
2017-03-17 10:51         ` Jan Glauber
2017-03-10 13:25 ` [PATCH v12 2/9] mmc: cavium: Add core MMC driver for Cavium SOCs Jan Glauber
2017-03-17 11:24   ` Ulf Hansson
2017-03-17 13:34     ` Jan Glauber
2017-03-17 13:47       ` Ulf Hansson
2017-03-10 13:25 ` [PATCH v12 3/9] mmc: cavium: Add MMC platform driver for Octeon SOCs Jan Glauber
2017-03-17 13:35   ` Ulf Hansson
2017-03-20 14:40     ` Jan Glauber
2017-03-20 15:19       ` Ulf Hansson
2017-03-10 13:25 ` [PATCH v12 4/9] mmc: cavium: Work-around hardware bug on cn6xxx and cnf7xxx Jan Glauber
2017-03-17 14:13   ` Ulf Hansson
2017-03-20 20:34     ` Arnd Bergmann
2017-03-20 20:45     ` David Daney
2017-03-21  8:58       ` Arnd Bergmann
2017-03-21 15:19         ` David Daney
2017-03-21 19:49           ` Arnd Bergmann
2017-03-21 20:22             ` David Daney
2017-03-22 10:00               ` Jan Glauber
2017-03-10 13:25 ` [PATCH v12 5/9] mmc: cavium: Add support for Octeon cn7890 Jan Glauber
2017-03-10 13:25 ` [PATCH v12 6/9] mmc: cavium: Add MMC PCI driver for ThunderX SOCs Jan Glauber
2017-03-17 14:58   ` Ulf Hansson
2017-03-23  8:58     ` Jan Glauber [this message]
2017-03-23  9:28       ` Ulf Hansson
2017-03-23 17:41         ` David Daney
2017-03-10 13:25 ` [PATCH v12 7/9] mmc: cavium: Add scatter-gather DMA support Jan Glauber
2017-03-10 13:25 ` [PATCH v12 8/9] mmc: cavium: Support DDR mode for eMMC devices Jan Glauber
2017-03-10 13:25 ` [PATCH v12 9/9] MAINTAINERS: Add entry for Cavium MMC driver Jan Glauber
2017-03-15 15:57 ` [PATCH v12 0/9] " Arnd Bergmann
2017-03-15 16:20   ` Jan Glauber

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170323085812.GA2250@hardcore \
    --to=jan.glauber@caviumnetworks.com \
    --cc=Steven.Hill@cavium.com \
    --cc=ddaney@caviumnetworks.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=ulf.hansson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.