197933d6cSTarun Kanti DebBarma /** 297933d6cSTarun Kanti DebBarma * OMAP1 Dual-Mode Timers - platform device registration 397933d6cSTarun Kanti DebBarma * 497933d6cSTarun Kanti DebBarma * Contains first level initialization routines which internally 597933d6cSTarun Kanti DebBarma * generates timer device information and registers with linux 6764e4ef0SMarkus Elfring * device model. It also has a low level function to change the timer 797933d6cSTarun Kanti DebBarma * input clock source. 897933d6cSTarun Kanti DebBarma * 997933d6cSTarun Kanti DebBarma * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ 1097933d6cSTarun Kanti DebBarma * Tarun Kanti DebBarma <tarun.kanti@ti.com> 1197933d6cSTarun Kanti DebBarma * Thara Gopinath <thara@ti.com> 1297933d6cSTarun Kanti DebBarma * 1397933d6cSTarun Kanti DebBarma * This program is free software; you can redistribute it and/or modify 1497933d6cSTarun Kanti DebBarma * it under the terms of the GNU General Public License version 2 as 1597933d6cSTarun Kanti DebBarma * published by the Free Software Foundation. 1697933d6cSTarun Kanti DebBarma * 1797933d6cSTarun Kanti DebBarma * This program is distributed "as is" WITHOUT ANY WARRANTY of any 1897933d6cSTarun Kanti DebBarma * kind, whether express or implied; without even the implied warranty 1997933d6cSTarun Kanti DebBarma * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2097933d6cSTarun Kanti DebBarma * GNU General Public License for more details. 2197933d6cSTarun Kanti DebBarma */ 2297933d6cSTarun Kanti DebBarma 2397933d6cSTarun Kanti DebBarma #include <linux/clk.h> 2497933d6cSTarun Kanti DebBarma #include <linux/io.h> 2597933d6cSTarun Kanti DebBarma #include <linux/err.h> 2697933d6cSTarun Kanti DebBarma #include <linux/slab.h> 2797933d6cSTarun Kanti DebBarma #include <linux/platform_device.h> 2840fc3bb5SJon Hunter #include <linux/platform_data/dmtimer-omap.h> 2997933d6cSTarun Kanti DebBarma 3097933d6cSTarun Kanti DebBarma #include <plat/dmtimer.h> 3197933d6cSTarun Kanti DebBarma 32685e2d08STony Lindgren #include "soc.h" 33685e2d08STony Lindgren 3497933d6cSTarun Kanti DebBarma #define OMAP1610_GPTIMER1_BASE 0xfffb1400 3597933d6cSTarun Kanti DebBarma #define OMAP1610_GPTIMER2_BASE 0xfffb1c00 3697933d6cSTarun Kanti DebBarma #define OMAP1610_GPTIMER3_BASE 0xfffb2400 3797933d6cSTarun Kanti DebBarma #define OMAP1610_GPTIMER4_BASE 0xfffb2c00 3897933d6cSTarun Kanti DebBarma #define OMAP1610_GPTIMER5_BASE 0xfffb3400 3997933d6cSTarun Kanti DebBarma #define OMAP1610_GPTIMER6_BASE 0xfffb3c00 4097933d6cSTarun Kanti DebBarma #define OMAP1610_GPTIMER7_BASE 0xfffb7400 4197933d6cSTarun Kanti DebBarma #define OMAP1610_GPTIMER8_BASE 0xfffbd400 4297933d6cSTarun Kanti DebBarma 4397933d6cSTarun Kanti DebBarma #define OMAP1_DM_TIMER_COUNT 8 4497933d6cSTarun Kanti DebBarma 4597933d6cSTarun Kanti DebBarma static int omap1_dm_timer_set_src(struct platform_device *pdev, 4697933d6cSTarun Kanti DebBarma int source) 4797933d6cSTarun Kanti DebBarma { 4897933d6cSTarun Kanti DebBarma int n = (pdev->id - 1) << 1; 4997933d6cSTarun Kanti DebBarma u32 l; 5097933d6cSTarun Kanti DebBarma 516aaec67dSPaul Walmsley l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n); 5297933d6cSTarun Kanti DebBarma l |= source << n; 536aaec67dSPaul Walmsley omap_writel(l, MOD_CONF_CTRL_1); 5497933d6cSTarun Kanti DebBarma 5597933d6cSTarun Kanti DebBarma return 0; 5697933d6cSTarun Kanti DebBarma } 5797933d6cSTarun Kanti DebBarma 588c3d4534SPaul Walmsley static int __init omap1_dm_timer_init(void) 5997933d6cSTarun Kanti DebBarma { 6097933d6cSTarun Kanti DebBarma int i; 6197933d6cSTarun Kanti DebBarma int ret; 6297933d6cSTarun Kanti DebBarma struct dmtimer_platform_data *pdata; 6397933d6cSTarun Kanti DebBarma struct platform_device *pdev; 6497933d6cSTarun Kanti DebBarma 6597933d6cSTarun Kanti DebBarma if (!cpu_is_omap16xx()) 6697933d6cSTarun Kanti DebBarma return 0; 6797933d6cSTarun Kanti DebBarma 6897933d6cSTarun Kanti DebBarma for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) { 6997933d6cSTarun Kanti DebBarma struct resource res[2]; 7097933d6cSTarun Kanti DebBarma u32 base, irq; 7197933d6cSTarun Kanti DebBarma 7297933d6cSTarun Kanti DebBarma switch (i) { 7397933d6cSTarun Kanti DebBarma case 1: 7497933d6cSTarun Kanti DebBarma base = OMAP1610_GPTIMER1_BASE; 7597933d6cSTarun Kanti DebBarma irq = INT_1610_GPTIMER1; 7697933d6cSTarun Kanti DebBarma break; 7797933d6cSTarun Kanti DebBarma case 2: 7897933d6cSTarun Kanti DebBarma base = OMAP1610_GPTIMER2_BASE; 7997933d6cSTarun Kanti DebBarma irq = INT_1610_GPTIMER2; 8097933d6cSTarun Kanti DebBarma break; 8197933d6cSTarun Kanti DebBarma case 3: 8297933d6cSTarun Kanti DebBarma base = OMAP1610_GPTIMER3_BASE; 8397933d6cSTarun Kanti DebBarma irq = INT_1610_GPTIMER3; 8497933d6cSTarun Kanti DebBarma break; 8597933d6cSTarun Kanti DebBarma case 4: 8697933d6cSTarun Kanti DebBarma base = OMAP1610_GPTIMER4_BASE; 8797933d6cSTarun Kanti DebBarma irq = INT_1610_GPTIMER4; 8897933d6cSTarun Kanti DebBarma break; 8997933d6cSTarun Kanti DebBarma case 5: 9097933d6cSTarun Kanti DebBarma base = OMAP1610_GPTIMER5_BASE; 9197933d6cSTarun Kanti DebBarma irq = INT_1610_GPTIMER5; 9297933d6cSTarun Kanti DebBarma break; 9397933d6cSTarun Kanti DebBarma case 6: 9497933d6cSTarun Kanti DebBarma base = OMAP1610_GPTIMER6_BASE; 9597933d6cSTarun Kanti DebBarma irq = INT_1610_GPTIMER6; 9697933d6cSTarun Kanti DebBarma break; 9797933d6cSTarun Kanti DebBarma case 7: 9897933d6cSTarun Kanti DebBarma base = OMAP1610_GPTIMER7_BASE; 9997933d6cSTarun Kanti DebBarma irq = INT_1610_GPTIMER7; 10097933d6cSTarun Kanti DebBarma break; 10197933d6cSTarun Kanti DebBarma case 8: 10297933d6cSTarun Kanti DebBarma base = OMAP1610_GPTIMER8_BASE; 10397933d6cSTarun Kanti DebBarma irq = INT_1610_GPTIMER8; 10497933d6cSTarun Kanti DebBarma break; 10597933d6cSTarun Kanti DebBarma default: 10697933d6cSTarun Kanti DebBarma /* 10797933d6cSTarun Kanti DebBarma * not supposed to reach here. 10897933d6cSTarun Kanti DebBarma * this is to remove warning. 10997933d6cSTarun Kanti DebBarma */ 11097933d6cSTarun Kanti DebBarma return -EINVAL; 11197933d6cSTarun Kanti DebBarma } 11297933d6cSTarun Kanti DebBarma 11397933d6cSTarun Kanti DebBarma pdev = platform_device_alloc("omap_timer", i); 11497933d6cSTarun Kanti DebBarma if (!pdev) { 11597933d6cSTarun Kanti DebBarma pr_err("%s: Failed to device alloc for dmtimer%d\n", 11697933d6cSTarun Kanti DebBarma __func__, i); 11797933d6cSTarun Kanti DebBarma return -ENOMEM; 11897933d6cSTarun Kanti DebBarma } 11997933d6cSTarun Kanti DebBarma 12097933d6cSTarun Kanti DebBarma memset(res, 0, 2 * sizeof(struct resource)); 12197933d6cSTarun Kanti DebBarma res[0].start = base; 12297933d6cSTarun Kanti DebBarma res[0].end = base + 0x46; 12397933d6cSTarun Kanti DebBarma res[0].flags = IORESOURCE_MEM; 12497933d6cSTarun Kanti DebBarma res[1].start = irq; 12597933d6cSTarun Kanti DebBarma res[1].end = irq; 12697933d6cSTarun Kanti DebBarma res[1].flags = IORESOURCE_IRQ; 12797933d6cSTarun Kanti DebBarma ret = platform_device_add_resources(pdev, res, 12897933d6cSTarun Kanti DebBarma ARRAY_SIZE(res)); 12997933d6cSTarun Kanti DebBarma if (ret) { 13097933d6cSTarun Kanti DebBarma dev_err(&pdev->dev, "%s: Failed to add resources.\n", 13197933d6cSTarun Kanti DebBarma __func__); 13297933d6cSTarun Kanti DebBarma goto err_free_pdev; 13397933d6cSTarun Kanti DebBarma } 13497933d6cSTarun Kanti DebBarma 13597933d6cSTarun Kanti DebBarma pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); 13697933d6cSTarun Kanti DebBarma if (!pdata) { 13797933d6cSTarun Kanti DebBarma ret = -ENOMEM; 13897933d6cSTarun Kanti DebBarma goto err_free_pdata; 13997933d6cSTarun Kanti DebBarma } 14097933d6cSTarun Kanti DebBarma 14197933d6cSTarun Kanti DebBarma pdata->set_timer_src = omap1_dm_timer_set_src; 1426615975bSJon Hunter pdata->timer_capability = OMAP_TIMER_ALWON | 1435c3e4ec4SJon Hunter OMAP_TIMER_NEEDS_RESET | OMAP_TIMER_HAS_DSP_IRQ; 14497933d6cSTarun Kanti DebBarma 14597933d6cSTarun Kanti DebBarma ret = platform_device_add_data(pdev, pdata, sizeof(*pdata)); 14697933d6cSTarun Kanti DebBarma if (ret) { 14797933d6cSTarun Kanti DebBarma dev_err(&pdev->dev, "%s: Failed to add platform data.\n", 14897933d6cSTarun Kanti DebBarma __func__); 14997933d6cSTarun Kanti DebBarma goto err_free_pdata; 15097933d6cSTarun Kanti DebBarma } 15197933d6cSTarun Kanti DebBarma 15297933d6cSTarun Kanti DebBarma ret = platform_device_add(pdev); 15397933d6cSTarun Kanti DebBarma if (ret) { 15497933d6cSTarun Kanti DebBarma dev_err(&pdev->dev, "%s: Failed to add platform device.\n", 15597933d6cSTarun Kanti DebBarma __func__); 15697933d6cSTarun Kanti DebBarma goto err_free_pdata; 15797933d6cSTarun Kanti DebBarma } 15897933d6cSTarun Kanti DebBarma 15997933d6cSTarun Kanti DebBarma dev_dbg(&pdev->dev, " Registered.\n"); 16097933d6cSTarun Kanti DebBarma } 16197933d6cSTarun Kanti DebBarma 16297933d6cSTarun Kanti DebBarma return 0; 16397933d6cSTarun Kanti DebBarma 16497933d6cSTarun Kanti DebBarma err_free_pdata: 16597933d6cSTarun Kanti DebBarma kfree(pdata); 16697933d6cSTarun Kanti DebBarma 16797933d6cSTarun Kanti DebBarma err_free_pdev: 16897933d6cSTarun Kanti DebBarma platform_device_unregister(pdev); 16997933d6cSTarun Kanti DebBarma 17097933d6cSTarun Kanti DebBarma return ret; 17197933d6cSTarun Kanti DebBarma } 17297933d6cSTarun Kanti DebBarma arch_initcall(omap1_dm_timer_init); 173