1/* 2 * Mailbox reservation modules for DSP 3 * 4 * Copyright (C) 2006 Nokia Corporation 5 * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> 6 * 7 * This file is subject to the terms and conditions of the GNU General Public 8 * License. See the file "COPYING" in the main directory of this archive 9 * for more details. 10 */ 11 12#include <linux/kernel.h> 13#include <linux/resource.h> 14#include <linux/interrupt.h> 15#include <linux/platform_device.h> 16#include <asm/arch/mailbox.h> 17#include <asm/arch/irqs.h> 18#include <asm/io.h> 19 20#define MAILBOX_ARM2DSP1 0x00 21#define MAILBOX_ARM2DSP1b 0x04 22#define MAILBOX_DSP2ARM1 0x08 23#define MAILBOX_DSP2ARM1b 0x0c 24#define MAILBOX_DSP2ARM2 0x10 25#define MAILBOX_DSP2ARM2b 0x14 26#define MAILBOX_ARM2DSP1_Flag 0x18 27#define MAILBOX_DSP2ARM1_Flag 0x1c 28#define MAILBOX_DSP2ARM2_Flag 0x20 29 30unsigned long mbox_base; 31 32struct omap_mbox1_fifo { 33 unsigned long cmd; 34 unsigned long data; 35 unsigned long flag; 36}; 37 38struct omap_mbox1_priv { 39 struct omap_mbox1_fifo tx_fifo; 40 struct omap_mbox1_fifo rx_fifo; 41}; 42 43static inline int mbox_read_reg(unsigned int reg) 44{ 45 return __raw_readw(mbox_base + reg); 46} 47 48static inline void mbox_write_reg(unsigned int val, unsigned int reg) 49{ 50 __raw_writew(val, mbox_base + reg); 51} 52 53/* msg */ 54static inline mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox) 55{ 56 struct omap_mbox1_fifo *fifo = 57 &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; 58 mbox_msg_t msg; 59 60 msg = mbox_read_reg(fifo->data); 61 msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16; 62 63 return msg; 64} 65 66static inline void 67omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) 68{ 69 struct omap_mbox1_fifo *fifo = 70 &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo; 71 72 mbox_write_reg(msg & 0xffff, fifo->data); 73 mbox_write_reg(msg >> 16, fifo->cmd); 74} 75 76static inline int omap1_mbox_fifo_empty(struct omap_mbox *mbox) 77{ 78 return 0; 79} 80 81static inline int omap1_mbox_fifo_full(struct omap_mbox *mbox) 82{ 83 struct omap_mbox1_fifo *fifo = 84 &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; 85 86 return (mbox_read_reg(fifo->flag)); 87} 88 89/* irq */ 90static inline void 91omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) 92{ 93 if (irq == IRQ_RX) 94 enable_irq(mbox->irq); 95} 96 97static inline void 98omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) 99{ 100 if (irq == IRQ_RX) 101 disable_irq(mbox->irq); 102} 103 104static inline int 105omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) 106{ 107 if (irq == IRQ_TX) 108 return 0; 109 return 1; 110} 111 112static struct omap_mbox_ops omap1_mbox_ops = { 113 .type = OMAP_MBOX_TYPE1, 114 .fifo_read = omap1_mbox_fifo_read, 115 .fifo_write = omap1_mbox_fifo_write, 116 .fifo_empty = omap1_mbox_fifo_empty, 117 .fifo_full = omap1_mbox_fifo_full, 118 .enable_irq = omap1_mbox_enable_irq, 119 .disable_irq = omap1_mbox_disable_irq, 120 .is_irq = omap1_mbox_is_irq, 121}; 122 123 124/* DSP */ 125static struct omap_mbox1_priv omap1_mbox_dsp_priv = { 126 .tx_fifo = { 127 .cmd = MAILBOX_ARM2DSP1b, 128 .data = MAILBOX_ARM2DSP1, 129 .flag = MAILBOX_ARM2DSP1_Flag, 130 }, 131 .rx_fifo = { 132 .cmd = MAILBOX_DSP2ARM1b, 133 .data = MAILBOX_DSP2ARM1, 134 .flag = MAILBOX_DSP2ARM1_Flag, 135 }, 136}; 137 138struct omap_mbox mbox_dsp_info = { 139 .name = "dsp", 140 .ops = &omap1_mbox_ops, 141 .priv = &omap1_mbox_dsp_priv, 142}; 143EXPORT_SYMBOL(mbox_dsp_info); 144 145static int __init omap1_mbox_probe(struct platform_device *pdev) 146{ 147 struct resource *res; 148 int ret = 0; 149 150 if (pdev->num_resources != 2) { 151 dev_err(&pdev->dev, "invalid number of resources: %d\n", 152 pdev->num_resources); 153 return -ENODEV; 154 } 155 156 /* MBOX base */ 157 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 158 if (unlikely(!res)) { 159 dev_err(&pdev->dev, "invalid mem resource\n"); 160 return -ENODEV; 161 } 162 mbox_base = res->start; 163 164 /* DSP IRQ */ 165 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 166 if (unlikely(!res)) { 167 dev_err(&pdev->dev, "invalid irq resource\n"); 168 return -ENODEV; 169 } 170 mbox_dsp_info.irq = res->start; 171 172 ret = omap_mbox_register(&mbox_dsp_info); 173 174 return ret; 175} 176 177static int omap1_mbox_remove(struct platform_device *pdev) 178{ 179 omap_mbox_unregister(&mbox_dsp_info); 180 181 return 0; 182} 183 184static struct platform_driver omap1_mbox_driver = { 185 .probe = omap1_mbox_probe, 186 .remove = omap1_mbox_remove, 187 .driver = { 188 .name = "mailbox", 189 }, 190}; 191 192static int __init omap1_mbox_init(void) 193{ 194 return platform_driver_register(&omap1_mbox_driver); 195} 196 197static void __exit omap1_mbox_exit(void) 198{ 199 platform_driver_unregister(&omap1_mbox_driver); 200} 201 202module_init(omap1_mbox_init); 203module_exit(omap1_mbox_exit); 204 205MODULE_LICENSE("GPL"); 206