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 <mach/gpio.h>
33 #include <mach/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);
102 #define cbus_output(base, gpio, val) cbus_set_gpio_direction(base, gpio, 0)
106 #define cbus_output(base, gpio, val) gpio_direction_output(gpio, val)
107 #define cbus_set_gpio_dataout(base, gpio, enable) gpio_set_value(gpio, enable)
108 #define cbus_get_gpio_datain(base, int, gpio) gpio_get_value(gpio)
110 static void _cbus_send_bit(struct cbus_host *host, int bit, int set_to_input)
112 gpio_set_value(host->dat_gpio, bit ? 1 : 0);
113 gpio_set_value(host->clk_gpio, 1);
115 /* The data bit is read on the rising edge of CLK */
117 gpio_direction_input(host->dat_gpio);
119 gpio_set_value(host->clk_gpio, 0);
122 static u8 _cbus_receive_bit(struct cbus_host *host)
126 gpio_set_value(host->clk_gpio, 1);
127 ret = gpio_get_value(host->dat_gpio);
128 gpio_set_value(host->clk_gpio, 0);
133 #define cbus_send_bit(host, base, bit, set_to_input) _cbus_send_bit(host, bit, set_to_input)
134 #define cbus_receive_bit(host, base) _cbus_receive_bit(host)
138 static int cbus_transfer(struct cbus_host *host, int dev, int reg, int data)
145 #ifdef CONFIG_ARCH_OMAP1
146 base = OMAP1_IO_ADDRESS(OMAP_MPUIO_BASE);
154 /* We don't want interrupts disturbing our transfer */
155 spin_lock_irqsave(&host->lock, flags);
157 /* Reset state and start of transfer, SEL stays down during transfer */
158 cbus_set_gpio_dataout(base, host->sel_gpio, 0);
160 /* Set the DAT pin to output */
161 cbus_output(base, host->dat_gpio, 1);
163 /* Send the device address */
164 for (i = 3; i > 0; i--)
165 cbus_send_bit(host, base, dev & (1 << (i - 1)), 0);
167 /* Send the rw flag */
168 cbus_send_bit(host, base, is_read, 0);
170 /* Send the register address */
171 for (i = 5; i > 0; i--) {
172 int set_to_input = 0;
174 if (is_read && i == 1)
177 cbus_send_bit(host, base, reg & (1 << (i - 1)), set_to_input);
181 for (i = 16; i > 0; i--)
182 cbus_send_bit(host, base, data & (1 << (i - 1)), 0);
184 cbus_set_gpio_dataout(base, host->clk_gpio, 1);
187 for (i = 16; i > 0; i--) {
188 u8 bit = cbus_receive_bit(host, base);
191 data |= 1 << (i - 1);
195 /* Indicate end of transfer, SEL goes up until next transfer */
196 cbus_set_gpio_dataout(base, host->sel_gpio, 1);
197 cbus_set_gpio_dataout(base, host->clk_gpio, 1);
198 cbus_set_gpio_dataout(base, host->clk_gpio, 0);
200 spin_unlock_irqrestore(&host->lock, flags);
202 return is_read ? data : 0;
206 * Read a given register from the device
208 int cbus_read_reg(struct cbus_host *host, int dev, int reg)
210 return cbus_host ? cbus_transfer(host, dev, reg, -1) : -ENODEV;
214 * Write to a given register of the device
216 int cbus_write_reg(struct cbus_host *host, int dev, int reg, u16 val)
218 return cbus_host ? cbus_transfer(host, dev, reg, (int)val) : -ENODEV;
221 int __init cbus_bus_init(void)
223 const struct omap_cbus_config * cbus_config;
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 cbus_config = omap_get_config(OMAP_TAG_CBUS, struct omap_cbus_config);
237 if (cbus_config == NULL) {
238 printk(KERN_ERR "cbus: Unable to retrieve config data\n");
242 chost->clk_gpio = cbus_config->clk_gpio;
243 chost->dat_gpio = cbus_config->dat_gpio;
244 chost->sel_gpio = cbus_config->sel_gpio;
246 #ifdef CONFIG_ARCH_OMAP1
247 if (!OMAP_GPIO_IS_MPUIO(chost->clk_gpio) ||
248 !OMAP_GPIO_IS_MPUIO(chost->dat_gpio) ||
249 !OMAP_GPIO_IS_MPUIO(chost->sel_gpio)) {
250 printk(KERN_ERR "cbus: Only MPUIO pins supported\n");
256 if ((ret = omap_request_gpio(chost->clk_gpio)) < 0)
259 if ((ret = omap_request_gpio(chost->dat_gpio)) < 0)
262 if ((ret = omap_request_gpio(chost->sel_gpio)) < 0)
265 gpio_direction_output(chost->clk_gpio, 0);
266 gpio_direction_input(chost->dat_gpio);
267 gpio_direction_output(chost->sel_gpio, 1);
269 gpio_set_value(chost->clk_gpio, 1);
270 gpio_set_value(chost->clk_gpio, 0);
276 omap_free_gpio(chost->dat_gpio);
278 omap_free_gpio(chost->clk_gpio);
284 subsys_initcall(cbus_bus_init);
286 EXPORT_SYMBOL(cbus_host);
287 EXPORT_SYMBOL(cbus_read_reg);
288 EXPORT_SYMBOL(cbus_write_reg);
290 MODULE_DESCRIPTION("CBUS serial protocol");
291 MODULE_LICENSE("GPL");
292 MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen");