Loading drivers/staging/vme/TODO +0 −1 Original line number Diff line number Diff line Loading @@ -58,7 +58,6 @@ Universe II (ca91c142) - DMA unsupported. - RMW transactions unsupported. - Location Monitors unsupported. - Mailboxes unsupported. - Error Detection. - Control of prefetch size, threshold. Loading drivers/staging/vme/bridges/vme_ca91cx42.c +200 −72 Original line number Diff line number Diff line Loading @@ -899,6 +899,206 @@ ssize_t ca91cx42_master_write(struct vme_master_resource *image, void *buf, return retval; } /* * All 4 location monitors reside at the same base - this is therefore a * system wide configuration. * * This does not enable the LM monitor - that should be done when the first * callback is attached and disabled when the last callback is removed. */ int ca91cx42_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, vme_address_t aspace, vme_cycle_t cycle) { u32 temp_base, lm_ctl = 0; int i; struct ca91cx42_driver *bridge; struct device *dev; bridge = lm->parent->driver_priv; dev = lm->parent->parent; /* Check the alignment of the location monitor */ temp_base = (u32)lm_base; if (temp_base & 0xffff) { dev_err(dev, "Location monitor must be aligned to 64KB " "boundary"); return -EINVAL; } mutex_lock(&(lm->mtx)); /* If we already have a callback attached, we can't move it! */ for (i = 0; i < lm->monitors; i++) { if (bridge->lm_callback[i] != NULL) { mutex_unlock(&(lm->mtx)); dev_err(dev, "Location monitor callback attached, " "can't reset\n"); return -EBUSY; } } switch (aspace) { case VME_A16: lm_ctl |= CA91CX42_LM_CTL_AS_A16; break; case VME_A24: lm_ctl |= CA91CX42_LM_CTL_AS_A24; break; case VME_A32: lm_ctl |= CA91CX42_LM_CTL_AS_A32; break; default: mutex_unlock(&(lm->mtx)); dev_err(dev, "Invalid address space\n"); return -EINVAL; break; } if (cycle & VME_SUPER) lm_ctl |= CA91CX42_LM_CTL_SUPR; if (cycle & VME_USER) lm_ctl |= CA91CX42_LM_CTL_NPRIV; if (cycle & VME_PROG) lm_ctl |= CA91CX42_LM_CTL_PGM; if (cycle & VME_DATA) lm_ctl |= CA91CX42_LM_CTL_DATA; iowrite32(lm_base, bridge->base + LM_BS); iowrite32(lm_ctl, bridge->base + LM_CTL); mutex_unlock(&(lm->mtx)); return 0; } /* Get configuration of the callback monitor and return whether it is enabled * or disabled. */ int ca91cx42_lm_get(struct vme_lm_resource *lm, unsigned long long *lm_base, vme_address_t *aspace, vme_cycle_t *cycle) { u32 lm_ctl, enabled = 0; struct ca91cx42_driver *bridge; bridge = lm->parent->driver_priv; mutex_lock(&(lm->mtx)); *lm_base = (unsigned long long)ioread32(bridge->base + LM_BS); lm_ctl = ioread32(bridge->base + LM_CTL); if (lm_ctl & CA91CX42_LM_CTL_EN) enabled = 1; if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16) *aspace = VME_A16; if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24) *aspace = VME_A24; if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32) *aspace = VME_A32; *cycle = 0; if (lm_ctl & CA91CX42_LM_CTL_SUPR) *cycle |= VME_SUPER; if (lm_ctl & CA91CX42_LM_CTL_NPRIV) *cycle |= VME_USER; if (lm_ctl & CA91CX42_LM_CTL_PGM) *cycle |= VME_PROG; if (lm_ctl & CA91CX42_LM_CTL_DATA) *cycle |= VME_DATA; mutex_unlock(&(lm->mtx)); return enabled; } /* * Attach a callback to a specific location monitor. * * Callback will be passed the monitor triggered. */ int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, void (*callback)(int)) { u32 lm_ctl, tmp; struct ca91cx42_driver *bridge; struct device *dev; bridge = lm->parent->driver_priv; dev = lm->parent->parent; mutex_lock(&(lm->mtx)); /* Ensure that the location monitor is configured - need PGM or DATA */ lm_ctl = ioread32(bridge->base + LM_CTL); if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) { mutex_unlock(&(lm->mtx)); dev_err(dev, "Location monitor not properly configured\n"); return -EINVAL; } /* Check that a callback isn't already attached */ if (bridge->lm_callback[monitor] != NULL) { mutex_unlock(&(lm->mtx)); dev_err(dev, "Existing callback attached\n"); return -EBUSY; } /* Attach callback */ bridge->lm_callback[monitor] = callback; /* Enable Location Monitor interrupt */ tmp = ioread32(bridge->base + LINT_EN); tmp |= CA91CX42_LINT_LM[monitor]; iowrite32(tmp, bridge->base + LINT_EN); /* Ensure that global Location Monitor Enable set */ if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) { lm_ctl |= CA91CX42_LM_CTL_EN; iowrite32(lm_ctl, bridge->base + LM_CTL); } mutex_unlock(&(lm->mtx)); return 0; } /* * Detach a callback function forn a specific location monitor. */ int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor) { u32 tmp; struct ca91cx42_driver *bridge; bridge = lm->parent->driver_priv; mutex_lock(&(lm->mtx)); /* Disable Location Monitor and ensure previous interrupts are clear */ tmp = ioread32(bridge->base + LINT_EN); tmp &= ~CA91CX42_LINT_LM[monitor]; iowrite32(tmp, bridge->base + LINT_EN); iowrite32(CA91CX42_LINT_LM[monitor], bridge->base + LINT_STAT); /* Detach callback */ bridge->lm_callback[monitor] = NULL; /* If all location monitors disabled, disable global Location Monitor */ if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | CA91CX42_LINT_LM3)) == 0) { tmp = ioread32(bridge->base + LM_CTL); tmp &= ~CA91CX42_LM_CTL_EN; iowrite32(tmp, bridge->base + LM_CTL); } mutex_unlock(&(lm->mtx)); return 0; } int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) { u32 slot = 0; Loading Loading @@ -1190,12 +1390,10 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) #endif ca91cx42_bridge->irq_set = ca91cx42_irq_set; ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; #if 0 ca91cx42_bridge->lm_set = ca91cx42_lm_set; ca91cx42_bridge->lm_get = ca91cx42_lm_get; ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; #endif ca91cx42_bridge->slot_get = ca91cx42_slot_get; data = ioread32(ca91cx42_device->base + MISC_CTL); Loading Loading @@ -1786,77 +1984,7 @@ int ca91cx42_do_dma(vmeDmaPacket_t *vmeDma) return 0; } int ca91cx42_lm_set(vmeLmCfg_t *vmeLm) { int temp_ctl = 0; if (vmeLm->addrU) return -EINVAL; switch (vmeLm->addrSpace) { case VME_A64: case VME_USER3: case VME_USER4: return -EINVAL; case VME_A16: temp_ctl |= 0x00000; break; case VME_A24: temp_ctl |= 0x10000; break; case VME_A32: temp_ctl |= 0x20000; break; case VME_CRCSR: temp_ctl |= 0x50000; break; case VME_USER1: temp_ctl |= 0x60000; break; case VME_USER2: temp_ctl |= 0x70000; break; } /* Disable while we are mucking around */ iowrite32(0x00000000, bridge->base + LM_CTL); iowrite32(vmeLm->addr, bridge->base + LM_BS); /* Setup CTL register. */ if (vmeLm->userAccessType & VME_SUPER) temp_ctl |= 0x00200000; if (vmeLm->userAccessType & VME_USER) temp_ctl |= 0x00100000; if (vmeLm->dataAccessType & VME_PROG) temp_ctl |= 0x00800000; if (vmeLm->dataAccessType & VME_DATA) temp_ctl |= 0x00400000; /* Write ctl reg and enable */ iowrite32(0x80000000 | temp_ctl, bridge->base + LM_CTL); temp_ctl = ioread32(bridge->base + LM_CTL); return 0; } int ca91cx42_wait_lm(vmeLmCfg_t *vmeLm) { unsigned long flags; unsigned int tmp; spin_lock_irqsave(&lm_lock, flags); spin_unlock_irqrestore(&lm_lock, flags); if (tmp == 0) { if (vmeLm->lmWait < 10) vmeLm->lmWait = 10; interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait); } iowrite32(0x00000000, bridge->base + LM_CTL); return 0; } Loading drivers/staging/vme/bridges/vme_ca91cx42.h +13 −0 Original line number Diff line number Diff line Loading @@ -491,6 +491,19 @@ static const int CA91CX42_LINT_LM[] = { CA91CX42_LINT_LM0, CA91CX42_LINT_LM1, #define CA91CX42_VSI_CTL_LAS_PCI_IO (1<<0) #define CA91CX42_VSI_CTL_LAS_PCI_CONF (1<<1) /* LM_CTL Register * offset F64 */ #define CA91CX42_LM_CTL_EN (1<<31) #define CA91CX42_LM_CTL_PGM (1<<23) #define CA91CX42_LM_CTL_DATA (1<<22) #define CA91CX42_LM_CTL_SUPR (1<<21) #define CA91CX42_LM_CTL_NPRIV (1<<20) #define CA91CX42_LM_CTL_AS_M (5<<16) #define CA91CX42_LM_CTL_AS_A16 0 #define CA91CX42_LM_CTL_AS_A24 (1<<16) #define CA91CX42_LM_CTL_AS_A32 (1<<17) /* * VRAI_CTL Register * offset F70 Loading Loading
drivers/staging/vme/TODO +0 −1 Original line number Diff line number Diff line Loading @@ -58,7 +58,6 @@ Universe II (ca91c142) - DMA unsupported. - RMW transactions unsupported. - Location Monitors unsupported. - Mailboxes unsupported. - Error Detection. - Control of prefetch size, threshold. Loading
drivers/staging/vme/bridges/vme_ca91cx42.c +200 −72 Original line number Diff line number Diff line Loading @@ -899,6 +899,206 @@ ssize_t ca91cx42_master_write(struct vme_master_resource *image, void *buf, return retval; } /* * All 4 location monitors reside at the same base - this is therefore a * system wide configuration. * * This does not enable the LM monitor - that should be done when the first * callback is attached and disabled when the last callback is removed. */ int ca91cx42_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, vme_address_t aspace, vme_cycle_t cycle) { u32 temp_base, lm_ctl = 0; int i; struct ca91cx42_driver *bridge; struct device *dev; bridge = lm->parent->driver_priv; dev = lm->parent->parent; /* Check the alignment of the location monitor */ temp_base = (u32)lm_base; if (temp_base & 0xffff) { dev_err(dev, "Location monitor must be aligned to 64KB " "boundary"); return -EINVAL; } mutex_lock(&(lm->mtx)); /* If we already have a callback attached, we can't move it! */ for (i = 0; i < lm->monitors; i++) { if (bridge->lm_callback[i] != NULL) { mutex_unlock(&(lm->mtx)); dev_err(dev, "Location monitor callback attached, " "can't reset\n"); return -EBUSY; } } switch (aspace) { case VME_A16: lm_ctl |= CA91CX42_LM_CTL_AS_A16; break; case VME_A24: lm_ctl |= CA91CX42_LM_CTL_AS_A24; break; case VME_A32: lm_ctl |= CA91CX42_LM_CTL_AS_A32; break; default: mutex_unlock(&(lm->mtx)); dev_err(dev, "Invalid address space\n"); return -EINVAL; break; } if (cycle & VME_SUPER) lm_ctl |= CA91CX42_LM_CTL_SUPR; if (cycle & VME_USER) lm_ctl |= CA91CX42_LM_CTL_NPRIV; if (cycle & VME_PROG) lm_ctl |= CA91CX42_LM_CTL_PGM; if (cycle & VME_DATA) lm_ctl |= CA91CX42_LM_CTL_DATA; iowrite32(lm_base, bridge->base + LM_BS); iowrite32(lm_ctl, bridge->base + LM_CTL); mutex_unlock(&(lm->mtx)); return 0; } /* Get configuration of the callback monitor and return whether it is enabled * or disabled. */ int ca91cx42_lm_get(struct vme_lm_resource *lm, unsigned long long *lm_base, vme_address_t *aspace, vme_cycle_t *cycle) { u32 lm_ctl, enabled = 0; struct ca91cx42_driver *bridge; bridge = lm->parent->driver_priv; mutex_lock(&(lm->mtx)); *lm_base = (unsigned long long)ioread32(bridge->base + LM_BS); lm_ctl = ioread32(bridge->base + LM_CTL); if (lm_ctl & CA91CX42_LM_CTL_EN) enabled = 1; if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16) *aspace = VME_A16; if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24) *aspace = VME_A24; if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32) *aspace = VME_A32; *cycle = 0; if (lm_ctl & CA91CX42_LM_CTL_SUPR) *cycle |= VME_SUPER; if (lm_ctl & CA91CX42_LM_CTL_NPRIV) *cycle |= VME_USER; if (lm_ctl & CA91CX42_LM_CTL_PGM) *cycle |= VME_PROG; if (lm_ctl & CA91CX42_LM_CTL_DATA) *cycle |= VME_DATA; mutex_unlock(&(lm->mtx)); return enabled; } /* * Attach a callback to a specific location monitor. * * Callback will be passed the monitor triggered. */ int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, void (*callback)(int)) { u32 lm_ctl, tmp; struct ca91cx42_driver *bridge; struct device *dev; bridge = lm->parent->driver_priv; dev = lm->parent->parent; mutex_lock(&(lm->mtx)); /* Ensure that the location monitor is configured - need PGM or DATA */ lm_ctl = ioread32(bridge->base + LM_CTL); if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) { mutex_unlock(&(lm->mtx)); dev_err(dev, "Location monitor not properly configured\n"); return -EINVAL; } /* Check that a callback isn't already attached */ if (bridge->lm_callback[monitor] != NULL) { mutex_unlock(&(lm->mtx)); dev_err(dev, "Existing callback attached\n"); return -EBUSY; } /* Attach callback */ bridge->lm_callback[monitor] = callback; /* Enable Location Monitor interrupt */ tmp = ioread32(bridge->base + LINT_EN); tmp |= CA91CX42_LINT_LM[monitor]; iowrite32(tmp, bridge->base + LINT_EN); /* Ensure that global Location Monitor Enable set */ if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) { lm_ctl |= CA91CX42_LM_CTL_EN; iowrite32(lm_ctl, bridge->base + LM_CTL); } mutex_unlock(&(lm->mtx)); return 0; } /* * Detach a callback function forn a specific location monitor. */ int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor) { u32 tmp; struct ca91cx42_driver *bridge; bridge = lm->parent->driver_priv; mutex_lock(&(lm->mtx)); /* Disable Location Monitor and ensure previous interrupts are clear */ tmp = ioread32(bridge->base + LINT_EN); tmp &= ~CA91CX42_LINT_LM[monitor]; iowrite32(tmp, bridge->base + LINT_EN); iowrite32(CA91CX42_LINT_LM[monitor], bridge->base + LINT_STAT); /* Detach callback */ bridge->lm_callback[monitor] = NULL; /* If all location monitors disabled, disable global Location Monitor */ if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | CA91CX42_LINT_LM3)) == 0) { tmp = ioread32(bridge->base + LM_CTL); tmp &= ~CA91CX42_LM_CTL_EN; iowrite32(tmp, bridge->base + LM_CTL); } mutex_unlock(&(lm->mtx)); return 0; } int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) { u32 slot = 0; Loading Loading @@ -1190,12 +1390,10 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) #endif ca91cx42_bridge->irq_set = ca91cx42_irq_set; ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; #if 0 ca91cx42_bridge->lm_set = ca91cx42_lm_set; ca91cx42_bridge->lm_get = ca91cx42_lm_get; ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; #endif ca91cx42_bridge->slot_get = ca91cx42_slot_get; data = ioread32(ca91cx42_device->base + MISC_CTL); Loading Loading @@ -1786,77 +1984,7 @@ int ca91cx42_do_dma(vmeDmaPacket_t *vmeDma) return 0; } int ca91cx42_lm_set(vmeLmCfg_t *vmeLm) { int temp_ctl = 0; if (vmeLm->addrU) return -EINVAL; switch (vmeLm->addrSpace) { case VME_A64: case VME_USER3: case VME_USER4: return -EINVAL; case VME_A16: temp_ctl |= 0x00000; break; case VME_A24: temp_ctl |= 0x10000; break; case VME_A32: temp_ctl |= 0x20000; break; case VME_CRCSR: temp_ctl |= 0x50000; break; case VME_USER1: temp_ctl |= 0x60000; break; case VME_USER2: temp_ctl |= 0x70000; break; } /* Disable while we are mucking around */ iowrite32(0x00000000, bridge->base + LM_CTL); iowrite32(vmeLm->addr, bridge->base + LM_BS); /* Setup CTL register. */ if (vmeLm->userAccessType & VME_SUPER) temp_ctl |= 0x00200000; if (vmeLm->userAccessType & VME_USER) temp_ctl |= 0x00100000; if (vmeLm->dataAccessType & VME_PROG) temp_ctl |= 0x00800000; if (vmeLm->dataAccessType & VME_DATA) temp_ctl |= 0x00400000; /* Write ctl reg and enable */ iowrite32(0x80000000 | temp_ctl, bridge->base + LM_CTL); temp_ctl = ioread32(bridge->base + LM_CTL); return 0; } int ca91cx42_wait_lm(vmeLmCfg_t *vmeLm) { unsigned long flags; unsigned int tmp; spin_lock_irqsave(&lm_lock, flags); spin_unlock_irqrestore(&lm_lock, flags); if (tmp == 0) { if (vmeLm->lmWait < 10) vmeLm->lmWait = 10; interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait); } iowrite32(0x00000000, bridge->base + LM_CTL); return 0; } Loading
drivers/staging/vme/bridges/vme_ca91cx42.h +13 −0 Original line number Diff line number Diff line Loading @@ -491,6 +491,19 @@ static const int CA91CX42_LINT_LM[] = { CA91CX42_LINT_LM0, CA91CX42_LINT_LM1, #define CA91CX42_VSI_CTL_LAS_PCI_IO (1<<0) #define CA91CX42_VSI_CTL_LAS_PCI_CONF (1<<1) /* LM_CTL Register * offset F64 */ #define CA91CX42_LM_CTL_EN (1<<31) #define CA91CX42_LM_CTL_PGM (1<<23) #define CA91CX42_LM_CTL_DATA (1<<22) #define CA91CX42_LM_CTL_SUPR (1<<21) #define CA91CX42_LM_CTL_NPRIV (1<<20) #define CA91CX42_LM_CTL_AS_M (5<<16) #define CA91CX42_LM_CTL_AS_A16 0 #define CA91CX42_LM_CTL_AS_A24 (1<<16) #define CA91CX42_LM_CTL_AS_A32 (1<<17) /* * VRAI_CTL Register * offset F70 Loading