blob: c2ba6c11936c9f9c2f63f796e5e29ed35a6e4f8e [file] [log] [blame]
Yan He620fe162013-01-29 12:32:20 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -06002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13/*
14 * MSM PCIe controller driver.
15 */
16
17#define pr_fmt(fmt) "%s: " fmt, __func__
18
Steve Mucklef132c6c2012-06-06 18:30:57 -070019#include <linux/module.h>
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -060020#include <linux/bitops.h>
21#include <linux/clk.h>
22#include <linux/debugfs.h>
23#include <linux/delay.h>
24#include <linux/gpio.h>
25#include <linux/iopoll.h>
26#include <linux/kernel.h>
27#include <linux/pci.h>
28#include <linux/platform_device.h>
29#include <linux/regulator/consumer.h>
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -060030#include <linux/slab.h>
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -060031#include <linux/types.h>
32#include <asm/mach/pci.h>
33#include <mach/gpiomux.h>
34#include <mach/hardware.h>
35#include <mach/msm_iomap.h>
36
37#include "pcie.h"
38
39/* Root Complex Port vendor/device IDs */
40#define PCIE_VENDOR_ID_RCP 0x17cb
41#define PCIE_DEVICE_ID_RCP 0x0101
42
43#define PCIE20_PARF_PCS_DEEMPH 0x34
44#define PCIE20_PARF_PCS_SWING 0x38
45#define PCIE20_PARF_PHY_CTRL 0x40
46#define PCIE20_PARF_PHY_REFCLK 0x4C
47#define PCIE20_PARF_CONFIG_BITS 0x50
48
49#define PCIE20_ELBI_SYS_CTRL 0x04
50
51#define PCIE20_CAP 0x70
52#define PCIE20_CAP_LINKCTRLSTATUS (PCIE20_CAP + 0x10)
53
54#define PCIE20_COMMAND_STATUS 0x04
55#define PCIE20_BUSNUMBERS 0x18
56#define PCIE20_MEMORY_BASE_LIMIT 0x20
57
58#define PCIE20_PLR_IATU_VIEWPORT 0x900
59#define PCIE20_PLR_IATU_CTRL1 0x904
60#define PCIE20_PLR_IATU_CTRL2 0x908
61#define PCIE20_PLR_IATU_LBAR 0x90C
62#define PCIE20_PLR_IATU_UBAR 0x910
63#define PCIE20_PLR_IATU_LAR 0x914
64#define PCIE20_PLR_IATU_LTAR 0x918
65#define PCIE20_PLR_IATU_UTAR 0x91c
66
67#define PCIE_RESET (MSM_CLK_CTL_BASE + 0x22dc)
68#define PCIE_SFAB_AXI_S5_FCLK_CTL (MSM_CLK_CTL_BASE + 0x2154)
69
70#define MSM_PCIE_DEV_BAR_ADDR PCIBIOS_MIN_MEM
71#define MSM_PCIE_DEV_CFG_ADDR 0x01000000
72
73#define RD 0
74#define WR 1
75
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -060076/* PCIE AXI address space */
77#define PCIE_AXI_CONF_SIZE SZ_1M
78
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -060079/* debug mask sys interface */
80static int msm_pcie_debug_mask;
81module_param_named(debug_mask, msm_pcie_debug_mask,
82 int, S_IRUGO | S_IWUSR | S_IWGRP);
83
84/* resources from device file */
85enum msm_pcie_res {
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -060086 /* platform defined resources */
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -060087 MSM_PCIE_RES_PARF,
88 MSM_PCIE_RES_ELBI,
89 MSM_PCIE_RES_PCIE20,
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -060090 MSM_PCIE_MAX_PLATFORM_RES,
91
92 /* other resources */
93 MSM_PCIE_RES_AXI_CONF = MSM_PCIE_MAX_PLATFORM_RES,
94 MSM_PCIE_MAX_RES,
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -060095};
96
97/* msm pcie device data */
98static struct msm_pcie_dev_t msm_pcie_dev;
99
100/* regulators */
101static struct msm_pcie_vreg_info_t msm_pcie_vreg_info[MSM_PCIE_MAX_VREG] = {
102 {NULL, "vp_pcie", 1050000, 1050000, 40900},
103 {NULL, "vptx_pcie", 1050000, 1050000, 18200},
104 {NULL, "vdd_pcie_vph", 0, 0, 0},
105 {NULL, "pcie_ext_3p3v", 0, 0, 0}
106};
107
108/* clocks */
109static struct msm_pcie_clk_info_t msm_pcie_clk_info[MSM_PCIE_MAX_CLK] = {
110 {NULL, "bus_clk"},
111 {NULL, "iface_clk"},
112 {NULL, "ref_clk"}
113};
114
115/* resources */
116static struct msm_pcie_res_info_t msm_pcie_res_info[MSM_PCIE_MAX_RES] = {
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600117 {"pcie_parf", 0, 0},
118 {"pcie_elbi", 0, 0},
119 {"pcie20", 0, 0},
120 {"pcie_axi_conf", 0, 0},
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600121};
122
123int msm_pcie_get_debug_mask(void)
124{
125 return msm_pcie_debug_mask;
126}
127
128static void msm_pcie_write_mask(void __iomem *addr,
129 uint32_t clear_mask, uint32_t set_mask)
130{
131 uint32_t val;
132
133 val = (readl_relaxed(addr) & ~clear_mask) | set_mask;
134 writel_relaxed(val, addr);
135 wmb(); /* ensure data is written to hardware register */
136}
137
138static int msm_pcie_is_link_up(void)
139{
140 return readl_relaxed(msm_pcie_dev.pcie20 + PCIE20_CAP_LINKCTRLSTATUS) &
141 BIT(29);
142}
143
144static inline int msm_pcie_oper_conf(struct pci_bus *bus, u32 devfn, int oper,
145 int where, int size, u32 *val)
146{
147 uint32_t word_offset, byte_offset, mask;
148 uint32_t rd_val, wr_val;
149 struct msm_pcie_dev_t *dev = &msm_pcie_dev;
150 void __iomem *config_base;
151
152 /*
153 * Only buses 0 and 1 are supported. RC port on bus 0 and EP in bus 1.
154 * For downstream bus (1), make sure link is up
155 */
156 if ((bus->number > 1) || (devfn != 0)) {
157 PCIE_DBG("invalid %s - bus %d devfn %d\n",
158 (oper == RD) ? "rd" : "wr", bus->number, devfn);
159 *val = ~0;
160 return PCIBIOS_DEVICE_NOT_FOUND;
161 } else if ((bus->number != 0) && !msm_pcie_is_link_up()) {
162 PCIE_DBG("%s fail, link down - bus %d devfn %d\n",
163 (oper == RD) ? "rd" : "wr", bus->number, devfn);
164 *val = ~0;
165 return PCIBIOS_DEVICE_NOT_FOUND;
166 }
167
168 word_offset = where & ~0x3;
169 byte_offset = where & 0x3;
170 mask = (~0 >> (8 * (4 - size))) << (8 * byte_offset);
171
172 config_base = (bus->number == 0) ? dev->pcie20 : dev->axi_conf;
173 rd_val = readl_relaxed(config_base + word_offset);
174
175 if (oper == RD) {
176 *val = ((rd_val & mask) >> (8 * byte_offset));
177
178 PCIE_DBG("%d:0x%02x + 0x%04x[%d] -> 0x%08x; rd 0x%08x\n",
179 bus->number, devfn, where, size, *val, rd_val);
180 } else {
181 wr_val = (rd_val & ~mask) |
182 ((*val << (8 * byte_offset)) & mask);
183 writel_relaxed(wr_val, config_base + word_offset);
184 wmb(); /* ensure config data is written to hardware register */
185
186 PCIE_DBG("%d:0x%02x + 0x%04x[%d] <- 0x%08x;"
187 " rd 0x%08x val 0x%08x\n", bus->number,
188 devfn, where, size, wr_val, rd_val, *val);
189 }
190
191 return 0;
192}
193
194static int msm_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
195 int size, u32 *val)
196{
197 return msm_pcie_oper_conf(bus, devfn, RD, where, size, val);
198}
199
200static int msm_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
201 int where, int size, u32 val)
202{
Niranjana Vishwanathapuraeb78cbf2012-07-19 11:44:07 -0600203 /*
204 *Attempt to reset secondary bus is causing PCIE core to reset.
205 *Disable secondary bus reset functionality.
206 */
207 if ((bus->number == 0) && (where == PCI_BRIDGE_CONTROL) &&
208 (val & PCI_BRIDGE_CTL_BUS_RESET)) {
209 pr_info("PCIE secondary bus reset not supported\n");
210 val &= ~PCI_BRIDGE_CTL_BUS_RESET;
211 }
212
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600213 return msm_pcie_oper_conf(bus, devfn, WR, where, size, &val);
214}
215
216static struct pci_ops msm_pcie_ops = {
217 .read = msm_pcie_rd_conf,
218 .write = msm_pcie_wr_conf,
219};
220
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600221static int __init msm_pcie_gpio_init(void)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600222{
223 int rc, i;
224 struct msm_pcie_gpio_info_t *info;
225
226 for (i = 0; i < MSM_PCIE_MAX_GPIO; i++) {
227 info = &msm_pcie_dev.gpio[i];
228
229 rc = gpio_request(info->num, info->name);
230 if (rc) {
231 pr_err("can't get gpio %s; %d\n", info->name, rc);
232 break;
233 }
234
235 rc = gpio_direction_output(info->num, 0);
236 if (rc) {
237 pr_err("can't set gpio direction %s; %d\n",
238 info->name, rc);
239 gpio_free(info->num);
240 break;
241 }
242 }
243
244 if (rc)
245 while (i--)
246 gpio_free(msm_pcie_dev.gpio[i].num);
247
248 return rc;
249}
250
251static void msm_pcie_gpio_deinit(void)
252{
253 int i;
254
255 for (i = 0; i < MSM_PCIE_MAX_GPIO; i++)
256 gpio_free(msm_pcie_dev.gpio[i].num);
257}
258
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600259static int __init msm_pcie_vreg_init(struct device *dev)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600260{
261 int i, rc = 0;
262 struct regulator *vreg;
263 struct msm_pcie_vreg_info_t *info;
264
Yan He620fe162013-01-29 12:32:20 -0800265 for (i = 0; i < msm_pcie_dev.vreg_n; i++) {
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600266 info = &msm_pcie_dev.vreg[i];
267
268 vreg = regulator_get(dev, info->name);
269 if (!vreg || IS_ERR(vreg)) {
270 rc = (PTR_ERR(vreg)) ? PTR_ERR(vreg) : -ENODEV;
271 pr_err("can't get %s; %d\n", info->name, rc);
272 break;
273 }
274
275 if (info->max_v) {
276 rc = regulator_set_voltage(vreg,
277 info->min_v, info->max_v);
278 if (rc) {
279 pr_err("can't set voltage %s; %d\n",
280 info->name, rc);
281 regulator_put(vreg);
282 break;
283 }
284 }
285
286 if (info->opt_mode) {
287 rc = regulator_set_optimum_mode(vreg, info->opt_mode);
288 if (rc < 0) {
289 pr_err("can't set mode %s; %d\n",
290 info->name, rc);
291 regulator_put(vreg);
292 break;
293 }
294 }
295
296 rc = regulator_enable(vreg);
297 if (rc) {
298 pr_err("can't enable %s, %d\n", info->name, rc);
299 regulator_put(vreg);
300 break;
301 }
302 info->hdl = vreg;
303 }
304
305 if (rc)
306 while (i--) {
307 regulator_disable(msm_pcie_dev.vreg[i].hdl);
308 regulator_put(msm_pcie_dev.vreg[i].hdl);
309 msm_pcie_dev.vreg[i].hdl = NULL;
310 }
311
312 return rc;
313}
314
315static void msm_pcie_vreg_deinit(void)
316{
317 int i;
318
Yan He620fe162013-01-29 12:32:20 -0800319 for (i = 0; i < msm_pcie_dev.vreg_n; i++) {
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600320 regulator_disable(msm_pcie_dev.vreg[i].hdl);
321 regulator_put(msm_pcie_dev.vreg[i].hdl);
322 msm_pcie_dev.vreg[i].hdl = NULL;
323 }
324}
325
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600326static int __init msm_pcie_clk_init(struct device *dev)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600327{
328 int i, rc = 0;
329 struct clk *clk_hdl;
330 struct msm_pcie_clk_info_t *info;
331
332 for (i = 0; i < MSM_PCIE_MAX_CLK; i++) {
333 info = &msm_pcie_dev.clk[i];
334
335 clk_hdl = clk_get(dev, info->name);
336 if (!clk_hdl || IS_ERR(clk_hdl)) {
337 rc = (PTR_ERR(clk_hdl)) ? PTR_ERR(clk_hdl) : -ENODEV;
338 pr_err("can't get clk %s; %d\n", info->name, rc);
339 break;
340 }
341 clk_prepare_enable(clk_hdl);
342 info->hdl = clk_hdl;
343 }
344
345 if (rc)
346 while (i--) {
347 clk_disable_unprepare(msm_pcie_dev.clk[i].hdl);
348 clk_put(msm_pcie_dev.clk[i].hdl);
349 msm_pcie_dev.clk[i].hdl = NULL;
350 }
351
352 return rc;
353}
354
355static void msm_pcie_clk_deinit(void)
356{
357 int i;
358
359 for (i = 0; i < MSM_PCIE_MAX_CLK; i++) {
360 clk_disable_unprepare(msm_pcie_dev.clk[i].hdl);
361 clk_put(msm_pcie_dev.clk[i].hdl);
362 msm_pcie_dev.clk[i].hdl = NULL;
363 }
364}
365
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600366static void __init msm_pcie_config_controller(void)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600367{
368 struct msm_pcie_dev_t *dev = &msm_pcie_dev;
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600369 struct resource *axi_conf = dev->res[MSM_PCIE_RES_AXI_CONF].resource;
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600370
371 /*
372 * program and enable address translation region 0 (device config
373 * address space); region type config;
374 * axi config address range to device config address range
375 */
376 writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_VIEWPORT);
377 /* ensure that hardware locks the region before programming it */
378 wmb();
379
380 writel_relaxed(4, dev->pcie20 + PCIE20_PLR_IATU_CTRL1);
381 writel_relaxed(BIT(31), dev->pcie20 + PCIE20_PLR_IATU_CTRL2);
382 writel_relaxed(axi_conf->start, dev->pcie20 + PCIE20_PLR_IATU_LBAR);
383 writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_UBAR);
384 writel_relaxed(axi_conf->end, dev->pcie20 + PCIE20_PLR_IATU_LAR);
385 writel_relaxed(MSM_PCIE_DEV_CFG_ADDR,
386 dev->pcie20 + PCIE20_PLR_IATU_LTAR);
387 writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_UTAR);
388 /* ensure that hardware registers the configuration */
389 wmb();
390
391 /*
392 * program and enable address translation region 2 (device resource
393 * address space); region type memory;
394 * axi device bar address range to device bar address range
395 */
396 writel_relaxed(2, dev->pcie20 + PCIE20_PLR_IATU_VIEWPORT);
397 /* ensure that hardware locks the region before programming it */
398 wmb();
399
400 writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_CTRL1);
401 writel_relaxed(BIT(31), dev->pcie20 + PCIE20_PLR_IATU_CTRL2);
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600402 writel_relaxed(dev->axi_bar_start, dev->pcie20 + PCIE20_PLR_IATU_LBAR);
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600403 writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_UBAR);
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600404 writel_relaxed(dev->axi_bar_end, dev->pcie20 + PCIE20_PLR_IATU_LAR);
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600405 writel_relaxed(MSM_PCIE_DEV_BAR_ADDR,
406 dev->pcie20 + PCIE20_PLR_IATU_LTAR);
407 writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_UTAR);
408 /* ensure that hardware registers the configuration */
409 wmb();
410}
411
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600412static int __init msm_pcie_get_resources(struct platform_device *pdev)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600413{
414 int i, rc = 0;
415 struct resource *res;
416 struct msm_pcie_res_info_t *info;
417 struct msm_pcie_dev_t *dev = &msm_pcie_dev;
418
419 for (i = 0; i < MSM_PCIE_MAX_RES; i++) {
420 info = &dev->res[i];
421
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600422 if (i < MSM_PCIE_MAX_PLATFORM_RES) {
423 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
424 info->name);
425 } else {
426 res = dev->res[i].resource;
427 if (request_resource(&iomem_resource, res))
428 res = NULL;
429 }
430
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600431 if (!res) {
432 pr_err("can't get %s resource\n", info->name);
433 rc = -ENOMEM;
434 break;
435 }
436
437 info->base = ioremap(res->start, resource_size(res));
438 if (!info->base) {
439 pr_err("can't remap %s\n", info->name);
440 rc = -ENOMEM;
441 break;
442 }
443
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600444 info->resource = res;
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600445 }
446
447 if (rc) {
448 while (i--) {
449 iounmap(dev->res[i].base);
450 dev->res[i].base = NULL;
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600451 if (i >= MSM_PCIE_MAX_PLATFORM_RES)
452 release_resource(dev->res[i].resource);
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600453 }
454 } else {
455 dev->parf = dev->res[MSM_PCIE_RES_PARF].base;
456 dev->elbi = dev->res[MSM_PCIE_RES_ELBI].base;
457 dev->pcie20 = dev->res[MSM_PCIE_RES_PCIE20].base;
458 dev->axi_conf = dev->res[MSM_PCIE_RES_AXI_CONF].base;
459 }
460
461 return rc;
462}
463
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600464static void msm_pcie_release_resources(void)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600465{
466 int i;
467
468 for (i = 0; i < MSM_PCIE_MAX_RES; i++) {
469 iounmap(msm_pcie_dev.res[i].base);
470 msm_pcie_dev.res[i].base = NULL;
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600471 if (i >= MSM_PCIE_MAX_PLATFORM_RES)
472 release_resource(msm_pcie_dev.res[i].resource);
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600473 }
474
475 msm_pcie_dev.parf = NULL;
476 msm_pcie_dev.elbi = NULL;
477 msm_pcie_dev.pcie20 = NULL;
478 msm_pcie_dev.axi_conf = NULL;
479}
480
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600481static int __init msm_pcie_setup(int nr, struct pci_sys_data *sys)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600482{
483 int rc;
484 struct msm_pcie_dev_t *dev = &msm_pcie_dev;
485 uint32_t val;
486
487 PCIE_DBG("bus %d\n", nr);
488 if (nr != 0)
489 return 0;
490
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600491 /*
492 * specify linux PCI framework to allocate device memory (BARs)
493 * from msm_pcie_dev.dev_mem_res resource.
494 */
495 sys->mem_offset = 0;
496 pci_add_resource(&sys->resources, &msm_pcie_dev.dev_mem_res);
497
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600498 /* assert PCIe reset link to keep EP in reset */
499 gpio_set_value_cansleep(dev->gpio[MSM_PCIE_GPIO_RST_N].num,
500 dev->gpio[MSM_PCIE_GPIO_RST_N].on);
501
502 /* enable power */
503 rc = msm_pcie_vreg_init(&dev->pdev->dev);
504 if (rc)
505 goto out;
506
507 /* assert PCIe PARF reset while powering the core */
508 msm_pcie_write_mask(PCIE_RESET, 0, BIT(2));
509
510 /* enable clocks */
511 rc = msm_pcie_clk_init(&dev->pdev->dev);
512 if (rc)
513 goto clk_fail;
514
515 /* enable pcie power; wait 3ms for clock to stabilize */
516 gpio_set_value_cansleep(dev->gpio[MSM_PCIE_GPIO_PWR_EN].num,
517 dev->gpio[MSM_PCIE_GPIO_PWR_EN].on);
518 usleep(3000);
519
520 /*
521 * de-assert PCIe PARF reset;
522 * wait 1us before accessing PARF registers
523 */
524 msm_pcie_write_mask(PCIE_RESET, BIT(2), 0);
525 udelay(1);
526
527 /* enable PCIe clocks and resets */
528 msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0);
529
530 /* PARF programming */
Rohit Vaswaniafe48202013-03-05 15:10:47 -0800531 writel_relaxed(dev->parf_deemph, dev->parf + PCIE20_PARF_PCS_DEEMPH);
532 writel_relaxed(dev->parf_swing, dev->parf + PCIE20_PARF_PCS_SWING);
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600533 writel_relaxed((4<<24), dev->parf + PCIE20_PARF_CONFIG_BITS);
534 /* ensure that hardware registers the PARF configuration */
535 wmb();
536
537 /* enable reference clock */
538 msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_REFCLK, 0, BIT(16));
539
540 /* enable access to PCIe slave port on system fabric */
541 writel_relaxed(BIT(4), PCIE_SFAB_AXI_S5_FCLK_CTL);
542 /* ensure that access is enabled before proceeding */
543 wmb();
544
545 /* de-assert PICe PHY, Core, POR and AXI clk domain resets */
546 msm_pcie_write_mask(PCIE_RESET, BIT(5), 0);
547 msm_pcie_write_mask(PCIE_RESET, BIT(4), 0);
548 msm_pcie_write_mask(PCIE_RESET, BIT(3), 0);
549 msm_pcie_write_mask(PCIE_RESET, BIT(0), 0);
550
551 /* wait 150ms for clock acquisition */
552 udelay(150);
553
554 /* de-assert PCIe reset link to bring EP out of reset */
555 gpio_set_value_cansleep(dev->gpio[MSM_PCIE_GPIO_RST_N].num,
556 !dev->gpio[MSM_PCIE_GPIO_RST_N].on);
557
558 /* enable link training */
559 msm_pcie_write_mask(dev->elbi + PCIE20_ELBI_SYS_CTRL, 0, BIT(0));
560
561 /* poll for link to come up for upto 100ms */
562 rc = readl_poll_timeout(
563 (msm_pcie_dev.pcie20 + PCIE20_CAP_LINKCTRLSTATUS),
564 val, (val & BIT(29)), 10000, 100000);
565 if (rc) {
566 pr_err("link initialization failed\n");
567 goto link_fail;
568 } else
569 pr_info("link initialized\n");
570
571 msm_pcie_config_controller();
572 rc = msm_pcie_irq_init(dev);
573 if (!rc)
574 goto out;
575
576link_fail:
577 msm_pcie_clk_deinit();
578clk_fail:
579 msm_pcie_vreg_deinit();
580out:
581 return (rc) ? 0 : 1;
582}
583
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600584static struct pci_bus __init *msm_pcie_scan_bus(int nr,
585 struct pci_sys_data *sys)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600586{
587 struct pci_bus *bus = NULL;
588
589 PCIE_DBG("bus %d\n", nr);
590 if (nr == 0)
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600591 bus = pci_scan_root_bus(NULL, sys->busnr, &msm_pcie_ops, sys,
592 &sys->resources);
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600593
594 return bus;
595}
596
Steve Mucklef132c6c2012-06-06 18:30:57 -0700597static int __init msm_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600598{
599 PCIE_DBG("slot %d pin %d\n", slot, pin);
600 return (pin <= 4) ? (PCIE20_INTA + pin - 1) : 0;
601}
602
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600603static struct hw_pci msm_pci __initdata = {
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600604 .nr_controllers = 1,
605 .swizzle = pci_std_swizzle,
606 .setup = msm_pcie_setup,
607 .scan = msm_pcie_scan_bus,
608 .map_irq = msm_pcie_map_irq,
609};
610
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600611static int __init msm_pcie_probe(struct platform_device *pdev)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600612{
613 const struct msm_pcie_platform *pdata;
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600614 struct resource *res;
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600615 int rc;
616
617 PCIE_DBG("\n");
618
619 msm_pcie_dev.pdev = pdev;
620 pdata = pdev->dev.platform_data;
621 msm_pcie_dev.gpio = pdata->gpio;
Niranjana Vishwanathapura459a27d2012-07-20 12:23:55 -0600622 msm_pcie_dev.wake_n = pdata->wake_n;
Yan He620fe162013-01-29 12:32:20 -0800623 msm_pcie_dev.vreg_n = pdata->vreg_n;
Rohit Vaswaniafe48202013-03-05 15:10:47 -0800624 msm_pcie_dev.parf_deemph = pdata->parf_deemph;
625 msm_pcie_dev.parf_swing = pdata->parf_swing;
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600626 msm_pcie_dev.vreg = msm_pcie_vreg_info;
627 msm_pcie_dev.clk = msm_pcie_clk_info;
628 msm_pcie_dev.res = msm_pcie_res_info;
629
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600630 /* device memory resource */
631 res = &msm_pcie_dev.dev_mem_res;
632 res->name = "pcie_dev_mem";
633 res->start = MSM_PCIE_DEV_BAR_ADDR;
634 res->end = res->start + pdata->axi_size - 1;
635 res->flags = IORESOURCE_MEM;
636
637 /* axi address space = axi bar space + axi config space */
638 msm_pcie_dev.axi_bar_start = pdata->axi_addr;
639 msm_pcie_dev.axi_bar_end = pdata->axi_addr + pdata->axi_size -
640 PCIE_AXI_CONF_SIZE - 1;
641
642 /* axi config space resource */
643 res = kzalloc(sizeof(*res), GFP_KERNEL);
644 if (!res) {
645 pr_err("can't allocate memory\n");
646 return -ENOMEM;
647 }
648
649 msm_pcie_dev.res[MSM_PCIE_RES_AXI_CONF].resource = res;
650 res->name = msm_pcie_dev.res[MSM_PCIE_RES_AXI_CONF].name;
651 res->start = msm_pcie_dev.axi_bar_end + 1;
652 res->end = res->start + PCIE_AXI_CONF_SIZE - 1;
653 res->flags = IORESOURCE_MEM;
654
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600655 rc = msm_pcie_get_resources(msm_pcie_dev.pdev);
656 if (rc)
657 return rc;
658
659 rc = msm_pcie_gpio_init();
660 if (rc) {
661 msm_pcie_release_resources();
662 return rc;
663 }
664
665 /* kick start ARM PCI configuration framework */
666 pci_common_init(&msm_pci);
667 return 0;
668}
669
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600670static int __exit msm_pcie_remove(struct platform_device *pdev)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600671{
672 PCIE_DBG("\n");
673
674 msm_pcie_irq_deinit(&msm_pcie_dev);
675 msm_pcie_vreg_deinit();
676 msm_pcie_clk_deinit();
677 msm_pcie_gpio_deinit();
678 msm_pcie_release_resources();
679
680 msm_pcie_dev.pdev = NULL;
681 msm_pcie_dev.vreg = NULL;
682 msm_pcie_dev.clk = NULL;
683 msm_pcie_dev.gpio = NULL;
684 return 0;
685}
686
687static struct platform_driver msm_pcie_driver = {
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600688 .remove = __exit_p(msm_pcie_remove),
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600689 .driver = {
690 .name = "msm_pcie",
691 .owner = THIS_MODULE,
692 },
693};
694
695static int __init msm_pcie_init(void)
696{
697 PCIE_DBG("\n");
Steve Mucklef132c6c2012-06-06 18:30:57 -0700698 pcibios_min_mem = 0x10000000;
Niranjana Vishwanathapurad3803302012-05-25 15:13:09 -0600699 return platform_driver_probe(&msm_pcie_driver, msm_pcie_probe);
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600700}
701subsys_initcall(msm_pcie_init);
702
703/* RC do not represent the right class; set it to PCI_CLASS_BRIDGE_PCI */
Niranjana Vishwanathapuradb684cb2012-06-27 11:24:28 -0600704static void __devinit msm_pcie_fixup_early(struct pci_dev *dev)
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600705{
706 PCIE_DBG("hdr_type %d\n", dev->hdr_type);
707 if (dev->hdr_type == 1)
708 dev->class = (dev->class & 0xff) | (PCI_CLASS_BRIDGE_PCI << 8);
709}
Niranjana Vishwanathapuradb684cb2012-06-27 11:24:28 -0600710DECLARE_PCI_FIXUP_EARLY(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP,
711 msm_pcie_fixup_early);
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600712
Niranjana Vishwanathapura459a27d2012-07-20 12:23:55 -0600713/* enable wake_n interrupt during suspend */
714static void msm_pcie_fixup_suspend(struct pci_dev *dev)
715{
716 PCIE_DBG("enabling wake_n\n");
717 if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
718 enable_irq(msm_pcie_dev.wake_n);
719}
720DECLARE_PCI_FIXUP_SUSPEND(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP,
721 msm_pcie_fixup_suspend);
722
723/* disable wake_n interrupt when system is not in suspend */
724static void msm_pcie_fixup_resume(struct pci_dev *dev)
725{
726 PCIE_DBG("disabling wake_n\n");
727 if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
728 disable_irq(msm_pcie_dev.wake_n);
729}
730DECLARE_PCI_FIXUP_RESUME(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP,
731 msm_pcie_fixup_resume);
732
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600733/*
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600734 * actual physical (BAR) address of the device resources starts from
735 * MSM_PCIE_DEV_BAR_ADDR; the system axi address for the device resources starts
736 * from msm_pcie_dev.axi_bar_start; correct the device resource structure here;
737 * address translation unit handles the required translations
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600738 */
739static void __devinit msm_pcie_fixup_final(struct pci_dev *dev)
740{
741 int i;
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600742 struct resource *res;
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600743
744 PCIE_DBG("vendor 0x%x 0x%x\n", dev->vendor, dev->device);
745 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
Niranjana Vishwanathapura68210ff2012-06-24 18:03:49 -0600746 res = &dev->resource[i];
747 if (res->start & MSM_PCIE_DEV_BAR_ADDR) {
748 res->start -= MSM_PCIE_DEV_BAR_ADDR;
749 res->start += msm_pcie_dev.axi_bar_start;
750 res->end -= MSM_PCIE_DEV_BAR_ADDR;
751 res->end += msm_pcie_dev.axi_bar_start;
752
753 /* If Root Port, request for the changed resource */
754 if ((dev->vendor == PCIE_VENDOR_ID_RCP) &&
755 (dev->device == PCIE_DEVICE_ID_RCP)) {
756 insert_resource(&iomem_resource, res);
757 }
Niranjana Vishwanathapuraf1427ac2012-05-03 14:28:21 -0600758 }
759 }
760}
761DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, msm_pcie_fixup_final);