Skip to content

Commit

Permalink
pci: rockchip: Add pcie port initialized flag
Browse files Browse the repository at this point in the history
rk_pcie_port_initialized can be used to check if rockchip pcie port
initialization has been done (either successfully or failed). This
is needed for synchronization Rockpro64 sdio0 driver loading which
seems to make pcie training unstable if done too early.
  • Loading branch information
nuumio authored and ayufan committed Mar 19, 2019
1 parent d7ab0c3 commit d181c73
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 3 deletions.
7 changes: 7 additions & 0 deletions Documentation/kernel-parameters.txt
Expand Up @@ -3501,6 +3501,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
rhash_entries= [KNL,NET]
Set number of hash buckets for route cache

rkdwmmc_defer_time=
Minimum time in ms to wait for Rockchip pcie port to get initialized
and to defer Rockchip dw_mmc probe. This is a workaround for
Rockpro64 sdio0 and pcie conflict. Only enabled with
CONFIG_PCIE_ROCKCHIP.
Default value is 2000.

ro [KNL] Mount root device read-only on boot

rockchip.usb_uart
Expand Down
3 changes: 2 additions & 1 deletion arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts
Expand Up @@ -778,7 +778,8 @@
pinctrl-names = "default";
pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
sd-uhs-sdr104;
status = "disabled";
status = "okay";
defer_pcie = <2000>;
};

&sdhci {
Expand Down
28 changes: 27 additions & 1 deletion drivers/mmc/host/dw_mmc-rockchip.c
Expand Up @@ -6,7 +6,7 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/

#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
Expand Down Expand Up @@ -202,10 +202,16 @@ static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
return ret;
}

#ifdef CONFIG_PCIE_ROCKCHIP
extern bool rk_pcie_port_initialized;
static s64 defer_start = 0, elapsed = 0;
#endif

static int dw_mci_rk3288_parse_dt(struct dw_mci *host)
{
struct device_node *np = host->dev->of_node;
struct dw_mci_rockchip_priv_data *priv;
int defer_pcie;

priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
Expand All @@ -223,6 +229,26 @@ static int dw_mci_rk3288_parse_dt(struct dw_mci *host)
if (IS_ERR(priv->sample_clk))
dev_dbg(host->dev, "ciu_sample not available\n");

#ifdef CONFIG_PCIE_ROCKCHIP
if (of_property_read_u32(np, "defer_pcie", &defer_pcie))
defer_pcie = 0;

if (defer_pcie > 0) {
if (!rk_pcie_port_initialized) {
if (defer_start == 0)
defer_start = ktime_to_ms(ktime_get());
elapsed = ktime_to_ms(ktime_get()) - defer_start;
if (elapsed <= defer_pcie) {
dev_info(host->dev, "deferring for a max of %dms while pcie port initializes. Waited %lldms so far.\n", defer_pcie, elapsed);
return -EPROBE_DEFER;
} else
dev_info(host->dev, "probe defer timed out waiting for pcie init, continuing...\n");
} else {
dev_info(host->dev, "detected pcie initialized, continuing...\n");
}
}
#endif

host->priv = priv;

return 0;
Expand Down
23 changes: 22 additions & 1 deletion drivers/mmc/host/dw_mmc.c
Expand Up @@ -3182,6 +3182,13 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
if (!pdata)
return ERR_PTR(-ENOMEM);

/* find reset controller when exist */
pdata->rstc = devm_reset_control_get_optional(dev, NULL);
if (IS_ERR(pdata->rstc)) {
if (PTR_ERR(pdata->rstc) == -EPROBE_DEFER)
return ERR_PTR(-EPROBE_DEFER);
}

/* find out number of slots supported */
if (of_property_read_u32(dev->of_node, "num-slots",
&pdata->num_slots)) {
Expand Down Expand Up @@ -3262,7 +3269,9 @@ int dw_mci_probe(struct dw_mci *host)

if (!host->pdata) {
host->pdata = dw_mci_parse_dt(host);
if (IS_ERR(host->pdata)) {
if (PTR_ERR(host->pdata) == -EPROBE_DEFER) {
return -EPROBE_DEFER;
} else if (IS_ERR(host->pdata)) {
dev_err(host->dev, "platform data not available\n");
return -EINVAL;
}
Expand Down Expand Up @@ -3331,6 +3340,12 @@ int dw_mci_probe(struct dw_mci *host)
}
}

if (!IS_ERR(host->pdata->rstc)) {
reset_control_assert(host->pdata->rstc);
usleep_range(10, 50);
reset_control_deassert(host->pdata->rstc);
}

setup_timer(&host->cmd11_timer,
dw_mci_cmd11_timer, (unsigned long)host);

Expand Down Expand Up @@ -3484,6 +3499,9 @@ int dw_mci_probe(struct dw_mci *host)
if (host->use_dma && host->dma_ops->exit)
host->dma_ops->exit(host);

if (!IS_ERR(host->pdata->rstc))
reset_control_assert(host->pdata->rstc);

err_clk_ciu:
if (!IS_ERR(host->ciu_clk))
clk_disable_unprepare(host->ciu_clk);
Expand Down Expand Up @@ -3516,6 +3534,9 @@ void dw_mci_remove(struct dw_mci *host)
if (host->use_dma && host->dma_ops->exit)
host->dma_ops->exit(host);

if (!IS_ERR(host->pdata->rstc))
reset_control_assert(host->pdata->rstc);

if (!IS_ERR(host->ciu_clk))
clk_disable_unprepare(host->ciu_clk);

Expand Down
5 changes: 5 additions & 0 deletions drivers/pci/host/pcie-rockchip.c
Expand Up @@ -1508,6 +1508,9 @@ static const struct attribute_group pcie_attr_group = {
.attrs = pcie_attrs,
};

bool rk_pcie_port_initialized = false;
EXPORT_SYMBOL(rk_pcie_port_initialized);

static int rockchip_pcie_probe(struct platform_device *pdev)
{
struct rockchip_pcie *rockchip;
Expand Down Expand Up @@ -1634,6 +1637,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
goto err_probe_dma;
}

rk_pcie_port_initialized = true;
return 0;

err_probe_dma:
Expand All @@ -1657,6 +1661,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
err_aclk_perf_pcie:
clk_disable_unprepare(rockchip->aclk_pcie);
err_aclk_pcie:
rk_pcie_port_initialized = true;
return err;
}

Expand Down
2 changes: 2 additions & 0 deletions include/linux/mmc/dw_mmc.h
Expand Up @@ -17,6 +17,7 @@
#include <linux/scatterlist.h>
#include <linux/mmc/core.h>
#include <linux/dmaengine.h>
#include <linux/reset.h>

#define MAX_MCI_SLOTS 2

Expand Down Expand Up @@ -280,6 +281,7 @@ struct dw_mci_board {
/* delay in mS before detecting cards after interrupt */
u32 detect_delay_ms;

struct reset_control *rstc;
struct dw_mci_dma_ops *dma_ops;
struct dma_pdata *data;
};
Expand Down

0 comments on commit d181c73

Please sign in to comment.