#ifndef _CN30XXPOWVAR_H_
#define _CN30XXPOWVAR_H_
#define POW_TAG_TYPE_ORDERED 0
#define POW_TAG_TYPE_ATOMIC 1
#define POW_TAG_TYPE_NULL 2
#define POW_TAG_TYPE_NULL_NULL 3
#define POW_TAG_OP_SWTAG 0
#define POW_TAG_OP_SWTAG_FULL 1
#define POW_TAG_OP_SWTAG_DESCHED 2
#define POW_TAG_OP_DESCHED 3
#define POW_TAG_OP_ADDWQ 4
#define POW_TAG_OP_UPD_WQP_GRP 5
#define POW_TAG_OP_CLR_NSCHED 7
#define POW_TAG_OP_NOP 15
#define POW_WAIT 1
#define POW_NO_WAIT 0
#define POW_WORKQ_IRQ(group) (group)
struct cn30xxpow_softc {
struct device sc_dev;
bus_space_tag_t sc_regt;
bus_space_handle_t sc_regh;
int sc_port;
int sc_int_pc_base;
};
struct cn30xxpow_attach_args {
int aa_port;
bus_space_tag_t aa_regt;
};
void cn30xxpow_config(struct cn30xxpow_softc *, int);
#define _POW_RD8(sc, off) \
bus_space_read_8((sc)->sc_regt, (sc)->sc_regh, (off))
#define _POW_WR8(sc, off, v) \
bus_space_write_8((sc)->sc_regt, (sc)->sc_regh, (off), (v))
#define _POW_GROUP_RD8(sc, pi, off) \
bus_space_read_8((sc)->sc_regt, (sc)->sc_regh, \
(off) + sizeof(uint64_t) * (pi)->pi_group)
#define _POW_GROUP_WR8(sc, pi, off, v) \
bus_space_write_8((sc)->sc_regt, (sc)->sc_regh, \
(off) + sizeof(uint64_t) * (pi)->pi_group, (v))
extern struct cn30xxpow_softc cn30xxpow_softc;
static inline uint64_t
cn30xxpow_ops_get_work_load(
int wait)
{
uint64_t ptr =
POW_OPERATION_BASE_IO_BIT |
__BITS64_SET(POW_OPERATION_BASE_MAJOR_DID, 0x0c) |
__BITS64_SET(POW_OPERATION_BASE_SUB_DID, 0x00) |
__BITS64_SET(POW_GET_WORK_LOAD_WAIT, wait);
return octeon_xkphys_read_8(ptr);
}
static inline void
cn30xxpow_ops_get_work_iobdma(
int scraddr,
int wait)
{
const int scrindex = scraddr / sizeof(uint64_t);
uint64_t args =
__BITS64_SET(POW_IOBDMA_GET_WORK_WAIT, wait);
uint64_t value =
__BITS64_SET(POW_IOBDMA_BASE_SCRADDR, scrindex) |
__BITS64_SET(POW_IOBDMA_BASE_LEN, 0x01) |
__BITS64_SET(POW_IOBDMA_BASE_MAJOR_DID, 0x0c) |
__BITS64_SET(POW_IOBDMA_BASE_SUB_DID, 0x00) |
__BITS64_SET(POW_IOBDMA_BASE_39_0, args);
octeon_iobdma_write_8(value);
}
static inline void
cn30xxpow_ops_null_rd_iobdma(
int scraddr)
{
const int scrindex = scraddr / sizeof(uint64_t);
uint64_t value =
__BITS64_SET(POW_IOBDMA_BASE_SCRADDR, scrindex) |
__BITS64_SET(POW_IOBDMA_BASE_LEN, 0x01) |
__BITS64_SET(POW_IOBDMA_BASE_MAJOR_DID, 0x0c) |
__BITS64_SET(POW_IOBDMA_BASE_SUB_DID, 0x04) |
__BITS64_SET(POW_IOBDMA_BASE_39_0, 0);
octeon_iobdma_write_8(value);
}
static inline void
cn30xxpow_store(
int subdid,
uint64_t addr,
int no_sched,
int index,
int op,
int qos,
int grp,
int type,
uint32_t tag)
{
uint64_t ptr =
POW_OPERATION_BASE_IO_BIT |
__BITS64_SET(POW_OPERATION_BASE_MAJOR_DID, 0x0c) |
__BITS64_SET(POW_OPERATION_BASE_SUB_DID, subdid) |
__BITS64_SET(POW_PHY_ADDR_STORE_ADDR, addr);
uint64_t args =
__BITS64_SET(POW_STORE_DATA_NO_SCHED, no_sched) |
__BITS64_SET(POW_STORE_DATA_INDEX, index) |
__BITS64_SET(POW_STORE_DATA_OP, op) |
__BITS64_SET(POW_STORE_DATA_QOS, qos) |
__BITS64_SET(POW_STORE_DATA_GRP, grp) |
__BITS64_SET(POW_STORE_DATA_TYPE, type) |
__BITS64_SET(POW_STORE_DATA_TAG, tag);
octeon_xkphys_write_8(ptr, args);
}
static inline void
cn30xxpow_ops_swtag(int type, uint32_t tag)
{
cn30xxpow_store(
1,
0,
0,
0,
POW_TAG_OP_SWTAG,
0,
0,
type,
tag);
}
static inline void
cn30xxpow_ops_swtag_full(paddr_t addr, int grp, int type, uint32_t tag)
{
cn30xxpow_store(
0,
addr,
0,
0,
POW_TAG_OP_SWTAG_FULL,
0,
grp,
type,
tag);
}
static inline void
cn30xxpow_ops_swtag_desched(int no_sched, int grp, int type, uint32_t tag)
{
cn30xxpow_store(
3,
0,
no_sched,
0,
POW_TAG_OP_SWTAG_DESCHED,
0,
grp,
type,
tag);
}
static inline void
cn30xxpow_ops_desched(int no_sched)
{
cn30xxpow_store(
3,
0,
no_sched,
0,
POW_TAG_OP_DESCHED,
0,
0,
0,
0);
}
static inline void
cn30xxpow_ops_addwq(paddr_t addr, int qos, int grp, int type, uint32_t tag)
{
cn30xxpow_store(
1,
addr,
0,
0,
POW_TAG_OP_ADDWQ,
qos,
grp,
type,
tag);
}
static inline void
cn30xxpow_ops_upd_wqp_grp(paddr_t addr, int grp)
{
cn30xxpow_store(
1,
addr,
0,
0,
POW_TAG_OP_UPD_WQP_GRP,
0,
grp,
0,
0);
}
static inline void
cn30xxpow_ops_clr_nsched(paddr_t addr, int index)
{
cn30xxpow_store(
1,
addr,
0,
index,
POW_TAG_OP_CLR_NSCHED,
0,
0,
0,
0);
}
static inline void
cn30xxpow_ops_nop(void)
{
cn30xxpow_store(
1,
0,
0,
0,
POW_TAG_OP_NOP,
0,
0,
0,
0);
}
static inline int
cn30xxpow_tag_sw_pending(void)
{
int result;
__asm volatile (
" .set push\n"
" .set noreorder\n"
" .set arch=mips64r2\n"
" rdhwr %0, $30\n"
" .set pop\n"
: "=r" (result));
return result == 0;
}
static inline void
cn30xxpow_tag_sw_wait(void)
{
while (cn30xxpow_tag_sw_pending())
continue;
}
void cn30xxpow_work_request_async(uint64_t, uint64_t);
uint64_t *cn30xxpow_work_response_async(uint64_t);
void cn30xxpow_ops_swtag(int, uint32_t);
static inline void
cn30xxpow_config_int_pc(struct cn30xxpow_softc *sc, int unit)
{
uint64_t wq_int_pc;
uint64_t pc_thr;
static uint64_t cpu_clock_hz;
if (cpu_clock_hz == 0)
cpu_clock_hz = curcpu()->ci_hw.clock;
#if 0
pc_thr = (((cpu_clock_hz / 1000000) * (unit)) - 255) / 256;
#else
pc_thr = (cpu_clock_hz) / (unit * 16 * 256);
#endif
wq_int_pc = pc_thr << POW_WQ_INT_PC_PC_THR_SHIFT;
_POW_WR8(sc, POW_WQ_INT_PC_OFFSET, wq_int_pc);
}
static inline void
cn30xxpow_config_int_pc_rate(struct cn30xxpow_softc *sc, int rate)
{
cn30xxpow_config_int_pc(sc, sc->sc_int_pc_base / rate);
}
#endif