+++ /dev/null
-#ifndef __LUNAIX_AA64_ISRM_H
-#define __LUNAIX_AA64_ISRM_H
-
-#include <asm-generic/isrm.h>
-#include "soc/gic.h"
-
-unsigned int
-aa64_isrm_ivalloc(struct gic_int_param* ivcfg, isr_cb handler);
-
-#endif /* __LUNAIX_AA64_ISRM_H */
};
void
-gic_create_from_dt(struct arm_gic* gic);
+gic_create_from_dt(struct arm_gic* gic, struct dtn* node);
unsigned int;
-gic_dtprop_interpret(struct gic_int_param* param,
- struct dt_prop_val* val, int width);
+gic_decode_specifier(struct gic_int_param* param,
+ struct dtp_val* val, int nr_cells);
struct gic_its*
gic_its_create(struct arm_gic* gic, ptr_t regs);
#include <lunaix/syslog.h>
#include <hal/devtree.h>
+#include <hal/devtreem.h>
-#include <asm/aa64_isrm.h>
#include <asm/soc/gic.h>
static struct arm_gic gic;
set_sysreg(ICC_EOIR1_EL1, pe->iar_val);
}
-/* ****** Lunaix ISRM Interfacing ****** */
-
-void
-isrm_init()
-{
- // nothing to do
-}
-
-void
-isrm_ivfree(int iv)
-{
- struct gic_interrupt* ent;
- struct gic_distributor* dist;
-
- ent = __find_interrupt_record(iv);
- if (!ent) {
- return;
- }
-
- dist = __attached_distributor(0, ent);
- __undone_interrupt(&gic, dist, ent);
-
- hlist_delete(&ent->node);
- vfree(ent);
-}
-
-int
-isrm_ivosalloc(isr_cb handler)
+struct arm_gic*
+gic_instance()
{
- return isrm_ivexalloc(handler);
+ return &gic;
}
-int
-isrm_ivexalloc(isr_cb handler)
-{
- struct gic_int_param param;
- struct gic_interrupt* intr;
-
- param = (struct gic_int_param) {
- .class = GIC_SPI,
- .group = GIC_G1NS,
- .trigger = GIC_TRIG_EDGE,
- };
-
- intr = gic_install_int(¶m, handler, true);
-
- return intr->intid;
-}
-
-isr_cb
-isrm_get(int iv)
-{
- struct gic_interrupt* intr;
-
- intr = __find_interrupt_record(iv);
- if (!intr) {
- return NULL;
- }
-
- return intr->handler;
-}
-
-ptr_t
-isrm_get_payload(const struct hart_state* state)
-{
- struct gic_interrupt* active;
-
- active = gic.pes[0].active;
- assert(active);
-
- return active->handler;
-}
-
-void
-isrm_set_payload(int iv, ptr_t payload)
-{
- struct gic_interrupt* intr;
-
- intr = __find_interrupt_record(iv);
- if (!intr) {
- return NULL;
- }
-
- intr->payload = payload;
-}
-
-void
-isrm_notify_eoi(cpu_t id, int iv)
-{
- gic_signal_eoi();
-}
-
-void
-isrm_notify_eos(cpu_t id)
-{
- isrm_notify_eoi(id, 0);
-}
+/* ****** Device Definition & Export ****** */
-msi_vector_t
-isrm_msialloc(isr_cb handler)
+static void
+gic_register(struct device_def* def)
{
- int intid;
- msi_vector_t msiv;
- struct gic_int_param param;
-
- param = (struct gic_int_param) {
- .group = GIC_G1NS,
- .trigger = GIC_TRIG_EDGE
- };
-
- if (gic.msi_via_spi) {
- param.class = GIC_SPI;
-
- intid = gic_install_int(¶m, handler, true);
- msiv.msi_addr = gic_regptr(gic.mmrs.dist_base, GICD_SETSPI_NSR);
- goto done;
- }
-
- if (unlikely(!gic.lpi_ready)) {
- return invalid_msi_vector;
- }
-
- if (unlikely(llist_empty(&gic.its))) {
- // FIXME The MSI interface need rework
- WARN("ITS-base MSI is yet unsupported.");
- return invalid_msi_vector;
- }
-
- param.class = GIC_LPI;
- intid = gic_install_int(¶m, handler, true);
- msiv.msi_addr = gic_regptr(gic.pes[0]._rd->base, GICR_SETLPIR);
+ dtm_register_entry(def, "arm,gic-v3");
-done:
- msiv.mapped_iv = intid;
- msiv.msi_data = intid;
+ // TODO need to re-exam the programming model for gic v1,v2
+ // dtm_register_entry(def, "arm,cortex-a*-gic");
+ // dtm_register_entry(def, "arm,gic-400");
- return msiv;
+ memset(&gic, 0, sizeof(gic));
}
-int
-isrm_bind_dtnode(struct dt_intr_node* node, isr_cb handler)
+static void
+gic_init(struct device_def* def, morph_t* mobj)
{
- struct dt_prop_val* val;
- struct gic_int_param param;
- struct gic_interrupt* installed;
-
- val = dt_resolve_interrupt(INTR_TO_DTNODE(node));
- if (!val) {
- return EINVAL;
- }
+ struct dtn* node;
+ struct device* gic_dev;
- if (node->intr.extended) {
- WARN("binding of multi interrupt is yet to supported");
- return EINVAL;
+ node = changeling_try_reveal(mobj, dt_morpher);
+ if (!node) {
+ return;
}
- gic_dtprop_interpret(¶m, val, 3);
- param.cpu_id = 0;
-
- installed = gic_install_int(¶m, handler, false);
-
- return installed->intid;
-}
-
-/* ****** Device Definition & Export ****** */
-
-static void
-gic_init()
-{
- memset(&gic, 0, sizeof(gic));
-
- gic_create_from_dt(&gic);
+ gic_create_from_dt(&gic, node);
// configure the system interfaces
gic_configure_icc();
gic_configure_pe(&gic, &gic.pes[i]);
}
+ gic_dev = device_allocsys(NULL, &gic);
+ register_device_var(gic_dev, &def->class, "gic");
+
gic_configure_its(&gic);
}
static struct device_def dev_arm_gic = {
- .name = "ARM Generic Interrupt Controller",
- .class = DEVCLASS(DEVIF_SOC, DEVFN_CFG, DEV_INTC),
- .init = gic_init
+ def_device_name("ARM Generic Interrupt Controller"),
+ def_device_class(ARM, CFG, INTC),
+
+ def_on_register(gic_register),
+ def_on_create(gic_init)
};
EXPORT_DEVICE(arm_gic, &dev_arm_gic, load_sysconf);
\ No newline at end of file
#include <klibc/string.h>
static bool
-__gic_predicate(struct dt_node_iter* iter, struct dt_node_base* pos)
+__its_predicate(struct dt_node_iter* iter, struct dtn_base* pos)
{
- if (likely(!pos->intr_controll)) {
- return false;
- }
-
- return strneq(pos->compat.str_val, "arm,gic-", 8);
+ return strneq(pos->compat.str_val, "arm,gic-v3-its", 14);
}
-static bool
-__its_predicate(struct dt_node_iter* iter, struct dt_node_base* pos)
+static inline void*
+__do_remap_mmio(struct dtpropx* dtpx, int row)
{
- return strneq(pos->compat.str_val, "arm,gic-v3-its", 14);
+ struct dtprop_xval base, size;
+
+ dtpx_extract_loc(&dtpx, &base, row, 0);
+ dtpx_extract_loc(&dtpx, &size, row, 1);
+
+ return ioremap(base.u64, size.u64);
}
-static void
-__setup_pe_rdist(struct arm_gic* gic, struct dt_prop_iter* prop, int cpu)
+static inline void*
+__remap_mmio_dtn(struct dtn* node)
{
- ptr_t base;
- size_t len;
+ struct dtprop_xval base, size;
+ struct dtpropx dtpx;
+ dt_proplet gic_mmio = dtprop_reglike(&node->base);
- base = dtprop_reg_nextaddr(prop);
- len = dtprop_reg_nextlen(prop);
+ dtpx_compile_proplet(gic_mmio);
+ dtpx_prepare_with(&dtpx, &node->reg, &gic_mmio);
- gic->pes[cpu]._rd = (struct gic_rd*)ioremap(base, len);
+ return __do_remap_mmio(&dtpx, 0);
}
static void
-__create_its(struct arm_gic* gic, struct dt_node* gic_node)
+__create_its(struct arm_gic* gic, struct dtn* gic_node)
{
struct dt_node* its_node;
- struct dt_node_iter iter;
- struct dt_prop_iter prop;
- struct gic_its* its;
- ptr_t its_base;
- size_t its_size;
+ struct dtn_iter iter;
dt_begin_find(&iter, gic_node, __its_predicate, NULL);
while (dt_find_next(&iter, (struct dt_node_base**)&its_node))
{
- dt_decode_reg(&prop, its_node, reg);
-
- its_base = dtprop_reg_nextaddr(&prop);
- its_size = dtprop_reg_nextlen(&prop);
-
- its = gic_its_create(gic, ioremap(its_base, its_size));
- dt_bind_object(&its_node->base, its);
+ gic_its_create(gic, __remap_mmio_dtn(its_node));
}
dt_end_find(&iter);
}
void
-gic_create_from_dt(struct arm_gic* gic)
+gic_create_from_dt(struct arm_gic* gic, struct dtn* node)
{
- struct dt_node* gic_node;
- struct dt_node_iter iter;
- struct dt_prop_iter prop;
- ptr_t ptr;
- size_t sz;
+ struct dtpropx dtpx;
+ struct gic_rd* rd;
+ dt_proplet gic_mmio = dtprop_reglike(&node->base);
- dt_begin_find(&iter, NULL, __gic_predicate, NULL);
+ dtpx_compile_proplet(gic_mmio);
+ dtpx_prepare_with(&dtpx, &node->reg, &gic_mmio);
- if (!dt_find_next(&iter, (struct dt_node_base**)&gic_node)) {
- fail("expected 'arm,gic-*' compatible node, but found none");
- }
-
- dt_end_find(&iter);
-
- dt_decode_reg(&prop, gic_node, reg);
-
- ptr = dtprop_reg_nextaddr(&prop);
- sz = dtprop_reg_nextlen(&prop);
- gic->mmrs.dist_base = (gicreg_t*)ioremap(ptr, sz);
+ gic->mmrs.dist_base = (gicreg_t*)__do_remap_mmio(&dtpx, 0);
for (int i = 0; i < NR_CPU; i++) {
- __setup_pe_rdist(gic, &prop, i);
+ rd = (struct gic_rd*)__do_remap_mmio(&dtpx, i + 1);
+ gic->pes[i]._rd = rd;
}
// ignore cpu_if, as we use sysreg to access them
// ignore vcpu_if, as we dont do any EL2 stuff
- __create_its(gic, gic_node);
-
- dt_bind_object(&gic_node->base, gic);
+ __create_its(gic, node);
}
unsigned int;
-gic_dtprop_interpret(struct gic_int_param* param,
- struct dt_prop_val* val, int width)
+gic_decode_specifier(struct gic_int_param* param,
+ struct dtp_val* val, int nr_cells)
{
- struct dt_prop_iter iter;
+ struct dtpropi dtpi;
unsigned int v;
- dt_decode_simple(&iter, val);
+ assert(nr_cells >= 3);
+ dtpi_init(&dtpi, val);
- v = dtprop_u32_at(&iter, 0);
+ v = dtpi_next_u32(&dtpi);
switch (v)
{
case 0:
break;
}
- v = dtprop_u32_at(&iter, 2);
+ param->group = GIC_G1NS;
+ param->rel_intid = dtpi_next_u32(&dtpi);
+
+ v = dtpi_next_u32(&dtpi);
param->trigger = v == 1 ? GIC_TRIG_EDGE : GIC_TRIG_LEVEL;
- param->group = GIC_G1NS;
- param->rel_intid = dtprop_u32_at(&iter, 1);
+ // 4th cell only applicable to PPI, ignore for now
return param->rel_intid;
}
\ No newline at end of file
{
devtree_link_t devtree_node;
- devtree_node = changeling_try_reveal(obj, dt_node_morpher);
+ devtree_node = changeling_try_reveal(obj, dt_morpher);
pci_bridge = device_allocsys(NULL, NULL);
device_set_devtree_node(pci_bridge, devtree_node);
{
int i;
unsigned int acc = 0;
+ struct dtprop_def* pl;
for (i = 0; proplet[i].type && i < 10; ++i)
{
- proplet[i].acc_sz = acc;
- acc += proplet[i].cell;
+ pl = &proplet[i];
+
+ if (pl->type == DTP_COMPX) {
+ if (pl->cell == 1)
+ pl->type = DTP_U32;
+ else if (pl->cell == 2)
+ pl->type = DTP_U64;
+ }
+
+ pl->acc_sz = acc;
+ acc += pl->cell;
}
if (proplet[i - 1].type && i == 10) {
} break;
case DTP_COMPX:
- val->composite = enc;
+ {
+ val->composite = enc;
+ }
break;
default:
return parent;
}
- if (p->binded_dev) {
- cat = changeling_reveal(p->binded_dev, devcat_morpher);
+ if (p->binded_obj) {
+ cat = changeling_reveal(p->binded_obj, devcat_morpher);
}
else {
cat = device_addcat(parent, HSTR_VAL(dt_mobj(p)->name));
- p->binded_dev = dev_mobj(cat);
+ p->binded_obj = dev_mobj(cat);
}
return dev_meta(cat);
struct dtp_table *props;
- morph_t *binded_dev;
+ morph_t *binded_obj;
};
struct dtspec_key
val->size = cells * sizeof(u32_t);
}
+static inline void
+dtn_bind_object(struct dtn* node, morph_t* mobj)
+{
+ node->base.binded_obj = changeling_ref(mobj);
+}
+
//////////////////////////////////////
/// DT Methods: Specifier Map
#define dtprop_reglike(base) \
({ \
dt_proplet p = { \
- dtprop_compx(base->addr_c), \
- dtprop_compx(base->sz_c), \
+ dtprop_compx((base)->addr_c), \
+ dtprop_compx((base)->sz_c), \
dtprop_end \
}; \
- dt_proplet; \
+ p; \
})
#define dtprop_rangelike(node) \
dtprop_compx(base->sz_c), \
dtprop_end \
}; \
- dt_proplet; \
+ p; \
})
#define dtprop_strlst_foreach(pos, prop) \
typedef struct dtn* devtree_link_t;
-#define dt_node_morpher morphable_attrs(dt_node, mobj)
-
struct dtm_driver_info
{
struct list_node node;