1 /*
2 * Copyright (C) STMicroelectronics 2009
3 * Copyright (C) ST-Ericsson SA 2010
4 *
5 * License Terms: GNU General Public License v2
6 * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
7 * Author: Sundar Iyer <sundar.iyer@stericsson.com>
8 * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
9 *
10 * U8500 PRCM Unit interface driver
11 *
12 */
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/errno.h>
16 #include <linux/err.h>
17 #include <linux/io.h>
18 #include <linux/mutex.h>
19 #include <linux/completion.h>
20 #include <linux/jiffies.h>
21 #include <linux/bitops.h>
22 #include <linux/interrupt.h>
23
24 #include <mach/hardware.h>
25 #include <mach/prcmu-regs.h>
26 #include <mach/prcmu-defs.h>
27
28 /* Global var to runtime determine TCDM base for v2 or v1 */
29 static __iomem void *tcdm_base;
30
31 #define _MBOX_HEADER (tcdm_base + 0xFE8)
32 #define MBOX_HEADER_REQ_MB0 (_MBOX_HEADER + 0x0)
33
34 #define REQ_MB1 (tcdm_base + 0xFD0)
35 #define REQ_MB5 (tcdm_base + 0xE44)
36
37 #define REQ_MB1_ARMOPP (REQ_MB1 + 0x0)
38 #define REQ_MB1_APEOPP (REQ_MB1 + 0x1)
39 #define REQ_MB1_BOOSTOPP (REQ_MB1 + 0x2)
40
41 #define ACK_MB1 (tcdm_base + 0xE04)
42 #define ACK_MB5 (tcdm_base + 0xDF4)
43
44 #define ACK_MB1_CURR_ARMOPP (ACK_MB1 + 0x0)
45 #define ACK_MB1_CURR_APEOPP (ACK_MB1 + 0x1)
46
47 #define REQ_MB5_I2C_SLAVE_OP (REQ_MB5)
48 #define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1)
49 #define REQ_MB5_I2C_REG (REQ_MB5 + 2)
50 #define REQ_MB5_I2C_VAL (REQ_MB5 + 3)
51
52 #define ACK_MB5_I2C_STATUS (ACK_MB5 + 1)
53 #define ACK_MB5_I2C_VAL (ACK_MB5 + 3)
54
55 #define PRCM_AVS_VARM_MAX_OPP (tcdm_base + 0x2E4)
56 #define PRCM_AVS_ISMODEENABLE 7
57 #define PRCM_AVS_ISMODEENABLE_MASK (1 << PRCM_AVS_ISMODEENABLE)
58
59 #define I2C_WRITE(slave) \
60 (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0))
61 #define I2C_READ(slave) \
62 (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0) | BIT(0))
63 #define I2C_STOP_EN BIT(3)
64
65 enum mb1_h {
66 MB1H_ARM_OPP = 1,
67 MB1H_APE_OPP,
68 MB1H_ARM_APE_OPP,
69 };
70
71 static struct {
72 struct mutex lock;
73 struct completion work;
74 struct {
75 u8 arm_opp;
76 u8 ape_opp;
77 u8 arm_status;
78 u8 ape_status;
79 } ack;
80 } mb1_transfer;
81
82 enum ack_mb5_status {
83 I2C_WR_OK = 0x01,
84 I2C_RD_OK = 0x02,
85 };
86
87 #define MBOX_BIT BIT
88 #define NUM_MBOX 8
89
90 static struct {
91 struct mutex lock;
92 struct completion work;
93 bool failed;
94 struct {
95 u8 status;
96 u8 value;
97 } ack;
98 } mb5_transfer;
99
100 /**
101 * prcmu_abb_read() - Read register value(s) from the ABB.
102 * @slave: The I2C slave address.
103 * @reg: The (start) register address.
104 * @value: The read out value(s).
105 * @size: The number of registers to read.
106 *
107 * Reads register value(s) from the ABB.
108 * @size has to be 1 for the current firmware version.
109 */
prcmu_abb_read(u8 slave,u8 reg,u8 * value,u8 size)110 int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
111 {
112 int r;
113
114 if (size != 1)
115 return -EINVAL;
116
117 r = mutex_lock_interruptible(&mb5_transfer.lock);
118 if (r)
119 return r;
120
121 while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
122 cpu_relax();
123
124 writeb(I2C_READ(slave), REQ_MB5_I2C_SLAVE_OP);
125 writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
126 writeb(reg, REQ_MB5_I2C_REG);
127
128 writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
129 if (!wait_for_completion_timeout(&mb5_transfer.work,
130 msecs_to_jiffies(500))) {
131 pr_err("prcmu: prcmu_abb_read timed out.\n");
132 r = -EIO;
133 goto unlock_and_return;
134 }
135 r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
136 if (!r)
137 *value = mb5_transfer.ack.value;
138
139 unlock_and_return:
140 mutex_unlock(&mb5_transfer.lock);
141 return r;
142 }
143 EXPORT_SYMBOL(prcmu_abb_read);
144
145 /**
146 * prcmu_abb_write() - Write register value(s) to the ABB.
147 * @slave: The I2C slave address.
148 * @reg: The (start) register address.
149 * @value: The value(s) to write.
150 * @size: The number of registers to write.
151 *
152 * Reads register value(s) from the ABB.
153 * @size has to be 1 for the current firmware version.
154 */
prcmu_abb_write(u8 slave,u8 reg,u8 * value,u8 size)155 int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
156 {
157 int r;
158
159 if (size != 1)
160 return -EINVAL;
161
162 r = mutex_lock_interruptible(&mb5_transfer.lock);
163 if (r)
164 return r;
165
166
167 while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
168 cpu_relax();
169
170 writeb(I2C_WRITE(slave), REQ_MB5_I2C_SLAVE_OP);
171 writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
172 writeb(reg, REQ_MB5_I2C_REG);
173 writeb(*value, REQ_MB5_I2C_VAL);
174
175 writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
176 if (!wait_for_completion_timeout(&mb5_transfer.work,
177 msecs_to_jiffies(500))) {
178 pr_err("prcmu: prcmu_abb_write timed out.\n");
179 r = -EIO;
180 goto unlock_and_return;
181 }
182 r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO);
183
184 unlock_and_return:
185 mutex_unlock(&mb5_transfer.lock);
186 return r;
187 }
188 EXPORT_SYMBOL(prcmu_abb_write);
189
set_ape_cpu_opps(u8 header,enum prcmu_ape_opp ape_opp,enum prcmu_cpu_opp cpu_opp)190 static int set_ape_cpu_opps(u8 header, enum prcmu_ape_opp ape_opp,
191 enum prcmu_cpu_opp cpu_opp)
192 {
193 bool do_ape;
194 bool do_arm;
195 int err = 0;
196
197 do_ape = ((header == MB1H_APE_OPP) || (header == MB1H_ARM_APE_OPP));
198 do_arm = ((header == MB1H_ARM_OPP) || (header == MB1H_ARM_APE_OPP));
199
200 mutex_lock(&mb1_transfer.lock);
201
202 while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
203 cpu_relax();
204
205 writeb(0, MBOX_HEADER_REQ_MB0);
206 writeb(cpu_opp, REQ_MB1_ARMOPP);
207 writeb(ape_opp, REQ_MB1_APEOPP);
208 writeb(0, REQ_MB1_BOOSTOPP);
209 writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
210 wait_for_completion(&mb1_transfer.work);
211 if ((do_ape) && (mb1_transfer.ack.ape_status != 0))
212 err = -EIO;
213 if ((do_arm) && (mb1_transfer.ack.arm_status != 0))
214 err = -EIO;
215
216 mutex_unlock(&mb1_transfer.lock);
217
218 return err;
219 }
220
221 /**
222 * prcmu_set_ape_opp() - Set the OPP of the APE.
223 * @opp: The OPP to set.
224 *
225 * This function sets the OPP of the APE.
226 */
prcmu_set_ape_opp(enum prcmu_ape_opp opp)227 int prcmu_set_ape_opp(enum prcmu_ape_opp opp)
228 {
229 return set_ape_cpu_opps(MB1H_APE_OPP, opp, APE_OPP_NO_CHANGE);
230 }
231 EXPORT_SYMBOL(prcmu_set_ape_opp);
232
233 /**
234 * prcmu_set_cpu_opp() - Set the OPP of the CPU.
235 * @opp: The OPP to set.
236 *
237 * This function sets the OPP of the CPU.
238 */
prcmu_set_cpu_opp(enum prcmu_cpu_opp opp)239 int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp)
240 {
241 return set_ape_cpu_opps(MB1H_ARM_OPP, CPU_OPP_NO_CHANGE, opp);
242 }
243 EXPORT_SYMBOL(prcmu_set_cpu_opp);
244
245 /**
246 * prcmu_set_ape_cpu_opps() - Set the OPPs of the APE and the CPU.
247 * @ape_opp: The APE OPP to set.
248 * @cpu_opp: The CPU OPP to set.
249 *
250 * This function sets the OPPs of the APE and the CPU.
251 */
prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp,enum prcmu_cpu_opp cpu_opp)252 int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp,
253 enum prcmu_cpu_opp cpu_opp)
254 {
255 return set_ape_cpu_opps(MB1H_ARM_APE_OPP, ape_opp, cpu_opp);
256 }
257 EXPORT_SYMBOL(prcmu_set_ape_cpu_opps);
258
259 /**
260 * prcmu_get_ape_opp() - Get the OPP of the APE.
261 *
262 * This function gets the OPP of the APE.
263 */
prcmu_get_ape_opp(void)264 enum prcmu_ape_opp prcmu_get_ape_opp(void)
265 {
266 return readb(ACK_MB1_CURR_APEOPP);
267 }
268 EXPORT_SYMBOL(prcmu_get_ape_opp);
269
270 /**
271 * prcmu_get_cpu_opp() - Get the OPP of the CPU.
272 *
273 * This function gets the OPP of the CPU. The OPP is specified in %%.
274 * PRCMU_OPP_EXT is a special OPP value, not specified in %%.
275 */
prcmu_get_cpu_opp(void)276 int prcmu_get_cpu_opp(void)
277 {
278 return readb(ACK_MB1_CURR_ARMOPP);
279 }
280 EXPORT_SYMBOL(prcmu_get_cpu_opp);
281
prcmu_has_arm_maxopp(void)282 bool prcmu_has_arm_maxopp(void)
283 {
284 return (readb(PRCM_AVS_VARM_MAX_OPP) & PRCM_AVS_ISMODEENABLE_MASK)
285 == PRCM_AVS_ISMODEENABLE_MASK;
286 }
287
read_mailbox_0(void)288 static void read_mailbox_0(void)
289 {
290 writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
291 }
292
read_mailbox_1(void)293 static void read_mailbox_1(void)
294 {
295 mb1_transfer.ack.arm_opp = readb(ACK_MB1_CURR_ARMOPP);
296 mb1_transfer.ack.ape_opp = readb(ACK_MB1_CURR_APEOPP);
297 complete(&mb1_transfer.work);
298 writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
299 }
300
read_mailbox_2(void)301 static void read_mailbox_2(void)
302 {
303 writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR);
304 }
305
read_mailbox_3(void)306 static void read_mailbox_3(void)
307 {
308 writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR);
309 }
310
read_mailbox_4(void)311 static void read_mailbox_4(void)
312 {
313 writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR);
314 }
315
read_mailbox_5(void)316 static void read_mailbox_5(void)
317 {
318 mb5_transfer.ack.status = readb(ACK_MB5_I2C_STATUS);
319 mb5_transfer.ack.value = readb(ACK_MB5_I2C_VAL);
320 complete(&mb5_transfer.work);
321 writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
322 }
323
read_mailbox_6(void)324 static void read_mailbox_6(void)
325 {
326 writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
327 }
328
read_mailbox_7(void)329 static void read_mailbox_7(void)
330 {
331 writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
332 }
333
334 static void (* const read_mailbox[NUM_MBOX])(void) = {
335 read_mailbox_0,
336 read_mailbox_1,
337 read_mailbox_2,
338 read_mailbox_3,
339 read_mailbox_4,
340 read_mailbox_5,
341 read_mailbox_6,
342 read_mailbox_7
343 };
344
prcmu_irq_handler(int irq,void * data)345 static irqreturn_t prcmu_irq_handler(int irq, void *data)
346 {
347 u32 bits;
348 u8 n;
349
350 bits = (readl(PRCM_ARM_IT1_VAL) & (MBOX_BIT(NUM_MBOX) - 1));
351 if (unlikely(!bits))
352 return IRQ_NONE;
353
354 for (n = 0; bits; n++) {
355 if (bits & MBOX_BIT(n)) {
356 bits -= MBOX_BIT(n);
357 read_mailbox[n]();
358 }
359 }
360 return IRQ_HANDLED;
361 }
362
prcmu_early_init(void)363 void __init prcmu_early_init(void)
364 {
365 if (cpu_is_u8500v11() || cpu_is_u8500ed()) {
366 tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1);
367 } else if (cpu_is_u8500v2()) {
368 tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
369 } else {
370 pr_err("prcmu: Unsupported chip version\n");
371 BUG();
372 }
373 }
374
prcmu_init(void)375 static int __init prcmu_init(void)
376 {
377 if (cpu_is_u8500ed()) {
378 pr_err("prcmu: Unsupported chip version\n");
379 return 0;
380 }
381
382 mutex_init(&mb1_transfer.lock);
383 init_completion(&mb1_transfer.work);
384 mutex_init(&mb5_transfer.lock);
385 init_completion(&mb5_transfer.work);
386
387 /* Clean up the mailbox interrupts after pre-kernel code. */
388 writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR);
389
390 return request_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, 0,
391 "prcmu", NULL);
392 }
393
394 arch_initcall(prcmu_init);
395