From dd3876ed6220b0d1ebc7a200c822180cabb1a36a Mon Sep 17 00:00:00 2001 From: hhb Date: Tue, 4 Mar 2014 15:05:09 +0800 Subject: [PATCH 1/2] watch dog: prepare driver for kernel3.10 --- arch/arm/boot/dts/rk3188.dtsi | 13 ++++ drivers/watchdog/Kconfig | 24 +++++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/rk29_wdt.c | 122 ++++++++++++++++------------------ 4 files changed, 96 insertions(+), 64 deletions(-) diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index 4472b94cb96c..34d96873a1f1 100755 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -201,6 +201,19 @@ rockchip,clocksource = <1>; }; + watchdog:wdt@2004c000 { + compatible = "rockchip,watch dog"; + reg = <0x2004c000 0x100>; + clocks = <&clk_gates7 15>; + clock-names = "pclk_wdt"; + interrupts = ; + rockchip,irq = <1>; + rockchip,timeout = <5>; + rockchip,atboot = <1>; + rockchip,debug = <0>; + status = "disabled"; + }; + amba { #address-cells = <1>; #size-cells = <1>; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index e89fc3133972..47a548955422 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -107,6 +107,30 @@ config WM8350_WATCHDOG # ARM Architecture +config RK29_WATCHDOG + tristate "RK29 watchdog" + help + Watchdog timer embedded into RK29xx chips. This will reboot your + system when the timeout is reached. + +config RK29_FEED_DOG_BY_INTE + bool "feed watchdog by interrupt" + depends on RK29_WATCHDOG + +config RK29_WATCHDOG_ATBOOT + bool "start watchdog at system boot" + depends on RK29_WATCHDOG + +config RK29_WATCHDOG_DEFAULT_TIME + int "set watchdog time out value (unit second)" + depends on RK29_WATCHDOG + help + the real time out value is two times more than the setting value + +config RK29_WATCHDOG_DEBUG + bool "enable watchdog debug" + depends on RK29_WATCHDOG + config ARM_SP805_WATCHDOG tristate "ARM SP805 Watchdog" depends on ARM && ARM_AMBA diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index a300b948f254..63ad0297c06f 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o +obj-$(CONFIG_RK29_WATCHDOG) += rk29_wdt.o obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o diff --git a/drivers/watchdog/rk29_wdt.c b/drivers/watchdog/rk29_wdt.c index 06a06c31e031..990b6d145575 100644 --- a/drivers/watchdog/rk29_wdt.c +++ b/drivers/watchdog/rk29_wdt.c @@ -33,6 +33,9 @@ #include #include #include +#ifdef CONFIG_OF +#include +#endif /* RK29 registers define */ @@ -139,7 +142,7 @@ static void __rk29_wdt_stop(void) void rk29_wdt_stop(void) { __rk29_wdt_stop(); - clk_disable(wdt_clock); + clk_disable_unprepare(wdt_clock); } /* timeout unit second */ @@ -174,7 +177,7 @@ int rk29_wdt_set_heartbeat(int timeout) void rk29_wdt_start(void) { unsigned long wtcon; - clk_enable(wdt_clock); + clk_prepare_enable(wdt_clock); rk29_wdt_set_heartbeat(tmr_margin); wtcon = (RK29_WDT_EN << 0) | (RK29_RESPONSE_MODE << 1) | (RK29_RESET_PULSE << 2); wdt_writel(wtcon, RK29_WDT_CR); @@ -319,65 +322,69 @@ static irqreturn_t rk29_wdt_irq_handler(int irqno, void *param) /* device interface */ -static int __devinit rk29_wdt_probe(struct platform_device *pdev) +static int rk29_wdt_probe(struct platform_device *pdev) { struct resource *res; struct device *dev; int started = 0; - int ret; - int size; + int ret, val; dev = &pdev->dev; wdt_dev = &pdev->dev; /* get the memory region for the watchdog timer */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(dev, "no memory resource specified\n"); return -ENOENT; } - size = (res->end - res->start) + 1; - wdt_mem = request_mem_region(res->start, size, pdev->name); - if (wdt_mem == NULL) { - dev_err(dev, "failed to get memory region\n"); - ret = -ENOENT; - goto err_req; - } - - wdt_base = ioremap(res->start, size); + wdt_base = devm_request_and_ioremap(&pdev->dev, res); if (wdt_base == NULL) { dev_err(dev, "failed to ioremap() region\n"); - ret = -EINVAL; - goto err_req; + return -EINVAL; } + +#ifdef CONFIG_OF + if(!of_property_read_u32(pdev->dev.of_node, "rockchip,atboot", &val)) + tmr_atboot = val; + else + tmr_atboot = 0; + if(!of_property_read_u32(pdev->dev.of_node, "rockchip,timeout", &val)) + tmr_margin = val; + else + tmr_margin = 0; + + if(!of_property_read_u32(pdev->dev.of_node, "rockchip,debug", &val)) + debug = val; + else + debug = 0; DBG("probe: mapped wdt_base=%p\n", wdt_base); - -#ifdef CONFIG_RK29_FEED_DOG_BY_INTE - - wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (wdt_irq == NULL) { - dev_err(dev, "no irq resource specified\n"); - ret = -ENOENT; - goto err_map; - } - - ret = request_irq(wdt_irq->start, rk29_wdt_irq_handler, 0, pdev->name, pdev); - - if (ret != 0) { - dev_err(dev, "failed to install irq (%d)\n", ret); - goto err_map; - } - + of_property_read_u32(pdev->dev.of_node, "rockchip,irq", &val); #endif - wdt_clock = clk_get(&pdev->dev, "wdt"); - if (IS_ERR(wdt_clock)) { - wdt_clock = clk_get(&pdev->dev, "pclk_wdt"); +#ifdef CONFIG_RK29_FEED_DOG_BY_INTE + val = 1; +#endif + //printk("atboot:%d, timeout:%ds, debug:%d, irq:%d\n", tmr_atboot, tmr_margin, debug, val); + + if(val == 1) { + wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (wdt_irq == NULL) { + dev_err(dev, "no irq resource specified\n"); + return -ENOENT; + } + + ret = request_irq(wdt_irq->start, rk29_wdt_irq_handler, 0, pdev->name, pdev); + if (ret != 0) { + dev_err(dev, "failed to install irq (%d)\n", ret); + return ret; + } } + + wdt_clock = devm_clk_get(&pdev->dev, "pclk_wdt"); if (IS_ERR(wdt_clock)) { dev_err(dev, "failed to find watchdog clock source\n"); ret = PTR_ERR(wdt_clock); @@ -388,7 +395,7 @@ static int __devinit rk29_wdt_probe(struct platform_device *pdev) if (ret) { dev_err(dev, "cannot register miscdev on minor=%d (%d)\n", WATCHDOG_MINOR, ret); - goto err_clk; + goto err_irq; } if (tmr_atboot && started == 0) { dev_info(dev, "starting watchdog timer\n"); @@ -400,42 +407,21 @@ static int __devinit rk29_wdt_probe(struct platform_device *pdev) rk29_wdt_stop(); } - return 0; - err_clk: - clk_disable(wdt_clock); - clk_put(wdt_clock); - - err_irq: +err_irq: free_irq(wdt_irq->start, pdev); - - err_map: - iounmap(wdt_base); - - err_req: - release_resource(wdt_mem); - kfree(wdt_mem); - return ret; } -static int __devexit rk29_wdt_remove(struct platform_device *dev) +static int rk29_wdt_remove(struct platform_device *dev) { - release_resource(wdt_mem); - kfree(wdt_mem); wdt_mem = NULL; - free_irq(wdt_irq->start, dev); wdt_irq = NULL; - - clk_disable(wdt_clock); - clk_put(wdt_clock); + clk_disable_unprepare(wdt_clock); wdt_clock = NULL; - - iounmap(wdt_base); misc_deregister(&rk29_wdt_miscdev); - return 0; } @@ -463,15 +449,23 @@ static int rk29_wdt_resume(struct platform_device *dev) #define rk29_wdt_resume NULL #endif /* CONFIG_PM */ - +#ifdef CONFIG_OF +static const struct of_device_id of_rk29_wdt_match[] = { + { .compatible = "rockchip,watch dog" }, + { /* Sentinel */ } +}; +#endif static struct platform_driver rk29_wdt_driver = { .probe = rk29_wdt_probe, - .remove = __devexit_p(rk29_wdt_remove), + .remove = rk29_wdt_remove, .shutdown = rk29_wdt_shutdown, .suspend = rk29_wdt_suspend, .resume = rk29_wdt_resume, .driver = { .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = of_rk29_wdt_match, +#endif .name = "rk29-wdt", }, }; From 2e9fd45831dc294c634a61a9746e38aed8ea57cd Mon Sep 17 00:00:00 2001 From: hhb Date: Tue, 4 Mar 2014 15:14:02 +0800 Subject: [PATCH 2/2] dma pl330:change SINGLE to BURST --- arch/arm/boot/dts/rk3188.dtsi | 4 ---- drivers/dma/pl330.c | 26 +++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index 34d96873a1f1..f4e8d7e25075 100755 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -227,8 +227,6 @@ interrupts = , ; #dma-cells = <1>; - #dma-channels = <9>; - #dma-requests = <10>; }; pdma1: pdma@20078000 { @@ -237,8 +235,6 @@ interrupts = , ; #dma-cells = <1>; - #dma-channels = <7>; - #dma-requests = <14>; }; }; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 1244c8f780b3..9ca6f7df9ec1 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1288,10 +1288,17 @@ static inline int _ldst_devtomem(unsigned dry_run, u8 buf[], int off = 0; while (cyc--) { +#ifdef CONFIG_ARCH_ROCKCHIP + off += _emit_WFP(dry_run, &buf[off], BURST, pxs->r->peri); + off += _emit_LDP(dry_run, &buf[off], BURST, pxs->r->peri); + off += _emit_ST(dry_run, &buf[off], ALWAYS); + //off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri); //for sdmmc sdio +#else off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri); off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->r->peri); off += _emit_ST(dry_run, &buf[off], ALWAYS); - //off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri); //for sdmmc sdio + off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri); +#endif } return off; @@ -1303,10 +1310,17 @@ static inline int _ldst_memtodev(unsigned dry_run, u8 buf[], int off = 0; while (cyc--) { +#ifdef CONFIG_ARCH_ROCKCHIP + off += _emit_WFP(dry_run, &buf[off], BURST, pxs->r->peri); + off += _emit_LD(dry_run, &buf[off], ALWAYS); + off += _emit_STP(dry_run, &buf[off], BURST, pxs->r->peri); + //off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri); +#else off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri); off += _emit_LD(dry_run, &buf[off], ALWAYS); off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->r->peri); - //off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri); + off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri); +#endif } return off; @@ -2510,7 +2524,13 @@ static enum dma_status pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, struct dma_tx_state *txstate) { - return dma_cookie_status(chan, cookie, txstate); + struct dma_pl330_chan *pch = to_pchan(chan); + void __iomem *regs = pch->dmac->pif.base; + struct pl330_thread *pt = pch->pl330_chid; + enum dma_status st; + st = dma_cookie_status(chan, cookie, txstate); + txstate->residue = readl(regs + DA(pt->id)); + return st; } static void pl330_issue_pending(struct dma_chan *chan)