blob: 07d5f13d2a4e1be05bdd373fd2cde1d765e7c99c [file] [log] [blame]
Linus Walleije3726fc2010-08-19 12:36:01 +01001/*
2 * Copyright (C) ST Ericsson SA 2010
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
6 *
7 * U8500 PRCMU driver.
8 */
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/errno.h>
12#include <linux/err.h>
13#include <linux/io.h>
14#include <linux/mutex.h>
15#include <linux/completion.h>
16#include <linux/jiffies.h>
17#include <linux/bitops.h>
18#include <linux/interrupt.h>
19
20#include <mach/hardware.h>
21#include <mach/prcmu-regs.h>
22
Mattias Wallinfcbd4582010-12-02 16:20:42 +010023/* Global var to runtime determine TCDM base for v2 or v1 */
24static __iomem void *tcdm_base;
Linus Walleije3726fc2010-08-19 12:36:01 +010025
Mattias Wallinfcbd4582010-12-02 16:20:42 +010026#define REQ_MB5 (tcdm_base + 0xE44)
27#define ACK_MB5 (tcdm_base + 0xDF4)
Linus Walleije3726fc2010-08-19 12:36:01 +010028
29#define REQ_MB5_I2C_SLAVE_OP (REQ_MB5)
30#define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1)
31#define REQ_MB5_I2C_REG (REQ_MB5 + 2)
32#define REQ_MB5_I2C_VAL (REQ_MB5 + 3)
33
34#define ACK_MB5_I2C_STATUS (ACK_MB5 + 1)
35#define ACK_MB5_I2C_VAL (ACK_MB5 + 3)
36
Mattias Wallinfcbd4582010-12-02 16:20:42 +010037#define I2C_WRITE(slave) \
38 (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0))
39#define I2C_READ(slave) \
40 (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0) | BIT(0))
Linus Walleije3726fc2010-08-19 12:36:01 +010041#define I2C_STOP_EN BIT(3)
42
43enum ack_mb5_status {
44 I2C_WR_OK = 0x01,
45 I2C_RD_OK = 0x02,
46};
47
48#define MBOX_BIT BIT
49#define NUM_MBOX 8
50
51static struct {
52 struct mutex lock;
53 struct completion work;
54 bool failed;
55 struct {
56 u8 status;
57 u8 value;
58 } ack;
59} mb5_transfer;
60
61/**
62 * prcmu_abb_read() - Read register value(s) from the ABB.
63 * @slave: The I2C slave address.
64 * @reg: The (start) register address.
65 * @value: The read out value(s).
66 * @size: The number of registers to read.
67 *
68 * Reads register value(s) from the ABB.
69 * @size has to be 1 for the current firmware version.
70 */
71int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
72{
73 int r;
74
75 if (size != 1)
76 return -EINVAL;
77
78 r = mutex_lock_interruptible(&mb5_transfer.lock);
79 if (r)
80 return r;
81
82 while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
83 cpu_relax();
84
85 writeb(I2C_READ(slave), REQ_MB5_I2C_SLAVE_OP);
86 writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
87 writeb(reg, REQ_MB5_I2C_REG);
88
89 writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
90 if (!wait_for_completion_timeout(&mb5_transfer.work,
91 msecs_to_jiffies(500))) {
92 pr_err("prcmu: prcmu_abb_read timed out.\n");
93 r = -EIO;
94 goto unlock_and_return;
95 }
96 r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
97 if (!r)
98 *value = mb5_transfer.ack.value;
99
100unlock_and_return:
101 mutex_unlock(&mb5_transfer.lock);
102 return r;
103}
104EXPORT_SYMBOL(prcmu_abb_read);
105
106/**
107 * prcmu_abb_write() - Write register value(s) to the ABB.
108 * @slave: The I2C slave address.
109 * @reg: The (start) register address.
110 * @value: The value(s) to write.
111 * @size: The number of registers to write.
112 *
113 * Reads register value(s) from the ABB.
114 * @size has to be 1 for the current firmware version.
115 */
116int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
117{
118 int r;
119
120 if (size != 1)
121 return -EINVAL;
122
123 r = mutex_lock_interruptible(&mb5_transfer.lock);
124 if (r)
125 return r;
126
127
128 while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
129 cpu_relax();
130
131 writeb(I2C_WRITE(slave), REQ_MB5_I2C_SLAVE_OP);
132 writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
133 writeb(reg, REQ_MB5_I2C_REG);
134 writeb(*value, REQ_MB5_I2C_VAL);
135
136 writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
137 if (!wait_for_completion_timeout(&mb5_transfer.work,
138 msecs_to_jiffies(500))) {
139 pr_err("prcmu: prcmu_abb_write timed out.\n");
140 r = -EIO;
141 goto unlock_and_return;
142 }
143 r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO);
144
145unlock_and_return:
146 mutex_unlock(&mb5_transfer.lock);
147 return r;
148}
149EXPORT_SYMBOL(prcmu_abb_write);
150
151static void read_mailbox_0(void)
152{
153 writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
154}
155
156static void read_mailbox_1(void)
157{
158 writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
159}
160
161static void read_mailbox_2(void)
162{
163 writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR);
164}
165
166static void read_mailbox_3(void)
167{
168 writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR);
169}
170
171static void read_mailbox_4(void)
172{
173 writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR);
174}
175
176static void read_mailbox_5(void)
177{
178 mb5_transfer.ack.status = readb(ACK_MB5_I2C_STATUS);
179 mb5_transfer.ack.value = readb(ACK_MB5_I2C_VAL);
180 complete(&mb5_transfer.work);
181 writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
182}
183
184static void read_mailbox_6(void)
185{
186 writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
187}
188
189static void read_mailbox_7(void)
190{
191 writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
192}
193
194static void (* const read_mailbox[NUM_MBOX])(void) = {
195 read_mailbox_0,
196 read_mailbox_1,
197 read_mailbox_2,
198 read_mailbox_3,
199 read_mailbox_4,
200 read_mailbox_5,
201 read_mailbox_6,
202 read_mailbox_7
203};
204
205static irqreturn_t prcmu_irq_handler(int irq, void *data)
206{
207 u32 bits;
208 u8 n;
209
210 bits = (readl(PRCM_ARM_IT1_VAL) & (MBOX_BIT(NUM_MBOX) - 1));
211 if (unlikely(!bits))
212 return IRQ_NONE;
213
214 for (n = 0; bits; n++) {
215 if (bits & MBOX_BIT(n)) {
216 bits -= MBOX_BIT(n);
217 read_mailbox[n]();
218 }
219 }
220 return IRQ_HANDLED;
221}
222
Mattias Wallinfcbd4582010-12-02 16:20:42 +0100223void __init prcmu_early_init(void)
224{
225 if (cpu_is_u8500v11() || cpu_is_u8500ed()) {
226 tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1);
227 } else if (cpu_is_u8500v2()) {
228 tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
229 } else {
230 pr_err("prcmu: Unsupported chip version\n");
231 BUG();
232 }
233}
234
Linus Walleije3726fc2010-08-19 12:36:01 +0100235static int __init prcmu_init(void)
236{
237 mutex_init(&mb5_transfer.lock);
238 init_completion(&mb5_transfer.work);
239
240 /* Clean up the mailbox interrupts after pre-kernel code. */
241 writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR);
242
Rabin Vincent22039b72010-12-08 11:07:56 +0530243 return request_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, 0,
244 "prcmu", NULL);
Linus Walleije3726fc2010-08-19 12:36:01 +0100245}
246
247arch_initcall(prcmu_init);