static int pcf2123_rtc_attach(device_t dev) { struct pcf2123_rtc_softc *sc; struct spi_command cmd; unsigned char rxBuf[3]; unsigned char txBuf[3]; int err; sc = device_get_softc(dev); sc->dev = dev; clock_register(dev, 1000000); memset(&cmd, 0, sizeof(cmd)); memset(rxBuf, 0, sizeof(rxBuf)); memset(txBuf, 0, sizeof(txBuf)); /* Make sure Ctrl1 and Ctrl2 are zeroes */ txBuf[0] = PCF2123_WRITE(PCF2123_REG_CTRL1); cmd.rx_cmd = rxBuf; cmd.tx_cmd = txBuf; cmd.rx_cmd_sz = sizeof(rxBuf); cmd.tx_cmd_sz = sizeof(txBuf); err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd); DELAY(PCF2123_DELAY); return (0); }
static void pcf8563_start(void *xdev) { device_t dev; uint8_t reg = PCF8563_R_SECOND, val; struct iic_msg msgs[] = { { 0, IIC_M_WR, sizeof(reg), ® }, { 0, IIC_M_RD, sizeof(val), &val } }; struct pcf8563_softc *sc; dev = (device_t)xdev; sc = device_get_softc(dev); config_intrhook_disestablish(&sc->enum_hook); /* * NB: PCF8563_R_SECOND_VL doesn't automatically clear when VDD * rises above Vlow again and needs to be cleared manually. * However, apparently this needs all of the time registers to be * set, i.e. pcf8563_settime(), and not just PCF8563_R_SECOND in * order for PCF8563_R_SECOND_VL to stick. Thus, we just issue a * warning here rather than failing with ENXIO in case it is set. * Note that pcf8563_settime() will also clear PCF8563_R_SECOND_VL * as a side-effect. */ msgs[0].slave = msgs[1].slave = sc->sc_addr; if (iicbus_transfer(dev, msgs, nitems(msgs)) != 0) { device_printf(dev, "%s: cannot read RTC\n", __func__); return; } if ((val & PCF8563_R_SECOND_VL) != 0) device_printf(dev, "%s: battery low\n", __func__); clock_register(dev, 1000000); /* 1 second resolution */ }
static int rtasdev_attach(device_t dev) { if (rtas_token_lookup("get-time-of-day") != -1) clock_register(dev, 2000); EVENTHANDLER_REGISTER(shutdown_final, rtas_shutdown, NULL, SHUTDOWN_PRI_LAST); return (0); }
static int octeon_rtc_attach(device_t dev) { cvmx_rtc_options_t supported; supported = cvmx_rtc_supported(); if ((supported & CVMX_RTC_READ) == 0) return (ENXIO); clock_register(dev, 1000000); return (0); }
static int opaldev_attach(device_t dev) { phandle_t child; device_t cdev; uint64_t junk; int i, rv; struct ofw_bus_devinfo *dinfo; struct resource *irq; /* Test for RTC support and register clock if it works */ rv = opal_call(OPAL_RTC_READ, vtophys(&junk), vtophys(&junk)); do { rv = opal_call(OPAL_RTC_READ, vtophys(&junk), vtophys(&junk)); if (rv == OPAL_BUSY_EVENT) rv = opal_call(OPAL_POLL_EVENTS, 0); } while (rv == OPAL_BUSY_EVENT); if (rv == OPAL_SUCCESS) clock_register(dev, 2000); EVENTHANDLER_REGISTER(shutdown_final, opal_shutdown, NULL, SHUTDOWN_PRI_LAST); /* Bind to interrupts */ for (i = 0; (irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE)) != NULL; i++) bus_setup_intr(dev, irq, INTR_TYPE_TTY | INTR_MPSAFE | INTR_ENTROPY, NULL, opal_intr, (void *)rman_get_start(irq), NULL); for (child = OF_child(ofw_bus_get_node(dev)); child != 0; child = OF_peer(child)) { dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) { free(dinfo, M_DEVBUF); continue; } cdev = device_add_child(dev, NULL, -1); if (cdev == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", dinfo->obd_name); ofw_bus_gen_destroy_devinfo(dinfo); free(dinfo, M_DEVBUF); continue; } device_set_ivars(cdev, dinfo); } return (bus_generic_attach(dev)); }
static int at91_rtc_attach(device_t dev) { struct at91_rtc_softc *sc = device_get_softc(dev); int err; sc->dev = dev; err = at91_rtc_activate(dev); if (err) goto out; AT91_RTC_LOCK_INIT(sc); /* * Disable all interrupts in the hardware. * Clear all bits in the status register. * Set 24-hour-clock mode. */ WR4(sc, RTC_IDR, 0xffffffff); WR4(sc, RTC_SCCR, 0x1f); WR4(sc, RTC_MR, 0); #ifdef AT91_RTC_USE_INTERRUPTS err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC, at91_rtc_intr, NULL, sc, &sc->intrhand); if (err) { AT91_RTC_LOCK_DESTROY(sc); goto out; } #endif /* * Read the calendar register. If the century is 19 then the clock has * never been set. Try to store an invalid value into the register, * which will turn on the error bit in RTC_VER, and our getclock code * knows to return EINVAL if any error bits are on. */ if (RTC_CALR_CEN(RD4(sc, RTC_CALR)) == 19) WR4(sc, RTC_CALR, 0); /* * Register as a time of day clock with 1-second resolution. */ clock_register(dev, 1000000); out: if (err) at91_rtc_deactivate(dev); return (err); }
int mc146818_attach(device_t dev) { struct mc146818_softc *sc; sc = device_get_softc(dev); if (mtx_initialized(&sc->sc_mtx) == 0) { device_printf(dev, "%s: mutex not initialized\n", __func__); return (ENXIO); } if (sc->sc_mcread == NULL) sc->sc_mcread = mc146818_def_read; if (sc->sc_mcwrite == NULL) sc->sc_mcwrite = mc146818_def_write; if (sc->sc_flag & MC146818_NO_CENT_ADJUST) { /* * Note that setting MC146818_NO_CENT_ADJUST means that * the century has to be stored in NVRAM somewhere. */ if (sc->sc_getcent == NULL) sc->sc_getcent = mc146818_def_getcent; if (sc->sc_setcent == NULL) sc->sc_setcent = mc146818_def_setcent; } mtx_lock_spin(&sc->sc_mtx); if (!(*sc->sc_mcread)(dev, MC_REGD) & MC_REGD_VRT) { mtx_unlock_spin(&sc->sc_mtx); device_printf(dev, "%s: battery low\n", __func__); return (ENXIO); } sc->sc_rega = MC_BASE_32_KHz; (*sc->sc_mcwrite)(dev, MC_REGA, sc->sc_rega); sc->sc_regb = 0; sc->sc_regb |= (sc->sc_flag & MC146818_BCD) ? 0 : MC_REGB_BINARY; sc->sc_regb |= (sc->sc_flag & MC146818_12HR) ? 0 : MC_REGB_24HR; (*sc->sc_mcwrite)(dev, MC_REGB, sc->sc_regb); mtx_unlock_spin(&sc->sc_mtx); clock_register(dev, 1000000); /* 1 second resolution. */ return (0); }
static int nexus_attach(device_t dev) { /* * Mask the legacy PICs - we will use the I/O SAPIC for interrupt. */ outb(IO_ICU1+1, 0xff); outb(IO_ICU2+1, 0xff); if (acpi_identify() == 0) BUS_ADD_CHILD(dev, 10, "acpi", 0); clock_register(dev, 1000); bus_generic_attach(dev); return 0; }
static int aw_rtc_attach(device_t dev) { struct aw_rtc_softc *sc = device_get_softc(dev); bus_size_t rtc_losc_sta; uint32_t val; int rid = 0; sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->res) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; switch (sc->type) { case A10_RTC: case A20_RTC: sc->rtc_date = A10_RTC_DATE_REG; sc->rtc_time = A10_RTC_TIME_REG; rtc_losc_sta = LOSC_CTRL_REG; break; case A31_RTC: sc->rtc_date = A31_RTC_DATE_REG; sc->rtc_time = A31_RTC_TIME_REG; rtc_losc_sta = A31_LOSC_AUTO_SWT_STA; break; } val = RTC_READ(sc, LOSC_CTRL_REG); val |= LOSC_AUTO_SW_EN; val |= LOSC_MAGIC | LOSC_GSM | LOSC_OSC_SRC; RTC_WRITE(sc, LOSC_CTRL_REG, val); DELAY(100); if (bootverbose) { val = RTC_READ(sc, rtc_losc_sta); if ((val & LOSC_OSC_SRC) == 0) device_printf(dev, "Using internal oscillator\n"); else device_printf(dev, "Using external oscillator\n"); } clock_register(dev, RTC_RES_US); return (0); }
int as3722_rtc_attach(struct as3722_softc *sc, phandle_t node) { int rv; /* Enable RTC, set 24 hours mode and alarms */ rv = RM1(sc, AS3722_RTC_CONTROL, AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN | AS3722_RTC_AM_PM_MODE, AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN); if (rv < 0) { device_printf(sc->dev, "Failed to initialize RTC controller\n"); return (ENXIO); } clock_register(sc->dev, 1000000); return (0); }
static int mv_rtc_attach(device_t dev) { struct mv_rtc_softc *sc; sc = device_get_softc(dev); sc->dev = dev; clock_register(dev, 1000000); if (bus_alloc_resources(dev, res_spec, sc->res)) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } return (0); }
static int snvs_attach(device_t dev) { struct snvs_softc *sc; int rid; sc = device_get_softc(dev); sc->dev = dev; rid = 0; sc->memres = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->memres == NULL) { device_printf(sc->dev, "could not allocate registers\n"); return (ENXIO); } clock_register(sc->dev, RTC_RESOLUTION_US); return (0); }
static int rtc_attach(device_t dev) { struct timespec ts; struct ds1553_softc *sc; int error; sc = device_get_softc(dev); bzero(sc, sizeof(struct ds1553_softc)); mtx_init(&sc->sc_mtx, "rtc_mtx", NULL, MTX_SPIN); sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid, RF_ACTIVE); if (sc->res == NULL) { device_printf(dev, "cannot allocate resources\n"); mtx_destroy(&sc->sc_mtx); return (ENXIO); } sc->sc_bst = rman_get_bustag(sc->res); sc->sc_bsh = rman_get_bushandle(sc->res); if ((error = ds1553_attach(dev)) != 0) { device_printf(dev, "cannot attach time of day clock\n"); bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res); mtx_destroy(&sc->sc_mtx); return (error); } clock_register(dev, 1000000); if (bootverbose) { ds1553_gettime(dev, &ts); device_printf(dev, "current time: %ld.%09ld\n", (long)ts.tv_sec, ts.tv_nsec); } return (0); }
static int lpc_rtc_attach(device_t dev) { struct lpc_rtc_softc *sc = device_get_softc(dev); int rid = 0; sc->lr_dev = dev; clock_register(dev, 1000000); sc->lr_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->lr_mem_res) { device_printf(dev, "cannot allocate memory window\n"); return (ENXIO); } sc->lr_bst = rman_get_bustag(sc->lr_mem_res); sc->lr_bsh = rman_get_bushandle(sc->lr_mem_res); return (0); }
static void ds1307_start(void *xdev) { device_t dev; struct ds1307_softc *sc; struct sysctl_ctx_list *ctx; struct sysctl_oid *tree_node; struct sysctl_oid_list *tree; dev = (device_t)xdev; sc = device_get_softc(dev); ctx = device_get_sysctl_ctx(dev); tree_node = device_get_sysctl_tree(dev); tree = SYSCTL_CHILDREN(tree_node); config_intrhook_disestablish(&sc->enum_hook); /* Set the 24 hours mode. */ if (ds1307_set_24hrs_mode(sc) != 0) return; /* Enable the oscillator if halted. */ if (ds1307_osc_enable(sc) != 0) return; /* Configuration parameters. */ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqwe", CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0, ds1307_sqwe_sysctl, "IU", "DS1307 square-wave enable"); SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_freq", CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0, ds1307_sqw_freq_sysctl, "IU", "DS1307 square-wave output frequency"); SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_out", CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0, ds1307_sqw_out_sysctl, "IU", "DS1307 square-wave output state"); /* 1 second resolution. */ clock_register(dev, 1000000); }
static int s3c2xx0_rtc_attach(device_t dev) { struct s3c2xx0_rtc_softc *sc; int error, rid; sc = device_get_softc(dev); error = 0; rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { error = ENOMEM; goto out; } bus_write_1(sc->mem_res, RTC_RTCCON, RTCCON_RTCEN); clock_register(dev, 1000000); out: return (error); }
static int atrtc_attach(device_t dev) { struct atrtc_softc *sc; int i; /* * Not that we need them or anything, but grab our resources * so they show up, correctly attributed, in the big picture. */ sc = device_get_softc(dev); if (!(sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, IO_RTC, IO_RTC + 1, 2, RF_ACTIVE))) device_printf(dev,"Warning: Couldn't map I/O.\n"); if (!(sc->intr_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->intr_rid, 8, 8, 1, RF_ACTIVE))) device_printf(dev,"Warning: Couldn't map Interrupt.\n"); clock_register(dev, 1000000); if (resource_int_value("atrtc", 0, "clock", &i) == 0 && i == 0) atrtcclock_disable = 1; return(0); }
static int cuda_attach(device_t dev) { struct cuda_softc *sc; volatile int i; uint8_t reg; phandle_t node,child; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_memrid = 0; sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_memrid, RF_ACTIVE); if (sc->sc_memr == NULL) { device_printf(dev, "Could not alloc mem resource!\n"); return (ENXIO); } sc->sc_irqrid = 0; sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqrid, RF_ACTIVE); if (sc->sc_irq == NULL) { device_printf(dev, "could not allocate interrupt\n"); return (ENXIO); } if (bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE | INTR_ENTROPY, NULL, cuda_intr, dev, &sc->sc_ih) != 0) { device_printf(dev, "could not setup interrupt\n"); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid, sc->sc_irq); return (ENXIO); } mtx_init(&sc->sc_mutex,"cuda",NULL,MTX_DEF | MTX_RECURSE); sc->sc_sent = 0; sc->sc_received = 0; sc->sc_waiting = 0; sc->sc_polling = 0; sc->sc_state = CUDA_NOTREADY; sc->sc_autopoll = 0; sc->sc_rtc = -1; STAILQ_INIT(&sc->sc_inq); STAILQ_INIT(&sc->sc_outq); STAILQ_INIT(&sc->sc_freeq); for (i = 0; i < CUDA_MAXPACKETS; i++) STAILQ_INSERT_TAIL(&sc->sc_freeq, &sc->sc_pkts[i], pkt_q); /* Init CUDA */ reg = cuda_read_reg(sc, vDirB); reg |= 0x30; /* register B bits 4 and 5: outputs */ cuda_write_reg(sc, vDirB, reg); reg = cuda_read_reg(sc, vDirB); reg &= 0xf7; /* register B bit 3: input */ cuda_write_reg(sc, vDirB, reg); reg = cuda_read_reg(sc, vACR); reg &= ~vSR_OUT; /* make sure SR is set to IN */ cuda_write_reg(sc, vACR, reg); cuda_write_reg(sc, vACR, (cuda_read_reg(sc, vACR) | 0x0c) & ~0x10); sc->sc_state = CUDA_IDLE; /* used by all types of hardware */ cuda_write_reg(sc, vIER, 0x84); /* make sure VIA interrupts are on */ cuda_idle(sc); /* reset ADB */ /* Reset CUDA */ i = cuda_read_reg(sc, vSR); /* clear interrupt */ cuda_write_reg(sc, vIER, 0x04); /* no interrupts while clearing */ cuda_idle(sc); /* reset state to idle */ DELAY(150); cuda_tip(sc); /* signal start of frame */ DELAY(150); cuda_toggle_ack(sc); DELAY(150); cuda_clear_tip(sc); DELAY(150); cuda_idle(sc); /* back to idle state */ i = cuda_read_reg(sc, vSR); /* clear interrupt */ cuda_write_reg(sc, vIER, 0x84); /* ints ok now */ /* Initialize child buses (ADB) */ node = ofw_bus_get_node(dev); for (child = OF_child(node); child != 0; child = OF_peer(child)) { char name[32]; memset(name, 0, sizeof(name)); OF_getprop(child, "name", name, sizeof(name)); if (bootverbose) device_printf(dev, "CUDA child <%s>\n",name); if (strncmp(name, "adb", 4) == 0) { sc->adb_bus = device_add_child(dev,"adb",-1); } } clock_register(dev, 1000); EVENTHANDLER_REGISTER(shutdown_final, cuda_shutdown, sc, SHUTDOWN_PRI_LAST); return (bus_generic_attach(dev)); }
int mk48txx_attach(device_t dev) { struct mk48txx_softc *sc; int i; uint8_t wday; sc = device_get_softc(dev); if (mtx_initialized(&sc->sc_mtx) == 0) { device_printf(dev, "%s: mutex not initialized\n", __func__); return (ENXIO); } device_printf(dev, "model %s", sc->sc_model); i = sizeof(mk48txx_models) / sizeof(mk48txx_models[0]); while (--i >= 0) { if (strcmp(sc->sc_model, mk48txx_models[i].name) == 0) { break; } } if (i < 0) { device_printf(dev, " (unsupported)\n"); return (ENXIO); } printf("\n"); sc->sc_nvramsz = mk48txx_models[i].nvramsz; sc->sc_clkoffset = mk48txx_models[i].clkoff; if (sc->sc_nvrd == NULL) sc->sc_nvrd = mk48txx_def_nvrd; if (sc->sc_nvwr == NULL) sc->sc_nvwr = mk48txx_def_nvwr; if (mk48txx_models[i].flags & MK48TXX_EXT_REGISTERS) { mtx_lock(&sc->sc_mtx); if ((*sc->sc_nvrd)(dev, sc->sc_clkoffset + MK48TXX_FLAGS) & MK48TXX_FLAGS_BL) { mtx_unlock(&sc->sc_mtx); device_printf(dev, "%s: battery low\n", __func__); return (ENXIO); } mtx_unlock(&sc->sc_mtx); } if (sc->sc_flag & MK48TXX_NO_CENT_ADJUST) { /* * Use MK48TXX_WDAY_CB instead of manually adjusting the * century. */ if (!(mk48txx_models[i].flags & MK48TXX_EXT_REGISTERS)) { device_printf(dev, "%s: no century bit\n", __func__); return (ENXIO); } else { mtx_lock(&sc->sc_mtx); wday = (*sc->sc_nvrd) (dev, sc->sc_clkoffset + MK48TXX_IWDAY); wday |= MK48TXX_WDAY_CEB; (*sc->sc_nvwr) (dev, sc->sc_clkoffset + MK48TXX_IWDAY, wday); mtx_unlock(&sc->sc_mtx); } } clock_register(dev, 1000000); /* 1 second resolution */ if ((sc->sc_flag & MK48TXX_WDOG_REGISTER) && (mk48txx_models[i].flags & MK48TXX_EXT_REGISTERS)) { sc->sc_wet = EVENTHANDLER_REGISTER(watchdog_list, mk48txx_watchdog, dev, 0); device_printf(dev, "watchdog registered, timeout interval max. 128 sec\n"); } return (0); }
static int smu_attach(device_t dev) { struct smu_softc *sc; phandle_t node, child; uint8_t data[12]; sc = device_get_softc(dev); mtx_init(&sc->sc_mtx, "smu", NULL, MTX_DEF); sc->sc_cur_cmd = NULL; sc->sc_doorbellirqid = -1; sc->sc_u3 = 0; if (OF_finddevice("/u3") != -1) sc->sc_u3 = 1; /* * Map the mailbox area. This should be determined from firmware, * but I have not found a simple way to do that. */ bus_dma_tag_create(NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE, 1, PAGE_SIZE, 0, NULL, NULL, &(sc->sc_dmatag)); sc->sc_bt = &bs_le_tag; bus_space_map(sc->sc_bt, SMU_MAILBOX, 4, 0, &sc->sc_mailbox); /* * Allocate the command buffer. This can be anywhere in the low 4 GB * of memory. */ bus_dmamem_alloc(sc->sc_dmatag, (void **)&sc->sc_cmd, BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->sc_cmd_dmamap); bus_dmamap_load(sc->sc_dmatag, sc->sc_cmd_dmamap, sc->sc_cmd, PAGE_SIZE, smu_phys_callback, sc, 0); STAILQ_INIT(&sc->sc_cmdq); /* * Set up handlers to change CPU voltage when CPU frequency is changed. */ EVENTHANDLER_REGISTER(cpufreq_pre_change, smu_cpufreq_pre_change, dev, EVENTHANDLER_PRI_ANY); EVENTHANDLER_REGISTER(cpufreq_post_change, smu_cpufreq_post_change, dev, EVENTHANDLER_PRI_ANY); /* * Detect and attach child devices. */ node = ofw_bus_get_node(dev); for (child = OF_child(node); child != 0; child = OF_peer(child)) { char name[32]; memset(name, 0, sizeof(name)); OF_getprop(child, "name", name, sizeof(name)); if (strncmp(name, "rpm-fans", 9) == 0 || strncmp(name, "fans", 5) == 0) smu_attach_fans(dev, child); if (strncmp(name, "sensors", 8) == 0) smu_attach_sensors(dev, child); if (strncmp(name, "smu-i2c-control", 15) == 0) smu_attach_i2c(dev, child); } /* Some SMUs have the I2C children directly under the bus. */ smu_attach_i2c(dev, node); /* * Collect calibration constants. */ smu_get_datablock(dev, SMU_CPUTEMP_CAL, data, sizeof(data)); sc->sc_cpu_diode_scale = (data[4] << 8) + data[5]; sc->sc_cpu_diode_offset = (data[6] << 8) + data[7]; smu_get_datablock(dev, SMU_CPUVOLT_CAL, data, sizeof(data)); sc->sc_cpu_volt_scale = (data[4] << 8) + data[5]; sc->sc_cpu_volt_offset = (data[6] << 8) + data[7]; sc->sc_cpu_curr_scale = (data[8] << 8) + data[9]; sc->sc_cpu_curr_offset = (data[10] << 8) + data[11]; smu_get_datablock(dev, SMU_SLOTPW_CAL, data, sizeof(data)); sc->sc_slots_pow_scale = (data[4] << 8) + data[5]; sc->sc_slots_pow_offset = (data[6] << 8) + data[7]; /* * Set up LED interface */ sc->sc_leddev = led_create(smu_set_sleepled, dev, "sleepled"); /* * Reset on power loss behavior */ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "server_mode", CTLTYPE_INT | CTLFLAG_RW, dev, 0, smu_server_mode, "I", "Enable reboot after power failure"); /* * Set up doorbell interrupt. */ sc->sc_doorbellirqid = 0; sc->sc_doorbellirq = bus_alloc_resource_any(smu_doorbell, SYS_RES_IRQ, &sc->sc_doorbellirqid, RF_ACTIVE); bus_setup_intr(smu_doorbell, sc->sc_doorbellirq, INTR_TYPE_MISC | INTR_MPSAFE, NULL, smu_doorbell_intr, dev, &sc->sc_doorbellirqcookie); powerpc_config_intr(rman_get_start(sc->sc_doorbellirq), INTR_TRIGGER_EDGE, INTR_POLARITY_LOW); /* * Connect RTC interface. */ clock_register(dev, 1000); /* * Learn about shutdown events */ EVENTHANDLER_REGISTER(shutdown_final, smu_shutdown, dev, SHUTDOWN_PRI_LAST); return (bus_generic_attach(dev)); }
static int ps3bus_attach(device_t self) { struct ps3bus_softc *sc; struct ps3bus_devinfo *dinfo; int bus_index, dev_index, result; uint64_t bustype, bus, devs; uint64_t dev, devtype; uint64_t junk; device_t cdev; sc = device_get_softc(self); sc->sc_mem_rman.rm_type = RMAN_ARRAY; sc->sc_mem_rman.rm_descr = "PS3Bus Memory Mapped I/O"; sc->sc_intr_rman.rm_type = RMAN_ARRAY; sc->sc_intr_rman.rm_descr = "PS3Bus Interrupts"; rman_init(&sc->sc_mem_rman); rman_init(&sc->sc_intr_rman); rman_manage_region(&sc->sc_intr_rman, 0, ~0); /* Get memory regions for DMA */ mem_regions(&sc->regions, &sc->rcount, &sc->regions, &sc->rcount); /* * Probe all the PS3's buses. */ for (bus_index = 0; bus_index < 5; bus_index++) { result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, (lv1_repository_string("bus") >> 32) | bus_index, lv1_repository_string("type"), 0, 0, &bustype, &junk); if (result != 0) continue; result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, (lv1_repository_string("bus") >> 32) | bus_index, lv1_repository_string("id"), 0, 0, &bus, &junk); if (result != 0) continue; result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, (lv1_repository_string("bus") >> 32) | bus_index, lv1_repository_string("num_dev"), 0, 0, &devs, &junk); for (dev_index = 0; dev_index < devs; dev_index++) { result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, (lv1_repository_string("bus") >> 32) | bus_index, lv1_repository_string("dev") | dev_index, lv1_repository_string("type"), 0, &devtype, &junk); if (result != 0) continue; result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, (lv1_repository_string("bus") >> 32) | bus_index, lv1_repository_string("dev") | dev_index, lv1_repository_string("id"), 0, &dev, &junk); if (result != 0) continue; switch (devtype) { case PS3_DEVTYPE_USB: /* USB device has OHCI and EHCI USB host controllers */ lv1_open_device(bus, dev, 0); /* OHCI host controller */ dinfo = malloc(sizeof(*dinfo), M_PS3BUS, M_WAITOK | M_ZERO); dinfo->bus = bus; dinfo->dev = dev; dinfo->bustype = bustype; dinfo->devtype = devtype; dinfo->busidx = bus_index; dinfo->devidx = dev_index; ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index, dev_index, OHCI_IRQ, OHCI_REG, dinfo); cdev = device_add_child(self, "ohci", -1); if (cdev == NULL) { device_printf(self, "device_add_child failed\n"); free(dinfo, M_PS3BUS); continue; } mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF); device_set_ivars(cdev, dinfo); /* EHCI host controller */ dinfo = malloc(sizeof(*dinfo), M_PS3BUS, M_WAITOK | M_ZERO); dinfo->bus = bus; dinfo->dev = dev; dinfo->bustype = bustype; dinfo->devtype = devtype; dinfo->busidx = bus_index; dinfo->devidx = dev_index; ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index, dev_index, EHCI_IRQ, EHCI_REG, dinfo); cdev = device_add_child(self, "ehci", -1); if (cdev == NULL) { device_printf(self, "device_add_child failed\n"); free(dinfo, M_PS3BUS); continue; } mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF); device_set_ivars(cdev, dinfo); break; default: dinfo = malloc(sizeof(*dinfo), M_PS3BUS, M_WAITOK | M_ZERO); dinfo->bus = bus; dinfo->dev = dev; dinfo->bustype = bustype; dinfo->devtype = devtype; dinfo->busidx = bus_index; dinfo->devidx = dev_index; if (dinfo->bustype == PS3_BUSTYPE_SYSBUS || dinfo->bustype == PS3_BUSTYPE_STORAGE) lv1_open_device(bus, dev, 0); ps3bus_resources_init(&sc->sc_mem_rman, bus_index, dev_index, dinfo); cdev = device_add_child(self, NULL, -1); if (cdev == NULL) { device_printf(self, "device_add_child failed\n"); free(dinfo, M_PS3BUS); continue; } mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF); device_set_ivars(cdev, dinfo); } } } clock_register(self, 1000); return (bus_generic_attach(self)); }