blob: a16f74ffbd650c884ab8b083ba7ce38dad1ebcd6 [file] [log] [blame]
Pratik Patel17f3b822011-11-21 12:41:47 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Pratik Patel7831c082011-06-08 21:44:37 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
Pratik Patelcf418622011-09-22 11:15:11 -070015#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/device.h>
Pratik Patel7831c082011-06-08 21:44:37 -070018#include <linux/platform_device.h>
19#include <linux/io.h>
20#include <linux/err.h>
21
22#include "qdss.h"
23
24#define funnel_writel(funnel, id, val, off) \
25 __raw_writel((val), funnel.base + (SZ_4K * id) + off)
26#define funnel_readl(funnel, id, off) \
27 __raw_readl(funnel.base + (SZ_4K * id) + off)
28
Pratik Patel61de7302012-03-07 12:06:10 -080029#define FUNNEL_FUNCTL (0x000)
30#define FUNNEL_PRICTL (0x004)
31#define FUNNEL_ITATBDATA0 (0xEEC)
32#define FUNNEL_ITATBCTR2 (0xEF0)
33#define FUNNEL_ITATBCTR1 (0xEF4)
34#define FUNNEL_ITATBCTR0 (0xEF8)
Pratik Patel7831c082011-06-08 21:44:37 -070035
36
37#define FUNNEL_LOCK(id) \
38do { \
39 mb(); \
Pratik Patel17f3b822011-11-21 12:41:47 -080040 funnel_writel(funnel, id, 0x0, CS_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -070041} while (0)
42#define FUNNEL_UNLOCK(id) \
43do { \
Pratik Patel17f3b822011-11-21 12:41:47 -080044 funnel_writel(funnel, id, CS_UNLOCK_MAGIC, CS_LAR); \
Pratik Patel7831c082011-06-08 21:44:37 -070045 mb(); \
46} while (0)
47
Pratik Patel7831c082011-06-08 21:44:37 -070048#define DEFAULT_PRIORITY (0xFAC680)
Pratik Patel61de7302012-03-07 12:06:10 -080049#define FUNNEL_HOLDTIME_MASK (0xF00)
50#define FUNNEL_HOLDTIME_SHFT (0x8)
51#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
Pratik Patel7831c082011-06-08 21:44:37 -070052
53struct funnel_ctx {
54 void __iomem *base;
55 bool enabled;
56 struct device *dev;
57};
58
59static struct funnel_ctx funnel;
60
61static void __funnel_enable(uint8_t id, uint32_t port_mask)
62{
63 uint32_t functl;
64
65 FUNNEL_UNLOCK(id);
66
Pratik Patel61de7302012-03-07 12:06:10 -080067 functl = funnel_readl(funnel, id, FUNNEL_FUNCTL);
68 functl &= ~FUNNEL_HOLDTIME_MASK;
69 functl |= FUNNEL_HOLDTIME;
Pratik Patel7831c082011-06-08 21:44:37 -070070 functl |= port_mask;
Pratik Patel61de7302012-03-07 12:06:10 -080071 funnel_writel(funnel, id, functl, FUNNEL_FUNCTL);
72 funnel_writel(funnel, id, DEFAULT_PRIORITY, FUNNEL_PRICTL);
Pratik Patel7831c082011-06-08 21:44:37 -070073
74 FUNNEL_LOCK(id);
75}
76
77void funnel_enable(uint8_t id, uint32_t port_mask)
78{
79 __funnel_enable(id, port_mask);
80 funnel.enabled = true;
Pratik Patel61de7302012-03-07 12:06:10 -080081 dev_info(funnel.dev, "FUNNEL port mask 0x%lx enabled\n",
Pratik Patel7831c082011-06-08 21:44:37 -070082 (unsigned long) port_mask);
83}
84
85static void __funnel_disable(uint8_t id, uint32_t port_mask)
86{
87 uint32_t functl;
88
89 FUNNEL_UNLOCK(id);
90
Pratik Patel61de7302012-03-07 12:06:10 -080091 functl = funnel_readl(funnel, id, FUNNEL_FUNCTL);
Pratik Patel7831c082011-06-08 21:44:37 -070092 functl &= ~port_mask;
Pratik Patel61de7302012-03-07 12:06:10 -080093 funnel_writel(funnel, id, functl, FUNNEL_FUNCTL);
Pratik Patel7831c082011-06-08 21:44:37 -070094
95 FUNNEL_LOCK(id);
96}
97
98void funnel_disable(uint8_t id, uint32_t port_mask)
99{
100 __funnel_disable(id, port_mask);
101 funnel.enabled = false;
Pratik Patel61de7302012-03-07 12:06:10 -0800102 dev_info(funnel.dev, "FUNNEL port mask 0x%lx disabled\n",
Pratik Patel7831c082011-06-08 21:44:37 -0700103 (unsigned long) port_mask);
104}
105
106static int __devinit funnel_probe(struct platform_device *pdev)
107{
108 int ret;
109 struct resource *res;
110
111 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
112 if (!res) {
113 ret = -EINVAL;
114 goto err_res;
115 }
116
117 funnel.base = ioremap_nocache(res->start, resource_size(res));
118 if (!funnel.base) {
119 ret = -EINVAL;
120 goto err_ioremap;
121 }
122
123 funnel.dev = &pdev->dev;
124
Pratik Patel61de7302012-03-07 12:06:10 -0800125 dev_info(funnel.dev, "FUNNEL initialized\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700126 return 0;
127
128err_ioremap:
129err_res:
Pratik Patel61de7302012-03-07 12:06:10 -0800130 dev_err(funnel.dev, "FUNNEL init failed\n");
Pratik Patel7831c082011-06-08 21:44:37 -0700131 return ret;
132}
133
Pratik Patel59e29942011-12-27 10:31:33 -0800134static int funnel_remove(struct platform_device *pdev)
Pratik Patel7831c082011-06-08 21:44:37 -0700135{
136 if (funnel.enabled)
137 funnel_disable(0x0, 0xFF);
138 iounmap(funnel.base);
139
140 return 0;
141}
142
143static struct platform_driver funnel_driver = {
144 .probe = funnel_probe,
Pratik Patel59e29942011-12-27 10:31:33 -0800145 .remove = funnel_remove,
Pratik Patel7831c082011-06-08 21:44:37 -0700146 .driver = {
147 .name = "msm_funnel",
148 },
149};
150
Pratik Patel59e29942011-12-27 10:31:33 -0800151int __init funnel_init(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700152{
153 return platform_driver_register(&funnel_driver);
154}
Pratik Patel7831c082011-06-08 21:44:37 -0700155
Pratik Patel59e29942011-12-27 10:31:33 -0800156void funnel_exit(void)
Pratik Patel7831c082011-06-08 21:44:37 -0700157{
158 platform_driver_unregister(&funnel_driver);
159}