static void __init ppc4xx_pciex_port_init_mapping(struct ppc4xx_pciex_port *port) { /* We map PCI Express configuration based on the reg property */ dcr_write(port->dcrs, DCRO_PEGPL_CFGBAH, RES_TO_U32_HIGH(port->cfg_space.start)); dcr_write(port->dcrs, DCRO_PEGPL_CFGBAL, RES_TO_U32_LOW(port->cfg_space.start)); /* XXX FIXME: Use size from reg property. For now, map 512M */ dcr_write(port->dcrs, DCRO_PEGPL_CFGMSK, 0xe0000001); /* We map UTL registers based on the reg property */ dcr_write(port->dcrs, DCRO_PEGPL_REGBAH, RES_TO_U32_HIGH(port->utl_regs.start)); dcr_write(port->dcrs, DCRO_PEGPL_REGBAL, RES_TO_U32_LOW(port->utl_regs.start)); /* XXX FIXME: Use size from reg property */ dcr_write(port->dcrs, DCRO_PEGPL_REGMSK, 0x00007001); /* Disable all other outbound windows */ dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, 0); dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, 0); dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, 0); dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0); }
static int nwpserial_startup(struct uart_port *port) { struct nwpserial_port *up; int err; up = container_of(port, struct nwpserial_port, port); /* disable flow control by default */ up->mcr = dcr_read(up->dcr_host, UART_MCR) & ~UART_MCR_AFE; dcr_write(up->dcr_host, UART_MCR, up->mcr); /* register interrupt handler */ err = request_irq(up->port.irq, nwpserial_interrupt, IRQF_SHARED, "nwpserial", up); if (err) return err; /* enable interrupts */ up->ier = UART_IER_RDI; dcr_write(up->dcr_host, UART_IER, up->ier); /* enable receiving */ up->port.ignore_status_mask &= ~NWPSERIAL_STATUS_RXVALID; return 0; }
static void nwpserial_console_write(struct console *co, const char *s, unsigned int count) { struct nwpserial_port *up = &nwpserial_ports[co->index]; unsigned long flags; int locked = 1; if (oops_in_progress) locked = spin_trylock_irqsave(&up->port.lock, flags); else spin_lock_irqsave(&up->port.lock, flags); /* save and disable interrupt */ up->ier = dcr_read(up->dcr_host, UART_IER); dcr_write(up->dcr_host, UART_IER, up->ier & ~UART_IER_RDI); uart_console_write(&up->port, s, count, nwpserial_console_putchar); /* wait for transmitter to become emtpy */ while ((dcr_read(up->dcr_host, UART_LSR) & UART_LSR_THRE) == 0) cpu_relax(); /* restore interrupt state */ dcr_write(up->dcr_host, UART_IER, up->ier); if (locked) spin_unlock_irqrestore(&up->port.lock, flags); }
static int ppc4xx_pciex_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { struct pci_controller *hose = pci_bus_to_host(bus); struct ppc4xx_pciex_port *port = &ppc4xx_pciex_ports[hose->indirect_type]; void __iomem *addr; u32 gpl_cfg; BUG_ON(hose != port->hose); if (ppc4xx_pciex_validate_bdf(port, bus, devfn) != 0) return PCIBIOS_DEVICE_NOT_FOUND; addr = ppc4xx_pciex_get_config_base(port, bus, devfn); /* * Reading from configuration space of non-existing device can * generate transaction errors. For the read duration we suppress * assertion of machine check exceptions to avoid those. */ gpl_cfg = dcr_read(port->dcrs, DCRO_PEGPL_CFG); dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg | GPL_DMER_MASK_DISA); /* Make sure no CRS is recorded */ out_be32(port->utl_base + PEUTL_RCSTA, 0x00040000); switch (len) { case 1: *val = in_8((u8 *)(addr + offset)); break; case 2: *val = in_le16((u16 *)(addr + offset)); break; default: *val = in_le32((u32 *)(addr + offset)); break; } pr_debug("pcie-config-read: bus=%3d [%3d..%3d] devfn=0x%04x" " offset=0x%04x len=%d, addr=0x%p val=0x%08x\n", bus->number, hose->first_busno, hose->last_busno, devfn, offset, len, addr + offset, *val); /* Check for CRS (440SPe rev B does that for us but heh ..) */ if (in_be32(port->utl_base + PEUTL_RCSTA) & 0x00040000) { pr_debug("Got CRS !\n"); if (len != 4 || offset != 0) return PCIBIOS_DEVICE_NOT_FOUND; *val = 0xffff0001; } dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg); return PCIBIOS_SUCCESSFUL; }
static ssize_t dcrraw_write(struct file *filp, const char __user *buf, size_t len, loff_t *off) { unsigned long dcrn; unsigned long value; unsigned long res; if(len != 4) { printk(KERN_DEBUG "dcrraw_write: wrong len :%i\n", (int)len); return -EINVAL; } if(*off % 4 != 0) { printk(KERN_DEBUG "dcrraw_write: wrong offset: %lu\n", *off); return -EINVAL; } if(*off >= 4*1024) { printk(KERN_DEBUG "dcrraw_write: offset to large: %lu\n", *off); return -EINVAL; } dcrn = (unsigned long)(*off / 4); if ((res = copy_from_user(&value, buf, 4))){ printk(KERN_DEBUG "dcrraw_write: copy from user failed\n"); res = -EFAULT; } printk(KERN_DEBUG "dcrrraw: writing value 0x%08lX to dcrn 0x%08lX\n", value, dcrn); dcr_write(dcrn, value); return 4; }
static void nwpserial_putchar(struct nwpserial_port *up, unsigned char c) { /* check if tx buffer is full */ wait_for_bits(up, UART_LSR_THRE); dcr_write(up->dcr_host, UART_TX, c); up->port.icount.tx++; }
static irqreturn_t nwpserial_interrupt(int irq, void *dev_id) { struct nwpserial_port *up = dev_id; struct tty_struct *tty = up->port.state->port.tty; irqreturn_t ret; unsigned int iir; unsigned char ch; spin_lock(&up->port.lock); /* check if the uart was the interrupt source. */ iir = dcr_read(up->dcr_host, UART_IIR); if (!iir) { ret = IRQ_NONE; goto out; } do { up->port.icount.rx++; ch = dcr_read(up->dcr_host, UART_RX); if (up->port.ignore_status_mask != NWPSERIAL_STATUS_RXVALID) tty_insert_flip_char(tty, ch, TTY_NORMAL); } while (dcr_read(up->dcr_host, UART_LSR) & UART_LSR_DR); tty_flip_buffer_push(tty); ret = IRQ_HANDLED; /* clear interrupt */ dcr_write(up->dcr_host, UART_IIR, 1); out: spin_unlock(&up->port.lock); return ret; }
static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) { u32 val; if (port->endpoint) val = PTYPE_LEGACY_ENDPOINT; else val = PTYPE_ROOT_PORT; mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, 1 << 24 | val << 20 | LNKW_X1 << 12); mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, 0x00000000); mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01010000); mtdcri(SDR0, port->sdr_base + PESDRn_405EX_PHYSET1, 0x720F0000); mtdcri(SDR0, port->sdr_base + PESDRn_405EX_PHYSET2, 0x70600003); /* * Only reset the PHY when no link is currently established. * This is for the Atheros PCIe board which has problems to establish * the link (again) after this PHY reset. All other currently tested * PCIe boards don't show this problem. * This has to be re-tested and fixed in a later release! */ val = mfdcri(SDR0, port->sdr_base + PESDRn_LOOP); if (!(val & 0x00001000)) ppc405ex_pcie_phy_reset(port); dcr_write(port->dcrs, DCRO_PEGPL_CFG, 0x10000000); /* guarded on */ port->has_ibpre = 1; return 0; }
/* * The XPS TFT Controller can be accessed through PLB or DCR interface. * To perform the read/write on the registers we need to check on * which bus its connected and call the appropriate write API. */ static void xilinx_fb_out_be32(struct xilinxfb_drvdata *drvdata, u32 offset, u32 val) { if (drvdata->flags & PLB_ACCESS_FLAG) out_be32(drvdata->regs + (offset << 2), val); else dcr_write(drvdata->dcr_host, offset, val); }
static void nwpserial_console_putchar(struct uart_port *port, int c) { struct nwpserial_port *up; up = container_of(port, struct nwpserial_port, port); /* check if tx buffer is full */ wait_for_bits(up, UART_LSR_THRE); dcr_write(up->dcr_host, UART_TX, c); up->port.icount.tx++; }
/* * The XPS TFT Controller can be accessed through PLB or DCR interface. * To perform the read/write on the registers we need to check on * which bus its connected and call the appropriate write API. */ static void xilinx_fb_out_be32(struct xilinxfb_drvdata *drvdata, u32 offset, u32 val) { if (drvdata->flags & PLB_ACCESS_FLAG) iowrite32(val, drvdata->regs + (offset << 2)); #ifdef CONFIG_PPC_DCR else dcr_write(drvdata->dcr_host, offset, val); #endif }
static int ppc4xx_pciex_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose = pci_bus_to_host(bus); struct ppc4xx_pciex_port *port = &ppc4xx_pciex_ports[hose->indirect_type]; void __iomem *addr; u32 gpl_cfg; if (ppc4xx_pciex_validate_bdf(port, bus, devfn) != 0) return PCIBIOS_DEVICE_NOT_FOUND; addr = ppc4xx_pciex_get_config_base(port, bus, devfn); /* * Reading from configuration space of non-existing device can * generate transaction errors. For the read duration we suppress * assertion of machine check exceptions to avoid those. */ gpl_cfg = dcr_read(port->dcrs, DCRO_PEGPL_CFG); dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg | GPL_DMER_MASK_DISA); pr_debug("pcie-config-write: bus=%3d [%3d..%3d] devfn=0x%04x" " offset=0x%04x len=%d, addr=0x%p val=0x%08x\n", bus->number, hose->first_busno, hose->last_busno, devfn, offset, len, addr + offset, val); switch (len) { case 1: out_8((u8 *)(addr + offset), val); break; case 2: out_le16((u16 *)(addr + offset), val); break; default: out_le32((u32 *)(addr + offset), val); break; } dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg); return PCIBIOS_SUCCESSFUL; }
/* * The XPS TFT Controller can be accessed through BUS or DCR interface. * To perform the read/write on the registers we need to check on * which bus its connected and call the appropriate write API. */ static void xilinx_fb_out32(struct xilinxfb_drvdata *drvdata, u32 offset, u32 val) { if (drvdata->flags & BUS_ACCESS_FLAG) { if (drvdata->flags & LITTLE_ENDIAN_ACCESS) iowrite32(val, drvdata->regs + (offset << 2)); else iowrite32be(val, drvdata->regs + (offset << 2)); } #ifdef CONFIG_PPC_DCR else dcr_write(drvdata->dcr_host, offset, val); #endif }
/// /// Write to OSIF registers. /// /// This function performs DCR writes on the OSIF registers. Every OSIF /// register is 32 bits in length /// Again, we support byte-wise reads, though all registers should be /// read together. See osif_read() for details. /// /// \param filp Pointer to kernel file structure /// \param buf Pointer to _user-space_ buffer /// \param count Number of bytes to write /// \param f_pos Offset into the DCR registers in bytes /// /// \return The number of written bytes /// ssize_t osif_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct osif_dev *dev = filp->private_data; size_t to_copy = 0, remaining = 0; ssize_t retval; int i; PDEBUG("trying to write %d bytes to pos %ld\n", count, (unsigned long int)*f_pos); if (dev->next_write != *f_pos) printk(KERN_WARNING "osif: non-consecutive write access, possible data loss!\n"); // calculate how many bytes can be written max. remaining = sizeof(dev->write_buffer) - *f_pos; if (count >= remaining) to_copy = remaining; else to_copy = count; // bytewise copy data from user space to write buffer if ((retval = copy_from_user(&((char *)(dev->write_buffer))[*f_pos], buf, to_copy))){ retval = -EFAULT; } else { retval = to_copy; } // update file position pointer, wrap to 0 if beyond end of write buffer *f_pos += to_copy; if (*f_pos >= sizeof(dev->write_buffer)) { *f_pos = 0; // if the buffer is full, we need to write to dcr PDEBUG("writing to DCR\n"); // intercept command MMU_SETPGD if(dev->write_buffer[0] == OSIF_CMD_MMU_SETPGD && !dev->write_buffer[1]){ dev->write_buffer[1] = ((unsigned int)current->mm->pgd) - 0xC0000000; PDEBUG("osif: intercepting command SETPGD. setting pgd to 0x%08X\n",dev->write_buffer[1]); } for (i = 0; i < OSIF_DCR_WRITESIZE; i++) { dcr_write(dev->dcr_host, i, dev->write_buffer[i]); PDEBUG("wrote 0x%08X to register %d (DCR address %d)\n", dev->write_buffer[i], i, DCR_ADDR(dev->dcr_host) + i); } } dev->next_write = *f_pos; return retval; }
static void nwpserial_shutdown(struct uart_port *port) { struct nwpserial_port *up; up = container_of(port, struct nwpserial_port, port); /* disable receiving */ up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID; /* disable interrupts from this port */ up->ier = 0; dcr_write(up->dcr_host, UART_IER, up->ier); /* free irq */ free_irq(up->port.irq, port); }
static inline void _mpic_write(enum mpic_reg_type type, struct mpic_reg_bank *rb, unsigned int reg, u32 value) { switch(type) { #ifdef CONFIG_PPC_DCR case mpic_access_dcr: return dcr_write(rb->dhost, reg, value); #endif case mpic_access_mmio_be: return out_be32(rb->base + (reg >> 2), value); case mpic_access_mmio_le: default: return out_le32(rb->base + (reg >> 2), value); } }
static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port) { dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x0); /* * Set buffer allocations and then assert VRB and TXE. */ out_be32(port->utl_base + PEUTL_PBCTL, 0x0800000c); out_be32(port->utl_base + PEUTL_OUTTR, 0x08000000); out_be32(port->utl_base + PEUTL_INTR, 0x02000000); out_be32(port->utl_base + PEUTL_OPDBSZ, 0x04000000); out_be32(port->utl_base + PEUTL_PBBSZ, 0x00000000); out_be32(port->utl_base + PEUTL_IPHBSZ, 0x02000000); out_be32(port->utl_base + PEUTL_IPDBSZ, 0x04000000); out_be32(port->utl_base + PEUTL_RCIRQEN,0x00f00000); out_be32(port->utl_base + PEUTL_PCTL, 0x80800066); return 0; }
static int ppc440speA_pciex_init_utl(struct ppc4xx_pciex_port *port) { /* XXX Check what that value means... I hate magic */ dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x68782800); /* * Set buffer allocations and then assert VRB and TXE. */ out_be32(port->utl_base + PEUTL_OUTTR, 0x08000000); out_be32(port->utl_base + PEUTL_INTR, 0x02000000); out_be32(port->utl_base + PEUTL_OPDBSZ, 0x10000000); out_be32(port->utl_base + PEUTL_PBBSZ, 0x53000000); out_be32(port->utl_base + PEUTL_IPHBSZ, 0x08000000); out_be32(port->utl_base + PEUTL_IPDBSZ, 0x10000000); out_be32(port->utl_base + PEUTL_RCIRQEN, 0x00f00000); out_be32(port->utl_base + PEUTL_PCTL, 0x80800066); return 0; }
static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, struct pci_controller *hose, void __iomem *mbase) { u32 lah, lal, pciah, pcial, sa; int i, j; /* Setup outbound memory windows */ for (i = j = 0; i < 3; i++) { struct resource *res = &hose->mem_resources[i]; /* we only care about memory windows */ if (!(res->flags & IORESOURCE_MEM)) continue; if (j > 1) { printk(KERN_WARNING "%s: Too many ranges\n", port->node->full_name); break; } /* Calculate register values */ lah = RES_TO_U32_HIGH(res->start); lal = RES_TO_U32_LOW(res->start); pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset); pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset); sa = res->end + 1 - res->start; if (!is_power_of_2(sa) || sa < 0x100000 || sa > 0xffffffffu) { printk(KERN_WARNING "%s: Resource out of range\n", port->node->full_name); continue; } sa = (0xffffffffu << ilog2(sa)) | 0x1; /* Program register values */ switch (j) { case 0: out_le32(mbase + PECFG_POM0LAH, pciah); out_le32(mbase + PECFG_POM0LAL, pcial); dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah); dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal); dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3); break; case 1: out_le32(mbase + PECFG_POM1LAH, pciah); out_le32(mbase + PECFG_POM1LAL, pcial); dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah); dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal); dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3); break; } j++; } /* Configure IO, always 64K starting at 0 */ if (hose->io_resource.flags & IORESOURCE_IO) { lah = RES_TO_U32_HIGH(hose->io_base_phys); lal = RES_TO_U32_LOW(hose->io_base_phys); out_le32(mbase + PECFG_POM2LAH, 0); out_le32(mbase + PECFG_POM2LAL, 0); dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah); dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal); dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff); dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, 0xffff0000 | 3); } }
static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port, struct pci_controller *hose, void __iomem *mbase, u64 plb_addr, u64 pci_addr, u64 size, unsigned int flags, int index) { u32 lah, lal, pciah, pcial, sa; if (!is_power_of_2(size) || (index < 2 && size < 0x100000) || (index == 2 && size < 0x100) || (plb_addr & (size - 1)) != 0) { printk(KERN_WARNING "%s: Resource out of range\n", hose->dn->full_name); return -1; } /* Calculate register values */ lah = RES_TO_U32_HIGH(plb_addr); lal = RES_TO_U32_LOW(plb_addr); pciah = RES_TO_U32_HIGH(pci_addr); pcial = RES_TO_U32_LOW(pci_addr); sa = (0xffffffffu << ilog2(size)) | 0x1; /* Program register values */ switch (index) { case 0: out_le32(mbase + PECFG_POM0LAH, pciah); out_le32(mbase + PECFG_POM0LAL, pcial); dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah); dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal); dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); /* Note that 3 here means enabled | single region */ dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3); break; case 1: out_le32(mbase + PECFG_POM1LAH, pciah); out_le32(mbase + PECFG_POM1LAL, pcial); dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah); dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal); dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); /* Note that 3 here means enabled | single region */ dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3); break; case 2: out_le32(mbase + PECFG_POM2LAH, pciah); out_le32(mbase + PECFG_POM2LAL, pcial); dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah); dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal); dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff); /* Note that 3 here means enabled | IO space !!! */ dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3); break; } return 0; }
void tlb_setid(reconos_tlb_t * tlb, unsigned long id){ fprintf(stderr, "tlb_setid called\n"); dcr_write(tlb->id_dcrn, id); }
/******************************************************************************* Name: mvpstb_set_lbox_offset Description: Sets the offset for letterboxed output, seems to be in lines per field Return: *******************************************************************************/ int mvpstb_set_lbox_offset(unsigned int offset) { return(dcr_write(VIDEO_LETTERBOX_OFFSET,offset)); }
void tlb_invalidate(reconos_tlb_t * tlb) { fprintf(stderr, "tlb_invalidate called\n"); dcr_write(tlb->invalidate_dcrn,TLB_INVALIDATE); }
static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) { pr_devel("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); dcr_write(msic->dcr_host, dcr_n, val); }
/** * temac_dma_dcr_out32 - DCR based DMA write */ static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value) { dcr_write(lp->sdma_dcrs, reg, value); }