linux/drivers/staging/tidspbridge/core/wdt.c
<<
>>
Prefs
   1/*
   2 * wdt.c
   3 *
   4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
   5 *
   6 * IO dispatcher for a shared memory channel driver.
   7 *
   8 * Copyright (C) 2010 Texas Instruments, Inc.
   9 *
  10 * This package is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 *
  14 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  17 */
  18#include <linux/types.h>
  19
  20#include <dspbridge/dbdefs.h>
  21#include <dspbridge/dspdeh.h>
  22#include <dspbridge/dev.h>
  23#include <dspbridge/_chnl_sm.h>
  24#include <dspbridge/wdt.h>
  25#include <dspbridge/host_os.h>
  26
  27
  28#define OMAP34XX_WDT3_BASE      (0x49000000 + 0x30000)
  29#define INT_34XX_WDT3_IRQ       (36 + NR_IRQS)
  30
  31static struct dsp_wdt_setting dsp_wdt;
  32
  33void dsp_wdt_dpc(unsigned long data)
  34{
  35        struct deh_mgr *deh_mgr;
  36        dev_get_deh_mgr(dev_get_first(), &deh_mgr);
  37        if (deh_mgr)
  38                bridge_deh_notify(deh_mgr, DSP_WDTOVERFLOW, 0);
  39}
  40
  41irqreturn_t dsp_wdt_isr(int irq, void *data)
  42{
  43        u32 value;
  44        /* ack wdt3 interrupt */
  45        value = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
  46        __raw_writel(value, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
  47
  48        tasklet_schedule(&dsp_wdt.wdt3_tasklet);
  49        return IRQ_HANDLED;
  50}
  51
  52int dsp_wdt_init(void)
  53{
  54        int ret = 0;
  55
  56        dsp_wdt.sm_wdt = NULL;
  57        dsp_wdt.reg_base = ioremap(OMAP34XX_WDT3_BASE, SZ_4K);
  58        if (!dsp_wdt.reg_base)
  59                return -ENOMEM;
  60
  61        tasklet_init(&dsp_wdt.wdt3_tasklet, dsp_wdt_dpc, 0);
  62
  63        dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");
  64
  65        if (!IS_ERR(dsp_wdt.fclk)) {
  66                clk_prepare(dsp_wdt.fclk);
  67
  68                dsp_wdt.iclk = clk_get(NULL, "wdt3_ick");
  69                if (IS_ERR(dsp_wdt.iclk)) {
  70                        clk_put(dsp_wdt.fclk);
  71                        dsp_wdt.fclk = NULL;
  72                        ret = -EFAULT;
  73                } else {
  74                        clk_prepare(dsp_wdt.iclk);
  75                }
  76        } else
  77                ret = -EFAULT;
  78
  79        if (!ret)
  80                ret = request_irq(INT_34XX_WDT3_IRQ, dsp_wdt_isr, 0,
  81                                                        "dsp_wdt", &dsp_wdt);
  82
  83        /* Disable at this moment, it will be enabled when DSP starts */
  84        if (!ret)
  85                disable_irq(INT_34XX_WDT3_IRQ);
  86
  87        return ret;
  88}
  89
  90void dsp_wdt_sm_set(void *data)
  91{
  92        dsp_wdt.sm_wdt = data;
  93        dsp_wdt.sm_wdt->wdt_overflow = 5;       /* in seconds */
  94}
  95
  96
  97void dsp_wdt_exit(void)
  98{
  99        free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt);
 100        tasklet_kill(&dsp_wdt.wdt3_tasklet);
 101
 102        if (dsp_wdt.fclk) {
 103                clk_unprepare(dsp_wdt.fclk);
 104                clk_put(dsp_wdt.fclk);
 105        }
 106        if (dsp_wdt.iclk) {
 107                clk_unprepare(dsp_wdt.iclk);
 108                clk_put(dsp_wdt.iclk);
 109        }
 110
 111        dsp_wdt.fclk = NULL;
 112        dsp_wdt.iclk = NULL;
 113        dsp_wdt.sm_wdt = NULL;
 114
 115        if (dsp_wdt.reg_base)
 116                iounmap(dsp_wdt.reg_base);
 117        dsp_wdt.reg_base = NULL;
 118}
 119
 120void dsp_wdt_enable(bool enable)
 121{
 122        u32 tmp;
 123        static bool wdt_enable;
 124
 125        if (wdt_enable == enable || !dsp_wdt.fclk || !dsp_wdt.iclk)
 126                return;
 127
 128        wdt_enable = enable;
 129
 130        if (enable) {
 131                clk_enable(dsp_wdt.fclk);
 132                clk_enable(dsp_wdt.iclk);
 133                dsp_wdt.sm_wdt->wdt_setclocks = 1;
 134                tmp = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
 135                __raw_writel(tmp, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
 136                enable_irq(INT_34XX_WDT3_IRQ);
 137        } else {
 138                disable_irq(INT_34XX_WDT3_IRQ);
 139                dsp_wdt.sm_wdt->wdt_setclocks = 0;
 140                clk_disable(dsp_wdt.iclk);
 141                clk_disable(dsp_wdt.fclk);
 142        }
 143}
 144