static unsigned bfin_jtag_io_write_buffer (struct hw *me, const void *source, int space, address_word addr, unsigned nr_bytes) { struct bfin_jtag *jtag = hw_data (me); bu32 mmr_off; bu32 value; bu32 *valuep; value = dv_load_4 (source); mmr_off = addr - jtag->base; valuep = (void *)((unsigned long)jtag + mmr_base() + mmr_off); HW_TRACE_WRITE (); switch (mmr_off) { case mmr_offset(dbgstat): dv_w1c_4 (valuep, value, 0xc); break; case mmr_offset(dspid): /* Discard writes to these. */ break; default: dv_bfin_mmr_invalid (me, addr, nr_bytes, true); break; } return nr_bytes; }
static unsigned bfin_cec_io_write_buffer (struct hw *me, const void *source, int space, address_word addr, unsigned nr_bytes) { struct bfin_cec *cec = hw_data (me); bu32 mmr_off; bu32 value; value = dv_load_4 (source); mmr_off = addr - cec->base; HW_TRACE_WRITE (); switch (mmr_off) { case mmr_offset(evt_override): cec->evt_override = value; break; case mmr_offset(imask): _cec_imask_write (cec, value); bfin_cec_check_pending (me, cec); break; case mmr_offset(ipend): /* Read-only register. */ break; case mmr_offset(ilat): dv_w1c_4 (&cec->ilat, value, 0xffee); break; case mmr_offset(iprio): cec->iprio = (value & IVG_UNMASKABLE_B); break; } return nr_bytes; }
static unsigned bfin_eppi_io_write_buffer (struct hw *me, const void *source, int space, address_word addr, unsigned nr_bytes) { struct bfin_eppi *eppi = hw_data (me); bu32 mmr_off; bu32 value; bu16 *value16p; bu32 *value32p; void *valuep; if (nr_bytes == 4) value = dv_load_4 (source); else value = dv_load_2 (source); mmr_off = addr - eppi->base; valuep = (void *)((unsigned long)eppi + mmr_base() + mmr_off); value16p = valuep; value32p = valuep; HW_TRACE_WRITE (); switch (mmr_off) { case mmr_offset(status): dv_bfin_mmr_require_16 (me, addr, nr_bytes, true); dv_w1c_2 (value16p, value, 0x1ff); break; case mmr_offset(hcount): case mmr_offset(hdelay): case mmr_offset(vcount): case mmr_offset(vdelay): case mmr_offset(frame): case mmr_offset(line): case mmr_offset(clkdiv): dv_bfin_mmr_require_16 (me, addr, nr_bytes, true); *value16p = value; break; case mmr_offset(control): *value32p = value; bfin_eppi_gui_setup (eppi); break; case mmr_offset(fs1w_hbl): case mmr_offset(fs1p_avpl): case mmr_offset(fsw2_lvb): case mmr_offset(fs2p_lavf): case mmr_offset(clip): case mmr_offset(err): dv_bfin_mmr_require_32 (me, addr, nr_bytes, true); *value32p = value; break; default: dv_bfin_mmr_invalid (me, addr, nr_bytes, true); break; } return nr_bytes; }
static unsigned bfin_wdog_io_write_buffer (struct hw *me, const void *source, int space, address_word addr, unsigned nr_bytes) { struct bfin_wdog *wdog = hw_data (me); bu32 mmr_off; bu32 value; bu16 *value16p; bu32 *value32p; void *valuep; /* Invalid access mode is higher priority than missing register. */ if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true)) return 0; if (nr_bytes == 4) value = dv_load_4 (source); else value = dv_load_2 (source); mmr_off = addr - wdog->base; valuep = (void *)((unsigned long)wdog + mmr_base() + mmr_off); value16p = valuep; value32p = valuep; HW_TRACE_WRITE (); switch (mmr_off) { case mmr_offset(ctl): dv_w1c_2_partial (value16p, value, WDRO); /* XXX: Should enable an event here to handle timeouts. */ break; case mmr_offset(cnt): /* Writes are discarded when enabeld. */ if (!bfin_wdog_enabled (wdog)) { *value32p = value; /* Writes to CNT preloads the STAT. */ wdog->stat = wdog->cnt; } break; case mmr_offset(stat): /* When enabled, writes to STAT reload the counter. */ if (bfin_wdog_enabled (wdog)) wdog->stat = wdog->cnt; /* XXX: When disabled, are writes just ignored ? */ break; } return nr_bytes; }
static unsigned bfin_ebiu_sdc_io_write_buffer (struct hw *me, const void *source, int space, address_word addr, unsigned nr_bytes) { struct bfin_ebiu_sdc *sdc = hw_data (me); bu32 mmr_off; bu32 value; bu16 *value16p; bu32 *value32p; void *valuep; if (nr_bytes == 4) value = dv_load_4 (source); else value = dv_load_2 (source); mmr_off = addr - sdc->base; valuep = (void *)((unsigned long)sdc + mmr_base() + mmr_off); value16p = valuep; value32p = valuep; HW_TRACE_WRITE (); switch (mmr_off) { case mmr_offset(sdgctl): /* XXX: SRFS should make external mem unreadable. */ *value32p = value; break; case mmr_offset(sdbctl): if (sdc->type == 561) { dv_bfin_mmr_require_32 (me, addr, nr_bytes, true); *value32p = value; } else { dv_bfin_mmr_require_16 (me, addr, nr_bytes, true); *value16p = value; } break; case mmr_offset(sdrrc): dv_bfin_mmr_require_16 (me, addr, nr_bytes, true); *value16p = value; break; case mmr_offset(sdstat): dv_bfin_mmr_require_16 (me, addr, nr_bytes, true); /* XXX: Some bits are W1C ... */ break; } return nr_bytes; }
static unsigned bfin_gptimer_io_write_buffer (struct hw *me, const void *source, int space, address_word addr, unsigned nr_bytes) { struct bfin_gptimer *gptimer = hw_data (me); bu32 mmr_off; bu32 value; bu16 *value16p; bu32 *value32p; void *valuep; /* Invalid access mode is higher priority than missing register. */ if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true)) return 0; if (nr_bytes == 4) value = dv_load_4 (source); else value = dv_load_2 (source); mmr_off = addr - gptimer->base; valuep = (void *)((unsigned long)gptimer + mmr_base() + mmr_off); value16p = valuep; value32p = valuep; HW_TRACE_WRITE (); switch (mmr_off) { case mmr_offset(config): if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true)) return 0; *value16p = value; break; case mmr_offset(counter): case mmr_offset(period): case mmr_offset(width): if (!dv_bfin_mmr_require_32 (me, addr, nr_bytes, true)) return 0; *value32p = value; break; default: dv_bfin_mmr_invalid (me, addr, nr_bytes, true); return 0; } return nr_bytes; }
static unsigned bfin_ebiu_ddrc_io_write_buffer (struct hw *me, const void *source, int space, address_word addr, unsigned nr_bytes) { struct bfin_ebiu_ddrc *ddrc = hw_data (me); bu32 mmr_off; bu32 value; bu16 *value16p; bu32 *value32p; void *valuep; /* Invalid access mode is higher priority than missing register. */ if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true)) return 0; if (nr_bytes == 4) value = dv_load_4 (source); else value = dv_load_2 (source); mmr_off = addr - ddrc->base; valuep = (void *)((unsigned long)ddrc + mmr_base() + mmr_off); value16p = valuep; value32p = valuep; HW_TRACE_WRITE (); switch (mmr_off) { case mmr_offset(errmst): case mmr_offset(rstctl): if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true)) return 0; *value16p = value; break; default: if (!dv_bfin_mmr_require_32 (me, addr, nr_bytes, true)) return 0; *value32p = value; break; } return nr_bytes; }
static unsigned bfin_rtc_io_write_buffer (struct hw *me, const void *source, int space, address_word addr, unsigned nr_bytes) { struct bfin_rtc *rtc = hw_data (me); bu32 mmr_off; bu32 value; bu16 *value16p; bu32 *value32p; void *valuep; if (nr_bytes == 4) value = dv_load_4 (source); else value = dv_load_2 (source); mmr_off = addr - rtc->base; valuep = (void *)((unsigned long)rtc + mmr_base() + mmr_off); value16p = valuep; value32p = valuep; HW_TRACE_WRITE (); /* XXX: These probably need more work. */ switch (mmr_off) { case mmr_offset(stat): /* XXX: Ignore these since we are wired to host. */ break; case mmr_offset(istat): dv_w1c_2 (value16p, value, ~(1 << 14)); break; case mmr_offset(alarm): break; case mmr_offset(ictl): /* XXX: This should schedule an event handler. */ case mmr_offset(swcnt): case mmr_offset(pren): break; } return nr_bytes; }
static unsigned bfin_ctimer_io_write_buffer (struct hw *me, const void *source, int space, address_word addr, unsigned nr_bytes) { struct bfin_ctimer *ctimer = hw_data (me); bool curr_enabled; bu32 mmr_off; bu32 value; bu32 *valuep; value = dv_load_4 (source); mmr_off = addr - ctimer->base; valuep = (void *)((unsigned long)ctimer + mmr_base() + mmr_off); HW_TRACE_WRITE (); curr_enabled = bfin_ctimer_enabled (ctimer); switch (mmr_off) { case mmr_offset(tcntl): /* HRM describes TINT as sticky, but it isn't W1C. */ *valuep = value; if (bfin_ctimer_enabled (ctimer) == curr_enabled) { /* Do nothing. */ } else if (curr_enabled) { bfin_ctimer_update_count (me, ctimer); bfin_ctimer_deschedule (me, ctimer); } else bfin_ctimer_schedule (me, ctimer); break; case mmr_offset(tcount): /* HRM says writes are discarded when enabled. */ /* XXX: But hardware seems to be writeable all the time ? */ /* if (!curr_enabled) */ *valuep = value; break; case mmr_offset(tperiod): /* HRM says writes are discarded when enabled. */ /* XXX: But hardware seems to be writeable all the time ? */ /* if (!curr_enabled) */ { /* Writes are mirrored into TCOUNT. */ ctimer->tcount = value; *valuep = value; } break; case mmr_offset(tscale): if (curr_enabled) { bfin_ctimer_update_count (me, ctimer); bfin_ctimer_deschedule (me, ctimer); } *valuep = value; if (curr_enabled) bfin_ctimer_schedule (me, ctimer); break; } return nr_bytes; }
static unsigned bfin_gpio_io_write_buffer (struct hw *me, const void *source, int space, address_word addr, unsigned nr_bytes) { struct bfin_gpio *port = hw_data (me); bu32 mmr_off; bu32 value; bu16 *value16p; bu32 *value32p; void *valuep; mmr_off = addr - port->base; /* Invalid access mode is higher priority than missing register. */ if (mmr_off == mmr_offset (mux)) { if (!dv_bfin_mmr_require_32 (me, addr, nr_bytes, true)) return 0; } else if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true)) return 0; if (nr_bytes == 4) value = dv_load_4 (source); else value = dv_load_2 (source); valuep = (void *)((unsigned long)port + mmr_base() + mmr_off); value16p = valuep; value32p = valuep; HW_TRACE_WRITE (); switch (mmr_off) { case mmr_offset(fer): case mmr_offset(data): case mmr_offset(inen): *value16p = value; break; case mmr_offset(clear): /* We want to clear the related data MMR. */ dv_w1c_2 (&port->data, value, -1); break; case mmr_offset(set): /* We want to set the related data MMR. */ port->data |= value; break; case mmr_offset(dir_clear): dv_w1c_2 (&port->dir, value, -1); break; case mmr_offset(dir_set): port->dir |= value; break; case mmr_offset(mux): *value32p = value; break; default: dv_bfin_mmr_invalid (me, addr, nr_bytes, true); return 0; } /* If tweaking output pins, make sure we send updated port info. */ switch (mmr_off) { case mmr_offset(data): case mmr_offset(set): case mmr_offset(clear): case mmr_offset(dir_set): { int i; bu32 bit; for (i = 0; i < 16; ++i) { bit = (1 << i); if (!(port->inen & bit)) hw_port_event (me, i, !!(port->data & bit)); } break; } } return nr_bytes; }