⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atmel-ssc.c

📁 linux 内核源代码
💻 C
字号:
/* * Atmel SSC driver * * Copyright (C) 2007 Atmel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include <linux/platform_device.h>#include <linux/list.h>#include <linux/clk.h>#include <linux/err.h>#include <linux/io.h>#include <linux/list.h>#include <linux/spinlock.h>#include <linux/atmel-ssc.h>/* Serialize access to ssc_list and user count */static DEFINE_SPINLOCK(user_lock);static LIST_HEAD(ssc_list);struct ssc_device *ssc_request(unsigned int ssc_num){	int ssc_valid = 0;	struct ssc_device *ssc;	spin_lock(&user_lock);	list_for_each_entry(ssc, &ssc_list, list) {		if (ssc->pdev->id == ssc_num) {			ssc_valid = 1;			break;		}	}	if (!ssc_valid) {		spin_unlock(&user_lock);		dev_dbg(&ssc->pdev->dev, "could not find requested device\n");		return ERR_PTR(-ENODEV);	}	if (ssc->user) {		spin_unlock(&user_lock);		dev_dbg(&ssc->pdev->dev, "module busy\n");		return ERR_PTR(-EBUSY);	}	ssc->user++;	spin_unlock(&user_lock);	clk_enable(ssc->clk);	return ssc;}EXPORT_SYMBOL(ssc_request);void ssc_free(struct ssc_device *ssc){	spin_lock(&user_lock);	if (ssc->user) {		ssc->user--;		clk_disable(ssc->clk);	} else {		dev_dbg(&ssc->pdev->dev, "device already free\n");	}	spin_unlock(&user_lock);}EXPORT_SYMBOL(ssc_free);static int __init ssc_probe(struct platform_device *pdev){	int retval = 0;	struct resource *regs;	struct ssc_device *ssc;	ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL);	if (!ssc) {		dev_dbg(&pdev->dev, "out of memory\n");		retval = -ENOMEM;		goto out;	}	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);	if (!regs) {		dev_dbg(&pdev->dev, "no mmio resource defined\n");		retval = -ENXIO;		goto out_free;	}	ssc->clk = clk_get(&pdev->dev, "pclk");	if (IS_ERR(ssc->clk)) {		dev_dbg(&pdev->dev, "no pclk clock defined\n");		retval = -ENXIO;		goto out_free;	}	ssc->pdev = pdev;	ssc->regs = ioremap(regs->start, regs->end - regs->start + 1);	if (!ssc->regs) {		dev_dbg(&pdev->dev, "ioremap failed\n");		retval = -EINVAL;		goto out_clk;	}	/* disable all interrupts */	clk_enable(ssc->clk);	ssc_writel(ssc->regs, IDR, ~0UL);	ssc_readl(ssc->regs, SR);	clk_disable(ssc->clk);	ssc->irq = platform_get_irq(pdev, 0);	if (!ssc->irq) {		dev_dbg(&pdev->dev, "could not get irq\n");		retval = -ENXIO;		goto out_unmap;	}	spin_lock(&user_lock);	list_add_tail(&ssc->list, &ssc_list);	spin_unlock(&user_lock);	platform_set_drvdata(pdev, ssc);	dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",			ssc->regs, ssc->irq);	goto out;out_unmap:	iounmap(ssc->regs);out_clk:	clk_put(ssc->clk);out_free:	kfree(ssc);out:	return retval;}static int __devexit ssc_remove(struct platform_device *pdev){	struct ssc_device *ssc = platform_get_drvdata(pdev);	spin_lock(&user_lock);	iounmap(ssc->regs);	clk_put(ssc->clk);	list_del(&ssc->list);	kfree(ssc);	spin_unlock(&user_lock);	return 0;}static struct platform_driver ssc_driver = {	.remove		= __devexit_p(ssc_remove),	.driver		= {		.name		= "ssc",	},};static int __init ssc_init(void){	return platform_driver_probe(&ssc_driver, ssc_probe);}module_init(ssc_init);static void __exit ssc_exit(void){	platform_driver_unregister(&ssc_driver);}module_exit(ssc_exit);MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -