--- a/arch/mips/pci/pci-rt3883.c +++ b/arch/mips/pci/pci-rt3883.c @@ -1,7 +1,7 @@ /* - * Ralink RT3883 SoC PCI support + * Ralink RT3662/RT3883 SoC PCI support * - * Copyright (C) 2011-2012 Gabor Juhos + * Copyright (C) 2011-2013 Gabor Juhos * * Parts of this file are based on Ralink's 2.6.21 BSP * @@ -16,52 +16,82 @@ #include #include #include +#include +#include +#include +#include +#include #include -#include +#include #define RT3883_MEMORY_BASE 0x00000000 #define RT3883_MEMORY_SIZE 0x02000000 -#define RT3883_PCI_MEM_BASE 0x20000000 -#define RT3883_PCI_MEM_SIZE 0x10000000 -#define RT3883_PCI_IO_BASE 0x10160000 -#define RT3883_PCI_IO_SIZE 0x00010000 - -#define RT3883_PCI_REG_PCICFG_ADDR 0x00 -#define RT3883_PCI_REG_PCIRAW_ADDR 0x04 -#define RT3883_PCI_REG_PCIINT_ADDR 0x08 -#define RT3883_PCI_REG_PCIMSK_ADDR 0x0c -#define RT3833_PCI_PCIINT_PCIE BIT(20) -#define RT3833_PCI_PCIINT_PCI1 BIT(19) -#define RT3833_PCI_PCIINT_PCI0 BIT(18) +#define RT3883_PCI_REG_PCICFG 0x00 +#define RT3883_PCICFG_P2P_BR_DEVNUM_M 0xf +#define RT3883_PCICFG_P2P_BR_DEVNUM_S 16 +#define RT3883_PCICFG_PCIRST BIT(1) +#define RT3883_PCI_REG_PCIRAW 0x04 +#define RT3883_PCI_REG_PCIINT 0x08 +#define RT3883_PCI_REG_PCIENA 0x0c -#define RT3883_PCI_REG_CONFIG_ADDR 0x20 -#define RT3883_PCI_REG_CONFIG_DATA 0x24 +#define RT3883_PCI_REG_CFGADDR 0x20 +#define RT3883_PCI_REG_CFGDATA 0x24 #define RT3883_PCI_REG_MEMBASE 0x28 #define RT3883_PCI_REG_IOBASE 0x2c #define RT3883_PCI_REG_ARBCTL 0x80 #define RT3883_PCI_REG_BASE(_x) (0x1000 + (_x) * 0x1000) -#define RT3883_PCI_REG_BAR0SETUP_ADDR(_x) (RT3883_PCI_REG_BASE((_x)) + 0x10) -#define RT3883_PCI_REG_IMBASEBAR0_ADDR(_x) (RT3883_PCI_REG_BASE((_x)) + 0x18) +#define RT3883_PCI_REG_BAR0SETUP(_x) (RT3883_PCI_REG_BASE((_x)) + 0x10) +#define RT3883_PCI_REG_IMBASEBAR0(_x) (RT3883_PCI_REG_BASE((_x)) + 0x18) #define RT3883_PCI_REG_ID(_x) (RT3883_PCI_REG_BASE((_x)) + 0x30) #define RT3883_PCI_REG_CLASS(_x) (RT3883_PCI_REG_BASE((_x)) + 0x34) #define RT3883_PCI_REG_SUBID(_x) (RT3883_PCI_REG_BASE((_x)) + 0x38) #define RT3883_PCI_REG_STATUS(_x) (RT3883_PCI_REG_BASE((_x)) + 0x50) -static int (*rt3883_pci_plat_dev_init)(struct pci_dev *dev); -static void __iomem *rt3883_pci_base; -static DEFINE_SPINLOCK(rt3883_pci_lock); +#define RT3883_PCI_MODE_NONE 0 +#define RT3883_PCI_MODE_PCI BIT(0) +#define RT3883_PCI_MODE_PCIE BIT(1) +#define RT3883_PCI_MODE_BOTH (RT3883_PCI_MODE_PCI | RT3883_PCI_MODE_PCIE) -static inline u32 rt3883_pci_rr(unsigned reg) +#define RT3883_PCI_IRQ_COUNT 32 + +#define RT3883_P2P_BR_DEVNUM 1 + +struct rt3883_pci_controller { + void __iomem *base; + spinlock_t lock; + + struct irq_domain *irq_domain; + + struct pci_controller pci_controller; + struct resource io_res; + struct resource mem_res; + + bool pcie_ready; + unsigned char p2p_devnum; +}; + +static inline struct rt3883_pci_controller * +pci_bus_to_rt3883_controller(struct pci_bus *bus) { - return readl(rt3883_pci_base + reg); + struct pci_controller *hose; + + hose = (struct pci_controller *) bus->sysdata; + return container_of(hose, struct rt3883_pci_controller, pci_controller); +} + +static inline u32 rt3883_pci_r32(struct rt3883_pci_controller *rpc, + unsigned reg) +{ + return ioread32(rpc->base + reg); } -static inline void rt3883_pci_wr(u32 val, unsigned reg) +static inline void rt3883_pci_w32(struct rt3883_pci_controller *rpc, + u32 val, unsigned reg) { - writel(val, rt3883_pci_base + reg); + iowrite32(val, rpc->base + reg); } static inline u32 rt3883_pci_get_cfgaddr(unsigned int bus, unsigned int slot, @@ -71,7 +101,8 @@ static inline u32 rt3883_pci_get_cfgaddr 0x80000000); } -static u32 rt3883_pci_read_u32(unsigned bus, unsigned slot, +static u32 rt3883_pci_read_cfg32(struct rt3883_pci_controller *rpc, + unsigned bus, unsigned slot, unsigned func, unsigned reg) { unsigned long flags; @@ -80,15 +111,16 @@ static u32 rt3883_pci_read_u32(unsigned address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); - spin_lock_irqsave(&rt3883_pci_lock, flags); - rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR); - ret = rt3883_pci_rr(RT3883_PCI_REG_CONFIG_DATA); - spin_unlock_irqrestore(&rt3883_pci_lock, flags); + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + ret = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); return ret; } -static void rt3883_pci_write_u32(unsigned bus, unsigned slot, +static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc, + unsigned bus, unsigned slot, unsigned func, unsigned reg, u32 val) { unsigned long flags; @@ -96,84 +128,61 @@ static void rt3883_pci_write_u32(unsigne address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); - spin_lock_irqsave(&rt3883_pci_lock, flags); - rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR); - rt3883_pci_wr(val, RT3883_PCI_REG_CONFIG_DATA); - spin_unlock_irqrestore(&rt3883_pci_lock, flags); + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); } static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc) { + struct rt3883_pci_controller *rpc; u32 pending; - pending = rt3883_pci_rr(RT3883_PCI_REG_PCIINT_ADDR) & - rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR); + rpc = irq_get_handler_data(irq); + + pending = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIINT) & + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); if (!pending) { spurious_interrupt(); return; } - if (pending & RT3833_PCI_PCIINT_PCI0) - generic_handle_irq(RT3883_PCI_IRQ_PCI0); + while (pending) { + unsigned bit = __ffs(pending); - if (pending & RT3833_PCI_PCIINT_PCI1) - generic_handle_irq(RT3883_PCI_IRQ_PCI1); + irq = irq_find_mapping(rpc->irq_domain, bit); + generic_handle_irq(irq); - if (pending & RT3833_PCI_PCIINT_PCIE) - generic_handle_irq(RT3883_PCI_IRQ_PCIE); + pending &= ~BIT(bit); + } } static void rt3883_pci_irq_unmask(struct irq_data *d) { - int irq = d->irq; - u32 mask; + struct rt3883_pci_controller *rpc; u32 t; - switch (irq) { - case RT3883_PCI_IRQ_PCI0: - mask = RT3833_PCI_PCIINT_PCI0; - break; - case RT3883_PCI_IRQ_PCI1: - mask = RT3833_PCI_PCIINT_PCI1; - break; - case RT3883_PCI_IRQ_PCIE: - mask = RT3833_PCI_PCIINT_PCIE; - break; - default: - BUG(); - } + rpc = irq_data_get_irq_chip_data(d); - t = rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR); - rt3883_pci_wr(t | mask, RT3883_PCI_REG_PCIMSK_ADDR); + t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); + rt3883_pci_w32(rpc, t | BIT(d->hwirq), RT3883_PCI_REG_PCIENA); /* flush write */ - rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR); + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); } static void rt3883_pci_irq_mask(struct irq_data *d) { - int irq = d->irq; - u32 mask; + struct rt3883_pci_controller *rpc; u32 t; - switch (irq) { - case RT3883_PCI_IRQ_PCI0: - mask = RT3833_PCI_PCIINT_PCI0; - break; - case RT3883_PCI_IRQ_PCI1: - mask = RT3833_PCI_PCIINT_PCI1; - break; - case RT3883_PCI_IRQ_PCIE: - mask = RT3833_PCI_PCIINT_PCIE; - break; - default: - BUG(); - } + rpc = irq_data_get_irq_chip_data(d); - t = rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR); - rt3883_pci_wr(t & ~mask, RT3883_PCI_REG_PCIMSK_ADDR); + t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); + rt3883_pci_w32(rpc, t & ~BIT(d->hwirq), RT3883_PCI_REG_PCIENA); /* flush write */ - rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR); + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); } static struct irq_chip rt3883_pci_irq_chip = { @@ -183,36 +192,84 @@ static struct irq_chip rt3883_pci_irq_ch .irq_mask_ack = rt3883_pci_irq_mask, }; -static void __init rt3883_pci_irq_init(void) +static int rt3883_pci_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) { - int i; + irq_set_chip_and_handler(irq, &rt3883_pci_irq_chip, handle_level_irq); + irq_set_chip_data(irq, d->host_data); + + return 0; +} + +static const struct irq_domain_ops rt3883_pci_irq_domain_ops = { + .map = rt3883_pci_irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int rt3883_pci_irq_init(struct device *dev, + struct rt3883_pci_controller *rpc) +{ + struct device_node *np = dev->of_node; + struct device_node *intc_np; + int irq; + int err; + + intc_np = of_get_child_by_name(np, "interrupt-controller"); + if (!intc_np) { + dev_err(dev, "no %s child node found", "interrupt-controller"); + return -ENODEV; + } + + irq = irq_of_parse_and_map(intc_np, 0); + if (irq == 0) { + dev_err(dev, "%s has no IRQ", of_node_full_name(intc_np)); + err = -EINVAL; + goto err_put_intc; + } /* disable all interrupts */ - rt3883_pci_wr(0, RT3883_PCI_REG_PCIMSK_ADDR); + rt3883_pci_w32(rpc, 0, RT3883_PCI_REG_PCIENA); - for (i = RT3883_PCI_IRQ_BASE; - i < RT3883_PCI_IRQ_BASE + RT3883_PCI_IRQ_COUNT; i++) { - irq_set_chip_and_handler(i, &rt3883_pci_irq_chip, - handle_level_irq); + rpc->irq_domain = + irq_domain_add_linear(intc_np, RT3883_PCI_IRQ_COUNT, + &rt3883_pci_irq_domain_ops, + rpc); + if (!rpc->irq_domain) { + dev_err(dev, "unable to add IRQ domain\n"); + err = -ENODEV; + goto err_put_intc; } - irq_set_chained_handler(RT3883_CPU_IRQ_PCI, rt3883_pci_irq_handler); + irq_set_handler_data(irq, rpc); + irq_set_chained_handler(irq, rt3883_pci_irq_handler); + + return 0; + +err_put_intc: + of_node_put(intc_np); + return err; } static int rt3883_pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { + struct rt3883_pci_controller *rpc; unsigned long flags; u32 address; u32 data; + rpc = pci_bus_to_rt3883_controller(bus); + + if (!rpc->pcie_ready && bus->number == 1) + return PCIBIOS_DEVICE_NOT_FOUND; + address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where); - spin_lock_irqsave(&rt3883_pci_lock, flags); - rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR); - data = rt3883_pci_rr(RT3883_PCI_REG_CONFIG_DATA); - spin_unlock_irqrestore(&rt3883_pci_lock, flags); + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); switch (size) { case 1: @@ -232,16 +289,22 @@ static int rt3883_pci_config_read(struct static int rt3883_pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) { + struct rt3883_pci_controller *rpc; unsigned long flags; u32 address; u32 data; + rpc = pci_bus_to_rt3883_controller(bus); + + if (!rpc->pcie_ready && bus->number == 1) + return PCIBIOS_DEVICE_NOT_FOUND; + address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where); - spin_lock_irqsave(&rt3883_pci_lock, flags); - rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR); - data = rt3883_pci_rr(RT3883_PCI_REG_CONFIG_DATA); + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); switch (size) { case 1: @@ -257,8 +320,8 @@ static int rt3883_pci_config_write(struc break; } - rt3883_pci_wr(data, RT3883_PCI_REG_CONFIG_DATA); - spin_unlock_irqrestore(&rt3883_pci_lock, flags); + rt3883_pci_w32(rpc, data, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); return PCIBIOS_SUCCESSFUL; } @@ -268,220 +331,310 @@ static struct pci_ops rt3883_pci_ops = { .write = rt3883_pci_config_write, }; -static struct resource rt3883_pci_mem_resource = { - .name = "PCI MEM space", - .start = RT3883_PCI_MEM_BASE, - .end = RT3883_PCI_MEM_BASE + RT3883_PCI_MEM_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct resource rt3883_pci_io_resource = { - .name = "PCI IO space", - .start = RT3883_PCI_IO_BASE, - .end = RT3883_PCI_IO_BASE + RT3883_PCI_IO_SIZE - 1, - .flags = IORESOURCE_IO, -}; - -static struct pci_controller rt3883_pci_controller = { - .pci_ops = &rt3883_pci_ops, - .mem_resource = &rt3883_pci_mem_resource, - .io_resource = &rt3883_pci_io_resource, -}; - -static void rt3883_pci_preinit(unsigned mode) +static void rt3883_pci_preinit(struct rt3883_pci_controller *rpc, unsigned mode) { u32 syscfg1; u32 rstctrl; u32 clkcfg1; + u32 t; + + rstctrl = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); + syscfg1 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); + clkcfg1 = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); if (mode & RT3883_PCI_MODE_PCIE) { - u32 val; + rstctrl |= RT3883_RSTCTRL_PCIE; + rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); - val = rt3883_sysc_rr(RT3883_SYSC_REG_SYSCFG1); - val &= ~(0x30); - val |= (2 << 4); - rt3883_sysc_wr(val, RT3883_SYSC_REG_SYSCFG1); - - val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN0); - val &= ~BIT(31); - rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN0); - - val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN1); - val &= 0x80ffffff; - rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN1); - - val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN1); - val |= 0xa << 24; - rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN1); - - val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN0); - val |= BIT(31); - rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN0); + /* setup PCI PAD drive mode */ + syscfg1 &= ~(0x30); + syscfg1 |= (2 << 4); + rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); + t &= ~BIT(31); + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1); + t &= 0x80ffffff; + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1); + t |= 0xa << 24; + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); + t |= BIT(31); + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); msleep(50); + + rstctrl &= ~RT3883_RSTCTRL_PCIE; + rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); } - syscfg1 = rt3883_sysc_rr(RT3883_SYSC_REG_SYSCFG1); - syscfg1 &= ~(RT3883_SYSCFG1_PCIE_RC_MODE | - RT3883_SYSCFG1_PCI_HOST_MODE); - - rstctrl = rt3883_sysc_rr(RT3883_SYSC_REG_RSTCTRL); - rstctrl |= (RT3883_RSTCTRL_PCI | RT3883_RSTCTRL_PCIE); - - clkcfg1 = rt3883_sysc_rr(RT3883_SYSC_REG_CLKCFG1); - clkcfg1 &= ~(RT3883_CLKCFG1_PCI_CLK_EN | - RT3883_CLKCFG1_PCIE_CLK_EN); + syscfg1 |= (RT3883_SYSCFG1_PCIE_RC_MODE | RT3883_SYSCFG1_PCI_HOST_MODE); + + clkcfg1 &= ~(RT3883_CLKCFG1_PCI_CLK_EN | RT3883_CLKCFG1_PCIE_CLK_EN); if (mode & RT3883_PCI_MODE_PCI) { - syscfg1 |= RT3883_SYSCFG1_PCI_HOST_MODE; clkcfg1 |= RT3883_CLKCFG1_PCI_CLK_EN; rstctrl &= ~RT3883_RSTCTRL_PCI; } + if (mode & RT3883_PCI_MODE_PCIE) { - syscfg1 |= RT3883_SYSCFG1_PCI_HOST_MODE | - RT3883_SYSCFG1_PCIE_RC_MODE; clkcfg1 |= RT3883_CLKCFG1_PCIE_CLK_EN; rstctrl &= ~RT3883_RSTCTRL_PCIE; } - rt3883_sysc_wr(syscfg1, RT3883_SYSC_REG_SYSCFG1); - rt3883_sysc_wr(rstctrl, RT3883_SYSC_REG_RSTCTRL); - rt3883_sysc_wr(clkcfg1, RT3883_SYSC_REG_CLKCFG1); + rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1); + rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); + rt_sysc_w32(clkcfg1, RT3883_SYSC_REG_CLKCFG1); msleep(500); -} -static int rt3883_pcie_ready(void) -{ - u32 status; + /* + * setup the device number of the P2P bridge + * and de-assert the reset line + */ + t = (RT3883_P2P_BR_DEVNUM << RT3883_PCICFG_P2P_BR_DEVNUM_S); + rt3883_pci_w32(rpc, t, RT3883_PCI_REG_PCICFG); + /* flush write */ + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCICFG); msleep(500); - status = rt3883_pci_rr(RT3883_PCI_REG_STATUS(1)); - if (status & BIT(0)) - return 0; + if (mode & RT3883_PCI_MODE_PCIE) { + msleep(500); + + t = rt3883_pci_r32(rpc, RT3883_PCI_REG_STATUS(1)); + + rpc->pcie_ready = t & BIT(0); + + if (!rpc->pcie_ready) { + /* reset the PCIe block */ + t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); + t |= RT3883_RSTCTRL_PCIE; + rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); + t &= ~RT3883_RSTCTRL_PCIE; + rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); + + /* turn off PCIe clock */ + t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); + t &= ~RT3883_CLKCFG1_PCIE_CLK_EN; + rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); + t &= ~0xf000c080; + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); + } + } + + /* enable PCI arbiter */ + rt3883_pci_w32(rpc, 0x79, RT3883_PCI_REG_ARBCTL); +} - /* TODO: reset PCIe and turn off PCIe clock */ +static inline void +rt3883_dump_pci_config(struct rt3883_pci_controller *rpc, + int bus, int slot) +{ + int i; + + for (i = 0; i < 16; i++) { + u32 val; - return -ENODEV; + val = rt3883_pci_read_cfg32(rpc, bus, slot, 0, i << 2); + pr_info("pci %02x:%02x.0 0x%02x = %08x\n", + bus, slot, i << 2, val); + } } -void __init rt3883_pci_init(unsigned mode) +static int rt3883_pci_probe(struct platform_device *pdev) { + struct rt3883_pci_controller *rpc; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct resource *res; + struct device_node *child; u32 val; int err; + int mode; - rt3883_pci_preinit(mode); + rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL); + if (!rpc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + rpc->base = devm_ioremap_resource(dev, res); + if (IS_ERR(rpc->base)) + return PTR_ERR(rpc->base); + + rpc->pci_controller.of_node = of_get_child_by_name(np, "host-bridge"); + if (!rpc->pci_controller.of_node) { + dev_err(dev, "no %s child node found", "host-bridge"); + return -ENODEV; + } + + mode = RT3883_PCI_MODE_NONE; + for_each_child_of_node(rpc->pci_controller.of_node, child) { + u32 slot; + + if (!of_device_is_available(child)) + continue; + + if (of_property_read_u32(child, "ralink,pci-slot", + &slot)) { + dev_err(dev, "no '%s' property found for %s\n", + "ralink,pci-slot", + of_node_full_name(child)); + continue; + } - rt3883_pci_base = ioremap(RT3883_PCI_BASE, PAGE_SIZE); - if (rt3883_pci_base == NULL) { - pr_err("failed to ioremap PCI registers\n"); - return; + switch (slot) { + case 1: + mode |= RT3883_PCI_MODE_PCIE; + break; + + case 17: + case 18: + mode |= RT3883_PCI_MODE_PCI; + break; + } } - rt3883_pci_wr(0, RT3883_PCI_REG_PCICFG_ADDR); - if (mode & RT3883_PCI_MODE_PCI) - rt3883_pci_wr(BIT(16), RT3883_PCI_REG_PCICFG_ADDR); + if (mode == RT3883_PCI_MODE_NONE) { + dev_err(dev, "unable to determine PCI mode\n"); + err = -EINVAL; + goto err_put_hb_node; + } - msleep(500); + dev_info(dev, "mode:%s%s\n", + (mode & RT3883_PCI_MODE_PCI) ? " PCI" : "", + (mode & RT3883_PCI_MODE_PCIE) ? " PCIe" : ""); - if (mode & RT3883_PCI_MODE_PCIE) { - err = rt3883_pcie_ready(); - if (err) - return; - } + rt3883_pci_preinit(rpc, mode); - if (mode & RT3883_PCI_MODE_PCI) - rt3883_pci_wr(0x79, RT3883_PCI_REG_ARBCTL); + rpc->pci_controller.pci_ops = &rt3883_pci_ops; + rpc->pci_controller.io_resource = &rpc->io_res; + rpc->pci_controller.mem_resource = &rpc->mem_res; - rt3883_pci_wr(RT3883_PCI_MEM_BASE, RT3883_PCI_REG_MEMBASE); - rt3883_pci_wr(RT3883_PCI_IO_BASE, RT3883_PCI_REG_IOBASE); + /* Load PCI I/O and memory resources from DT */ + pci_load_of_ranges(&rpc->pci_controller, + rpc->pci_controller.of_node); + + rt3883_pci_w32(rpc, rpc->mem_res.start, RT3883_PCI_REG_MEMBASE); + rt3883_pci_w32(rpc, rpc->io_res.start, RT3883_PCI_REG_IOBASE); + + ioport_resource.start = rpc->io_res.start; + ioport_resource.end = rpc->io_res.end; /* PCI */ - rt3883_pci_wr(0x03ff0000, RT3883_PCI_REG_BAR0SETUP_ADDR(0)); - rt3883_pci_wr(RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0_ADDR(0)); - rt3883_pci_wr(0x08021814, RT3883_PCI_REG_ID(0)); - rt3883_pci_wr(0x00800001, RT3883_PCI_REG_CLASS(0)); - rt3883_pci_wr(0x28801814, RT3883_PCI_REG_SUBID(0)); + rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(0)); + rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(0)); + rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(0)); + rt3883_pci_w32(rpc, 0x00800001, RT3883_PCI_REG_CLASS(0)); + rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(0)); /* PCIe */ - rt3883_pci_wr(0x01ff0000, RT3883_PCI_REG_BAR0SETUP_ADDR(1)); - rt3883_pci_wr(RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0_ADDR(1)); - rt3883_pci_wr(0x08021814, RT3883_PCI_REG_ID(1)); - rt3883_pci_wr(0x06040001, RT3883_PCI_REG_CLASS(1)); - rt3883_pci_wr(0x28801814, RT3883_PCI_REG_SUBID(1)); - - rt3883_pci_irq_init(); + rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(1)); + rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(1)); + rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(1)); + rt3883_pci_w32(rpc, 0x06040001, RT3883_PCI_REG_CLASS(1)); + rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(1)); + + err = rt3883_pci_irq_init(dev, rpc); + if (err) + goto err_put_hb_node; /* PCIe */ - val = rt3883_pci_read_u32(0, 0x01, 0, PCI_COMMAND); - val |= 0x7; - rt3883_pci_write_u32(0, 0x01, 0, PCI_COMMAND, val); + val = rt3883_pci_read_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND); + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + rt3883_pci_write_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND, val); /* PCI */ - val = rt3883_pci_read_u32(0, 0x00, 0, PCI_COMMAND); - val |= 0x7; - rt3883_pci_write_u32(0, 0x00, 0, PCI_COMMAND, val); + val = rt3883_pci_read_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND); + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + rt3883_pci_write_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND, val); + + if (mode == RT3883_PCI_MODE_PCIE) { + rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(0)); + rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(1)); + + rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, + PCI_BASE_ADDRESS_0, + RT3883_MEMORY_BASE); + /* flush write */ + rt3883_pci_read_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, + PCI_BASE_ADDRESS_0); + } else { + rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, + PCI_IO_BASE, 0x00000101); + } + + register_pci_controller(&rpc->pci_controller); - ioport_resource.start = rt3883_pci_io_resource.start; - ioport_resource.end = rt3883_pci_io_resource.end; + return 0; - register_pci_controller(&rt3883_pci_controller); +err_put_hb_node: + of_node_put(rpc->pci_controller.of_node); + return err; } int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { - int irq = -1; - - switch (dev->bus->number) { - case 0: - switch (PCI_SLOT(dev->devfn)) { - case 0x00: - rt3883_pci_wr(0x03ff0001, - RT3883_PCI_REG_BAR0SETUP_ADDR(0)); - rt3883_pci_wr(0x03ff0001, - RT3883_PCI_REG_BAR0SETUP_ADDR(1)); - - rt3883_pci_write_u32(0, 0x00, 0, PCI_BASE_ADDRESS_0, - RT3883_MEMORY_BASE); - rt3883_pci_read_u32(0, 0x00, 0, PCI_BASE_ADDRESS_0); - - irq = RT3883_CPU_IRQ_PCI; - break; - case 0x01: - rt3883_pci_write_u32(0, 0x01, 0, PCI_IO_BASE, - 0x00000101); - break; - case 0x11: - irq = RT3883_PCI_IRQ_PCI0; - break; - case 0x12: - irq = RT3883_PCI_IRQ_PCI1; - break; - } - break; - - case 1: - irq = RT3883_PCI_IRQ_PCIE; - break; + struct rt3883_pci_controller *rpc; + struct of_irq dev_irq; + int err; + int irq; - default: - dev_err(&dev->dev, "no IRQ specified\n"); - return irq; + rpc = pci_bus_to_rt3883_controller(dev->bus); + err = of_irq_map_pci(dev, &dev_irq); + if (err) { + pr_err("pci %s: unable to get irq map, err=%d\n", + pci_name((struct pci_dev *) dev), err); + return 0; } + irq = irq_create_of_mapping(dev_irq.controller, + dev_irq.specifier, + dev_irq.size); + + if (irq == 0) + pr_crit("pci %s: no irq found for pin %u\n", + pci_name((struct pci_dev *) dev), pin); + else + pr_info("pci %s: using irq %d for pin %u\n", + pci_name((struct pci_dev *) dev), irq, pin); + return irq; } -void __init rt3883_pci_set_plat_dev_init(int (*f)(struct pci_dev *dev)) +int pcibios_plat_dev_init(struct pci_dev *dev) { - rt3883_pci_plat_dev_init = f; + return 0; } -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - if (rt3883_pci_plat_dev_init) - return rt3883_pci_plat_dev_init(dev); +static const struct of_device_id rt3883_pci_ids[] = { + { .compatible = "ralink,rt3883-pci" }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt3883_pci_ids); - return 0; +static struct platform_driver rt3883_pci_driver = { + .probe = rt3883_pci_probe, + .driver = { + .name = "rt3883-pci", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rt3883_pci_ids), + }, +}; + +static int __init rt3883_pci_init(void) +{ + return platform_driver_register(&rt3883_pci_driver); } + +postcore_initcall(rt3883_pci_init);