struct device *mcuio_add_soft_hc(struct mcuio_device_id *id, const struct mcuio_soft_hc_ops *ops, void *priv) { struct mcuio_hc_platform_data *plat; struct mcuio_soft_hc *shc = __setup_shc(ops, priv); struct device *out; int stat; if (IS_ERR(shc)) return ERR_PTR(PTR_ERR(shc)); plat = kzalloc(sizeof(*plat), GFP_KERNEL); if (!plat) { kfree(shc); return ERR_PTR(-ENOMEM); } plat->setup_regmap = mcuio_soft_hc_setup_regmap; plat->data = shc; stat = bus_register_notifier(&mcuio_bus_type, &device_nb); if (stat < 0) { kfree(shc); return ERR_PTR(stat); } out = mcuio_add_hc_device(id ? id : &default_soft_hc_id, plat, mcuio_soft_hc_release); if (IS_ERR(out)) { kfree(shc); bus_unregister_notifier(&mcuio_bus_type, &device_nb); return out; } shc->hc = to_mcuio_dev(out); return out; }
static void __device_added(struct device *dev) { struct mcuio_device *mdev = to_mcuio_dev(dev); struct mcuio_device *hc; struct mcuio_soft_hc *shc; struct mcuio_device *ic; struct mcuio_hc_platform_data *plat; int base_irq; /* Ignore the hc */ if (!mdev->device) return; hc = to_mcuio_dev(dev->parent); plat = dev_get_platdata(&hc->dev); if (!plat) { WARN_ON(1); return; } shc = plat->data; if (!shc) { WARN_ON(1); return; } /* FIXME: ADD LOCKING */ ic = shc->irq_controllers[mdev->device]; if (ic) return; base_irq = irq_alloc_descs(-1, 0, MCUIO_FUNCS_PER_DEV, 0); /* New device, add soft local irq controller */ ic = mcuio_add_soft_local_irq_ctrl(hc, mdev->device, base_irq); if (!ic) { pr_err("mcuio soft hc: error adding irq ctrl for dev %d\n", mdev->device); return; } shc->irq_controllers[mdev->device] = ic; /* This is the first function of the new device. When the corresponding mcuio_device was instantiated, the hc had no irqs, fix the field up now */ mdev->irq = base_irq + mdev->fn; }
static struct regmap_mcuio_context * regmap_mcuio_setup_context(struct mcuio_device *mdev, const struct regmap_config *config) { struct mcuio_device *hc = to_mcuio_dev(mdev->dev.parent); struct regmap_mcuio_context *ctx; int min_stride; if (config->reg_bits != 32) return ERR_PTR(-EINVAL); switch (config->val_bits) { case 8: /* The core treats 0 as 1 */ min_stride = 0; break; case 16: min_stride = 2; break; case 32: min_stride = 4; break; #ifdef CONFIG_64BIT case 64: min_stride = 8; break; #endif break; default: return ERR_PTR(-EINVAL); } ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return ERR_PTR(-ENOMEM); ctx->hc = hc; ctx->dev = mdev->device; ctx->func = mdev->fn; ctx->val_bytes = config->val_bits / 8; return ctx; }
static ssize_t show_func(struct device *dev, struct device_attribute *attr, char *buf) { struct mcuio_device *mdev = to_mcuio_dev(dev); return sprintf(buf, "%u", mdev->fn); }
static ssize_t show_class(struct device *dev, struct device_attribute *attr, char *buf) { struct mcuio_device *mdev = to_mcuio_dev(dev); return sprintf(buf, "0x%08x", mdev->id.class); }
static ssize_t show_vendor(struct device *dev, struct device_attribute *attr, char *buf) { struct mcuio_device *mdev = to_mcuio_dev(dev); return sprintf(buf, "0x%04x", mdev->id.vendor); }