Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 309085
b: refs/heads/master
c: 57c8cb8
h: refs/heads/master
i:
  309083: 6eb066f
v: v3
  • Loading branch information
John Crispin authored and Ralf Baechle committed May 21, 2012
1 parent 45a5ab3 commit 839bdbb
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 95 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ddd4eeca961cc6b1d57e0ca2f264403d690b6882
refs/heads/master: 57c8cb8f242988b8048a7058cd1edde025c6f232
5 changes: 4 additions & 1 deletion trunk/arch/mips/lantiq/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ config SOC_XWAY
select HW_HAS_PCI
endchoice


choice
prompt "Devicetree"

Expand All @@ -27,4 +26,8 @@ config DT_EASY50712
depends on SOC_XWAY
endchoice

config PCI_LANTIQ
bool "PCI Support"
depends on SOC_XWAY && PCI

endif
3 changes: 2 additions & 1 deletion trunk/arch/mips/pci/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o
obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o
obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
obj-$(CONFIG_SOC_XWAY) += pci-lantiq.o ops-lantiq.o
obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
Expand Down
40 changes: 40 additions & 0 deletions trunk/arch/mips/pci/fixup-lantiq.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
*/

#include <linux/of_irq.h>
#include <linux/of_pci.h>

int (*ltq_pci_plat_arch_init)(struct pci_dev *dev) = NULL;
int (*ltq_pci_plat_dev_init)(struct pci_dev *dev) = NULL;

int pcibios_plat_dev_init(struct pci_dev *dev)
{
if (ltq_pci_plat_arch_init)
return ltq_pci_plat_arch_init(dev);

if (ltq_pci_plat_dev_init)
return ltq_pci_plat_dev_init(dev);

return 0;
}

int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct of_irq dev_irq;
int irq;

if (of_irq_map_pci(dev, &dev_irq)) {
dev_err(&dev->dev, "trying to map irq for unknown slot:%d pin:%d\n",
slot, pin);
return 0;
}
irq = irq_create_of_mapping(dev_irq.controller, dev_irq.specifier,
dev_irq.size);
dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, irq);
return irq;
}
177 changes: 85 additions & 92 deletions trunk/arch/mips/pci/pci-lantiq.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,22 @@
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/export.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_pci.h>

#include <asm/pci.h>
#include <asm/gpio.h>
#include <asm/addrspace.h>

#include <lantiq_soc.h>
#include <lantiq_irq.h>
#include <lantiq_platform.h>

#include "pci-lantiq.h"

#define LTQ_PCI_CFG_BASE 0x17000000
#define LTQ_PCI_CFG_SIZE 0x00008000
#define LTQ_PCI_MEM_BASE 0x18000000
#define LTQ_PCI_MEM_SIZE 0x02000000
#define LTQ_PCI_IO_BASE 0x1AE00000
#define LTQ_PCI_IO_SIZE 0x00200000

#define PCI_CR_FCI_ADDR_MAP0 0x00C0
#define PCI_CR_FCI_ADDR_MAP1 0x00C4
#define PCI_CR_FCI_ADDR_MAP2 0x00C8
Expand Down Expand Up @@ -71,50 +67,24 @@
__iomem void *ltq_pci_mapped_cfg;
static __iomem void *ltq_pci_membase;

int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL;

/* Since the PCI REQ pins can be reused for other functionality, make it
possible to exclude those from interpretation by the PCI controller */
static int ltq_pci_req_mask = 0xf;

static int *ltq_pci_irq_map;

struct pci_ops ltq_pci_ops = {
static int reset_gpio;
static struct clk *clk_pci, *clk_external;
static struct resource pci_io_resource;
static struct resource pci_mem_resource;
static struct pci_ops pci_ops = {
.read = ltq_pci_read_config_dword,
.write = ltq_pci_write_config_dword
};

static struct resource pci_io_resource = {
.name = "pci io space",
.start = LTQ_PCI_IO_BASE,
.end = LTQ_PCI_IO_BASE + LTQ_PCI_IO_SIZE - 1,
.flags = IORESOURCE_IO
};

static struct resource pci_mem_resource = {
.name = "pci memory space",
.start = LTQ_PCI_MEM_BASE,
.end = LTQ_PCI_MEM_BASE + LTQ_PCI_MEM_SIZE - 1,
.flags = IORESOURCE_MEM
};

static struct pci_controller ltq_pci_controller = {
.pci_ops = &ltq_pci_ops,
static struct pci_controller pci_controller = {
.pci_ops = &pci_ops,
.mem_resource = &pci_mem_resource,
.mem_offset = 0x00000000UL,
.io_resource = &pci_io_resource,
.io_offset = 0x00000000UL,
};

int pcibios_plat_dev_init(struct pci_dev *dev)
{
if (ltqpci_plat_dev_init)
return ltqpci_plat_dev_init(dev);

return 0;
}

static u32 ltq_calc_bar11mask(void)
static inline u32 ltq_calc_bar11mask(void)
{
u32 mem, bar11mask;

Expand All @@ -125,32 +95,42 @@ static u32 ltq_calc_bar11mask(void)
return bar11mask;
}

static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
static int __devinit ltq_pci_startup(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
const __be32 *req_mask, *bus_clk;
u32 temp_buffer;

/* set clock to 33Mhz */
if (ltq_is_ar9()) {
ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0x1f00000, LTQ_CGU_IFCCR);
ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0xe00000, LTQ_CGU_IFCCR);
} else {
ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR);
ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR);
/* get our clocks */
clk_pci = clk_get(&pdev->dev, NULL);
if (IS_ERR(clk_pci)) {
dev_err(&pdev->dev, "failed to get pci clock\n");
return PTR_ERR(clk_pci);
}

