pcie-spear13xx.c (6529B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * PCIe host controller driver for ST Microelectronics SPEAr13xx SoCs 4 * 5 * SPEAr13xx PCIe Glue Layer Source Code 6 * 7 * Copyright (C) 2010-2014 ST Microelectronics 8 * Pratyush Anand <pratyush.anand@gmail.com> 9 * Mohit Kumar <mohit.kumar.dhaka@gmail.com> 10 */ 11 12#include <linux/clk.h> 13#include <linux/interrupt.h> 14#include <linux/kernel.h> 15#include <linux/init.h> 16#include <linux/of.h> 17#include <linux/pci.h> 18#include <linux/phy/phy.h> 19#include <linux/platform_device.h> 20#include <linux/resource.h> 21 22#include "pcie-designware.h" 23 24struct spear13xx_pcie { 25 struct dw_pcie *pci; 26 void __iomem *app_base; 27 struct phy *phy; 28 struct clk *clk; 29}; 30 31struct pcie_app_reg { 32 u32 app_ctrl_0; /* cr0 */ 33 u32 app_ctrl_1; /* cr1 */ 34 u32 app_status_0; /* cr2 */ 35 u32 app_status_1; /* cr3 */ 36 u32 msg_status; /* cr4 */ 37 u32 msg_payload; /* cr5 */ 38 u32 int_sts; /* cr6 */ 39 u32 int_clr; /* cr7 */ 40 u32 int_mask; /* cr8 */ 41 u32 mst_bmisc; /* cr9 */ 42 u32 phy_ctrl; /* cr10 */ 43 u32 phy_status; /* cr11 */ 44 u32 cxpl_debug_info_0; /* cr12 */ 45 u32 cxpl_debug_info_1; /* cr13 */ 46 u32 ven_msg_ctrl_0; /* cr14 */ 47 u32 ven_msg_ctrl_1; /* cr15 */ 48 u32 ven_msg_data_0; /* cr16 */ 49 u32 ven_msg_data_1; /* cr17 */ 50 u32 ven_msi_0; /* cr18 */ 51 u32 ven_msi_1; /* cr19 */ 52 u32 mst_rmisc; /* cr20 */ 53}; 54 55/* CR0 ID */ 56#define APP_LTSSM_ENABLE_ID 3 57#define DEVICE_TYPE_RC (4 << 25) 58#define MISCTRL_EN_ID 30 59#define REG_TRANSLATION_ENABLE 31 60 61/* CR3 ID */ 62#define XMLH_LINK_UP (1 << 6) 63 64/* CR6 */ 65#define MSI_CTRL_INT (1 << 26) 66 67#define to_spear13xx_pcie(x) dev_get_drvdata((x)->dev) 68 69static int spear13xx_pcie_start_link(struct dw_pcie *pci) 70{ 71 struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci); 72 struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base; 73 74 /* enable ltssm */ 75 writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID) 76 | (1 << APP_LTSSM_ENABLE_ID) 77 | ((u32)1 << REG_TRANSLATION_ENABLE), 78 &app_reg->app_ctrl_0); 79 80 return 0; 81} 82 83static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg) 84{ 85 struct spear13xx_pcie *spear13xx_pcie = arg; 86 struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base; 87 struct dw_pcie *pci = spear13xx_pcie->pci; 88 struct pcie_port *pp = &pci->pp; 89 unsigned int status; 90 91 status = readl(&app_reg->int_sts); 92 93 if (status & MSI_CTRL_INT) { 94 BUG_ON(!IS_ENABLED(CONFIG_PCI_MSI)); 95 dw_handle_msi_irq(pp); 96 } 97 98 writel(status, &app_reg->int_clr); 99 100 return IRQ_HANDLED; 101} 102 103static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pcie) 104{ 105 struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base; 106 107 /* Enable MSI interrupt */ 108 if (IS_ENABLED(CONFIG_PCI_MSI)) 109 writel(readl(&app_reg->int_mask) | 110 MSI_CTRL_INT, &app_reg->int_mask); 111} 112 113static int spear13xx_pcie_link_up(struct dw_pcie *pci) 114{ 115 struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci); 116 struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base; 117 118 if (readl(&app_reg->app_status_1) & XMLH_LINK_UP) 119 return 1; 120 121 return 0; 122} 123 124static int spear13xx_pcie_host_init(struct pcie_port *pp) 125{ 126 struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 127 struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci); 128 u32 exp_cap_off = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); 129 u32 val; 130 131 spear13xx_pcie->app_base = pci->dbi_base + 0x2000; 132 133 /* 134 * this controller support only 128 bytes read size, however its 135 * default value in capability register is 512 bytes. So force 136 * it to 128 here. 137 */ 138 val = dw_pcie_readw_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL); 139 val &= ~PCI_EXP_DEVCTL_READRQ; 140 dw_pcie_writew_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL, val); 141 142 dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, 0x104A); 143 dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, 0xCD80); 144 145 spear13xx_pcie_enable_interrupts(spear13xx_pcie); 146 147 return 0; 148} 149 150static const struct dw_pcie_host_ops spear13xx_pcie_host_ops = { 151 .host_init = spear13xx_pcie_host_init, 152}; 153 154static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie, 155 struct platform_device *pdev) 156{ 157 struct dw_pcie *pci = spear13xx_pcie->pci; 158 struct pcie_port *pp = &pci->pp; 159 struct device *dev = &pdev->dev; 160 int ret; 161 162 pp->irq = platform_get_irq(pdev, 0); 163 if (pp->irq < 0) 164 return pp->irq; 165 166 ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler, 167 IRQF_SHARED | IRQF_NO_THREAD, 168 "spear1340-pcie", spear13xx_pcie); 169 if (ret) { 170 dev_err(dev, "failed to request irq %d\n", pp->irq); 171 return ret; 172 } 173 174 pp->ops = &spear13xx_pcie_host_ops; 175 pp->msi_irq = -ENODEV; 176 177 ret = dw_pcie_host_init(pp); 178 if (ret) { 179 dev_err(dev, "failed to initialize host\n"); 180 return ret; 181 } 182 183 return 0; 184} 185 186static const struct dw_pcie_ops dw_pcie_ops = { 187 .link_up = spear13xx_pcie_link_up, 188 .start_link = spear13xx_pcie_start_link, 189}; 190 191static int spear13xx_pcie_probe(struct platform_device *pdev) 192{ 193 struct device *dev = &pdev->dev; 194 struct dw_pcie *pci; 195 struct spear13xx_pcie *spear13xx_pcie; 196 struct device_node *np = dev->of_node; 197 int ret; 198 199 spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL); 200 if (!spear13xx_pcie) 201 return -ENOMEM; 202 203 pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); 204 if (!pci) 205 return -ENOMEM; 206 207 pci->dev = dev; 208 pci->ops = &dw_pcie_ops; 209 210 spear13xx_pcie->pci = pci; 211 212 spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy"); 213 if (IS_ERR(spear13xx_pcie->phy)) { 214 ret = PTR_ERR(spear13xx_pcie->phy); 215 if (ret == -EPROBE_DEFER) 216 dev_info(dev, "probe deferred\n"); 217 else 218 dev_err(dev, "couldn't get pcie-phy\n"); 219 return ret; 220 } 221 222 phy_init(spear13xx_pcie->phy); 223 224 spear13xx_pcie->clk = devm_clk_get(dev, NULL); 225 if (IS_ERR(spear13xx_pcie->clk)) { 226 dev_err(dev, "couldn't get clk for pcie\n"); 227 return PTR_ERR(spear13xx_pcie->clk); 228 } 229 ret = clk_prepare_enable(spear13xx_pcie->clk); 230 if (ret) { 231 dev_err(dev, "couldn't enable clk for pcie\n"); 232 return ret; 233 } 234 235 if (of_property_read_bool(np, "st,pcie-is-gen1")) 236 pci->link_gen = 1; 237 238 platform_set_drvdata(pdev, spear13xx_pcie); 239 240 ret = spear13xx_add_pcie_port(spear13xx_pcie, pdev); 241 if (ret < 0) 242 goto fail_clk; 243 244 return 0; 245 246fail_clk: 247 clk_disable_unprepare(spear13xx_pcie->clk); 248 249 return ret; 250} 251 252static const struct of_device_id spear13xx_pcie_of_match[] = { 253 { .compatible = "st,spear1340-pcie", }, 254 {}, 255}; 256 257static struct platform_driver spear13xx_pcie_driver = { 258 .probe = spear13xx_pcie_probe, 259 .driver = { 260 .name = "spear-pcie", 261 .of_match_table = of_match_ptr(spear13xx_pcie_of_match), 262 .suppress_bind_attrs = true, 263 }, 264}; 265 266builtin_platform_driver(spear13xx_pcie_driver);