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#ifdef CONFIG_TIDSPBRIDGE_WDT3 29 30#define OMAP34XX_WDT3_BASE (L4_PER_34XX_BASE + 0x30000) 31 32static struct dsp_wdt_setting dsp_wdt; 33 34void dsp_wdt_dpc(unsigned long data) 35{ 36 struct deh_mgr *deh_mgr; 37 dev_get_deh_mgr(dev_get_first(), &deh_mgr); 38 if (deh_mgr) 39 bridge_deh_notify(deh_mgr, DSP_WDTOVERFLOW, 0); 40} 41 42irqreturn_t dsp_wdt_isr(int irq, void *data) 43{ 44 u32 value; 45 /* ack wdt3 interrupt */ 46 value = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET); 47 __raw_writel(value, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET); 48 49 tasklet_schedule(&dsp_wdt.wdt3_tasklet); 50 return IRQ_HANDLED; 51} 52 53int dsp_wdt_init(void) 54{ 55 int ret = 0; 56 57 dsp_wdt.sm_wdt = NULL; 58 dsp_wdt.reg_base = OMAP2_L4_IO_ADDRESS(OMAP34XX_WDT3_BASE); 59 tasklet_init(&dsp_wdt.wdt3_tasklet, dsp_wdt_dpc, 0); 60 61 dsp_wdt.fclk = clk_get(NULL, "wdt3_fck"); 62 63 if (dsp_wdt.fclk) { 64 dsp_wdt.iclk = clk_get(NULL, "wdt3_ick"); 65 if (!dsp_wdt.iclk) { 66 clk_put(dsp_wdt.fclk); 67 dsp_wdt.fclk = NULL; 68 ret = -EFAULT; 69 } 70 } else 71 ret = -EFAULT; 72 73 if (!ret) 74 ret = request_irq(INT_34XX_WDT3_IRQ, dsp_wdt_isr, 0, 75 "dsp_wdt", &dsp_wdt); 76 77 /* Disable at this moment, it will be enabled when DSP starts */ 78 if (!ret) 79 disable_irq(INT_34XX_WDT3_IRQ); 80 81 return ret; 82} 83 84void dsp_wdt_sm_set(void *data) 85{ 86 dsp_wdt.sm_wdt = data; 87 dsp_wdt.sm_wdt->wdt_overflow = CONFIG_TIDSPBRIDGE_WDT_TIMEOUT; 88} 89 90 91void dsp_wdt_exit(void) 92{ 93 free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt); 94 tasklet_kill(&dsp_wdt.wdt3_tasklet); 95 96 if (dsp_wdt.fclk) 97 clk_put(dsp_wdt.fclk); 98 if (dsp_wdt.iclk) 99 clk_put(dsp_wdt.iclk); 100 101 dsp_wdt.fclk = NULL; 102 dsp_wdt.iclk = NULL; 103 dsp_wdt.sm_wdt = NULL; 104 dsp_wdt.reg_base = NULL; 105} 106 107void dsp_wdt_enable(bool enable) 108{ 109 u32 tmp; 110 static bool wdt_enable; 111 112 if (wdt_enable == enable || !dsp_wdt.fclk || !dsp_wdt.iclk) 113 return; 114 115 wdt_enable = enable; 116 117 if (enable) { 118 clk_enable(dsp_wdt.fclk); 119 clk_enable(dsp_wdt.iclk); 120 dsp_wdt.sm_wdt->wdt_setclocks = 1; 121 tmp = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET); 122 __raw_writel(tmp, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET); 123 enable_irq(INT_34XX_WDT3_IRQ); 124 } else { 125 disable_irq(INT_34XX_WDT3_IRQ); 126 dsp_wdt.sm_wdt->wdt_setclocks = 0; 127 clk_disable(dsp_wdt.iclk); 128 clk_disable(dsp_wdt.fclk); 129 } 130} 131 132#else 133void dsp_wdt_enable(bool enable) 134{ 135} 136 137void dsp_wdt_sm_set(void *data) 138{ 139} 140 141int dsp_wdt_init(void) 142{ 143 return 0; 144} 145 146void dsp_wdt_exit(void) 147{ 148} 149#endif 150