/* external or internal clock ? */
if (conf->clock) {
ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~(1 << 16),
LTQ_CGU_IFCCR);
ltq_cgu_w32((1 << 30), LTQ_CGU_PCICR);
} else {
ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | (1 << 16),
LTQ_CGU_IFCCR);
ltq_cgu_w32((1 << 31) | (1 << 30), LTQ_CGU_PCICR);
clk_external = clk_get(&pdev->dev, "external");
if (IS_ERR(clk_external)) {
clk_put(clk_pci);
dev_err(&pdev->dev, "failed to get external pci clock\n");
return PTR_ERR(clk_external);
}

/* setup pci clock and gpis used by pci */
gpio_request(21, "pci-reset");
/* read the bus speed that we want */
bus_clk = of_get_property(node, "lantiq,bus-clock", NULL);
if (bus_clk)
clk_set_rate(clk_pci, *bus_clk);

/* and enable the clocks */
clk_enable(clk_pci);
if (of_find_property(node, "lantiq,external-clock", NULL))
clk_enable(clk_external);
else
clk_disable(clk_external);

/* setup reset gpio used by pci */
reset_gpio = of_get_named_gpio(node, "gpio-reset", 0);
if (reset_gpio > 0)
devm_gpio_request(&pdev->dev, reset_gpio, "pci-reset");

/* enable auto-switching between PCI and EBU */
ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
Expand All @@ -163,7 +143,12 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)

/* enable external 2 PCI masters */
temp_buffer = ltq_pci_r32(PCI_CR_PC_ARB);
temp_buffer &= (~(ltq_pci_req_mask << 16));
/* setup the request mask */
req_mask = of_get_property(node, "req-mask", NULL);
if (req_mask)
temp_buffer &= ~((*req_mask & 0xf) << 16);
else
temp_buffer &= ~0xf0000;
/* enable internal arbiter */
temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT);
/* enable internal PCI master reqest */
Expand Down Expand Up @@ -207,55 +192,63 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN);

/* toggle reset pin */
__gpio_set_value(21, 0);
wmb();
mdelay(1);
__gpio_set_value(21, 1);
return 0;
}

int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (ltq_pci_irq_map[slot])
return ltq_pci_irq_map[slot];
printk(KERN_ERR "lq_pci: trying to map irq for unknown slot %d\n",
slot);

if (reset_gpio > 0) {
__gpio_set_value(reset_gpio, 0);
wmb();
mdelay(1);
__gpio_set_value(reset_gpio, 1);
}
return 0;
}

static int __devinit ltq_pci_probe(struct platform_device *pdev)
{
struct ltq_pci_data *ltq_pci_data =
(struct ltq_pci_data *) pdev->dev.platform_data;
struct resource *res_cfg, *res_bridge;

pci_clear_flags(PCI_PROBE_ONLY);
ltq_pci_irq_map = ltq_pci_data->irq;
ltq_pci_membase = ioremap_nocache(PCI_CR_BASE_ADDR, PCI_CR_SIZE);
ltq_pci_mapped_cfg =
ioremap_nocache(LTQ_PCI_CFG_BASE, LTQ_PCI_CFG_BASE);
ltq_pci_controller.io_map_base =
(unsigned long)ioremap(LTQ_PCI_IO_BASE, LTQ_PCI_IO_SIZE - 1);
ltq_pci_startup(ltq_pci_data);
register_pci_controller(&ltq_pci_controller);

res_cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
res_bridge = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res_cfg || !res_bridge) {
dev_err(&pdev->dev, "missing memory reources\n");
return -EINVAL;
}

ltq_pci_membase = devm_request_and_ioremap(&pdev->dev, res_bridge);
ltq_pci_mapped_cfg = devm_request_and_ioremap(&pdev->dev, res_cfg);

if (!ltq_pci_membase || !ltq_pci_mapped_cfg) {
dev_err(&pdev->dev, "failed to remap resources\n");
return -ENOMEM;
}

ltq_pci_startup(pdev);

pci_load_of_ranges(&pci_controller, pdev->dev.of_node);
register_pci_controller(&pci_controller);
return 0;
}

static struct platform_driver
ltq_pci_driver = {
static const struct of_device_id ltq_pci_match[] = {
{ .compatible = "lantiq,pci-xway" },
{},
};
MODULE_DEVICE_TABLE(of, ltq_pci_match);

static struct platform_driver ltq_pci_driver = {
.probe = ltq_pci_probe,
.driver = {
.name = "ltq_pci",
.name = "pci-xway",
.owner = THIS_MODULE,
.of_match_table = ltq_pci_match,
},
};

int __init pcibios_init(void)
{
int ret = platform_driver_register(&ltq_pci_driver);
if (ret)
printk(KERN_INFO "ltq_pci: Error registering platfom driver!");
pr_info("pci-xway: Error registering platform driver!");
return ret;
}

Expand Down

0 comments on commit 839bdbb

Please sign in to comment.