* [PATCH 0/2] mmc: atmel-mci: introduce MCI2 support on at91
@ 2009-09-17 16:29 Nicolas Ferre
2009-09-17 16:29 ` [PATCH 1/2] atmel-mci: change use of dma slave interface Nicolas Ferre
2009-09-17 16:29 ` [PATCH 2/2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver Nicolas Ferre
0 siblings, 2 replies; 47+ messages in thread
From: Nicolas Ferre @ 2009-09-17 16:29 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-kernel, haavard.skinnemoen, kernel
This patchset introduces the support of a new revision of the MCI IP on AT91
SOCs. The use of an alternate DMA engine on those platforms introduces the need
of a generic way of handling dma slave interface.
Note: those patches goes on top of the following patch that is already in
mmotm:
atmel-mci: Unified Atmel MCI drivers (AVR32 & AT91)
Nicolas Ferre (2):
atmel-mci: change use of dma slave interface
mmc: atmel-mci: New MCI2 module support in atmel-mci driver
arch/avr32/mach-at32ap/at32ap700x.c | 6 +-
drivers/mmc/host/atmel-mci.c | 167 ++++++++++++++++++++++++++++-------
include/linux/atmel-mci.h | 3 +-
3 files changed, 143 insertions(+), 33 deletions(-)
^ permalink raw reply [flat|nested] 47+ messages in thread* [PATCH 1/2] atmel-mci: change use of dma slave interface 2009-09-17 16:29 [PATCH 0/2] mmc: atmel-mci: introduce MCI2 support on at91 Nicolas Ferre @ 2009-09-17 16:29 ` Nicolas Ferre 2009-09-29 19:29 ` Andrew Morton 2009-09-17 16:29 ` [PATCH 2/2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver Nicolas Ferre 1 sibling, 1 reply; 47+ messages in thread From: Nicolas Ferre @ 2009-09-17 16:29 UTC (permalink / raw) To: linux-mmc; +Cc: linux-kernel, haavard.skinnemoen, kernel, Nicolas Ferre Allow the use of another DMA controller driver in atmel-mci sd/mmc driver. This adds a generic dma_slave pointer to the mci platform structure where we can store DMA controller information. In atmel-mci we use information provided by this structure to initialize the driver (with new helper functions that are architecture dependant). This also adds at32/avr32 chip modifications to cope with this new access method. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> --- arch/avr32/mach-at32ap/at32ap700x.c | 6 ++- drivers/mmc/host/atmel-mci.c | 82 ++++++++++++++++++++++++++--------- include/linux/atmel-mci.h | 3 +- 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index eb9d4dc..d1fe145 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1320,7 +1320,7 @@ struct platform_device *__init at32_add_device_mci(unsigned int id, struct mci_platform_data *data) { struct platform_device *pdev; - struct dw_dma_slave *dws = &data->dma_slave; + struct dw_dma_slave *dws; u32 pioa_mask; u32 piob_mask; @@ -1339,6 +1339,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) ARRAY_SIZE(atmel_mci0_resource))) goto fail; + dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL); + dws->dma_dev = &dw_dmac0_device.dev; dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT; dws->cfg_hi = (DWC_CFGH_SRC_PER(0) @@ -1346,6 +1348,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL); + data->dma_slave = dws; + if (platform_device_add_data(pdev, data, sizeof(struct mci_platform_data))) goto fail; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 065fa81..1689396 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1575,16 +1575,71 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, } #ifdef CONFIG_MMC_ATMELMCI_DMA -static bool filter(struct dma_chan *chan, void *slave) +static struct device *find_slave_dev(void *slave) +{ + if (!slave) + return NULL; + + if (cpu_is_at32ap7000()) + return ((struct dw_dma_slave *)slave)->dma_dev; + else + return ((struct at_dma_slave *)slave)->dma_dev; +} + +static void setup_dma_addr(struct mci_platform_data *pdata, + dma_addr_t tx_addr, dma_addr_t rx_addr) { - struct dw_dma_slave *dws = slave; + if (!pdata) + return; + + if (cpu_is_at32ap7000()) { + struct dw_dma_slave *dws = pdata->dma_slave; + + dws->tx_reg = tx_addr; + dws->rx_reg = rx_addr; + } else { + struct at_dma_slave *ats = pdata->dma_slave; - if (dws->dma_dev == chan->device->dev) { - chan->private = dws; + ats->tx_reg = tx_addr; + ats->rx_reg = rx_addr; + } +} + +static bool filter(struct dma_chan *chan, void *slave) +{ + if (find_slave_dev(slave) == chan->device->dev) { + chan->private = slave; return true; - } else + } else { return false; + } +} + +static void atmci_configure_dma(struct atmel_mci *host) +{ + struct mci_platform_data *pdata; + + if (host == NULL) + return; + + pdata = host->pdev->dev.platform_data; + + if (pdata && find_slave_dev(pdata->dma_slave)) { + dma_cap_mask_t mask; + + setup_dma_addr(pdata, host->mapbase + MCI_TDR, + host->mapbase + MCI_RDR); + + /* Try to grab a DMA channel */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + host->dma.chan = dma_request_channel(mask, filter, pdata->dma_slave); + } + if (!host->dma.chan) + dev_notice(&host->pdev->dev, "DMA not available, using PIO\n"); } +#else +static void atmci_configure_dma(struct atmel_mci *host) {} #endif static int __init atmci_probe(struct platform_device *pdev) @@ -1638,22 +1693,7 @@ static int __init atmci_probe(struct platform_device *pdev) if (ret) goto err_request_irq; -#ifdef CONFIG_MMC_ATMELMCI_DMA - if (pdata->dma_slave.dma_dev) { - struct dw_dma_slave *dws = &pdata->dma_slave; - dma_cap_mask_t mask; - - dws->tx_reg = regs->start + MCI_TDR; - dws->rx_reg = regs->start + MCI_RDR; - - /* Try to grab a DMA channel */ - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - host->dma.chan = dma_request_channel(mask, filter, dws); - } - if (!host->dma.chan) - dev_notice(&pdev->dev, "DMA not available, using PIO\n"); -#endif /* CONFIG_MMC_ATMELMCI_DMA */ + atmci_configure_dma(host); platform_set_drvdata(pdev, host); diff --git a/include/linux/atmel-mci.h b/include/linux/atmel-mci.h index 57b1846..e26b7de 100644 --- a/include/linux/atmel-mci.h +++ b/include/linux/atmel-mci.h @@ -4,6 +4,7 @@ #define ATMEL_MCI_MAX_NR_SLOTS 2 #include <linux/dw_dmac.h> +#include <mach/at_hdmac.h> /** * struct mci_slot_pdata - board-specific per-slot configuration @@ -34,7 +35,7 @@ struct mci_slot_pdata { * @slot: Per-slot configuration data. */ struct mci_platform_data { - struct dw_dma_slave dma_slave; + void *dma_slave; struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; }; -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH 1/2] atmel-mci: change use of dma slave interface 2009-09-17 16:29 ` [PATCH 1/2] atmel-mci: change use of dma slave interface Nicolas Ferre @ 2009-09-29 19:29 ` Andrew Morton 2009-09-30 13:33 ` Nicolas Ferre 0 siblings, 1 reply; 47+ messages in thread From: Andrew Morton @ 2009-09-29 19:29 UTC (permalink / raw) To: Nicolas Ferre Cc: linux-mmc, linux-kernel, haavard.skinnemoen, kernel, nicolas.ferre On Thu, 17 Sep 2009 18:29:26 +0200 Nicolas Ferre <nicolas.ferre@atmel.com> wrote: > Allow the use of another DMA controller driver in atmel-mci sd/mmc driver. This > adds a generic dma_slave pointer to the mci platform structure where we can > store DMA controller information. In atmel-mci we use information provided by > this structure to initialize the driver (with new helper functions that are > architecture dependant). > This also adds at32/avr32 chip modifications to cope with this new access > method. > > Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> > --- > arch/avr32/mach-at32ap/at32ap700x.c | 6 ++- > drivers/mmc/host/atmel-mci.c | 82 ++++++++++++++++++++++++++--------- > include/linux/atmel-mci.h | 3 +- > 3 files changed, 68 insertions(+), 23 deletions(-) > > diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c > index eb9d4dc..d1fe145 100644 > --- a/arch/avr32/mach-at32ap/at32ap700x.c > +++ b/arch/avr32/mach-at32ap/at32ap700x.c > @@ -1320,7 +1320,7 @@ struct platform_device *__init > at32_add_device_mci(unsigned int id, struct mci_platform_data *data) > { > struct platform_device *pdev; > - struct dw_dma_slave *dws = &data->dma_slave; > + struct dw_dma_slave *dws; > u32 pioa_mask; > u32 piob_mask; > > @@ -1339,6 +1339,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) > ARRAY_SIZE(atmel_mci0_resource))) > goto fail; > > + dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL); I don't see anywhere where this gets freed again? > dws->dma_dev = &dw_dmac0_device.dev; > dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT; > dws->cfg_hi = (DWC_CFGH_SRC_PER(0) > @@ -1346,6 +1348,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) > dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL > | DWC_CFGL_HS_SRC_POL); > > + data->dma_slave = dws; > + > if (platform_device_add_data(pdev, data, > sizeof(struct mci_platform_data))) > goto fail; > diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c > index 065fa81..1689396 100644 > --- a/drivers/mmc/host/atmel-mci.c > +++ b/drivers/mmc/host/atmel-mci.c > @@ -1575,16 +1575,71 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, > } > > #ifdef CONFIG_MMC_ATMELMCI_DMA > -static bool filter(struct dma_chan *chan, void *slave) > +static struct device *find_slave_dev(void *slave) > +{ > + if (!slave) > + return NULL; > + > + if (cpu_is_at32ap7000()) > + return ((struct dw_dma_slave *)slave)->dma_dev; > + else > + return ((struct at_dma_slave *)slave)->dma_dev; > +} Quite a few unsafeish typecasts here. > struct mci_platform_data { > - struct dw_dma_slave dma_slave; > + void *dma_slave; > struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; > }; I think the code would come out better if this has type dw_dma_slave*. You'll still need typecasts to support the dma_request_channel() callback, but the code will be safer and cleaner, I expect. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 1/2] atmel-mci: change use of dma slave interface 2009-09-29 19:29 ` Andrew Morton @ 2009-09-30 13:33 ` Nicolas Ferre 2009-09-30 13:55 ` Haavard Skinnemoen 0 siblings, 1 reply; 47+ messages in thread From: Nicolas Ferre @ 2009-09-30 13:33 UTC (permalink / raw) To: Andrew Morton, haavard.skinnemoen Cc: linux-mmc, linux-kernel, kernel, Hans-Christian Egtvedt Andrew Morton : > On Thu, 17 Sep 2009 18:29:26 +0200 > Nicolas Ferre <nicolas.ferre@atmel.com> wrote: > >> Allow the use of another DMA controller driver in atmel-mci sd/mmc driver. This >> adds a generic dma_slave pointer to the mci platform structure where we can >> store DMA controller information. In atmel-mci we use information provided by >> this structure to initialize the driver (with new helper functions that are >> architecture dependant). >> This also adds at32/avr32 chip modifications to cope with this new access >> method. >> >> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> >> --- >> arch/avr32/mach-at32ap/at32ap700x.c | 6 ++- >> drivers/mmc/host/atmel-mci.c | 82 ++++++++++++++++++++++++++--------- >> include/linux/atmel-mci.h | 3 +- >> 3 files changed, 68 insertions(+), 23 deletions(-) >> >> diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c >> index eb9d4dc..d1fe145 100644 >> --- a/arch/avr32/mach-at32ap/at32ap700x.c >> +++ b/arch/avr32/mach-at32ap/at32ap700x.c >> @@ -1320,7 +1320,7 @@ struct platform_device *__init >> at32_add_device_mci(unsigned int id, struct mci_platform_data *data) >> { >> struct platform_device *pdev; >> - struct dw_dma_slave *dws = &data->dma_slave; >> + struct dw_dma_slave *dws; >> u32 pioa_mask; >> u32 piob_mask; >> >> @@ -1339,6 +1339,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) >> ARRAY_SIZE(atmel_mci0_resource))) >> goto fail; >> >> + dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL); > > I don't see anywhere where this gets freed again? Well, in fact those are platform initialization functions that have no "exit" equivalent. Is this the proper way of managing this ? Anyway, I have forgotten to free memory in case of a "fail" error case that is present in this function. I will correct this in my v2 patch. > >> dws->dma_dev = &dw_dmac0_device.dev; >> dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT; >> dws->cfg_hi = (DWC_CFGH_SRC_PER(0) >> @@ -1346,6 +1348,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) >> dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL >> | DWC_CFGL_HS_SRC_POL); >> >> + data->dma_slave = dws; >> + >> if (platform_device_add_data(pdev, data, >> sizeof(struct mci_platform_data))) >> goto fail; >> diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c >> index 065fa81..1689396 100644 >> --- a/drivers/mmc/host/atmel-mci.c >> +++ b/drivers/mmc/host/atmel-mci.c >> @@ -1575,16 +1575,71 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, >> } >> >> #ifdef CONFIG_MMC_ATMELMCI_DMA >> -static bool filter(struct dma_chan *chan, void *slave) >> +static struct device *find_slave_dev(void *slave) >> +{ >> + if (!slave) >> + return NULL; >> + >> + if (cpu_is_at32ap7000()) >> + return ((struct dw_dma_slave *)slave)->dma_dev; >> + else >> + return ((struct at_dma_slave *)slave)->dma_dev; >> +} > > Quite a few unsafeish typecasts here. I am afraid, yes. >> struct mci_platform_data { >> - struct dw_dma_slave dma_slave; >> + void *dma_slave; >> struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; >> }; > > I think the code would come out better if this has type dw_dma_slave*. Do you mean that I would leave dw_dma_slave* in mci_platform_data and use this field for struct at_dma_slave content where I need it ? I thought it was more confusing... > You'll still need typecasts to support the dma_request_channel() > callback, but the code will be safer and cleaner, I expect. My concern are: 1/ allow the use of either dmaengine driver 2/ avoid too much modification to dw_dma_slave as it is also used for audio stuff on avr32 platforms... 3/ not introduce heavy weigh solution like the use of an union Best regards, -- Nicolas Ferre ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 1/2] atmel-mci: change use of dma slave interface 2009-09-30 13:33 ` Nicolas Ferre @ 2009-09-30 13:55 ` Haavard Skinnemoen 2009-10-23 16:34 ` [PATCH 0/2 v2]mmc: atmel-mci: introduce MCI2 support on at91 Nicolas Ferre 2009-10-23 16:34 ` [PATCH 1/3 v2] atmel-mci: change use of dma slave interface Nicolas Ferre 0 siblings, 2 replies; 47+ messages in thread From: Haavard Skinnemoen @ 2009-09-30 13:55 UTC (permalink / raw) To: Nicolas Ferre Cc: Andrew Morton, linux-mmc, linux-kernel, kernel, Hans-Christian Egtvedt Nicolas Ferre <nicolas.ferre@atmel.com> wrote: > > You'll still need typecasts to support the dma_request_channel() > > callback, but the code will be safer and cleaner, I expect. > > My concern are: > 1/ allow the use of either dmaengine driver > 2/ avoid too much modification to dw_dma_slave as it > is also used for audio stuff on avr32 platforms... > 3/ not introduce heavy weigh solution like the use of an union We used to have a struct dma_slave in linux/dmaengine.h which took care of all this, but it got removed at some point. How about introducing a new mach/atmel-mci.h file with a struct mci_dma_data encapsulating either a struct dw_dma_slave or a struct at_dma_slave, as well as any other DMA-related definitions needed by the atmel-mci driver? Then we just need to make sure that we either 1) use the same name on all fields in struct {dw,at}_dma_slave which are used by the atmel-mci driver, or 2) add accessor functions or macros for those fields. I think I would prefer the latter, but both should work equally well. Haavard ^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH 0/2 v2]mmc: atmel-mci: introduce MCI2 support on at91 2009-09-30 13:55 ` Haavard Skinnemoen @ 2009-10-23 16:34 ` Nicolas Ferre 2009-10-23 16:34 ` [PATCH 1/3 v2] atmel-mci: change use of dma slave interface Nicolas Ferre 1 sibling, 0 replies; 47+ messages in thread From: Nicolas Ferre @ 2009-10-23 16:34 UTC (permalink / raw) To: linux-mmc, haavard.skinnemoen Cc: linux-kernel, kernel, akpm, linux-arm-kernel This patchset introduces the support of a new revision of the MCI IP on AT91 SOCs. The use of an alternate DMA engine on those platforms introduces the need of a generic way of handling dma slave interface. Note: those patches goes on top of the following patch that is already in mainline: atmel-mci: unified Atmel MCI drivers (AVR32 & AT91) Nicolas Ferre (3): atmel-mci: change use of dma slave interface mmc: atmel-mci: New MCI2 module support in atmel-mci driver at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board arch/arm/mach-at91/at91sam9g45_devices.c | 164 +++++++++++++++++++++++ arch/arm/mach-at91/board-sam9m10g45ek.c | 24 ++++ arch/arm/mach-at91/include/mach/atmel-mci.h | 24 ++++ arch/avr32/mach-at32ap/at32ap700x.c | 18 ++- arch/avr32/mach-at32ap/include/mach/atmel-mci.h | 24 ++++ drivers/mmc/host/Kconfig | 2 +- drivers/mmc/host/atmel-mci.c | 141 +++++++++++++++---- include/linux/atmel-mci.h | 4 +- 8 files changed, 362 insertions(+), 39 deletions(-) create mode 100644 arch/arm/mach-at91/include/mach/atmel-mci.h create mode 100644 arch/avr32/mach-at32ap/include/mach/atmel-mci.h ^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH 1/3 v2] atmel-mci: change use of dma slave interface 2009-09-30 13:55 ` Haavard Skinnemoen 2009-10-23 16:34 ` [PATCH 0/2 v2]mmc: atmel-mci: introduce MCI2 support on at91 Nicolas Ferre @ 2009-10-23 16:34 ` Nicolas Ferre 2009-10-23 16:34 ` [PATCH 2/3 v2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver Nicolas Ferre 2009-10-23 16:34 ` [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board Nicolas Ferre 1 sibling, 2 replies; 47+ messages in thread From: Nicolas Ferre @ 2009-10-23 16:34 UTC (permalink / raw) To: linux-mmc, haavard.skinnemoen Cc: linux-kernel, kernel, akpm, linux-arm-kernel, Nicolas Ferre Allow the use of another DMA controller driver in atmel-mci sd/mmc driver. This adds a generic dma_slave pointer to the mci platform structure where we can store DMA controller information. In atmel-mci we use information provided by this structure to initialize the driver (with new helper functions that are architecture dependant). This also adds at32/avr32 chip modifications to cope with this new access method. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> --- arch/arm/mach-at91/include/mach/atmel-mci.h | 24 ++++++++++ arch/avr32/mach-at32ap/at32ap700x.c | 18 +++++-- arch/avr32/mach-at32ap/include/mach/atmel-mci.h | 24 ++++++++++ drivers/mmc/host/atmel-mci.c | 56 +++++++++++++++-------- include/linux/atmel-mci.h | 4 +- 5 files changed, 98 insertions(+), 28 deletions(-) create mode 100644 arch/arm/mach-at91/include/mach/atmel-mci.h create mode 100644 arch/avr32/mach-at32ap/include/mach/atmel-mci.h diff --git a/arch/arm/mach-at91/include/mach/atmel-mci.h b/arch/arm/mach-at91/include/mach/atmel-mci.h new file mode 100644 index 0000000..998cb0c --- /dev/null +++ b/arch/arm/mach-at91/include/mach/atmel-mci.h @@ -0,0 +1,24 @@ +#ifndef __MACH_ATMEL_MCI_H +#define __MACH_ATMEL_MCI_H + +#include <mach/at_hdmac.h> + +/** + * struct mci_dma_data - DMA data for MCI interface + */ +struct mci_dma_data { + struct at_dma_slave sdata; +}; + +/* accessor macros */ +#define slave_data_ptr(s) (&(s)->sdata) +#define find_slave_dev(s) ((s)->sdata.dma_dev) + +#define setup_dma_addr(s, t, r) do { \ + if (s) { \ + (s)->sdata.tx_reg = (t); \ + (s)->sdata.rx_reg = (r); \ + } \ +} while (0) + +#endif /* __MACH_ATMEL_MCI_H */ diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index eb9d4dc..b40ff39 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -15,6 +15,8 @@ #include <linux/gpio.h> #include <linux/spi/spi.h> #include <linux/usb/atmel_usba_udc.h> + +#include <mach/atmel-mci.h> #include <linux/atmel-mci.h> #include <asm/io.h> @@ -1320,7 +1322,7 @@ struct platform_device *__init at32_add_device_mci(unsigned int id, struct mci_platform_data *data) { struct platform_device *pdev; - struct dw_dma_slave *dws = &data->dma_slave; + struct mci_dma_slave *slave; u32 pioa_mask; u32 piob_mask; @@ -1339,13 +1341,17 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) ARRAY_SIZE(atmel_mci0_resource))) goto fail; - dws->dma_dev = &dw_dmac0_device.dev; - dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT; - dws->cfg_hi = (DWC_CFGH_SRC_PER(0) + slave = kzalloc(sizeof(struct mci_dma_slave), GFP_KERNEL); + + slave->sdata.dma_dev = &dw_dmac0_device.dev; + slave->sdata.reg_width = DW_DMA_SLAVE_WIDTH_32BIT; + slave->sdata.cfg_hi = (DWC_CFGH_SRC_PER(0) | DWC_CFGH_DST_PER(1)); - dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL + slave->sdata.cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL); + data->dma_slave = slave; + if (platform_device_add_data(pdev, data, sizeof(struct mci_platform_data))) goto fail; @@ -1411,6 +1417,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) return pdev; fail: + data->dma_slave = NULL; + kfree(slave); platform_device_put(pdev); return NULL; } diff --git a/arch/avr32/mach-at32ap/include/mach/atmel-mci.h b/arch/avr32/mach-at32ap/include/mach/atmel-mci.h new file mode 100644 index 0000000..a9b3896 --- /dev/null +++ b/arch/avr32/mach-at32ap/include/mach/atmel-mci.h @@ -0,0 +1,24 @@ +#ifndef __MACH_ATMEL_MCI_H +#define __MACH_ATMEL_MCI_H + +#include <linux/dw_dmac.h> + +/** + * struct mci_dma_data - DMA data for MCI interface + */ +struct mci_dma_data { + struct dw_dma_slave sdata; +}; + +/* accessor macros */ +#define slave_data_ptr(s) (&(s)->sdata) +#define find_slave_dev(s) ((s)->sdata.dma_dev) + +#define setup_dma_addr(s, t, r) do { \ + if (s) { \ + (s)->sdata.tx_reg = (t); \ + (s)->sdata.rx_reg = (r); \ + } \ +} while (0) + +#endif /* __MACH_ATMEL_MCI_H */ diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index fc25586..ba8b219 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -25,6 +25,8 @@ #include <linux/stat.h> #include <linux/mmc/host.h> + +#include <mach/atmel-mci.h> #include <linux/atmel-mci.h> #include <asm/io.h> @@ -1584,14 +1586,43 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, #ifdef CONFIG_MMC_ATMELMCI_DMA static bool filter(struct dma_chan *chan, void *slave) { - struct dw_dma_slave *dws = slave; + struct mci_dma_data *sl = slave; - if (dws->dma_dev == chan->device->dev) { - chan->private = dws; + if (sl && find_slave_dev(sl) == chan->device->dev) { + chan->private = slave_data_ptr(sl); return true; - } else + } else { return false; + } } + +static void atmci_configure_dma(struct atmel_mci *host) +{ + struct mci_platform_data *pdata; + + if (host == NULL) + return; + + pdata = host->pdev->dev.platform_data; + + if (pdata && find_slave_dev(pdata->dma_slave)) { + dma_cap_mask_t mask; + + setup_dma_addr(pdata->dma_slave, + host->mapbase + MCI_TDR, + host->mapbase + MCI_RDR); + + /* Try to grab a DMA channel */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + host->dma.chan = + dma_request_channel(mask, filter, pdata->dma_slave); + } + if (!host->dma.chan) + dev_notice(&host->pdev->dev, "DMA not available, using PIO\n"); +} +#else +static void atmci_configure_dma(struct atmel_mci *host) {} #endif static int __init atmci_probe(struct platform_device *pdev) @@ -1645,22 +1676,7 @@ static int __init atmci_probe(struct platform_device *pdev) if (ret) goto err_request_irq; -#ifdef CONFIG_MMC_ATMELMCI_DMA - if (pdata->dma_slave.dma_dev) { - struct dw_dma_slave *dws = &pdata->dma_slave; - dma_cap_mask_t mask; - - dws->tx_reg = regs->start + MCI_TDR; - dws->rx_reg = regs->start + MCI_RDR; - - /* Try to grab a DMA channel */ - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - host->dma.chan = dma_request_channel(mask, filter, dws); - } - if (!host->dma.chan) - dev_notice(&pdev->dev, "DMA not available, using PIO\n"); -#endif /* CONFIG_MMC_ATMELMCI_DMA */ + atmci_configure_dma(host); platform_set_drvdata(pdev, host); diff --git a/include/linux/atmel-mci.h b/include/linux/atmel-mci.h index 57b1846..3e09b34 100644 --- a/include/linux/atmel-mci.h +++ b/include/linux/atmel-mci.h @@ -3,8 +3,6 @@ #define ATMEL_MCI_MAX_NR_SLOTS 2 -#include <linux/dw_dmac.h> - /** * struct mci_slot_pdata - board-specific per-slot configuration * @bus_width: Number of data lines wired up the slot @@ -34,7 +32,7 @@ struct mci_slot_pdata { * @slot: Per-slot configuration data. */ struct mci_platform_data { - struct dw_dma_slave dma_slave; + struct mci_dma_data *dma_slave; struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; }; -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH 2/3 v2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver 2009-10-23 16:34 ` [PATCH 1/3 v2] atmel-mci: change use of dma slave interface Nicolas Ferre @ 2009-10-23 16:34 ` Nicolas Ferre 2009-11-02 17:18 ` Nicolas Ferre 2009-10-23 16:34 ` [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board Nicolas Ferre 1 sibling, 1 reply; 47+ messages in thread From: Nicolas Ferre @ 2009-10-23 16:34 UTC (permalink / raw) To: linux-mmc, haavard.skinnemoen Cc: linux-kernel, kernel, akpm, linux-arm-kernel, Nicolas Ferre This new revision of the IP adds some improvements to the MCI already present in several Atmel SOC. Some new registers are added and a particular way of handling DMA interaction lead to a new sequence in function call which is backward compatible: On MCI2, we must set the DMAEN bit to enable the DMA handshaking interface. This must happen before the data transfer command is sent. A new function is able to differentiate MCI2 code and is based on knowledge of processor id (cpu_is_xxx()). Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> --- drivers/mmc/host/atmel-mci.c | 85 +++++++++++++++++++++++++++++++++++++----- 1 files changed, 75 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index ba8b219..8072128 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -94,6 +94,7 @@ struct atmel_mci_dma { * @need_clock_update: Update the clock rate before the next request. * @need_reset: Reset controller before next request. * @mode_reg: Value of the MR register. + * @cfg_reg: Value of the CFG register. * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus * rate and timeout calculations. * @mapbase: Physical address of the MMIO registers. @@ -157,6 +158,7 @@ struct atmel_mci { bool need_clock_update; bool need_reset; u32 mode_reg; + u32 cfg_reg; unsigned long bus_hz; unsigned long mapbase; struct clk *mck; @@ -225,6 +227,19 @@ static bool mci_has_rwproof(void) } /* + * The new MCI2 module isn't 100% compatible with the old MCI module, + * and it has a few nice features which we want to use... + */ +static inline bool atmci_is_mci2(void) +{ + if (cpu_is_at91sam9g45()) + return true; + + return false; +} + + +/* * The debugfs stuff below is mostly optimized away when * CONFIG_DEBUG_FS is not set. */ @@ -359,12 +374,33 @@ static int atmci_regs_show(struct seq_file *s, void *v) buf[MCI_BLKR / 4], buf[MCI_BLKR / 4] & 0xffff, (buf[MCI_BLKR / 4] >> 16) & 0xffff); + if (atmci_is_mci2()) + seq_printf(s, "CSTOR:\t0x%08x\n", buf[MCI_CSTOR / 4]); /* Don't read RSPR and RDR; it will consume the data there */ atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]); atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]); + if (atmci_is_mci2()) { + u32 val; + + val = buf[MCI_DMA / 4]; + seq_printf(s, "DMA:\t0x%08x OFFSET=%u CHKSIZE=%u%s\n", + val, val & 3, + ((val >> 4) & 3) ? + 1 << (((val >> 4) & 3) + 1) : 1, + val & MCI_DMAEN ? " DMAEN" : ""); + + val = buf[MCI_CFG / 4]; + seq_printf(s, "CFG:\t0x%08x%s%s%s%s\n", + val, + val & MCI_CFG_FIFOMODE_1DATA ? " FIFOMODE_ONE_DATA" : "", + val & MCI_CFG_FERRCTRL_COR ? " FERRCTRL_CLEAR_ON_READ" : "", + val & MCI_CFG_HSMODE ? " HSMODE" : "", + val & MCI_CFG_LSYNC ? " LSYNC" : ""); + } + kfree(buf); return 0; @@ -559,6 +595,10 @@ static void atmci_dma_complete(void *arg) dev_vdbg(&host->pdev->dev, "DMA complete\n"); + if (atmci_is_mci2()) + /* Disable DMA hardware handshaking on MCI */ + mci_writel(host, DMA, mci_readl(host, DMA) & ~MCI_DMAEN); + atmci_dma_cleanup(host); /* @@ -594,7 +634,7 @@ static void atmci_dma_complete(void *arg) } static int -atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) +atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) { struct dma_chan *chan; struct dma_async_tx_descriptor *desc; @@ -626,6 +666,9 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) if (!chan) return -ENODEV; + if (atmci_is_mci2()) + mci_writel(host, DMA, MCI_DMA_CHKSIZE(3) | MCI_DMAEN); + if (data->flags & MMC_DATA_READ) direction = DMA_FROM_DEVICE; else @@ -643,10 +686,6 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) host->dma.data_desc = desc; desc->callback = atmci_dma_complete; desc->callback_param = host; - desc->tx_submit(desc); - - /* Go! */ - chan->device->device_issue_pending(chan); return 0; unmap_exit: @@ -654,13 +693,26 @@ unmap_exit: return -ENOMEM; } +static void atmci_submit_data(struct atmel_mci *host) +{ + struct dma_chan *chan = host->data_chan; + struct dma_async_tx_descriptor *desc = host->dma.data_desc; + + if (chan) { + desc->tx_submit(desc); + chan->device->device_issue_pending(chan); + } +} + #else /* CONFIG_MMC_ATMELMCI_DMA */ -static int atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) +static int atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) { return -ENOSYS; } +static void atmci_submit_data(struct atmel_mci *host) {} + static void atmci_stop_dma(struct atmel_mci *host) { /* Data transfer was stopped by the interrupt handler */ @@ -674,7 +726,7 @@ static void atmci_stop_dma(struct atmel_mci *host) * Returns a mask of interrupt flags to be enabled after the whole * request has been prepared. */ -static u32 atmci_submit_data(struct atmel_mci *host, struct mmc_data *data) +static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data) { u32 iflags; @@ -685,7 +737,7 @@ static u32 atmci_submit_data(struct atmel_mci *host, struct mmc_data *data) host->data = data; iflags = ATMCI_DATA_ERROR_FLAGS; - if (atmci_submit_data_dma(host, data)) { + if (atmci_prepare_data_dma(host, data)) { host->data_chan = NULL; /* @@ -731,6 +783,8 @@ static void atmci_start_request(struct atmel_mci *host, mci_writel(host, CR, MCI_CR_SWRST); mci_writel(host, CR, MCI_CR_MCIEN); mci_writel(host, MR, host->mode_reg); + if (atmci_is_mci2()) + mci_writel(host, CFG, host->cfg_reg); host->need_reset = false; } mci_writel(host, SDCR, slot->sdc_reg); @@ -746,6 +800,7 @@ static void atmci_start_request(struct atmel_mci *host, while (!(mci_readl(host, SR) & MCI_CMDRDY)) cpu_relax(); } + iflags = 0; data = mrq->data; if (data) { atmci_set_timeout(host, slot, data); @@ -755,15 +810,17 @@ static void atmci_start_request(struct atmel_mci *host, | MCI_BLKLEN(data->blksz)); dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n", MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz)); + + iflags |= atmci_prepare_data(host, data); } - iflags = MCI_CMDRDY; + iflags |= MCI_CMDRDY; cmd = mrq->cmd; cmdflags = atmci_prepare_command(slot->mmc, cmd); atmci_start_command(host, cmd, cmdflags); if (data) - iflags |= atmci_submit_data(host, data); + atmci_submit_data(host); if (mrq->stop) { host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); @@ -859,6 +916,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) clk_enable(host->mck); mci_writel(host, CR, MCI_CR_SWRST); mci_writel(host, CR, MCI_CR_MCIEN); + if (atmci_is_mci2()) + mci_writel(host, CFG, host->cfg_reg); } /* @@ -1097,6 +1156,8 @@ static void atmci_detect_change(unsigned long data) mci_writel(host, CR, MCI_CR_SWRST); mci_writel(host, CR, MCI_CR_MCIEN); mci_writel(host, MR, host->mode_reg); + if (atmci_is_mci2()) + mci_writel(host, CFG, host->cfg_reg); host->data = NULL; host->cmd = NULL; @@ -1620,6 +1681,10 @@ static void atmci_configure_dma(struct atmel_mci *host) } if (!host->dma.chan) dev_notice(&host->pdev->dev, "DMA not available, using PIO\n"); + else + dev_info(&host->pdev->dev, + "Using %s for DMA transfers\n", + dma_chan_name(host->dma.chan)); } #else static void atmci_configure_dma(struct atmel_mci *host) {} -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH 2/3 v2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver 2009-10-23 16:34 ` [PATCH 2/3 v2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver Nicolas Ferre @ 2009-11-02 17:18 ` Nicolas Ferre 2009-11-18 13:33 ` Nicolas Ferre 0 siblings, 1 reply; 47+ messages in thread From: Nicolas Ferre @ 2009-11-02 17:18 UTC (permalink / raw) To: linux-mmc, haavard.skinnemoen, akpm Cc: linux-kernel, kernel, linux-arm-kernel Hi, What do you think about the rework of this atmel-mci DMA interface ? patches: [PATCH 1/3 v2] atmel-mci: change use of dma slave interface [PATCH 2/3 v2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver We may consider them in replacement of the previous ones and dissociate this series from the third one which will be reworked and may goes through using another path. (for the record: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board). Thanks, Bye, -- Nicolas Ferre ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 2/3 v2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver 2009-11-02 17:18 ` Nicolas Ferre @ 2009-11-18 13:33 ` Nicolas Ferre 0 siblings, 0 replies; 47+ messages in thread From: Nicolas Ferre @ 2009-11-18 13:33 UTC (permalink / raw) To: haavard.skinnemoen, akpm; +Cc: linux-mmc, linux-kernel, linux-arm-kernel Nicolas Ferre : > Hi, > > What do you think about the rework of this atmel-mci DMA interface ? > patches: > [PATCH 1/3 v2] atmel-mci: change use of dma slave interface > [PATCH 2/3 v2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver > > We may consider them in replacement of the previous ones and dissociate > this series from the third one which will be reworked and may goes through > using another path. > (for the record: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc > driver in at91sam9g45 chip and board). Andrew, Haavard, Ping ? -- Nicolas Ferre ^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-10-23 16:34 ` [PATCH 1/3 v2] atmel-mci: change use of dma slave interface Nicolas Ferre 2009-10-23 16:34 ` [PATCH 2/3 v2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver Nicolas Ferre @ 2009-10-23 16:34 ` Nicolas Ferre 2009-10-26 8:15 ` Yegor Yefremov 2009-10-27 19:43 ` Andrew Victor 1 sibling, 2 replies; 47+ messages in thread From: Nicolas Ferre @ 2009-10-23 16:34 UTC (permalink / raw) To: linux-mmc, haavard.skinnemoen Cc: linux-kernel, kernel, akpm, linux-arm-kernel, Nicolas Ferre This adds the support of atmel-mci sd/mmc driver in at91sam9g45 devices and board files. This also configures the DMA controller slave interface for at_hdmac dmaengine driver. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> --- arch/arm/mach-at91/at91sam9g45_devices.c | 164 ++++++++++++++++++++++++++++++ arch/arm/mach-at91/board-sam9m10g45ek.c | 24 +++++ drivers/mmc/host/Kconfig | 2 +- 3 files changed, 189 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index d581cff..f341b7e 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -24,7 +24,10 @@ #include <mach/at91sam9g45.h> #include <mach/at91sam9g45_matrix.h> #include <mach/at91sam9_smc.h> + #include <mach/at_hdmac.h> +#include <mach/atmel-mci.h> +#include <linux/atmel-mci.h> #include "generic.h" @@ -294,6 +297,167 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {} /* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) +static u64 mmc_dmamask = DMA_BIT_MASK(32); +static struct mci_platform_data mmc0_data, mmc1_data; + +static struct resource mmc0_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_MCI0, + .end = AT91SAM9G45_BASE_MCI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_MCI0, + .end = AT91SAM9G45_ID_MCI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_mmc0_device = { + .name = "atmel_mci", + .id = 0, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &mmc0_data, + }, + .resource = mmc0_resources, + .num_resources = ARRAY_SIZE(mmc0_resources), +}; + +static struct resource mmc1_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_MCI1, + .end = AT91SAM9G45_BASE_MCI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_MCI1, + .end = AT91SAM9G45_ID_MCI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_mmc1_device = { + .name = "atmel_mci", + .id = 1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &mmc1_data, + }, + .resource = mmc1_resources, + .num_resources = ARRAY_SIZE(mmc1_resources), +}; + +/* Consider only one slot : slot 0 */ +void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) +{ + + if (!data) + return; + + /* Must have at least one usable slot */ + if (!data->slot[0].bus_width) + return; + +#if defined(CONFIG_MMC_ATMELMCI_DMA) + { + struct mci_dma_data *slave; + + slave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL); + + /* DMA slave channel configuration */ + slave->sdata.dma_dev = &at_hdmac_device.dev; + slave->sdata.reg_width = DW_DMA_SLAVE_WIDTH_32BIT; + slave->sdata.cfg = ATC_FIFOCFG_HALFFIFO + | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW; + slave->sdata.ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16; + if (mmc_id == 0) /* MCI0 */ + slave->sdata.cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0) + | ATC_DST_PER(AT_DMA_ID_MCI0); + + else /* MCI1 */ + slave->sdata.cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1) + | ATC_DST_PER(AT_DMA_ID_MCI1); + + data->dma_slave = slave; + } +#endif + + + /* input/irq */ + if (data->slot[0].detect_pin) { + at91_set_gpio_input(data->slot[0].detect_pin, 1); + at91_set_deglitch(data->slot[0].detect_pin, 1); + } + if (data->slot[0].wp_pin) + at91_set_gpio_input(data->slot[0].wp_pin, 1); + + if (mmc_id == 0) { /* MCI0 */ + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA0, 0); + + /* CMD */ + at91_set_A_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */ + at91_set_A_periph(AT91_PIN_PA2, 1); + if (data->slot[0].bus_width == 4) { + at91_set_A_periph(AT91_PIN_PA3, 1); + at91_set_A_periph(AT91_PIN_PA4, 1); + at91_set_A_periph(AT91_PIN_PA5, 1); + if (data->slot[0].bus_width == 8) { + at91_set_A_periph(AT91_PIN_PA6, 1); + at91_set_A_periph(AT91_PIN_PA7, 1); + at91_set_A_periph(AT91_PIN_PA8, 1); + at91_set_A_periph(AT91_PIN_PA9, 1); + } + } + + mmc0_data = *data; + at91_clock_associate("mci0_clk", &at91sam9g45_mmc0_device.dev, "mci_clk"); + platform_device_register(&at91sam9g45_mmc0_device); + + } else { /* MCI1 */ + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA31, 0); + + /* CMD */ + at91_set_A_periph(AT91_PIN_PA22, 1); + + /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */ + at91_set_A_periph(AT91_PIN_PA23, 1); + if (data->slot[0].bus_width == 4) { + at91_set_A_periph(AT91_PIN_PA24, 1); + at91_set_A_periph(AT91_PIN_PA25, 1); + at91_set_A_periph(AT91_PIN_PA26, 1); + if (data->slot[0].bus_width == 8) { + at91_set_A_periph(AT91_PIN_PA27, 1); + at91_set_A_periph(AT91_PIN_PA28, 1); + at91_set_A_periph(AT91_PIN_PA29, 1); + at91_set_A_periph(AT91_PIN_PA30, 1); + } + } + + mmc1_data = *data; + at91_clock_associate("mci1_clk", &at91sam9g45_mmc1_device.dev, "mci_clk"); + platform_device_register(&at91sam9g45_mmc1_device); + + } +} +#else +void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {} +#endif + + +/* -------------------------------------------------------------------- * NAND / SmartMedia * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index 64c3843..1cce010 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -24,6 +24,7 @@ #include <linux/input.h> #include <linux/leds.h> #include <linux/clk.h> +#include <linux/atmel-mci.h> #include <mach/hardware.h> #include <video/atmel_lcdc.h> @@ -99,6 +100,26 @@ static struct spi_board_info ek_spi_devices[] = { /* + * MCI (SD/MMC) + */ +static struct mci_platform_data __initdata mci0_data = { + .slot[0] = { + .bus_width = 4, + .detect_pin = AT91_PIN_PD10, + .wp_pin = -1, + }, +}; + +static struct mci_platform_data __initdata mci1_data = { + .slot[0] = { + .bus_width = 4, + .detect_pin = AT91_PIN_PD11, + .wp_pin = AT91_PIN_PD29, + }, +}; + + +/* * MACB Ethernet device */ static struct at91_eth_data __initdata ek_macb_data = { @@ -370,6 +391,9 @@ static void __init ek_board_init(void) at91_add_device_usba(&ek_usba_udc_data); /* SPI */ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); + /* MMC */ + at91_add_device_mci(0, &mci0_data); + at91_add_device_mci(1, &mci1_data); /* Ethernet */ at91_add_device_eth(&ek_macb_data); /* NAND */ diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 432ae83..b4aeb9d 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -188,7 +188,7 @@ endchoice config MMC_ATMELMCI_DMA bool "Atmel MCI DMA support (EXPERIMENTAL)" - depends on MMC_ATMELMCI && AVR32 && DMA_ENGINE && EXPERIMENTAL + depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE && EXPERIMENTAL help Say Y here to have the Atmel MCI driver use a DMA engine to do data transfers and thus increase the throughput and -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-10-23 16:34 ` [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board Nicolas Ferre @ 2009-10-26 8:15 ` Yegor Yefremov 2009-11-02 17:14 ` Nicolas Ferre 2009-10-27 19:43 ` Andrew Victor 1 sibling, 1 reply; 47+ messages in thread From: Yegor Yefremov @ 2009-10-26 8:15 UTC (permalink / raw) To: Nicolas Ferre Cc: linux-mmc, haavard.skinnemoen, akpm, kernel, linux-kernel, linux-arm-kernel Nicolas Ferre wrote: > This adds the support of atmel-mci sd/mmc driver in at91sam9g45 devices and > board files. This also configures the DMA controller slave interface for > at_hdmac dmaengine driver. > > Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> > --- > arch/arm/mach-at91/at91sam9g45_devices.c | 164 ++++++++++++++++++++++++++++++ > arch/arm/mach-at91/board-sam9m10g45ek.c | 24 +++++ > drivers/mmc/host/Kconfig | 2 +- > 3 files changed, 189 insertions(+), 1 deletions(-) > > diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c > index d581cff..f341b7e 100644 > --- a/arch/arm/mach-at91/at91sam9g45_devices.c > +++ b/arch/arm/mach-at91/at91sam9g45_devices.c > @@ -24,7 +24,10 @@ > #include <mach/at91sam9g45.h> > #include <mach/at91sam9g45_matrix.h> > #include <mach/at91sam9_smc.h> > + > #include <mach/at_hdmac.h> > +#include <mach/atmel-mci.h> > +#include <linux/atmel-mci.h> > > #include "generic.h" > > @@ -294,6 +297,167 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {} > > > /* -------------------------------------------------------------------- > + * MMC / SD > + * -------------------------------------------------------------------- */ > + > +#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) > +static u64 mmc_dmamask = DMA_BIT_MASK(32); > +static struct mci_platform_data mmc0_data, mmc1_data; > + > +static struct resource mmc0_resources[] = { > + [0] = { > + .start = AT91SAM9G45_BASE_MCI0, > + .end = AT91SAM9G45_BASE_MCI0 + SZ_16K - 1, > + .flags = IORESOURCE_MEM, > + }, > + [1] = { > + .start = AT91SAM9G45_ID_MCI0, > + .end = AT91SAM9G45_ID_MCI0, > + .flags = IORESOURCE_IRQ, > + }, > +}; > + > +static struct platform_device at91sam9g45_mmc0_device = { > + .name = "atmel_mci", > + .id = 0, > + .dev = { > + .dma_mask = &mmc_dmamask, > + .coherent_dma_mask = DMA_BIT_MASK(32), > + .platform_data = &mmc0_data, > + }, > + .resource = mmc0_resources, > + .num_resources = ARRAY_SIZE(mmc0_resources), > +}; > + > +static struct resource mmc1_resources[] = { > + [0] = { > + .start = AT91SAM9G45_BASE_MCI1, > + .end = AT91SAM9G45_BASE_MCI1 + SZ_16K - 1, > + .flags = IORESOURCE_MEM, > + }, > + [1] = { > + .start = AT91SAM9G45_ID_MCI1, > + .end = AT91SAM9G45_ID_MCI1, > + .flags = IORESOURCE_IRQ, > + }, > +}; > + > +static struct platform_device at91sam9g45_mmc1_device = { > + .name = "atmel_mci", > + .id = 1, > + .dev = { > + .dma_mask = &mmc_dmamask, > + .coherent_dma_mask = DMA_BIT_MASK(32), > + .platform_data = &mmc1_data, > + }, > + .resource = mmc1_resources, > + .num_resources = ARRAY_SIZE(mmc1_resources), > +}; > + > +/* Consider only one slot : slot 0 */ > +void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) > +{ > + > + if (!data) > + return; > + > + /* Must have at least one usable slot */ > + if (!data->slot[0].bus_width) > + return; > + > +#if defined(CONFIG_MMC_ATMELMCI_DMA) > + { > + struct mci_dma_data *slave; > + > + slave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL); > + > + /* DMA slave channel configuration */ > + slave->sdata.dma_dev = &at_hdmac_device.dev; > + slave->sdata.reg_width = DW_DMA_SLAVE_WIDTH_32BIT; slave->sdata.reg_width = AT_DMA_SLAVE_WIDTH_32BIT; > + slave->sdata.cfg = ATC_FIFOCFG_HALFFIFO > + | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW; > + slave->sdata.ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16; > + if (mmc_id == 0) /* MCI0 */ > + slave->sdata.cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0) > + | ATC_DST_PER(AT_DMA_ID_MCI0); > + > + else /* MCI1 */ > + slave->sdata.cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1) > + | ATC_DST_PER(AT_DMA_ID_MCI1); > + > + data->dma_slave = slave; > + } > +#endif > + > + > + /* input/irq */ > + if (data->slot[0].detect_pin) { > + at91_set_gpio_input(data->slot[0].detect_pin, 1); > + at91_set_deglitch(data->slot[0].detect_pin, 1); > + } > + if (data->slot[0].wp_pin) > + at91_set_gpio_input(data->slot[0].wp_pin, 1); > + > + if (mmc_id == 0) { /* MCI0 */ > + > + /* CLK */ > + at91_set_A_periph(AT91_PIN_PA0, 0); > + > + /* CMD */ > + at91_set_A_periph(AT91_PIN_PA1, 1); > + > + /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */ > + at91_set_A_periph(AT91_PIN_PA2, 1); > + if (data->slot[0].bus_width == 4) { > + at91_set_A_periph(AT91_PIN_PA3, 1); > + at91_set_A_periph(AT91_PIN_PA4, 1); > + at91_set_A_periph(AT91_PIN_PA5, 1); > + if (data->slot[0].bus_width == 8) { > + at91_set_A_periph(AT91_PIN_PA6, 1); > + at91_set_A_periph(AT91_PIN_PA7, 1); > + at91_set_A_periph(AT91_PIN_PA8, 1); > + at91_set_A_periph(AT91_PIN_PA9, 1); > + } > + } > + > + mmc0_data = *data; > + at91_clock_associate("mci0_clk", &at91sam9g45_mmc0_device.dev, "mci_clk"); > + platform_device_register(&at91sam9g45_mmc0_device); > + > + } else { /* MCI1 */ > + > + /* CLK */ > + at91_set_A_periph(AT91_PIN_PA31, 0); > + > + /* CMD */ > + at91_set_A_periph(AT91_PIN_PA22, 1); > + > + /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */ > + at91_set_A_periph(AT91_PIN_PA23, 1); > + if (data->slot[0].bus_width == 4) { > + at91_set_A_periph(AT91_PIN_PA24, 1); > + at91_set_A_periph(AT91_PIN_PA25, 1); > + at91_set_A_periph(AT91_PIN_PA26, 1); > + if (data->slot[0].bus_width == 8) { > + at91_set_A_periph(AT91_PIN_PA27, 1); > + at91_set_A_periph(AT91_PIN_PA28, 1); > + at91_set_A_periph(AT91_PIN_PA29, 1); > + at91_set_A_periph(AT91_PIN_PA30, 1); > + } > + } > + > + mmc1_data = *data; > + at91_clock_associate("mci1_clk", &at91sam9g45_mmc1_device.dev, "mci_clk"); > + platform_device_register(&at91sam9g45_mmc1_device); > + > + } > +} > +#else > +void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {} > +#endif > + > + > +/* -------------------------------------------------------------------- > * NAND / SmartMedia > * -------------------------------------------------------------------- */ > > diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c > index 64c3843..1cce010 100644 > --- a/arch/arm/mach-at91/board-sam9m10g45ek.c > +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c > @@ -24,6 +24,7 @@ > #include <linux/input.h> > #include <linux/leds.h> > #include <linux/clk.h> > +#include <linux/atmel-mci.h> > > #include <mach/hardware.h> > #include <video/atmel_lcdc.h> > @@ -99,6 +100,26 @@ static struct spi_board_info ek_spi_devices[] = { > > > /* > + * MCI (SD/MMC) > + */ > +static struct mci_platform_data __initdata mci0_data = { > + .slot[0] = { > + .bus_width = 4, > + .detect_pin = AT91_PIN_PD10, > + .wp_pin = -1, > + }, > +}; > + > +static struct mci_platform_data __initdata mci1_data = { > + .slot[0] = { > + .bus_width = 4, > + .detect_pin = AT91_PIN_PD11, > + .wp_pin = AT91_PIN_PD29, > + }, > +}; > + > + > +/* > * MACB Ethernet device > */ > static struct at91_eth_data __initdata ek_macb_data = { > @@ -370,6 +391,9 @@ static void __init ek_board_init(void) > at91_add_device_usba(&ek_usba_udc_data); > /* SPI */ > at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); > + /* MMC */ > + at91_add_device_mci(0, &mci0_data); > + at91_add_device_mci(1, &mci1_data); > /* Ethernet */ > at91_add_device_eth(&ek_macb_data); > /* NAND */ > diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig > index 432ae83..b4aeb9d 100644 > --- a/drivers/mmc/host/Kconfig > +++ b/drivers/mmc/host/Kconfig > @@ -188,7 +188,7 @@ endchoice > > config MMC_ATMELMCI_DMA > bool "Atmel MCI DMA support (EXPERIMENTAL)" > - depends on MMC_ATMELMCI && AVR32 && DMA_ENGINE && EXPERIMENTAL > + depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE && EXPERIMENTAL > help > Say Y here to have the Atmel MCI driver use a DMA engine to > do data transfers and thus increase the throughput and Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com> ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-10-26 8:15 ` Yegor Yefremov @ 2009-11-02 17:14 ` Nicolas Ferre 0 siblings, 0 replies; 47+ messages in thread From: Nicolas Ferre @ 2009-11-02 17:14 UTC (permalink / raw) To: yegor_sub1, linux-mmc Cc: haavard.skinnemoen, akpm, kernel, linux-kernel, linux-arm-kernel Yegor Yefremov : > Nicolas Ferre wrote: >> This adds the support of atmel-mci sd/mmc driver in at91sam9g45 devices and >> board files. This also configures the DMA controller slave interface for >> at_hdmac dmaengine driver. >> >> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> [..] >> + /* DMA slave channel configuration */ >> + slave->sdata.dma_dev = &at_hdmac_device.dev; >> + slave->sdata.reg_width = DW_DMA_SLAVE_WIDTH_32BIT; > > slave->sdata.reg_width = AT_DMA_SLAVE_WIDTH_32BIT; > >> + slave->sdata.cfg = ATC_FIFOCFG_HALFFIFO >> + | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW; Queued for v3 of this patch (I will dissociate if from the patch series). > Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com> Ok, I will add. Thanks a lot. Best regards, -- Nicolas Ferre ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-10-23 16:34 ` [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board Nicolas Ferre 2009-10-26 8:15 ` Yegor Yefremov @ 2009-10-27 19:43 ` Andrew Victor 2009-10-28 0:35 ` Haavard Skinnemoen 1 sibling, 1 reply; 47+ messages in thread From: Andrew Victor @ 2009-10-27 19:43 UTC (permalink / raw) To: Nicolas Ferre Cc: linux-mmc, haavard.skinnemoen, akpm, kernel, linux-kernel, linux-arm-kernel hi Nicolas, > + if (data->slot[0].wp_pin) > + at91_set_gpio_input(data->slot[0].wp_pin, 1); > +static struct mci_platform_data __initdata mci0_data = { > + .slot[0] = { > + .bus_width = 4, > + .detect_pin = AT91_PIN_PD10, > + .wp_pin = -1, > + }, Causes at91_set_gpio_input() to be called for pin -1. Which shouldn't be valid. AT91 platforms use 0 to indicate an un-connected GPIO pin, so the assignment of "wp_pin" should probably just be removed. Regards, Andrew Victor ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-10-27 19:43 ` Andrew Victor @ 2009-10-28 0:35 ` Haavard Skinnemoen 2009-10-28 0:53 ` Thiago A. Corrêa 0 siblings, 1 reply; 47+ messages in thread From: Haavard Skinnemoen @ 2009-10-28 0:35 UTC (permalink / raw) To: Andrew Victor Cc: Nicolas Ferre, kernel, linux-mmc, linux-kernel, akpm, linux-arm-kernel Andrew Victor <avictor.za@gmail.com> wrote: > > +static struct mci_platform_data __initdata mci0_data = { > > + .slot[0] = { > > + .bus_width = 4, > > + .detect_pin = AT91_PIN_PD10, > > + .wp_pin = -1, > > + }, > > Causes at91_set_gpio_input() to be called for pin -1. Which shouldn't be valid. > AT91 platforms use 0 to indicate an un-connected GPIO pin, so the > assignment of "wp_pin" should probably just be removed. The mci driver expects non-existent pins to have a negative value, as do all other drivers which use gpio_is_valid(). Haavard ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-10-28 0:35 ` Haavard Skinnemoen @ 2009-10-28 0:53 ` Thiago A. Corrêa 2009-10-28 1:31 ` Haavard Skinnemoen 2009-10-28 19:53 ` Andrew Victor 0 siblings, 2 replies; 47+ messages in thread From: Thiago A. Corrêa @ 2009-10-28 0:53 UTC (permalink / raw) To: Haavard Skinnemoen Cc: Andrew Victor, linux-mmc, kernel, linux-kernel, Nicolas Ferre, akpm, linux-arm-kernel On Tue, Oct 27, 2009 at 10:35 PM, Haavard Skinnemoen <haavard.skinnemoen@atmel.com> wrote: > Andrew Victor <avictor.za@gmail.com> wrote: >> > +static struct mci_platform_data __initdata mci0_data = { >> > + .slot[0] = { >> > + .bus_width = 4, >> > + .detect_pin = AT91_PIN_PD10, >> > + .wp_pin = -1, >> > + }, >> >> Causes at91_set_gpio_input() to be called for pin -1. Which shouldn't be valid. >> AT91 platforms use 0 to indicate an un-connected GPIO pin, so the >> assignment of "wp_pin" should probably just be removed. > > The mci driver expects non-existent pins to have a negative value, as > do all other drivers which use gpio_is_valid(). > Then I think it would be best to use GPIO_PIN_NONE. Makes it clear what is expected and avoids confusion on what should be the proper value. I hope I'm not saying non-sense, but even if I am, I guess you can see that I'm advocating against the magic numbers :) Kind Regards, Thiago A. Correa ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-10-28 0:53 ` Thiago A. Corrêa @ 2009-10-28 1:31 ` Haavard Skinnemoen 2009-10-28 19:53 ` Andrew Victor 1 sibling, 0 replies; 47+ messages in thread From: Haavard Skinnemoen @ 2009-10-28 1:31 UTC (permalink / raw) To: Thiago A. Corrêa Cc: linux-mmc, kernel, linux-kernel, Nicolas Ferre, Andrew Victor, akpm, linux-arm-kernel Thiago A. Corrêa <thiago.correa@gmail.com> wrote: > >> Causes at91_set_gpio_input() to be called for pin -1. Which shouldn't be valid. > >> AT91 platforms use 0 to indicate an un-connected GPIO pin, so the > >> assignment of "wp_pin" should probably just be removed. > > > > The mci driver expects non-existent pins to have a negative value, as > > do all other drivers which use gpio_is_valid(). > > > > Then I think it would be best to use GPIO_PIN_NONE. Makes it clear > what is expected and avoids confusion on what should be the proper > value. Unfortunately, GPIO_PIN_NONE only exists on AVR32. > I hope I'm not saying non-sense, but even if I am, I guess you can see > that I'm advocating against the magic numbers :) IIRC, the correct way to specify a non-existent pin is to use -ENODEV. Haavard ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-10-28 0:53 ` Thiago A. Corrêa 2009-10-28 1:31 ` Haavard Skinnemoen @ 2009-10-28 19:53 ` Andrew Victor 2009-10-28 20:50 ` Ben Nizette 1 sibling, 1 reply; 47+ messages in thread From: Andrew Victor @ 2009-10-28 19:53 UTC (permalink / raw) To: Thiago A. Corrêa Cc: Haavard Skinnemoen, linux-mmc, kernel, linux-kernel, Nicolas Ferre, akpm, linux-arm-kernel hi, > Then I think it would be best to use GPIO_PIN_NONE. Makes it clear > what is expected and avoids confusion on what should be the proper > value. > I hope I'm not saying non-sense, but even if I am, I guess you can see > that I'm advocating against the magic numbers :) What magic numbers ? If you have a "wp_pin" on the board, you declare the struct as: static struct mci_platform_data __initdata mci0_data = { .slot[0] = { .bus_width = 4, .detect_pin = AT91_PIN_PD10, } } and if you do have a "wp_pin" on your board, you declare the struct as: static struct mci_platform_data __initdata mci0_data = { .slot[0] = { .bus_width = 4, .detect_pin = AT91_PIN_PD10, .wp_pin = AT91_PIN_PD11, } } And it's more future-proof. If the next version of the driver/peripheral has a "toggle_pin" GPIO option, you don't need to go update all board files with a ".toggle_pin = GPIO_PIN_NONE" or ".toggle_pin = -ENODEV". Regards, Andrew Victor ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-10-28 19:53 ` Andrew Victor @ 2009-10-28 20:50 ` Ben Nizette 2009-11-02 17:11 ` Nicolas Ferre 0 siblings, 1 reply; 47+ messages in thread From: Ben Nizette @ 2009-10-28 20:50 UTC (permalink / raw) To: Andrew Victor Cc: Thiago A. Corrêa, kernel, linux-mmc, linux-kernel, Nicolas Ferre, akpm, linux-arm-kernel On Wed, 2009-10-28 at 21:53 +0200, Andrew Victor wrote: > hi, > > > Then I think it would be best to use GPIO_PIN_NONE. Makes it clear > > what is expected and avoids confusion on what should be the proper > > value. > > I hope I'm not saying non-sense, but even if I am, I guess you can see > > that I'm advocating against the magic numbers :) > > What magic numbers ? I think Thiago was referring to the "-1" in the original patch as the magic number. Leaving the field blank to be initialised to 0 is certainly the cleanest, I agree, but it doesn't actually /work/. On many archs 0 is a valid gpio number; the gpio_is_valid check used throughout the kernel (including atmel-mci.c) looks like static inline int gpio_is_valid(int number) { /* only some non-negative numbers are valid */ return ((unsigned)number) < ARCH_NR_GPIOS; } --Ben. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-10-28 20:50 ` Ben Nizette @ 2009-11-02 17:11 ` Nicolas Ferre 2009-11-02 22:10 ` Ben Nizette ` (2 more replies) 0 siblings, 3 replies; 47+ messages in thread From: Nicolas Ferre @ 2009-11-02 17:11 UTC (permalink / raw) To: Ben Nizette, Andrew Victor, linux-arm-kernel Cc: "\"Thiago A.\" Corrêa", kernel, linux-mmc, linux-kernel, akpm Ben Nizette : > On Wed, 2009-10-28 at 21:53 +0200, Andrew Victor wrote: >> hi, >> >>> Then I think it would be best to use GPIO_PIN_NONE. Makes it clear >>> what is expected and avoids confusion on what should be the proper >>> value. >>> I hope I'm not saying non-sense, but even if I am, I guess you can see >>> that I'm advocating against the magic numbers :) >> What magic numbers ? > > I think Thiago was referring to the "-1" in the original patch as the > magic number. > > Leaving the field blank to be initialised to 0 is certainly the > cleanest, I agree, but it doesn't actually /work/. On many archs 0 is a > valid gpio number; the gpio_is_valid check used throughout the kernel > (including atmel-mci.c) looks like > > static inline int gpio_is_valid(int number) > { > /* only some non-negative numbers are valid */ > return ((unsigned)number) < ARCH_NR_GPIOS; > } I understand that the better way to solve this issue is to: - keep the AT91 way of specifying not connected pins (= 0) - code the gpio_is_valid() function for at91 that tests this way of handling not connected gpio I see that in arch/arm/mach-at91/include/mach/gpio.h we include the asm-generic/gpio.h file... must I implement the full set of gpiolib ? Best regards, -- Nicolas Ferre ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-11-02 17:11 ` Nicolas Ferre @ 2009-11-02 22:10 ` Ben Nizette 2009-11-02 22:14 ` Ben Nizette 2009-11-03 2:30 ` Ryan Mallon 2 siblings, 0 replies; 47+ messages in thread From: Ben Nizette @ 2009-11-02 22:10 UTC (permalink / raw) To: Nicolas Ferre Cc: Andrew Victor, linux-arm-kernel, "\"Thiago A.\" Corrêa", kernel, linux-mmc, linux-kernel, akpm On Mon, 2009-11-02 at 18:11 +0100, Nicolas Ferre wrote: > Ben Nizette : > > > > static inline int gpio_is_valid(int number) > > { > > /* only some non-negative numbers are valid */ > > return ((unsigned)number) < ARCH_NR_GPIOS; > > } > > I understand that the better way to solve this issue is to: > - keep the AT91 way of specifying not connected pins (= 0) > - code the gpio_is_valid() function for at91 that tests this way of > handling not connected gpio > > I see that in arch/arm/mach-at91/include/mach/gpio.h > we include the asm-generic/gpio.h file... must I implement the full set > of gpiolib ? > > Best regards, ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-11-02 17:11 ` Nicolas Ferre 2009-11-02 22:10 ` Ben Nizette @ 2009-11-02 22:14 ` Ben Nizette 2009-11-03 2:30 ` Ryan Mallon 2 siblings, 0 replies; 47+ messages in thread From: Ben Nizette @ 2009-11-02 22:14 UTC (permalink / raw) To: Nicolas Ferre Cc: Andrew Victor, linux-arm-kernel, "\"Thiago A.\" Corrêa", kernel, linux-mmc, linux-kernel, akpm [apologies for the MTA fart causing that weird, rouge blank email :-) ] On Mon, 2009-11-02 at 18:11 +0100, Nicolas Ferre wrote: > Ben Nizette : > > > > static inline int gpio_is_valid(int number) > > { > > /* only some non-negative numbers are valid */ > > return ((unsigned)number) < ARCH_NR_GPIOS; > > } > > I understand that the better way to solve this issue is to: > - keep the AT91 way of specifying not connected pins (= 0) > - code the gpio_is_valid() function for at91 that tests this way of > handling not connected gpio > I'm not sure I'd break cross-arch compat here, but whatever. I guess it depends how deeply the =0 stuff is ingrained in the at91 codebase > I see that in arch/arm/mach-at91/include/mach/gpio.h > we include the asm-generic/gpio.h file... must I implement the full set > of gpiolib ? I'd suggest creating an ARCH_HAVE_GPIO_VALID (darn, long name) or something; define it before #include <asm-generic/gpio.h> and #ifdef protect the offending declaration in that header. --Ben. > > Best regards, ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-11-02 17:11 ` Nicolas Ferre 2009-11-02 22:10 ` Ben Nizette 2009-11-02 22:14 ` Ben Nizette @ 2009-11-03 2:30 ` Ryan Mallon 2009-11-03 2:55 ` Ben Nizette 2 siblings, 1 reply; 47+ messages in thread From: Ryan Mallon @ 2009-11-03 2:30 UTC (permalink / raw) To: Nicolas Ferre Cc: Ben Nizette, Andrew Victor, linux-arm-kernel, linux-mmc, "\"Thiago A.\" Corrêa", kernel, linux-kernel, akpm, David Brownell, David Brownell Nicolas Ferre wrote: > Ben Nizette : > >> On Wed, 2009-10-28 at 21:53 +0200, Andrew Victor wrote: >> >>> hi, >>> >>> >>>> Then I think it would be best to use GPIO_PIN_NONE. Makes it clear >>>> what is expected and avoids confusion on what should be the proper >>>> value. >>>> I hope I'm not saying non-sense, but even if I am, I guess you can see >>>> that I'm advocating against the magic numbers :) >>>> >>> What magic numbers ? >>> >> I think Thiago was referring to the "-1" in the original patch as the >> magic number. >> >> Leaving the field blank to be initialised to 0 is certainly the >> cleanest, I agree, but it doesn't actually /work/. On many archs 0 is a >> valid gpio number; the gpio_is_valid check used throughout the kernel >> (including atmel-mci.c) looks like >> >> static inline int gpio_is_valid(int number) >> { >> /* only some non-negative numbers are valid */ >> return ((unsigned)number) < ARCH_NR_GPIOS; >> } >> > > I understand that the better way to solve this issue is to: > - keep the AT91 way of specifying not connected pins (= 0) > - code the gpio_is_valid() function for at91 that tests this way of > handling not connected gpio > It doesn't appear that the gpio_is_valid function can be overridden by a platform specific version. However, as you point out, on AT91 it appears broken since anything less than AT91_PIN_PA0 (32) is not a valid gpio. IIRC, we can't mark static inline functions as weak, and we don't want to turn gpio_is_valid into an actual function call. We could do some preprocessor magic, but that gets a bit messy. CC'ed David Brownell, who does most of the gpiolib stuff. Any ideas? ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan@bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-11-03 2:30 ` Ryan Mallon @ 2009-11-03 2:55 ` Ben Nizette 2009-11-07 11:20 ` Haavard Skinnemoen 0 siblings, 1 reply; 47+ messages in thread From: Ben Nizette @ 2009-11-03 2:55 UTC (permalink / raw) To: Ryan Mallon Cc: Nicolas Ferre, Andrew Victor, linux-arm-kernel, linux-mmc, "\"Thiago A.\" Corrêa", kernel, linux-kernel, akpm, David Brownell, David Brownell On Tue, 2009-11-03 at 15:30 +1300, Ryan Mallon wrote: > > > IIRC, we can't mark static inline functions as weak, and we don't want > to turn gpio_is_valid into an actual function call. We could do some > preprocessor magic, but that gets a bit messy. Messy but generally accepted. Have a grep for, eg, __HAVE_ARCH_<string functions> and HAVE_ARCH_BUG{_ON} --Ben. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board 2009-11-03 2:55 ` Ben Nizette @ 2009-11-07 11:20 ` Haavard Skinnemoen 2010-08-23 15:01 ` [PATCH] pio: add arch specific gpio_is_valid() function Nicolas Ferre 0 siblings, 1 reply; 47+ messages in thread From: Haavard Skinnemoen @ 2009-11-07 11:20 UTC (permalink / raw) To: Ben Nizette Cc: Ryan Mallon, David Brownell, kernel, linux-mmc, linux-kernel, Nicolas Ferre, David Brownell, Andrew Victor, akpm, linux-arm-kernel Ben Nizette <bn@niasdigital.com> wrote: > On Tue, 2009-11-03 at 15:30 +1300, Ryan Mallon wrote: > > > > > IIRC, we can't mark static inline functions as weak, and we don't want > > to turn gpio_is_valid into an actual function call. We could do some > > preprocessor magic, but that gets a bit messy. > > Messy but generally accepted. IIRC the most generally accepted way is to do static inline bool gpio_is_valid(int pin) { /* whatever */ } #define gpio_is_valid gpio_is_valid in the platform code and #ifndef gpio_is_valid /* provide definition of gpio_is_valid */ #endif in the generic code. This way, there's only one symbol to grep for. Haavard ^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH] pio: add arch specific gpio_is_valid() function 2009-11-07 11:20 ` Haavard Skinnemoen @ 2010-08-23 15:01 ` Nicolas Ferre 2010-08-23 16:36 ` David Brownell 2010-09-03 16:41 ` [PATCH] pio: add arch specific " Jean-Christophe PLAGNIOL-VILLARD 0 siblings, 2 replies; 47+ messages in thread From: Nicolas Ferre @ 2010-08-23 15:01 UTC (permalink / raw) To: linux-kernel, linux-arm-kernel, bn, ryan, david-b Cc: avictor.za, Nicolas Ferre Add a simple gpio_is_valid() function to replace the standard one. It introduces the __HAVE_ARCH_GPIO_IS_VALID macro to overload the generic code. As an implementation example, it takes into account the AT91 pio numbering to check if a proper value is used. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> --- Hi all, I come back on this thread as I would like to implement the gpio_is_valid() function for AT91. I have based this piece of code on comments from Ben and Haavard and chose the __HAVE_ARCH_* macro definition as it seems wide spread in kernel code. Please make comments and if it is ok for you, eventually accept for merging... arch/arm/mach-at91/include/mach/gpio.h | 9 +++++++++ include/asm-generic/gpio.h | 4 ++++ 2 files changed, 13 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index 5cce2ed..103486d 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -188,6 +188,15 @@ #define AT91_PIN_PE31 (PIN_BASE + 0x80 + 31) #ifndef __ASSEMBLY__ +static inline int gpio_is_valid(int number) +{ + if (number >= PIN_BASE) + return 1; + return 0; +} +#define __HAVE_ARCH_GPIO_IS_VALID 1 + + /* setup setup routines, called from board init or driver probe() */ extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup); extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup); diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 4f3d75e..2840f35 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -22,11 +22,13 @@ #define ARCH_NR_GPIOS 256 #endif +#ifndef __HAVE_ARCH_GPIO_IS_VALID static inline int gpio_is_valid(int number) { /* only some non-negative numbers are valid */ return ((unsigned)number) < ARCH_NR_GPIOS; } +#endif struct device; struct seq_file; @@ -185,11 +187,13 @@ extern void gpio_unexport(unsigned gpio); #else /* !CONFIG_HAVE_GPIO_LIB */ +#ifndef __HAVE_ARCH_GPIO_IS_VALID static inline int gpio_is_valid(int number) { /* only non-negative numbers are valid */ return number >= 0; } +#endif /* platforms that don't directly support access to GPIOs through I2C, SPI, * or other blocking infrastructure can use these wrappers. -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-08-23 15:01 ` [PATCH] pio: add arch specific gpio_is_valid() function Nicolas Ferre @ 2010-08-23 16:36 ` David Brownell 2010-08-24 8:19 ` Nicolas Ferre 2010-09-03 16:41 ` [PATCH] pio: add arch specific " Jean-Christophe PLAGNIOL-VILLARD 1 sibling, 1 reply; 47+ messages in thread From: David Brownell @ 2010-08-23 16:36 UTC (permalink / raw) To: linux-kernel, linux-arm-kernel, bn, ryan, Nicolas Ferre Cc: avictor.za, Nicolas Ferre --- On Mon, 8/23/10, Nicolas Ferre <nicolas.ferre@atmel.com> wrote: > From: Nicolas Ferre <nicolas.ferre@atmel.com> > Subject: [PATCH] pio: add arch specific gpio_is_valid() function What's the rationale? It's valid or not. And there's already a function whose job it is to report that status ... which is set up for arch customization. Which ISTR worked fine for AT91 (among other platforms) ... So my first reacion is "NAK, pointless". > ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-08-23 16:36 ` David Brownell @ 2010-08-24 8:19 ` Nicolas Ferre 2010-09-06 14:21 ` [PATCH v2] AT91: pio: add " Nicolas Ferre 0 siblings, 1 reply; 47+ messages in thread From: Nicolas Ferre @ 2010-08-24 8:19 UTC (permalink / raw) To: David Brownell; +Cc: linux-kernel, linux-arm-kernel, bn, ryan, avictor.za Le 23/08/2010 18:36, David Brownell : > > > --- On Mon, 8/23/10, Nicolas Ferre <nicolas.ferre@atmel.com> wrote: > >> From: Nicolas Ferre <nicolas.ferre@atmel.com> >> Subject: [PATCH] pio: add arch specific gpio_is_valid() function > > What's the rationale? It's valid or not. And there's already a > function whose job it is to report that status ... which is set up > for arch customization. How do you customize it? I would like to keep the benefit of gpiolib implementation. In arch/arm/mach-at91/include/mach/gpio.h we include the asm-generic/gpio.h. That is why I protect the generic code with __HAVE_ARCH_GPIO_IS_VALID. With this, we can keep the benefit of having an inline function. > Which ISTR worked fine for AT91 (among other > platforms) ... Well the standard function: return ((unsigned)number) < ARCH_NR_GPIOS; is not suitable for AT91 as said in the thread. Best regards, -- Nicolas Ferre ^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH v2] AT91: pio: add gpio_is_valid() function 2010-08-24 8:19 ` Nicolas Ferre @ 2010-09-06 14:21 ` Nicolas Ferre 2010-09-07 1:51 ` David Brownell 0 siblings, 1 reply; 47+ messages in thread From: Nicolas Ferre @ 2010-09-06 14:21 UTC (permalink / raw) To: linux-kernel, linux-arm-kernel, bn, ryan, david-b Cc: avictor.za, plagnioj, Nicolas Ferre Add a simple gpio_is_valid() function to overload the standard one. It takes into account the AT91 pio numbering to check if a proper value is used. The upper limit keeps room for IO expanders above regular on-chip GPIO numbers. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> --- Changes since v1: define ARCH_NR_GPIOS for AT91 keeping room for IO expanders now use an upper limit to conform with gpiolib arch/arm/mach-at91/include/mach/gpio.h | 14 ++++++++++++++ include/asm-generic/gpio.h | 4 ++++ 2 files changed, 18 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index bfdd8ab..55828ad 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -21,6 +21,10 @@ #define MAX_GPIO_BANKS 5 #define NR_BUILTIN_GPIO (PIN_BASE + (MAX_GPIO_BANKS * 32)) +/* keep room for a couple of GPIO expanders */ +#define NR_EXTRA_GPIO 64 +#define ARCH_NR_GPIOS (NR_BUILTIN_GPIO + NR_EXTRA_GPIO) + /* these pin numbers double as IRQ numbers, like AT91xxx_ID_* values */ #define AT91_PIN_PA0 (PIN_BASE + 0x00 + 0) @@ -189,6 +193,16 @@ #define AT91_PIN_PE31 (PIN_BASE + 0x80 + 31) #ifndef __ASSEMBLY__ +static inline int gpio_is_valid(int number) +{ + if (number >= PIN_BASE && + number <= ARCH_NR_GPIOS) + return 1; + return 0; +} +#define __HAVE_ARCH_GPIO_IS_VALID 1 + + /* setup setup routines, called from board init or driver probe() */ extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup); extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup); diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index c7376bf..264e701 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -22,11 +22,13 @@ #define ARCH_NR_GPIOS 256 #endif +#ifndef __HAVE_ARCH_GPIO_IS_VALID static inline int gpio_is_valid(int number) { /* only some non-negative numbers are valid */ return ((unsigned)number) < ARCH_NR_GPIOS; } +#endif struct device; struct seq_file; @@ -200,11 +202,13 @@ extern void gpio_unexport(unsigned gpio); #else /* !CONFIG_HAVE_GPIO_LIB */ +#ifndef __HAVE_ARCH_GPIO_IS_VALID static inline int gpio_is_valid(int number) { /* only non-negative numbers are valid */ return number >= 0; } +#endif /* platforms that don't directly support access to GPIOs through I2C, SPI, * or other blocking infrastructure can use these wrappers. -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH v2] AT91: pio: add gpio_is_valid() function 2010-09-06 14:21 ` [PATCH v2] AT91: pio: add " Nicolas Ferre @ 2010-09-07 1:51 ` David Brownell 0 siblings, 0 replies; 47+ messages in thread From: David Brownell @ 2010-09-07 1:51 UTC (permalink / raw) To: linux-kernel, linux-arm-kernel, bn, ryan, Nicolas Ferre Cc: avictor.za, plagnioj, Nicolas Ferre --- On Mon, 9/6/10, Nicolas Ferre <nicolas.ferre@atmel.com> wrote: > From: Nicolas Ferre <nicolas.ferre@atmel.com> > Subject: [PATCH v2] AT91: pio: add gpio_is_valid() function Of course there already *IS* a gpio_is_valid(), with arch/platform hooks > --- a/arch/arm/mach-at91/include/mach/gpio.h > +++ b/arch/arm/mach-at91/include/mach/gpio.h > > +/* keep room for a couple of GPIO expanders */ > +#define NR_EXTRA_GPIO 64 > +#define ARCH_NR_GPIOS > (NR_BUILTIN_GPIO + NR_EXTRA_GPIO) ISTR contemplating something like NR_EXTRA_GPIO once too, but deciding against it. Doing it this way (per-platform) seems OK. ISTR, matches OMAP; might be worth generalizing...) > #ifndef __ASSEMBLY__ > +static inline int gpio_is_valid(int number) > +{ > + if (number >= PIN_BASE && I suppose that clause is the entire reason to not like the standard gpio_is_valid() ?? Since on AT91 the IRQ and GPIO numbers share the same space, but 0..(PIN_BASE-1) are IRQs not GPIOs. Yes? Worth re-thinking your approach to handling that. Most of the numbers in that range are valid GPIO numbers -- on non-AT91 platforms. Maybe AT91 scould grow to_gpio(N) and to_irq(N) macros. It was handy sharing the spaces when implementing GPIO IRQ support, but in retrospect maybe that was not the best idea. > + number <= > ARCH_NR_GPIOS) More conventional, FWIW -- just return the boolean xpression's value ... > + return 1; > + return 0; ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-08-23 15:01 ` [PATCH] pio: add arch specific gpio_is_valid() function Nicolas Ferre 2010-08-23 16:36 ` David Brownell @ 2010-09-03 16:41 ` Jean-Christophe PLAGNIOL-VILLARD 2010-09-07 2:23 ` David Brownell 1 sibling, 1 reply; 47+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-09-03 16:41 UTC (permalink / raw) To: Nicolas Ferre Cc: linux-kernel, linux-arm-kernel, bn, ryan, david-b, avictor.za On 17:01 Mon 23 Aug , Nicolas Ferre wrote: > Add a simple gpio_is_valid() function to replace > the standard one. It introduces the __HAVE_ARCH_GPIO_IS_VALID > macro to overload the generic code. > As an implementation example, it takes into account the AT91 > pio numbering to check if a proper value is used. > > Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> > --- > Hi all, > > I come back on this thread as I would like to implement the gpio_is_valid() > function for AT91. I have based this piece of code on comments from Ben and > Haavard and chose the __HAVE_ARCH_* macro definition as it seems wide spread > in kernel code. > Please make comments and if it is ok for you, eventually accept for merging... > Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> specially when the drivers are share between different arch such as here avr32 and arm but also for renesas between sh and arm and ST between SH and ST200 the representation of an invalid gpio could differ and invalade it dito Best Regards, J. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-03 16:41 ` [PATCH] pio: add arch specific " Jean-Christophe PLAGNIOL-VILLARD @ 2010-09-07 2:23 ` David Brownell 2010-09-07 2:44 ` Ryan Mallon 0 siblings, 1 reply; 47+ messages in thread From: David Brownell @ 2010-09-07 2:23 UTC (permalink / raw) To: Nicolas Ferre, Jean-Christophe PLAGNIOL-VILLARD Cc: linux-kernel, linux-arm-kernel, bn, ryan, avictor.za Still not liking or accepting this proposed change to the GPIO framework. For the AT91 case (where integers 0..N are IRQs, but N..max are GPIOs) A simpler solution is just to use a bit in the integer to indicate IRQ vs GPIO. Like maybe the sign bit.. which is never set on valid GPIO numbers, but platforms could let be set on IRQs. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 2:23 ` David Brownell @ 2010-09-07 2:44 ` Ryan Mallon 2010-09-07 3:54 ` Eric Miao 2010-09-07 6:33 ` David Brownell 0 siblings, 2 replies; 47+ messages in thread From: Ryan Mallon @ 2010-09-07 2:44 UTC (permalink / raw) To: David Brownell Cc: Nicolas Ferre, Jean-Christophe PLAGNIOL-VILLARD, linux-kernel, linux-arm-kernel, bn, avictor.za On 09/07/2010 02:23 PM, David Brownell wrote: > Still not liking or accepting this proposed > change to the GPIO framework. > > For the AT91 case (where integers 0..N are > IRQs, but N..max are GPIOs) > > A simpler solution is just to use a bit in > the integer to indicate IRQ vs GPIO. Like > maybe the sign bit.. which is never set on > valid GPIO numbers, but platforms could let > be set on IRQs. > How about this approach instead? ---- On some architectures gpio numbering does not start from zero. Allow for correct behaviour of gpio_is_valid on values below the first gpio by adding the architecture overrideable ARCH_FIRST_GPIO. Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> ---- diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index c7376bf..01aab1f 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -22,10 +22,15 @@ #define ARCH_NR_GPIOS 256 #endif +#ifndef ARCH_FIRST_GPIO +#define ARCH_FIRST_GPIO 0 +#endif + static inline int gpio_is_valid(int number) { /* only some non-negative numbers are valid */ - return ((unsigned)number) < ARCH_NR_GPIOS; + return (number >= ARCH_FIRST_GPIO && + (unsigned)number < ARCH_NR_GPIOS; } struct device; ^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 2:44 ` Ryan Mallon @ 2010-09-07 3:54 ` Eric Miao 2010-09-07 4:07 ` Ryan Mallon 2010-09-07 6:33 ` David Brownell 1 sibling, 1 reply; 47+ messages in thread From: Eric Miao @ 2010-09-07 3:54 UTC (permalink / raw) To: Ryan Mallon Cc: David Brownell, Nicolas Ferre, linux-kernel, avictor.za, bn, Jean-Christophe PLAGNIOL-VILLARD, linux-arm-kernel On Tue, Sep 7, 2010 at 10:44 AM, Ryan Mallon <ryan@bluewatersys.com> wrote: > On 09/07/2010 02:23 PM, David Brownell wrote: >> Still not liking or accepting this proposed >> change to the GPIO framework. >> >> For the AT91 case (where integers 0..N are >> IRQs, but N..max are GPIOs) >> >> A simpler solution is just to use a bit in >> the integer to indicate IRQ vs GPIO. Like >> maybe the sign bit.. which is never set on >> valid GPIO numbers, but platforms could let >> be set on IRQs. >> > How about this approach instead? > This doesn't solve the problem with more complicated settings, e.g. some GPIOs within are not valid, not just the begining ones. So the real question here is the semantics of gpio_is_valid(). I'd personally incline it reads as if a GPIO _number_ is valid generally, (e.g. like -1 is not a valid GPIO number), instead of that specific GPIO is valid on that specific platform. The latter can be judged with gpio_request(). > ---- > On some architectures gpio numbering does not start from zero. Allow for > correct behaviour of gpio_is_valid on values below the first gpio by > adding the architecture overrideable ARCH_FIRST_GPIO. > > Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> > ---- > > diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h > index c7376bf..01aab1f 100644 > --- a/include/asm-generic/gpio.h > +++ b/include/asm-generic/gpio.h > @@ -22,10 +22,15 @@ > #define ARCH_NR_GPIOS 256 > #endif > > +#ifndef ARCH_FIRST_GPIO > +#define ARCH_FIRST_GPIO 0 > +#endif > + > static inline int gpio_is_valid(int number) > { > /* only some non-negative numbers are valid */ > - return ((unsigned)number) < ARCH_NR_GPIOS; > + return (number >= ARCH_FIRST_GPIO && > + (unsigned)number < ARCH_NR_GPIOS; > } > > struct device; > > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel > ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 3:54 ` Eric Miao @ 2010-09-07 4:07 ` Ryan Mallon 2010-09-07 4:19 ` Eric Miao 0 siblings, 1 reply; 47+ messages in thread From: Ryan Mallon @ 2010-09-07 4:07 UTC (permalink / raw) To: Eric Miao Cc: David Brownell, Nicolas Ferre, linux-kernel, avictor.za, bn, Jean-Christophe PLAGNIOL-VILLARD, linux-arm-kernel On 09/07/2010 03:54 PM, Eric Miao wrote: > On Tue, Sep 7, 2010 at 10:44 AM, Ryan Mallon <ryan@bluewatersys.com> wrote: >> On 09/07/2010 02:23 PM, David Brownell wrote: >>> Still not liking or accepting this proposed >>> change to the GPIO framework. >>> >>> For the AT91 case (where integers 0..N are >>> IRQs, but N..max are GPIOs) >>> >>> A simpler solution is just to use a bit in >>> the integer to indicate IRQ vs GPIO. Like >>> maybe the sign bit.. which is never set on >>> valid GPIO numbers, but platforms could let >>> be set on IRQs. >>> >> How about this approach instead? >> > > This doesn't solve the problem with more complicated settings, e.g. > some GPIOs within are not valid, not just the begining ones. Agreed, but this does solve the immediate problem for AT91 in a simple way. Are there boards in the kernel which have holes in the gpio layout? Another possible solution is to loop through all the gpio_chips to see if the number maps to a valid gpio. The obvious downside to this approach is that the complexity of gpio_is_valid becomes reasonably high for something which should be a very simple test and, as you say below, we probably just don't need that fine-grained information. > So the real question here is the semantics of gpio_is_valid(). I'd > personally incline it reads as if a GPIO _number_ is valid generally, > (e.g. like -1 is not a valid GPIO number), instead of that specific > GPIO is valid on that specific platform. The latter can be judged > with gpio_request(). Some drivers in the kernel appear to be using this behaviour to have optional gpios, ie setting the foo_gpio = -1 in the platform data for some driver. The documentation also suggests that this is what gpio_is_valid is intended for. However, the documentation also says we may want gpio_is_valid to return invalid on some other numbers. ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan@bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 4:07 ` Ryan Mallon @ 2010-09-07 4:19 ` Eric Miao 2010-09-07 4:26 ` Ryan Mallon 0 siblings, 1 reply; 47+ messages in thread From: Eric Miao @ 2010-09-07 4:19 UTC (permalink / raw) To: Ryan Mallon Cc: David Brownell, Nicolas Ferre, linux-kernel, avictor.za, bn, Jean-Christophe PLAGNIOL-VILLARD, linux-arm-kernel On Tue, Sep 7, 2010 at 12:07 PM, Ryan Mallon <ryan@bluewatersys.com> wrote: > On 09/07/2010 03:54 PM, Eric Miao wrote: >> On Tue, Sep 7, 2010 at 10:44 AM, Ryan Mallon <ryan@bluewatersys.com> wrote: >>> On 09/07/2010 02:23 PM, David Brownell wrote: >>>> Still not liking or accepting this proposed >>>> change to the GPIO framework. >>>> >>>> For the AT91 case (where integers 0..N are >>>> IRQs, but N..max are GPIOs) >>>> >>>> A simpler solution is just to use a bit in >>>> the integer to indicate IRQ vs GPIO. Like >>>> maybe the sign bit.. which is never set on >>>> valid GPIO numbers, but platforms could let >>>> be set on IRQs. >>>> >>> How about this approach instead? >>> >> >> This doesn't solve the problem with more complicated settings, e.g. >> some GPIOs within are not valid, not just the begining ones. > > Agreed, but this does solve the immediate problem for AT91 in a simple > way. Are there boards in the kernel which have holes in the gpio layout? > > Another possible solution is to loop through all the gpio_chips to see > if the number maps to a valid gpio. The obvious downside to this > approach is that the complexity of gpio_is_valid becomes reasonably high > for something which should be a very simple test and, as you say below, > we probably just don't need that fine-grained information. > >> So the real question here is the semantics of gpio_is_valid(). I'd >> personally incline it reads as if a GPIO _number_ is valid generally, >> (e.g. like -1 is not a valid GPIO number), instead of that specific >> GPIO is valid on that specific platform. The latter can be judged >> with gpio_request(). > > Some drivers in the kernel appear to be using this behaviour to have > optional gpios, ie setting the foo_gpio = -1 in the platform data for > some driver. The documentation also suggests that this is what > gpio_is_valid is intended for. However, the documentation also says we > may want gpio_is_valid to return invalid on some other numbers. Right. So I'd really like David to make the semantics clear. My intention is to keep gpio_is_valid() as simple as checking a general range to rule out most invalid cases. And just use gpio_request() to handle the platform specific cases. > > ~Ryan > > -- > Bluewater Systems Ltd - ARM Technology Solution Centre > > Ryan Mallon 5 Amuri Park, 404 Barbadoes St > ryan@bluewatersys.com PO Box 13 889, Christchurch 8013 > http://www.bluewatersys.com New Zealand > Phone: +64 3 3779127 Freecall: Australia 1800 148 751 > Fax: +64 3 3779135 USA 1800 261 2934 > ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 4:19 ` Eric Miao @ 2010-09-07 4:26 ` Ryan Mallon 2010-09-07 18:10 ` David Brownell 0 siblings, 1 reply; 47+ messages in thread From: Ryan Mallon @ 2010-09-07 4:26 UTC (permalink / raw) To: Eric Miao Cc: David Brownell, Nicolas Ferre, linux-kernel, avictor.za, bn, Jean-Christophe PLAGNIOL-VILLARD, linux-arm-kernel On 09/07/2010 04:19 PM, Eric Miao wrote: > On Tue, Sep 7, 2010 at 12:07 PM, Ryan Mallon <ryan@bluewatersys.com> wrote: >> On 09/07/2010 03:54 PM, Eric Miao wrote: >>> On Tue, Sep 7, 2010 at 10:44 AM, Ryan Mallon <ryan@bluewatersys.com> wrote: >>>> On 09/07/2010 02:23 PM, David Brownell wrote: >>>>> Still not liking or accepting this proposed >>>>> change to the GPIO framework. >>>>> >>>>> For the AT91 case (where integers 0..N are >>>>> IRQs, but N..max are GPIOs) >>>>> >>>>> A simpler solution is just to use a bit in >>>>> the integer to indicate IRQ vs GPIO. Like >>>>> maybe the sign bit.. which is never set on >>>>> valid GPIO numbers, but platforms could let >>>>> be set on IRQs. >>>>> >>>> How about this approach instead? >>>> >>> >>> This doesn't solve the problem with more complicated settings, e.g. >>> some GPIOs within are not valid, not just the begining ones. >> >> Agreed, but this does solve the immediate problem for AT91 in a simple >> way. Are there boards in the kernel which have holes in the gpio layout? >> >> Another possible solution is to loop through all the gpio_chips to see >> if the number maps to a valid gpio. The obvious downside to this >> approach is that the complexity of gpio_is_valid becomes reasonably high >> for something which should be a very simple test and, as you say below, >> we probably just don't need that fine-grained information. >> >>> So the real question here is the semantics of gpio_is_valid(). I'd >>> personally incline it reads as if a GPIO _number_ is valid generally, >>> (e.g. like -1 is not a valid GPIO number), instead of that specific >>> GPIO is valid on that specific platform. The latter can be judged >>> with gpio_request(). >> >> Some drivers in the kernel appear to be using this behaviour to have >> optional gpios, ie setting the foo_gpio = -1 in the platform data for >> some driver. The documentation also suggests that this is what >> gpio_is_valid is intended for. However, the documentation also says we >> may want gpio_is_valid to return invalid on some other numbers. > > Right. So I'd really like David to make the semantics clear. My intention > is to keep gpio_is_valid() as simple as checking a general range to > rule out most invalid cases. And just use gpio_request() to handle the > platform specific cases. Agreed. The intent of my patch was to keep gpio_is_valid simple, but add a simple check for architectures where the base gpio is not zero. Will wait and see what David has to say. ~Ryan -- Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St ryan@bluewatersys.com PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934 ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 4:26 ` Ryan Mallon @ 2010-09-07 18:10 ` David Brownell 2010-09-07 19:13 ` avictor.za 0 siblings, 1 reply; 47+ messages in thread From: David Brownell @ 2010-09-07 18:10 UTC (permalink / raw) To: Eric Miao, Ryan Mallon Cc: Nicolas Ferre, linux-kernel, avictor.za, bn, Jean-Christophe PLAGNIOL-VILLARD, linux-arm-kernel --- On Mon, 9/6/10, Ryan Mallon <ryan@bluewatersys.com> wrote: > > The intent of my patch was to keep gpio_is_valid > simple, but add > a simple check for architectures where the base gpio is not > zero. Will > wait and see what David has to say. NAK still. You're trying to abuse gpio_is_valid(), which I see no need to support. In terms of GPIO framework architecture, zero is the first GPIO in all cases, and is always a valid GPIO number, even if it's not requestable/swritable/readable on a given board. Whether it's usable on a given platform depends on whether a GPIO controller is registered which claims numbers 0..N ... (assuming gpiolib in use). ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 18:10 ` David Brownell @ 2010-09-07 19:13 ` avictor.za 2010-09-07 19:30 ` Ryan Mallon 0 siblings, 1 reply; 47+ messages in thread From: avictor.za @ 2010-09-07 19:13 UTC (permalink / raw) To: David Brownell Cc: Eric Miao, Ryan Mallon, Nicolas Ferre, linux-kernel, bn, Jean-Christophe PLAGNIOL-VILLARD, linux-arm-kernel hi, > NAK still. You're trying to abuse gpio_is_valid(), > which I see no need to support. > > In terms of GPIO framework architecture, zero is > the first GPIO in all cases, and is always > a valid GPIO number, even if it's not > requestable/swritable/readable on a given board. > > Whether it's usable on a given platform depends > on whether a GPIO controller is registered which > claims numbers 0..N ... (assuming gpiolib in use). How should the following be done in a driver then? if (gpio_is_valid(device->output_pin)) { if (gpio_request(device->output_pin, "driverX") != 0) goto error_handling; /* continue with gpio setup */ } else { /* there is no vcc_pin, so don't do any gpio setup */ } .... if (gpio_is_valid(device->output_pin)) { /* set value high */ } Regards, Andrew Victor ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 19:13 ` avictor.za @ 2010-09-07 19:30 ` Ryan Mallon 2010-09-07 21:22 ` Alan Cox 0 siblings, 1 reply; 47+ messages in thread From: Ryan Mallon @ 2010-09-07 19:30 UTC (permalink / raw) To: avictor.za@gmail.com Cc: David Brownell, Eric Miao, Nicolas Ferre, linux-kernel, bn, Jean-Christophe PLAGNIOL-VILLARD, linux-arm-kernel avictor.za@gmail.com wrote: > hi, > >> NAK still. You're trying to abuse gpio_is_valid(), >> which I see no need to support. >> >> In terms of GPIO framework architecture, zero is >> the first GPIO in all cases, and is always >> a valid GPIO number, even if it's not >> requestable/swritable/readable on a given board. >> >> Whether it's usable on a given platform depends >> on whether a GPIO controller is registered which >> claims numbers 0..N ... (assuming gpiolib in use). > > How should the following be done in a driver then? > > if (gpio_is_valid(device->output_pin)) { > if (gpio_request(device->output_pin, "driverX") != 0) > goto error_handling; > > /* continue with gpio setup */ > } > else { > /* there is no vcc_pin, so don't do any gpio setup */ Adding: device->output_pin = -EINVAL; Will force the gpio to be invalid here, so that subsequent uses of gpio_is_valid will behave as expected in the case where device->output_pin >= 0, but doesn't map to a useable gpio. > } > > .... > > if (gpio_is_valid(device->output_pin)) { > /* set value high */ > } ~Ryan ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 19:30 ` Ryan Mallon @ 2010-09-07 21:22 ` Alan Cox 2010-09-07 23:44 ` David Brownell 0 siblings, 1 reply; 47+ messages in thread From: Alan Cox @ 2010-09-07 21:22 UTC (permalink / raw) To: Ryan Mallon Cc: avictor.za@gmail.com, David Brownell, Eric Miao, Nicolas Ferre, linux-kernel, bn, Jean-Christophe PLAGNIOL-VILLARD, linux-arm-kernel > Adding: > > device->output_pin = -EINVAL; gpio numbers are unsigned in the rest of the API It's unfortunate that 0 was used for a GPIO - I take it this is too late to get fixed as we had to fix IRQ numbering and the like ? ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 21:22 ` Alan Cox @ 2010-09-07 23:44 ` David Brownell 2010-09-08 0:11 ` Alan Cox 0 siblings, 1 reply; 47+ messages in thread From: David Brownell @ 2010-09-07 23:44 UTC (permalink / raw) To: Ryan Mallon, Alan Cox Cc: avictor.za@gmail.com, Eric Miao, Nicolas Ferre, linux-kernel, bn, Jean-Christophe PLAGNIOL-VILLARD, linux-arm-kernel --- On Tue, 9/7/10, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote: > > > > device->output_pin = -EINVAL; > > gpio numbers are unsigned in the rest of the API Minor goof; should have been "int" everywhere, as implied by the references to negative numbers in the docs... negatives not used internally, but preserved for external use (as above). > > It's unfortunate that 0 was used for a GPIO Intentional: board schematics and chip docs can easily match up to Linux this way. What would be unfortunate is needing to map hardware docs into software ones all the time -- error prone. When the API is used correctly, it's not an issue. ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 23:44 ` David Brownell @ 2010-09-08 0:11 ` Alan Cox 0 siblings, 0 replies; 47+ messages in thread From: Alan Cox @ 2010-09-08 0:11 UTC (permalink / raw) To: David Brownell Cc: Ryan Mallon, avictor.za@gmail.com, Eric Miao, Nicolas Ferre, linux-kernel, bn, Jean-Christophe PLAGNIOL-VILLARD, linux-arm-kernel On Tue, 7 Sep 2010 16:44:55 -0700 (PDT) David Brownell <david-b@pacbell.net> wrote: > > > --- On Tue, 9/7/10, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote: > > > > > > device->output_pin = -EINVAL; > > > > gpio numbers are unsigned in the rest of the API > > Minor goof; should have been "int" everywhere, > as implied by the references to negative numbers > in the docs... negatives not used internally, but > preserved for external use (as above). Ok I need to patch a couple of the intel drivers to use -1 then. Alan ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 2:44 ` Ryan Mallon 2010-09-07 3:54 ` Eric Miao @ 2010-09-07 6:33 ` David Brownell 2010-09-07 8:41 ` Ben Nizette 1 sibling, 1 reply; 47+ messages in thread From: David Brownell @ 2010-09-07 6:33 UTC (permalink / raw) To: Ryan Mallon Cc: Nicolas Ferre, Jean-Christophe PLAGNIOL-VILLARD, linux-kernel, linux-arm-kernel, bn, avictor.za --- On Mon, 9/6/10, Ryan Mallon <ryan@bluewatersys.com> wrote: > How about this approach instead? Still don't like it, sorry. gpio_is_valid() is not intended as a fine-grained call, there is a call which is fine grained; use that instead. > ---- > On some architectures gpio numbering does not start from zero. But on all of them, zero is a valid GPIO number. It could get dynamically allocated someday... Allow for > correct behaviour of gpio_is_valid I'd say it's already correct ... what's not correct is expecting to validate the *active* set of GPIOs (some dynamically allocated) through that, instead of one of the GPIO setup calls like gpio_request, which have explicit guarantees of reporting errors for GPIO numbers which are not usable on the target board. on values below the > first gpio by > adding the architecture overrideable ARCH_FIRST_GPIO. What are you (?) doing that it even matters to a driver which GPIOs are built into the SOC versus external? Caring about arch-specific stuff at this level is a big thought-bug... And I'd ask why you're ignoring or bypassing the error reporting from gpio_request() ... That is, just what are you doing that makes you want gpio_is_valid() to include error checks you are supposed to get via gpio_request as part of GPIO configuration? ^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 6:33 ` David Brownell @ 2010-09-07 8:41 ` Ben Nizette 2010-09-07 17:32 ` David Brownell 0 siblings, 1 reply; 47+ messages in thread From: Ben Nizette @ 2010-09-07 8:41 UTC (permalink / raw) To: David Brownell Cc: Ryan Mallon, Nicolas Ferre, Jean-Christophe PLAGNIOL-VILLARD, linux-kernel, linux-arm-kernel, avictor.za On 07/09/2010, at 4:33 PM, David Brownell wrote: > > > --- On Mon, 9/6/10, Ryan Mallon <ryan@bluewatersys.com> wrote: > > >> How about this approach instead? > > Still don't like it, sorry. gpio_is_valid() > is not intended as a fine-grained call, there is > a call which is fine grained; use that instead. > I've been sitting on the sidelines but it seems like the below might help :-) ---8K--- A recent discussion on LKML [1] highlighted some confusion regarding the semantics of the gpio validity checks versus the gpio request mechanism. gpio_is_valid determines whether a gpio /can/ be attached to a controller, gpio_request determines whether that gpio currently /is/ attached to a controller. Part of the confusion seems to come at least in part from the overlooking of facility for dynamically added gpio numbers. Fix the documentation to clarify these points. [1] http://lkml.org/lkml/2010/8/23/187 Signed-off-by: Ben Nizette <bn@niasdigital.com> --- diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt index d96a6db..adc0db2 100644 --- a/Documentation/gpio.txt +++ b/Documentation/gpio.txt @@ -113,12 +113,13 @@ test if a number could reference a GPIO, you may use this predicate: int gpio_is_valid(int number); -A number that's not valid will be rejected by calls which may request -or free GPIOs (see below). Other numbers may also be rejected; for -example, a number might be valid but unused on a given board. +This will return true for any number which may represent a valid gpio +regardless of whether or not that identifier is currently active. To +determine whether an identifier is linked to a controller and therefore +able to be used the request/free mechanism should be used (see below). -Whether a platform supports multiple GPIO controllers is currently a -platform-specific implementation issue. +Whether a platform supports multiple and/or dynamically added GPIO +controllers is currently a platform-specific implementation issue. Using GPIOs ^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH] pio: add arch specific gpio_is_valid() function 2010-09-07 8:41 ` Ben Nizette @ 2010-09-07 17:32 ` David Brownell 0 siblings, 0 replies; 47+ messages in thread From: David Brownell @ 2010-09-07 17:32 UTC (permalink / raw) To: Ben Nizette Cc: Ryan Mallon, Nicolas Ferre, Jean-Christophe PLAGNIOL-VILLARD, linux-kernel, linux-arm-kernel, avictor.za > gpio_is_valid determines whether a gpio /can/ be attached to acontroller, Or more simply: whether its numeric prameter is a valid argument to gpio_request() and friends. gpio_request determines whether that gpio > currently /is/ > attached to a controller. Of course, "controller" is out of sight of folk just using GPIOs. Otherwise, that's a fair take on one set of gpio_request() error reports. Part of the confusion seems > to come at least > in part from the overlooking of facility for dynamically added gpio numbers. Maybe, but I think most of it came from folk who expected "valid" to mean (your terminology) the GPIO number is now connected to a controller. (Otherwise $SUBJECT would be meaningless since there'd be no arch-specific issue. > > Fix the documentation to clarify these points. Patch is forthcoming. ^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH 2/2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver 2009-09-17 16:29 [PATCH 0/2] mmc: atmel-mci: introduce MCI2 support on at91 Nicolas Ferre 2009-09-17 16:29 ` [PATCH 1/2] atmel-mci: change use of dma slave interface Nicolas Ferre @ 2009-09-17 16:29 ` Nicolas Ferre 1 sibling, 0 replies; 47+ messages in thread From: Nicolas Ferre @ 2009-09-17 16:29 UTC (permalink / raw) To: linux-mmc; +Cc: linux-kernel, haavard.skinnemoen, kernel, Nicolas Ferre This new revision of the IP adds some improvements to the MCI already present in several Atmel SOC. Some new registers are added and a particular way of handling DMA interaction lead to a new sequence in function call which is backward compatible: On MCI2, we must set the DMAEN bit to enable the DMA handshaking interface. This must happen before the data transfer command is sent. A new function is able to differentiate MCI2 code and is based on knowledge of processor id (cpu_is_xxx()). Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> --- drivers/mmc/host/atmel-mci.c | 85 +++++++++++++++++++++++++++++++++++++----- 1 files changed, 75 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 1689396..d9a1a8e 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -92,6 +92,7 @@ struct atmel_mci_dma { * @need_clock_update: Update the clock rate before the next request. * @need_reset: Reset controller before next request. * @mode_reg: Value of the MR register. + * @cfg_reg: Value of the CFG register. * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus * rate and timeout calculations. * @mapbase: Physical address of the MMIO registers. @@ -155,6 +156,7 @@ struct atmel_mci { bool need_clock_update; bool need_reset; u32 mode_reg; + u32 cfg_reg; unsigned long bus_hz; unsigned long mapbase; struct clk *mck; @@ -223,6 +225,19 @@ static bool mci_has_rwproof(void) } /* + * The new MCI2 module isn't 100% compatible with the old MCI module, + * and it has a few nice features which we want to use... + */ +static inline bool atmci_is_mci2(void) +{ + if (cpu_is_at91sam9g45()) + return true; + + return false; +} + + +/* * The debugfs stuff below is mostly optimized away when * CONFIG_DEBUG_FS is not set. */ @@ -357,12 +372,33 @@ static int atmci_regs_show(struct seq_file *s, void *v) buf[MCI_BLKR / 4], buf[MCI_BLKR / 4] & 0xffff, (buf[MCI_BLKR / 4] >> 16) & 0xffff); + if (atmci_is_mci2()) + seq_printf(s, "CSTOR:\t0x%08x\n", buf[MCI_CSTOR / 4]); /* Don't read RSPR and RDR; it will consume the data there */ atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]); atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]); + if (atmci_is_mci2()) { + u32 val; + + val = buf[MCI_DMA / 4]; + seq_printf(s, "DMA:\t0x%08x OFFSET=%u CHKSIZE=%u%s\n", + val, val & 3, + ((val >> 4) & 3) ? + 1 << (((val >> 4) & 3) + 1) : 1, + val & MCI_DMAEN ? " DMAEN" : ""); + + val = buf[MCI_CFG / 4]; + seq_printf(s, "CFG:\t0x%08x%s%s%s%s\n", + val, + val & MCI_CFG_FIFOMODE_1DATA ? " FIFOMODE_ONE_DATA" : "", + val & MCI_CFG_FERRCTRL_COR ? " FERRCTRL_CLEAR_ON_READ" : "", + val & MCI_CFG_HSMODE ? " HSMODE" : "", + val & MCI_CFG_LSYNC ? " LSYNC" : ""); + } + kfree(buf); return 0; @@ -557,6 +593,10 @@ static void atmci_dma_complete(void *arg) dev_vdbg(&host->pdev->dev, "DMA complete\n"); + if (atmci_is_mci2()) + /* Disable DMA hardware handshaking on MCI */ + mci_writel(host, DMA, mci_readl(host, DMA) & ~MCI_DMAEN); + atmci_dma_cleanup(host); /* @@ -592,7 +632,7 @@ static void atmci_dma_complete(void *arg) } static int -atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) +atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) { struct dma_chan *chan; struct dma_async_tx_descriptor *desc; @@ -623,6 +663,9 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) if (!chan) return -ENODEV; + if (atmci_is_mci2()) + mci_writel(host, DMA, MCI_DMA_CHKSIZE(3) | MCI_DMAEN); + if (data->flags & MMC_DATA_READ) direction = DMA_FROM_DEVICE; else @@ -637,21 +680,30 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) host->dma.data_desc = desc; desc->callback = atmci_dma_complete; desc->callback_param = host; - desc->tx_submit(desc); - - /* Go! */ - chan->device->device_issue_pending(chan); return 0; } +static void atmci_submit_data(struct atmel_mci *host) +{ + struct dma_chan *chan = host->data_chan; + struct dma_async_tx_descriptor *desc = host->dma.data_desc; + + if (chan) { + desc->tx_submit(desc); + chan->device->device_issue_pending(chan); + } +} + #else /* CONFIG_MMC_ATMELMCI_DMA */ -static int atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) +static int atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) { return -ENOSYS; } +static void atmci_submit_data(struct atmel_mci *host) {} + static void atmci_stop_dma(struct atmel_mci *host) { /* Data transfer was stopped by the interrupt handler */ @@ -665,7 +717,7 @@ static void atmci_stop_dma(struct atmel_mci *host) * Returns a mask of interrupt flags to be enabled after the whole * request has been prepared. */ -static u32 atmci_submit_data(struct atmel_mci *host, struct mmc_data *data) +static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data) { u32 iflags; @@ -676,7 +728,7 @@ static u32 atmci_submit_data(struct atmel_mci *host, struct mmc_data *data) host->data = data; iflags = ATMCI_DATA_ERROR_FLAGS; - if (atmci_submit_data_dma(host, data)) { + if (atmci_prepare_data_dma(host, data)) { host->data_chan = NULL; /* @@ -722,6 +774,8 @@ static void atmci_start_request(struct atmel_mci *host, mci_writel(host, CR, MCI_CR_SWRST); mci_writel(host, CR, MCI_CR_MCIEN); mci_writel(host, MR, host->mode_reg); + if (atmci_is_mci2()) + mci_writel(host, CFG, host->cfg_reg); host->need_reset = false; } mci_writel(host, SDCR, slot->sdc_reg); @@ -737,6 +791,7 @@ static void atmci_start_request(struct atmel_mci *host, while (!(mci_readl(host, SR) & MCI_CMDRDY)) cpu_relax(); } + iflags = 0; data = mrq->data; if (data) { atmci_set_timeout(host, slot, data); @@ -746,15 +801,17 @@ static void atmci_start_request(struct atmel_mci *host, | MCI_BLKLEN(data->blksz)); dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n", MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz)); + + iflags |= atmci_prepare_data(host, data); } - iflags = MCI_CMDRDY; + iflags |= MCI_CMDRDY; cmd = mrq->cmd; cmdflags = atmci_prepare_command(slot->mmc, cmd); atmci_start_command(host, cmd, cmdflags); if (data) - iflags |= atmci_submit_data(host, data); + atmci_submit_data(host); if (mrq->stop) { host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); @@ -850,6 +907,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) clk_enable(host->mck); mci_writel(host, CR, MCI_CR_SWRST); mci_writel(host, CR, MCI_CR_MCIEN); + if (atmci_is_mci2()) + mci_writel(host, CFG, host->cfg_reg); } /* @@ -1088,6 +1147,8 @@ static void atmci_detect_change(unsigned long data) mci_writel(host, CR, MCI_CR_SWRST); mci_writel(host, CR, MCI_CR_MCIEN); mci_writel(host, MR, host->mode_reg); + if (atmci_is_mci2()) + mci_writel(host, CFG, host->cfg_reg); host->data = NULL; host->cmd = NULL; @@ -1637,6 +1698,10 @@ static void atmci_configure_dma(struct atmel_mci *host) } if (!host->dma.chan) dev_notice(&host->pdev->dev, "DMA not available, using PIO\n"); + else + dev_info(&host->pdev->dev, + "Using %s for DMA transfers\n", + dma_chan_name(host->dma.chan)); } #else static void atmci_configure_dma(struct atmel_mci *host) {} -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 47+ messages in thread
end of thread, other threads:[~2010-09-07 23:52 UTC | newest] Thread overview: 47+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-09-17 16:29 [PATCH 0/2] mmc: atmel-mci: introduce MCI2 support on at91 Nicolas Ferre 2009-09-17 16:29 ` [PATCH 1/2] atmel-mci: change use of dma slave interface Nicolas Ferre 2009-09-29 19:29 ` Andrew Morton 2009-09-30 13:33 ` Nicolas Ferre 2009-09-30 13:55 ` Haavard Skinnemoen 2009-10-23 16:34 ` [PATCH 0/2 v2]mmc: atmel-mci: introduce MCI2 support on at91 Nicolas Ferre 2009-10-23 16:34 ` [PATCH 1/3 v2] atmel-mci: change use of dma slave interface Nicolas Ferre 2009-10-23 16:34 ` [PATCH 2/3 v2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver Nicolas Ferre 2009-11-02 17:18 ` Nicolas Ferre 2009-11-18 13:33 ` Nicolas Ferre 2009-10-23 16:34 ` [PATCH 3/3 v2] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board Nicolas Ferre 2009-10-26 8:15 ` Yegor Yefremov 2009-11-02 17:14 ` Nicolas Ferre 2009-10-27 19:43 ` Andrew Victor 2009-10-28 0:35 ` Haavard Skinnemoen 2009-10-28 0:53 ` Thiago A. Corrêa 2009-10-28 1:31 ` Haavard Skinnemoen 2009-10-28 19:53 ` Andrew Victor 2009-10-28 20:50 ` Ben Nizette 2009-11-02 17:11 ` Nicolas Ferre 2009-11-02 22:10 ` Ben Nizette 2009-11-02 22:14 ` Ben Nizette 2009-11-03 2:30 ` Ryan Mallon 2009-11-03 2:55 ` Ben Nizette 2009-11-07 11:20 ` Haavard Skinnemoen 2010-08-23 15:01 ` [PATCH] pio: add arch specific gpio_is_valid() function Nicolas Ferre 2010-08-23 16:36 ` David Brownell 2010-08-24 8:19 ` Nicolas Ferre 2010-09-06 14:21 ` [PATCH v2] AT91: pio: add " Nicolas Ferre 2010-09-07 1:51 ` David Brownell 2010-09-03 16:41 ` [PATCH] pio: add arch specific " Jean-Christophe PLAGNIOL-VILLARD 2010-09-07 2:23 ` David Brownell 2010-09-07 2:44 ` Ryan Mallon 2010-09-07 3:54 ` Eric Miao 2010-09-07 4:07 ` Ryan Mallon 2010-09-07 4:19 ` Eric Miao 2010-09-07 4:26 ` Ryan Mallon 2010-09-07 18:10 ` David Brownell 2010-09-07 19:13 ` avictor.za 2010-09-07 19:30 ` Ryan Mallon 2010-09-07 21:22 ` Alan Cox 2010-09-07 23:44 ` David Brownell 2010-09-08 0:11 ` Alan Cox 2010-09-07 6:33 ` David Brownell 2010-09-07 8:41 ` Ben Nizette 2010-09-07 17:32 ` David Brownell 2009-09-17 16:29 ` [PATCH 2/2] mmc: atmel-mci: New MCI2 module support in atmel-mci driver Nicolas Ferre
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox