Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * OMAP1 Dual-Mode Timers - platform device registration
0004  *
0005  * Contains first level initialization routines which internally
0006  * generates timer device information and registers with linux
0007  * device model. It also has a low level function to change the timer
0008  * input clock source.
0009  *
0010  * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
0011  * Tarun Kanti DebBarma <tarun.kanti@ti.com>
0012  * Thara Gopinath <thara@ti.com>
0013  */
0014 
0015 #include <linux/clk.h>
0016 #include <linux/io.h>
0017 #include <linux/err.h>
0018 #include <linux/slab.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/platform_data/dmtimer-omap.h>
0021 #include <linux/soc/ti/omap1-io.h>
0022 
0023 #include <clocksource/timer-ti-dm.h>
0024 
0025 #include "soc.h"
0026 
0027 #define OMAP1610_GPTIMER1_BASE      0xfffb1400
0028 #define OMAP1610_GPTIMER2_BASE      0xfffb1c00
0029 #define OMAP1610_GPTIMER3_BASE      0xfffb2400
0030 #define OMAP1610_GPTIMER4_BASE      0xfffb2c00
0031 #define OMAP1610_GPTIMER5_BASE      0xfffb3400
0032 #define OMAP1610_GPTIMER6_BASE      0xfffb3c00
0033 #define OMAP1610_GPTIMER7_BASE      0xfffb7400
0034 #define OMAP1610_GPTIMER8_BASE      0xfffbd400
0035 
0036 #define OMAP1_DM_TIMER_COUNT        8
0037 
0038 static int omap1_dm_timer_set_src(struct platform_device *pdev,
0039                 int source)
0040 {
0041     int n = (pdev->id - 1) << 1;
0042     u32 l;
0043 
0044     l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
0045     l |= source << n;
0046     omap_writel(l, MOD_CONF_CTRL_1);
0047 
0048     return 0;
0049 }
0050 
0051 static int __init omap1_dm_timer_init(void)
0052 {
0053     int i;
0054     int ret;
0055     struct dmtimer_platform_data *pdata;
0056     struct platform_device *pdev;
0057 
0058     if (!cpu_is_omap16xx())
0059         return 0;
0060 
0061     for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) {
0062         struct resource res[2];
0063         u32 base, irq;
0064 
0065         switch (i) {
0066         case 1:
0067             base = OMAP1610_GPTIMER1_BASE;
0068             irq = INT_1610_GPTIMER1;
0069             break;
0070         case 2:
0071             base = OMAP1610_GPTIMER2_BASE;
0072             irq = INT_1610_GPTIMER2;
0073             break;
0074         case 3:
0075             base = OMAP1610_GPTIMER3_BASE;
0076             irq = INT_1610_GPTIMER3;
0077             break;
0078         case 4:
0079             base = OMAP1610_GPTIMER4_BASE;
0080             irq = INT_1610_GPTIMER4;
0081             break;
0082         case 5:
0083             base = OMAP1610_GPTIMER5_BASE;
0084             irq = INT_1610_GPTIMER5;
0085             break;
0086         case 6:
0087             base = OMAP1610_GPTIMER6_BASE;
0088             irq = INT_1610_GPTIMER6;
0089             break;
0090         case 7:
0091             base = OMAP1610_GPTIMER7_BASE;
0092             irq = INT_1610_GPTIMER7;
0093             break;
0094         case 8:
0095             base = OMAP1610_GPTIMER8_BASE;
0096             irq = INT_1610_GPTIMER8;
0097             break;
0098         default:
0099             /*
0100              * not supposed to reach here.
0101              * this is to remove warning.
0102              */
0103             return -EINVAL;
0104         }
0105 
0106         pdev = platform_device_alloc("omap_timer", i);
0107         if (!pdev) {
0108             pr_err("%s: Failed to device alloc for dmtimer%d\n",
0109                 __func__, i);
0110             return -ENOMEM;
0111         }
0112 
0113         memset(res, 0, 2 * sizeof(struct resource));
0114         res[0].start = base;
0115         res[0].end = base + 0x46;
0116         res[0].flags = IORESOURCE_MEM;
0117         res[1].start = irq;
0118         res[1].end = irq;
0119         res[1].flags = IORESOURCE_IRQ;
0120         ret = platform_device_add_resources(pdev, res,
0121                 ARRAY_SIZE(res));
0122         if (ret) {
0123             dev_err(&pdev->dev, "%s: Failed to add resources.\n",
0124                 __func__);
0125             goto err_free_pdev;
0126         }
0127 
0128         pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
0129         if (!pdata) {
0130             ret = -ENOMEM;
0131             goto err_free_pdata;
0132         }
0133 
0134         pdata->set_timer_src = omap1_dm_timer_set_src;
0135         pdata->timer_capability = OMAP_TIMER_ALWON |
0136                 OMAP_TIMER_NEEDS_RESET | OMAP_TIMER_HAS_DSP_IRQ;
0137 
0138         ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
0139         if (ret) {
0140             dev_err(&pdev->dev, "%s: Failed to add platform data.\n",
0141                 __func__);
0142             goto err_free_pdata;
0143         }
0144 
0145         ret = platform_device_add(pdev);
0146         if (ret) {
0147             dev_err(&pdev->dev, "%s: Failed to add platform device.\n",
0148                 __func__);
0149             goto err_free_pdata;
0150         }
0151 
0152         dev_dbg(&pdev->dev, " Registered.\n");
0153     }
0154 
0155     return 0;
0156 
0157 err_free_pdata:
0158     kfree(pdata);
0159 
0160 err_free_pdev:
0161     platform_device_unregister(pdev);
0162 
0163     return ret;
0164 }
0165 arch_initcall(omap1_dm_timer_init);