📄 feature.c
字号:
int i; /* Save state & config of DBDMA channels */ for (i = 0; i < 13; i++) { volatile struct dbdma_regs __iomem * chan = (void __iomem *) (macio->base + ((0x8000+i*0x100)>>2)); save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi); save[i].cmdptr = in_le32(&chan->cmdptr); save[i].intr_sel = in_le32(&chan->intr_sel); save[i].br_sel = in_le32(&chan->br_sel); save[i].wait_sel = in_le32(&chan->wait_sel); }}static void dbdma_restore(struct macio_chip *macio, struct dbdma_regs *save){ int i; /* Save state & config of DBDMA channels */ for (i = 0; i < 13; i++) { volatile struct dbdma_regs __iomem * chan = (void __iomem *) (macio->base + ((0x8000+i*0x100)>>2)); out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16); while (in_le32(&chan->status) & ACTIVE) mb(); out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi); out_le32(&chan->cmdptr, save[i].cmdptr); out_le32(&chan->intr_sel, save[i].intr_sel); out_le32(&chan->br_sel, save[i].br_sel); out_le32(&chan->wait_sel, save[i].wait_sel); }}static void heathrow_sleep(struct macio_chip *macio, int secondary){ if (secondary) { dbdma_save(macio, save_alt_dbdma); save_fcr[2] = MACIO_IN32(0x38); save_fcr[3] = MACIO_IN32(0x3c); } else { dbdma_save(macio, save_dbdma); save_fcr[0] = MACIO_IN32(0x38); save_fcr[1] = MACIO_IN32(0x3c); save_mbcr = MACIO_IN32(0x34); /* Make sure sound is shut down */ MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); /* This seems to be necessary as well or the fan * keeps coming up and battery drains fast */ MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE); MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N); /* Make sure eth is down even if module or sleep * won't work properly */ MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET); } /* Make sure modem is shut down */ MACIO_OUT8(HRW_GPIO_MODEM_RESET, MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1); MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE); /* Let things settle */ (void)MACIO_IN32(HEATHROW_FCR);}static void heathrow_wakeup(struct macio_chip *macio, int secondary){ if (secondary) { MACIO_OUT32(0x38, save_fcr[2]); (void)MACIO_IN32(0x38); mdelay(1); MACIO_OUT32(0x3c, save_fcr[3]); (void)MACIO_IN32(0x38); mdelay(10); dbdma_restore(macio, save_alt_dbdma); } else { MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE); (void)MACIO_IN32(0x38); mdelay(1); MACIO_OUT32(0x3c, save_fcr[1]); (void)MACIO_IN32(0x38); mdelay(1); MACIO_OUT32(0x34, save_mbcr); (void)MACIO_IN32(0x38); mdelay(10); dbdma_restore(macio, save_dbdma); }}static long heathrow_sleep_state(struct device_node *node, long param, long value){ if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) return -EPERM; if (value == 1) { if (macio_chips[1].type == macio_gatwick) heathrow_sleep(&macio_chips[0], 1); heathrow_sleep(&macio_chips[0], 0); } else if (value == 0) { heathrow_wakeup(&macio_chips[0], 0); if (macio_chips[1].type == macio_gatwick) heathrow_wakeup(&macio_chips[0], 1); } return 0;}static long core99_scc_enable(struct device_node *node, long param, long value){ struct macio_chip* macio; unsigned long flags; unsigned long chan_mask; u32 fcr; macio = macio_find(node, 0); if (!macio) return -ENODEV; if (!strcmp(node->name, "ch-a")) chan_mask = MACIO_FLAG_SCCA_ON; else if (!strcmp(node->name, "ch-b")) chan_mask = MACIO_FLAG_SCCB_ON; else return -ENODEV; if (value) { int need_reset_scc = 0; int need_reset_irda = 0; LOCK(flags); fcr = MACIO_IN32(KEYLARGO_FCR0); /* Check if scc cell need enabling */ if (!(fcr & KL0_SCC_CELL_ENABLE)) { fcr |= KL0_SCC_CELL_ENABLE; need_reset_scc = 1; } if (chan_mask & MACIO_FLAG_SCCA_ON) { fcr |= KL0_SCCA_ENABLE; /* Don't enable line drivers for I2S modem */ if ((param & 0xfff) == PMAC_SCC_I2S1) fcr &= ~KL0_SCC_A_INTF_ENABLE; else fcr |= KL0_SCC_A_INTF_ENABLE; } if (chan_mask & MACIO_FLAG_SCCB_ON) { fcr |= KL0_SCCB_ENABLE; /* Perform irda specific inits */ if ((param & 0xfff) == PMAC_SCC_IRDA) { fcr &= ~KL0_SCC_B_INTF_ENABLE; fcr |= KL0_IRDA_ENABLE; fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE; fcr |= KL0_IRDA_SOURCE1_SEL; fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); need_reset_irda = 1; } else fcr |= KL0_SCC_B_INTF_ENABLE; } MACIO_OUT32(KEYLARGO_FCR0, fcr); macio->flags |= chan_mask; if (need_reset_scc) { MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET); (void)MACIO_IN32(KEYLARGO_FCR0); UNLOCK(flags); mdelay(15); LOCK(flags); MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET); } if (need_reset_irda) { MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET); (void)MACIO_IN32(KEYLARGO_FCR0); UNLOCK(flags); mdelay(15); LOCK(flags); MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET); } UNLOCK(flags); if (param & PMAC_SCC_FLAG_XMON) macio->flags |= MACIO_FLAG_SCC_LOCKED; } else { if (macio->flags & MACIO_FLAG_SCC_LOCKED) return -EPERM; LOCK(flags); fcr = MACIO_IN32(KEYLARGO_FCR0); if (chan_mask & MACIO_FLAG_SCCA_ON) fcr &= ~KL0_SCCA_ENABLE; if (chan_mask & MACIO_FLAG_SCCB_ON) { fcr &= ~KL0_SCCB_ENABLE; /* Perform irda specific clears */ if ((param & 0xfff) == PMAC_SCC_IRDA) { fcr &= ~KL0_IRDA_ENABLE; fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE); fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); } } MACIO_OUT32(KEYLARGO_FCR0, fcr); if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) { fcr &= ~KL0_SCC_CELL_ENABLE; MACIO_OUT32(KEYLARGO_FCR0, fcr); } macio->flags &= ~(chan_mask); UNLOCK(flags); mdelay(10); } return 0;}static longcore99_modem_enable(struct device_node *node, long param, long value){ struct macio_chip* macio; u8 gpio; unsigned long flags; /* Hack for internal USB modem */ if (node == NULL) { if (macio_chips[0].type != macio_keylargo) return -ENODEV; node = macio_chips[0].of_node; } macio = macio_find(node, 0); if (!macio) return -ENODEV; gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; if (!value) { LOCK(flags); MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); UNLOCK(flags); (void)MACIO_IN8(KL_GPIO_MODEM_RESET); mdelay(250); } LOCK(flags); if (value) { MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); UNLOCK(flags); (void)MACIO_IN32(KEYLARGO_FCR2); mdelay(250); } else { MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); UNLOCK(flags); } if (value) { LOCK(flags); MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); (void)MACIO_IN8(KL_GPIO_MODEM_RESET); UNLOCK(flags); mdelay(250); LOCK(flags); MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); (void)MACIO_IN8(KL_GPIO_MODEM_RESET); UNLOCK(flags); mdelay(250); LOCK(flags); MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); (void)MACIO_IN8(KL_GPIO_MODEM_RESET); UNLOCK(flags); mdelay(250); } return 0;}static longpangea_modem_enable(struct device_node *node, long param, long value){ struct macio_chip* macio; u8 gpio; unsigned long flags; /* Hack for internal USB modem */ if (node == NULL) { if (macio_chips[0].type != macio_pangea && macio_chips[0].type != macio_intrepid) return -ENODEV; node = macio_chips[0].of_node; } macio = macio_find(node, 0); if (!macio) return -ENODEV; gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; if (!value) { LOCK(flags); MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); UNLOCK(flags); (void)MACIO_IN8(KL_GPIO_MODEM_RESET); mdelay(250); } LOCK(flags); if (value) { MACIO_OUT8(KL_GPIO_MODEM_POWER, KEYLARGO_GPIO_OUTPUT_ENABLE); UNLOCK(flags); (void)MACIO_IN32(KEYLARGO_FCR2); mdelay(250); } else { MACIO_OUT8(KL_GPIO_MODEM_POWER, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); UNLOCK(flags); } if (value) { LOCK(flags); MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); (void)MACIO_IN8(KL_GPIO_MODEM_RESET); UNLOCK(flags); mdelay(250); LOCK(flags); MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); (void)MACIO_IN8(KL_GPIO_MODEM_RESET); UNLOCK(flags); mdelay(250); LOCK(flags); MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); (void)MACIO_IN8(KL_GPIO_MODEM_RESET); UNLOCK(flags); mdelay(250); } return 0;}static longcore99_ata100_enable(struct device_node *node, long value){ unsigned long flags; struct pci_dev *pdev = NULL; u8 pbus, pid; int rc; if (uninorth_rev < 0x24) return -ENODEV; LOCK(flags); if (value) UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); else UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); (void)UN_IN(UNI_N_CLOCK_CNTL); UNLOCK(flags); udelay(20); if (value) { if (pci_device_from_OF_node(node, &pbus, &pid) == 0) pdev = pci_get_bus_and_slot(pbus, pid); if (pdev == NULL) return 0; rc = pci_enable_device(pdev); if (rc == 0) pci_set_master(pdev); pci_dev_put(pdev); if (rc) return rc; } return 0;}static longcore99_ide_enable(struct device_node *node, long param, long value){ /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2 * based ata-100 */ switch(param) { case 0: return simple_feature_tweak(node, macio_unknown, KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value); case 1: return simple_feature_tweak(node, macio_unknown, KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value); case 2: return simple_feature_tweak(node, macio_unknown, KEYLARGO_FCR1, KL1_UIDE_ENABLE, value); case 3: return core99_ata100_enable(node, value); default: return -ENODEV; }}static longcore99_ide_reset(struct device_node *node, long param, long value){ switch(param) { case 0: return simple_feature_tweak(node, macio_unknown, KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value); case 1: return simple_feature_tweak(node, macio_unknown, KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value); case 2: return simple_feature_tweak(node, macio_unknown, KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value); default: return -ENODEV; }}static longcore99_gmac_enable(struct device_node *node, long param, long value){ unsigned long flags; LOCK(flags); if (value) UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); else UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); (void)UN_IN(UNI_N_CLOCK_CNTL); UNLOCK(flags); udelay(20); return 0;}static longcore99_gmac_phy_reset(struct device_node *node, long param, long value){ unsigned long flags; struct macio_chip *macio; macio = &macio_chips[0]; if (macio->type != macio_keylargo && macio->type != macio_pangea && macio->type != macio_intrepid) return -ENODEV; LOCK(flags); MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET); UNLOCK(flags); mdelay(10); LOCK(flags); MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */ KEYLARGO_GPIO_OUTOUT_DATA); UNLOCK(flags); mdelay(10); return 0;}static longcore99_sound_chip_enable(struct device_node *node, long param, long value){ struct macio_chip* macio; unsigned long flags; macio = macio_find(node, 0); if (!macio) return -ENODEV; /* Do a better probe code, screamer G4 desktops & * iMacs can do that too, add a recalibrate in * the driver as well */ if (pmac_mb.model_id == PMAC_TYPE_PISMO || pmac_mb.model_id == PMAC_TYPE_TITANIUM) { LOCK(flags); if (value) MACIO_OUT8(KL_GPIO_SOUND_POWER, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); else MACIO_OUT8(KL_GPIO_SOUND_POWER, KEYLARGO_GPIO_OUTPUT_ENABLE); (void)MACIO_IN8(KL_GPIO_SOUND_POWER); UNLOCK(flags); } return 0;}static longcore99_airport_enable(struct device_node *node, long param, long value){ struct macio_chip* macio; unsigned long flags; int state; macio = macio_find(node, 0); if (!macio) return -ENODEV; /* Hint: we allow passing of macio itself for the sake of the * sleep code */ if (node != macio->of_node && (!node->parent || node->parent != macio->of_node)) return -ENODEV; state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0; if (value == state) return 0; if (value) { /* This code is a reproduction of OF enable-cardslot * and init-wireless methods, slightly hacked until * I got it working. */ LOCK(flags); MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5); (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); UNLOCK(flags); mdelay(10); LOCK(flags); MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -