diff options
author | Richard Zhu <hongxing.zhu@nxp.com> | 2017-11-15 12:57:23 +0800 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:29:14 +0800 |
commit | 9c17d58c0277702721f4b875b0fd76b0d2009a99 (patch) | |
tree | 056ee643fa8a744586d48262f7ec6ac206f01573 /drivers/pci | |
parent | beedb539728326f9e14d41ad955cfe66aec3aa3f (diff) |
MLK-16836 PCI: imx: add the bus freq sysfile interface
To support the bus freq power saving mode, add the
sysfile interface.
request bus high: echo 1 > /sys/devices/platform/xxxxxxxx.pcie/bus_freq
release bus high: echo 1 > /sys/devices/platform/xxxxxxxx.pcie/bus_freq
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/dwc/pci-imx6.c | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index 479c3015c9f5..76fa24f6f134 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -675,7 +675,6 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) if (gpio_is_valid(imx6_pcie->power_on_gpio)) gpio_set_value_cansleep(imx6_pcie->power_on_gpio, 1); - request_bus_freq(BUS_FREQ_HIGH); ret = clk_prepare_enable(imx6_pcie->pcie); if (ret) { dev_err(dev, "unable to enable pcie clock\n"); @@ -1265,8 +1264,6 @@ static void pci_imx_clk_disable(struct device *dev) clk_disable_unprepare(imx6_pcie->pcie_inbound_axi); break; } - - release_bus_freq(BUS_FREQ_HIGH); } static void pci_imx_ltssm_enable(struct device *dev) @@ -1593,13 +1590,34 @@ imx_pcie_memw_size(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t imx_pcie_bus_freq(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + u32 bus_freq; + + ret = sscanf(buf, "%x\n", &bus_freq); + if (ret != 1) + return -EINVAL; + if (bus_freq) { + dev_info(dev, "pcie request bus freq high.\n"); + request_bus_freq(BUS_FREQ_HIGH); + } else { + dev_info(dev, "pcie release bus freq high.\n"); + release_bus_freq(BUS_FREQ_HIGH); + } + + return count; +} + static DEVICE_ATTR(memw_info, S_IRUGO, imx_pcie_memw_info, NULL); static DEVICE_ATTR(memw_start_set, S_IWUSR, NULL, imx_pcie_memw_start); static DEVICE_ATTR(memw_size_set, S_IWUSR, NULL, imx_pcie_memw_size); static DEVICE_ATTR(ep_bar0_addr, S_IWUSR | S_IRUGO, imx_pcie_bar0_addr_info, imx_pcie_bar0_addr_start); +static DEVICE_ATTR(bus_freq, 0200, NULL, imx_pcie_bus_freq); -static struct attribute *imx_pcie_attrs[] = { +static struct attribute *imx_pcie_ep_attrs[] = { /* * The start address, and the limitation (64KB ~ (16MB - 1MB)) * of the ddr mem window reserved by RC, and used for EP to access. @@ -1612,8 +1630,13 @@ static struct attribute *imx_pcie_attrs[] = { NULL }; +static struct attribute *imx_pcie_rc_attrs[] = { + &dev_attr_bus_freq.attr, + NULL +}; + static struct attribute_group imx_pcie_attrgroup = { - .attrs = imx_pcie_attrs, + .attrs = imx_pcie_ep_attrs, }; static void imx6_pcie_setup_ep(struct dw_pcie *pci) @@ -2301,6 +2324,12 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) dev_info(dev, "pcie ep: Data transfer is failed.\n"); } /* end of self io test. */ } else { + /* add attributes for bus freq */ + imx_pcie_attrgroup.attrs = imx_pcie_rc_attrs; + ret = sysfs_create_group(&pdev->dev.kobj, &imx_pcie_attrgroup); + if (ret) + return -EINVAL; + ret = imx6_add_pcie_port(imx6_pcie, pdev); if (ret < 0) return ret; |