📄 via-pmu.c
字号:
break; } }recheck: if (pmu_state == idle) { if (adb_int_pending) { if (int_data_state[0] == int_data_empty) int_data_last = 0; else if (int_data_state[1] == int_data_empty) int_data_last = 1; else goto no_free_slot; pmu_state = intack; int_data_state[int_data_last] = int_data_fill; /* Sounds safer to make sure ACK is high before writing. * This helped kill a problem with ADB and some iBooks */ wait_for_ack(); send_byte(PMU_INT_ACK); adb_int_pending = 0; } else if (current_req) pmu_start(); }no_free_slot: /* Mark the oldest buffer for flushing */ if (int_data_state[!int_data_last] == int_data_ready) { int_data_state[!int_data_last] = int_data_flush; int_data = !int_data_last; } else if (int_data_state[int_data_last] == int_data_ready) { int_data_state[int_data_last] = int_data_flush; int_data = int_data_last; } --disable_poll; spin_unlock_irqrestore(&pmu_lock, flags); /* Deal with completed PMU requests outside of the lock */ if (req) { pmu_done(req); req = NULL; } /* Deal with interrupt datas outside of the lock */ if (int_data >= 0) { pmu_handle_data(interrupt_data[int_data], interrupt_data_len[int_data], regs); spin_lock_irqsave(&pmu_lock, flags); ++disable_poll; int_data_state[int_data] = int_data_empty; int_data = -1; goto recheck; } return IRQ_RETVAL(handled);}void __pmacpmu_unlock(void){ unsigned long flags; spin_lock_irqsave(&pmu_lock, flags); if (pmu_state == locked) pmu_state = idle; adb_int_pending = 1; spin_unlock_irqrestore(&pmu_lock, flags);}static irqreturn_t __pmacgpio1_interrupt(int irq, void *arg, struct pt_regs *regs){ unsigned long flags; if ((in_8(gpio_reg + 0x9) & 0x02) == 0) { spin_lock_irqsave(&pmu_lock, flags); if (gpio_irq_enabled > 0) { disable_irq_nosync(gpio_irq); gpio_irq_enabled = 0; } pmu_irq_stats[1]++; adb_int_pending = 1; spin_unlock_irqrestore(&pmu_lock, flags); via_pmu_interrupt(0, NULL, NULL); return IRQ_HANDLED; } return IRQ_NONE;}#ifdef CONFIG_PMAC_BACKLIGHTstatic int backlight_to_bright[] __pmacdata = { 0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e, 0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e}; static int __openfirmwarepmu_set_backlight_enable(int on, int level, void* data){ struct adb_request req; if (vias == NULL) return -ENODEV; if (on) { pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, backlight_to_bright[level]); pmu_wait_complete(&req); } pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF)); pmu_wait_complete(&req); return 0;}static void __openfirmwarepmu_bright_complete(struct adb_request *req){ if (req == &bright_req_1) clear_bit(1, &async_req_locks); if (req == &bright_req_2) clear_bit(2, &async_req_locks);}static int __openfirmwarepmu_set_backlight_level(int level, void* data){ if (vias == NULL) return -ENODEV; if (test_and_set_bit(1, &async_req_locks)) return -EAGAIN; pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT, backlight_to_bright[level]); if (test_and_set_bit(2, &async_req_locks)) return -EAGAIN; pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL, PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ? PMU_POW_ON : PMU_POW_OFF)); return 0;}#endif /* CONFIG_PMAC_BACKLIGHT */void __pmacpmu_enable_irled(int on){ struct adb_request req; if (vias == NULL) return ; if (pmu_kind == PMU_KEYLARGO_BASED) return ; pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_IRLED | (on ? PMU_POW_ON : PMU_POW_OFF)); pmu_wait_complete(&req);}void __pmacpmu_restart(void){ struct adb_request req; local_irq_disable(); drop_interrupts = 1; if (pmu_kind != PMU_KEYLARGO_BASED) { pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | PMU_INT_TICK ); while(!req.complete) pmu_poll(); } pmu_request(&req, NULL, 1, PMU_RESET); pmu_wait_complete(&req); for (;;) ;}void __pmacpmu_shutdown(void){ struct adb_request req; local_irq_disable(); drop_interrupts = 1; if (pmu_kind != PMU_KEYLARGO_BASED) { pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | PMU_INT_TICK ); pmu_wait_complete(&req); } else { /* Disable server mode on shutdown or we'll just * wake up again */ pmu_set_server_mode(0); } pmu_request(&req, NULL, 5, PMU_SHUTDOWN, 'M', 'A', 'T', 'T'); pmu_wait_complete(&req); for (;;) ;}intpmu_present(void){ return via != 0;}struct pmu_i2c_hdr { u8 bus; u8 mode; u8 bus2; u8 address; u8 sub_addr; u8 comb_addr; u8 count;};intpmu_i2c_combined_read(int bus, int addr, int subaddr, u8* data, int len){ struct adb_request req; struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; int retry; int rc; for (retry=0; retry<16; retry++) { memset(&req, 0, sizeof(req)); hdr->bus = bus; hdr->address = addr & 0xfe; hdr->mode = PMU_I2C_MODE_COMBINED; hdr->bus2 = 0; hdr->sub_addr = subaddr; hdr->comb_addr = addr | 1; hdr->count = len; req.nbytes = sizeof(struct pmu_i2c_hdr) + 1; req.reply_expected = 0; req.reply_len = 0; req.data[0] = PMU_I2C_CMD; req.reply[0] = 0xff; rc = pmu_queue_request(&req); if (rc) return rc; while(!req.complete) pmu_poll(); if (req.reply[0] == PMU_I2C_STATUS_OK) break; mdelay(15); } if (req.reply[0] != PMU_I2C_STATUS_OK) return -1; for (retry=0; retry<16; retry++) { memset(&req, 0, sizeof(req)); mdelay(15); hdr->bus = PMU_I2C_BUS_STATUS; req.reply[0] = 0xff; req.nbytes = 2; req.reply_expected = 0; req.reply_len = 0; req.data[0] = PMU_I2C_CMD; rc = pmu_queue_request(&req); if (rc) return rc; while(!req.complete) pmu_poll(); if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) { memcpy(data, &req.reply[1], req.reply_len - 1); return req.reply_len - 1; } } return -1;}intpmu_i2c_stdsub_write(int bus, int addr, int subaddr, u8* data, int len){ struct adb_request req; struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; int retry; int rc; for (retry=0; retry<16; retry++) { memset(&req, 0, sizeof(req)); hdr->bus = bus; hdr->address = addr & 0xfe; hdr->mode = PMU_I2C_MODE_STDSUB; hdr->bus2 = 0; hdr->sub_addr = subaddr; hdr->comb_addr = addr & 0xfe; hdr->count = len; req.data[0] = PMU_I2C_CMD; memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len); req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1; req.reply_expected = 0; req.reply_len = 0; req.reply[0] = 0xff; rc = pmu_queue_request(&req); if (rc) return rc; while(!req.complete) pmu_poll(); if (req.reply[0] == PMU_I2C_STATUS_OK) break; mdelay(15); } if (req.reply[0] != PMU_I2C_STATUS_OK) return -1; for (retry=0; retry<16; retry++) { memset(&req, 0, sizeof(req)); mdelay(15); hdr->bus = PMU_I2C_BUS_STATUS; req.reply[0] = 0xff; req.nbytes = 2; req.reply_expected = 0; req.reply_len = 0; req.data[0] = PMU_I2C_CMD; rc = pmu_queue_request(&req); if (rc) return rc; while(!req.complete) pmu_poll(); if (req.reply[0] == PMU_I2C_STATUS_OK) return len; } return -1;}intpmu_i2c_simple_read(int bus, int addr, u8* data, int len){ struct adb_request req; struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; int retry; int rc; for (retry=0; retry<16; retry++) { memset(&req, 0, sizeof(req)); hdr->bus = bus; hdr->address = addr | 1; hdr->mode = PMU_I2C_MODE_SIMPLE; hdr->bus2 = 0; hdr->sub_addr = 0; hdr->comb_addr = 0; hdr->count = len; req.data[0] = PMU_I2C_CMD; req.nbytes = sizeof(struct pmu_i2c_hdr) + 1; req.reply_expected = 0; req.reply_len = 0; req.reply[0] = 0xff; rc = pmu_queue_request(&req); if (rc) return rc; while(!req.complete) pmu_poll(); if (req.reply[0] == PMU_I2C_STATUS_OK) break; mdelay(15); } if (req.reply[0] != PMU_I2C_STATUS_OK) return -1; for (retry=0; retry<16; retry++) { memset(&req, 0, sizeof(req)); mdelay(15); hdr->bus = PMU_I2C_BUS_STATUS; req.reply[0] = 0xff; req.nbytes = 2; req.reply_expected = 0; req.reply_len = 0; req.data[0] = PMU_I2C_CMD; rc = pmu_queue_request(&req); if (rc) return rc; while(!req.complete) pmu_poll(); if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) { memcpy(data, &req.reply[1], req.reply_len - 1); return req.reply_len - 1; } } return -1;}intpmu_i2c_simple_write(int bus, int addr, u8* data, int len){ struct adb_request req; struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; int retry; int rc; for (retry=0; retry<16; retry++) { memset(&req, 0, sizeof(req)); hdr->bus = bus; hdr->address = addr & 0xfe; hdr->mode = PMU_I2C_MODE_SIMPLE; hdr->bus2 = 0; hdr->sub_addr = 0; hdr->comb_addr = 0; hdr->count = len; req.data[0] = PMU_I2C_CMD; memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len); req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1; req.reply_expected = 0; req.reply_len = 0; req.reply[0] = 0xff; rc = pmu_queue_request(&req); if (rc) return rc; while(!req.complete) pmu_poll(); if (req.reply[0] == PMU_I2C_STATUS_OK) break; mdelay(15); } if (req.reply[0] != PMU_I2C_STATUS_OK) return -1; for (retry=0; retry<16; retry++) { memset(&req, 0, sizeof(req)); mdelay(15); hdr->bus = PMU_I2C_BUS_STATUS; req.reply[0] = 0xff; req.nbytes = 2; req.reply_expected = 0; req.reply_len = 0; req.data[0] = PMU_I2C_CMD; rc = pmu_queue_request(&req); if (rc) return rc; while(!req.complete) pmu_poll(); if (req.reply[0] == PMU_I2C_STATUS_OK) return len; } return -1;}#ifdef CONFIG_PMAC_PBOOKstatic LIST_HEAD(sleep_notifiers);intpmu_register_sleep_notifier(struct pmu_sleep_notifier *n){ struct list_head *list; struct pmu_sleep_notifier *notifier; for (list = sleep_notifiers.next; list != &sleep_notifiers; list = list->next) { notifier = list_entry(list, struct pmu_sleep_notifier, list); if (n->priority > notifier->priority) break; } __list_add(&n->list, list->prev, list); return 0;}intpmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n){ if (n->list.next == 0) return -ENOENT; list_del(&n->list); n->list.next = NULL; return 0;}/* Sleep is broadcast last-to-first */static int __pmacbroadcast_sleep(int when, int fallback){ int ret = PBOOK_SLEEP_OK; struct list_head *list; struct pmu_sleep_notifier *notifier; for (list = sleep_notifiers.prev; list != &sleep_notifiers; list = list->prev) { notifier = list_entry(list, struct pmu_sleep_notifier, list); ret = notifier->notifier_call(notifier, when); if (ret != PBOOK_SLEEP_OK) { printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n", when, notifier, notifier->notifier_call); for (; list != &sleep_notifiers; list = list->next) { notifier = list_entry(list, struct pmu_sleep_notifier, list); notifier->notifier_call(notifier, fallback); } return ret; } } return ret;}/* Wake is broadcast first-to-last */static int __pmacbroadcast_wake(void){ int ret = PBOOK_SLEEP_OK; struct list_head *list; struct pmu_sleep_notifier *notifier;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -