Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.26-rc6 176 lines 3.6 kB view raw
1/* 2 * Atmel SSC driver 3 * 4 * Copyright (C) 2007 Atmel Corporation 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 11#include <linux/platform_device.h> 12#include <linux/list.h> 13#include <linux/clk.h> 14#include <linux/err.h> 15#include <linux/io.h> 16#include <linux/list.h> 17#include <linux/spinlock.h> 18#include <linux/atmel-ssc.h> 19 20/* Serialize access to ssc_list and user count */ 21static DEFINE_SPINLOCK(user_lock); 22static LIST_HEAD(ssc_list); 23 24struct ssc_device *ssc_request(unsigned int ssc_num) 25{ 26 int ssc_valid = 0; 27 struct ssc_device *ssc; 28 29 spin_lock(&user_lock); 30 list_for_each_entry(ssc, &ssc_list, list) { 31 if (ssc->pdev->id == ssc_num) { 32 ssc_valid = 1; 33 break; 34 } 35 } 36 37 if (!ssc_valid) { 38 spin_unlock(&user_lock); 39 dev_dbg(&ssc->pdev->dev, "could not find requested device\n"); 40 return ERR_PTR(-ENODEV); 41 } 42 43 if (ssc->user) { 44 spin_unlock(&user_lock); 45 dev_dbg(&ssc->pdev->dev, "module busy\n"); 46 return ERR_PTR(-EBUSY); 47 } 48 ssc->user++; 49 spin_unlock(&user_lock); 50 51 clk_enable(ssc->clk); 52 53 return ssc; 54} 55EXPORT_SYMBOL(ssc_request); 56 57void ssc_free(struct ssc_device *ssc) 58{ 59 spin_lock(&user_lock); 60 if (ssc->user) { 61 ssc->user--; 62 clk_disable(ssc->clk); 63 } else { 64 dev_dbg(&ssc->pdev->dev, "device already free\n"); 65 } 66 spin_unlock(&user_lock); 67} 68EXPORT_SYMBOL(ssc_free); 69 70static int __init ssc_probe(struct platform_device *pdev) 71{ 72 int retval = 0; 73 struct resource *regs; 74 struct ssc_device *ssc; 75 76 ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL); 77 if (!ssc) { 78 dev_dbg(&pdev->dev, "out of memory\n"); 79 retval = -ENOMEM; 80 goto out; 81 } 82 83 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 84 if (!regs) { 85 dev_dbg(&pdev->dev, "no mmio resource defined\n"); 86 retval = -ENXIO; 87 goto out_free; 88 } 89 90 ssc->clk = clk_get(&pdev->dev, "pclk"); 91 if (IS_ERR(ssc->clk)) { 92 dev_dbg(&pdev->dev, "no pclk clock defined\n"); 93 retval = -ENXIO; 94 goto out_free; 95 } 96 97 ssc->pdev = pdev; 98 ssc->regs = ioremap(regs->start, regs->end - regs->start + 1); 99 if (!ssc->regs) { 100 dev_dbg(&pdev->dev, "ioremap failed\n"); 101 retval = -EINVAL; 102 goto out_clk; 103 } 104 105 /* disable all interrupts */ 106 clk_enable(ssc->clk); 107 ssc_writel(ssc->regs, IDR, ~0UL); 108 ssc_readl(ssc->regs, SR); 109 clk_disable(ssc->clk); 110 111 ssc->irq = platform_get_irq(pdev, 0); 112 if (!ssc->irq) { 113 dev_dbg(&pdev->dev, "could not get irq\n"); 114 retval = -ENXIO; 115 goto out_unmap; 116 } 117 118 spin_lock(&user_lock); 119 list_add_tail(&ssc->list, &ssc_list); 120 spin_unlock(&user_lock); 121 122 platform_set_drvdata(pdev, ssc); 123 124 dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n", 125 ssc->regs, ssc->irq); 126 127 goto out; 128 129out_unmap: 130 iounmap(ssc->regs); 131out_clk: 132 clk_put(ssc->clk); 133out_free: 134 kfree(ssc); 135out: 136 return retval; 137} 138 139static int __devexit ssc_remove(struct platform_device *pdev) 140{ 141 struct ssc_device *ssc = platform_get_drvdata(pdev); 142 143 spin_lock(&user_lock); 144 iounmap(ssc->regs); 145 clk_put(ssc->clk); 146 list_del(&ssc->list); 147 kfree(ssc); 148 spin_unlock(&user_lock); 149 150 return 0; 151} 152 153static struct platform_driver ssc_driver = { 154 .remove = __devexit_p(ssc_remove), 155 .driver = { 156 .name = "ssc", 157 .owner = THIS_MODULE, 158 }, 159}; 160 161static int __init ssc_init(void) 162{ 163 return platform_driver_probe(&ssc_driver, ssc_probe); 164} 165module_init(ssc_init); 166 167static void __exit ssc_exit(void) 168{ 169 platform_driver_unregister(&ssc_driver); 170} 171module_exit(ssc_exit); 172 173MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); 174MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91"); 175MODULE_LICENSE("GPL"); 176MODULE_ALIAS("platform:ssc");