From 10c8828c7b2bf26ab6ec9feee860fc5cc8eb2ce7 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Thu, 29 Dec 2011 16:03:51 +0200 Subject: video: tegra: host: Move device data to nvhost_device Move all device data from nvhost_channeldesc, nvhost_moduledesc and nvhost_module to nvhost_device. nvhost_devices are also assigned into a hierarchy to prepare for implementation of runtime power management. Change-Id: I1e18daae8fe538086cd1f453d316e0f73e9d7d92 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/72844 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Rohan Somvanshi Tested-by: Rohan Somvanshi Reviewed-on: http://git-master/r/74560 Reviewed-by: Varun Wadekar Tested-by: Varun Wadekar --- drivers/video/tegra/host/nvhost_acm.c | 390 ++++++++++++++++------------------ 1 file changed, 184 insertions(+), 206 deletions(-) (limited to 'drivers/video/tegra/host/nvhost_acm.c') diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c index c3b4085df738..7a0108ab5f2f 100644 --- a/drivers/video/tegra/host/nvhost_acm.c +++ b/drivers/video/tegra/host/nvhost_acm.c @@ -56,250 +56,246 @@ static void do_unpowergate_locked(int id) tegra_unpowergate_partition(id); } -void nvhost_module_reset(struct device *dev, struct nvhost_module *mod) +void nvhost_module_reset(struct nvhost_device *dev) { - dev_dbg(dev, + dev_dbg(&dev->dev, "%s: asserting %s module reset (id %d, id2 %d)\n", - __func__, mod->name, - mod->desc->powergate_ids[0], mod->desc->powergate_ids[1]); + __func__, dev->name, + dev->powergate_ids[0], dev->powergate_ids[1]); - mutex_lock(&mod->lock); + mutex_lock(&dev->lock); /* assert module and mc client reset */ - if (mod->desc->powergate_ids[0] != -1) { - tegra_powergate_mc_disable(mod->desc->powergate_ids[0]); - tegra_periph_reset_assert(mod->clk[0]); - tegra_powergate_mc_flush(mod->desc->powergate_ids[0]); + if (dev->powergate_ids[0] != -1) { + tegra_powergate_mc_disable(dev->powergate_ids[0]); + tegra_periph_reset_assert(dev->clk[0]); + tegra_powergate_mc_flush(dev->powergate_ids[0]); } - if (mod->desc->powergate_ids[1] != -1) { - tegra_powergate_mc_disable(mod->desc->powergate_ids[1]); - tegra_periph_reset_assert(mod->clk[1]); - tegra_powergate_mc_flush(mod->desc->powergate_ids[1]); + if (dev->powergate_ids[1] != -1) { + tegra_powergate_mc_disable(dev->powergate_ids[1]); + tegra_periph_reset_assert(dev->clk[1]); + tegra_powergate_mc_flush(dev->powergate_ids[1]); } udelay(POWERGATE_DELAY); /* deassert reset */ - if (mod->desc->powergate_ids[0] != -1) { - tegra_powergate_mc_flush_done(mod->desc->powergate_ids[0]); - tegra_periph_reset_deassert(mod->clk[0]); - tegra_powergate_mc_enable(mod->desc->powergate_ids[0]); + if (dev->powergate_ids[0] != -1) { + tegra_powergate_mc_flush_done(dev->powergate_ids[0]); + tegra_periph_reset_deassert(dev->clk[0]); + tegra_powergate_mc_enable(dev->powergate_ids[0]); } - if (mod->desc->powergate_ids[1] != -1) { - tegra_powergate_mc_flush_done(mod->desc->powergate_ids[1]); - tegra_periph_reset_deassert(mod->clk[1]); - tegra_powergate_mc_enable(mod->desc->powergate_ids[1]); + if (dev->powergate_ids[1] != -1) { + tegra_powergate_mc_flush_done(dev->powergate_ids[1]); + tegra_periph_reset_deassert(dev->clk[1]); + tegra_powergate_mc_enable(dev->powergate_ids[1]); } - mutex_unlock(&mod->lock); + mutex_unlock(&dev->lock); - dev_dbg(dev, "%s: module %s out of reset\n", - __func__, mod->name); + dev_dbg(&dev->dev, "%s: module %s out of reset\n", + __func__, dev->name); } -static void to_state_clockgated_locked(struct nvhost_module *mod) +static void to_state_clockgated_locked(struct nvhost_device *dev) { - const struct nvhost_moduledesc *desc = mod->desc; - if (mod->powerstate == NVHOST_POWER_STATE_RUNNING) { + if (dev->powerstate == NVHOST_POWER_STATE_RUNNING) { int i; - for (i = 0; i < mod->num_clks; i++) - clk_disable(mod->clk[i]); - if (mod->parent) - nvhost_module_idle(mod->parent); - } else if (mod->powerstate == NVHOST_POWER_STATE_POWERGATED - && mod->desc->can_powergate) { - do_unpowergate_locked(desc->powergate_ids[0]); - do_unpowergate_locked(desc->powergate_ids[1]); + for (i = 0; i < dev->num_clks; i++) + clk_disable(dev->clk[i]); + if (dev->dev.parent) + nvhost_module_idle(to_nvhost_device(dev->dev.parent)); + } else if (dev->powerstate == NVHOST_POWER_STATE_POWERGATED + && dev->can_powergate) { + do_unpowergate_locked(dev->powergate_ids[0]); + do_unpowergate_locked(dev->powergate_ids[1]); } - mod->powerstate = NVHOST_POWER_STATE_CLOCKGATED; + dev->powerstate = NVHOST_POWER_STATE_CLOCKGATED; } -static void to_state_running_locked(struct nvhost_module *mod) +static void to_state_running_locked(struct nvhost_device *dev) { - int prev_state = mod->powerstate; - if (mod->powerstate == NVHOST_POWER_STATE_POWERGATED) - to_state_clockgated_locked(mod); - if (mod->powerstate == NVHOST_POWER_STATE_CLOCKGATED) { + int prev_state = dev->powerstate; + if (dev->powerstate == NVHOST_POWER_STATE_POWERGATED) + to_state_clockgated_locked(dev); + if (dev->powerstate == NVHOST_POWER_STATE_CLOCKGATED) { int i; - if (mod->parent) - nvhost_module_busy(mod->parent); + if (dev->dev.parent) + nvhost_module_busy(to_nvhost_device(dev->dev.parent)); - for (i = 0; i < mod->num_clks; i++) { - int err = clk_enable(mod->clk[i]); + for (i = 0; i < dev->num_clks; i++) { + int err = clk_enable(dev->clk[i]); BUG_ON(err); } if (prev_state == NVHOST_POWER_STATE_POWERGATED - && mod->desc->finalize_poweron) - mod->desc->finalize_poweron(mod); + && dev->finalize_poweron) + dev->finalize_poweron(dev); } - mod->powerstate = NVHOST_POWER_STATE_RUNNING; + dev->powerstate = NVHOST_POWER_STATE_RUNNING; } /* This gets called from powergate_handler() and from module suspend. * Module suspend is done for all modules, runtime power gating only * for modules with can_powergate set. */ -static int to_state_powergated_locked(struct nvhost_module *mod) +static int to_state_powergated_locked(struct nvhost_device *dev) { int err = 0; - if (mod->desc->prepare_poweroff - && mod->powerstate != NVHOST_POWER_STATE_POWERGATED) { + if (dev->prepare_poweroff + && dev->powerstate != NVHOST_POWER_STATE_POWERGATED) { /* Clock needs to be on in prepare_poweroff */ - to_state_running_locked(mod); - err = mod->desc->prepare_poweroff(mod); + to_state_running_locked(dev); + err = dev->prepare_poweroff(dev); if (err) return err; } - if (mod->powerstate == NVHOST_POWER_STATE_RUNNING) - to_state_clockgated_locked(mod); + if (dev->powerstate == NVHOST_POWER_STATE_RUNNING) + to_state_clockgated_locked(dev); - if (mod->desc->can_powergate) { - do_powergate_locked(mod->desc->powergate_ids[0]); - do_powergate_locked(mod->desc->powergate_ids[1]); + if (dev->can_powergate) { + do_powergate_locked(dev->powergate_ids[0]); + do_powergate_locked(dev->powergate_ids[1]); } - mod->powerstate = NVHOST_POWER_STATE_POWERGATED; + dev->powerstate = NVHOST_POWER_STATE_POWERGATED; return 0; } -static void schedule_powergating_locked(struct nvhost_module *mod) +static void schedule_powergating_locked(struct nvhost_device *dev) { - if (mod->desc->can_powergate) - schedule_delayed_work(&mod->powerstate_down, - msecs_to_jiffies(mod->desc->powergate_delay)); + if (dev->can_powergate) + schedule_delayed_work(&dev->powerstate_down, + msecs_to_jiffies(dev->powergate_delay)); } -static void schedule_clockgating_locked(struct nvhost_module *mod) +static void schedule_clockgating_locked(struct nvhost_device *dev) { - schedule_delayed_work(&mod->powerstate_down, - msecs_to_jiffies(mod->desc->clockgate_delay)); + schedule_delayed_work(&dev->powerstate_down, + msecs_to_jiffies(dev->clockgate_delay)); } -void nvhost_module_busy(struct nvhost_module *mod) +void nvhost_module_busy(struct nvhost_device *dev) { - if (mod->desc->busy) - mod->desc->busy(mod); + if (dev->busy) + dev->busy(dev); - mutex_lock(&mod->lock); - cancel_delayed_work(&mod->powerstate_down); + mutex_lock(&dev->lock); + cancel_delayed_work(&dev->powerstate_down); - mod->refcount++; - if (mod->refcount > 0 && !nvhost_module_powered(mod)) - to_state_running_locked(mod); - mutex_unlock(&mod->lock); + dev->refcount++; + if (dev->refcount > 0 && !nvhost_module_powered(dev)) + to_state_running_locked(dev); + mutex_unlock(&dev->lock); } static void powerstate_down_handler(struct work_struct *work) { - struct nvhost_module *mod; + struct nvhost_device *dev; - mod = container_of(to_delayed_work(work), - struct nvhost_module, + dev = container_of(to_delayed_work(work), + struct nvhost_device, powerstate_down); - mutex_lock(&mod->lock); - if (mod->refcount == 0) { - switch (mod->powerstate) { + mutex_lock(&dev->lock); + if (dev->refcount == 0) { + switch (dev->powerstate) { case NVHOST_POWER_STATE_RUNNING: - to_state_clockgated_locked(mod); - schedule_powergating_locked(mod); + to_state_clockgated_locked(dev); + schedule_powergating_locked(dev); break; case NVHOST_POWER_STATE_CLOCKGATED: - if (to_state_powergated_locked(mod)) - schedule_powergating_locked(mod); + if (to_state_powergated_locked(dev)) + schedule_powergating_locked(dev); break; default: break; } } - mutex_unlock(&mod->lock); + mutex_unlock(&dev->lock); } -void nvhost_module_idle_mult(struct nvhost_module *mod, int refs) +void nvhost_module_idle_mult(struct nvhost_device *dev, int refs) { bool kick = false; - mutex_lock(&mod->lock); - mod->refcount -= refs; - if (mod->refcount == 0) { - if (nvhost_module_powered(mod)) - schedule_clockgating_locked(mod); + mutex_lock(&dev->lock); + dev->refcount -= refs; + if (dev->refcount == 0) { + if (nvhost_module_powered(dev)) + schedule_clockgating_locked(dev); kick = true; } - mutex_unlock(&mod->lock); + mutex_unlock(&dev->lock); if (kick) { - wake_up(&mod->idle); + wake_up(&dev->idle_wq); - if (mod->desc->idle) - mod->desc->idle(mod); + if (dev->idle) + dev->idle(dev); } } -int nvhost_module_get_rate(struct nvhost_master *host, - struct nvhost_module *mod, unsigned long *rate, +int nvhost_module_get_rate(struct nvhost_device *dev, unsigned long *rate, int index) { struct clk *c; - c = mod->clk[index]; + c = dev->clk[index]; if (IS_ERR_OR_NULL(c)) return -EINVAL; /* Need to enable client to get correct rate */ - nvhost_module_busy(mod); + nvhost_module_busy(dev); *rate = clk_get_rate(c); - nvhost_module_idle(mod); + nvhost_module_idle(dev); return 0; } -static int nvhost_module_update_rate(struct nvhost_module *mod, int index) +static int nvhost_module_update_rate(struct nvhost_device *dev, int index) { unsigned long rate = 0; struct nvhost_module_client *m; - if (!mod->clk[index]) + if (!dev->clk[index]) return -EINVAL; - list_for_each_entry(m, &mod->client_list, node) { + list_for_each_entry(m, &dev->client_list, node) { rate = max(m->rate[index], rate); } if (!rate) - rate = clk_round_rate(mod->clk[index], - mod->desc->clocks[index].default_rate); + rate = clk_round_rate(dev->clk[index], + dev->clocks[index].default_rate); - return clk_set_rate(mod->clk[index], rate); + return clk_set_rate(dev->clk[index], rate); } -int nvhost_module_set_rate(struct nvhost_master *host, - struct nvhost_module *mod, void *priv, +int nvhost_module_set_rate(struct nvhost_device *dev, void *priv, unsigned long rate, int index) { struct nvhost_module_client *m; int ret; mutex_lock(&client_list_lock); - list_for_each_entry(m, &mod->client_list, node) { + list_for_each_entry(m, &dev->client_list, node) { if (m->priv == priv) { - rate = clk_round_rate(mod->clk[index], rate); + rate = clk_round_rate(dev->clk[index], rate); m->rate[index] = rate; break; } } - ret = nvhost_module_update_rate(mod, index); + ret = nvhost_module_update_rate(dev, index); mutex_unlock(&client_list_lock); return ret; } -int nvhost_module_add_client(struct nvhost_master *host, - struct nvhost_module *mod, void *priv) +int nvhost_module_add_client(struct nvhost_device *dev, void *priv) { int i; unsigned long rate; @@ -312,25 +308,24 @@ int nvhost_module_add_client(struct nvhost_master *host, INIT_LIST_HEAD(&client->node); client->priv = priv; - for (i = 0; i < mod->num_clks; i++) { - rate = clk_round_rate(mod->clk[i], - mod->desc->clocks[i].default_rate); + for (i = 0; i < dev->num_clks; i++) { + rate = clk_round_rate(dev->clk[i], + dev->clocks[i].default_rate); client->rate[i] = rate; } mutex_lock(&client_list_lock); - list_add_tail(&client->node, &mod->client_list); + list_add_tail(&client->node, &dev->client_list); mutex_unlock(&client_list_lock); return 0; } -void nvhost_module_remove_client(struct nvhost_master *host, - struct nvhost_module *mod, void *priv) +void nvhost_module_remove_client(struct nvhost_device *dev, void *priv) { int i; struct nvhost_module_client *m; mutex_lock(&client_list_lock); - list_for_each_entry(m, &mod->client_list, node) { + list_for_each_entry(m, &dev->client_list, node) { if (priv == m->priv) { list_del(&m->node); break; @@ -338,25 +333,24 @@ void nvhost_module_remove_client(struct nvhost_master *host, } if (m) { kfree(m); - for (i = 0; i < mod->num_clks; i++) - nvhost_module_update_rate(mod, i); + for (i = 0; i < dev->num_clks; i++) + nvhost_module_update_rate(dev, i); } mutex_unlock(&client_list_lock); } -void nvhost_module_preinit(const char *name, - const struct nvhost_moduledesc *desc) +void nvhost_module_preinit(struct nvhost_device *dev) { int i = 0; /* initialize clocks to known state */ - while (desc->clocks[i].name && i < NVHOST_MODULE_MAX_CLOCKS) { + while (dev->clocks[i].name && i < NVHOST_MODULE_MAX_CLOCKS) { char devname[MAX_DEVID_LENGTH]; - long rate = desc->clocks[i].default_rate; + long rate = dev->clocks[i].default_rate; struct clk *c; - snprintf(devname, MAX_DEVID_LENGTH, "tegra_%s", name); - c = clk_get_sys(devname, desc->clocks[i].name); + snprintf(devname, MAX_DEVID_LENGTH, "tegra_%s", dev->name); + c = clk_get_sys(devname, dev->clocks[i].name); BUG_ON(IS_ERR_OR_NULL(c)); rate = clk_round_rate(c, rate); @@ -366,145 +360,129 @@ void nvhost_module_preinit(const char *name, i++; } - if (desc->can_powergate) { - do_powergate_locked(desc->powergate_ids[0]); - do_powergate_locked(desc->powergate_ids[1]); + if (dev->can_powergate) { + do_powergate_locked(dev->powergate_ids[0]); + do_powergate_locked(dev->powergate_ids[1]); } else { - do_unpowergate_locked(desc->powergate_ids[0]); - do_unpowergate_locked(desc->powergate_ids[1]); + do_unpowergate_locked(dev->powergate_ids[0]); + do_unpowergate_locked(dev->powergate_ids[1]); } } -int nvhost_module_init(struct nvhost_module *mod, const char *name, - const struct nvhost_moduledesc *desc, - struct nvhost_module *parent, - struct device *dev) +int nvhost_module_init(struct nvhost_device *dev) { int i = 0; - int err; - /* register to kernel */ - mod->drv.driver.name = name; - mod->drv.driver.owner = THIS_MODULE; - err = nvhost_driver_register(&mod->drv); - if (err) - return err; + nvhost_module_preinit(dev); - nvhost_module_preinit(name, desc); - mod->name = name; - - INIT_LIST_HEAD(&mod->client_list); - while (desc->clocks[i].name && i < NVHOST_MODULE_MAX_CLOCKS) { + INIT_LIST_HEAD(&dev->client_list); + while (dev->clocks[i].name && i < NVHOST_MODULE_MAX_CLOCKS) { char devname[MAX_DEVID_LENGTH]; - snprintf(devname, MAX_DEVID_LENGTH, "tegra_%s", name); - mod->clk[i] = clk_get_sys(devname, desc->clocks[i].name); - BUG_ON(IS_ERR_OR_NULL(mod->clk[i])); + snprintf(devname, MAX_DEVID_LENGTH, "tegra_%s", dev->name); + dev->clk[i] = clk_get_sys(devname, dev->clocks[i].name); + BUG_ON(IS_ERR_OR_NULL(dev->clk[i])); i++; } - mod->num_clks = i; - mod->desc = desc; - mod->parent = parent; + dev->num_clks = i; - mutex_init(&mod->lock); - init_waitqueue_head(&mod->idle); - INIT_DELAYED_WORK(&mod->powerstate_down, powerstate_down_handler); + mutex_init(&dev->lock); + init_waitqueue_head(&dev->idle_wq); + INIT_DELAYED_WORK(&dev->powerstate_down, powerstate_down_handler); - if (desc->can_powergate) { - mod->powerstate = NVHOST_POWER_STATE_POWERGATED; - } else { - mod->powerstate = NVHOST_POWER_STATE_CLOCKGATED; - } + if (dev->can_powergate) + dev->powerstate = NVHOST_POWER_STATE_POWERGATED; + else + dev->powerstate = NVHOST_POWER_STATE_CLOCKGATED; - if (desc->init) - desc->init(dev, mod); + if (dev->init) + dev->init(dev); return 0; } -static int is_module_idle(struct nvhost_module *mod) +static int is_module_idle(struct nvhost_device *dev) { int count; - mutex_lock(&mod->lock); - count = mod->refcount; - mutex_unlock(&mod->lock); + mutex_lock(&dev->lock); + count = dev->refcount; + mutex_unlock(&dev->lock); return (count == 0); } -static void debug_not_idle(struct nvhost_master *dev) +static void debug_not_idle(struct nvhost_master *host) { int i; bool lock_released = true; - for (i = 0; i < dev->nb_channels; i++) { - struct nvhost_module *mod = &dev->channels[i].mod; - mutex_lock(&mod->lock); - if (mod->name) - dev_warn(&dev->pdev->dev, + for (i = 0; i < host->nb_channels; i++) { + struct nvhost_device *dev = host->channels[i].dev; + mutex_lock(&dev->lock); + if (dev->name) + dev_warn(&host->pdev->dev, "tegra_grhost: %s: refcnt %d\n", - mod->name, mod->refcount); - mutex_unlock(&mod->lock); + dev->name, dev->refcount); + mutex_unlock(&dev->lock); } - for (i = 0; i < dev->nb_mlocks; i++) { - int c = atomic_read(&dev->cpuaccess.lock_counts[i]); + for (i = 0; i < host->nb_mlocks; i++) { + int c = atomic_read(&host->cpuaccess.lock_counts[i]); if (c) { - dev_warn(&dev->pdev->dev, + dev_warn(&host->pdev->dev, "tegra_grhost: lock id %d: refcnt %d\n", i, c); lock_released = false; } } if (lock_released) - dev_dbg(&dev->pdev->dev, "tegra_grhost: all locks released\n"); + dev_dbg(&host->pdev->dev, "tegra_grhost: all locks released\n"); } -int nvhost_module_suspend(struct nvhost_module *mod, bool system_suspend) +int nvhost_module_suspend(struct nvhost_device *dev, bool system_suspend) { int ret; - struct nvhost_master *dev; + struct nvhost_master *host; if (system_suspend) { - dev = container_of(mod, struct nvhost_master, mod); - if (!is_module_idle(mod)) - debug_not_idle(dev); + host = dev->host; + if (!is_module_idle(dev)) + debug_not_idle(host); } else { - dev = container_of(mod, struct nvhost_channel, mod)->dev; + host = dev->host; } - ret = wait_event_timeout(mod->idle, is_module_idle(mod), + ret = wait_event_timeout(dev->idle_wq, is_module_idle(dev), ACM_SUSPEND_WAIT_FOR_IDLE_TIMEOUT); if (ret == 0) { - dev_info(&dev->pdev->dev, "%s prevented suspend\n", mod->name); + dev_info(&dev->dev, "%s prevented suspend\n", + dev->name); return -EBUSY; } if (system_suspend) - dev_dbg(&dev->pdev->dev, "tegra_grhost: entered idle\n"); + dev_dbg(&dev->dev, "tegra_grhost: entered idle\n"); - mutex_lock(&mod->lock); - cancel_delayed_work(&mod->powerstate_down); - to_state_powergated_locked(mod); - mutex_unlock(&mod->lock); + mutex_lock(&dev->lock); + cancel_delayed_work(&dev->powerstate_down); + to_state_powergated_locked(dev); + mutex_unlock(&dev->lock); - if (mod->desc->suspend) - mod->desc->suspend(mod); + if (dev->suspend) + dev->suspend(dev); return 0; } -void nvhost_module_deinit(struct device *dev, struct nvhost_module *mod) +void nvhost_module_deinit(struct nvhost_device *dev) { int i; - nvhost_driver_unregister(&mod->drv); - - if (mod->desc->deinit) - mod->desc->deinit(dev, mod); + if (dev->deinit) + dev->deinit(dev); - nvhost_module_suspend(mod, false); - for (i = 0; i < mod->num_clks; i++) - clk_put(mod->clk[i]); - mod->powerstate = NVHOST_POWER_STATE_DEINIT; + nvhost_module_suspend(dev, false); + for (i = 0; i < dev->num_clks; i++) + clk_put(dev->clk[i]); + dev->powerstate = NVHOST_POWER_STATE_DEINIT; } -- cgit v1.2.3