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>
33 #include <mach/board.h>
34 #include <mach/board-nokia.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(OMAP_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 const struct omap_cbus_config * cbus_config;
225 struct cbus_host *chost;
228 chost = kmalloc(sizeof (*chost), GFP_KERNEL);
232 memset(chost, 0, sizeof (*chost));
234 spin_lock_init(&chost->lock);
236 cbus_config = omap_get_config(OMAP_TAG_CBUS, struct omap_cbus_config);
238 if (cbus_config == NULL) {
239 printk(KERN_ERR "cbus: Unable to retrieve config data\n");
243 chost->clk_gpio = cbus_config->clk_gpio;
244 chost->dat_gpio = cbus_config->dat_gpio;
245 chost->sel_gpio = cbus_config->sel_gpio;
247 #ifdef CONFIG_ARCH_OMAP1
248 if (!OMAP_GPIO_IS_MPUIO(chost->clk_gpio) ||
249 !OMAP_GPIO_IS_MPUIO(chost->dat_gpio) ||
250 !OMAP_GPIO_IS_MPUIO(chost->sel_gpio)) {
251 printk(KERN_ERR "cbus: Only MPUIO pins supported\n");
257 if ((ret = gpio_request(chost->clk_gpio, "CBUS clk")) < 0)
260 if ((ret = gpio_request(chost->dat_gpio, "CBUS data")) < 0)
263 if ((ret = gpio_request(chost->sel_gpio, "CBUS sel")) < 0)
266 gpio_direction_output(chost->clk_gpio, 0);
267 gpio_direction_input(chost->dat_gpio);
268 gpio_direction_output(chost->sel_gpio, 1);
270 gpio_set_value(chost->clk_gpio, 1);
271 gpio_set_value(chost->clk_gpio, 0);
277 gpio_free(chost->dat_gpio);
279 gpio_free(chost->clk_gpio);
285 subsys_initcall(cbus_bus_init);
287 EXPORT_SYMBOL(cbus_host);
288 EXPORT_SYMBOL(cbus_read_reg);
289 EXPORT_SYMBOL(cbus_write_reg);
291 MODULE_DESCRIPTION("CBUS serial protocol");
292 MODULE_LICENSE("GPL");
293 MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen");