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>
32 #include <asm/arch/gpio.h>
33 #include <asm/arch/board.h>
39 struct cbus_host *cbus_host = NULL;
41 #ifdef CONFIG_ARCH_OMAP1
42 /* We use our own MPUIO functions to get closer to 1MHz bus speed */
44 static inline void cbus_set_gpio_direction(u32 base, int mpuio, int is_input)
49 w = __raw_readw(base + OMAP_MPUIO_IO_CNTL);
54 __raw_writew(w, base + OMAP_MPUIO_IO_CNTL);
58 static inline void cbus_set_gpio_dataout(u32 base, int mpuio, int enable)
63 w = __raw_readw(base + OMAP_MPUIO_OUTPUT);
68 __raw_writew(w, base + OMAP_MPUIO_OUTPUT);
71 static inline int cbus_get_gpio_datain(u32 base, int mpuio)
75 return (__raw_readw(base + OMAP_MPUIO_INPUT_LATCH) & (1 << mpuio)) != 0;
78 static void cbus_send_bit(struct cbus_host *host, u32 base, int bit,
81 cbus_set_gpio_dataout(base, host->dat_gpio, bit ? 1 : 0);
82 cbus_set_gpio_dataout(base, host->clk_gpio, 1);
84 /* The data bit is read on the rising edge of CLK */
86 cbus_set_gpio_direction(base, host->dat_gpio, 1);
88 cbus_set_gpio_dataout(base, host->clk_gpio, 0);
91 static u8 cbus_receive_bit(struct cbus_host *host, u32 base)
95 cbus_set_gpio_dataout(base, host->clk_gpio, 1);
96 ret = cbus_get_gpio_datain(base, host->dat_gpio);
97 cbus_set_gpio_dataout(base, host->clk_gpio, 0);
104 #define cbus_set_gpio_direction(base, gpio, is_input) omap_set_gpio_direction(gpio, is_input)
105 #define cbus_set_gpio_dataout(base, gpio, enable) omap_set_gpio_dataout(gpio, enable)
106 #define cbus_get_gpio_datain(base, int, gpio) omap_get_gpio_datain(gpio)
108 static void _cbus_send_bit(struct cbus_host *host, int bit, int set_to_input)
110 omap_set_gpio_dataout(host->dat_gpio, bit ? 1 : 0);
111 omap_set_gpio_dataout(host->clk_gpio, 1);
113 /* The data bit is read on the rising edge of CLK */
115 omap_set_gpio_direction(host->dat_gpio, 1);
117 omap_set_gpio_dataout(host->clk_gpio, 0);
120 static u8 _cbus_receive_bit(struct cbus_host *host)
124 omap_set_gpio_dataout(host->clk_gpio, 1);
125 ret = omap_get_gpio_datain(host->dat_gpio);
126 omap_set_gpio_dataout(host->clk_gpio, 0);
131 #define cbus_send_bit(host, base, bit, set_to_input) _cbus_send_bit(host, bit, set_to_input)
132 #define cbus_receive_bit(host, base) _cbus_receive_bit(host)
136 static int cbus_transfer(struct cbus_host *host, int dev, int reg, int data)
143 #ifdef CONFIG_ARCH_OMAP1
144 base = (u32) io_p2v(OMAP_MPUIO_BASE);
152 /* We don't want interrupts disturbing our transfer */
153 spin_lock_irqsave(&host->lock, flags);
155 /* Reset state and start of transfer, SEL stays down during transfer */
156 cbus_set_gpio_dataout(base, host->sel_gpio, 0);
158 /* Set the DAT pin to output */
159 cbus_set_gpio_direction(base, host->dat_gpio, 0);
161 /* Send the device address */
162 for (i = 3; i > 0; i--)
163 cbus_send_bit(host, base, dev & (1 << (i - 1)), 0);
165 /* Send the rw flag */
166 cbus_send_bit(host, base, is_read, 0);
168 /* Send the register address */
169 for (i = 5; i > 0; i--) {
170 int set_to_input = 0;
172 if (is_read && i == 1)
175 cbus_send_bit(host, base, reg & (1 << (i - 1)), set_to_input);
179 for (i = 16; i > 0; i--)
180 cbus_send_bit(host, base, data & (1 << (i - 1)), 0);
182 cbus_set_gpio_dataout(base, host->clk_gpio, 1);
185 for (i = 16; i > 0; i--) {
186 u8 bit = cbus_receive_bit(host, base);
189 data |= 1 << (i - 1);
193 /* Indicate end of transfer, SEL goes up until next transfer */
194 cbus_set_gpio_dataout(base, host->sel_gpio, 1);
195 cbus_set_gpio_dataout(base, host->clk_gpio, 1);
196 cbus_set_gpio_dataout(base, host->clk_gpio, 0);
198 spin_unlock_irqrestore(&host->lock, flags);
200 return is_read ? data : 0;
204 * Read a given register from the device
206 int cbus_read_reg(struct cbus_host *host, int dev, int reg)
208 return cbus_host ? cbus_transfer(host, dev, reg, -1) : -ENODEV;
212 * Write to a given register of the device
214 int cbus_write_reg(struct cbus_host *host, int dev, int reg, u16 val)
216 return cbus_host ? cbus_transfer(host, dev, reg, (int)val) : -ENODEV;
219 int __init cbus_bus_init(void)
221 const struct omap_cbus_config * cbus_config;
222 struct cbus_host *chost;
225 chost = kmalloc(sizeof (*chost), GFP_KERNEL);
229 memset(chost, 0, sizeof (*chost));
231 spin_lock_init(&chost->lock);
233 cbus_config = omap_get_config(OMAP_TAG_CBUS, struct omap_cbus_config);
235 if (cbus_config == NULL) {
236 printk(KERN_ERR "cbus: Unable to retrieve config data\n");
240 chost->clk_gpio = cbus_config->clk_gpio;
241 chost->dat_gpio = cbus_config->dat_gpio;
242 chost->sel_gpio = cbus_config->sel_gpio;
244 if (!OMAP_GPIO_IS_MPUIO(chost->clk_gpio) ||
245 !OMAP_GPIO_IS_MPUIO(chost->dat_gpio) ||
246 !OMAP_GPIO_IS_MPUIO(chost->sel_gpio)) {
247 printk(KERN_ERR "cbus: Only MPUIO pins supported\n");
252 if ((ret = omap_request_gpio(chost->clk_gpio)) < 0)
255 if ((ret = omap_request_gpio(chost->dat_gpio)) < 0)
258 if ((ret = omap_request_gpio(chost->sel_gpio)) < 0)
261 omap_set_gpio_dataout(chost->clk_gpio, 0);
262 omap_set_gpio_dataout(chost->sel_gpio, 1);
264 omap_set_gpio_direction(chost->clk_gpio, 0);
265 omap_set_gpio_direction(chost->dat_gpio, 1);
266 omap_set_gpio_direction(chost->sel_gpio, 0);
268 omap_set_gpio_dataout(chost->clk_gpio, 1);
269 omap_set_gpio_dataout(chost->clk_gpio, 0);
275 omap_free_gpio(chost->dat_gpio);
277 omap_free_gpio(chost->clk_gpio);
283 subsys_initcall(cbus_bus_init);
285 EXPORT_SYMBOL(cbus_host);
286 EXPORT_SYMBOL(cbus_read_reg);
287 EXPORT_SYMBOL(cbus_write_reg);
289 MODULE_DESCRIPTION("CBUS serial protocol");
290 MODULE_LICENSE("GPL");
291 MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen");