static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) { struct sh_timer_config *cfg = pdev->dev.platform_data; struct resource *res; int irq, ret; ret = -ENXIO; memset(p, 0, sizeof(*p)); p->pdev = pdev; if (!cfg) { dev_err(&p->pdev->dev, "missing platform data\n"); goto err0; } platform_set_drvdata(pdev, p); res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&p->pdev->dev, "failed to get I/O memory\n"); goto err0; } irq = platform_get_irq(p->pdev, 0); if (irq < 0) { dev_err(&p->pdev->dev, "failed to get irq\n"); goto err0; } /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { pr_err("sh_cmt: failed to remap I/O memory\n"); goto err0; } /* request irq using setup_irq() (too early for request_irq()) */ p->irqaction.name = cfg->name; p->irqaction.handler = sh_cmt_interrupt; p->irqaction.dev_id = p; p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; ret = setup_irq(irq, &p->irqaction); if (ret) { pr_err("sh_cmt: failed to request irq %d\n", irq); goto err1; } /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, cfg->clk); if (IS_ERR(p->clk)) { pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk); ret = PTR_ERR(p->clk); goto err2; } if (resource_size(res) == 6) { p->width = 16; p->overflow_bit = 0x80; p->clear_bits = ~0x80; } else { p->width = 32; p->overflow_bit = 0x8000; p->clear_bits = ~0xc000; } return sh_cmt_register(p, cfg->name, cfg->clockevent_rating, cfg->clocksource_rating); err2: remove_irq(irq, &p->irqaction); err1: iounmap(p->mapbase); err0: return ret; }
static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) { struct sh_timer_config *cfg = pdev->dev.platform_data; struct resource *res, *res2; int irq, ret; ret = -ENXIO; memset(p, 0, sizeof(*p)); p->pdev = pdev; if (!cfg) { dev_err(&p->pdev->dev, "missing platform data\n"); goto err0; } res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&p->pdev->dev, "failed to get I/O memory\n"); goto err0; } /* optional resource for the shared timer start/stop register */ res2 = platform_get_resource(p->pdev, IORESOURCE_MEM, 1); irq = platform_get_irq(p->pdev, 0); if (irq < 0) { dev_err(&p->pdev->dev, "failed to get irq\n"); goto err0; } /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); goto err0; } /* map second resource for CMSTR */ p->mapbase_str = ioremap_nocache(res2 ? res2->start : res->start - cfg->channel_offset, res2 ? resource_size(res2) : 2); if (p->mapbase_str == NULL) { dev_err(&p->pdev->dev, "failed to remap I/O second memory\n"); goto err1; } /* request irq using setup_irq() (too early for request_irq()) */ p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_cmt_interrupt; p->irqaction.dev_id = p; p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING; /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, "cmt_fck"); if (IS_ERR(p->clk)) { dev_err(&p->pdev->dev, "cannot get clock\n"); ret = PTR_ERR(p->clk); goto err2; } ret = clk_prepare(p->clk); if (ret < 0) goto err3; if (res2 && (resource_size(res2) == 4)) { /* assume both CMSTR and CMCSR to be 32-bit */ p->read_control = sh_cmt_read32; p->write_control = sh_cmt_write32; } else { p->read_control = sh_cmt_read16; p->write_control = sh_cmt_write16; } if (resource_size(res) == 6) { p->width = 16; p->read_count = sh_cmt_read16; p->write_count = sh_cmt_write16; p->overflow_bit = 0x80; p->clear_bits = ~0x80; } else { p->width = 32; p->read_count = sh_cmt_read32; p->write_count = sh_cmt_write32; p->overflow_bit = 0x8000; p->clear_bits = ~0xc000; } if (p->width == (sizeof(p->max_match_value) * 8)) p->max_match_value = ~0; else p->max_match_value = (1 << p->width) - 1; p->match_value = p->max_match_value; raw_spin_lock_init(&p->lock); ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev), cfg->clockevent_rating, cfg->clocksource_rating); if (ret) { dev_err(&p->pdev->dev, "registration failed\n"); goto err4; } p->cs_enabled = false; ret = setup_irq(irq, &p->irqaction); if (ret) { dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); goto err4; } platform_set_drvdata(pdev, p); return 0; err4: clk_unprepare(p->clk); err3: clk_put(p->clk); err2: iounmap(p->mapbase_str); err1: iounmap(p->mapbase); err0: return ret; }