brintos

brintos / linux-shallow public Read only

0
0
Text · 10.9 KiB · 7a11c61 Raw
451 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * PCIe host controller driver for HiSilicon STB SoCs4 *5 * Copyright (C) 2016-2017 HiSilicon Co., Ltd. http://www.hisilicon.com6 *7 * Authors: Ruqiang Ju <juruqiang@hisilicon.com>8 *          Jianguo Sun <sunjianguo1@huawei.com>9 */10 11#include <linux/clk.h>12#include <linux/delay.h>13#include <linux/gpio/consumer.h>14#include <linux/interrupt.h>15#include <linux/kernel.h>16#include <linux/module.h>17#include <linux/of.h>18#include <linux/pci.h>19#include <linux/phy/phy.h>20#include <linux/platform_device.h>21#include <linux/resource.h>22#include <linux/reset.h>23 24#include "pcie-designware.h"25 26#define to_histb_pcie(x)	dev_get_drvdata((x)->dev)27 28#define PCIE_SYS_CTRL0			0x000029#define PCIE_SYS_CTRL1			0x000430#define PCIE_SYS_CTRL7			0x001C31#define PCIE_SYS_CTRL13			0x003432#define PCIE_SYS_CTRL15			0x003C33#define PCIE_SYS_CTRL16			0x004034#define PCIE_SYS_CTRL17			0x004435 36#define PCIE_SYS_STAT0			0x010037#define PCIE_SYS_STAT4			0x011038 39#define PCIE_RDLH_LINK_UP		BIT(5)40#define PCIE_XMLH_LINK_UP		BIT(15)41#define PCIE_ELBI_SLV_DBI_ENABLE	BIT(21)42#define PCIE_APP_LTSSM_ENABLE		BIT(11)43 44#define PCIE_DEVICE_TYPE_MASK		GENMASK(31, 28)45#define PCIE_WM_EP			046#define PCIE_WM_LEGACY			BIT(1)47#define PCIE_WM_RC			BIT(30)48 49#define PCIE_LTSSM_STATE_MASK		GENMASK(5, 0)50#define PCIE_LTSSM_STATE_ACTIVE		0x1151 52struct histb_pcie {53	struct dw_pcie *pci;54	struct clk *aux_clk;55	struct clk *pipe_clk;56	struct clk *sys_clk;57	struct clk *bus_clk;58	struct phy *phy;59	struct reset_control *soft_reset;60	struct reset_control *sys_reset;61	struct reset_control *bus_reset;62	void __iomem *ctrl;63	struct gpio_desc *reset_gpio;64	struct regulator *vpcie;65};66 67static u32 histb_pcie_readl(struct histb_pcie *histb_pcie, u32 reg)68{69	return readl(histb_pcie->ctrl + reg);70}71 72static void histb_pcie_writel(struct histb_pcie *histb_pcie, u32 reg, u32 val)73{74	writel(val, histb_pcie->ctrl + reg);75}76 77static void histb_pcie_dbi_w_mode(struct dw_pcie_rp *pp, bool enable)78{79	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);80	struct histb_pcie *hipcie = to_histb_pcie(pci);81	u32 val;82 83	val = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0);84	if (enable)85		val |= PCIE_ELBI_SLV_DBI_ENABLE;86	else87		val &= ~PCIE_ELBI_SLV_DBI_ENABLE;88	histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, val);89}90 91static void histb_pcie_dbi_r_mode(struct dw_pcie_rp *pp, bool enable)92{93	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);94	struct histb_pcie *hipcie = to_histb_pcie(pci);95	u32 val;96 97	val = histb_pcie_readl(hipcie, PCIE_SYS_CTRL1);98	if (enable)99		val |= PCIE_ELBI_SLV_DBI_ENABLE;100	else101		val &= ~PCIE_ELBI_SLV_DBI_ENABLE;102	histb_pcie_writel(hipcie, PCIE_SYS_CTRL1, val);103}104 105static u32 histb_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base,106			       u32 reg, size_t size)107{108	u32 val;109 110	histb_pcie_dbi_r_mode(&pci->pp, true);111	dw_pcie_read(base + reg, size, &val);112	histb_pcie_dbi_r_mode(&pci->pp, false);113 114	return val;115}116 117static void histb_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base,118				 u32 reg, size_t size, u32 val)119{120	histb_pcie_dbi_w_mode(&pci->pp, true);121	dw_pcie_write(base + reg, size, val);122	histb_pcie_dbi_w_mode(&pci->pp, false);123}124 125static int histb_pcie_rd_own_conf(struct pci_bus *bus, unsigned int devfn,126				  int where, int size, u32 *val)127{128	struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata);129 130	if (PCI_SLOT(devfn))131		return PCIBIOS_DEVICE_NOT_FOUND;132 133	*val = dw_pcie_read_dbi(pci, where, size);134	return PCIBIOS_SUCCESSFUL;135}136 137static int histb_pcie_wr_own_conf(struct pci_bus *bus, unsigned int devfn,138				  int where, int size, u32 val)139{140	struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata);141 142	if (PCI_SLOT(devfn))143		return PCIBIOS_DEVICE_NOT_FOUND;144 145	dw_pcie_write_dbi(pci, where, size, val);146	return PCIBIOS_SUCCESSFUL;147}148 149static struct pci_ops histb_pci_ops = {150	.read = histb_pcie_rd_own_conf,151	.write = histb_pcie_wr_own_conf,152};153 154static int histb_pcie_link_up(struct dw_pcie *pci)155{156	struct histb_pcie *hipcie = to_histb_pcie(pci);157	u32 regval;158	u32 status;159 160	regval = histb_pcie_readl(hipcie, PCIE_SYS_STAT0);161	status = histb_pcie_readl(hipcie, PCIE_SYS_STAT4);162	status &= PCIE_LTSSM_STATE_MASK;163	if ((regval & PCIE_XMLH_LINK_UP) && (regval & PCIE_RDLH_LINK_UP) &&164	    (status == PCIE_LTSSM_STATE_ACTIVE))165		return 1;166 167	return 0;168}169 170static int histb_pcie_start_link(struct dw_pcie *pci)171{172	struct histb_pcie *hipcie = to_histb_pcie(pci);173	u32 regval;174 175	/* assert LTSSM enable */176	regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL7);177	regval |= PCIE_APP_LTSSM_ENABLE;178	histb_pcie_writel(hipcie, PCIE_SYS_CTRL7, regval);179 180	return 0;181}182 183static int histb_pcie_host_init(struct dw_pcie_rp *pp)184{185	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);186	struct histb_pcie *hipcie = to_histb_pcie(pci);187	u32 regval;188 189	pp->bridge->ops = &histb_pci_ops;190 191	/* PCIe RC work mode */192	regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0);193	regval &= ~PCIE_DEVICE_TYPE_MASK;194	regval |= PCIE_WM_RC;195	histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, regval);196 197	return 0;198}199 200static const struct dw_pcie_host_ops histb_pcie_host_ops = {201	.init = histb_pcie_host_init,202};203 204static void histb_pcie_host_disable(struct histb_pcie *hipcie)205{206	reset_control_assert(hipcie->soft_reset);207	reset_control_assert(hipcie->sys_reset);208	reset_control_assert(hipcie->bus_reset);209 210	clk_disable_unprepare(hipcie->aux_clk);211	clk_disable_unprepare(hipcie->pipe_clk);212	clk_disable_unprepare(hipcie->sys_clk);213	clk_disable_unprepare(hipcie->bus_clk);214 215	if (hipcie->reset_gpio)216		gpiod_set_value_cansleep(hipcie->reset_gpio, 1);217 218	if (hipcie->vpcie)219		regulator_disable(hipcie->vpcie);220}221 222static int histb_pcie_host_enable(struct dw_pcie_rp *pp)223{224	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);225	struct histb_pcie *hipcie = to_histb_pcie(pci);226	struct device *dev = pci->dev;227	int ret;228 229	/* power on PCIe device if have */230	if (hipcie->vpcie) {231		ret = regulator_enable(hipcie->vpcie);232		if (ret) {233			dev_err(dev, "failed to enable regulator: %d\n", ret);234			return ret;235		}236	}237 238	if (hipcie->reset_gpio)239		gpiod_set_value_cansleep(hipcie->reset_gpio, 0);240 241	ret = clk_prepare_enable(hipcie->bus_clk);242	if (ret) {243		dev_err(dev, "cannot prepare/enable bus clk\n");244		goto err_bus_clk;245	}246 247	ret = clk_prepare_enable(hipcie->sys_clk);248	if (ret) {249		dev_err(dev, "cannot prepare/enable sys clk\n");250		goto err_sys_clk;251	}252 253	ret = clk_prepare_enable(hipcie->pipe_clk);254	if (ret) {255		dev_err(dev, "cannot prepare/enable pipe clk\n");256		goto err_pipe_clk;257	}258 259	ret = clk_prepare_enable(hipcie->aux_clk);260	if (ret) {261		dev_err(dev, "cannot prepare/enable aux clk\n");262		goto err_aux_clk;263	}264 265	reset_control_assert(hipcie->soft_reset);266	reset_control_deassert(hipcie->soft_reset);267 268	reset_control_assert(hipcie->sys_reset);269	reset_control_deassert(hipcie->sys_reset);270 271	reset_control_assert(hipcie->bus_reset);272	reset_control_deassert(hipcie->bus_reset);273 274	return 0;275 276err_aux_clk:277	clk_disable_unprepare(hipcie->pipe_clk);278err_pipe_clk:279	clk_disable_unprepare(hipcie->sys_clk);280err_sys_clk:281	clk_disable_unprepare(hipcie->bus_clk);282err_bus_clk:283	if (hipcie->vpcie)284		regulator_disable(hipcie->vpcie);285 286	return ret;287}288 289static const struct dw_pcie_ops dw_pcie_ops = {290	.read_dbi = histb_pcie_read_dbi,291	.write_dbi = histb_pcie_write_dbi,292	.link_up = histb_pcie_link_up,293	.start_link = histb_pcie_start_link,294};295 296static int histb_pcie_probe(struct platform_device *pdev)297{298	struct histb_pcie *hipcie;299	struct dw_pcie *pci;300	struct dw_pcie_rp *pp;301	struct device *dev = &pdev->dev;302	int ret;303 304	hipcie = devm_kzalloc(dev, sizeof(*hipcie), GFP_KERNEL);305	if (!hipcie)306		return -ENOMEM;307 308	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);309	if (!pci)310		return -ENOMEM;311 312	hipcie->pci = pci;313	pp = &pci->pp;314	pci->dev = dev;315	pci->ops = &dw_pcie_ops;316 317	hipcie->ctrl = devm_platform_ioremap_resource_byname(pdev, "control");318	if (IS_ERR(hipcie->ctrl)) {319		dev_err(dev, "cannot get control reg base\n");320		return PTR_ERR(hipcie->ctrl);321	}322 323	pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "rc-dbi");324	if (IS_ERR(pci->dbi_base)) {325		dev_err(dev, "cannot get rc-dbi base\n");326		return PTR_ERR(pci->dbi_base);327	}328 329	hipcie->vpcie = devm_regulator_get_optional(dev, "vpcie");330	if (IS_ERR(hipcie->vpcie)) {331		if (PTR_ERR(hipcie->vpcie) != -ENODEV)332			return PTR_ERR(hipcie->vpcie);333		hipcie->vpcie = NULL;334	}335 336	hipcie->reset_gpio = devm_gpiod_get_optional(dev, "reset",337						     GPIOD_OUT_HIGH);338	ret = PTR_ERR_OR_ZERO(hipcie->reset_gpio);339	if (ret) {340		dev_err(dev, "unable to request reset gpio: %d\n", ret);341		return ret;342	}343 344	ret = gpiod_set_consumer_name(hipcie->reset_gpio,345				      "PCIe device power control");346	if (ret) {347		dev_err(dev, "unable to set reset gpio name: %d\n", ret);348		return ret;349	}350 351	hipcie->aux_clk = devm_clk_get(dev, "aux");352	if (IS_ERR(hipcie->aux_clk)) {353		dev_err(dev, "Failed to get PCIe aux clk\n");354		return PTR_ERR(hipcie->aux_clk);355	}356 357	hipcie->pipe_clk = devm_clk_get(dev, "pipe");358	if (IS_ERR(hipcie->pipe_clk)) {359		dev_err(dev, "Failed to get PCIe pipe clk\n");360		return PTR_ERR(hipcie->pipe_clk);361	}362 363	hipcie->sys_clk = devm_clk_get(dev, "sys");364	if (IS_ERR(hipcie->sys_clk)) {365		dev_err(dev, "Failed to get PCIEe sys clk\n");366		return PTR_ERR(hipcie->sys_clk);367	}368 369	hipcie->bus_clk = devm_clk_get(dev, "bus");370	if (IS_ERR(hipcie->bus_clk)) {371		dev_err(dev, "Failed to get PCIe bus clk\n");372		return PTR_ERR(hipcie->bus_clk);373	}374 375	hipcie->soft_reset = devm_reset_control_get(dev, "soft");376	if (IS_ERR(hipcie->soft_reset)) {377		dev_err(dev, "couldn't get soft reset\n");378		return PTR_ERR(hipcie->soft_reset);379	}380 381	hipcie->sys_reset = devm_reset_control_get(dev, "sys");382	if (IS_ERR(hipcie->sys_reset)) {383		dev_err(dev, "couldn't get sys reset\n");384		return PTR_ERR(hipcie->sys_reset);385	}386 387	hipcie->bus_reset = devm_reset_control_get(dev, "bus");388	if (IS_ERR(hipcie->bus_reset)) {389		dev_err(dev, "couldn't get bus reset\n");390		return PTR_ERR(hipcie->bus_reset);391	}392 393	hipcie->phy = devm_phy_get(dev, "phy");394	if (IS_ERR(hipcie->phy)) {395		dev_info(dev, "no pcie-phy found\n");396		hipcie->phy = NULL;397		/* fall through here!398		 * if no pcie-phy found, phy init399		 * should be done under boot!400		 */401	} else {402		phy_init(hipcie->phy);403	}404 405	pp->ops = &histb_pcie_host_ops;406 407	platform_set_drvdata(pdev, hipcie);408 409	ret = histb_pcie_host_enable(pp);410	if (ret) {411		dev_err(dev, "failed to enable host\n");412		return ret;413	}414 415	ret = dw_pcie_host_init(pp);416	if (ret) {417		dev_err(dev, "failed to initialize host\n");418		return ret;419	}420 421	return 0;422}423 424static void histb_pcie_remove(struct platform_device *pdev)425{426	struct histb_pcie *hipcie = platform_get_drvdata(pdev);427 428	histb_pcie_host_disable(hipcie);429 430	if (hipcie->phy)431		phy_exit(hipcie->phy);432}433 434static const struct of_device_id histb_pcie_of_match[] = {435	{ .compatible = "hisilicon,hi3798cv200-pcie", },436	{},437};438MODULE_DEVICE_TABLE(of, histb_pcie_of_match);439 440static struct platform_driver histb_pcie_platform_driver = {441	.probe	= histb_pcie_probe,442	.remove_new = histb_pcie_remove,443	.driver = {444		.name = "histb-pcie",445		.of_match_table = histb_pcie_of_match,446	},447};448module_platform_driver(histb_pcie_platform_driver);449 450MODULE_DESCRIPTION("HiSilicon STB PCIe host controller driver");451