Merge HEAD from master.kernel.org:/home/rmk/linux-2.6-ucb.git

+692 -1
+2
arch/arm/Kconfig
··· 752 752 753 753 source "drivers/misc/Kconfig" 754 754 755 + source "drivers/mfd/Kconfig" 756 + 755 757 source "drivers/media/Kconfig" 756 758 757 759 source "drivers/video/Kconfig"
+7
arch/arm/mach-sa1100/assabet.c
··· 35 35 #include <asm/mach/map.h> 36 36 #include <asm/mach/serial_sa1100.h> 37 37 #include <asm/arch/assabet.h> 38 + #include <asm/arch/mcp.h> 38 39 39 40 #include "generic.h" 40 41 ··· 199 198 .set_speed = assabet_irda_set_speed, 200 199 }; 201 200 201 + static struct mcp_plat_data assabet_mcp_data = { 202 + .mccr0 = MCCR0_ADM, 203 + .sclk_rate = 11981000, 204 + }; 205 + 202 206 static void __init assabet_init(void) 203 207 { 204 208 /* ··· 252 246 sa11x0_set_flash_data(&assabet_flash_data, assabet_flash_resources, 253 247 ARRAY_SIZE(assabet_flash_resources)); 254 248 sa11x0_set_irda_data(&assabet_irda_data); 249 + sa11x0_set_mcp_data(&assabet_mcp_data); 255 250 } 256 251 257 252 /*
+7
arch/arm/mach-sa1100/cerf.c
··· 29 29 #include <asm/mach/serial_sa1100.h> 30 30 31 31 #include <asm/arch/cerf.h> 32 + #include <asm/arch/mcp.h> 32 33 #include "generic.h" 33 34 34 35 static struct resource cerfuart2_resources[] = { ··· 117 116 GPDR |= CERF_GPIO_CF_RESET; 118 117 } 119 118 119 + static struct mcp_plat_data cerf_mcp_data = { 120 + .mccr0 = MCCR0_ADM, 121 + .sclk_rate = 11981000, 122 + }; 123 + 120 124 static void __init cerf_init(void) 121 125 { 122 126 platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices)); 123 127 sa11x0_set_flash_data(&cerf_flash_data, &cerf_flash_resource, 1); 128 + sa11x0_set_mcp_data(&cerf_mcp_data); 124 129 } 125 130 126 131 MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
+5
arch/arm/mach-sa1100/generic.c
··· 221 221 .resource = sa11x0mcp_resources, 222 222 }; 223 223 224 + void sa11x0_set_mcp_data(struct mcp_plat_data *data) 225 + { 226 + sa11x0mcp_device.dev.platform_data = data; 227 + } 228 + 224 229 static struct resource sa11x0ssp_resources[] = { 225 230 [0] = { 226 231 .start = 0x80070000,
+3
arch/arm/mach-sa1100/generic.h
··· 34 34 extern void sa11x0_set_flash_data(struct flash_platform_data *flash, 35 35 struct resource *res, int nr); 36 36 37 + struct sa11x0_ssp_plat_ops; 38 + extern void sa11x0_set_ssp_data(struct sa11x0_ssp_plat_ops *ops); 39 + 37 40 struct irda_platform_data; 38 41 void sa11x0_set_irda_data(struct irda_platform_data *irda);
+12
arch/arm/mach-sa1100/lart.c
··· 13 13 #include <asm/mach/arch.h> 14 14 #include <asm/mach/map.h> 15 15 #include <asm/mach/serial_sa1100.h> 16 + #include <asm/arch/mcp.h> 16 17 17 18 #include "generic.h" 18 19 19 20 20 21 #warning "include/asm/arch-sa1100/ide.h needs fixing for lart" 22 + 23 + static struct mcp_plat_data lart_mcp_data = { 24 + .mccr0 = MCCR0_ADM, 25 + .sclk_rate = 11981000, 26 + }; 27 + 28 + static void __init lart_init(void) 29 + { 30 + sa11x0_set_mcp_data(&lart_mcp_data); 31 + } 21 32 22 33 static struct map_desc lart_io_desc[] __initdata = { 23 34 /* virtual physical length type */ ··· 58 47 .boot_params = 0xc0000100, 59 48 .map_io = lart_map_io, 60 49 .init_irq = sa1100_init_irq, 50 + .init_machine = lart_init, 61 51 .timer = &sa1100_timer, 62 52 MACHINE_END
+7
arch/arm/mach-sa1100/shannon.c
··· 18 18 #include <asm/mach/flash.h> 19 19 #include <asm/mach/map.h> 20 20 #include <asm/mach/serial_sa1100.h> 21 + #include <asm/arch/mcp.h> 21 22 #include <asm/arch/shannon.h> 22 23 23 24 #include "generic.h" ··· 53 52 .flags = IORESOURCE_MEM, 54 53 }; 55 54 55 + static struct mcp_plat_data shannon_mcp_data = { 56 + .mccr0 = MCCR0_ADM, 57 + .sclk_rate = 11981000, 58 + }; 59 + 56 60 static void __init shannon_init(void) 57 61 { 58 62 sa11x0_set_flash_data(&shannon_flash_data, &shannon_flash_resource, 1); 63 + sa11x0_set_mcp_data(&shannon_mcp_data); 59 64 } 60 65 61 66 static void __init shannon_map_io(void)
+7
arch/arm/mach-sa1100/simpad.c
··· 23 23 #include <asm/mach/flash.h> 24 24 #include <asm/mach/map.h> 25 25 #include <asm/mach/serial_sa1100.h> 26 + #include <asm/arch/mcp.h> 26 27 #include <asm/arch/simpad.h> 27 28 28 29 #include <linux/serial_core.h> ··· 124 123 } 125 124 }; 126 125 126 + static struct mcp_plat_data simpad_mcp_data = { 127 + .mccr0 = MCCR0_ADM, 128 + .sclk_rate = 11981000, 129 + }; 130 + 127 131 128 132 129 133 static void __init simpad_map_io(void) ··· 163 157 164 158 sa11x0_set_flash_data(&simpad_flash_data, simpad_flash_resources, 165 159 ARRAY_SIZE(simpad_flash_resources)); 160 + sa11x0_set_mcp_data(&simpad_mcp_data); 166 161 } 167 162 168 163 static void simpad_power_off(void)
+2
drivers/Kconfig
··· 48 48 49 49 source "drivers/misc/Kconfig" 50 50 51 + source "drivers/mfd/Kconfig" 52 + 51 53 source "drivers/media/Kconfig" 52 54 53 55 source "drivers/video/Kconfig"
+1 -1
drivers/Makefile
··· 26 26 obj-$(CONFIG_SERIO) += input/serio/ 27 27 obj-y += serial/ 28 28 obj-$(CONFIG_PARPORT) += parport/ 29 - obj-y += base/ block/ misc/ net/ media/ 29 + obj-y += base/ block/ misc/ mfd/ net/ media/ 30 30 obj-$(CONFIG_NUBUS) += nubus/ 31 31 obj-$(CONFIG_ATM) += atm/ 32 32 obj-$(CONFIG_PPC_PMAC) += macintosh/
+16
drivers/mfd/Kconfig
··· 1 + # 2 + # Multifunction miscellaneous devices 3 + # 4 + 5 + menu "Multimedia Capabilities Port drivers" 6 + 7 + config MCP 8 + tristate 9 + 10 + # Interface drivers 11 + config MCP_SA11X0 12 + tristate "Support SA11x0 MCP interface" 13 + depends on ARCH_SA1100 14 + select MCP 15 + 16 + endmenu
+6
drivers/mfd/Makefile
··· 1 + # 2 + # Makefile for multifunction miscellaneous devices 3 + # 4 + 5 + obj-$(CONFIG_MCP) += mcp-core.o 6 + obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
+255
drivers/mfd/mcp-core.c
··· 1 + /* 2 + * linux/drivers/mfd/mcp-core.c 3 + * 4 + * Copyright (C) 2001 Russell King 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License. 9 + * 10 + * Generic MCP (Multimedia Communications Port) layer. All MCP locking 11 + * is solely held within this file. 12 + */ 13 + #include <linux/module.h> 14 + #include <linux/init.h> 15 + #include <linux/errno.h> 16 + #include <linux/smp.h> 17 + #include <linux/device.h> 18 + 19 + #include <asm/dma.h> 20 + #include <asm/system.h> 21 + 22 + #include "mcp.h" 23 + 24 + #define to_mcp(d) container_of(d, struct mcp, attached_device) 25 + #define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) 26 + 27 + static int mcp_bus_match(struct device *dev, struct device_driver *drv) 28 + { 29 + return 1; 30 + } 31 + 32 + static int mcp_bus_probe(struct device *dev) 33 + { 34 + struct mcp *mcp = to_mcp(dev); 35 + struct mcp_driver *drv = to_mcp_driver(dev->driver); 36 + 37 + return drv->probe(mcp); 38 + } 39 + 40 + static int mcp_bus_remove(struct device *dev) 41 + { 42 + struct mcp *mcp = to_mcp(dev); 43 + struct mcp_driver *drv = to_mcp_driver(dev->driver); 44 + 45 + drv->remove(mcp); 46 + return 0; 47 + } 48 + 49 + static int mcp_bus_suspend(struct device *dev, pm_message_t state) 50 + { 51 + struct mcp *mcp = to_mcp(dev); 52 + int ret = 0; 53 + 54 + if (dev->driver) { 55 + struct mcp_driver *drv = to_mcp_driver(dev->driver); 56 + 57 + ret = drv->suspend(mcp, state); 58 + } 59 + return ret; 60 + } 61 + 62 + static int mcp_bus_resume(struct device *dev) 63 + { 64 + struct mcp *mcp = to_mcp(dev); 65 + int ret = 0; 66 + 67 + if (dev->driver) { 68 + struct mcp_driver *drv = to_mcp_driver(dev->driver); 69 + 70 + ret = drv->resume(mcp); 71 + } 72 + return ret; 73 + } 74 + 75 + static struct bus_type mcp_bus_type = { 76 + .name = "mcp", 77 + .match = mcp_bus_match, 78 + .suspend = mcp_bus_suspend, 79 + .resume = mcp_bus_resume, 80 + }; 81 + 82 + /** 83 + * mcp_set_telecom_divisor - set the telecom divisor 84 + * @mcp: MCP interface structure 85 + * @div: SIB clock divisor 86 + * 87 + * Set the telecom divisor on the MCP interface. The resulting 88 + * sample rate is SIBCLOCK/div. 89 + */ 90 + void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div) 91 + { 92 + spin_lock_irq(&mcp->lock); 93 + mcp->ops->set_telecom_divisor(mcp, div); 94 + spin_unlock_irq(&mcp->lock); 95 + } 96 + EXPORT_SYMBOL(mcp_set_telecom_divisor); 97 + 98 + /** 99 + * mcp_set_audio_divisor - set the audio divisor 100 + * @mcp: MCP interface structure 101 + * @div: SIB clock divisor 102 + * 103 + * Set the audio divisor on the MCP interface. 104 + */ 105 + void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div) 106 + { 107 + spin_lock_irq(&mcp->lock); 108 + mcp->ops->set_audio_divisor(mcp, div); 109 + spin_unlock_irq(&mcp->lock); 110 + } 111 + EXPORT_SYMBOL(mcp_set_audio_divisor); 112 + 113 + /** 114 + * mcp_reg_write - write a device register 115 + * @mcp: MCP interface structure 116 + * @reg: 4-bit register index 117 + * @val: 16-bit data value 118 + * 119 + * Write a device register. The MCP interface must be enabled 120 + * to prevent this function hanging. 121 + */ 122 + void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val) 123 + { 124 + unsigned long flags; 125 + 126 + spin_lock_irqsave(&mcp->lock, flags); 127 + mcp->ops->reg_write(mcp, reg, val); 128 + spin_unlock_irqrestore(&mcp->lock, flags); 129 + } 130 + EXPORT_SYMBOL(mcp_reg_write); 131 + 132 + /** 133 + * mcp_reg_read - read a device register 134 + * @mcp: MCP interface structure 135 + * @reg: 4-bit register index 136 + * 137 + * Read a device register and return its value. The MCP interface 138 + * must be enabled to prevent this function hanging. 139 + */ 140 + unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg) 141 + { 142 + unsigned long flags; 143 + unsigned int val; 144 + 145 + spin_lock_irqsave(&mcp->lock, flags); 146 + val = mcp->ops->reg_read(mcp, reg); 147 + spin_unlock_irqrestore(&mcp->lock, flags); 148 + 149 + return val; 150 + } 151 + EXPORT_SYMBOL(mcp_reg_read); 152 + 153 + /** 154 + * mcp_enable - enable the MCP interface 155 + * @mcp: MCP interface to enable 156 + * 157 + * Enable the MCP interface. Each call to mcp_enable will need 158 + * a corresponding call to mcp_disable to disable the interface. 159 + */ 160 + void mcp_enable(struct mcp *mcp) 161 + { 162 + spin_lock_irq(&mcp->lock); 163 + if (mcp->use_count++ == 0) 164 + mcp->ops->enable(mcp); 165 + spin_unlock_irq(&mcp->lock); 166 + } 167 + EXPORT_SYMBOL(mcp_enable); 168 + 169 + /** 170 + * mcp_disable - disable the MCP interface 171 + * @mcp: MCP interface to disable 172 + * 173 + * Disable the MCP interface. The MCP interface will only be 174 + * disabled once the number of calls to mcp_enable matches the 175 + * number of calls to mcp_disable. 176 + */ 177 + void mcp_disable(struct mcp *mcp) 178 + { 179 + unsigned long flags; 180 + 181 + spin_lock_irqsave(&mcp->lock, flags); 182 + if (--mcp->use_count == 0) 183 + mcp->ops->disable(mcp); 184 + spin_unlock_irqrestore(&mcp->lock, flags); 185 + } 186 + EXPORT_SYMBOL(mcp_disable); 187 + 188 + static void mcp_release(struct device *dev) 189 + { 190 + struct mcp *mcp = container_of(dev, struct mcp, attached_device); 191 + 192 + kfree(mcp); 193 + } 194 + 195 + struct mcp *mcp_host_alloc(struct device *parent, size_t size) 196 + { 197 + struct mcp *mcp; 198 + 199 + mcp = kmalloc(sizeof(struct mcp) + size, GFP_KERNEL); 200 + if (mcp) { 201 + memset(mcp, 0, sizeof(struct mcp) + size); 202 + spin_lock_init(&mcp->lock); 203 + mcp->attached_device.parent = parent; 204 + mcp->attached_device.bus = &mcp_bus_type; 205 + mcp->attached_device.dma_mask = parent->dma_mask; 206 + mcp->attached_device.release = mcp_release; 207 + } 208 + return mcp; 209 + } 210 + EXPORT_SYMBOL(mcp_host_alloc); 211 + 212 + int mcp_host_register(struct mcp *mcp) 213 + { 214 + strcpy(mcp->attached_device.bus_id, "mcp0"); 215 + return device_register(&mcp->attached_device); 216 + } 217 + EXPORT_SYMBOL(mcp_host_register); 218 + 219 + void mcp_host_unregister(struct mcp *mcp) 220 + { 221 + device_unregister(&mcp->attached_device); 222 + } 223 + EXPORT_SYMBOL(mcp_host_unregister); 224 + 225 + int mcp_driver_register(struct mcp_driver *mcpdrv) 226 + { 227 + mcpdrv->drv.bus = &mcp_bus_type; 228 + mcpdrv->drv.probe = mcp_bus_probe; 229 + mcpdrv->drv.remove = mcp_bus_remove; 230 + return driver_register(&mcpdrv->drv); 231 + } 232 + EXPORT_SYMBOL(mcp_driver_register); 233 + 234 + void mcp_driver_unregister(struct mcp_driver *mcpdrv) 235 + { 236 + driver_unregister(&mcpdrv->drv); 237 + } 238 + EXPORT_SYMBOL(mcp_driver_unregister); 239 + 240 + static int __init mcp_init(void) 241 + { 242 + return bus_register(&mcp_bus_type); 243 + } 244 + 245 + static void __exit mcp_exit(void) 246 + { 247 + bus_unregister(&mcp_bus_type); 248 + } 249 + 250 + module_init(mcp_init); 251 + module_exit(mcp_exit); 252 + 253 + MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); 254 + MODULE_DESCRIPTION("Core multimedia communications port driver"); 255 + MODULE_LICENSE("GPL");
+275
drivers/mfd/mcp-sa11x0.c
··· 1 + /* 2 + * linux/drivers/mfd/mcp-sa11x0.c 3 + * 4 + * Copyright (C) 2001-2005 Russell King 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License. 9 + * 10 + * SA11x0 MCP (Multimedia Communications Port) driver. 11 + * 12 + * MCP read/write timeouts from Jordi Colomer, rehacked by rmk. 13 + */ 14 + #include <linux/module.h> 15 + #include <linux/init.h> 16 + #include <linux/errno.h> 17 + #include <linux/kernel.h> 18 + #include <linux/delay.h> 19 + #include <linux/spinlock.h> 20 + #include <linux/slab.h> 21 + #include <linux/device.h> 22 + 23 + #include <asm/dma.h> 24 + #include <asm/hardware.h> 25 + #include <asm/mach-types.h> 26 + #include <asm/system.h> 27 + #include <asm/arch/mcp.h> 28 + 29 + #include <asm/arch/assabet.h> 30 + 31 + #include "mcp.h" 32 + 33 + struct mcp_sa11x0 { 34 + u32 mccr0; 35 + u32 mccr1; 36 + }; 37 + 38 + #define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp)) 39 + 40 + static void 41 + mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) 42 + { 43 + unsigned int mccr0; 44 + 45 + divisor /= 32; 46 + 47 + mccr0 = Ser4MCCR0 & ~0x00007f00; 48 + mccr0 |= divisor << 8; 49 + Ser4MCCR0 = mccr0; 50 + } 51 + 52 + static void 53 + mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) 54 + { 55 + unsigned int mccr0; 56 + 57 + divisor /= 32; 58 + 59 + mccr0 = Ser4MCCR0 & ~0x0000007f; 60 + mccr0 |= divisor; 61 + Ser4MCCR0 = mccr0; 62 + } 63 + 64 + /* 65 + * Write data to the device. The bit should be set after 3 subframe 66 + * times (each frame is 64 clocks). We wait a maximum of 6 subframes. 67 + * We really should try doing something more productive while we 68 + * wait. 69 + */ 70 + static void 71 + mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) 72 + { 73 + int ret = -ETIME; 74 + int i; 75 + 76 + Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff); 77 + 78 + for (i = 0; i < 2; i++) { 79 + udelay(mcp->rw_timeout); 80 + if (Ser4MCSR & MCSR_CWC) { 81 + ret = 0; 82 + break; 83 + } 84 + } 85 + 86 + if (ret < 0) 87 + printk(KERN_WARNING "mcp: write timed out\n"); 88 + } 89 + 90 + /* 91 + * Read data from the device. The bit should be set after 3 subframe 92 + * times (each frame is 64 clocks). We wait a maximum of 6 subframes. 93 + * We really should try doing something more productive while we 94 + * wait. 95 + */ 96 + static unsigned int 97 + mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) 98 + { 99 + int ret = -ETIME; 100 + int i; 101 + 102 + Ser4MCDR2 = reg << 17 | MCDR2_Rd; 103 + 104 + for (i = 0; i < 2; i++) { 105 + udelay(mcp->rw_timeout); 106 + if (Ser4MCSR & MCSR_CRC) { 107 + ret = Ser4MCDR2 & 0xffff; 108 + break; 109 + } 110 + } 111 + 112 + if (ret < 0) 113 + printk(KERN_WARNING "mcp: read timed out\n"); 114 + 115 + return ret; 116 + } 117 + 118 + static void mcp_sa11x0_enable(struct mcp *mcp) 119 + { 120 + Ser4MCSR = -1; 121 + Ser4MCCR0 |= MCCR0_MCE; 122 + } 123 + 124 + static void mcp_sa11x0_disable(struct mcp *mcp) 125 + { 126 + Ser4MCCR0 &= ~MCCR0_MCE; 127 + } 128 + 129 + /* 130 + * Our methods. 131 + */ 132 + static struct mcp_ops mcp_sa11x0 = { 133 + .set_telecom_divisor = mcp_sa11x0_set_telecom_divisor, 134 + .set_audio_divisor = mcp_sa11x0_set_audio_divisor, 135 + .reg_write = mcp_sa11x0_write, 136 + .reg_read = mcp_sa11x0_read, 137 + .enable = mcp_sa11x0_enable, 138 + .disable = mcp_sa11x0_disable, 139 + }; 140 + 141 + static int mcp_sa11x0_probe(struct device *dev) 142 + { 143 + struct platform_device *pdev = to_platform_device(dev); 144 + struct mcp_plat_data *data = pdev->dev.platform_data; 145 + struct mcp *mcp; 146 + int ret; 147 + 148 + if (!data) 149 + return -ENODEV; 150 + 151 + if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp")) 152 + return -EBUSY; 153 + 154 + mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0)); 155 + if (!mcp) { 156 + ret = -ENOMEM; 157 + goto release; 158 + } 159 + 160 + mcp->owner = THIS_MODULE; 161 + mcp->ops = &mcp_sa11x0; 162 + mcp->sclk_rate = data->sclk_rate; 163 + mcp->dma_audio_rd = DMA_Ser4MCP0Rd; 164 + mcp->dma_audio_wr = DMA_Ser4MCP0Wr; 165 + mcp->dma_telco_rd = DMA_Ser4MCP1Rd; 166 + mcp->dma_telco_wr = DMA_Ser4MCP1Wr; 167 + 168 + dev_set_drvdata(dev, mcp); 169 + 170 + if (machine_is_assabet()) { 171 + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); 172 + } 173 + 174 + /* 175 + * Setup the PPC unit correctly. 176 + */ 177 + PPDR &= ~PPC_RXD4; 178 + PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; 179 + PSDR |= PPC_RXD4; 180 + PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); 181 + PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); 182 + 183 + /* 184 + * Initialise device. Note that we initially 185 + * set the sampling rate to minimum. 186 + */ 187 + Ser4MCSR = -1; 188 + Ser4MCCR1 = data->mccr1; 189 + Ser4MCCR0 = data->mccr0 | 0x7f7f; 190 + 191 + /* 192 + * Calculate the read/write timeout (us) from the bit clock 193 + * rate. This is the period for 3 64-bit frames. Always 194 + * round this time up. 195 + */ 196 + mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / 197 + mcp->sclk_rate; 198 + 199 + ret = mcp_host_register(mcp); 200 + if (ret == 0) 201 + goto out; 202 + 203 + release: 204 + release_mem_region(0x80060000, 0x60); 205 + dev_set_drvdata(dev, NULL); 206 + 207 + out: 208 + return ret; 209 + } 210 + 211 + static int mcp_sa11x0_remove(struct device *dev) 212 + { 213 + struct mcp *mcp = dev_get_drvdata(dev); 214 + 215 + dev_set_drvdata(dev, NULL); 216 + mcp_host_unregister(mcp); 217 + release_mem_region(0x80060000, 0x60); 218 + 219 + return 0; 220 + } 221 + 222 + static int mcp_sa11x0_suspend(struct device *dev, pm_message_t state, u32 level) 223 + { 224 + struct mcp *mcp = dev_get_drvdata(dev); 225 + 226 + if (level == SUSPEND_DISABLE) { 227 + priv(mcp)->mccr0 = Ser4MCCR0; 228 + priv(mcp)->mccr1 = Ser4MCCR1; 229 + Ser4MCCR0 &= ~MCCR0_MCE; 230 + } 231 + return 0; 232 + } 233 + 234 + static int mcp_sa11x0_resume(struct device *dev, u32 level) 235 + { 236 + struct mcp *mcp = dev_get_drvdata(dev); 237 + 238 + if (level == RESUME_RESTORE_STATE) { 239 + Ser4MCCR1 = priv(mcp)->mccr1; 240 + Ser4MCCR0 = priv(mcp)->mccr0; 241 + } 242 + return 0; 243 + } 244 + 245 + /* 246 + * The driver for the SA11x0 MCP port. 247 + */ 248 + static struct device_driver mcp_sa11x0_driver = { 249 + .name = "sa11x0-mcp", 250 + .bus = &platform_bus_type, 251 + .probe = mcp_sa11x0_probe, 252 + .remove = mcp_sa11x0_remove, 253 + .suspend = mcp_sa11x0_suspend, 254 + .resume = mcp_sa11x0_resume, 255 + }; 256 + 257 + /* 258 + * This needs re-working 259 + */ 260 + static int __init mcp_sa11x0_init(void) 261 + { 262 + return driver_register(&mcp_sa11x0_driver); 263 + } 264 + 265 + static void __exit mcp_sa11x0_exit(void) 266 + { 267 + driver_unregister(&mcp_sa11x0_driver); 268 + } 269 + 270 + module_init(mcp_sa11x0_init); 271 + module_exit(mcp_sa11x0_exit); 272 + 273 + MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); 274 + MODULE_DESCRIPTION("SA11x0 multimedia communications port driver"); 275 + MODULE_LICENSE("GPL");
+66
drivers/mfd/mcp.h
··· 1 + /* 2 + * linux/drivers/mfd/mcp.h 3 + * 4 + * Copyright (C) 2001 Russell King, All Rights Reserved. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License. 9 + */ 10 + #ifndef MCP_H 11 + #define MCP_H 12 + 13 + struct mcp_ops; 14 + 15 + struct mcp { 16 + struct module *owner; 17 + struct mcp_ops *ops; 18 + spinlock_t lock; 19 + int use_count; 20 + unsigned int sclk_rate; 21 + unsigned int rw_timeout; 22 + dma_device_t dma_audio_rd; 23 + dma_device_t dma_audio_wr; 24 + dma_device_t dma_telco_rd; 25 + dma_device_t dma_telco_wr; 26 + struct device attached_device; 27 + }; 28 + 29 + struct mcp_ops { 30 + void (*set_telecom_divisor)(struct mcp *, unsigned int); 31 + void (*set_audio_divisor)(struct mcp *, unsigned int); 32 + void (*reg_write)(struct mcp *, unsigned int, unsigned int); 33 + unsigned int (*reg_read)(struct mcp *, unsigned int); 34 + void (*enable)(struct mcp *); 35 + void (*disable)(struct mcp *); 36 + }; 37 + 38 + void mcp_set_telecom_divisor(struct mcp *, unsigned int); 39 + void mcp_set_audio_divisor(struct mcp *, unsigned int); 40 + void mcp_reg_write(struct mcp *, unsigned int, unsigned int); 41 + unsigned int mcp_reg_read(struct mcp *, unsigned int); 42 + void mcp_enable(struct mcp *); 43 + void mcp_disable(struct mcp *); 44 + #define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate) 45 + 46 + struct mcp *mcp_host_alloc(struct device *, size_t); 47 + int mcp_host_register(struct mcp *); 48 + void mcp_host_unregister(struct mcp *); 49 + 50 + struct mcp_driver { 51 + struct device_driver drv; 52 + int (*probe)(struct mcp *); 53 + void (*remove)(struct mcp *); 54 + int (*suspend)(struct mcp *, pm_message_t); 55 + int (*resume)(struct mcp *); 56 + }; 57 + 58 + int mcp_driver_register(struct mcp_driver *); 59 + void mcp_driver_unregister(struct mcp_driver *); 60 + 61 + #define mcp_get_drvdata(mcp) dev_get_drvdata(&(mcp)->attached_device) 62 + #define mcp_set_drvdata(mcp,d) dev_set_drvdata(&(mcp)->attached_device, d) 63 + 64 + #define mcp_priv(mcp) ((void *)((mcp)+1)) 65 + 66 + #endif
+21
include/asm-arm/arch-sa1100/mcp.h
··· 1 + /* 2 + * linux/include/asm-arm/arch-sa1100/mcp.h 3 + * 4 + * Copyright (C) 2005 Russell King. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + #ifndef __ASM_ARM_ARCH_MCP_H 11 + #define __ASM_ARM_ARCH_MCP_H 12 + 13 + #include <linux/types.h> 14 + 15 + struct mcp_plat_data { 16 + u32 mccr0; 17 + u32 mccr1; 18 + unsigned int sclk_rate; 19 + }; 20 + 21 + #endif