* [PATCH 0/5] mmc: Add OMAP SDHCI driver @ 2017-08-21 7:41 Kishon Vijay Abraham I 2017-08-21 7:41 ` [PATCH 1/5] mmc: sdhci: Tidy reading 136-bit responses Kishon Vijay Abraham I ` (4 more replies) 0 siblings, 5 replies; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-21 7:41 UTC (permalink / raw) To: Ulf Hansson, Adrian Hunter Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel, Kishon Vijay Abraham I This is the first step in deprecating omap_hsmmc driver completely and moving to sdhci-omap driver which uses the sdhci library. This series adds a new SDHCI quirk to indicate MMC_RSP_136 has CRC (since sdhci in OMAP has CRC) Apart from the quirk, sdhci-omap has it's own callbacks to set_clock (clock divider programming is different from generic sdhci) , set_power, set_bus_width, set_bus_mode and platform_send_init_74_clocks. These callback functions are implemented based on omap_hsmmc driver. The sdhci-omap driver supports only the high speed mode and UHS/HS200 mode will be added in a later series. It has been tested only in boards having DRA7 SoCs like dra7-evm, dra72-evm, am571x-idk, am572x-idk, am57xx-evm. (Tested only eMMC and SD. SDIO support will be added later). The plan is to fully convert DRA7 SoC to use SDHCI driver and then convert other legacy platforms to use SDHCI. Next Steps: *) Add UHS support to sdhci-omap *) Add SDIO support *) Add support for older TI platforms Changes from v1: *) Remove the quirks and instead use sdhci_omap specific callbacks for set_power, set_busmode etc. *) Add a patch from Adrian to tidy reading 136-bit responses I've also pushed the entire series along with dependent dt patches @ https://github.com/kishon/linux-wip.git sdhci_omap_v1 (in case someone wants to test) Adrian Hunter (1): mmc: sdhci: Tidy reading 136-bit responses Kishon Vijay Abraham I (4): mmc: sdhci: Add quirk to indicate MMC_RSP_136 has CRC dt-bindings: ti-omap-hsmmc: Document new compatible for sdhci omap mmc: sdhci-omap: Add OMAP SDHCI driver MAINTAINERS: Add TI OMAP SDHCI Maintainer .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 + MAINTAINERS | 6 + drivers/mmc/host/Kconfig | 12 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/sdhci-omap.c | 629 +++++++++++++++++++++ drivers/mmc/host/sdhci.c | 31 +- drivers/mmc/host/sdhci.h | 2 + 7 files changed, 672 insertions(+), 10 deletions(-) create mode 100644 drivers/mmc/host/sdhci-omap.c -- 2.11.0 ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 1/5] mmc: sdhci: Tidy reading 136-bit responses 2017-08-21 7:41 [PATCH 0/5] mmc: Add OMAP SDHCI driver Kishon Vijay Abraham I @ 2017-08-21 7:41 ` Kishon Vijay Abraham I 2017-08-30 13:13 ` Ulf Hansson 2017-08-21 7:41 ` [PATCH 2/5] mmc: sdhci: Add quirk to indicate MMC_RSP_136 has CRC Kishon Vijay Abraham I ` (3 subsequent siblings) 4 siblings, 1 reply; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-21 7:41 UTC (permalink / raw) To: Ulf Hansson, Adrian Hunter Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel, Kishon Vijay Abraham I From: Adrian Hunter <adrian.hunter@intel.com> Read each register only once and move the code to a separate function so that it is not jammed against the 80 column margin. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> --- drivers/mmc/host/sdhci.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index a1ad2ddadca1..ba639b7851cb 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1173,24 +1173,32 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) } EXPORT_SYMBOL_GPL(sdhci_send_command); +static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) +{ + int i, reg; + + for (i = 0; i < 4; i++) { + reg = SDHCI_RESPONSE + (3 - i) * 4; + cmd->resp[i] = sdhci_readl(host, reg); + } + + /* CRC is stripped so we need to do some shifting */ + for (i = 0; i < 4; i++) { + cmd->resp[i] <<= 8; + if (i != 3) + cmd->resp[i] |= cmd->resp[i + 1] >> 24; + } +} + static void sdhci_finish_command(struct sdhci_host *host) { struct mmc_command *cmd = host->cmd; - int i; host->cmd = NULL; if (cmd->flags & MMC_RSP_PRESENT) { if (cmd->flags & MMC_RSP_136) { - /* CRC is stripped so we need to do some shifting. */ - for (i = 0;i < 4;i++) { - cmd->resp[i] = sdhci_readl(host, - SDHCI_RESPONSE + (3-i)*4) << 8; - if (i != 3) - cmd->resp[i] |= - sdhci_readb(host, - SDHCI_RESPONSE + (3-i)*4-1); - } + sdhci_read_rsp_136(host, cmd); } else { cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); } -- 2.11.0 ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 1/5] mmc: sdhci: Tidy reading 136-bit responses 2017-08-21 7:41 ` [PATCH 1/5] mmc: sdhci: Tidy reading 136-bit responses Kishon Vijay Abraham I @ 2017-08-30 13:13 ` Ulf Hansson 0 siblings, 0 replies; 31+ messages in thread From: Ulf Hansson @ 2017-08-30 13:13 UTC (permalink / raw) To: Kishon Vijay Abraham I Cc: Adrian Hunter, Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel On 21 August 2017 at 09:41, Kishon Vijay Abraham I <kishon@ti.com> wrote: > From: Adrian Hunter <adrian.hunter@intel.com> > > Read each register only once and move the code to a separate function so > that it is not jammed against the 80 column margin. > > Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Thanks, applied for next! Kind regards Uffe > --- > drivers/mmc/host/sdhci.c | 28 ++++++++++++++++++---------- > 1 file changed, 18 insertions(+), 10 deletions(-) > > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > index a1ad2ddadca1..ba639b7851cb 100644 > --- a/drivers/mmc/host/sdhci.c > +++ b/drivers/mmc/host/sdhci.c > @@ -1173,24 +1173,32 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) > } > EXPORT_SYMBOL_GPL(sdhci_send_command); > > +static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) > +{ > + int i, reg; > + > + for (i = 0; i < 4; i++) { > + reg = SDHCI_RESPONSE + (3 - i) * 4; > + cmd->resp[i] = sdhci_readl(host, reg); > + } > + > + /* CRC is stripped so we need to do some shifting */ > + for (i = 0; i < 4; i++) { > + cmd->resp[i] <<= 8; > + if (i != 3) > + cmd->resp[i] |= cmd->resp[i + 1] >> 24; > + } > +} > + > static void sdhci_finish_command(struct sdhci_host *host) > { > struct mmc_command *cmd = host->cmd; > - int i; > > host->cmd = NULL; > > if (cmd->flags & MMC_RSP_PRESENT) { > if (cmd->flags & MMC_RSP_136) { > - /* CRC is stripped so we need to do some shifting. */ > - for (i = 0;i < 4;i++) { > - cmd->resp[i] = sdhci_readl(host, > - SDHCI_RESPONSE + (3-i)*4) << 8; > - if (i != 3) > - cmd->resp[i] |= > - sdhci_readb(host, > - SDHCI_RESPONSE + (3-i)*4-1); > - } > + sdhci_read_rsp_136(host, cmd); > } else { > cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); > } > -- > 2.11.0 > ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 2/5] mmc: sdhci: Add quirk to indicate MMC_RSP_136 has CRC 2017-08-21 7:41 [PATCH 0/5] mmc: Add OMAP SDHCI driver Kishon Vijay Abraham I 2017-08-21 7:41 ` [PATCH 1/5] mmc: sdhci: Tidy reading 136-bit responses Kishon Vijay Abraham I @ 2017-08-21 7:41 ` Kishon Vijay Abraham I 2017-08-28 7:57 ` Adrian Hunter 2017-08-30 13:13 ` Ulf Hansson 2017-08-21 7:41 ` [PATCH 3/5] dt-bindings: ti-omap-hsmmc: Document new compatible for sdhci omap Kishon Vijay Abraham I ` (2 subsequent siblings) 4 siblings, 2 replies; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-21 7:41 UTC (permalink / raw) To: Ulf Hansson, Adrian Hunter Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel, Kishon Vijay Abraham I TI's implementation of sdhci controller used in DRA7 SoC's has CRC in responses with length 136 bits. Add quirk to indicate the controller has CRC in MMC_RSP_136. If this quirk is set sdhci library shouldn't shift the response present in SDHCI_RESPONSE register. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> --- drivers/mmc/host/sdhci.c | 3 +++ drivers/mmc/host/sdhci.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ba639b7851cb..9c8d7428df3c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1182,6 +1182,9 @@ static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) cmd->resp[i] = sdhci_readl(host, reg); } + if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC) + return; + /* CRC is stripped so we need to do some shifting */ for (i = 0; i < 4; i++) { cmd->resp[i] <<= 8; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 399edc681623..54bc444c317f 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -435,6 +435,8 @@ struct sdhci_host { #define SDHCI_QUIRK2_ACMD23_BROKEN (1<<14) /* Broken Clock divider zero in controller */ #define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN (1<<15) +/* Controller has CRC in 136 bit Command Response */ +#define SDHCI_QUIRK2_RSP_136_HAS_CRC (1<<16) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ -- 2.11.0 ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 2/5] mmc: sdhci: Add quirk to indicate MMC_RSP_136 has CRC 2017-08-21 7:41 ` [PATCH 2/5] mmc: sdhci: Add quirk to indicate MMC_RSP_136 has CRC Kishon Vijay Abraham I @ 2017-08-28 7:57 ` Adrian Hunter 2017-08-30 13:13 ` Ulf Hansson 1 sibling, 0 replies; 31+ messages in thread From: Adrian Hunter @ 2017-08-28 7:57 UTC (permalink / raw) To: Kishon Vijay Abraham I, Ulf Hansson Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel On 21/08/17 10:41, Kishon Vijay Abraham I wrote: > TI's implementation of sdhci controller used in DRA7 SoC's has > CRC in responses with length 136 bits. Add quirk to indicate > the controller has CRC in MMC_RSP_136. If this quirk is > set sdhci library shouldn't shift the response present in > SDHCI_RESPONSE register. > > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> > --- > drivers/mmc/host/sdhci.c | 3 +++ > drivers/mmc/host/sdhci.h | 2 ++ > 2 files changed, 5 insertions(+) > > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > index ba639b7851cb..9c8d7428df3c 100644 > --- a/drivers/mmc/host/sdhci.c > +++ b/drivers/mmc/host/sdhci.c > @@ -1182,6 +1182,9 @@ static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) > cmd->resp[i] = sdhci_readl(host, reg); > } > > + if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC) > + return; > + > /* CRC is stripped so we need to do some shifting */ > for (i = 0; i < 4; i++) { > cmd->resp[i] <<= 8; > diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h > index 399edc681623..54bc444c317f 100644 > --- a/drivers/mmc/host/sdhci.h > +++ b/drivers/mmc/host/sdhci.h > @@ -435,6 +435,8 @@ struct sdhci_host { > #define SDHCI_QUIRK2_ACMD23_BROKEN (1<<14) > /* Broken Clock divider zero in controller */ > #define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN (1<<15) > +/* Controller has CRC in 136 bit Command Response */ > +#define SDHCI_QUIRK2_RSP_136_HAS_CRC (1<<16) > > int irq; /* Device IRQ */ > void __iomem *ioaddr; /* Mapped address */ > ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 2/5] mmc: sdhci: Add quirk to indicate MMC_RSP_136 has CRC 2017-08-21 7:41 ` [PATCH 2/5] mmc: sdhci: Add quirk to indicate MMC_RSP_136 has CRC Kishon Vijay Abraham I 2017-08-28 7:57 ` Adrian Hunter @ 2017-08-30 13:13 ` Ulf Hansson 1 sibling, 0 replies; 31+ messages in thread From: Ulf Hansson @ 2017-08-30 13:13 UTC (permalink / raw) To: Kishon Vijay Abraham I Cc: Adrian Hunter, Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel On 21 August 2017 at 09:41, Kishon Vijay Abraham I <kishon@ti.com> wrote: > TI's implementation of sdhci controller used in DRA7 SoC's has > CRC in responses with length 136 bits. Add quirk to indicate > the controller has CRC in MMC_RSP_136. If this quirk is > set sdhci library shouldn't shift the response present in > SDHCI_RESPONSE register. > > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Thanks, applied for next! Kind regards Uffe > --- > drivers/mmc/host/sdhci.c | 3 +++ > drivers/mmc/host/sdhci.h | 2 ++ > 2 files changed, 5 insertions(+) > > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > index ba639b7851cb..9c8d7428df3c 100644 > --- a/drivers/mmc/host/sdhci.c > +++ b/drivers/mmc/host/sdhci.c > @@ -1182,6 +1182,9 @@ static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) > cmd->resp[i] = sdhci_readl(host, reg); > } > > + if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC) > + return; > + > /* CRC is stripped so we need to do some shifting */ > for (i = 0; i < 4; i++) { > cmd->resp[i] <<= 8; > diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h > index 399edc681623..54bc444c317f 100644 > --- a/drivers/mmc/host/sdhci.h > +++ b/drivers/mmc/host/sdhci.h > @@ -435,6 +435,8 @@ struct sdhci_host { > #define SDHCI_QUIRK2_ACMD23_BROKEN (1<<14) > /* Broken Clock divider zero in controller */ > #define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN (1<<15) > +/* Controller has CRC in 136 bit Command Response */ > +#define SDHCI_QUIRK2_RSP_136_HAS_CRC (1<<16) > > int irq; /* Device IRQ */ > void __iomem *ioaddr; /* Mapped address */ > -- > 2.11.0 > ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 3/5] dt-bindings: ti-omap-hsmmc: Document new compatible for sdhci omap 2017-08-21 7:41 [PATCH 0/5] mmc: Add OMAP SDHCI driver Kishon Vijay Abraham I 2017-08-21 7:41 ` [PATCH 1/5] mmc: sdhci: Tidy reading 136-bit responses Kishon Vijay Abraham I 2017-08-21 7:41 ` [PATCH 2/5] mmc: sdhci: Add quirk to indicate MMC_RSP_136 has CRC Kishon Vijay Abraham I @ 2017-08-21 7:41 ` Kishon Vijay Abraham I 2017-08-21 14:21 ` Tony Lindgren 2017-08-21 7:41 ` [PATCH 4/5] mmc: sdhci-omap: Add OMAP SDHCI driver Kishon Vijay Abraham I 2017-08-21 7:41 ` [PATCH 5/5] MAINTAINERS: Add TI OMAP SDHCI Maintainer Kishon Vijay Abraham I 4 siblings, 1 reply; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-21 7:41 UTC (permalink / raw) To: Ulf Hansson, Adrian Hunter Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel, Kishon Vijay Abraham I Document the new compatible string "ti,dra7-sdhci" to be used for MMC controllers in DRA7 and DRA72 SoCs. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> --- Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt index 0e026c151c1c..db80fdfd05d7 100644 --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt @@ -13,6 +13,7 @@ Required properties: Should be "ti,omap3-pre-es3-hsmmc" for OMAP3 controllers pre ES3.0 Should be "ti,omap4-hsmmc", for OMAP4 controllers Should be "ti,am33xx-hsmmc", for AM335x controllers + Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers - ti,hwmods: Must be "mmc<n>", n is controller instance starting 1 Optional properties: -- 2.11.0 ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 3/5] dt-bindings: ti-omap-hsmmc: Document new compatible for sdhci omap 2017-08-21 7:41 ` [PATCH 3/5] dt-bindings: ti-omap-hsmmc: Document new compatible for sdhci omap Kishon Vijay Abraham I @ 2017-08-21 14:21 ` Tony Lindgren 2017-08-22 13:39 ` [PATCH v2 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller Kishon Vijay Abraham I 2017-08-23 5:42 ` [PATCH v3 " Kishon Vijay Abraham I 0 siblings, 2 replies; 31+ messages in thread From: Tony Lindgren @ 2017-08-21 14:21 UTC (permalink / raw) To: Kishon Vijay Abraham I Cc: Ulf Hansson, Adrian Hunter, Rob Herring, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel * Kishon Vijay Abraham I <kishon@ti.com> [170821 00:42]: > Document the new compatible string "ti,dra7-sdhci" to be used for > MMC controllers in DRA7 and DRA72 SoCs. I suggest that you add a new one sdhci-omap.txt instead. We are not currently parsing the all the hsmmc properties for sdhci. Then eventually when they are fully compatible, we can just change ti-omap-hsmmc.txt to point to the sdhci-omap.txt. Regards, Tony > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> > --- > Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt > index 0e026c151c1c..db80fdfd05d7 100644 > --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt > +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt > @@ -13,6 +13,7 @@ Required properties: > Should be "ti,omap3-pre-es3-hsmmc" for OMAP3 controllers pre ES3.0 > Should be "ti,omap4-hsmmc", for OMAP4 controllers > Should be "ti,am33xx-hsmmc", for AM335x controllers > + Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers > - ti,hwmods: Must be "mmc<n>", n is controller instance starting 1 > > Optional properties: > -- > 2.11.0 > ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v2 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-21 14:21 ` Tony Lindgren @ 2017-08-22 13:39 ` Kishon Vijay Abraham I 2017-08-22 17:39 ` Tony Lindgren 2017-08-23 5:42 ` [PATCH v3 " Kishon Vijay Abraham I 1 sibling, 1 reply; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-22 13:39 UTC (permalink / raw) To: Ulf Hansson, Adrian Hunter, Rob Herring, Tony Lindgren Cc: Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel, Kishon Vijay Abraham I Add binding for the TI's sdhci-omap controller. This now includes only a subset of properties documented in ti-omap-hsmmc.txt but will eventually include all the properties. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> --- Changes from v1: *) Create a new sdhci-omap.txt document for TI's sdhci-omap controller instead of using the ti-omap-hsmmc.txt as suggested by Tony .../devicetree/bindings/mmc/sdhci-omap.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-omap.txt diff --git a/Documentation/devicetree/bindings/mmc/sdhci-omap.txt b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt new file mode 100644 index 000000000000..139695ad2d58 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt @@ -0,0 +1,22 @@ +* TI OMAP SDHCI Controller + +Refer to mmc.txt for standard MMC bindings. + +Required properties: +- compatible: Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers +- ti,hwmods: Must be "mmc<n>", <n> is controller instance starting 1 + +Optional properties: +- ti,dual-volt: boolean, supports dual voltage cards +- ti,non-removable: non-removable slot (like eMMC) + +Example: + mmc1: mmc@0x4809c000 { + compatible = "ti,omap4-hsmmc"; + reg = <0x4809c000 0x400>; + ti,hwmods = "mmc1"; + ti,dual-volt; + bus-width = <4>; + vmmc-supply = <&vmmc>; /* phandle to regulator node */ + ti,non-removable; + }; -- 2.11.0 ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v2 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-22 13:39 ` [PATCH v2 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller Kishon Vijay Abraham I @ 2017-08-22 17:39 ` Tony Lindgren 0 siblings, 0 replies; 31+ messages in thread From: Tony Lindgren @ 2017-08-22 17:39 UTC (permalink / raw) To: Kishon Vijay Abraham I Cc: Ulf Hansson, Adrian Hunter, Rob Herring, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel * Kishon Vijay Abraham I <kishon@ti.com> [170822 06:39]: > Add binding for the TI's sdhci-omap controller. This now includes only > a subset of properties documented in ti-omap-hsmmc.txt but will eventually > include all the properties. > > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> > --- > Changes from v1: > *) Create a new sdhci-omap.txt document for TI's sdhci-omap controller instead > of using the ti-omap-hsmmc.txt as suggested by Tony Works for me thanks, just one typo below.. > .../devicetree/bindings/mmc/sdhci-omap.txt | 22 ++++++++++++++++++++++ > 1 file changed, 22 insertions(+) > create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-omap.txt > > diff --git a/Documentation/devicetree/bindings/mmc/sdhci-omap.txt b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt > new file mode 100644 > index 000000000000..139695ad2d58 > --- /dev/null > +++ b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt > @@ -0,0 +1,22 @@ > +* TI OMAP SDHCI Controller > + > +Refer to mmc.txt for standard MMC bindings. > + > +Required properties: > +- compatible: Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers > +- ti,hwmods: Must be "mmc<n>", <n> is controller instance starting 1 > + > +Optional properties: > +- ti,dual-volt: boolean, supports dual voltage cards > +- ti,non-removable: non-removable slot (like eMMC) > + > +Example: > + mmc1: mmc@0x4809c000 { > + compatible = "ti,omap4-hsmmc"; The compatible in the example here is still using hsmmc :) Tony ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-21 14:21 ` Tony Lindgren 2017-08-22 13:39 ` [PATCH v2 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller Kishon Vijay Abraham I @ 2017-08-23 5:42 ` Kishon Vijay Abraham I 2017-08-23 13:07 ` Ulf Hansson 2017-08-29 17:11 ` Rob Herring 1 sibling, 2 replies; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-23 5:42 UTC (permalink / raw) To: Ulf Hansson, Adrian Hunter, Rob Herring, Tony Lindgren Cc: Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel, Kishon Vijay Abraham I Add binding for the TI's sdhci-omap controller. This now includes only a subset of properties documented in ti-omap-hsmmc.txt but will eventually include all the properties. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> --- Changes from v2: *) Fixed example to use the updated compatible Changes from v1: *) Create a new sdhci-omap.txt document for TI's sdhci-omap controller instead of using the ti-omap-hsmmc.txt as suggested by Tony .../devicetree/bindings/mmc/sdhci-omap.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-omap.txt diff --git a/Documentation/devicetree/bindings/mmc/sdhci-omap.txt b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt new file mode 100644 index 000000000000..139695ad2d58 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt @@ -0,0 +1,22 @@ +* TI OMAP SDHCI Controller + +Refer to mmc.txt for standard MMC bindings. + +Required properties: +- compatible: Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers +- ti,hwmods: Must be "mmc<n>", <n> is controller instance starting 1 + +Optional properties: +- ti,dual-volt: boolean, supports dual voltage cards +- ti,non-removable: non-removable slot (like eMMC) + +Example: + mmc1: mmc@0x4809c000 { + compatible = "ti,dra7-sdhci"; + reg = <0x4809c000 0x400>; + ti,hwmods = "mmc1"; + ti,dual-volt; + bus-width = <4>; + vmmc-supply = <&vmmc>; /* phandle to regulator node */ + ti,non-removable; + }; -- 2.11.0 ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-23 5:42 ` [PATCH v3 " Kishon Vijay Abraham I @ 2017-08-23 13:07 ` Ulf Hansson 2017-08-23 13:56 ` Kishon Vijay Abraham I 2017-08-29 17:11 ` Rob Herring 1 sibling, 1 reply; 31+ messages in thread From: Ulf Hansson @ 2017-08-23 13:07 UTC (permalink / raw) To: Kishon Vijay Abraham I Cc: Adrian Hunter, Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel On 23 August 2017 at 07:42, Kishon Vijay Abraham I <kishon@ti.com> wrote: > Add binding for the TI's sdhci-omap controller. This now includes only > a subset of properties documented in ti-omap-hsmmc.txt but will eventually > include all the properties. > > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> > --- > Changes from v2: > *) Fixed example to use the updated compatible > > Changes from v1: > *) Create a new sdhci-omap.txt document for TI's sdhci-omap controller instead > of using the ti-omap-hsmmc.txt as suggested by Tony > .../devicetree/bindings/mmc/sdhci-omap.txt | 22 ++++++++++++++++++++++ > 1 file changed, 22 insertions(+) > create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-omap.txt > > diff --git a/Documentation/devicetree/bindings/mmc/sdhci-omap.txt b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt > new file mode 100644 > index 000000000000..139695ad2d58 > --- /dev/null > +++ b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt > @@ -0,0 +1,22 @@ > +* TI OMAP SDHCI Controller > + > +Refer to mmc.txt for standard MMC bindings. > + > +Required properties: > +- compatible: Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers > +- ti,hwmods: Must be "mmc<n>", <n> is controller instance starting 1 > + > +Optional properties: > +- ti,dual-volt: boolean, supports dual voltage cards > +- ti,non-removable: non-removable slot (like eMMC) > + > +Example: > + mmc1: mmc@0x4809c000 { > + compatible = "ti,dra7-sdhci"; > + reg = <0x4809c000 0x400>; > + ti,hwmods = "mmc1"; > + ti,dual-volt; > + bus-width = <4>; > + vmmc-supply = <&vmmc>; /* phandle to regulator node */ > + ti,non-removable; > + }; > -- > 2.11.0 > I am wondering a bit on the long term plan here. Ideally at some point in future, we would like to remove the old omap_hsmmc driver, but from compatible string point of view, that means we first needs to deprecate the old ones for a while. Right? That said, what is then the reason to why we should bring over the existing omap_hsmmc bindings to the sdhci-omap bindings? For example, "ti,dual-volt" can likely be replaced with something better that already exists (either a common mmc binding or an sdhci binding). For "ti,non-removable", we already have a common mmc binding "non-removable" for this. Kind regards Uffe ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-23 13:07 ` Ulf Hansson @ 2017-08-23 13:56 ` Kishon Vijay Abraham I 2017-08-24 11:29 ` Ulf Hansson 0 siblings, 1 reply; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-23 13:56 UTC (permalink / raw) To: Ulf Hansson Cc: Adrian Hunter, Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel Hi Uffe, On Wednesday 23 August 2017 06:37 PM, Ulf Hansson wrote: > On 23 August 2017 at 07:42, Kishon Vijay Abraham I <kishon@ti.com> wrote: >> Add binding for the TI's sdhci-omap controller. This now includes only >> a subset of properties documented in ti-omap-hsmmc.txt but will eventually >> include all the properties. >> >> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> >> --- >> Changes from v2: >> *) Fixed example to use the updated compatible >> >> Changes from v1: >> *) Create a new sdhci-omap.txt document for TI's sdhci-omap controller instead >> of using the ti-omap-hsmmc.txt as suggested by Tony >> .../devicetree/bindings/mmc/sdhci-omap.txt | 22 ++++++++++++++++++++++ >> 1 file changed, 22 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-omap.txt >> >> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-omap.txt b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt >> new file mode 100644 >> index 000000000000..139695ad2d58 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt >> @@ -0,0 +1,22 @@ >> +* TI OMAP SDHCI Controller >> + >> +Refer to mmc.txt for standard MMC bindings. >> + >> +Required properties: >> +- compatible: Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers >> +- ti,hwmods: Must be "mmc<n>", <n> is controller instance starting 1 >> + >> +Optional properties: >> +- ti,dual-volt: boolean, supports dual voltage cards >> +- ti,non-removable: non-removable slot (like eMMC) >> + >> +Example: >> + mmc1: mmc@0x4809c000 { >> + compatible = "ti,dra7-sdhci"; >> + reg = <0x4809c000 0x400>; >> + ti,hwmods = "mmc1"; >> + ti,dual-volt; >> + bus-width = <4>; >> + vmmc-supply = <&vmmc>; /* phandle to regulator node */ >> + ti,non-removable; >> + }; >> -- >> 2.11.0 >> > > I am wondering a bit on the long term plan here. > > Ideally at some point in future, we would like to remove the old > omap_hsmmc driver, but from compatible string point of view, that > means we first needs to deprecate the old ones for a while. Right? right but sdhci-omap is still lacking features that was present in omap_hsmmc like context save/restore, SDIO support etc. I think we should deprecate omap_hsmmc compatible once we add all the features in sdhci-omap? > > That said, what is then the reason to why we should bring over the > existing omap_hsmmc bindings to the sdhci-omap bindings? This is mainly for old dt compatibility. Even after removing the omap_hsmmc driver, users should still be able to use newer kernel with their existing dtbs. Thanks Kishon ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-23 13:56 ` Kishon Vijay Abraham I @ 2017-08-24 11:29 ` Ulf Hansson 2017-08-29 11:20 ` Kishon Vijay Abraham I 0 siblings, 1 reply; 31+ messages in thread From: Ulf Hansson @ 2017-08-24 11:29 UTC (permalink / raw) To: Kishon Vijay Abraham I Cc: Adrian Hunter, Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel On 23 August 2017 at 15:56, Kishon Vijay Abraham I <kishon@ti.com> wrote: > Hi Uffe, > > On Wednesday 23 August 2017 06:37 PM, Ulf Hansson wrote: >> On 23 August 2017 at 07:42, Kishon Vijay Abraham I <kishon@ti.com> wrote: >>> Add binding for the TI's sdhci-omap controller. This now includes only >>> a subset of properties documented in ti-omap-hsmmc.txt but will eventually >>> include all the properties. >>> >>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> >>> --- >>> Changes from v2: >>> *) Fixed example to use the updated compatible >>> >>> Changes from v1: >>> *) Create a new sdhci-omap.txt document for TI's sdhci-omap controller instead >>> of using the ti-omap-hsmmc.txt as suggested by Tony >>> .../devicetree/bindings/mmc/sdhci-omap.txt | 22 ++++++++++++++++++++++ >>> 1 file changed, 22 insertions(+) >>> create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-omap.txt >>> >>> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-omap.txt b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt >>> new file mode 100644 >>> index 000000000000..139695ad2d58 >>> --- /dev/null >>> +++ b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt >>> @@ -0,0 +1,22 @@ >>> +* TI OMAP SDHCI Controller >>> + >>> +Refer to mmc.txt for standard MMC bindings. >>> + >>> +Required properties: >>> +- compatible: Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers >>> +- ti,hwmods: Must be "mmc<n>", <n> is controller instance starting 1 >>> + >>> +Optional properties: >>> +- ti,dual-volt: boolean, supports dual voltage cards >>> +- ti,non-removable: non-removable slot (like eMMC) >>> + >>> +Example: >>> + mmc1: mmc@0x4809c000 { >>> + compatible = "ti,dra7-sdhci"; >>> + reg = <0x4809c000 0x400>; >>> + ti,hwmods = "mmc1"; >>> + ti,dual-volt; >>> + bus-width = <4>; >>> + vmmc-supply = <&vmmc>; /* phandle to regulator node */ >>> + ti,non-removable; >>> + }; >>> -- >>> 2.11.0 >>> >> >> I am wondering a bit on the long term plan here. >> >> Ideally at some point in future, we would like to remove the old >> omap_hsmmc driver, but from compatible string point of view, that >> means we first needs to deprecate the old ones for a while. Right? > > right but sdhci-omap is still lacking features that was present in omap_hsmmc > like context save/restore, SDIO support etc. I think we should deprecate > omap_hsmmc compatible once we add all the features in sdhci-omap? >> >> That said, what is then the reason to why we should bring over the >> existing omap_hsmmc bindings to the sdhci-omap bindings? > > This is mainly for old dt compatibility. Even after removing the omap_hsmmc > driver, users should still be able to use newer kernel with their existing dtbs. I guess we have two options. 1) Allow us to invent and use new bindings - and a new compatible. When everything is implemented in sdhci-omap, we can deprecate the old omap_hsmmc driver and its corresponding compatible/bindings. At some point later we can remove the legacy driver/bindings altogether - of course that might take a while. This option allows us to re-think some of the old bindings and really clean up some if its related code. For example, I think "ti,dual-volt" is a bad binding. Instead it would be better to use the existing mmc bindings about which speed mode the controller/board supports (as the voltage level comes with it). 2) Invent only a new compatible, but stick to use the old omap hsmmc bindings and thus also deploy the similar code dealing with them. When everything is implemented move the old omap_hsmmc compatibles into the new sdhci-omap driver and them remove the old omap_hsmmc driver. At that point we could also deprecate the old omap hsmmc compatibles, but to me that is rather pointless. The two options has different advantages, feel free to pick any of them! Kind regards Uffe ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-24 11:29 ` Ulf Hansson @ 2017-08-29 11:20 ` Kishon Vijay Abraham I 2017-08-29 11:50 ` Sebastian Reichel 0 siblings, 1 reply; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-29 11:20 UTC (permalink / raw) To: Ulf Hansson Cc: Adrian Hunter, Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel Hi Uffe, On Thursday 24 August 2017 04:59 PM, Ulf Hansson wrote: > On 23 August 2017 at 15:56, Kishon Vijay Abraham I <kishon@ti.com> wrote: >> Hi Uffe, >> >> On Wednesday 23 August 2017 06:37 PM, Ulf Hansson wrote: >>> On 23 August 2017 at 07:42, Kishon Vijay Abraham I <kishon@ti.com> wrote: >>>> Add binding for the TI's sdhci-omap controller. This now includes only >>>> a subset of properties documented in ti-omap-hsmmc.txt but will eventually >>>> include all the properties. >>>> >>>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> >>>> --- >>>> Changes from v2: >>>> *) Fixed example to use the updated compatible >>>> >>>> Changes from v1: >>>> *) Create a new sdhci-omap.txt document for TI's sdhci-omap controller instead >>>> of using the ti-omap-hsmmc.txt as suggested by Tony >>>> .../devicetree/bindings/mmc/sdhci-omap.txt | 22 ++++++++++++++++++++++ >>>> 1 file changed, 22 insertions(+) >>>> create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-omap.txt >>>> >>>> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-omap.txt b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt >>>> new file mode 100644 >>>> index 000000000000..139695ad2d58 >>>> --- /dev/null >>>> +++ b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt >>>> @@ -0,0 +1,22 @@ >>>> +* TI OMAP SDHCI Controller >>>> + >>>> +Refer to mmc.txt for standard MMC bindings. >>>> + >>>> +Required properties: >>>> +- compatible: Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers >>>> +- ti,hwmods: Must be "mmc<n>", <n> is controller instance starting 1 >>>> + >>>> +Optional properties: >>>> +- ti,dual-volt: boolean, supports dual voltage cards >>>> +- ti,non-removable: non-removable slot (like eMMC) >>>> + >>>> +Example: >>>> + mmc1: mmc@0x4809c000 { >>>> + compatible = "ti,dra7-sdhci"; >>>> + reg = <0x4809c000 0x400>; >>>> + ti,hwmods = "mmc1"; >>>> + ti,dual-volt; >>>> + bus-width = <4>; >>>> + vmmc-supply = <&vmmc>; /* phandle to regulator node */ >>>> + ti,non-removable; >>>> + }; >>>> -- >>>> 2.11.0 >>>> >>> >>> I am wondering a bit on the long term plan here. >>> >>> Ideally at some point in future, we would like to remove the old >>> omap_hsmmc driver, but from compatible string point of view, that >>> means we first needs to deprecate the old ones for a while. Right? >> >> right but sdhci-omap is still lacking features that was present in omap_hsmmc >> like context save/restore, SDIO support etc. I think we should deprecate >> omap_hsmmc compatible once we add all the features in sdhci-omap? >>> >>> That said, what is then the reason to why we should bring over the >>> existing omap_hsmmc bindings to the sdhci-omap bindings? >> >> This is mainly for old dt compatibility. Even after removing the omap_hsmmc >> driver, users should still be able to use newer kernel with their existing dtbs. > > I guess we have two options. > > 1) Allow us to invent and use new bindings - and a new compatible. > When everything is implemented in sdhci-omap, we can deprecate the old > omap_hsmmc driver and its corresponding compatible/bindings. At some > point later we can remove the legacy driver/bindings altogether - of > course that might take a while. This option allows us to re-think some > of the old bindings and really clean up some if its related code. For > example, I think "ti,dual-volt" is a bad binding. Instead it would be > better to use the existing mmc bindings about which speed mode the > controller/board supports (as the voltage level comes with it). > > 2) Invent only a new compatible, but stick to use the old omap hsmmc > bindings and thus also deploy the similar code dealing with them. When > everything is implemented move the old omap_hsmmc compatibles into the > new sdhci-omap driver and them remove the old omap_hsmmc driver. At > that point we could also deprecate the old omap hsmmc compatibles, but > to me that is rather pointless. > > The two options has different advantages, feel free to pick any of them! Okay. I'll send a new version with option '1' (new compatible/new bindings). And when we deprecate the omap_hsmmc driver (some time later), we'll add support for the legacy bindings in sdhci-omap driver (so that old dtbs continue to work). Tony, are you okay with this? Thanks Kishon ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-29 11:20 ` Kishon Vijay Abraham I @ 2017-08-29 11:50 ` Sebastian Reichel 2017-08-29 13:58 ` Tony Lindgren 0 siblings, 1 reply; 31+ messages in thread From: Sebastian Reichel @ 2017-08-29 11:50 UTC (permalink / raw) To: Kishon Vijay Abraham I Cc: Ulf Hansson, Adrian Hunter, Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel [-- Attachment #1: Type: text/plain, Size: 5155 bytes --] Hi, On Tue, Aug 29, 2017 at 04:50:22PM +0530, Kishon Vijay Abraham I wrote: > Hi Uffe, > > On Thursday 24 August 2017 04:59 PM, Ulf Hansson wrote: > > On 23 August 2017 at 15:56, Kishon Vijay Abraham I <kishon@ti.com> wrote: > >> Hi Uffe, > >> > >> On Wednesday 23 August 2017 06:37 PM, Ulf Hansson wrote: > >>> On 23 August 2017 at 07:42, Kishon Vijay Abraham I <kishon@ti.com> wrote: > >>>> Add binding for the TI's sdhci-omap controller. This now includes only > >>>> a subset of properties documented in ti-omap-hsmmc.txt but will eventually > >>>> include all the properties. > >>>> > >>>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> > >>>> --- > >>>> Changes from v2: > >>>> *) Fixed example to use the updated compatible > >>>> > >>>> Changes from v1: > >>>> *) Create a new sdhci-omap.txt document for TI's sdhci-omap controller instead > >>>> of using the ti-omap-hsmmc.txt as suggested by Tony > >>>> .../devicetree/bindings/mmc/sdhci-omap.txt | 22 ++++++++++++++++++++++ > >>>> 1 file changed, 22 insertions(+) > >>>> create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-omap.txt > >>>> > >>>> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-omap.txt b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt > >>>> new file mode 100644 > >>>> index 000000000000..139695ad2d58 > >>>> --- /dev/null > >>>> +++ b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt > >>>> @@ -0,0 +1,22 @@ > >>>> +* TI OMAP SDHCI Controller > >>>> + > >>>> +Refer to mmc.txt for standard MMC bindings. > >>>> + > >>>> +Required properties: > >>>> +- compatible: Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers > >>>> +- ti,hwmods: Must be "mmc<n>", <n> is controller instance starting 1 > >>>> + > >>>> +Optional properties: > >>>> +- ti,dual-volt: boolean, supports dual voltage cards > >>>> +- ti,non-removable: non-removable slot (like eMMC) > >>>> + > >>>> +Example: > >>>> + mmc1: mmc@0x4809c000 { > >>>> + compatible = "ti,dra7-sdhci"; > >>>> + reg = <0x4809c000 0x400>; > >>>> + ti,hwmods = "mmc1"; > >>>> + ti,dual-volt; > >>>> + bus-width = <4>; > >>>> + vmmc-supply = <&vmmc>; /* phandle to regulator node */ > >>>> + ti,non-removable; > >>>> + }; > >>>> -- > >>>> 2.11.0 > >>>> > >>> > >>> I am wondering a bit on the long term plan here. > >>> > >>> Ideally at some point in future, we would like to remove the old > >>> omap_hsmmc driver, but from compatible string point of view, that > >>> means we first needs to deprecate the old ones for a while. Right? > >> > >> right but sdhci-omap is still lacking features that was present in omap_hsmmc > >> like context save/restore, SDIO support etc. I think we should deprecate > >> omap_hsmmc compatible once we add all the features in sdhci-omap? > >>> > >>> That said, what is then the reason to why we should bring over the > >>> existing omap_hsmmc bindings to the sdhci-omap bindings? > >> > >> This is mainly for old dt compatibility. Even after removing the omap_hsmmc > >> driver, users should still be able to use newer kernel with their existing dtbs. > > > > I guess we have two options. > > > > 1) Allow us to invent and use new bindings - and a new compatible. > > When everything is implemented in sdhci-omap, we can deprecate the old > > omap_hsmmc driver and its corresponding compatible/bindings. At some > > point later we can remove the legacy driver/bindings altogether - of > > course that might take a while. This option allows us to re-think some > > of the old bindings and really clean up some if its related code. For > > example, I think "ti,dual-volt" is a bad binding. Instead it would be > > better to use the existing mmc bindings about which speed mode the > > controller/board supports (as the voltage level comes with it). > > > > 2) Invent only a new compatible, but stick to use the old omap hsmmc > > bindings and thus also deploy the similar code dealing with them. When > > everything is implemented move the old omap_hsmmc compatibles into the > > new sdhci-omap driver and them remove the old omap_hsmmc driver. At > > that point we could also deprecate the old omap hsmmc compatibles, but > > to me that is rather pointless. > > > > The two options has different advantages, feel free to pick any of them! > > Okay. I'll send a new version with option '1' (new compatible/new bindings). > > And when we deprecate the omap_hsmmc driver (some time later), we'll add > support for the legacy bindings in sdhci-omap driver (so that old dtbs continue > to work). Tony, are you okay with this? I think you should Cc Rob Herring and Mark Rutland (DT binding maintainers). This sounds like "I use DT to describe driver behaviour" instead of "I use DT to describe hardware". I would expect the conversion to look like the one done for UART, see CONFIG_SERIAL_OMAP vs CONFIG_SERIAL_8250_OMAP. Both use the same compatible value and you can choose using kernel configuration. -- Sebastian [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-29 11:50 ` Sebastian Reichel @ 2017-08-29 13:58 ` Tony Lindgren 2017-08-29 14:43 ` Tony Lindgren 2017-08-29 17:09 ` Rob Herring 0 siblings, 2 replies; 31+ messages in thread From: Tony Lindgren @ 2017-08-29 13:58 UTC (permalink / raw) To: Sebastian Reichel Cc: Kishon Vijay Abraham I, Ulf Hansson, Adrian Hunter, Rob Herring, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel * Sebastian Reichel <sebastian.reichel@collabora.co.uk> [170829 04:51]: > On Tue, Aug 29, 2017 at 04:50:22PM +0530, Kishon Vijay Abraham I wrote: > > On Thursday 24 August 2017 04:59 PM, Ulf Hansson wrote: > > > I guess we have two options. > > > > > > 1) Allow us to invent and use new bindings - and a new compatible. > > > When everything is implemented in sdhci-omap, we can deprecate the old > > > omap_hsmmc driver and its corresponding compatible/bindings. At some > > > point later we can remove the legacy driver/bindings altogether - of > > > course that might take a while. This option allows us to re-think some > > > of the old bindings and really clean up some if its related code. For > > > example, I think "ti,dual-volt" is a bad binding. Instead it would be > > > better to use the existing mmc bindings about which speed mode the > > > controller/board supports (as the voltage level comes with it). > > > > > > 2) Invent only a new compatible, but stick to use the old omap hsmmc > > > bindings and thus also deploy the similar code dealing with them. When > > > everything is implemented move the old omap_hsmmc compatibles into the > > > new sdhci-omap driver and them remove the old omap_hsmmc driver. At > > > that point we could also deprecate the old omap hsmmc compatibles, but > > > to me that is rather pointless. > > > > > > The two options has different advantages, feel free to pick any of them! > > > > Okay. I'll send a new version with option '1' (new compatible/new bindings). Agreed. > > And when we deprecate the omap_hsmmc driver (some time later), we'll add > > support for the legacy bindings in sdhci-omap driver (so that old dtbs continue > > to work). Tony, are you okay with this? > > I think you should Cc Rob Herring and Mark Rutland (DT binding > maintainers). This sounds like "I use DT to describe driver > behaviour" instead of "I use DT to describe hardware". Yes please. > I would expect the conversion to look like the one done for UART, > see CONFIG_SERIAL_OMAP vs CONFIG_SERIAL_8250_OMAP. Both use the > same compatible value and you can choose using kernel configuration. That does not work unfortunately :( We are now stuck in a situation where two drivers are attempting to probe with the same compatible and we can't enable 8250_OMAP because of the user space breakage with the device names. And I'm actuallly thinking we should add a new compatible for 8250-omap to be able to start enabling it one board at a time. It's best to enable devices to use the new compatible as things are tested rather than hope for some magic "flag day" flip that might never happen. Having two days attempting to probe with the same binding just won't work. So yeah, I agree with Kishon that we should stick with generic and sdhci bindings. And then we can start already using it for boards that can use it, then eventually when we're ready, start parsing also the legacy bindings and maybe drop the old driver. Regards, Tony ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-29 13:58 ` Tony Lindgren @ 2017-08-29 14:43 ` Tony Lindgren 2017-08-29 17:09 ` Rob Herring 1 sibling, 0 replies; 31+ messages in thread From: Tony Lindgren @ 2017-08-29 14:43 UTC (permalink / raw) To: Sebastian Reichel Cc: Kishon Vijay Abraham I, Ulf Hansson, Adrian Hunter, Rob Herring, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel * Tony Lindgren <tony@atomide.com> [170829 06:58]: > It's best to enable devices to use the new compatible as things are > tested rather than hope for some magic "flag day" flip that might > never happen. Having two days attempting to probe with the same > binding just won't work. Hehe I mean "Having two drivers attempting to probe with the same binding" above. Tony ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-29 13:58 ` Tony Lindgren 2017-08-29 14:43 ` Tony Lindgren @ 2017-08-29 17:09 ` Rob Herring 2017-08-29 17:39 ` Tony Lindgren 1 sibling, 1 reply; 31+ messages in thread From: Rob Herring @ 2017-08-29 17:09 UTC (permalink / raw) To: Tony Lindgren Cc: Sebastian Reichel, Kishon Vijay Abraham I, Ulf Hansson, Adrian Hunter, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel On Tue, Aug 29, 2017 at 06:58:23AM -0700, Tony Lindgren wrote: > * Sebastian Reichel <sebastian.reichel@collabora.co.uk> [170829 04:51]: > > On Tue, Aug 29, 2017 at 04:50:22PM +0530, Kishon Vijay Abraham I wrote: > > > On Thursday 24 August 2017 04:59 PM, Ulf Hansson wrote: > > > > I guess we have two options. > > > > > > > > 1) Allow us to invent and use new bindings - and a new compatible. > > > > When everything is implemented in sdhci-omap, we can deprecate the old > > > > omap_hsmmc driver and its corresponding compatible/bindings. At some > > > > point later we can remove the legacy driver/bindings altogether - of > > > > course that might take a while. This option allows us to re-think some > > > > of the old bindings and really clean up some if its related code. For > > > > example, I think "ti,dual-volt" is a bad binding. Instead it would be > > > > better to use the existing mmc bindings about which speed mode the > > > > controller/board supports (as the voltage level comes with it). > > > > > > > > 2) Invent only a new compatible, but stick to use the old omap hsmmc > > > > bindings and thus also deploy the similar code dealing with them. When > > > > everything is implemented move the old omap_hsmmc compatibles into the > > > > new sdhci-omap driver and them remove the old omap_hsmmc driver. At > > > > that point we could also deprecate the old omap hsmmc compatibles, but > > > > to me that is rather pointless. > > > > > > > > The two options has different advantages, feel free to pick any of them! > > > > > > Okay. I'll send a new version with option '1' (new compatible/new bindings). > > Agreed. > > > > And when we deprecate the omap_hsmmc driver (some time later), we'll add > > > support for the legacy bindings in sdhci-omap driver (so that old dtbs continue > > > to work). Tony, are you okay with this? > > > > I think you should Cc Rob Herring and Mark Rutland (DT binding > > maintainers). This sounds like "I use DT to describe driver > > behaviour" instead of "I use DT to describe hardware". Indeed... > > Yes please. > > > I would expect the conversion to look like the one done for UART, > > see CONFIG_SERIAL_OMAP vs CONFIG_SERIAL_8250_OMAP. Both use the > > same compatible value and you can choose using kernel configuration. > > That does not work unfortunately :( We are now stuck in a situation > where two drivers are attempting to probe with the same compatible > and we can't enable 8250_OMAP because of the user space breakage > with the device names. And I'm actuallly thinking we should add a > new compatible for 8250-omap to be able to start enabling it one > board at a time. Is that the only problem? Presumably, the SD driver doesn't have a userspace facing issue. > It's best to enable devices to use the new compatible as things are > tested rather than hope for some magic "flag day" flip that might > never happen. Having two days attempting to probe with the same > binding just won't work. Aren't you just picking whether the flag day is in DT or the kernel? I guess you're assuming one kernel build and it would be switching all boards at one. > So yeah, I agree with Kishon that we should stick with generic > and sdhci bindings. And then we can start already using it for > boards that can use it, then eventually when we're ready, start > parsing also the legacy bindings and maybe drop the old driver. I assume there are some other common properties you would switch to in the transition? You could make the legacy driver bail from probe based on presence or absence of other properties. Or you could just blacklist converted platforms in the legacy driver. The point is that the problems are solvable in the kernel. But if your really want a new compatible, I don't really care. It's only one device. Rob ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-29 17:09 ` Rob Herring @ 2017-08-29 17:39 ` Tony Lindgren 2017-09-05 8:52 ` Kishon Vijay Abraham I 0 siblings, 1 reply; 31+ messages in thread From: Tony Lindgren @ 2017-08-29 17:39 UTC (permalink / raw) To: Rob Herring Cc: Sebastian Reichel, Kishon Vijay Abraham I, Ulf Hansson, Adrian Hunter, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel * Rob Herring <robh@kernel.org> [170829 10:09]: > On Tue, Aug 29, 2017 at 06:58:23AM -0700, Tony Lindgren wrote: > > * Sebastian Reichel <sebastian.reichel@collabora.co.uk> [170829 04:51]: > > > I would expect the conversion to look like the one done for UART, > > > see CONFIG_SERIAL_OMAP vs CONFIG_SERIAL_8250_OMAP. Both use the > > > same compatible value and you can choose using kernel configuration. > > > > That does not work unfortunately :( We are now stuck in a situation > > where two drivers are attempting to probe with the same compatible > > and we can't enable 8250_OMAP because of the user space breakage > > with the device names. And I'm actuallly thinking we should add a > > new compatible for 8250-omap to be able to start enabling it one > > board at a time. > > Is that the only problem? Presumably, the SD driver doesn't have a > userspace facing issue. No userspace issue with the sdhci-omap. But the sdhci-omap driver still has the issue of trying enable it for everything at once and expect everything to work. The sdhci-omap driver can already be used for boards that don't need power management for example, but will break things for devices running on batteries. > > It's best to enable devices to use the new compatible as things are > > tested rather than hope for some magic "flag day" flip that might > > never happen. Having two days attempting to probe with the same > > binding just won't work. > > Aren't you just picking whether the flag day is in DT or the kernel? I > guess you're assuming one kernel build and it would be switching all > boards at one. Right, this would be risky and would take unnecessarily long to use the new driver on boards that can already use it. While power management won't work yet, I'd expect the sdhci-omap be faster on SoCs that can do ADMA. > > So yeah, I agree with Kishon that we should stick with generic > > and sdhci bindings. And then we can start already using it for > > boards that can use it, then eventually when we're ready, start > > parsing also the legacy bindings and maybe drop the old driver. > > I assume there are some other common properties you would switch to in > the transition? You could make the legacy driver bail from probe based > on presence or absence of other properties. Or you could just blacklist > converted platforms in the legacy driver. The point is that the problems > are solvable in the kernel. Yes this could be done too. But let's enable it on per-board basis rather than attempt to flip it on at once. > But if your really want a new compatible, I don't really care. It's > only one device. Both a new compatible or a check for some resource work just fine for me as long as the driver can be selected on per-board basis. Regards, Tony ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-29 17:39 ` Tony Lindgren @ 2017-09-05 8:52 ` Kishon Vijay Abraham I 2017-09-05 16:51 ` Tony Lindgren 0 siblings, 1 reply; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-09-05 8:52 UTC (permalink / raw) To: Tony Lindgren, Rob Herring Cc: Sebastian Reichel, Ulf Hansson, Adrian Hunter, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel Hi, On Tuesday 29 August 2017 11:09 PM, Tony Lindgren wrote: > * Rob Herring <robh@kernel.org> [170829 10:09]: >> On Tue, Aug 29, 2017 at 06:58:23AM -0700, Tony Lindgren wrote: >>> * Sebastian Reichel <sebastian.reichel@collabora.co.uk> [170829 04:51]: >>>> I would expect the conversion to look like the one done for UART, >>>> see CONFIG_SERIAL_OMAP vs CONFIG_SERIAL_8250_OMAP. Both use the >>>> same compatible value and you can choose using kernel configuration. >>> >>> That does not work unfortunately :( We are now stuck in a situation >>> where two drivers are attempting to probe with the same compatible >>> and we can't enable 8250_OMAP because of the user space breakage >>> with the device names. And I'm actuallly thinking we should add a >>> new compatible for 8250-omap to be able to start enabling it one >>> board at a time. >> >> Is that the only problem? Presumably, the SD driver doesn't have a >> userspace facing issue. > > No userspace issue with the sdhci-omap. But the sdhci-omap driver > still has the issue of trying enable it for everything at once and > expect everything to work. The sdhci-omap driver can already be > used for boards that don't need power management for example, but > will break things for devices running on batteries. > >>> It's best to enable devices to use the new compatible as things are >>> tested rather than hope for some magic "flag day" flip that might >>> never happen. Having two days attempting to probe with the same >>> binding just won't work. >> >> Aren't you just picking whether the flag day is in DT or the kernel? I >> guess you're assuming one kernel build and it would be switching all >> boards at one. > > Right, this would be risky and would take unnecessarily long > to use the new driver on boards that can already use it. While > power management won't work yet, I'd expect the sdhci-omap be > faster on SoCs that can do ADMA. > >>> So yeah, I agree with Kishon that we should stick with generic >>> and sdhci bindings. And then we can start already using it for >>> boards that can use it, then eventually when we're ready, start >>> parsing also the legacy bindings and maybe drop the old driver. >> >> I assume there are some other common properties you would switch to in >> the transition? You could make the legacy driver bail from probe based >> on presence or absence of other properties. Or you could just blacklist >> converted platforms in the legacy driver. The point is that the problems >> are solvable in the kernel. > > Yes this could be done too. But let's enable it on per-board > basis rather than attempt to flip it on at once. > >> But if your really want a new compatible, I don't really care. It's >> only one device. > > Both a new compatible or a check for some resource work just fine > for me as long as the driver can be selected on per-board basis. New compatible sounds simpler to me since it allows to select a driver per-MMC instance. (SDIO support is not added/validated in sdhci-omap). To summarize, we'll create new compatible and new bindings for sdhci-omap and start enabling sdhci-omap on per-board basis. When all the TI platforms starts to use sdhci-omap, omap-hsmmc will be removed at which point support for old compatible and old dt bindings will be added to sdhci-omap.c. Does this sound reasonable? Thanks Kishon ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-09-05 8:52 ` Kishon Vijay Abraham I @ 2017-09-05 16:51 ` Tony Lindgren 0 siblings, 0 replies; 31+ messages in thread From: Tony Lindgren @ 2017-09-05 16:51 UTC (permalink / raw) To: Kishon Vijay Abraham I Cc: Rob Herring, Sebastian Reichel, Ulf Hansson, Adrian Hunter, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel * Kishon Vijay Abraham I <kishon@ti.com> [170905 01:53]: > Hi, > > On Tuesday 29 August 2017 11:09 PM, Tony Lindgren wrote: > > * Rob Herring <robh@kernel.org> [170829 10:09]: > >> On Tue, Aug 29, 2017 at 06:58:23AM -0700, Tony Lindgren wrote: > >>> * Sebastian Reichel <sebastian.reichel@collabora.co.uk> [170829 04:51]: > >>>> I would expect the conversion to look like the one done for UART, > >>>> see CONFIG_SERIAL_OMAP vs CONFIG_SERIAL_8250_OMAP. Both use the > >>>> same compatible value and you can choose using kernel configuration. > >>> > >>> That does not work unfortunately :( We are now stuck in a situation > >>> where two drivers are attempting to probe with the same compatible > >>> and we can't enable 8250_OMAP because of the user space breakage > >>> with the device names. And I'm actuallly thinking we should add a > >>> new compatible for 8250-omap to be able to start enabling it one > >>> board at a time. > >> > >> Is that the only problem? Presumably, the SD driver doesn't have a > >> userspace facing issue. > > > > No userspace issue with the sdhci-omap. But the sdhci-omap driver > > still has the issue of trying enable it for everything at once and > > expect everything to work. The sdhci-omap driver can already be > > used for boards that don't need power management for example, but > > will break things for devices running on batteries. > > > >>> It's best to enable devices to use the new compatible as things are > >>> tested rather than hope for some magic "flag day" flip that might > >>> never happen. Having two days attempting to probe with the same > >>> binding just won't work. > >> > >> Aren't you just picking whether the flag day is in DT or the kernel? I > >> guess you're assuming one kernel build and it would be switching all > >> boards at one. > > > > Right, this would be risky and would take unnecessarily long > > to use the new driver on boards that can already use it. While > > power management won't work yet, I'd expect the sdhci-omap be > > faster on SoCs that can do ADMA. > > > >>> So yeah, I agree with Kishon that we should stick with generic > >>> and sdhci bindings. And then we can start already using it for > >>> boards that can use it, then eventually when we're ready, start > >>> parsing also the legacy bindings and maybe drop the old driver. > >> > >> I assume there are some other common properties you would switch to in > >> the transition? You could make the legacy driver bail from probe based > >> on presence or absence of other properties. Or you could just blacklist > >> converted platforms in the legacy driver. The point is that the problems > >> are solvable in the kernel. > > > > Yes this could be done too. But let's enable it on per-board > > basis rather than attempt to flip it on at once. > > > >> But if your really want a new compatible, I don't really care. It's > >> only one device. > > > > Both a new compatible or a check for some resource work just fine > > for me as long as the driver can be selected on per-board basis. > > New compatible sounds simpler to me since it allows to select a driver per-MMC > instance. (SDIO support is not added/validated in sdhci-omap). > > To summarize, we'll create new compatible and new bindings for sdhci-omap and > start enabling sdhci-omap on per-board basis. When all the TI platforms starts > to use sdhci-omap, omap-hsmmc will be removed at which point support for old > compatible and old dt bindings will be added to sdhci-omap.c. Does this sound > reasonable? Sounds like a plan to me. Regards, Tony ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-23 5:42 ` [PATCH v3 " Kishon Vijay Abraham I 2017-08-23 13:07 ` Ulf Hansson @ 2017-08-29 17:11 ` Rob Herring 2017-09-05 8:53 ` Kishon Vijay Abraham I 1 sibling, 1 reply; 31+ messages in thread From: Rob Herring @ 2017-08-29 17:11 UTC (permalink / raw) To: Kishon Vijay Abraham I Cc: Ulf Hansson, Adrian Hunter, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel On Wed, Aug 23, 2017 at 11:12:46AM +0530, Kishon Vijay Abraham I wrote: > Add binding for the TI's sdhci-omap controller. This now includes only > a subset of properties documented in ti-omap-hsmmc.txt but will eventually > include all the properties. > > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> > --- > Changes from v2: > *) Fixed example to use the updated compatible > > Changes from v1: > *) Create a new sdhci-omap.txt document for TI's sdhci-omap controller instead > of using the ti-omap-hsmmc.txt as suggested by Tony > .../devicetree/bindings/mmc/sdhci-omap.txt | 22 ++++++++++++++++++++++ > 1 file changed, 22 insertions(+) > create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-omap.txt > > diff --git a/Documentation/devicetree/bindings/mmc/sdhci-omap.txt b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt > new file mode 100644 > index 000000000000..139695ad2d58 > --- /dev/null > +++ b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt > @@ -0,0 +1,22 @@ > +* TI OMAP SDHCI Controller > + > +Refer to mmc.txt for standard MMC bindings. > + > +Required properties: > +- compatible: Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers > +- ti,hwmods: Must be "mmc<n>", <n> is controller instance starting 1 > + > +Optional properties: > +- ti,dual-volt: boolean, supports dual voltage cards > +- ti,non-removable: non-removable slot (like eMMC) Well, if you are doing a new compatible, then why aren't you using common properties? > + > +Example: > + mmc1: mmc@0x4809c000 { Drop the '0x'. > + compatible = "ti,dra7-sdhci"; > + reg = <0x4809c000 0x400>; > + ti,hwmods = "mmc1"; > + ti,dual-volt; > + bus-width = <4>; > + vmmc-supply = <&vmmc>; /* phandle to regulator node */ > + ti,non-removable; > + }; > -- > 2.11.0 > ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v3 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller 2017-08-29 17:11 ` Rob Herring @ 2017-09-05 8:53 ` Kishon Vijay Abraham I 0 siblings, 0 replies; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-09-05 8:53 UTC (permalink / raw) To: Rob Herring Cc: Ulf Hansson, Adrian Hunter, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel Hi, On Tuesday 29 August 2017 10:41 PM, Rob Herring wrote: > On Wed, Aug 23, 2017 at 11:12:46AM +0530, Kishon Vijay Abraham I wrote: >> Add binding for the TI's sdhci-omap controller. This now includes only >> a subset of properties documented in ti-omap-hsmmc.txt but will eventually >> include all the properties. >> >> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> >> --- >> Changes from v2: >> *) Fixed example to use the updated compatible >> >> Changes from v1: >> *) Create a new sdhci-omap.txt document for TI's sdhci-omap controller instead >> of using the ti-omap-hsmmc.txt as suggested by Tony >> .../devicetree/bindings/mmc/sdhci-omap.txt | 22 ++++++++++++++++++++++ >> 1 file changed, 22 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-omap.txt >> >> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-omap.txt b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt >> new file mode 100644 >> index 000000000000..139695ad2d58 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/mmc/sdhci-omap.txt >> @@ -0,0 +1,22 @@ >> +* TI OMAP SDHCI Controller >> + >> +Refer to mmc.txt for standard MMC bindings. >> + >> +Required properties: >> +- compatible: Should be "ti,dra7-sdhci" for DRA7 and DRA72 controllers >> +- ti,hwmods: Must be "mmc<n>", <n> is controller instance starting 1 >> + >> +Optional properties: >> +- ti,dual-volt: boolean, supports dual voltage cards >> +- ti,non-removable: non-removable slot (like eMMC) > > Well, if you are doing a new compatible, then why aren't you using > common properties? yeah, now moved to generic bindings. > >> + >> +Example: >> + mmc1: mmc@0x4809c000 { > > Drop the '0x'. sure, will fix it. Thanks Kishon ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 4/5] mmc: sdhci-omap: Add OMAP SDHCI driver 2017-08-21 7:41 [PATCH 0/5] mmc: Add OMAP SDHCI driver Kishon Vijay Abraham I ` (2 preceding siblings ...) 2017-08-21 7:41 ` [PATCH 3/5] dt-bindings: ti-omap-hsmmc: Document new compatible for sdhci omap Kishon Vijay Abraham I @ 2017-08-21 7:41 ` Kishon Vijay Abraham I 2017-08-28 9:06 ` Adrian Hunter 2017-08-21 7:41 ` [PATCH 5/5] MAINTAINERS: Add TI OMAP SDHCI Maintainer Kishon Vijay Abraham I 4 siblings, 1 reply; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-21 7:41 UTC (permalink / raw) To: Ulf Hansson, Adrian Hunter Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel, Kishon Vijay Abraham I Create a new sdhci-omap driver to configure the eMMC/SD/SDIO controller in TI's OMAP SoCs making use of the SDHCI core library. For OMAP specific configurations, populate sdhci_ops with OMAP specific callbacks and use SDHCI quirks. Enable only high speed mode for both SD and eMMC here and add other UHS mode support later. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> --- drivers/mmc/host/Kconfig | 12 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/sdhci-omap.c | 629 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 642 insertions(+) create mode 100644 drivers/mmc/host/sdhci-omap.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 60f90d49e7a9..60d50843e165 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -899,3 +899,15 @@ config MMC_SDHCI_XENON This selects Marvell Xenon eMMC/SD/SDIO SDHCI. If you have a controller with this interface, say Y or M here. If unsure, say N. + +config MMC_SDHCI_OMAP + tristate "TI SDHCI Controller Support" + depends on MMC_SDHCI_PLTFM + help + This selects the Secure Digital Host Controller Interface (SDHCI) + support present in TI's DRA7 SOCs. The controller supports + SD/MMC/SDIO devices. + + If you have a controller with this interface, say Y or M here. + + If unsure, say N. diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 8c46766c000c..33181df88a10 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -88,6 +88,7 @@ obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32) += sdhci-pic32.o obj-$(CONFIG_MMC_SDHCI_BRCMSTB) += sdhci-brcmstb.o +obj-$(CONFIG_MMC_SDHCI_OMAP) += sdhci-omap.o ifeq ($(CONFIG_CB710_DEBUG),y) CFLAGS-cb710-mmc += -DDEBUG diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c new file mode 100644 index 000000000000..73ee3b4a400c --- /dev/null +++ b/drivers/mmc/host/sdhci-omap.c @@ -0,0 +1,629 @@ +/** + * SDHCI Controller driver for TI's OMAP SoCs + * + * Copyright (C) 2017 Texas Instruments + * Author: Kishon Vijay Abraham I <kishon@ti.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/delay.h> +#include <linux/mmc/slot-gpio.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> + +#include "sdhci-pltfm.h" + +#define SDHCI_OMAP_CON 0x12c +#define CON_DW8 BIT(5) +#define CON_DMA_MASTER BIT(20) +#define CON_INIT BIT(1) +#define CON_OD BIT(0) + +#define SDHCI_OMAP_CMD 0x20c + +#define SDHCI_OMAP_HCTL 0x228 +#define HCTL_SDBP BIT(8) +#define HCTL_SDVS_SHIFT 9 +#define HCTL_SDVS_MASK (0x7 << HCTL_SDVS_SHIFT) +#define HCTL_SDVS_33 (0x7 << HCTL_SDVS_SHIFT) +#define HCTL_SDVS_30 (0x6 << HCTL_SDVS_SHIFT) +#define HCTL_SDVS_18 (0x5 << HCTL_SDVS_SHIFT) + +#define SDHCI_OMAP_SYSCTL 0x22c +#define SYSCTL_CEN BIT(2) +#define SYSCTL_CLKD_SHIFT 6 +#define SYSCTL_CLKD_MASK 0x3ff + +#define SDHCI_OMAP_STAT 0x230 + +#define SDHCI_OMAP_IE 0x234 +#define INT_CC_EN BIT(0) + +#define SDHCI_OMAP_AC12 0x23c +#define AC12_V1V8_SIGEN BIT(19) + +#define SDHCI_OMAP_CAPA 0x240 +#define CAPA_VS33 BIT(24) +#define CAPA_VS30 BIT(25) +#define CAPA_VS18 BIT(26) + +#define MMC_TIMEOUT 1 /* 1 msec */ + +#define SYSCTL_CLKD_MAX 0x3FF + +#define IOV_1V8 1800000 /* 180000 uV */ +#define IOV_3V0 3000000 /* 300000 uV */ +#define IOV_3V3 3300000 /* 330000 uV */ + +struct sdhci_omap_data { + u32 offset; +}; + +struct sdhci_omap_host { + void __iomem *base; + struct device *dev; + struct regulator *pbias; + bool pbias_enabled; + struct sdhci_host *host; + unsigned int flags; + +#define SDHCI_OMAP_SUPPORTS_DUAL_VOLT BIT(0) +#define SDHCI_OMAP_NO_1_8_V BIT(1) + + u8 bus_mode; + u8 power_mode; + bool io_3_3v_support; +}; + +static inline u32 sdhci_omap_readl(struct sdhci_omap_host *host, + unsigned int offset) +{ + return readl(host->base + offset); +} + +static inline void sdhci_omap_writel(struct sdhci_omap_host *host, + unsigned int offset, u32 data) +{ + writel(data, host->base + offset); +} + +static int sdhci_omap_set_pbias(struct sdhci_omap_host *omap_host, + bool power_on, unsigned int iov) +{ + int ret; + struct device *dev = omap_host->dev; + + if (IS_ERR(omap_host->pbias)) + return 0; + + if (power_on) { + ret = regulator_set_voltage(omap_host->pbias, iov, iov); + if (ret) { + dev_err(dev, "pbias set voltage failed\n"); + return ret; + } + + if (omap_host->pbias_enabled) + return 0; + + ret = regulator_enable(omap_host->pbias); + if (ret) { + dev_err(dev, "pbias reg enable fail\n"); + return ret; + } + + omap_host->pbias_enabled = true; + } else { + if (!omap_host->pbias_enabled) + return 0; + + ret = regulator_disable(omap_host->pbias); + if (ret) { + dev_err(dev, "pbias reg disable fail\n"); + return ret; + } + omap_host->pbias_enabled = false; + } + + return 0; +} + +static int sdhci_omap_enable_iov(struct sdhci_omap_host *omap_host, + unsigned int iov) +{ + int ret; + struct sdhci_host *host = omap_host->host; + struct mmc_host *mmc = host->mmc; + + ret = sdhci_omap_set_pbias(omap_host, false, 0); + if (ret) + return ret; + + if (!IS_ERR(mmc->supply.vqmmc)) { + ret = regulator_set_voltage(mmc->supply.vqmmc, iov, iov); + if (ret) { + dev_err(mmc_dev(mmc), "vqmmc set voltage failed\n"); + return ret; + } + } + + ret = sdhci_omap_set_pbias(omap_host, true, iov); + if (ret) + return ret; + + return 0; +} + +static void sdhci_omap_conf_bus_power(struct sdhci_omap_host *omap_host, + unsigned char signal_voltage) +{ + u32 reg; + ktime_t timeout; + + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL); + reg &= ~HCTL_SDVS_MASK; + + if (signal_voltage == MMC_SIGNAL_VOLTAGE_180) + reg |= HCTL_SDVS_18; + else if (omap_host->io_3_3v_support) + reg |= HCTL_SDVS_33; + else + reg |= HCTL_SDVS_30; + + sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, reg); + + reg |= HCTL_SDBP; + sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, reg); + + /* wait 1ms */ + timeout = ktime_add_ms(ktime_get(), MMC_TIMEOUT); + while (!(sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL) & HCTL_SDBP)) { + if (WARN_ON(ktime_after(ktime_get(), timeout))) + return; + usleep_range(5, 10); + } +} + +static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + u32 reg; + int ret; + unsigned int iov; + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_pltfm_host *pltfm_host; + struct sdhci_omap_host *omap_host; + struct device *dev; + + pltfm_host = sdhci_priv(host); + omap_host = sdhci_pltfm_priv(pltfm_host); + dev = omap_host->dev; + + if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); + if (!(reg & (CAPA_VS33 | CAPA_VS30))) + return -EOPNOTSUPP; + + sdhci_omap_conf_bus_power(omap_host, ios->signal_voltage); + + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); + reg &= ~AC12_V1V8_SIGEN; + sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg); + + if (omap_host->io_3_3v_support) + iov = IOV_3V3; + else + iov = IOV_3V0; + } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); + if (!(reg & CAPA_VS18)) + return -EOPNOTSUPP; + + sdhci_omap_conf_bus_power(omap_host, ios->signal_voltage); + + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); + reg |= AC12_V1V8_SIGEN; + sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg); + + iov = IOV_1V8; + } else { + return -EOPNOTSUPP; + } + + ret = sdhci_omap_enable_iov(omap_host, iov); + if (ret) { + dev_err(dev, "failed to switch IO voltage to %dmV\n", iov); + return ret; + } + + dev_dbg(dev, "IO voltage switched to %dmV\n", iov); + return 0; +} + +static void sdhci_omap_set_bus_mode(struct sdhci_omap_host *omap_host, + unsigned int mode) +{ + u32 reg; + + if (omap_host->bus_mode == mode) + return; + + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); + if (mode == MMC_BUSMODE_OPENDRAIN) + reg |= CON_OD; + else + reg &= ~CON_OD; + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); + + omap_host->bus_mode = mode; +} + +void sdhci_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_pltfm_host *pltfm_host; + struct sdhci_omap_host *omap_host; + + pltfm_host = sdhci_priv(host); + omap_host = sdhci_pltfm_priv(pltfm_host); + + sdhci_omap_set_bus_mode(omap_host, ios->bus_mode); + sdhci_set_ios(mmc, ios); +} + +static void sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host) +{ + u32 reg; + + /* voltage capabilities might be set by boot loader, clear it */ + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); + reg &= ~(CAPA_VS18 | CAPA_VS30 | CAPA_VS33); + + if (omap_host->flags & SDHCI_OMAP_SUPPORTS_DUAL_VOLT) { + if (omap_host->io_3_3v_support) + reg |= (CAPA_VS33 | CAPA_VS18); + else + reg |= (CAPA_VS30 | CAPA_VS18); + } else if (omap_host->flags & SDHCI_OMAP_NO_1_8_V) { + if (omap_host->io_3_3v_support) + reg |= CAPA_VS33; + else + reg |= CAPA_VS30; + } else { + reg |= CAPA_VS18; + } + + sdhci_omap_writel(omap_host, SDHCI_OMAP_CAPA, reg); +} + +static u16 sdhci_omap_calc_divisor(struct sdhci_pltfm_host *host, + unsigned int clock) +{ + u16 dsor; + + dsor = DIV_ROUND_UP(clk_get_rate(host->clk), clock); + if (dsor > SYSCTL_CLKD_MAX) + dsor = SYSCTL_CLKD_MAX; + + return dsor; +} + +static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host) +{ + u32 reg; + + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL); + reg |= SYSCTL_CEN; + sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, reg); +} + +static void sdhci_omap_stop_clock(struct sdhci_omap_host *omap_host) +{ + u32 reg; + + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL); + reg &= ~SYSCTL_CEN; + sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, reg); +} + +static void sdhci_omap_set_clock(struct sdhci_host *host, unsigned int clock) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); + unsigned long clkdiv; + + if (!clock) + return; + + sdhci_omap_stop_clock(omap_host); + + clkdiv = sdhci_omap_calc_divisor(pltfm_host, clock); + clkdiv = (clkdiv & SYSCTL_CLKD_MASK) << SYSCTL_CLKD_SHIFT; + sdhci_enable_clk(host, clkdiv); + + sdhci_omap_start_clock(omap_host); +} + +void sdhci_omap_set_power(struct sdhci_host *host, unsigned char mode, + unsigned short vdd) +{ + struct mmc_host *mmc = host->mmc; + + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); +} + +static int sdhci_omap_enable_dma(struct sdhci_host *host) +{ + u32 reg; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); + + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); + reg |= CON_DMA_MASTER; + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); + + return 0; +} + +unsigned int sdhci_omap_get_min_clock(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + return clk_get_rate(pltfm_host->clk) / SYSCTL_CLKD_MAX; +} + +static void sdhci_omap_set_bus_width(struct sdhci_host *host, int width) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); + u32 reg; + + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); + if (width == MMC_BUS_WIDTH_8) + reg |= CON_DW8; + else + reg &= ~CON_DW8; + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); + + sdhci_set_bus_width(host, width); +} + +static void sdhci_omap_init_74_clocks(struct sdhci_host *host, u8 power_mode) +{ + u32 reg; + ktime_t timeout; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); + + if (omap_host->power_mode == power_mode) + return; + + if (power_mode != MMC_POWER_ON) + return; + + disable_irq(host->irq); + + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); + reg |= CON_INIT; + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); + sdhci_omap_writel(omap_host, SDHCI_OMAP_CMD, 0x0); + + /* wait 1ms */ + timeout = ktime_add_ms(ktime_get(), MMC_TIMEOUT); + while (!(sdhci_omap_readl(omap_host, SDHCI_OMAP_STAT) & INT_CC_EN)) { + if (WARN_ON(ktime_after(ktime_get(), timeout))) + return; + usleep_range(5, 10); + } + + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); + reg &= ~CON_INIT; + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); + sdhci_omap_writel(omap_host, SDHCI_OMAP_STAT, INT_CC_EN); + + enable_irq(host->irq); + + omap_host->power_mode = power_mode; +} + +static struct sdhci_ops sdhci_omap_ops = { + .set_clock = sdhci_omap_set_clock, + .set_power = sdhci_omap_set_power, + .enable_dma = sdhci_omap_enable_dma, + .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .get_min_clock = sdhci_omap_get_min_clock, + .set_bus_width = sdhci_omap_set_bus_width, + .platform_send_init_74_clocks = sdhci_omap_init_74_clocks, + .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, +}; + +void sdhci_omap_get_of_property(struct sdhci_omap_host *omap_host) +{ + struct device *dev = omap_host->dev; + struct sdhci_host *host = omap_host->host; + struct mmc_host *mmc = host->mmc; + + if (device_property_read_bool(dev, "ti,dual-volt")) + omap_host->flags |= SDHCI_OMAP_SUPPORTS_DUAL_VOLT; + + if (device_property_read_bool(dev, "no-1-8-v")) + omap_host->flags |= SDHCI_OMAP_NO_1_8_V; + + if (device_property_read_bool(dev, "ti,non-removable")) + mmc->caps |= MMC_CAP_NONREMOVABLE; +} + +static const struct sdhci_pltfm_data sdhci_omap_pdata = { + .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | + SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | + SDHCI_QUIRK_NO_HISPD_BIT | + SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, + .quirks2 = SDHCI_QUIRK2_NO_1_8_V | + SDHCI_QUIRK2_ACMD23_BROKEN | + SDHCI_QUIRK2_RSP_136_HAS_CRC, + .ops = &sdhci_omap_ops, +}; + +static const struct sdhci_omap_data dra7_data = { + .offset = 0x200, +}; + +static const struct of_device_id omap_sdhci_match[] = { + { .compatible = "ti,dra7-sdhci", .data = &dra7_data }, + {}, +}; +MODULE_DEVICE_TABLE(of, omap_sdhci_match); + +static int sdhci_omap_probe(struct platform_device *pdev) +{ + int ret; + u32 offset; + struct device *dev = &pdev->dev; + struct sdhci_host *host; + struct sdhci_pltfm_host *pltfm_host; + struct sdhci_omap_host *omap_host; + struct mmc_host *mmc; + const struct of_device_id *match; + struct sdhci_omap_data *data; + + match = of_match_device(omap_sdhci_match, dev); + if (!match) + return -EINVAL; + + data = (struct sdhci_omap_data *)match->data; + if (!data) { + dev_err(dev, "no sdhci omap data\n"); + return -EINVAL; + } + + offset = data->offset; + + host = sdhci_pltfm_init(pdev, &sdhci_omap_pdata, + sizeof(*omap_host)); + if (IS_ERR(host)) { + dev_err(dev, "Failed sdhci_pltfm_init\n"); + return PTR_ERR(host); + } + + pltfm_host = sdhci_priv(host); + omap_host = sdhci_pltfm_priv(pltfm_host); + omap_host->host = host; + omap_host->base = host->ioaddr; + omap_host->dev = dev; + sdhci_omap_get_of_property(omap_host); + + host->ioaddr += offset; + + mmc = host->mmc; + ret = mmc_of_parse(mmc); + if (ret) + goto err_of_parse; + + pltfm_host->clk = devm_clk_get(dev, "fck"); + if (IS_ERR(pltfm_host->clk)) { + ret = PTR_ERR(pltfm_host->clk); + goto err_of_parse; + } + + ret = clk_set_rate(pltfm_host->clk, mmc->f_max); + if (ret) { + dev_err(dev, "failed to set clock to %d\n", mmc->f_max); + goto err_of_parse; + } + + omap_host->pbias = devm_regulator_get_optional(dev, "pbias"); + if (IS_ERR(omap_host->pbias)) { + ret = PTR_ERR(omap_host->pbias); + if (ret != -ENODEV) { + dev_err(dev, "CONFIG_REGULATOR_PBIAS not enabled??\n"); + return ret; + } + dev_dbg(dev, "unable to get pbias regulator %ld\n", + PTR_ERR(omap_host->pbias)); + } else { + if (regulator_is_supported_voltage(omap_host->pbias, IOV_3V3, + IOV_3V3)) + omap_host->io_3_3v_support = true; + dev_vdbg(dev, "Max PBIAS support Voltage: %dmv\n", + omap_host->io_3_3v_support ? IOV_3V3 : IOV_3V0); + } + omap_host->pbias_enabled = false; + + /* Enable main Func clock, interface clock and program SYSCONFIG */ + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "pm_runtime_get_sync failed\n"); + goto err_get_sync; + } + + sdhci_omap_set_capabilities(omap_host); + + host->mmc_host_ops.get_ro = mmc_gpio_get_ro; + host->mmc_host_ops.start_signal_voltage_switch = + sdhci_omap_start_signal_voltage_switch; + host->mmc_host_ops.set_ios = sdhci_omap_set_ios; + + sdhci_read_caps(host); + host->caps |= SDHCI_CAN_DO_ADMA2; + + ret = sdhci_add_host(host); + if (ret) + goto err_get_sync; + + return 0; + +err_get_sync: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + +err_of_parse: + sdhci_pltfm_free(pdev); + return ret; +} + +static int sdhci_omap_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sdhci_host *host = platform_get_drvdata(pdev); + + sdhci_remove_host(host, true); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + sdhci_pltfm_free(pdev); + + return 0; +} + +static struct platform_driver sdhci_omap_driver = { + .probe = sdhci_omap_probe, + .remove = sdhci_omap_remove, + .driver = { + .name = "sdhci-omap", + .of_match_table = of_match_ptr(omap_sdhci_match), + }, +}; + +module_platform_driver(sdhci_omap_driver); + +MODULE_DESCRIPTION("SDHCI driver for OMAP SoCs"); +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("OMAP SDHCI Driver"); -- 2.11.0 ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 4/5] mmc: sdhci-omap: Add OMAP SDHCI driver 2017-08-21 7:41 ` [PATCH 4/5] mmc: sdhci-omap: Add OMAP SDHCI driver Kishon Vijay Abraham I @ 2017-08-28 9:06 ` Adrian Hunter 2017-08-30 13:53 ` Kishon Vijay Abraham I 0 siblings, 1 reply; 31+ messages in thread From: Adrian Hunter @ 2017-08-28 9:06 UTC (permalink / raw) To: Kishon Vijay Abraham I, Ulf Hansson Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel On 21/08/17 10:41, Kishon Vijay Abraham I wrote: > Create a new sdhci-omap driver to configure the eMMC/SD/SDIO controller > in TI's OMAP SoCs making use of the SDHCI core library. For OMAP specific > configurations, populate sdhci_ops with OMAP specific callbacks and use > SDHCI quirks. > Enable only high speed mode for both SD and eMMC here and add other > UHS mode support later. > > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> There are a few minor comments below. > --- > drivers/mmc/host/Kconfig | 12 + > drivers/mmc/host/Makefile | 1 + > drivers/mmc/host/sdhci-omap.c | 629 ++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 642 insertions(+) > create mode 100644 drivers/mmc/host/sdhci-omap.c > > diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig > index 60f90d49e7a9..60d50843e165 100644 > --- a/drivers/mmc/host/Kconfig > +++ b/drivers/mmc/host/Kconfig > @@ -899,3 +899,15 @@ config MMC_SDHCI_XENON > This selects Marvell Xenon eMMC/SD/SDIO SDHCI. > If you have a controller with this interface, say Y or M here. > If unsure, say N. > + > +config MMC_SDHCI_OMAP > + tristate "TI SDHCI Controller Support" > + depends on MMC_SDHCI_PLTFM > + help > + This selects the Secure Digital Host Controller Interface (SDHCI) > + support present in TI's DRA7 SOCs. The controller supports > + SD/MMC/SDIO devices. > + > + If you have a controller with this interface, say Y or M here. > + > + If unsure, say N. > diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile > index 8c46766c000c..33181df88a10 100644 > --- a/drivers/mmc/host/Makefile > +++ b/drivers/mmc/host/Makefile > @@ -88,6 +88,7 @@ obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o > obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o > obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32) += sdhci-pic32.o > obj-$(CONFIG_MMC_SDHCI_BRCMSTB) += sdhci-brcmstb.o > +obj-$(CONFIG_MMC_SDHCI_OMAP) += sdhci-omap.o > > ifeq ($(CONFIG_CB710_DEBUG),y) > CFLAGS-cb710-mmc += -DDEBUG > diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c > new file mode 100644 > index 000000000000..73ee3b4a400c > --- /dev/null > +++ b/drivers/mmc/host/sdhci-omap.c > @@ -0,0 +1,629 @@ > +/** > + * SDHCI Controller driver for TI's OMAP SoCs > + * > + * Copyright (C) 2017 Texas Instruments > + * Author: Kishon Vijay Abraham I <kishon@ti.com> > + * > + * This program is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 of > + * the License as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include <linux/delay.h> > +#include <linux/mmc/slot-gpio.h> > +#include <linux/module.h> > +#include <linux/of.h> > +#include <linux/of_device.h> > +#include <linux/platform_device.h> > +#include <linux/pm_runtime.h> > +#include <linux/regulator/consumer.h> > + > +#include "sdhci-pltfm.h" > + > +#define SDHCI_OMAP_CON 0x12c > +#define CON_DW8 BIT(5) > +#define CON_DMA_MASTER BIT(20) > +#define CON_INIT BIT(1) > +#define CON_OD BIT(0) > + > +#define SDHCI_OMAP_CMD 0x20c > + > +#define SDHCI_OMAP_HCTL 0x228 > +#define HCTL_SDBP BIT(8) > +#define HCTL_SDVS_SHIFT 9 > +#define HCTL_SDVS_MASK (0x7 << HCTL_SDVS_SHIFT) > +#define HCTL_SDVS_33 (0x7 << HCTL_SDVS_SHIFT) > +#define HCTL_SDVS_30 (0x6 << HCTL_SDVS_SHIFT) > +#define HCTL_SDVS_18 (0x5 << HCTL_SDVS_SHIFT) > + > +#define SDHCI_OMAP_SYSCTL 0x22c > +#define SYSCTL_CEN BIT(2) > +#define SYSCTL_CLKD_SHIFT 6 > +#define SYSCTL_CLKD_MASK 0x3ff > + > +#define SDHCI_OMAP_STAT 0x230 > + > +#define SDHCI_OMAP_IE 0x234 > +#define INT_CC_EN BIT(0) > + > +#define SDHCI_OMAP_AC12 0x23c > +#define AC12_V1V8_SIGEN BIT(19) > + > +#define SDHCI_OMAP_CAPA 0x240 > +#define CAPA_VS33 BIT(24) > +#define CAPA_VS30 BIT(25) > +#define CAPA_VS18 BIT(26) > + > +#define MMC_TIMEOUT 1 /* 1 msec */ As before, SDHCI_OMAP_TIMEOUT is a better name > + > +#define SYSCTL_CLKD_MAX 0x3FF > + > +#define IOV_1V8 1800000 /* 180000 uV */ > +#define IOV_3V0 3000000 /* 300000 uV */ > +#define IOV_3V3 3300000 /* 330000 uV */ > + > +struct sdhci_omap_data { > + u32 offset; > +}; > + > +struct sdhci_omap_host { > + void __iomem *base; > + struct device *dev; > + struct regulator *pbias; > + bool pbias_enabled; > + struct sdhci_host *host; > + unsigned int flags; > + > +#define SDHCI_OMAP_SUPPORTS_DUAL_VOLT BIT(0) > +#define SDHCI_OMAP_NO_1_8_V BIT(1) > + > + u8 bus_mode; > + u8 power_mode; > + bool io_3_3v_support; > +}; > + > +static inline u32 sdhci_omap_readl(struct sdhci_omap_host *host, > + unsigned int offset) > +{ > + return readl(host->base + offset); > +} > + > +static inline void sdhci_omap_writel(struct sdhci_omap_host *host, > + unsigned int offset, u32 data) > +{ > + writel(data, host->base + offset); > +} > + > +static int sdhci_omap_set_pbias(struct sdhci_omap_host *omap_host, > + bool power_on, unsigned int iov) > +{ > + int ret; > + struct device *dev = omap_host->dev; > + > + if (IS_ERR(omap_host->pbias)) > + return 0; > + > + if (power_on) { > + ret = regulator_set_voltage(omap_host->pbias, iov, iov); > + if (ret) { > + dev_err(dev, "pbias set voltage failed\n"); > + return ret; > + } > + > + if (omap_host->pbias_enabled) > + return 0; > + > + ret = regulator_enable(omap_host->pbias); > + if (ret) { > + dev_err(dev, "pbias reg enable fail\n"); > + return ret; > + } > + > + omap_host->pbias_enabled = true; > + } else { > + if (!omap_host->pbias_enabled) > + return 0; > + > + ret = regulator_disable(omap_host->pbias); > + if (ret) { > + dev_err(dev, "pbias reg disable fail\n"); > + return ret; > + } > + omap_host->pbias_enabled = false; > + } > + > + return 0; > +} > + > +static int sdhci_omap_enable_iov(struct sdhci_omap_host *omap_host, > + unsigned int iov) > +{ > + int ret; > + struct sdhci_host *host = omap_host->host; > + struct mmc_host *mmc = host->mmc; > + > + ret = sdhci_omap_set_pbias(omap_host, false, 0); > + if (ret) > + return ret; > + > + if (!IS_ERR(mmc->supply.vqmmc)) { > + ret = regulator_set_voltage(mmc->supply.vqmmc, iov, iov); > + if (ret) { > + dev_err(mmc_dev(mmc), "vqmmc set voltage failed\n"); > + return ret; > + } > + } > + > + ret = sdhci_omap_set_pbias(omap_host, true, iov); > + if (ret) > + return ret; > + > + return 0; > +} > + > +static void sdhci_omap_conf_bus_power(struct sdhci_omap_host *omap_host, > + unsigned char signal_voltage) > +{ > + u32 reg; > + ktime_t timeout; > + > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL); > + reg &= ~HCTL_SDVS_MASK; > + > + if (signal_voltage == MMC_SIGNAL_VOLTAGE_180) > + reg |= HCTL_SDVS_18; > + else if (omap_host->io_3_3v_support) > + reg |= HCTL_SDVS_33; > + else > + reg |= HCTL_SDVS_30; > + > + sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, reg); > + > + reg |= HCTL_SDBP; > + sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, reg); > + > + /* wait 1ms */ > + timeout = ktime_add_ms(ktime_get(), MMC_TIMEOUT); > + while (!(sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL) & HCTL_SDBP)) { > + if (WARN_ON(ktime_after(ktime_get(), timeout))) > + return; > + usleep_range(5, 10); > + } > +} > + > +static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc, > + struct mmc_ios *ios) > +{ > + u32 reg; > + int ret; > + unsigned int iov; > + struct sdhci_host *host = mmc_priv(mmc); > + struct sdhci_pltfm_host *pltfm_host; > + struct sdhci_omap_host *omap_host; > + struct device *dev; > + > + pltfm_host = sdhci_priv(host); > + omap_host = sdhci_pltfm_priv(pltfm_host); > + dev = omap_host->dev; > + > + if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); > + if (!(reg & (CAPA_VS33 | CAPA_VS30))) > + return -EOPNOTSUPP; > + > + sdhci_omap_conf_bus_power(omap_host, ios->signal_voltage); > + > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); > + reg &= ~AC12_V1V8_SIGEN; > + sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg); > + > + if (omap_host->io_3_3v_support) > + iov = IOV_3V3; > + else > + iov = IOV_3V0; > + } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); > + if (!(reg & CAPA_VS18)) > + return -EOPNOTSUPP; > + > + sdhci_omap_conf_bus_power(omap_host, ios->signal_voltage); > + > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); > + reg |= AC12_V1V8_SIGEN; > + sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg); > + > + iov = IOV_1V8; > + } else { > + return -EOPNOTSUPP; > + } > + > + ret = sdhci_omap_enable_iov(omap_host, iov); > + if (ret) { > + dev_err(dev, "failed to switch IO voltage to %dmV\n", iov); > + return ret; > + } > + > + dev_dbg(dev, "IO voltage switched to %dmV\n", iov); > + return 0; > +} > + > +static void sdhci_omap_set_bus_mode(struct sdhci_omap_host *omap_host, > + unsigned int mode) > +{ > + u32 reg; > + > + if (omap_host->bus_mode == mode) > + return; > + > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); > + if (mode == MMC_BUSMODE_OPENDRAIN) > + reg |= CON_OD; > + else > + reg &= ~CON_OD; > + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); > + > + omap_host->bus_mode = mode; > +} > + > +void sdhci_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) > +{ > + struct sdhci_host *host = mmc_priv(mmc); > + struct sdhci_pltfm_host *pltfm_host; > + struct sdhci_omap_host *omap_host; > + > + pltfm_host = sdhci_priv(host); > + omap_host = sdhci_pltfm_priv(pltfm_host); > + > + sdhci_omap_set_bus_mode(omap_host, ios->bus_mode); > + sdhci_set_ios(mmc, ios); > +} > + > +static void sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host) > +{ > + u32 reg; > + > + /* voltage capabilities might be set by boot loader, clear it */ > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); > + reg &= ~(CAPA_VS18 | CAPA_VS30 | CAPA_VS33); > + > + if (omap_host->flags & SDHCI_OMAP_SUPPORTS_DUAL_VOLT) { > + if (omap_host->io_3_3v_support) > + reg |= (CAPA_VS33 | CAPA_VS18); > + else > + reg |= (CAPA_VS30 | CAPA_VS18); > + } else if (omap_host->flags & SDHCI_OMAP_NO_1_8_V) { > + if (omap_host->io_3_3v_support) > + reg |= CAPA_VS33; > + else > + reg |= CAPA_VS30; > + } else { > + reg |= CAPA_VS18; > + } > + > + sdhci_omap_writel(omap_host, SDHCI_OMAP_CAPA, reg); > +} > + > +static u16 sdhci_omap_calc_divisor(struct sdhci_pltfm_host *host, > + unsigned int clock) > +{ > + u16 dsor; > + > + dsor = DIV_ROUND_UP(clk_get_rate(host->clk), clock); > + if (dsor > SYSCTL_CLKD_MAX) > + dsor = SYSCTL_CLKD_MAX; > + > + return dsor; > +} > + > +static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host) > +{ > + u32 reg; > + > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL); > + reg |= SYSCTL_CEN; > + sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, reg); > +} > + > +static void sdhci_omap_stop_clock(struct sdhci_omap_host *omap_host) > +{ > + u32 reg; > + > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL); > + reg &= ~SYSCTL_CEN; > + sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, reg); > +} > + > +static void sdhci_omap_set_clock(struct sdhci_host *host, unsigned int clock) > +{ > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); > + unsigned long clkdiv; > + > + if (!clock) > + return; Are you sure you don't want to stop the clock. > + > + sdhci_omap_stop_clock(omap_host); > + > + clkdiv = sdhci_omap_calc_divisor(pltfm_host, clock); > + clkdiv = (clkdiv & SYSCTL_CLKD_MASK) << SYSCTL_CLKD_SHIFT; > + sdhci_enable_clk(host, clkdiv); > + > + sdhci_omap_start_clock(omap_host); > +} > + > +void sdhci_omap_set_power(struct sdhci_host *host, unsigned char mode, > + unsigned short vdd) > +{ > + struct mmc_host *mmc = host->mmc; > + > + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); > +} > + > +static int sdhci_omap_enable_dma(struct sdhci_host *host) > +{ > + u32 reg; > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); > + > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); > + reg |= CON_DMA_MASTER; > + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); > + > + return 0; > +} > + > +unsigned int sdhci_omap_get_min_clock(struct sdhci_host *host) > +{ > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + > + return clk_get_rate(pltfm_host->clk) / SYSCTL_CLKD_MAX; > +} > + > +static void sdhci_omap_set_bus_width(struct sdhci_host *host, int width) > +{ > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); > + u32 reg; > + > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); > + if (width == MMC_BUS_WIDTH_8) > + reg |= CON_DW8; > + else > + reg &= ~CON_DW8; > + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); > + > + sdhci_set_bus_width(host, width); > +} > + > +static void sdhci_omap_init_74_clocks(struct sdhci_host *host, u8 power_mode) > +{ > + u32 reg; > + ktime_t timeout; > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); > + > + if (omap_host->power_mode == power_mode) > + return; > + > + if (power_mode != MMC_POWER_ON) > + return; > + > + disable_irq(host->irq); > + > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); > + reg |= CON_INIT; > + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); > + sdhci_omap_writel(omap_host, SDHCI_OMAP_CMD, 0x0); > + > + /* wait 1ms */ > + timeout = ktime_add_ms(ktime_get(), MMC_TIMEOUT); > + while (!(sdhci_omap_readl(omap_host, SDHCI_OMAP_STAT) & INT_CC_EN)) { > + if (WARN_ON(ktime_after(ktime_get(), timeout))) > + return; > + usleep_range(5, 10); > + } > + > + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); > + reg &= ~CON_INIT; > + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); > + sdhci_omap_writel(omap_host, SDHCI_OMAP_STAT, INT_CC_EN); > + > + enable_irq(host->irq); > + > + omap_host->power_mode = power_mode; > +} > + > +static struct sdhci_ops sdhci_omap_ops = { > + .set_clock = sdhci_omap_set_clock, > + .set_power = sdhci_omap_set_power, > + .enable_dma = sdhci_omap_enable_dma, > + .get_max_clock = sdhci_pltfm_clk_get_max_clock, > + .get_min_clock = sdhci_omap_get_min_clock, > + .set_bus_width = sdhci_omap_set_bus_width, > + .platform_send_init_74_clocks = sdhci_omap_init_74_clocks, > + .reset = sdhci_reset, > + .set_uhs_signaling = sdhci_set_uhs_signaling, > +}; > + > +void sdhci_omap_get_of_property(struct sdhci_omap_host *omap_host) > +{ > + struct device *dev = omap_host->dev; > + struct sdhci_host *host = omap_host->host; > + struct mmc_host *mmc = host->mmc; > + > + if (device_property_read_bool(dev, "ti,dual-volt")) > + omap_host->flags |= SDHCI_OMAP_SUPPORTS_DUAL_VOLT; > + > + if (device_property_read_bool(dev, "no-1-8-v")) > + omap_host->flags |= SDHCI_OMAP_NO_1_8_V; > + > + if (device_property_read_bool(dev, "ti,non-removable")) > + mmc->caps |= MMC_CAP_NONREMOVABLE; > +} > + > +static const struct sdhci_pltfm_data sdhci_omap_pdata = { > + .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | > + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | > + SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | > + SDHCI_QUIRK_NO_HISPD_BIT | > + SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, > + .quirks2 = SDHCI_QUIRK2_NO_1_8_V | > + SDHCI_QUIRK2_ACMD23_BROKEN | > + SDHCI_QUIRK2_RSP_136_HAS_CRC, > + .ops = &sdhci_omap_ops, > +}; > + > +static const struct sdhci_omap_data dra7_data = { > + .offset = 0x200, > +}; > + > +static const struct of_device_id omap_sdhci_match[] = { > + { .compatible = "ti,dra7-sdhci", .data = &dra7_data }, > + {}, > +}; > +MODULE_DEVICE_TABLE(of, omap_sdhci_match); > + > +static int sdhci_omap_probe(struct platform_device *pdev) > +{ > + int ret; > + u32 offset; > + struct device *dev = &pdev->dev; > + struct sdhci_host *host; > + struct sdhci_pltfm_host *pltfm_host; > + struct sdhci_omap_host *omap_host; > + struct mmc_host *mmc; > + const struct of_device_id *match; > + struct sdhci_omap_data *data; > + > + match = of_match_device(omap_sdhci_match, dev); > + if (!match) > + return -EINVAL; > + > + data = (struct sdhci_omap_data *)match->data; > + if (!data) { > + dev_err(dev, "no sdhci omap data\n"); > + return -EINVAL; > + } > + > + offset = data->offset; > + > + host = sdhci_pltfm_init(pdev, &sdhci_omap_pdata, > + sizeof(*omap_host)); > + if (IS_ERR(host)) { > + dev_err(dev, "Failed sdhci_pltfm_init\n"); > + return PTR_ERR(host); > + } > + > + pltfm_host = sdhci_priv(host); > + omap_host = sdhci_pltfm_priv(pltfm_host); > + omap_host->host = host; > + omap_host->base = host->ioaddr; > + omap_host->dev = dev; > + sdhci_omap_get_of_property(omap_host); > + > + host->ioaddr += offset; > + > + mmc = host->mmc; > + ret = mmc_of_parse(mmc); > + if (ret) > + goto err_of_parse; > + > + pltfm_host->clk = devm_clk_get(dev, "fck"); > + if (IS_ERR(pltfm_host->clk)) { > + ret = PTR_ERR(pltfm_host->clk); > + goto err_of_parse; > + } > + > + ret = clk_set_rate(pltfm_host->clk, mmc->f_max); > + if (ret) { > + dev_err(dev, "failed to set clock to %d\n", mmc->f_max); > + goto err_of_parse; > + } > + > + omap_host->pbias = devm_regulator_get_optional(dev, "pbias"); > + if (IS_ERR(omap_host->pbias)) { > + ret = PTR_ERR(omap_host->pbias); > + if (ret != -ENODEV) { > + dev_err(dev, "CONFIG_REGULATOR_PBIAS not enabled??\n"); > + return ret; > + } > + dev_dbg(dev, "unable to get pbias regulator %ld\n", > + PTR_ERR(omap_host->pbias)); > + } else { > + if (regulator_is_supported_voltage(omap_host->pbias, IOV_3V3, > + IOV_3V3)) > + omap_host->io_3_3v_support = true; > + dev_vdbg(dev, "Max PBIAS support Voltage: %dmv\n", > + omap_host->io_3_3v_support ? IOV_3V3 : IOV_3V0); > + } > + omap_host->pbias_enabled = false; > + > + /* Enable main Func clock, interface clock and program SYSCONFIG */ Maybe also mention that the PM domain does those things. Out of curiousity, what happens if CONFIG_PM is not set? > + pm_runtime_enable(dev); > + ret = pm_runtime_get_sync(dev); > + if (ret < 0) { > + dev_err(dev, "pm_runtime_get_sync failed\n"); > + goto err_get_sync; The correct "undo" function for pm_runtime_get_sync() failing is pm_runtime_put_noidle() not pm_runtime_put_sync(). So: pm_runtime_put_noidle(dev); goto err_rpm_disable; > + } > + > + sdhci_omap_set_capabilities(omap_host); > + > + host->mmc_host_ops.get_ro = mmc_gpio_get_ro; > + host->mmc_host_ops.start_signal_voltage_switch = > + sdhci_omap_start_signal_voltage_switch; > + host->mmc_host_ops.set_ios = sdhci_omap_set_ios; > + > + sdhci_read_caps(host); > + host->caps |= SDHCI_CAN_DO_ADMA2; > + > + ret = sdhci_add_host(host); > + if (ret) > + goto err_get_sync; > + > + return 0; > + > +err_get_sync: It is more usual for error labels to describe what they will do rather than what failed. i.e. this would be err_put_sync: > + pm_runtime_put_sync(dev); err_rpm_disable: > + pm_runtime_disable(dev); > + > +err_of_parse: err_pltfm_free: > + sdhci_pltfm_free(pdev); > + return ret; > +} > + > +static int sdhci_omap_remove(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct sdhci_host *host = platform_get_drvdata(pdev); > + > + sdhci_remove_host(host, true); > + pm_runtime_put_sync(dev); > + pm_runtime_disable(dev); > + sdhci_pltfm_free(pdev); > + > + return 0; > +} > + > +static struct platform_driver sdhci_omap_driver = { > + .probe = sdhci_omap_probe, > + .remove = sdhci_omap_remove, > + .driver = { > + .name = "sdhci-omap", > + .of_match_table = of_match_ptr(omap_sdhci_match), Don't you need #ifdef CONFIG_OF around the table if you use of_match_ptr()? > + }, > +}; > + > +module_platform_driver(sdhci_omap_driver); > + > +MODULE_DESCRIPTION("SDHCI driver for OMAP SoCs"); > +MODULE_AUTHOR("Texas Instruments Inc."); > +MODULE_LICENSE("GPL v2"); > +MODULE_ALIAS("OMAP SDHCI Driver"); A module alias with spaces in it looks strange. Is that the intention? ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 4/5] mmc: sdhci-omap: Add OMAP SDHCI driver 2017-08-28 9:06 ` Adrian Hunter @ 2017-08-30 13:53 ` Kishon Vijay Abraham I 2017-08-31 13:02 ` Adrian Hunter 0 siblings, 1 reply; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-30 13:53 UTC (permalink / raw) To: Adrian Hunter, Ulf Hansson Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel Hi, On Monday 28 August 2017 02:36 PM, Adrian Hunter wrote: > On 21/08/17 10:41, Kishon Vijay Abraham I wrote: >> Create a new sdhci-omap driver to configure the eMMC/SD/SDIO controller >> in TI's OMAP SoCs making use of the SDHCI core library. For OMAP specific >> configurations, populate sdhci_ops with OMAP specific callbacks and use >> SDHCI quirks. >> Enable only high speed mode for both SD and eMMC here and add other >> UHS mode support later. >> >> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> > > There are a few minor comments below. > >> --- >> drivers/mmc/host/Kconfig | 12 + >> drivers/mmc/host/Makefile | 1 + >> drivers/mmc/host/sdhci-omap.c | 629 ++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 642 insertions(+) >> create mode 100644 drivers/mmc/host/sdhci-omap.c >> >> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig >> index 60f90d49e7a9..60d50843e165 100644 >> --- a/drivers/mmc/host/Kconfig >> +++ b/drivers/mmc/host/Kconfig >> @@ -899,3 +899,15 @@ config MMC_SDHCI_XENON >> This selects Marvell Xenon eMMC/SD/SDIO SDHCI. >> If you have a controller with this interface, say Y or M here. >> If unsure, say N. >> + >> +config MMC_SDHCI_OMAP >> + tristate "TI SDHCI Controller Support" >> + depends on MMC_SDHCI_PLTFM >> + help >> + This selects the Secure Digital Host Controller Interface (SDHCI) >> + support present in TI's DRA7 SOCs. The controller supports >> + SD/MMC/SDIO devices. >> + >> + If you have a controller with this interface, say Y or M here. >> + >> + If unsure, say N. >> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile >> index 8c46766c000c..33181df88a10 100644 >> --- a/drivers/mmc/host/Makefile >> +++ b/drivers/mmc/host/Makefile >> @@ -88,6 +88,7 @@ obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o >> obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o >> obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32) += sdhci-pic32.o >> obj-$(CONFIG_MMC_SDHCI_BRCMSTB) += sdhci-brcmstb.o >> +obj-$(CONFIG_MMC_SDHCI_OMAP) += sdhci-omap.o >> >> ifeq ($(CONFIG_CB710_DEBUG),y) >> CFLAGS-cb710-mmc += -DDEBUG >> diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c >> new file mode 100644 >> index 000000000000..73ee3b4a400c >> --- /dev/null >> +++ b/drivers/mmc/host/sdhci-omap.c >> @@ -0,0 +1,629 @@ >> +/** >> + * SDHCI Controller driver for TI's OMAP SoCs >> + * >> + * Copyright (C) 2017 Texas Instruments >> + * Author: Kishon Vijay Abraham I <kishon@ti.com> >> + * >> + * This program is free software: you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 of >> + * the License as published by the Free Software Foundation. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + * >> + * You should have received a copy of the GNU General Public License >> + * along with this program. If not, see <http://www.gnu.org/licenses/>. >> + */ >> + >> +#include <linux/delay.h> >> +#include <linux/mmc/slot-gpio.h> >> +#include <linux/module.h> >> +#include <linux/of.h> >> +#include <linux/of_device.h> >> +#include <linux/platform_device.h> >> +#include <linux/pm_runtime.h> >> +#include <linux/regulator/consumer.h> >> + >> +#include "sdhci-pltfm.h" >> + >> +#define SDHCI_OMAP_CON 0x12c >> +#define CON_DW8 BIT(5) >> +#define CON_DMA_MASTER BIT(20) >> +#define CON_INIT BIT(1) >> +#define CON_OD BIT(0) >> + >> +#define SDHCI_OMAP_CMD 0x20c >> + >> +#define SDHCI_OMAP_HCTL 0x228 >> +#define HCTL_SDBP BIT(8) >> +#define HCTL_SDVS_SHIFT 9 >> +#define HCTL_SDVS_MASK (0x7 << HCTL_SDVS_SHIFT) >> +#define HCTL_SDVS_33 (0x7 << HCTL_SDVS_SHIFT) >> +#define HCTL_SDVS_30 (0x6 << HCTL_SDVS_SHIFT) >> +#define HCTL_SDVS_18 (0x5 << HCTL_SDVS_SHIFT) >> + >> +#define SDHCI_OMAP_SYSCTL 0x22c >> +#define SYSCTL_CEN BIT(2) >> +#define SYSCTL_CLKD_SHIFT 6 >> +#define SYSCTL_CLKD_MASK 0x3ff >> + >> +#define SDHCI_OMAP_STAT 0x230 >> + >> +#define SDHCI_OMAP_IE 0x234 >> +#define INT_CC_EN BIT(0) >> + >> +#define SDHCI_OMAP_AC12 0x23c >> +#define AC12_V1V8_SIGEN BIT(19) >> + >> +#define SDHCI_OMAP_CAPA 0x240 >> +#define CAPA_VS33 BIT(24) >> +#define CAPA_VS30 BIT(25) >> +#define CAPA_VS18 BIT(26) >> + >> +#define MMC_TIMEOUT 1 /* 1 msec */ > > As before, SDHCI_OMAP_TIMEOUT is a better name fixed it now. > >> + >> +#define SYSCTL_CLKD_MAX 0x3FF >> + >> +#define IOV_1V8 1800000 /* 180000 uV */ >> +#define IOV_3V0 3000000 /* 300000 uV */ >> +#define IOV_3V3 3300000 /* 330000 uV */ >> + >> +struct sdhci_omap_data { >> + u32 offset; >> +}; >> + >> +struct sdhci_omap_host { >> + void __iomem *base; >> + struct device *dev; >> + struct regulator *pbias; >> + bool pbias_enabled; >> + struct sdhci_host *host; >> + unsigned int flags; >> + >> +#define SDHCI_OMAP_SUPPORTS_DUAL_VOLT BIT(0) >> +#define SDHCI_OMAP_NO_1_8_V BIT(1) >> + >> + u8 bus_mode; >> + u8 power_mode; >> + bool io_3_3v_support; >> +}; >> + >> +static inline u32 sdhci_omap_readl(struct sdhci_omap_host *host, >> + unsigned int offset) >> +{ >> + return readl(host->base + offset); >> +} >> + >> +static inline void sdhci_omap_writel(struct sdhci_omap_host *host, >> + unsigned int offset, u32 data) >> +{ >> + writel(data, host->base + offset); >> +} >> + >> +static int sdhci_omap_set_pbias(struct sdhci_omap_host *omap_host, >> + bool power_on, unsigned int iov) >> +{ >> + int ret; >> + struct device *dev = omap_host->dev; >> + >> + if (IS_ERR(omap_host->pbias)) >> + return 0; >> + >> + if (power_on) { >> + ret = regulator_set_voltage(omap_host->pbias, iov, iov); >> + if (ret) { >> + dev_err(dev, "pbias set voltage failed\n"); >> + return ret; >> + } >> + >> + if (omap_host->pbias_enabled) >> + return 0; >> + >> + ret = regulator_enable(omap_host->pbias); >> + if (ret) { >> + dev_err(dev, "pbias reg enable fail\n"); >> + return ret; >> + } >> + >> + omap_host->pbias_enabled = true; >> + } else { >> + if (!omap_host->pbias_enabled) >> + return 0; >> + >> + ret = regulator_disable(omap_host->pbias); >> + if (ret) { >> + dev_err(dev, "pbias reg disable fail\n"); >> + return ret; >> + } >> + omap_host->pbias_enabled = false; >> + } >> + >> + return 0; >> +} >> + >> +static int sdhci_omap_enable_iov(struct sdhci_omap_host *omap_host, >> + unsigned int iov) >> +{ >> + int ret; >> + struct sdhci_host *host = omap_host->host; >> + struct mmc_host *mmc = host->mmc; >> + >> + ret = sdhci_omap_set_pbias(omap_host, false, 0); >> + if (ret) >> + return ret; >> + >> + if (!IS_ERR(mmc->supply.vqmmc)) { >> + ret = regulator_set_voltage(mmc->supply.vqmmc, iov, iov); >> + if (ret) { >> + dev_err(mmc_dev(mmc), "vqmmc set voltage failed\n"); >> + return ret; >> + } >> + } >> + >> + ret = sdhci_omap_set_pbias(omap_host, true, iov); >> + if (ret) >> + return ret; >> + >> + return 0; >> +} >> + >> +static void sdhci_omap_conf_bus_power(struct sdhci_omap_host *omap_host, >> + unsigned char signal_voltage) >> +{ >> + u32 reg; >> + ktime_t timeout; >> + >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL); >> + reg &= ~HCTL_SDVS_MASK; >> + >> + if (signal_voltage == MMC_SIGNAL_VOLTAGE_180) >> + reg |= HCTL_SDVS_18; >> + else if (omap_host->io_3_3v_support) >> + reg |= HCTL_SDVS_33; >> + else >> + reg |= HCTL_SDVS_30; >> + >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, reg); >> + >> + reg |= HCTL_SDBP; >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, reg); >> + >> + /* wait 1ms */ >> + timeout = ktime_add_ms(ktime_get(), MMC_TIMEOUT); >> + while (!(sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL) & HCTL_SDBP)) { >> + if (WARN_ON(ktime_after(ktime_get(), timeout))) >> + return; >> + usleep_range(5, 10); >> + } >> +} >> + >> +static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc, >> + struct mmc_ios *ios) >> +{ >> + u32 reg; >> + int ret; >> + unsigned int iov; >> + struct sdhci_host *host = mmc_priv(mmc); >> + struct sdhci_pltfm_host *pltfm_host; >> + struct sdhci_omap_host *omap_host; >> + struct device *dev; >> + >> + pltfm_host = sdhci_priv(host); >> + omap_host = sdhci_pltfm_priv(pltfm_host); >> + dev = omap_host->dev; >> + >> + if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); >> + if (!(reg & (CAPA_VS33 | CAPA_VS30))) >> + return -EOPNOTSUPP; >> + >> + sdhci_omap_conf_bus_power(omap_host, ios->signal_voltage); >> + >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); >> + reg &= ~AC12_V1V8_SIGEN; >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg); >> + >> + if (omap_host->io_3_3v_support) >> + iov = IOV_3V3; >> + else >> + iov = IOV_3V0; >> + } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); >> + if (!(reg & CAPA_VS18)) >> + return -EOPNOTSUPP; >> + >> + sdhci_omap_conf_bus_power(omap_host, ios->signal_voltage); >> + >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); >> + reg |= AC12_V1V8_SIGEN; >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg); >> + >> + iov = IOV_1V8; >> + } else { >> + return -EOPNOTSUPP; >> + } >> + >> + ret = sdhci_omap_enable_iov(omap_host, iov); >> + if (ret) { >> + dev_err(dev, "failed to switch IO voltage to %dmV\n", iov); >> + return ret; >> + } >> + >> + dev_dbg(dev, "IO voltage switched to %dmV\n", iov); >> + return 0; >> +} >> + >> +static void sdhci_omap_set_bus_mode(struct sdhci_omap_host *omap_host, >> + unsigned int mode) >> +{ >> + u32 reg; >> + >> + if (omap_host->bus_mode == mode) >> + return; >> + >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); >> + if (mode == MMC_BUSMODE_OPENDRAIN) >> + reg |= CON_OD; >> + else >> + reg &= ~CON_OD; >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); >> + >> + omap_host->bus_mode = mode; >> +} >> + >> +void sdhci_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) >> +{ >> + struct sdhci_host *host = mmc_priv(mmc); >> + struct sdhci_pltfm_host *pltfm_host; >> + struct sdhci_omap_host *omap_host; >> + >> + pltfm_host = sdhci_priv(host); >> + omap_host = sdhci_pltfm_priv(pltfm_host); >> + >> + sdhci_omap_set_bus_mode(omap_host, ios->bus_mode); >> + sdhci_set_ios(mmc, ios); >> +} >> + >> +static void sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host) >> +{ >> + u32 reg; >> + >> + /* voltage capabilities might be set by boot loader, clear it */ >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); >> + reg &= ~(CAPA_VS18 | CAPA_VS30 | CAPA_VS33); >> + >> + if (omap_host->flags & SDHCI_OMAP_SUPPORTS_DUAL_VOLT) { >> + if (omap_host->io_3_3v_support) >> + reg |= (CAPA_VS33 | CAPA_VS18); >> + else >> + reg |= (CAPA_VS30 | CAPA_VS18); >> + } else if (omap_host->flags & SDHCI_OMAP_NO_1_8_V) { >> + if (omap_host->io_3_3v_support) >> + reg |= CAPA_VS33; >> + else >> + reg |= CAPA_VS30; >> + } else { >> + reg |= CAPA_VS18; >> + } >> + >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_CAPA, reg); >> +} >> + >> +static u16 sdhci_omap_calc_divisor(struct sdhci_pltfm_host *host, >> + unsigned int clock) >> +{ >> + u16 dsor; >> + >> + dsor = DIV_ROUND_UP(clk_get_rate(host->clk), clock); >> + if (dsor > SYSCTL_CLKD_MAX) >> + dsor = SYSCTL_CLKD_MAX; >> + >> + return dsor; >> +} >> + >> +static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host) >> +{ >> + u32 reg; >> + >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL); >> + reg |= SYSCTL_CEN; >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, reg); >> +} >> + >> +static void sdhci_omap_stop_clock(struct sdhci_omap_host *omap_host) >> +{ >> + u32 reg; >> + >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL); >> + reg &= ~SYSCTL_CEN; >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, reg); >> +} >> + >> +static void sdhci_omap_set_clock(struct sdhci_host *host, unsigned int clock) >> +{ >> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); >> + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); >> + unsigned long clkdiv; >> + >> + if (!clock) >> + return; > > Are you sure you don't want to stop the clock. There is never a case where the MMC core sends a request to stop the clock. Maybe this check is not required at all. > >> + >> + sdhci_omap_stop_clock(omap_host); >> + >> + clkdiv = sdhci_omap_calc_divisor(pltfm_host, clock); >> + clkdiv = (clkdiv & SYSCTL_CLKD_MASK) << SYSCTL_CLKD_SHIFT; >> + sdhci_enable_clk(host, clkdiv); >> + >> + sdhci_omap_start_clock(omap_host); >> +} >> + >> +void sdhci_omap_set_power(struct sdhci_host *host, unsigned char mode, >> + unsigned short vdd) >> +{ >> + struct mmc_host *mmc = host->mmc; >> + >> + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); >> +} >> + >> +static int sdhci_omap_enable_dma(struct sdhci_host *host) >> +{ >> + u32 reg; >> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); >> + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); >> + >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); >> + reg |= CON_DMA_MASTER; >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); >> + >> + return 0; >> +} >> + >> +unsigned int sdhci_omap_get_min_clock(struct sdhci_host *host) >> +{ >> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); >> + >> + return clk_get_rate(pltfm_host->clk) / SYSCTL_CLKD_MAX; >> +} >> + >> +static void sdhci_omap_set_bus_width(struct sdhci_host *host, int width) >> +{ >> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); >> + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); >> + u32 reg; >> + >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); >> + if (width == MMC_BUS_WIDTH_8) >> + reg |= CON_DW8; >> + else >> + reg &= ~CON_DW8; >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); >> + >> + sdhci_set_bus_width(host, width); >> +} >> + >> +static void sdhci_omap_init_74_clocks(struct sdhci_host *host, u8 power_mode) >> +{ >> + u32 reg; >> + ktime_t timeout; >> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); >> + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); >> + >> + if (omap_host->power_mode == power_mode) >> + return; >> + >> + if (power_mode != MMC_POWER_ON) >> + return; >> + >> + disable_irq(host->irq); >> + >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); >> + reg |= CON_INIT; >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_CMD, 0x0); >> + >> + /* wait 1ms */ >> + timeout = ktime_add_ms(ktime_get(), MMC_TIMEOUT); >> + while (!(sdhci_omap_readl(omap_host, SDHCI_OMAP_STAT) & INT_CC_EN)) { >> + if (WARN_ON(ktime_after(ktime_get(), timeout))) >> + return; >> + usleep_range(5, 10); >> + } >> + >> + reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); >> + reg &= ~CON_INIT; >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); >> + sdhci_omap_writel(omap_host, SDHCI_OMAP_STAT, INT_CC_EN); >> + >> + enable_irq(host->irq); >> + >> + omap_host->power_mode = power_mode; >> +} >> + >> +static struct sdhci_ops sdhci_omap_ops = { >> + .set_clock = sdhci_omap_set_clock, >> + .set_power = sdhci_omap_set_power, >> + .enable_dma = sdhci_omap_enable_dma, >> + .get_max_clock = sdhci_pltfm_clk_get_max_clock, >> + .get_min_clock = sdhci_omap_get_min_clock, >> + .set_bus_width = sdhci_omap_set_bus_width, >> + .platform_send_init_74_clocks = sdhci_omap_init_74_clocks, >> + .reset = sdhci_reset, >> + .set_uhs_signaling = sdhci_set_uhs_signaling, >> +}; >> + >> +void sdhci_omap_get_of_property(struct sdhci_omap_host *omap_host) >> +{ >> + struct device *dev = omap_host->dev; >> + struct sdhci_host *host = omap_host->host; >> + struct mmc_host *mmc = host->mmc; >> + >> + if (device_property_read_bool(dev, "ti,dual-volt")) >> + omap_host->flags |= SDHCI_OMAP_SUPPORTS_DUAL_VOLT; >> + >> + if (device_property_read_bool(dev, "no-1-8-v")) >> + omap_host->flags |= SDHCI_OMAP_NO_1_8_V; >> + >> + if (device_property_read_bool(dev, "ti,non-removable")) >> + mmc->caps |= MMC_CAP_NONREMOVABLE; >> +} >> + >> +static const struct sdhci_pltfm_data sdhci_omap_pdata = { >> + .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | >> + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | >> + SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | >> + SDHCI_QUIRK_NO_HISPD_BIT | >> + SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, >> + .quirks2 = SDHCI_QUIRK2_NO_1_8_V | >> + SDHCI_QUIRK2_ACMD23_BROKEN | >> + SDHCI_QUIRK2_RSP_136_HAS_CRC, >> + .ops = &sdhci_omap_ops, >> +}; >> + >> +static const struct sdhci_omap_data dra7_data = { >> + .offset = 0x200, >> +}; >> + >> +static const struct of_device_id omap_sdhci_match[] = { >> + { .compatible = "ti,dra7-sdhci", .data = &dra7_data }, >> + {}, >> +}; >> +MODULE_DEVICE_TABLE(of, omap_sdhci_match); >> + >> +static int sdhci_omap_probe(struct platform_device *pdev) >> +{ >> + int ret; >> + u32 offset; >> + struct device *dev = &pdev->dev; >> + struct sdhci_host *host; >> + struct sdhci_pltfm_host *pltfm_host; >> + struct sdhci_omap_host *omap_host; >> + struct mmc_host *mmc; >> + const struct of_device_id *match; >> + struct sdhci_omap_data *data; >> + >> + match = of_match_device(omap_sdhci_match, dev); >> + if (!match) >> + return -EINVAL; >> + >> + data = (struct sdhci_omap_data *)match->data; >> + if (!data) { >> + dev_err(dev, "no sdhci omap data\n"); >> + return -EINVAL; >> + } >> + >> + offset = data->offset; >> + >> + host = sdhci_pltfm_init(pdev, &sdhci_omap_pdata, >> + sizeof(*omap_host)); >> + if (IS_ERR(host)) { >> + dev_err(dev, "Failed sdhci_pltfm_init\n"); >> + return PTR_ERR(host); >> + } >> + >> + pltfm_host = sdhci_priv(host); >> + omap_host = sdhci_pltfm_priv(pltfm_host); >> + omap_host->host = host; >> + omap_host->base = host->ioaddr; >> + omap_host->dev = dev; >> + sdhci_omap_get_of_property(omap_host); >> + >> + host->ioaddr += offset; >> + >> + mmc = host->mmc; >> + ret = mmc_of_parse(mmc); >> + if (ret) >> + goto err_of_parse; >> + >> + pltfm_host->clk = devm_clk_get(dev, "fck"); >> + if (IS_ERR(pltfm_host->clk)) { >> + ret = PTR_ERR(pltfm_host->clk); >> + goto err_of_parse; >> + } >> + >> + ret = clk_set_rate(pltfm_host->clk, mmc->f_max); >> + if (ret) { >> + dev_err(dev, "failed to set clock to %d\n", mmc->f_max); >> + goto err_of_parse; >> + } >> + >> + omap_host->pbias = devm_regulator_get_optional(dev, "pbias"); >> + if (IS_ERR(omap_host->pbias)) { >> + ret = PTR_ERR(omap_host->pbias); >> + if (ret != -ENODEV) { >> + dev_err(dev, "CONFIG_REGULATOR_PBIAS not enabled??\n"); >> + return ret; >> + } >> + dev_dbg(dev, "unable to get pbias regulator %ld\n", >> + PTR_ERR(omap_host->pbias)); >> + } else { >> + if (regulator_is_supported_voltage(omap_host->pbias, IOV_3V3, >> + IOV_3V3)) >> + omap_host->io_3_3v_support = true; >> + dev_vdbg(dev, "Max PBIAS support Voltage: %dmv\n", >> + omap_host->io_3_3v_support ? IOV_3V3 : IOV_3V0); >> + } >> + omap_host->pbias_enabled = false; >> + >> + /* Enable main Func clock, interface clock and program SYSCONFIG */ > > Maybe also mention that the PM domain does those things. Out of curiousity, > what happens if CONFIG_PM is not set? I think then most of the peripherals will depend on bootloader to enable the clocks if CONFIG_PM is not set. > >> + pm_runtime_enable(dev); >> + ret = pm_runtime_get_sync(dev); >> + if (ret < 0) { >> + dev_err(dev, "pm_runtime_get_sync failed\n"); >> + goto err_get_sync; > > The correct "undo" function for pm_runtime_get_sync() failing is > pm_runtime_put_noidle() not pm_runtime_put_sync(). So: yeah right! Missed that. > > pm_runtime_put_noidle(dev); > goto err_rpm_disable; > >> + } >> + >> + sdhci_omap_set_capabilities(omap_host); >> + >> + host->mmc_host_ops.get_ro = mmc_gpio_get_ro; >> + host->mmc_host_ops.start_signal_voltage_switch = >> + sdhci_omap_start_signal_voltage_switch; >> + host->mmc_host_ops.set_ios = sdhci_omap_set_ios; >> + >> + sdhci_read_caps(host); >> + host->caps |= SDHCI_CAN_DO_ADMA2; >> + >> + ret = sdhci_add_host(host); >> + if (ret) >> + goto err_get_sync; >> + >> + return 0; >> + >> +err_get_sync: > > It is more usual for error labels to describe what they will do rather than > what failed. i.e. this would be err_put_sync: > >> + pm_runtime_put_sync(dev); > > err_rpm_disable: > >> + pm_runtime_disable(dev); >> + >> +err_of_parse: > > err_pltfm_free: > >> + sdhci_pltfm_free(pdev); >> + return ret; >> +} >> + >> +static int sdhci_omap_remove(struct platform_device *pdev) >> +{ >> + struct device *dev = &pdev->dev; >> + struct sdhci_host *host = platform_get_drvdata(pdev); >> + >> + sdhci_remove_host(host, true); >> + pm_runtime_put_sync(dev); >> + pm_runtime_disable(dev); >> + sdhci_pltfm_free(pdev); >> + >> + return 0; >> +} >> + >> +static struct platform_driver sdhci_omap_driver = { >> + .probe = sdhci_omap_probe, >> + .remove = sdhci_omap_remove, >> + .driver = { >> + .name = "sdhci-omap", >> + .of_match_table = of_match_ptr(omap_sdhci_match), > > Don't you need #ifdef CONFIG_OF around the table if you use of_match_ptr()? yeah. I think I'll remove of_match_ptr here and make the driver depend on OF. > >> + }, >> +}; >> + >> +module_platform_driver(sdhci_omap_driver); >> + >> +MODULE_DESCRIPTION("SDHCI driver for OMAP SoCs"); >> +MODULE_AUTHOR("Texas Instruments Inc."); >> +MODULE_LICENSE("GPL v2"); >> +MODULE_ALIAS("OMAP SDHCI Driver"); > > A module alias with spaces in it looks strange. Is that the intention? No. Will fix it. Thanks Kishon ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 4/5] mmc: sdhci-omap: Add OMAP SDHCI driver 2017-08-30 13:53 ` Kishon Vijay Abraham I @ 2017-08-31 13:02 ` Adrian Hunter 2017-09-05 8:57 ` Kishon Vijay Abraham I 0 siblings, 1 reply; 31+ messages in thread From: Adrian Hunter @ 2017-08-31 13:02 UTC (permalink / raw) To: Kishon Vijay Abraham I, Ulf Hansson Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel On 30/08/17 16:53, Kishon Vijay Abraham I wrote: > On Monday 28 August 2017 02:36 PM, Adrian Hunter wrote: >> On 21/08/17 10:41, Kishon Vijay Abraham I wrote: >>> + >>> +static void sdhci_omap_set_clock(struct sdhci_host *host, unsigned int clock) >>> +{ >>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); >>> + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); >>> + unsigned long clkdiv; >>> + >>> + if (!clock) >>> + return; >> >> Are you sure you don't want to stop the clock. > > There is never a case where the MMC core sends a request to stop the clock. > Maybe this check is not required at all. It does when voltage switching e.g. mmc_set_uhs_voltage(), but host drivers should support the possibility anyway. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 4/5] mmc: sdhci-omap: Add OMAP SDHCI driver 2017-08-31 13:02 ` Adrian Hunter @ 2017-09-05 8:57 ` Kishon Vijay Abraham I 0 siblings, 0 replies; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-09-05 8:57 UTC (permalink / raw) To: Adrian Hunter, Ulf Hansson Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel Hi, On Thursday 31 August 2017 06:32 PM, Adrian Hunter wrote: > On 30/08/17 16:53, Kishon Vijay Abraham I wrote: >> On Monday 28 August 2017 02:36 PM, Adrian Hunter wrote: >>> On 21/08/17 10:41, Kishon Vijay Abraham I wrote: >>>> + >>>> +static void sdhci_omap_set_clock(struct sdhci_host *host, unsigned int clock) >>>> +{ >>>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); >>>> + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); >>>> + unsigned long clkdiv; >>>> + >>>> + if (!clock) >>>> + return; >>> >>> Are you sure you don't want to stop the clock. >> >> There is never a case where the MMC core sends a request to stop the clock. >> Maybe this check is not required at all. > > It does when voltage switching e.g. mmc_set_uhs_voltage(), but host drivers > should support the possibility anyway. Indeed! Will fix it and send a new revision once everyone agrees on the dt binding. Thanks Kishon ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 5/5] MAINTAINERS: Add TI OMAP SDHCI Maintainer 2017-08-21 7:41 [PATCH 0/5] mmc: Add OMAP SDHCI driver Kishon Vijay Abraham I ` (3 preceding siblings ...) 2017-08-21 7:41 ` [PATCH 4/5] mmc: sdhci-omap: Add OMAP SDHCI driver Kishon Vijay Abraham I @ 2017-08-21 7:41 ` Kishon Vijay Abraham I 2017-08-28 9:07 ` Adrian Hunter 4 siblings, 1 reply; 31+ messages in thread From: Kishon Vijay Abraham I @ 2017-08-21 7:41 UTC (permalink / raw) To: Ulf Hansson, Adrian Hunter Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel, Kishon Vijay Abraham I Add Maintainer for the TI OMAP SDHCI driver. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 44cb004c765d..c9871351c16f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11777,6 +11777,12 @@ L: linux-mmc@vger.kernel.org S: Maintained F: drivers/mmc/host/sdhci-spear.c +SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) TI OMAP DRIVER +M: Kishon Vijay Abraham I <kishon@ti.com> +L: linux-mmc@vger.kernel.org +S: Maintained +F: drivers/mmc/host/sdhci-omap.c + SECURE ENCRYPTING DEVICE (SED) OPAL DRIVER M: Scott Bauer <scott.bauer@intel.com> M: Jonathan Derrick <jonathan.derrick@intel.com> -- 2.11.0 ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 5/5] MAINTAINERS: Add TI OMAP SDHCI Maintainer 2017-08-21 7:41 ` [PATCH 5/5] MAINTAINERS: Add TI OMAP SDHCI Maintainer Kishon Vijay Abraham I @ 2017-08-28 9:07 ` Adrian Hunter 0 siblings, 0 replies; 31+ messages in thread From: Adrian Hunter @ 2017-08-28 9:07 UTC (permalink / raw) To: Kishon Vijay Abraham I, Ulf Hansson Cc: Rob Herring, Tony Lindgren, Sekhar Nori, Russell King, Ravikumar Kattekola, linux-mmc, devicetree, linux-kernel, linux-omap, linux-arm-kernel On 21/08/17 10:41, Kishon Vijay Abraham I wrote: > Add Maintainer for the TI OMAP SDHCI driver. > > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> > --- > MAINTAINERS | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/MAINTAINERS b/MAINTAINERS > index 44cb004c765d..c9871351c16f 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -11777,6 +11777,12 @@ L: linux-mmc@vger.kernel.org > S: Maintained > F: drivers/mmc/host/sdhci-spear.c > > +SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) TI OMAP DRIVER > +M: Kishon Vijay Abraham I <kishon@ti.com> > +L: linux-mmc@vger.kernel.org > +S: Maintained > +F: drivers/mmc/host/sdhci-omap.c > + > SECURE ENCRYPTING DEVICE (SED) OPAL DRIVER > M: Scott Bauer <scott.bauer@intel.com> > M: Jonathan Derrick <jonathan.derrick@intel.com> > ^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2017-09-05 16:51 UTC | newest] Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-08-21 7:41 [PATCH 0/5] mmc: Add OMAP SDHCI driver Kishon Vijay Abraham I 2017-08-21 7:41 ` [PATCH 1/5] mmc: sdhci: Tidy reading 136-bit responses Kishon Vijay Abraham I 2017-08-30 13:13 ` Ulf Hansson 2017-08-21 7:41 ` [PATCH 2/5] mmc: sdhci: Add quirk to indicate MMC_RSP_136 has CRC Kishon Vijay Abraham I 2017-08-28 7:57 ` Adrian Hunter 2017-08-30 13:13 ` Ulf Hansson 2017-08-21 7:41 ` [PATCH 3/5] dt-bindings: ti-omap-hsmmc: Document new compatible for sdhci omap Kishon Vijay Abraham I 2017-08-21 14:21 ` Tony Lindgren 2017-08-22 13:39 ` [PATCH v2 3/5] dt-bindings: sdhci-omap: Add bindings for the sdhci-omap controller Kishon Vijay Abraham I 2017-08-22 17:39 ` Tony Lindgren 2017-08-23 5:42 ` [PATCH v3 " Kishon Vijay Abraham I 2017-08-23 13:07 ` Ulf Hansson 2017-08-23 13:56 ` Kishon Vijay Abraham I 2017-08-24 11:29 ` Ulf Hansson 2017-08-29 11:20 ` Kishon Vijay Abraham I 2017-08-29 11:50 ` Sebastian Reichel 2017-08-29 13:58 ` Tony Lindgren 2017-08-29 14:43 ` Tony Lindgren 2017-08-29 17:09 ` Rob Herring 2017-08-29 17:39 ` Tony Lindgren 2017-09-05 8:52 ` Kishon Vijay Abraham I 2017-09-05 16:51 ` Tony Lindgren 2017-08-29 17:11 ` Rob Herring 2017-09-05 8:53 ` Kishon Vijay Abraham I 2017-08-21 7:41 ` [PATCH 4/5] mmc: sdhci-omap: Add OMAP SDHCI driver Kishon Vijay Abraham I 2017-08-28 9:06 ` Adrian Hunter 2017-08-30 13:53 ` Kishon Vijay Abraham I 2017-08-31 13:02 ` Adrian Hunter 2017-09-05 8:57 ` Kishon Vijay Abraham I 2017-08-21 7:41 ` [PATCH 5/5] MAINTAINERS: Add TI OMAP SDHCI Maintainer Kishon Vijay Abraham I 2017-08-28 9:07 ` Adrian Hunter
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).