Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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