4 * Support functions for CBUS serial protocol
6 * Copyright (C) 2004, 2005 Nokia Corporation
8 * Written by Juha Yrjölä <juha.yrjola@nokia.com>,
9 * David Weinehall <david.weinehall@nokia.com>, and
10 * Mikko Ylinen <mikko.k.ylinen@nokia.com>
12 * This file is subject to the terms and conditions of the GNU General
13 * Public License. See the file "COPYING" in the main directory of this
14 * archive for more details.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <linux/device.h>
27 #include <linux/init.h>
28 #include <linux/kernel.h>
29 #include <linux/delay.h>
30 #include <linux/spinlock.h>
31 #include <linux/gpio.h>
34 #include <asm/mach-types.h>
36 #include <plat/board.h>
40 struct cbus_host
*cbus_host
= NULL
;
42 #ifdef CONFIG_ARCH_OMAP1
43 /* We use our own MPUIO functions to get closer to 1MHz bus speed */
45 static inline void cbus_set_gpio_direction(u32 base
, int mpuio
, int is_input
)
50 w
= __raw_readw(base
+ OMAP_MPUIO_IO_CNTL
);
55 __raw_writew(w
, base
+ OMAP_MPUIO_IO_CNTL
);
59 static inline void cbus_set_gpio_dataout(u32 base
, int mpuio
, int enable
)
64 w
= __raw_readw(base
+ OMAP_MPUIO_OUTPUT
);
69 __raw_writew(w
, base
+ OMAP_MPUIO_OUTPUT
);
72 static inline int cbus_get_gpio_datain(u32 base
, int mpuio
)
76 return (__raw_readw(base
+ OMAP_MPUIO_INPUT_LATCH
) & (1 << mpuio
)) != 0;
79 static void cbus_send_bit(struct cbus_host
*host
, u32 base
, int bit
,
82 cbus_set_gpio_dataout(base
, host
->dat_gpio
, bit
? 1 : 0);
83 cbus_set_gpio_dataout(base
, host
->clk_gpio
, 1);
85 /* The data bit is read on the rising edge of CLK */
87 cbus_set_gpio_direction(base
, host
->dat_gpio
, 1);
89 cbus_set_gpio_dataout(base
, host
->clk_gpio
, 0);
92 static u8
cbus_receive_bit(struct cbus_host
*host
, u32 base
)
96 cbus_set_gpio_dataout(base
, host
->clk_gpio
, 1);
97 ret
= cbus_get_gpio_datain(base
, host
->dat_gpio
);
98 cbus_set_gpio_dataout(base
, host
->clk_gpio
, 0);
103 #define cbus_output(base, gpio, val) cbus_set_gpio_direction(base, gpio, 0)
107 #define cbus_output(base, gpio, val) gpio_direction_output(gpio, val)
108 #define cbus_set_gpio_dataout(base, gpio, enable) gpio_set_value(gpio, enable)
109 #define cbus_get_gpio_datain(base, int, gpio) gpio_get_value(gpio)
111 static void _cbus_send_bit(struct cbus_host
*host
, int bit
, int set_to_input
)
113 gpio_set_value(host
->dat_gpio
, bit
? 1 : 0);
114 gpio_set_value(host
->clk_gpio
, 1);
116 /* The data bit is read on the rising edge of CLK */
118 gpio_direction_input(host
->dat_gpio
);
120 gpio_set_value(host
->clk_gpio
, 0);
123 static u8
_cbus_receive_bit(struct cbus_host
*host
)
127 gpio_set_value(host
->clk_gpio
, 1);
128 ret
= gpio_get_value(host
->dat_gpio
);
129 gpio_set_value(host
->clk_gpio
, 0);
134 #define cbus_send_bit(host, base, bit, set_to_input) _cbus_send_bit(host, bit, set_to_input)
135 #define cbus_receive_bit(host, base) _cbus_receive_bit(host)
139 static int cbus_transfer(struct cbus_host
*host
, int dev
, int reg
, int data
)
146 #ifdef CONFIG_ARCH_OMAP1
147 base
= OMAP1_IO_ADDRESS(OMAP1_MPUIO_BASE
);
155 /* We don't want interrupts disturbing our transfer */
156 spin_lock_irqsave(&host
->lock
, flags
);
158 /* Reset state and start of transfer, SEL stays down during transfer */
159 cbus_set_gpio_dataout(base
, host
->sel_gpio
, 0);
161 /* Set the DAT pin to output */
162 cbus_output(base
, host
->dat_gpio
, 1);
164 /* Send the device address */
165 for (i
= 3; i
> 0; i
--)
166 cbus_send_bit(host
, base
, dev
& (1 << (i
- 1)), 0);
168 /* Send the rw flag */
169 cbus_send_bit(host
, base
, is_read
, 0);
171 /* Send the register address */
172 for (i
= 5; i
> 0; i
--) {
173 int set_to_input
= 0;
175 if (is_read
&& i
== 1)
178 cbus_send_bit(host
, base
, reg
& (1 << (i
- 1)), set_to_input
);
182 for (i
= 16; i
> 0; i
--)
183 cbus_send_bit(host
, base
, data
& (1 << (i
- 1)), 0);
185 cbus_set_gpio_dataout(base
, host
->clk_gpio
, 1);
188 for (i
= 16; i
> 0; i
--) {
189 u8 bit
= cbus_receive_bit(host
, base
);
192 data
|= 1 << (i
- 1);
196 /* Indicate end of transfer, SEL goes up until next transfer */
197 cbus_set_gpio_dataout(base
, host
->sel_gpio
, 1);
198 cbus_set_gpio_dataout(base
, host
->clk_gpio
, 1);
199 cbus_set_gpio_dataout(base
, host
->clk_gpio
, 0);
201 spin_unlock_irqrestore(&host
->lock
, flags
);
203 return is_read
? data
: 0;
207 * Read a given register from the device
209 int cbus_read_reg(struct cbus_host
*host
, int dev
, int reg
)
211 return cbus_host
? cbus_transfer(host
, dev
, reg
, -1) : -ENODEV
;
215 * Write to a given register of the device
217 int cbus_write_reg(struct cbus_host
*host
, int dev
, int reg
, u16 val
)
219 return cbus_host
? cbus_transfer(host
, dev
, reg
, (int)val
) : -ENODEV
;
222 int __init
cbus_bus_init(void)
224 struct cbus_host
*chost
;
227 chost
= kmalloc(sizeof (*chost
), GFP_KERNEL
);
231 memset(chost
, 0, sizeof (*chost
));
233 spin_lock_init(&chost
->lock
);
235 /* REVISIT: Pass these from board-*.c files in platform_data */
236 if (machine_is_nokia770()) {
237 chost
->clk_gpio
= OMAP_MPUIO(11);
238 chost
->dat_gpio
= OMAP_MPUIO(10);
239 chost
->sel_gpio
= OMAP_MPUIO(9);
240 } else if (machine_is_nokia_n800() || machine_is_nokia_n810() ||
241 machine_is_nokia_n810_wimax()) {
242 chost
->clk_gpio
= 66;
243 chost
->dat_gpio
= 65;
244 chost
->sel_gpio
= 64;
246 printk(KERN_ERR
"cbus: Unsupported board\n");
251 #ifdef CONFIG_ARCH_OMAP1
252 if (!OMAP_GPIO_IS_MPUIO(chost
->clk_gpio
) ||
253 !OMAP_GPIO_IS_MPUIO(chost
->dat_gpio
) ||
254 !OMAP_GPIO_IS_MPUIO(chost
->sel_gpio
)) {
255 printk(KERN_ERR
"cbus: Only MPUIO pins supported\n");
261 if ((ret
= gpio_request(chost
->clk_gpio
, "CBUS clk")) < 0)
264 if ((ret
= gpio_request(chost
->dat_gpio
, "CBUS data")) < 0)
267 if ((ret
= gpio_request(chost
->sel_gpio
, "CBUS sel")) < 0)
270 gpio_direction_output(chost
->clk_gpio
, 0);
271 gpio_direction_input(chost
->dat_gpio
);
272 gpio_direction_output(chost
->sel_gpio
, 1);
274 gpio_set_value(chost
->clk_gpio
, 1);
275 gpio_set_value(chost
->clk_gpio
, 0);
281 gpio_free(chost
->dat_gpio
);
283 gpio_free(chost
->clk_gpio
);
289 subsys_initcall(cbus_bus_init
);
291 EXPORT_SYMBOL(cbus_host
);
292 EXPORT_SYMBOL(cbus_read_reg
);
293 EXPORT_SYMBOL(cbus_write_reg
);
295 MODULE_DESCRIPTION("CBUS serial protocol");
296 MODULE_LICENSE("GPL");
297 MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen");